|
@@ -1,38 +1,47 @@
|
|
|
-"use client";
|
|
|
|
|
|
|
+'use client'
|
|
|
|
|
|
|
|
-import { useState, useEffect, useTransition } from "react";
|
|
|
|
|
-import { useRouter } from "next/navigation";
|
|
|
|
|
|
|
+import { useState, useEffect, useTransition } from 'react'
|
|
|
|
|
+import { useRouter } from 'next/navigation'
|
|
|
|
|
+import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
|
|
|
|
|
+import { Button } from '@/components/ui/button'
|
|
|
|
|
+import { Input } from '@/components/ui/input'
|
|
|
|
|
+import { Label } from '@/components/ui/label'
|
|
|
import {
|
|
import {
|
|
|
- Dialog, DialogContent, DialogHeader, DialogTitle,
|
|
|
|
|
-} from "@/components/ui/dialog";
|
|
|
|
|
-import { Button } from "@/components/ui/button";
|
|
|
|
|
-import { Input } from "@/components/ui/input";
|
|
|
|
|
-import { Label } from "@/components/ui/label";
|
|
|
|
|
|
|
+ Select,
|
|
|
|
|
+ SelectContent,
|
|
|
|
|
+ SelectItem,
|
|
|
|
|
+ SelectTrigger,
|
|
|
|
|
+ SelectValue,
|
|
|
|
|
+} from '@/components/ui/select'
|
|
|
|
|
+import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
|
|
|
import {
|
|
import {
|
|
|
- Select, SelectContent, SelectItem, SelectTrigger, SelectValue,
|
|
|
|
|
-} from "@/components/ui/select";
|
|
|
|
|
-import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
|
|
|
|
-import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
|
|
|
|
|
-import { Check, ChevronsUpDown, Loader2, Settings } from "lucide-react";
|
|
|
|
|
-import { cn } from "@/lib/utils";
|
|
|
|
|
-import Link from "next/link";
|
|
|
|
|
-import { toast } from "sonner";
|
|
|
|
|
-import { useServiceType } from "@/components/service-type-context";
|
|
|
|
|
-import { createInspection } from "../Actions/inspectionActions";
|
|
|
|
|
-import { getVehicles } from "@/features/vehicles/Actions/vehicleActions";
|
|
|
|
|
|
|
+ Command,
|
|
|
|
|
+ CommandEmpty,
|
|
|
|
|
+ CommandGroup,
|
|
|
|
|
+ CommandInput,
|
|
|
|
|
+ CommandItem,
|
|
|
|
|
+ CommandList,
|
|
|
|
|
+} from '@/components/ui/command'
|
|
|
|
|
+import { Check, ChevronsUpDown, Loader2, Settings } from 'lucide-react'
|
|
|
|
|
+import { cn } from '@/lib/utils'
|
|
|
|
|
+import Link from 'next/link'
|
|
|
|
|
+import { toast } from 'sonner'
|
|
|
|
|
+import { useServiceType } from '@/components/service-type-context'
|
|
|
|
|
+import { createInspection } from '../Actions/inspectionActions'
|
|
|
|
|
+import { getVehicles } from '@/features/vehicles/Actions/vehicleActions'
|
|
|
|
|
|
|
|
interface TemplateOption {
|
|
interface TemplateOption {
|
|
|
- id: string;
|
|
|
|
|
- name: string;
|
|
|
|
|
- isDefault: boolean;
|
|
|
|
|
|
|
+ id: string
|
|
|
|
|
+ name: string
|
|
|
|
|
+ isDefault: boolean
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
interface VehicleOption {
|
|
interface VehicleOption {
|
|
|
- id: string;
|
|
|
|
|
- make: string;
|
|
|
|
|
- model: string;
|
|
|
|
|
- year: number;
|
|
|
|
|
- licensePlate: string | null;
|
|
|
|
|
|
|
+ id: string
|
|
|
|
|
+ make: string
|
|
|
|
|
+ model: string
|
|
|
|
|
+ year: number
|
|
|
|
|
+ licensePlate: string | null
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
export function NewInspectionDialog({
|
|
export function NewInspectionDialog({
|
|
@@ -41,71 +50,73 @@ export function NewInspectionDialog({
|
|
|
templates,
|
|
templates,
|
|
|
preselectedVehicleId,
|
|
preselectedVehicleId,
|
|
|
}: {
|
|
}: {
|
|
|
- open: boolean;
|
|
|
|
|
- onOpenChange: (open: boolean) => void;
|
|
|
|
|
- templates: TemplateOption[];
|
|
|
|
|
- preselectedVehicleId?: string;
|
|
|
|
|
|
|
+ open: boolean
|
|
|
|
|
+ onOpenChange: (open: boolean) => void
|
|
|
|
|
+ templates: TemplateOption[]
|
|
|
|
|
+ preselectedVehicleId?: string
|
|
|
}) {
|
|
}) {
|
|
|
- const router = useRouter();
|
|
|
|
|
- const serviceType = useServiceType();
|
|
|
|
|
- const [isPending, startTransition] = useTransition();
|
|
|
|
|
- const [vehicles, setVehicles] = useState<VehicleOption[]>([]);
|
|
|
|
|
- const [loadingVehicles, setLoadingVehicles] = useState(false);
|
|
|
|
|
|
|
+ const router = useRouter()
|
|
|
|
|
+ const serviceType = useServiceType()
|
|
|
|
|
+ const [isPending, startTransition] = useTransition()
|
|
|
|
|
+ const [vehicles, setVehicles] = useState<VehicleOption[]>([])
|
|
|
|
|
+ const [loadingVehicles, setLoadingVehicles] = useState(false)
|
|
|
|
|
|
|
|
- const defaultTemplate = templates.find((t) => t.isDefault);
|
|
|
|
|
- const [vehicleId, setVehicleId] = useState(preselectedVehicleId || "");
|
|
|
|
|
- const [templateId, setTemplateId] = useState(defaultTemplate?.id || "");
|
|
|
|
|
- const [mileage, setMileage] = useState("");
|
|
|
|
|
- const [vehiclePopoverOpen, setVehiclePopoverOpen] = useState(false);
|
|
|
|
|
|
|
+ const defaultTemplate = templates.find((t) => t.isDefault)
|
|
|
|
|
+ const [vehicleId, setVehicleId] = useState(preselectedVehicleId || '')
|
|
|
|
|
+ const [templateId, setTemplateId] = useState(defaultTemplate?.id || '')
|
|
|
|
|
+ const [mileage, setMileage] = useState('')
|
|
|
|
|
+ const [vehiclePopoverOpen, setVehiclePopoverOpen] = useState(false)
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
|
if (open && vehicles.length === 0) {
|
|
if (open && vehicles.length === 0) {
|
|
|
- setLoadingVehicles(true);
|
|
|
|
|
|
|
+ setLoadingVehicles(true)
|
|
|
getVehicles().then((result) => {
|
|
getVehicles().then((result) => {
|
|
|
if (result.success && result.data) {
|
|
if (result.success && result.data) {
|
|
|
- setVehicles(result.data.map((v) => ({
|
|
|
|
|
- id: v.id,
|
|
|
|
|
- make: v.make,
|
|
|
|
|
- model: v.model,
|
|
|
|
|
- year: v.year,
|
|
|
|
|
- licensePlate: v.licensePlate,
|
|
|
|
|
- })));
|
|
|
|
|
|
|
+ setVehicles(
|
|
|
|
|
+ result.data.map((v) => ({
|
|
|
|
|
+ id: v.id,
|
|
|
|
|
+ make: v.make,
|
|
|
|
|
+ model: v.model,
|
|
|
|
|
+ year: v.year,
|
|
|
|
|
+ licensePlate: v.licensePlate,
|
|
|
|
|
+ }))
|
|
|
|
|
+ )
|
|
|
}
|
|
}
|
|
|
- setLoadingVehicles(false);
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ setLoadingVehicles(false)
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
- }, [open, vehicles.length]);
|
|
|
|
|
|
|
+ }, [open, vehicles.length])
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
|
if (open) {
|
|
if (open) {
|
|
|
- setVehicleId(preselectedVehicleId || "");
|
|
|
|
|
- setTemplateId(defaultTemplate?.id || "");
|
|
|
|
|
- setMileage("");
|
|
|
|
|
|
|
+ setVehicleId(preselectedVehicleId || '')
|
|
|
|
|
+ setTemplateId(defaultTemplate?.id || '')
|
|
|
|
|
+ setMileage('')
|
|
|
}
|
|
}
|
|
|
- }, [open, preselectedVehicleId, defaultTemplate?.id]);
|
|
|
|
|
|
|
+ }, [open, preselectedVehicleId, defaultTemplate?.id])
|
|
|
|
|
|
|
|
const handleSubmit = (e: React.FormEvent) => {
|
|
const handleSubmit = (e: React.FormEvent) => {
|
|
|
- e.preventDefault();
|
|
|
|
|
|
|
+ e.preventDefault()
|
|
|
startTransition(async () => {
|
|
startTransition(async () => {
|
|
|
const result = await createInspection({
|
|
const result = await createInspection({
|
|
|
vehicleId,
|
|
vehicleId,
|
|
|
templateId,
|
|
templateId,
|
|
|
mileage: mileage ? parseInt(mileage, 10) : undefined,
|
|
mileage: mileage ? parseInt(mileage, 10) : undefined,
|
|
|
- });
|
|
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
if (result.success && result.data) {
|
|
if (result.success && result.data) {
|
|
|
- toast.success("Inspection created");
|
|
|
|
|
- onOpenChange(false);
|
|
|
|
|
- router.push(`/inspections/${result.data.id}`);
|
|
|
|
|
|
|
+ toast.success('Inspection created')
|
|
|
|
|
+ onOpenChange(false)
|
|
|
|
|
+ router.push(`/inspections/${result.data.id}`)
|
|
|
} else {
|
|
} else {
|
|
|
- toast.error(result.error || "Failed to create inspection");
|
|
|
|
|
|
|
+ toast.error(result.error || 'Failed to create inspection')
|
|
|
}
|
|
}
|
|
|
- });
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
|
- <DialogContent className="sm:max-w-md">
|
|
|
|
|
|
|
+ <DialogContent className="sm:max-w-md" aria-describedby={undefined}>
|
|
|
<DialogHeader>
|
|
<DialogHeader>
|
|
|
<DialogTitle>New Inspection</DialogTitle>
|
|
<DialogTitle>New Inspection</DialogTitle>
|
|
|
</DialogHeader>
|
|
</DialogHeader>
|
|
@@ -128,12 +139,12 @@ export function NewInspectionDialog({
|
|
|
>
|
|
>
|
|
|
{vehicleId
|
|
{vehicleId
|
|
|
? (() => {
|
|
? (() => {
|
|
|
- const v = vehicles.find((v) => v.id === vehicleId);
|
|
|
|
|
|
|
+ const v = vehicles.find((v) => v.id === vehicleId)
|
|
|
return v
|
|
return v
|
|
|
- ? `${v.year} ${v.make} ${v.model}${v.licensePlate ? ` (${v.licensePlate})` : ""}`
|
|
|
|
|
- : "Select vehicle";
|
|
|
|
|
|
|
+ ? `${v.year} ${v.make} ${v.model}${v.licensePlate ? ` (${v.licensePlate})` : ''}`
|
|
|
|
|
+ : 'Select vehicle'
|
|
|
})()
|
|
})()
|
|
|
- : "Select vehicle"}
|
|
|
|
|
|
|
+ : 'Select vehicle'}
|
|
|
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
|
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
|
|
</Button>
|
|
</Button>
|
|
|
</PopoverTrigger>
|
|
</PopoverTrigger>
|
|
@@ -144,20 +155,25 @@ export function NewInspectionDialog({
|
|
|
<CommandEmpty>No vehicles found.</CommandEmpty>
|
|
<CommandEmpty>No vehicles found.</CommandEmpty>
|
|
|
<CommandGroup>
|
|
<CommandGroup>
|
|
|
{vehicles.map((v) => {
|
|
{vehicles.map((v) => {
|
|
|
- const label = `${v.year} ${v.make} ${v.model}${v.licensePlate ? ` (${v.licensePlate})` : ""}`;
|
|
|
|
|
|
|
+ const label = `${v.year} ${v.make} ${v.model}${v.licensePlate ? ` (${v.licensePlate})` : ''}`
|
|
|
return (
|
|
return (
|
|
|
<CommandItem
|
|
<CommandItem
|
|
|
key={v.id}
|
|
key={v.id}
|
|
|
value={label}
|
|
value={label}
|
|
|
onSelect={() => {
|
|
onSelect={() => {
|
|
|
- setVehicleId(v.id);
|
|
|
|
|
- setVehiclePopoverOpen(false);
|
|
|
|
|
|
|
+ setVehicleId(v.id)
|
|
|
|
|
+ setVehiclePopoverOpen(false)
|
|
|
}}
|
|
}}
|
|
|
>
|
|
>
|
|
|
- <Check className={cn("mr-2 h-4 w-4", vehicleId === v.id ? "opacity-100" : "opacity-0")} />
|
|
|
|
|
|
|
+ <Check
|
|
|
|
|
+ className={cn(
|
|
|
|
|
+ 'mr-2 h-4 w-4',
|
|
|
|
|
+ vehicleId === v.id ? 'opacity-100' : 'opacity-0'
|
|
|
|
|
+ )}
|
|
|
|
|
+ />
|
|
|
{label}
|
|
{label}
|
|
|
</CommandItem>
|
|
</CommandItem>
|
|
|
- );
|
|
|
|
|
|
|
+ )
|
|
|
})}
|
|
})}
|
|
|
</CommandGroup>
|
|
</CommandGroup>
|
|
|
</CommandList>
|
|
</CommandList>
|
|
@@ -171,7 +187,7 @@ export function NewInspectionDialog({
|
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center justify-between">
|
|
|
<Label>Template</Label>
|
|
<Label>Template</Label>
|
|
|
<Link
|
|
<Link
|
|
|
- href="/settings/templates?tab=inspection"
|
|
|
|
|
|
|
+ href="/settings/templates?tab=inspections"
|
|
|
className="inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground"
|
|
className="inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground"
|
|
|
onClick={() => onOpenChange(false)}
|
|
onClick={() => onOpenChange(false)}
|
|
|
>
|
|
>
|
|
@@ -187,7 +203,7 @@ export function NewInspectionDialog({
|
|
|
{templates.map((t) => (
|
|
{templates.map((t) => (
|
|
|
<SelectItem key={t.id} value={t.id}>
|
|
<SelectItem key={t.id} value={t.id}>
|
|
|
{t.name}
|
|
{t.name}
|
|
|
- {t.isDefault ? " (Default)" : ""}
|
|
|
|
|
|
|
+ {t.isDefault ? ' (Default)' : ''}
|
|
|
</SelectItem>
|
|
</SelectItem>
|
|
|
))}
|
|
))}
|
|
|
</SelectContent>
|
|
</SelectContent>
|
|
@@ -200,7 +216,7 @@ export function NewInspectionDialog({
|
|
|
type="number"
|
|
type="number"
|
|
|
value={mileage}
|
|
value={mileage}
|
|
|
onChange={(e) => setMileage(e.target.value)}
|
|
onChange={(e) => setMileage(e.target.value)}
|
|
|
- placeholder={serviceType === 'marine' ? "Current engine hours" : "Current mileage"}
|
|
|
|
|
|
|
+ placeholder={serviceType === 'marine' ? 'Current engine hours' : 'Current mileage'}
|
|
|
min={0}
|
|
min={0}
|
|
|
/>
|
|
/>
|
|
|
</div>
|
|
</div>
|
|
@@ -217,5 +233,5 @@ export function NewInspectionDialog({
|
|
|
</form>
|
|
</form>
|
|
|
</DialogContent>
|
|
</DialogContent>
|
|
|
</Dialog>
|
|
</Dialog>
|
|
|
- );
|
|
|
|
|
|
|
+ )
|
|
|
}
|
|
}
|