'use client'; import { formatErrorBanner } from '@/lib/api/toast-error'; import { useState, useEffect } from 'react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Switch } from '@/components/ui/switch'; import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetFooter } from '@/components/ui/sheet'; import { apiFetch } from '@/lib/api/client'; interface PortFormProps { open: boolean; onOpenChange: (open: boolean) => void; port?: { id: string; name: string; slug: string; logoUrl: string | null; primaryColor: string | null; defaultCurrency: string; timezone: string; isActive: boolean; } | null; onSuccess: () => void; } export function PortForm({ open, onOpenChange, port, onSuccess }: PortFormProps) { const [name, setName] = useState(''); const [slug, setSlug] = useState(''); const [primaryColor, setPrimaryColor] = useState('#0F4C81'); const [defaultCurrency, setDefaultCurrency] = useState('USD'); const [timezone, setTimezone] = useState('America/Anguilla'); const [isActive, setIsActive] = useState(true); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const isEdit = !!port; useEffect(() => { if (open) { if (port) { setName(port.name); setSlug(port.slug); setPrimaryColor(port.primaryColor ?? '#0F4C81'); setDefaultCurrency(port.defaultCurrency); setTimezone(port.timezone); setIsActive(port.isActive); } else { setName(''); setSlug(''); setPrimaryColor('#0F4C81'); setDefaultCurrency('USD'); setTimezone('America/Anguilla'); setIsActive(true); } setError(null); } }, [open, port]); function handleNameChange(value: string) { setName(value); if (!isEdit) { setSlug( value .toLowerCase() .replace(/[^a-z0-9]+/g, '-') .replace(/^-|-$/g, ''), ); } } async function handleSubmit(e: React.FormEvent) { e.preventDefault(); setError(null); setLoading(true); try { if (isEdit) { await apiFetch(`/api/v1/admin/ports/${port.id}`, { method: 'PATCH', body: { name, slug, primaryColor, defaultCurrency, timezone, isActive }, }); } else { await apiFetch('/api/v1/admin/ports', { method: 'POST', body: { name, slug, primaryColor, defaultCurrency, timezone }, }); } onSuccess(); onOpenChange(false); } catch (err: unknown) { const message = formatErrorBanner(err); setError(message); } finally { setLoading(false); } } return ( {isEdit ? 'Edit Port' : 'New Port'}
handleNameChange(e.target.value)} placeholder="Port Nimara" required />
setSlug(e.target.value)} placeholder="port-nimara" pattern="^[a-z0-9-]+$" required />

Used in URLs. Lowercase letters, numbers, and hyphens only.

setPrimaryColor(e.target.value)} className="h-9 w-9 rounded border cursor-pointer" /> setPrimaryColor(e.target.value)} placeholder="#0F4C81" className="w-28 font-mono text-sm" maxLength={7} />
setDefaultCurrency(e.target.value.toUpperCase())} placeholder="USD" maxLength={3} required />
setTimezone(e.target.value)} placeholder="America/Anguilla" required />
{isEdit && (

Inactive ports are hidden from users

)} {error &&

{error}

}
); }