/** * CSV Upload Component (ADMIN only) * * Upload CSV rate files for carrier companies * Protected: Only accessible to users with ADMIN role */ 'use client'; import { useState } from 'react'; import { useRouter } from 'next/navigation'; import { useTranslations } from 'next-intl'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Label } from '@/components/ui/label'; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; import { Upload, CheckCircle, XCircle, Loader2 } from 'lucide-react'; import { uploadCsvRates } from '@/lib/api/admin/csv-rates'; export function CsvUpload() { const t = useTranslations('components.csvUpload'); const router = useRouter(); const [companyName, setCompanyName] = useState(''); const [companyEmail, setCompanyEmail] = useState(''); const [file, setFile] = useState(null); const [loading, setLoading] = useState(false); const [success, setSuccess] = useState(null); const [error, setError] = useState(null); const handleFileChange = (e: React.ChangeEvent) => { const selectedFile = e.target.files?.[0] || null; setFile(selectedFile); setError(null); setSuccess(null); if (selectedFile && !selectedFile.name.endsWith('.csv')) { setError(t('fileTypeError')); setFile(null); } if (selectedFile && selectedFile.size > 10 * 1024 * 1024) { setError(t('fileSizeError')); setFile(null); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!file || !companyName || !companyEmail) { setError(t('fillAllFields')); return; } setLoading(true); setError(null); setSuccess(null); try { const formData = new FormData(); formData.append('file', file); formData.append('companyName', companyName); formData.append('companyEmail', companyEmail); const result = await uploadCsvRates(formData); setSuccess(t('successMessage', { count: result.rowCount, companyName: result.companyName })); setCompanyName(''); setCompanyEmail(''); setFile(null); const fileInput = document.getElementById('file-input') as HTMLInputElement; if (fileInput) { fileInput.value = ''; } setTimeout(() => { router.refresh(); }, 2000); } catch (err: any) { setError(err?.message || t('uploadError')); } finally { setLoading(false); } }; const handleReset = () => { setCompanyName(''); setCompanyEmail(''); setFile(null); setError(null); setSuccess(null); const fileInput = document.getElementById('file-input') as HTMLInputElement; if (fileInput) { fileInput.value = ''; } }; return ( {t('title')} {t('description')}
{/* Company Name */}
setCompanyName(e.target.value)} placeholder={t('form.companyNamePlaceholder')} required disabled={loading} />

{t('form.companyNameHint')}

{/* Company Email */}
setCompanyEmail(e.target.value)} placeholder={t('form.companyEmailPlaceholder')} required disabled={loading} />

{t('form.companyEmailHint')}

{/* File Input */}
{file && (

{t('form.fileSelected')} {file.name} ( {(file.size / 1024).toFixed(2)} KB)

)}
{/* CSV Format Info */} {t('form.formatTitle')}

{t('form.formatIntro')}

  • companyName, origin, destination, containerType
  • minVolumeCBM, maxVolumeCBM, minWeightKG, maxWeightKG
  • palletCount, pricePerCBM, pricePerKG
  • basePriceUSD, basePriceEUR, currency
  • hasSurcharges, surchargeBAF, surchargeCAF
  • transitDays, validFrom, validUntil
{/* Error Alert */} {error && ( {t('form.errorTitle')} {error} )} {/* Success Alert */} {success && ( {t('form.successTitle')} {success} )} {/* Actions */}
); }