import type { Apartment, ApartmentWithRooms, Room, RoomFull, Wall, WallOpening, ElectricalItem, FurnitureItem, CreateApartmentDto, UpdateApartmentDto, CreateRoomDto, UpdateRoomDto, CreateWallDto, CreateWallOpeningDto, UpdateWallOpeningDto, CreateElectricalItemDto, UpdateElectricalItemDto, CreateFurnitureItemDto, UpdateFurnitureItemDto, BatchSyncOpeningsDto, BatchSyncElectricalDto, BatchSyncFurnitureDto, ApiResponse, ApiListResponse, ApiErrorResponse, } from '@house-plan-maker/shared'; const BASE_URL = '/api'; class ApiError extends Error { readonly statusCode: number; constructor(message: string, statusCode: number) { super(message); this.name = 'ApiError'; this.statusCode = statusCode; } } async function request( path: string, options: RequestInit = {}, ): Promise { const url = `${BASE_URL}${path}`; const headers: Record = { ...((options.headers as Record) ?? {}), }; // Only set Content-Type for requests with a body if (options.body) { headers['Content-Type'] = 'application/json'; } const response = await fetch(url, { ...options, headers }); if (!response.ok) { let errorMessage = `Request failed with status ${response.status}`; try { const errorBody = (await response.json()) as ApiErrorResponse; errorMessage = errorBody.error ?? errorMessage; } catch { // If parsing fails, use the default message } throw new ApiError(errorMessage, response.status); } // Handle 204 No Content (e.g. DELETE responses) if (response.status === 204) { return undefined as T; } return response.json() as Promise; } // ── Apartments ── export async function getApartments(): Promise { const result = await request>('/apartments'); return result.data; } export async function getApartment(id: string): Promise { const result = await request>( `/apartments/${id}`, ); return result.data; } export async function createApartment( data: CreateApartmentDto, ): Promise { const result = await request>('/apartments', { method: 'POST', body: JSON.stringify(data), }); return result.data; } export async function updateApartment( id: string, data: UpdateApartmentDto, ): Promise { const result = await request>(`/apartments/${id}`, { method: 'PUT', body: JSON.stringify(data), }); return result.data; } export async function deleteApartment(id: string): Promise { await request(`/apartments/${id}`, { method: 'DELETE' }); } // ── Rooms ── export async function getRooms(apartmentId: string): Promise { const result = await request>( `/apartments/${apartmentId}/rooms`, ); return result.data; } export async function getRoomFull(roomId: string): Promise { const result = await request>( `/rooms/${roomId}/full`, ); return result.data; } export async function createRoom( apartmentId: string, data: CreateRoomDto, ): Promise { const result = await request>( `/apartments/${apartmentId}/rooms`, { method: 'POST', body: JSON.stringify(data), }, ); return result.data; } export async function updateRoom( id: string, data: UpdateRoomDto, ): Promise { const result = await request>(`/rooms/${id}`, { method: 'PUT', body: JSON.stringify(data), }); return result.data; } export async function deleteRoom(id: string): Promise { await request(`/rooms/${id}`, { method: 'DELETE' }); } // ── Walls ── export async function bulkUpdateWalls( roomId: string, walls: readonly CreateWallDto[], ): Promise { const result = await request>( `/rooms/${roomId}/walls`, { method: 'PUT', body: JSON.stringify({ walls }), }, ); return result.data; } // ── Wall Openings ── export async function createWallOpening( roomId: string, data: CreateWallOpeningDto, ): Promise { const result = await request>( `/rooms/${roomId}/openings`, { method: 'POST', body: JSON.stringify(data), }, ); return result.data; } export async function updateWallOpening( roomId: string, openingId: string, data: UpdateWallOpeningDto, ): Promise { const result = await request>( `/rooms/${roomId}/openings/${openingId}`, { method: 'PUT', body: JSON.stringify(data), }, ); return result.data; } export async function deleteWallOpening( roomId: string, openingId: string, ): Promise { await request(`/rooms/${roomId}/openings/${openingId}`, { method: 'DELETE', }); } // ── Electrical Items ── export async function createElectricalItem( roomId: string, data: CreateElectricalItemDto, ): Promise { const result = await request>( `/rooms/${roomId}/electrical`, { method: 'POST', body: JSON.stringify(data), }, ); return result.data; } export async function updateElectricalItem( roomId: string, itemId: string, data: UpdateElectricalItemDto, ): Promise { const result = await request>( `/electrical/${itemId}`, { method: 'PUT', body: JSON.stringify(data), }, ); return result.data; } export async function deleteElectricalItem( roomId: string, itemId: string, ): Promise { await request(`/electrical/${itemId}`, { method: 'DELETE', }); } // ── Furniture Items ── export async function createFurnitureItem( roomId: string, data: CreateFurnitureItemDto, ): Promise { const result = await request>( `/rooms/${roomId}/furniture`, { method: 'POST', body: JSON.stringify(data), }, ); return result.data; } export async function updateFurnitureItem( roomId: string, itemId: string, data: UpdateFurnitureItemDto, ): Promise { const result = await request>( `/furniture/${itemId}`, { method: 'PUT', body: JSON.stringify(data), }, ); return result.data; } export async function deleteFurnitureItem( roomId: string, itemId: string, ): Promise { await request(`/furniture/${itemId}`, { method: 'DELETE', }); } // ── Batch Sync ── export async function batchSyncOpenings( roomId: string, data: BatchSyncOpeningsDto, ): Promise { const result = await request>( `/rooms/${roomId}/openings/batch`, { method: 'PUT', body: JSON.stringify(data), }, ); return result.data; } export async function batchSyncElectrical( roomId: string, data: BatchSyncElectricalDto, ): Promise { const result = await request>( `/rooms/${roomId}/electrical/batch`, { method: 'PUT', body: JSON.stringify(data), }, ); return result.data; } export async function batchSyncFurniture( roomId: string, data: BatchSyncFurnitureDto, ): Promise { const result = await request>( `/rooms/${roomId}/furniture/batch`, { method: 'PUT', body: JSON.stringify(data), }, ); return result.data; } export { ApiError };