mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 00:38:11 +00:00
fix
This commit is contained in:
@@ -23,7 +23,7 @@ import {
|
||||
Marker,
|
||||
useMap,
|
||||
} from "@vis.gl/react-google-maps";
|
||||
import { Activity, Plus, Radio, Trash2 } from "lucide-react";
|
||||
import { Activity, Pencil, Plus, Radio, Trash2 } from "lucide-react";
|
||||
import Breadcrumbs from "@/components/ui/Breadcrumbs";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { vehiclesService } from "@/services/vehicles.service";
|
||||
@@ -97,9 +97,21 @@ export function TrackingPage() {
|
||||
const { toast } = useToast();
|
||||
const qc = useQueryClient();
|
||||
const [selectedId, setSelectedId] = useState<string | null>(null);
|
||||
const [registerOpen, setRegisterOpen] = useState(false);
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
const [editDevice, setEditDevice] = useState<GpsDevice | null>(null);
|
||||
const [form, setForm] = useState({ imei: "", name: "", vehicleId: "" });
|
||||
|
||||
const openRegister = () => {
|
||||
setEditDevice(null);
|
||||
setForm({ imei: "", name: "", vehicleId: "" });
|
||||
setModalOpen(true);
|
||||
};
|
||||
const openEdit = (d: GpsDevice) => {
|
||||
setEditDevice(d);
|
||||
setForm({ imei: d.imei, name: d.name ?? "", vehicleId: d.vehicleId ?? "" });
|
||||
setModalOpen(true);
|
||||
};
|
||||
|
||||
// Poll every 10s so the map tracks live movement.
|
||||
const { data: devices = [] } = useQuery({
|
||||
queryKey: ["gps", "devices"],
|
||||
@@ -155,23 +167,29 @@ export function TrackingPage() {
|
||||
} as google.maps.Symbol;
|
||||
};
|
||||
|
||||
const registerMutation = useMutation({
|
||||
const saveMutation = useMutation({
|
||||
mutationFn: () =>
|
||||
gpsTrackingService.register({
|
||||
imei: form.imei.trim(),
|
||||
name: form.name.trim() || undefined,
|
||||
vehicleId: form.vehicleId || null,
|
||||
}),
|
||||
editDevice
|
||||
? gpsTrackingService.update(editDevice.id, {
|
||||
name: form.name.trim() || undefined,
|
||||
vehicleId: form.vehicleId || null,
|
||||
})
|
||||
: gpsTrackingService.register({
|
||||
imei: form.imei.trim(),
|
||||
name: form.name.trim() || undefined,
|
||||
vehicleId: form.vehicleId || null,
|
||||
}),
|
||||
onSuccess: () => {
|
||||
toast({ title: "Tracker registered" });
|
||||
setRegisterOpen(false);
|
||||
toast({ title: editDevice ? "Tracker updated" : "Tracker registered" });
|
||||
setModalOpen(false);
|
||||
setEditDevice(null);
|
||||
setForm({ imei: "", name: "", vehicleId: "" });
|
||||
void qc.invalidateQueries({ queryKey: ["gps", "devices"] });
|
||||
},
|
||||
onError: (err: unknown) => {
|
||||
const description =
|
||||
(err as { response?: { data?: { message?: string } } })?.response?.data?.message ?? "Failed";
|
||||
toast({ title: "Registration failed", description, variant: "destructive" });
|
||||
toast({ title: editDevice ? "Update failed" : "Registration failed", description, variant: "destructive" });
|
||||
},
|
||||
});
|
||||
|
||||
@@ -204,7 +222,7 @@ export function TrackingPage() {
|
||||
<Text fw={700} size="xl">Real-Time Vehicle Tracking</Text>
|
||||
<Text c="dimmed" size="sm">Live GPS positions from GT06 trackers</Text>
|
||||
</div>
|
||||
<Button leftSection={<Plus size={16} />} color="edr-green" onClick={() => setRegisterOpen(true)}>
|
||||
<Button leftSection={<Plus size={16} />} color="edr-green" onClick={openRegister}>
|
||||
Register tracker
|
||||
</Button>
|
||||
</Group>
|
||||
@@ -327,7 +345,17 @@ export function TrackingPage() {
|
||||
</Stack>
|
||||
</Table.Td>
|
||||
<Table.Td align="right">
|
||||
<Badge color={d.online ? "edr-green" : "gray"} size="sm">{d.online ? "Live" : "Offline"}</Badge>
|
||||
<Group gap={6} justify="flex-end" wrap="nowrap">
|
||||
<Badge color={d.online ? "edr-green" : "gray"} size="sm">{d.online ? "Live" : "Offline"}</Badge>
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
size="sm"
|
||||
aria-label="Edit tracker"
|
||||
onClick={(e) => { e.stopPropagation(); openEdit(d); }}
|
||||
>
|
||||
<Pencil size={15} />
|
||||
</ActionIcon>
|
||||
</Group>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))}
|
||||
@@ -347,13 +375,20 @@ export function TrackingPage() {
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
|
||||
{/* Register modal */}
|
||||
<Modal opened={registerOpen} onClose={() => setRegisterOpen(false)} title="Register GPS tracker" radius="lg" centered>
|
||||
{/* Register / edit modal */}
|
||||
<Modal
|
||||
opened={modalOpen}
|
||||
onClose={() => setModalOpen(false)}
|
||||
title={editDevice ? "Edit GPS tracker" : "Register GPS tracker"}
|
||||
radius="lg"
|
||||
centered
|
||||
>
|
||||
<Stack gap="md">
|
||||
<TextInput
|
||||
label="IMEI"
|
||||
placeholder="15-digit device IMEI"
|
||||
required
|
||||
disabled={Boolean(editDevice)}
|
||||
value={form.imei}
|
||||
onChange={(e) => setForm({ ...form, imei: e.currentTarget.value })}
|
||||
/>
|
||||
@@ -373,13 +408,13 @@ export function TrackingPage() {
|
||||
clearable
|
||||
/>
|
||||
<Group justify="flex-end">
|
||||
<Button variant="default" onClick={() => setRegisterOpen(false)}>Cancel</Button>
|
||||
<Button variant="default" onClick={() => setModalOpen(false)}>Cancel</Button>
|
||||
<Button
|
||||
loading={registerMutation.isPending}
|
||||
loading={saveMutation.isPending}
|
||||
disabled={!form.imei.trim()}
|
||||
onClick={() => registerMutation.mutate()}
|
||||
onClick={() => saveMutation.mutate()}
|
||||
>
|
||||
Register
|
||||
{editDevice ? "Save" : "Register"}
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
|
||||
Reference in New Issue
Block a user