import { useState } from 'react' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { api } from '@/lib/api-client' import { repairTicketMutations, repairLineItemMutations, repairServiceTemplateListOptions } from '@/api/repairs' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { Separator } from '@/components/ui/separator' import { Badge } from '@/components/ui/badge' import { ArrowLeft, ArrowRight, Plus, Trash2, Check, Search } from 'lucide-react' import { toast } from 'sonner' import type { RepairServiceTemplate } from '@/types/repair' import type { PaginatedResponse } from '@lunarfront/shared/schemas' interface RepairIntakeFormProps { onComplete: (ticketId: string) => void onCancel: () => void } interface LineItemDraft { id: string itemType: string description: string qty: number unitPrice: number } const STEPS = ['Customer', 'Item', 'Problem & Estimate', 'Review'] const CONDITIONS = [ { value: 'excellent', label: 'Excellent' }, { value: 'good', label: 'Good' }, { value: 'fair', label: 'Fair' }, { value: 'poor', label: 'Poor' }, ] export function RepairIntakeForm({ onComplete, onCancel }: RepairIntakeFormProps) { const queryClient = useQueryClient() const [step, setStep] = useState(0) // Customer const [customerName, setCustomerName] = useState('') const [customerPhone, setCustomerPhone] = useState('') const [customerEmail, setCustomerEmail] = useState('') const [accountId, setAccountId] = useState(null) // Account search const [accountSearch, setAccountSearch] = useState('') const { data: accountResults } = useQuery({ queryKey: ['accounts', 'search', accountSearch], queryFn: () => api.get>('/v1/accounts', { page: 1, limit: 10, q: accountSearch }), enabled: accountSearch.length >= 2, staleTime: 10_000, }) // Item const [itemDescription, setItemDescription] = useState('') const [serialNumber, setSerialNumber] = useState('') const [conditionIn, setConditionIn] = useState('') const [conditionInNotes, setConditionInNotes] = useState('') // Problem & Estimate const [problemDescription, setProblemDescription] = useState('') const [estimatedCost, setEstimatedCost] = useState('') const [promisedDate, setPromisedDate] = useState('') const [lineItems, setLineItems] = useState([]) // Templates for quick-add const { data: templatesData } = useQuery({ ...repairServiceTemplateListOptions({ page: 1, limit: 100, q: undefined, sort: 'sort_order', order: 'asc' }), }) const templates = templatesData?.data ?? [] function addLineItem(template?: RepairServiceTemplate) { setLineItems([...lineItems, { id: crypto.randomUUID(), itemType: template?.itemType ?? 'labor', description: template?.description ?? template?.name ?? '', qty: 1, unitPrice: parseFloat(template?.defaultPrice ?? '0'), }]) } function removeLineItem(id: string) { setLineItems(lineItems.filter(i => i.id !== id)) } function updateLineItem(id: string, field: string, value: string | number) { setLineItems(lineItems.map(i => i.id === id ? { ...i, [field]: value } : i)) } const lineItemTotal = lineItems.reduce((sum, i) => sum + i.qty * i.unitPrice, 0) const createMutation = useMutation({ mutationFn: async () => { const ticket = await repairTicketMutations.create({ customerName, customerPhone: customerPhone || undefined, accountId: accountId || undefined, itemDescription: itemDescription || undefined, serialNumber: serialNumber || undefined, conditionIn: conditionIn || undefined, conditionInNotes: conditionInNotes || undefined, problemDescription, estimatedCost: estimatedCost ? parseFloat(estimatedCost) : undefined, promisedDate: promisedDate || undefined, }) // Create line items for (const item of lineItems) { await repairLineItemMutations.create(ticket.id, { itemType: item.itemType, description: item.description, qty: item.qty, unitPrice: item.unitPrice, }) } return ticket }, onSuccess: (ticket) => { queryClient.invalidateQueries({ queryKey: ['repair-tickets'] }) toast.success(`Ticket #${ticket.ticketNumber} created`) onComplete(ticket.id) }, onError: (err) => toast.error(err.message), }) function selectAccount(acct: { id: string; name: string; email: string | null; phone: string | null }) { setAccountId(acct.id) setCustomerName(acct.name) if (acct.phone) setCustomerPhone(acct.phone) if (acct.email) setCustomerEmail(acct.email) setAccountSearch('') } function canProceed() { if (step === 0) return customerName.trim().length > 0 if (step === 1) return true if (step === 2) return problemDescription.trim().length > 0 return true } return (
{/* Step indicator */}
{STEPS.map((s, i) => (
{i < step ? : i + 1} {s}
{i < STEPS.length - 1 &&
}
))}
{/* Step content */}
{step === 0 && (

Customer

setAccountSearch(e.target.value)} className="pl-9" />
{accountSearch.length >= 2 && accountResults?.data && accountResults.data.length > 0 && (
{accountResults.data.map((acct) => ( ))}
)}

Or enter walk-in customer info:

setCustomerName(e.target.value)} placeholder="Customer name" />
setCustomerPhone(e.target.value)} placeholder="555-1234" />
setCustomerEmail(e.target.value)} placeholder="email@example.com" />
)} {step === 1 && (

Item Details

setItemDescription(e.target.value)} placeholder="e.g. Fender Stratocaster, iPhone 15, etc." />
setSerialNumber(e.target.value)} placeholder="Optional" />