mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 07:38:10 +00:00
ui design for schedule
This commit is contained in:
@@ -1,20 +1,6 @@
|
||||
import { useCallback, useMemo, useRef, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import {
|
||||
AlertCircle,
|
||||
ArrowRight,
|
||||
Calendar,
|
||||
Clock,
|
||||
FileText,
|
||||
Inbox,
|
||||
LayoutList,
|
||||
Package,
|
||||
Plus,
|
||||
RefreshCw,
|
||||
Search,
|
||||
User,
|
||||
X,
|
||||
} from "lucide-react";
|
||||
import { ArrowRight, Calendar, Package, Search, User, X } from "lucide-react";
|
||||
import {
|
||||
Container,
|
||||
Stack,
|
||||
@@ -33,7 +19,7 @@ import {
|
||||
BookingStatusTabs,
|
||||
type BookingStatusTabKey,
|
||||
} from "@/components/bookings/BookingStatusTabs";
|
||||
import { BookingStatGrid } from "@/components/bookings/BookingStatGrid";
|
||||
import { BookingRequestsHeader } from "@/components/bookings/BookingRequestsHeader";
|
||||
import { BookingStatusBadge } from "@/components/bookings/BookingStatusBadge";
|
||||
import { BookingApprovalProgressCell } from "@/components/bookings/BookingApprovalProgressCell";
|
||||
import { AllocateBookingWizard } from "@/components/trainScheduling/AllocateBookingWizard";
|
||||
@@ -58,8 +44,6 @@ import {
|
||||
type ColumnDef,
|
||||
usePagination,
|
||||
Badge,
|
||||
Button,
|
||||
Input,
|
||||
} from "@edr/ui-common";
|
||||
|
||||
function getStatusesForTab(tab: BookingStatusTabKey): string | undefined {
|
||||
@@ -159,8 +143,6 @@ export default function BookingRequestsPage() {
|
||||
|
||||
const metrics = summary?.metrics;
|
||||
const tabCounts = summary?.tabs;
|
||||
const statValue = (value: number | undefined) =>
|
||||
summaryLoading ? "—" : (value ?? 0);
|
||||
|
||||
const handleRefresh = useCallback(() => {
|
||||
void refetch();
|
||||
@@ -315,88 +297,15 @@ export default function BookingRequestsPage() {
|
||||
<div style={{ background: "var(--mantine-color-gray-0)", minHeight: "100vh" }}>
|
||||
<Container size="xxl" py="xl">
|
||||
<Breadcrumbs items={[{ label: "Operations" }, { label: "Booking requests" }]} />
|
||||
{/*
|
||||
<Card
|
||||
p="lg"
|
||||
radius="lg"
|
||||
withBorder
|
||||
mb="xl"
|
||||
style={{
|
||||
background: "white",
|
||||
border: "1px solid var(--mantine-color-gray-2)",
|
||||
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.05)",
|
||||
}}
|
||||
>
|
||||
<Group justify="space-between" align="flex-start">
|
||||
<Group gap="md" align="flex-start">
|
||||
<ThemeIcon
|
||||
size="lg"
|
||||
radius="lg"
|
||||
color="green"
|
||||
variant="light"
|
||||
>
|
||||
<Inbox size={28} />
|
||||
</ThemeIcon>
|
||||
<Stack gap={8}>
|
||||
<Text size="xs" fw={600} c="dimmed" tt="uppercase">
|
||||
Operations
|
||||
</Text>
|
||||
<Title order={1} size="h2">
|
||||
Booking Requests
|
||||
</Title>
|
||||
<Text size="sm" c="dimmed" maw="500px">
|
||||
Track bookings from submission through payment and operations. Monitor status, prioritize urgent bookings, and manage approvals.
|
||||
</Text>
|
||||
</Stack>
|
||||
</Group>
|
||||
<MantineButton
|
||||
variant="light"
|
||||
color="green"
|
||||
leftSection={<RefreshCw size={18} />}
|
||||
disabled={isFetching}
|
||||
onClick={handleRefresh}
|
||||
loading={isFetching}
|
||||
>
|
||||
Refresh
|
||||
</MantineButton>
|
||||
</Group>
|
||||
</Card> */}
|
||||
|
||||
<div className="mt-6"></div>
|
||||
<Stack gap="lg">
|
||||
<BookingStatGrid
|
||||
items={[
|
||||
{
|
||||
label: "In queue",
|
||||
value: statValue(metrics?.inQueue),
|
||||
hint: "Total matching filter",
|
||||
icon: LayoutList,
|
||||
},
|
||||
{
|
||||
label: "On this page",
|
||||
value: statValue(metrics?.onThisPage),
|
||||
hint: "Current page",
|
||||
icon: FileText,
|
||||
},
|
||||
{
|
||||
label: "Needs action",
|
||||
value: statValue(metrics?.needsAction),
|
||||
hint: "Submitted or pending approval",
|
||||
icon: Clock,
|
||||
accent:
|
||||
!summaryLoading && (metrics?.needsAction ?? 0) > 0
|
||||
? "amber"
|
||||
: "default",
|
||||
},
|
||||
{
|
||||
label: "Urgent",
|
||||
value: statValue(metrics?.urgent),
|
||||
hint: "High priority score",
|
||||
icon: AlertCircle,
|
||||
accent:
|
||||
!summaryLoading && (metrics?.urgent ?? 0) > 0 ? "rose" : "default",
|
||||
},
|
||||
]}
|
||||
<Stack gap="lg" mt="md">
|
||||
<BookingRequestsHeader
|
||||
metrics={metrics}
|
||||
tabs={tabCounts}
|
||||
loading={summaryLoading}
|
||||
isFetching={isFetching}
|
||||
onCreate={() => navigate("/dashboard/booking-requests/new")}
|
||||
onRefresh={handleRefresh}
|
||||
/>
|
||||
|
||||
<Paper
|
||||
@@ -450,18 +359,9 @@ export default function BookingRequestsPage() {
|
||||
style={{ flex: 1, minWidth: "200px" }}
|
||||
radius="lg"
|
||||
/>
|
||||
<Group gap="sm">
|
||||
<Button
|
||||
variant="filled"
|
||||
leftSection={<Plus size={16} />}
|
||||
onClick={() => navigate("/dashboard/booking-requests/new")}
|
||||
>
|
||||
Create booking
|
||||
</Button>
|
||||
<Text size="sm" c="dimmed">
|
||||
{total} record{total !== 1 ? "s" : ""}
|
||||
</Text>
|
||||
</Group>
|
||||
<Text size="sm" c="dimmed">
|
||||
{total} record{total !== 1 ? "s" : ""}
|
||||
</Text>
|
||||
</Group>
|
||||
|
||||
{isOperationsTab ? (
|
||||
|
||||
@@ -22,6 +22,7 @@ import { useQueryClient } from "@tanstack/react-query";
|
||||
import { OverviewPageHeader } from "@/components/overview/OverviewPageHeader";
|
||||
import { OverviewQuickLinks } from "@/components/overview/OverviewQuickLinks";
|
||||
import { OverviewTabContent } from "@/components/overview/OverviewTabContent";
|
||||
import "@/components/overview/overview.css";
|
||||
import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
|
||||
import { useOverview } from "@/hooks/useOverview";
|
||||
import type { OverviewRange, OverviewTabKey } from "@/types/overview";
|
||||
@@ -127,60 +128,53 @@ const OverviewPage = () => {
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<Paper
|
||||
radius="lg"
|
||||
withBorder
|
||||
p="md"
|
||||
style={{
|
||||
background: "white",
|
||||
border: "1px solid var(--mantine-color-gray-2)",
|
||||
}}
|
||||
<Tabs
|
||||
value={activeTab}
|
||||
onChange={(value) => setActiveTab((value as OverviewTabKey) ?? "bookings")}
|
||||
variant="pills"
|
||||
color="green"
|
||||
keepMounted={false}
|
||||
classNames={{ list: "ov-tablist", tab: "ov-tab" }}
|
||||
>
|
||||
<Tabs
|
||||
value={activeTab}
|
||||
onChange={(value) => setActiveTab((value as OverviewTabKey) ?? "bookings")}
|
||||
variant="pills"
|
||||
color="green"
|
||||
keepMounted={false}
|
||||
>
|
||||
<Tabs.List
|
||||
style={{
|
||||
flexWrap: "wrap",
|
||||
gap: 8,
|
||||
background: "var(--freight-brand-muted, #f0fdf4)",
|
||||
padding: 8,
|
||||
borderRadius: 12,
|
||||
}}
|
||||
>
|
||||
{TAB_ITEMS.map((tab) => {
|
||||
const Icon = tab.icon;
|
||||
return (
|
||||
<Tabs.Tab
|
||||
key={tab.value}
|
||||
value={tab.value}
|
||||
leftSection={<Icon size={16} />}
|
||||
rightSection={
|
||||
summary ? (
|
||||
<Badge size="sm" variant="light" color="green">
|
||||
{getTabBadge(tab)}
|
||||
</Badge>
|
||||
) : undefined
|
||||
}
|
||||
style={{ fontWeight: 600 }}
|
||||
>
|
||||
{tab.label}
|
||||
</Tabs.Tab>
|
||||
);
|
||||
})}
|
||||
</Tabs.List>
|
||||
<Tabs.List>
|
||||
{TAB_ITEMS.map((tab) => {
|
||||
const Icon = tab.icon;
|
||||
const isActive = activeTab === tab.value;
|
||||
return (
|
||||
<Tabs.Tab
|
||||
key={tab.value}
|
||||
value={tab.value}
|
||||
leftSection={<Icon size={17} />}
|
||||
rightSection={
|
||||
summary ? (
|
||||
<Badge
|
||||
size="sm"
|
||||
radius="sm"
|
||||
variant={isActive ? "white" : "light"}
|
||||
color={isActive ? "green" : "gray"}
|
||||
styles={
|
||||
isActive
|
||||
? { root: { background: "rgba(255,255,255,0.9)", color: "#15803d" } }
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{getTabBadge(tab)}
|
||||
</Badge>
|
||||
) : undefined
|
||||
}
|
||||
>
|
||||
{tab.label}
|
||||
</Tabs.Tab>
|
||||
);
|
||||
})}
|
||||
</Tabs.List>
|
||||
|
||||
{TAB_ITEMS.map((tab) => (
|
||||
<Tabs.Panel key={tab.value} value={tab.value} pt="lg">
|
||||
<OverviewTabContent tab={tab.value} range={range} />
|
||||
</Tabs.Panel>
|
||||
))}
|
||||
</Tabs>
|
||||
</Paper>
|
||||
{TAB_ITEMS.map((tab) => (
|
||||
<Tabs.Panel key={tab.value} value={tab.value} pt="lg">
|
||||
<OverviewTabContent tab={tab.value} range={range} />
|
||||
</Tabs.Panel>
|
||||
))}
|
||||
</Tabs>
|
||||
|
||||
<Paper p="lg" radius="lg" withBorder>
|
||||
<OverviewQuickLinks />
|
||||
|
||||
Reference in New Issue
Block a user