mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 09:00:57 +00:00
vehicle
This commit is contained in:
@@ -84,29 +84,46 @@ const FleetCardGrid = ({
|
||||
radius="lg"
|
||||
padding="lg"
|
||||
withBorder
|
||||
style={{ borderColor: "var(--mantine-color-gray-2)" }}
|
||||
style={{
|
||||
borderColor: "var(--mantine-color-gray-2)",
|
||||
transition: "all 200ms ease",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
className="hover:shadow-md hover:border-green-3"
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.boxShadow =
|
||||
"0 4px 12px rgba(0, 0, 0, 0.08)";
|
||||
e.currentTarget.style.borderColor =
|
||||
"var(--mantine-color-green-3)";
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.boxShadow = "none";
|
||||
e.currentTarget.style.borderColor =
|
||||
"var(--mantine-color-gray-2)";
|
||||
}}
|
||||
>
|
||||
<Stack gap="md">
|
||||
<Group justify="space-between" align="flex-start" wrap="nowrap">
|
||||
<Group gap="sm" wrap="nowrap">
|
||||
<Group gap="sm" wrap="nowrap" style={{ flex: 1 }}>
|
||||
<div
|
||||
style={{
|
||||
width: 40,
|
||||
height: 40,
|
||||
borderRadius: 10,
|
||||
background: "var(--mantine-color-green-0)",
|
||||
color: "var(--mantine-color-green-7)",
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: 12,
|
||||
background: "linear-gradient(135deg, var(--mantine-color-green-0), var(--mantine-color-green-1))",
|
||||
color: "var(--mantine-color-green-8)",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
fontWeight: 700,
|
||||
fontSize: 14,
|
||||
fontSize: 16,
|
||||
flexShrink: 0,
|
||||
}}
|
||||
>
|
||||
{cardInitials(title)}
|
||||
</div>
|
||||
<Stack gap={2}>
|
||||
<Text fw={600} size="sm" lineClamp={1}>
|
||||
<Stack gap={4} style={{ flex: 1, minWidth: 0 }}>
|
||||
<Text fw={700} size="sm" lineClamp={1} c="dark">
|
||||
{title || "—"}
|
||||
</Text>
|
||||
{subtitle != null && subtitle !== "" ? (
|
||||
@@ -120,7 +137,7 @@ const FleetCardGrid = ({
|
||||
</Stack>
|
||||
</Group>
|
||||
{code != null && code !== "" ? (
|
||||
<Badge variant="light" color="blue" size="sm" radius="md">
|
||||
<Badge variant="filled" color="green" size="sm" radius="md" style={{ flexShrink: 0 }}>
|
||||
{String(code)}
|
||||
</Badge>
|
||||
) : null}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MoreHorizontal, Pencil, Trash2, Truck } from "lucide-react";
|
||||
import { MoreHorizontal, Pencil, Trash2, Eye, Copy } from "lucide-react";
|
||||
import { ActionIcon, Button, Group, Menu, Tooltip } from "@mantine/core";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
@@ -33,37 +33,40 @@ const FleetRecordActions = ({
|
||||
return (
|
||||
<Group gap={6} wrap="nowrap" justify="flex-end">
|
||||
{showDetail ? (
|
||||
<Button
|
||||
variant="light"
|
||||
color="green"
|
||||
size="compact-sm"
|
||||
radius="md"
|
||||
onClick={handleDetail}
|
||||
leftSection={<Truck size={14} />}
|
||||
>
|
||||
Manage wagons
|
||||
</Button>
|
||||
<Tooltip label="View details">
|
||||
<ActionIcon
|
||||
variant="light"
|
||||
color="green"
|
||||
size="md"
|
||||
radius="md"
|
||||
onClick={handleDetail}
|
||||
>
|
||||
<Eye size={16} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
<Button
|
||||
variant="light"
|
||||
color="gray"
|
||||
size="compact-sm"
|
||||
radius="md"
|
||||
onClick={() => onEdit(record)}
|
||||
leftSection={<Pencil size={14} />}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
<Button
|
||||
variant="light"
|
||||
color="red"
|
||||
size="compact-sm"
|
||||
radius="md"
|
||||
onClick={() => onRemove(record)}
|
||||
leftSection={<Trash2 size={14} />}
|
||||
>
|
||||
{removeLabel}
|
||||
</Button>
|
||||
<Tooltip label="Edit">
|
||||
<ActionIcon
|
||||
variant="light"
|
||||
color="blue"
|
||||
size="md"
|
||||
radius="md"
|
||||
onClick={() => onEdit(record)}
|
||||
>
|
||||
<Pencil size={16} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
<Tooltip label={removeLabel}>
|
||||
<ActionIcon
|
||||
variant="light"
|
||||
color="red"
|
||||
size="md"
|
||||
radius="md"
|
||||
onClick={() => onRemove(record)}
|
||||
>
|
||||
<Trash2 size={16} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
@@ -71,22 +74,24 @@ const FleetRecordActions = ({
|
||||
return (
|
||||
<Group gap={4} wrap="nowrap" justify="flex-end">
|
||||
{showDetail ? (
|
||||
<Tooltip label="Manage wagons">
|
||||
<ActionIcon variant="subtle" color="green" size="md" radius="md" onClick={handleDetail}>
|
||||
<Truck size={16} />
|
||||
<Tooltip label="View details">
|
||||
<ActionIcon variant="light" color="green" size="md" radius="md" onClick={handleDetail}>
|
||||
<Eye size={16} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
<Tooltip label="Edit">
|
||||
<ActionIcon variant="subtle" color="gray" size="md" radius="md" onClick={() => onEdit(record)}>
|
||||
<ActionIcon variant="light" color="blue" size="md" radius="md" onClick={() => onEdit(record)}>
|
||||
<Pencil size={16} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
<Menu position="bottom-end" withinPortal>
|
||||
<Menu.Target>
|
||||
<ActionIcon variant="subtle" color="gray" size="md" radius="md">
|
||||
<MoreHorizontal size={16} />
|
||||
</ActionIcon>
|
||||
<Tooltip label="More actions">
|
||||
<ActionIcon variant="light" color="gray" size="md" radius="md">
|
||||
<MoreHorizontal size={16} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</Menu.Target>
|
||||
<Menu.Dropdown>
|
||||
<Menu.Item color="red" leftSection={<Trash2 size={14} />} onClick={() => onRemove(record)}>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Navigate, useLocation } from "react-router-dom";
|
||||
import type { ColumnDef } from "@edr/ui-common";
|
||||
import { Box, Button, Card, Group, Modal, Select, Stack, Text } from "@mantine/core";
|
||||
import { Box, Button, Card, Group, Modal, Stack, Text } from "@mantine/core";
|
||||
import { Badge } from "@mantine/core";
|
||||
|
||||
import FleetCardGrid from "@/components/fleet/FleetCardGrid";
|
||||
import FleetFormDialog from "@/components/fleet/FleetFormDialog";
|
||||
@@ -291,10 +292,23 @@ const FleetResourcePage = () => {
|
||||
const itemLabel = config.label.toLowerCase();
|
||||
|
||||
return (
|
||||
<Stack gap="md">
|
||||
<Stack gap="lg" style={{ maxWidth: "100%" }}>
|
||||
<Box>
|
||||
<Stack gap="xs">
|
||||
<div>
|
||||
<Text size="lg" fw={700} c="dark">
|
||||
{config.label}
|
||||
</Text>
|
||||
<Text size="sm" c="dimmed">
|
||||
{config.subtitle}
|
||||
</Text>
|
||||
</div>
|
||||
</Stack>
|
||||
</Box>
|
||||
|
||||
<Card radius="lg" padding={0} withBorder style={{ borderColor: "var(--mantine-color-gray-2)" }}>
|
||||
<Stack gap={0}>
|
||||
<Box px="md" pt="md" pb="sm" w="100%">
|
||||
<Box px="md" pt="md" pb="md" w="100%" style={{ borderBottom: "1px solid var(--mantine-color-gray-2)" }}>
|
||||
<FleetToolbar
|
||||
search={search}
|
||||
onSearchChange={setSearch}
|
||||
@@ -309,35 +323,51 @@ const FleetResourcePage = () => {
|
||||
onViewModeChange={setViewMode}
|
||||
filters={
|
||||
listFilterSelects ? (
|
||||
<Group gap="xs" wrap="nowrap">
|
||||
<Group gap="xs" wrap="wrap">
|
||||
{listFilterSelects.map((filter) => (
|
||||
<Select
|
||||
key={filter.key}
|
||||
size="sm"
|
||||
radius="lg"
|
||||
label={filter.label}
|
||||
value={filter.value}
|
||||
onChange={(v) => {
|
||||
if (!v) return;
|
||||
setListFilterValues((prev) => ({ ...prev, [filter.key]: v }));
|
||||
setPagination((prev) => ({ ...prev, pageIndex: 0 }));
|
||||
}}
|
||||
data={filter.data}
|
||||
w={170}
|
||||
styles={{ input: { borderColor: "var(--mantine-color-gray-3)" } }}
|
||||
/>
|
||||
<Group key={filter.key} gap={4} wrap="wrap">
|
||||
<Text size="xs" fw={500} c="dimmed">{filter.label}:</Text>
|
||||
<Group gap={4} wrap="wrap">
|
||||
{[{ value: "ALL", label: "All" }, ...filter.data].map((option) => (
|
||||
<Button
|
||||
key={option.value}
|
||||
size="xs"
|
||||
radius="md"
|
||||
variant={filter.value === option.value ? "filled" : "light"}
|
||||
color={filter.value === option.value ? "green" : "gray"}
|
||||
onClick={() => {
|
||||
setListFilterValues((prev) => ({
|
||||
...prev,
|
||||
[filter.key]: option.value,
|
||||
}));
|
||||
setPagination((prev) => ({ ...prev, pageIndex: 0 }));
|
||||
}}
|
||||
>
|
||||
{option.label}
|
||||
</Button>
|
||||
))}
|
||||
</Group>
|
||||
</Group>
|
||||
))}
|
||||
</Group>
|
||||
) : hasStatusColumn && statusFilterOptions.length > 1 ? (
|
||||
<Select
|
||||
size="sm"
|
||||
radius="lg"
|
||||
value={statusFilter}
|
||||
onChange={(v) => v && setStatusFilter(v)}
|
||||
data={statusFilterOptions}
|
||||
w={160}
|
||||
styles={{ input: { borderColor: "var(--mantine-color-gray-3)" } }}
|
||||
/>
|
||||
<Group gap={4} wrap="wrap">
|
||||
<Text size="xs" fw={500} c="dimmed">Status:</Text>
|
||||
<Group gap={4} wrap="wrap">
|
||||
{[{ value: "ALL", label: "All" }, ...statusFilterOptions].map((option) => (
|
||||
<Button
|
||||
key={option.value}
|
||||
size="xs"
|
||||
radius="md"
|
||||
variant={statusFilter === option.value ? "filled" : "light"}
|
||||
color={statusFilter === option.value ? "green" : "gray"}
|
||||
onClick={() => setStatusFilter(option.value)}
|
||||
>
|
||||
{option.label}
|
||||
</Button>
|
||||
))}
|
||||
</Group>
|
||||
</Group>
|
||||
) : undefined
|
||||
}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user