import { clientFetch } from '@/lib/api/client'; import { unwrap, type ApiEnvelope, type Paginated } from '@/lib/api/types'; import { ADDRESSES_PAGE_SIZE } from '../constants'; import type { CreateAddressInput, CustomerAddress, CustomerAddressDto, AddressesApi } from '../types'; const BASE = '/api/v1/customer_addresses'; // REQ-009 (delivered): the wire `CustomerAddressDto` now carries `provinceId` (joined from // `cities.province_id`), so a freshly-fetched address prefills the cascade. The caller's chosen // province is kept as a fallback for the optimistic just-saved echo. interface AddressWire extends CustomerAddressDto { provinceId: number; } function toAddress(dto: AddressWire, provinceId?: number | null): CustomerAddress { return { ...dto, provinceId: dto.provinceId ?? provinceId ?? null }; } // Only the contract fields cross the wire. `latitude`/`longitude` are the picked pin (REQ-008 — // the server geocodes today; sending the pin makes the coordinate the user's once accepted); // `provinceId` stays client-side (city implies province server-side). function toBody(input: CreateAddressInput) { return { title: input.title, cityId: input.cityId, districtId: input.districtId ?? null, addressLine: input.addressLine, postalCode: input.postalCode ?? null, recipientName: input.recipientName ?? null, recipientPhone: input.recipientPhone ?? null, latitude: input.latitude ?? null, longitude: input.longitude ?? null, isPrimary: input.isPrimary ?? false, }; } /** * Real HTTP implementation of the AddressesApi seam (b4 action-style routes). `clientFetch` * returns the raw envelope, so each call reads its payload via `unwrap`. Selected once * USE_ADDRESSES_MOCK is false and REQ-008/REQ-009 land. */ export const addressesClientApi: AddressesApi = { list: async (params) => { const query = new URLSearchParams(); query.set('page', String(params?.page ?? 1)); // Pagination params bind case-insensitively to the server's `PageSize` (not snake_cased, unlike the // geo lookups' explicit `province_id`/`city_id`); match the patients template's `pageSize`. query.set('pageSize', String(params?.pageSize ?? ADDRESSES_PAGE_SIZE)); const page = unwrap( await clientFetch>>(`${BASE}/list?${query.toString()}`), ); return { ...page, items: page.items.map((dto) => toAddress(dto)) }; }, create: async (input) => toAddress( unwrap( await clientFetch>(`${BASE}/create`, { method: 'POST', body: JSON.stringify(toBody(input)), }), ), input.provinceId, ), update: async (id, input) => toAddress( unwrap( await clientFetch>(`${BASE}/update/${id}`, { method: 'POST', body: JSON.stringify(toBody(input)), }), ), input.provinceId, ), setPrimary: async (id) => { await clientFetch>(`${BASE}/set_primary/${id}`, { method: 'POST' }); }, remove: async (id) => { await clientFetch>(`${BASE}/delete/${id}`, { method: 'DELETE' }); }, };