'use client'; import { useState, useEffect } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { format } from 'date-fns'; import { Archive, Download, Edit, FileText, Loader2, Receipt } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { ArchiveConfirmDialog } from '@/components/shared/archive-confirm-dialog'; import { PermissionGate } from '@/components/shared/permission-gate'; import { toast } from 'sonner'; import { apiFetch } from '@/lib/api/client'; import { useMobileChrome } from '@/components/layout/mobile/mobile-layout-provider'; import type { ExpenseRow } from './expense-columns'; import { ExpenseDuplicateBanner } from './expense-duplicate-banner'; /** * Renders an image thumbnail for previewable receipts (jpeg/png/webp/heic * via the existing /files/[id]/preview presign), falling back to a "Download" * link for PDFs and other non-previewable types. Replaces the prior * impossible-to-use UUID-badge list — reps can finally see the receipt * they uploaded against the expense. */ function ReceiptThumbnail({ fileId }: { fileId: string }) { const { data, isLoading, isError } = useQuery<{ data: { url: string; mimeType: string } | null; error?: string; }>({ queryKey: ['file-preview', fileId], queryFn: async () => { try { const res = await apiFetch<{ data: { url: string; mimeType: string } }>( `/api/v1/files/${fileId}/preview`, ); return res; } catch (e) { // Non-image files raise ValidationError ("This file type cannot be // previewed") — fall through to the Download link. return { data: null, error: e instanceof Error ? e.message : 'preview unavailable' }; } }, staleTime: 5 * 60 * 1000, }); if (isLoading) { return (
{format(new Date(expense.expenseDate), 'MMMM d, yyyy')}
{Number(expense.amount).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2, })}{' '} {expense.currency}
{expense.amountUsd && expense.currency !== 'USD' && (≈ $ {Number(expense.amountUsd).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2, })}{' '} USD
)}{expense.category?.replace(/_/g, ' ') ?? '-'}
{expense.paymentMethod?.replace(/_/g, ' ') ?? '-'}
{expense.payer ?? '-'}
{expense.tripLabel ? (
{expense.description ?? '-'}