'use client' import { useState, useEffect } from 'react' import { useTranslations } from 'next-intl' import { createClient } from '@/lib/supabase/client' import { Button } from '@/components/ui/button' import { Card, CardContent } from '@/components/ui/card' import { Input } from '@/components/ui/input' import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog' import { EmptyState } from '@/components/ui/empty-state' import { ReportExportMenu } from '@/components/reports/ReportExportMenu' import { useToast } from '@/components/ui/use-toast' import { Plus, Search, Building2, Lock } from 'lucide-react' import SupplierForm from '@/components/suppliers/SupplierForm' import Link from 'next/link' import { useCompany } from '@/contexts/CompanyContext' import { useCanWrite } from '@/lib/hooks/use-can-write' import type { Supplier, SupplierType, CreateSupplierInput } from '@/types' const SUPPLIER_TYPE_KEYS: Record = { swedish_business: 'type_swedish_business', eu_business: 'type_eu_business', non_eu_business: 'type_non_eu_business', } function getPaymentInfo(supplier: Supplier, t: (key: string) => string): { label: string; value: string } | null { if (supplier.bankgiro) return { label: t('label_bg'), value: supplier.bankgiro } if (supplier.plusgiro) return { label: t('label_pg'), value: supplier.plusgiro } if (supplier.iban) return { label: t('label_iban'), value: supplier.iban } if (supplier.bank_account) return { label: t('label_bank_account'), value: supplier.bank_account } return null } function formatLocation(supplier: Supplier): string | null { if (supplier.city && supplier.country) return `${supplier.city}, ${supplier.country}` if (supplier.city) return supplier.city return null } export default function SuppliersPage() { const { company } = useCompany() const { canWrite } = useCanWrite() const t = useTranslations('suppliers') const [suppliers, setSuppliers] = useState([]) const [isLoading, setIsLoading] = useState(true) const [searchTerm, setSearchTerm] = useState('') const [isDialogOpen, setIsDialogOpen] = useState(false) const [isCreating, setIsCreating] = useState(false) const { toast } = useToast() const supabase = createClient() async function fetchSuppliers() { if (!company) return setIsLoading(true) const { data, error } = await supabase .from('suppliers') .select('*') .eq('company_id', company.id) .order('name', { ascending: true }) if (error) { toast({ title: t('load_failed_title'), description: t('load_failed_description'), variant: 'destructive', }) } else { setSuppliers(data || []) } setIsLoading(false) } useEffect(() => { fetchSuppliers() }, []) async function handleCreateSupplier(data: CreateSupplierInput) { setIsCreating(true) const response = await fetch('/api/suppliers', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }) const result = await response.json() if (!response.ok) { const fieldErrors = result.errors?.map((e: { field: string; message: string }) => `${e.field}: ${e.message}`).join(', ') toast({ title: t('create_failed_title'), description: fieldErrors || result.error || t('create_failed_retry'), variant: 'destructive', }) } else { toast({ title: t('created_title'), description: t('created_description', { name: data.name }), }) setSuppliers([...suppliers, result.data]) setIsDialogOpen(false) } setIsCreating(false) } const filteredSuppliers = suppliers.filter((s) => s.name.toLowerCase().includes(searchTerm.toLowerCase()) || s.email?.toLowerCase().includes(searchTerm.toLowerCase()) || s.org_number?.includes(searchTerm) ) return (

{t('title')}

{t('subtitle')}

{t('add_supplier')}
{/* Search */}
setSearchTerm(e.target.value)} className="pl-10" />
{/* Supplier list */} {isLoading ? (
{[1, 2, 3].map((i) => (
))}
) : filteredSuppliers.length === 0 ? ( {searchTerm ? ( ) : ( setIsDialogOpen(true) : undefined} /> )} ) : (
{filteredSuppliers.map((supplier) => { const payment = getPaymentInfo(supplier, t) const location = formatLocation(supplier) return (

{supplier.name}

{t(SUPPLIER_TYPE_KEYS[supplier.supplier_type])}

{supplier.org_number && (
{t('label_org_number')}
{supplier.org_number}
)} {payment && (
{payment.label}
{payment.value}
)} {supplier.email && (
{t('label_email')}
{supplier.email}
)} {location && (
{t('label_location')}
{location}
)} {!supplier.org_number && !payment && !supplier.email && !location && (

{t('no_contact_info')}

)}
) })}
)}
) }