import React, { useState, useEffect, useCallback } from 'react'; import { listAddresses, deleteAddress, setDefaultAddress } from '../core/checkout-api'; import type { SavedAddress } from '../core/checkout-api'; import type { SavedAddressStepProps } from '../core/types'; // ─── Label icons ────────────────────────────────────────────────────────────── const HomeIcon = () => ( ); const WorkIcon = () => ( ); const PinIcon = () => ( ); function LabelIcon({ label }: { label: string }) { if (label === 'home') return ; if (label === 'work') return ; return ; } function formatAddressLabel(address: SavedAddress): string { const custom = address.label_text?.trim(); if (address.label === 'other' && custom) return custom; return address.label.charAt(0).toUpperCase() + address.label.slice(1); } // ─── Address card ───────────────────────────────────────────────────────────── interface AddressCardProps { address: SavedAddress; onUse: () => void; onDelete: () => void; onSetDefault: () => void; deleting: boolean; } function AddressCard({ address, onUse, onDelete, onSetDefault, deleting }: AddressCardProps) { const parts = [ address.flat_number, address.building_name, address.street_name, address.locality, address.district, address.state, address.pincode, ].filter(Boolean); const line1 = [address.flat_number, address.building_name, address.street_name].filter(Boolean).join(', '); const line2 = [address.locality, address.district].filter(Boolean).join(', '); const line3 = [address.state, address.pincode].filter(Boolean).join(' – '); const summary = parts.length > 0 ? undefined : address.locality || address.district || address.state; return (
{formatAddressLabel(address)} {address.is_default && ( Default )}
{!address.is_default && ( )}
{summary ? (

{summary}

) : ( <> {line1 &&

{line1}

} {line2 &&

{line2}

} {line3 &&

{line3}

} )}
{address.digipin ? ( DigiPin {address.digipin} ) : ( Pin confirmation needed )} {address.saved_at_brand && ( {address.saved_at_brand} )}
); } // ─── Main component ─────────────────────────────────────────────────────────── const SavedAddressStep: React.FC = ({ sessionToken, functionBaseUrl, merchantId, onSelectAddress, onAddNew, }) => { const [addresses, setAddresses] = useState([]); const [loadingList, setLoadingList] = useState(true); const [listError, setListError] = useState(null); const [deletingId, setDeletingId] = useState(null); const config = { functionBaseUrl, merchantId }; const load = useCallback(async () => { setLoadingList(true); setListError(null); try { const list = await listAddresses(config, sessionToken); if (list.length === 0) { // No saved addresses — go straight to map onAddNew(); return; } setAddresses(list); } catch (err: unknown) { setListError(err instanceof Error ? err.message : 'Failed to load addresses.'); } finally { setLoadingList(false); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [sessionToken]); useEffect(() => { load(); }, [load]); const handleDelete = useCallback(async (id: string) => { setDeletingId(id); try { await deleteAddress(config, sessionToken, id); setAddresses((prev) => { const updated = prev.filter((a) => a.id !== id); if (updated.length === 0) { onAddNew(); } return updated; }); } catch (err: unknown) { setListError(err instanceof Error ? err.message : 'Failed to delete address.'); } finally { setDeletingId(null); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [sessionToken, onAddNew]); const handleSetDefault = useCallback(async (id: string) => { try { await setDefaultAddress(config, sessionToken, id); setAddresses((prev) => prev.map((a) => ({ ...a, is_default: a.id === id }))); } catch (err: unknown) { setListError(err instanceof Error ? err.message : 'Failed to set default.'); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [sessionToken]); // ── Loading ────────────────────────────────────────────────────────────────── if (loadingList) { return (
); } // ── Error ──────────────────────────────────────────────────────────────────── if (listError && addresses.length === 0) { return (

{listError}

); } return (
Saved Addresses Pick one or add a new location
{listError && (

{listError}

)}
{addresses.map((addr) => ( onSelectAddress(addr)} onDelete={() => handleDelete(addr.id)} onSetDefault={() => handleSetDefault(addr.id)} deleting={deletingId === addr.id} /> ))}
); }; export default SavedAddressStep;