'use client'; import { isApiError, type IrpCategory } from '@impuestos/contracts'; import { formatDateLong, formatGs, type Locale } from '@impuestos/i18n'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useState } from 'react'; import { CategoryPicker } from '@/components/category-picker'; import { Button } from '@/components/ui/button'; import { Card } from '@/components/ui/card'; import { Skeleton } from '@/components/ui/skeleton'; import { StatusChip } from '@/components/ui/status-chip'; import { Switch } from '@/components/ui/switch'; import { useT } from '@/i18n/t'; import { api } from '@/lib/api'; /** Flow E1 detail: the data, the image, and the classification the user can override. */ export function DocumentDetail({ id, locale }: { id: string; locale: string }) { const t = useT(); const queryClient = useQueryClient(); const [editing, setEditing] = useState(false); const document = useQuery({ queryKey: ['documents', id], queryFn: ({ signal }) => api.getDocument(id, signal), retry: (count, error) => !isApiError(error) && count < 1, }); const reclassify = useMutation({ mutationFn: (patch: { irpCategory?: IrpCategory | 'none'; ivaCreditEligible?: boolean }) => api.patchClassification(id, patch), onSuccess: async () => { setEditing(false); await queryClient.invalidateQueries({ queryKey: ['documents'] }); }, }); if (document.isPending) { return ( ); } if (document.isError || !document.data) { const missing = isApiError(document.error) && document.error.code === 'not_found'; return (

{missing ? t('error.not_found') : t('common.error.generic')}

{!missing ? ( ) : null}
); } const doc = document.data; const classification = doc.classification; const category = classification?.irpCategory ?? 'none'; return (

{doc.emitterName}

{formatDateLong(locale as Locale, doc.issueDate)}

{formatGs(doc.total)}

{t('bandeja.category')}

{editing ? ( reclassify.mutate({ irpCategory: next })} /> ) : (

{t(`categories.${category}` as const)}

)} {classification ? (
0 ? formatGs(classification.irpDeductibleAmount) : t('docs.detail.notDeductible') } /> {classification.reasons.length > 0 ? (
    {classification.reasons.map((reason) => (
  • {t(`classification.reason.${reason}` as 'classification.reason.irp_no_category')}
  • ))}
) : null}
) : null}
{doc.fileUrl ? ( {/* The stored photograph. Served through the authenticated file route. */} {doc.emitterName} ) : null}
); } function Row({ label, value }: { label: string; value: string }) { return (
{label}
{value}
); }