This commit is contained in:
natib21
2026-06-19 13:07:03 +00:00
parent 58bfb5045a
commit d49c7a48d5
3 changed files with 129 additions and 77 deletions

View File

@@ -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}

View File

@@ -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)}>

View File

@@ -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
}
/>