import { api as apiClient } from "@/auth/http"; import { URL_CONSTANTS } from "@/constants/URLS"; import type { Company, CompanyChangeRequest, CompanyListFilter, CompanyProfile, CompanyRevision, CompanyStats, CustomerBooking, CustomerDocument, CustomerPayment, CustomerResetTarget, PaginatedCompanies, ProfileStatus, ResetChannel, ResetPasswordResult, } from "@/types/customer"; const cleanParams = (params: object) => Object.fromEntries( Object.entries(params).filter( ([, value]) => value !== undefined && value !== "" && value !== null, ), ); /** Lift attributes JSONB into the flat contact/owner fields the UI reads. */ function mapCompany(dto: Record): Company { const attrs = (dto.attributes as Record | null) ?? {}; return { ...(dto as unknown as Company), companyProfiles: (dto.companyProfiles as Company["companyProfiles"]) ?? [], contactPersonName: (attrs.contactPersonName as string | null) ?? null, contactPersonPhone: (attrs.contactPersonPhone as string | null) ?? null, ownerName: (attrs.ownerName as string | null) ?? null, ownerEmail: (attrs.ownerEmail as string | null) ?? null, ownerPhone: (attrs.ownerPhone as string | null) ?? null, poaName: (attrs.poaName as string | null) ?? null, poaEmail: (attrs.poaEmail as string | null) ?? null, poaPhone: (attrs.poaPhone as string | null) ?? null, poaLocation: (attrs.poaLocation as string | null) ?? null, poaAddress: (attrs.poaAddress as string | null) ?? null, }; } export const customersService = { stats(): Promise { return apiClient .get(URL_CONSTANTS.COMPANIES.STATS) .then((r) => r.data); }, list(filter: CompanyListFilter): Promise { return apiClient .get<{ items: Record[]; total: number }>( URL_CONSTANTS.COMPANIES.BASE, { params: cleanParams(filter) }, ) .then((r) => ({ items: r.data.items.map(mapCompany), total: r.data.total, })); }, getById(id: string): Promise { return apiClient .get>(URL_CONSTANTS.COMPANIES.BY_ID(id)) .then((r) => mapCompany(r.data)); }, bookingsFor(companyId: string): Promise { return apiClient .get( URL_CONSTANTS.COMPANIES.BOOKINGS_CUSTOMER_VIEW(companyId), ) .then((r) => r.data); }, documentsFor(companyId: string): Promise { return apiClient .get(URL_CONSTANTS.COMPANIES.DOCUMENTS(companyId)) .then((r) => r.data); }, paymentsFor(companyId: string): Promise { return apiClient .get( URL_CONSTANTS.COMPANIES.PAYMENTS_CUSTOMER_VIEW(companyId), ) .then((r) => r.data); }, /** * The IAM account a reset link would go to. Read before offering the action * so staff see the credentials the link actually reaches, not the company's * business contact details. */ resetTarget(companyId: string): Promise { return apiClient .get(URL_CONSTANTS.COMPANIES.RESET_TARGET(companyId)) .then((r) => r.data); }, /** * Send a password-reset link to the company's primary contact. Staff never * receive a credential — the customer opens the link and sets their own * password. */ resetPassword( companyId: string, channel: ResetChannel, ): Promise { return apiClient .post( URL_CONSTANTS.COMPANIES.RESET_PASSWORD(companyId), { channel }, ) .then((r) => r.data); }, setProfileStatus( profileId: string, status: ProfileStatus, note?: string, ): Promise { return apiClient .patch( URL_CONSTANTS.COMPANIES.PROFILE_STATUS(profileId), { status, note }, ) .then((r) => r.data); }, /** Approve / change a company's status (e.g. pending → active). */ setCompanyStatus(companyId: string, status: string): Promise { return apiClient .patch(URL_CONSTANTS.COMPANIES.BY_ID(companyId), { status }) .then((r) => r.data); }, /** List a company's profile-edit change requests (newest first). */ changeRequests(companyId: string): Promise { return apiClient .get( URL_CONSTANTS.COMPANIES.CHANGE_REQUESTS(companyId), ) .then((r) => r.data); }, /** Onboarding-phase edit history for a company (version history), newest first. */ revisions(companyId: string): Promise { return apiClient .get(URL_CONSTANTS.COMPANIES.REVISIONS(companyId)) .then((r) => r.data); }, /** Approve a pending change request — applies the proposed changes. */ approveChangeRequest(id: string): Promise { return apiClient .post( URL_CONSTANTS.COMPANIES.CHANGE_REQUEST_APPROVE(id), ) .then((r) => r.data); }, /** Reject a pending change request with a note. */ rejectChangeRequest(id: string, note: string): Promise { return apiClient .post( URL_CONSTANTS.COMPANIES.CHANGE_REQUEST_REJECT(id), { note }, ) .then((r) => r.data); }, /** Ask for specific changes without rejecting — the request stays open for the customer's next edit to append to. */ requestChangeRequestChanges( id: string, note: string, ): Promise { return apiClient .post( URL_CONSTANTS.COMPANIES.CHANGE_REQUEST_REQUEST_CHANGES(id), { note }, ) .then((r) => r.data); }, /** * Ask the customer to correct one uploaded document. Narrower than rejecting * the whole role: the customer keeps their other documents and only re-uploads * this one, but the role cannot be approved until they do. */ requestDocumentChange( fileId: string, note: string, ): Promise { return apiClient .post( URL_CONSTANTS.COMPANIES.DOCUMENT_REQUEST_CHANGE(fileId), { note }, ) .then((r) => r.data); }, };