import { reportError } from '@/lib/error-handling'; import { CrudService } from '@/lib/service-base'; import { SERVICE_CONFIGS } from '@/lib/service-config'; import { backendSiteSchema, createSiteRequestSchema, nearbySitesQuerySchema, type BackendSite, type CreateSiteRequest, type NearbySitesQuery, } from '@/schemas/backend/site'; // Re-export types for use in hooks export type { CreateSiteRequest, NearbySitesQuery }; /** * Sites Service * Handles all site-related API operations with improved reliability and type safety */ class SitesService extends CrudService { protected entitySchema = backendSiteSchema; protected createSchema = createSiteRequestSchema; protected updateSchema = createSiteRequestSchema.partial(); // Allow partial updates constructor() { super(SERVICE_CONFIGS.SITES); } /** * Get all sites with enhanced error handling */ async getAllSites(): Promise { const result = await this.getAll({ context: 'getAllSites', useArrayFallback: true, }); if (!result.success) { console.error('[DEBUG] Site validation failed:', result.error); // For sites, we prefer to return empty array rather than throw this.logError(`Failed to fetch sites: ${result.error?.message}`, result.error); return []; } return result.data; } /** * Get sites by organization ID */ async getSitesByOrganization(organizationId: string): Promise { const result = await this.get( `organization/${organizationId}`, this.entitySchema.array(), undefined, { context: `getSitesByOrganization(${organizationId})`, useArrayFallback: true, } ); if (!result.success) { // Organizations without sites are valid, so return empty array this.log(`No sites found for organization ${organizationId}`); return []; } return result.data; } /** * Get heritage sites (sites with heritage status) * @param locale Optional locale code (en, tt, ru). Defaults to ru. */ async getHeritageSites(locale?: string): Promise { const params = locale ? { locale } : undefined; const result = await this.get('heritage', this.entitySchema.array(), params, { context: 'getHeritageSites', useArrayFallback: true, }); if (!result.success) { this.log(`No heritage sites found`); return []; } return result.data; } /** * Get nearby sites */ async getNearbySites(query: NearbySitesQuery): Promise { const validatedQuery = this.validateStrict( nearbySitesQuerySchema, query, 'getNearbySites query' ); const queryParams = { lat: validatedQuery.lat.toString(), lng: validatedQuery.lng.toString(), ...(validatedQuery.radius && { radius: validatedQuery.radius.toString() }), }; const result = await this.get('nearby', this.entitySchema.array(), queryParams, { context: 'getNearbySites', useArrayFallback: true, }); if (!result.success) { const error = reportError( new Error(result.error?.message || 'Failed to fetch nearby sites'), { operation: 'getNearbySites', query: validatedQuery } ); throw error; } return result.data; } } // Create and export service instance const sitesService = new SitesService(); // Export service instance for direct usage export { sitesService }; // Export service methods directly for cleaner imports export const getSiteById = (id: string) => sitesService.getById(id).then((result) => { if (!result.success) { const error = reportError(new Error(result.error?.message || 'Failed to fetch site'), { operation: 'getSiteById', id, }); throw error; } return result.data; }); export const getAllSites = sitesService.getAllSites.bind(sitesService); export const getSitesByOrganization = sitesService.getSitesByOrganization.bind(sitesService); export const getHeritageSites = sitesService.getHeritageSites.bind(sitesService); export const getNearbySites = sitesService.getNearbySites.bind(sitesService); export const createSite = (request: CreateSiteRequest) => sitesService.create(request).then((result) => { if (!result.success) { const error = reportError(new Error(result.error?.message || 'Failed to create site'), { operation: 'createSite', request, }); throw error; } return result.data; }); export const deleteSite = (id: string) => sitesService.remove(id).then((result) => { if (!result.success) { const error = reportError(new Error(result.error?.message || 'Failed to delete site'), { operation: 'deleteSite', id, }); throw error; } });