fix local merge conflict

This commit is contained in:
mengstabketemaw
2026-05-23 10:52:31 +03:00
parent 578f6f84ef
commit 3485ef299d
7 changed files with 1862 additions and 1511 deletions

View File

@@ -0,0 +1,228 @@
import { useMemo, useState } from "react";
import {
AlertCircle,
CircleOff,
Loader2,
MapPin,
Search,
TrainFront,
} from "lucide-react";
import Breadcrumbs from "@/components/Breadcrumbs";
import { useDropdownSettingByCode } from "@/hooks/useDropdownSettings";
import type { DropdownOption } from "@/types/dropdownSettings";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
DataTable,
DataTableFooter,
Input,
type ColumnDef,
usePagination,
} from "@edr/ui-common";
const STATION_DROPDOWN_CODE = "stations_ter";
export default function Station() {
const { pagination, setPagination } = usePagination({ pageSize: 10 });
const [query, setQuery] = useState("");
const { data, isLoading, isError, error } = useDropdownSettingByCode(
STATION_DROPDOWN_CODE,
);
const stations = useMemo<DropdownOption[]>(
() => [...(data?.children ?? [])].sort((a, b) => a.order - b.order),
[data?.children],
);
const filtered = useMemo(() => {
const q = query.trim().toLowerCase();
if (!q) return stations;
return stations.filter(
(station) =>
station.label.toLowerCase().includes(q) ||
station.value.toLowerCase().includes(q) ||
(station.note ?? "").toLowerCase().includes(q),
);
}, [query, stations]);
const total = filtered.length;
const pageCount = Math.max(1, Math.ceil(total / pagination.pageSize));
const start = pagination.pageIndex * pagination.pageSize;
const end = Math.min(start + pagination.pageSize, total);
const paginatedData = useMemo(
() => filtered.slice(start, end),
[end, filtered, start],
);
const activeCount = stations.filter((station) => !station.disabled).length;
const disabledCount = stations.length - activeCount;
const status: "loading" | "error" | "success" = isLoading
? "loading"
: isError
? "error"
: "success";
const columns: ColumnDef<DropdownOption>[] = [
{
id: "station",
header: "Station",
cell: ({ row }) => {
const station = row.original;
return (
<div className="flex items-center gap-3">
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-primary text-primary-foreground">
<MapPin />
</div>
<div>
<p className="font-medium text-slate-900">{station.label}</p>
<p className="text-xs text-slate-500">
{station.note ?? "No station note"}
</p>
</div>
</div>
);
},
},
{
id: "value",
header: "Code",
cell: ({ row }) => (
<span className="rounded-md bg-slate-100 px-2 py-1 font-mono text-xs text-slate-700">
{row.original.value}
</span>
),
},
{
accessorKey: "order",
header: "Order",
},
{
id: "status",
header: "Status",
cell: ({ row }) =>
row.original.disabled ? (
<span className="inline-flex items-center gap-1 rounded-full bg-slate-100 px-2 py-0.5 text-xs font-medium text-slate-600">
<CircleOff className="h-3 w-3" />
Disabled
</span>
) : (
<span className="inline-flex items-center gap-1 rounded-full bg-primary/10 px-2 py-0.5 text-xs font-medium text-primary">
<TrainFront className="h-3 w-3" />
Active
</span>
),
},
];
return (
<div className="min-h-screen p-6">
<div className="space-y-6">
<Breadcrumbs items={[{ label: "Stations" }]} />
<Card className="p-6 flex-row justify-between">
<div>
<h1 className="text-3xl font-bold tracking-tight text-slate-900">
Stations
</h1>
<p className="mt-1 text-sm text-secondary-foreground">
Station options loaded from dropdown code{" "}
<span className="font-mono">stations_ter</span>.
</p>
</div>
<div className="relative w-full sm:w-80">
<Search className="pointer-events-none absolute left-2 top-1/2 h-4 w-4 -translate-y-1/2 text-slate-400" />
<Input
type="search"
value={query}
onChange={(event) => {
setQuery(event.target.value);
setPagination({
pageIndex: 0,
pageSize: pagination.pageSize,
});
}}
placeholder="Search stations..."
className="pl-8!"
/>
</div>
</Card>
<div className="grid gap-4 md:grid-cols-3">
<StationStat label="Stations" value={stations.length} />
<StationStat label="Active" value={activeCount} />
<StationStat label="Disabled" value={disabledCount} />
</div>
{isError ? (
<Card>
<CardContent className="flex items-center gap-3 py-6 text-sm text-red-600">
<AlertCircle className="h-5 w-5" />
Failed to load stations.{" "}
{error instanceof Error ? error.message : "Unknown error."}
</CardContent>
</Card>
) : null}
<Card className="gap-0">
<CardHeader className="border-b">
<CardTitle>Station List</CardTitle>
<CardDescription>
All configured freight stations from the dropdown service.
</CardDescription>
</CardHeader>
<CardContent className="px-0">
{isLoading ? (
<div className="flex items-center justify-center py-12 text-sm text-slate-500">
<Loader2 className="mr-2 h-4 w-4 animate-spin text-primary" />
Loading stations...
</div>
) : (
<DataTable
columns={columns}
data={paginatedData}
status={status}
pagination={{
pageIndex: pagination.pageIndex,
pageSize: pagination.pageSize,
pageCount,
totalCount: total,
}}
tableOptions={{
state: { pagination },
onPaginationChange: setPagination,
}}
containerClassName="border-b shadow-none"
footer={DataTableFooter}
/>
)}
</CardContent>
</Card>
</div>
</div>
);
}
function StationStat({ label, value }: { label: string; value: number }) {
return (
<Card>
<CardContent className="flex items-center justify-between">
<div>
<p className="text-sm text-slate-500">{label}</p>
<h3 className="mt-2 text-3xl font-bold text-slate-900">{value}</h3>
</div>
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-primary/10 text-primary">
<MapPin />
</div>
</CardContent>
</Card>
);
}