/** * PersonalAddressSection * * Billing address editor rendered inside ProfilePage for PERSONAL accounts. * Writes through companiesApi.updateCompany since address lives on the * Company entity (same row, companyType=PERSONAL). BUSINESS users never see * this; they edit address on /dashboard/company instead. * * Uses AddressFieldset for the form body so the layout stays in sync with * CompanySettingsPage. * * (c) 2026 TWWIM UG. All rights reserved. (www.twwim.com) */ import { useState, useEffect } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { MapPin, Loader2, Pencil, X } from 'lucide-react'; import type { Address } from '@archer/domain'; import { AddressFieldset } from '@/components/shared'; import { queryKeys } from '@/lib/query-keys'; import { companiesApi } from '@/infrastructure/http/api/company'; import { authenticatedUserStore } from '@/infrastructure/storage/AuthenticatedUserStore'; import { forceTokenRefresh } from '@/infrastructure/http/auth-refresh'; import { useTranslation } from '@/i18n/TranslationProvider'; export function PersonalAddressSection() { const { t } = useTranslation(); const companyId = authenticatedUserStore.get()?.companyId; const queryClient = useQueryClient(); const { data: company, isLoading } = useQuery({ queryKey: queryKeys.companies.detail(companyId || ''), queryFn: () => companiesApi.getCompany(companyId!), enabled: !!companyId, }); const mutation = useMutation({ mutationFn: (data: Parameters[1]) => companiesApi.updateCompany(companyId!, data), onSuccess: async () => { queryClient.invalidateQueries({ queryKey: queryKeys.companies.all }); queryClient.invalidateQueries({ queryKey: queryKeys.profile.all }); // Address completion can flip isProfileComplete which gates paid actions — // round-trip the JWT so cached identity reflects the new server state. try { await forceTokenRefresh(); } catch { /* refresh failure: prior snapshot stays, will heal on next /auth/me */ } setEditing(false); }, }); const [editing, setEditing] = useState(false); const [address, setAddress] = useState
({}); useEffect(() => { if (company) setAddress(company.address ?? {}); }, [company]); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); mutation.mutate({ address: { street: address.street || undefined, zip: address.zip || undefined, city: address.city || undefined, country: address.country || undefined, }, }); }; const handleCancel = () => { if (company) setAddress(company.address ?? {}); setEditing(false); }; return (

{t('profile.billingAddress')}

{!editing && !isLoading && ( )}
{isLoading ? (
{[1, 2, 3, 4].map(i =>
)}
) : editing ? (
{mutation.isError && ( {(mutation.error as Error).message || t('profile.updateFailed')} )}
) : (

{t('address.street')}

{company?.address?.street || '-'}

{t('address.zip')}

{company?.address?.zip || '-'}

{t('address.city')}

{company?.address?.city || '-'}

{t('address.country')}

{company?.address?.country || '-'}

)}
); }