mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 13:10:56 +00:00
style: booking detail pages fix
This commit is contained in:
@@ -18,6 +18,7 @@ import {
|
||||
X,
|
||||
XCircle,
|
||||
} from "lucide-react";
|
||||
|
||||
import { useMemo, useRef, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
@@ -136,22 +137,17 @@ export function DraftBookingView({
|
||||
<PageHeader
|
||||
booking={booking}
|
||||
actions={
|
||||
<>
|
||||
<HeaderButton
|
||||
icon={<Download size={16} />}
|
||||
label="Documents"
|
||||
onClick={() =>
|
||||
documentsRef.current?.scrollIntoView({ behavior: "smooth" })
|
||||
}
|
||||
/>
|
||||
<HeaderButton
|
||||
dark
|
||||
icon={<Pencil size={16} />}
|
||||
label="Continue editing"
|
||||
onClick={() => navigate(`/bookings/${booking.id}/edit`)}
|
||||
/>
|
||||
</>
|
||||
<HeaderButton
|
||||
dark
|
||||
icon={<Pencil size={16} />}
|
||||
label="Continue editing"
|
||||
onClick={() => navigate(`/bookings/${booking.id}/edit`)}
|
||||
/>
|
||||
}
|
||||
menuActions={{
|
||||
onCancel: () => setCancelDialogOpen(true),
|
||||
onSupport: () => navigate("/support"),
|
||||
}}
|
||||
/>
|
||||
|
||||
<MutationErrors
|
||||
@@ -249,7 +245,7 @@ export function DraftBookingView({
|
||||
<NoticeBanner
|
||||
tone="red"
|
||||
icon={<AlertCircle size={16} />}
|
||||
style={{ marginBottom: 12 }}
|
||||
className="mb-3"
|
||||
>
|
||||
{docError}
|
||||
</NoticeBanner>
|
||||
|
||||
@@ -49,6 +49,11 @@ export function ReadonlyBookingView({ booking }: { booking: Freight.IBooking })
|
||||
/>
|
||||
)
|
||||
}
|
||||
menuActions={{
|
||||
onViewContract: booking.signedByCeoAt ? () => {} : undefined,
|
||||
onRebook: () => navigate("/bookings/new"),
|
||||
onSupport: () => navigate("/support"),
|
||||
}}
|
||||
/>
|
||||
|
||||
{isNegative(status) ? (
|
||||
|
||||
@@ -7,13 +7,13 @@ export function NoticeBanner({
|
||||
icon,
|
||||
title,
|
||||
children,
|
||||
style,
|
||||
className,
|
||||
}: {
|
||||
tone: "amber" | "red";
|
||||
icon: ReactNode;
|
||||
title?: string;
|
||||
children: ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
}) {
|
||||
const palette =
|
||||
tone === "amber"
|
||||
@@ -21,33 +21,26 @@ export function NoticeBanner({
|
||||
: { border: "#F3C8C1", bg: "#FBEAE7", color: "#A93226" };
|
||||
|
||||
return (
|
||||
<Group
|
||||
align="flex-start"
|
||||
gap={12}
|
||||
wrap="nowrap"
|
||||
p="md"
|
||||
<div
|
||||
className={`flex items-start gap-3 rounded-[14px] border p-4 ${className ?? ""}`}
|
||||
style={{
|
||||
borderRadius: 14,
|
||||
border: `1px solid ${palette.border}`,
|
||||
borderColor: palette.border,
|
||||
backgroundColor: palette.bg,
|
||||
color: palette.color,
|
||||
...style,
|
||||
}}
|
||||
>
|
||||
<Box component="span" mt={2} style={{ flexShrink: 0 }}>
|
||||
{icon}
|
||||
</Box>
|
||||
<Box miw={0}>
|
||||
<span className="mt-0.5 shrink-0">{icon}</span>
|
||||
<div className="min-w-0">
|
||||
{title && (
|
||||
<Text fz="13.5px" fw={800} c={palette.color}>
|
||||
{title}
|
||||
</Text>
|
||||
)}
|
||||
<Text fz="13px" c={palette.color} style={{ lineHeight: 1.45 }}>
|
||||
<Text fz="13px" c={palette.color} className="leading-[1.45]">
|
||||
{children}
|
||||
</Text>
|
||||
</Box>
|
||||
</Group>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -61,54 +54,35 @@ export function ActionRequiredBanner({
|
||||
onAction?: () => void;
|
||||
}) {
|
||||
return (
|
||||
<Group
|
||||
justify="space-between"
|
||||
align="center"
|
||||
wrap="wrap"
|
||||
gap={24}
|
||||
px={22}
|
||||
py={20}
|
||||
style={{
|
||||
borderRadius: 16,
|
||||
backgroundColor: "#FDF3E0",
|
||||
border: "1px solid #F4D9A8",
|
||||
}}
|
||||
<div
|
||||
className="flex flex-wrap items-center justify-between gap-6 rounded-2xl border border-[#F4D9A8] px-[22px] py-5"
|
||||
style={{ backgroundColor: "#FDF3E0" }}
|
||||
>
|
||||
<Group gap={16} align="center" wrap="nowrap" miw={0} flex={1}>
|
||||
<Box
|
||||
style={{
|
||||
flexShrink: 0,
|
||||
width: 44,
|
||||
height: 44,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
borderRadius: 12,
|
||||
backgroundColor: "#fff",
|
||||
border: "1px solid #F4D9A8",
|
||||
color: "#C77F12",
|
||||
}}
|
||||
<div className="flex min-w-0 flex-1 items-center gap-4">
|
||||
<div
|
||||
className="flex shrink-0 items-center justify-center rounded-xl border border-[#F4D9A8]"
|
||||
style={{ width: 44, height: 44, backgroundColor: "#fff", color: "#C77F12" }}
|
||||
>
|
||||
<AlertTriangle size={23} />
|
||||
</Box>
|
||||
<Box miw={0}>
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<Text
|
||||
fz="10.5px"
|
||||
fw={800}
|
||||
c="#B07A2A"
|
||||
tt="uppercase"
|
||||
style={{ letterSpacing: 0.6 }}
|
||||
className="tracking-[0.6px]"
|
||||
>
|
||||
Action required · You
|
||||
</Text>
|
||||
<Text mt={5} fz="15.5px" fw={700} c="#10202F">
|
||||
{title}
|
||||
</Text>
|
||||
<Text mt={2} fz="13px" c="#7A6A4E" style={{ lineHeight: 1.45 }}>
|
||||
<Text mt={2} fz="13px" c="#7A6A4E" className="leading-[1.45]">
|
||||
{children}
|
||||
</Text>
|
||||
</Box>
|
||||
</Group>
|
||||
</div>
|
||||
</div>
|
||||
{onAction && (
|
||||
<Button
|
||||
onClick={onAction}
|
||||
@@ -123,7 +97,7 @@ export function ActionRequiredBanner({
|
||||
Review & Resubmit
|
||||
</Button>
|
||||
)}
|
||||
</Group>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -145,44 +119,24 @@ export function CancelledBanner({
|
||||
radius={16}
|
||||
p={20}
|
||||
bg="#FCEEEA"
|
||||
style={{ border: "1px solid #F3C6BB" }}
|
||||
className="border border-[#F3C6BB]"
|
||||
>
|
||||
<Stack gap={14}>
|
||||
<Group justify="space-between" align="center" wrap="wrap" gap={20}>
|
||||
<Group gap={16} align="center" wrap="nowrap" miw={0}>
|
||||
<Box
|
||||
style={{
|
||||
flexShrink: 0,
|
||||
width: 46,
|
||||
height: 46,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
borderRadius: 13,
|
||||
backgroundColor: "#fff",
|
||||
border: "1px solid #F3C6BB",
|
||||
color: "#D93C15",
|
||||
}}
|
||||
<div
|
||||
className="flex shrink-0 items-center justify-center rounded-[13px] border border-[#F3C6BB]"
|
||||
style={{ width: 46, height: 46, backgroundColor: "#fff", color: "#D93C15" }}
|
||||
>
|
||||
<XCircle size={24} />
|
||||
</Box>
|
||||
</div>
|
||||
<Box miw={0}>
|
||||
<Box
|
||||
component="span"
|
||||
style={{
|
||||
display: "inline-flex",
|
||||
borderRadius: 999,
|
||||
backgroundColor: "#D93C15",
|
||||
padding: "4px 10px",
|
||||
fontSize: 10.5,
|
||||
fontWeight: 800,
|
||||
letterSpacing: 0.3,
|
||||
color: "#fff",
|
||||
textTransform: "uppercase",
|
||||
}}
|
||||
<span
|
||||
className="inline-flex rounded-full px-[10px] py-1 text-[10.5px] font-extrabold uppercase tracking-[0.3px] text-white"
|
||||
style={{ backgroundColor: "#D93C15" }}
|
||||
>
|
||||
{pillLabel}
|
||||
</Box>
|
||||
</span>
|
||||
<Text mt={6} fz="15.5px" fw={700} c="#10202F">
|
||||
{title}
|
||||
</Text>
|
||||
@@ -206,33 +160,26 @@ export function CancelledBanner({
|
||||
)}
|
||||
</Group>
|
||||
{reason && (
|
||||
<Group
|
||||
gap={11}
|
||||
align="flex-start"
|
||||
wrap="nowrap"
|
||||
p={14}
|
||||
style={{
|
||||
borderRadius: 12,
|
||||
backgroundColor: "#fff",
|
||||
border: "1px solid #F3C6BB",
|
||||
}}
|
||||
<div
|
||||
className="flex items-start gap-[11px] rounded-xl border border-[#F3C6BB] p-[14px]"
|
||||
style={{ backgroundColor: "#fff" }}
|
||||
>
|
||||
<StickyNote size={20} color="#B0341A" style={{ flexShrink: 0 }} />
|
||||
<Box miw={0}>
|
||||
<StickyNote size={20} color="#B0341A" className="shrink-0" />
|
||||
<div className="min-w-0">
|
||||
<Text
|
||||
fz="10.5px"
|
||||
fw={700}
|
||||
c="#B0341A"
|
||||
tt="uppercase"
|
||||
style={{ letterSpacing: 0.5 }}
|
||||
className="tracking-[0.5px]"
|
||||
>
|
||||
Reason for cancellation
|
||||
</Text>
|
||||
<Text mt={3} fz="13.5px" c="#3D2A26" style={{ lineHeight: 1.45 }}>
|
||||
<Text mt={3} fz="13.5px" c="#3D2A26" className="leading-[1.45]">
|
||||
{reason}
|
||||
</Text>
|
||||
</Box>
|
||||
</Group>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -1,17 +1,36 @@
|
||||
import { Box, Button, Group, Stack, Text } from "@mantine/core";
|
||||
import { ArrowDownLeft, ArrowUpRight } from "lucide-react";
|
||||
import { ActionIcon, Button, Group, Menu, Stack, Text } from "@mantine/core";
|
||||
import {
|
||||
ArrowDownLeft,
|
||||
ArrowUpRight,
|
||||
Edit2,
|
||||
FileText,
|
||||
HelpCircle,
|
||||
MoreHorizontal,
|
||||
RefreshCw,
|
||||
XCircle,
|
||||
} from "lucide-react";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
import type { Freight } from "@edr/types";
|
||||
|
||||
import { bookingSubtitle, isDraftLike, isNegative } from "../utils";
|
||||
|
||||
export interface PageHeaderMenuActions {
|
||||
onViewContract?: () => void;
|
||||
onCancel?: () => void;
|
||||
onEdit?: () => void;
|
||||
onSupport?: () => void;
|
||||
onRebook?: () => void;
|
||||
}
|
||||
|
||||
export function PageHeader({
|
||||
booking,
|
||||
actions,
|
||||
menuActions,
|
||||
}: {
|
||||
booking: Freight.IBooking;
|
||||
actions: ReactNode;
|
||||
actions?: ReactNode;
|
||||
menuActions?: PageHeaderMenuActions;
|
||||
}) {
|
||||
const status = booking.status as string;
|
||||
const negative = isNegative(status);
|
||||
@@ -23,6 +42,8 @@ export function PageHeader({
|
||||
const pillText = negative ? "#A93226" : draft ? "#475569" : "#0A6F4D";
|
||||
const isExport = booking.tradeDirection === "EXPORT";
|
||||
|
||||
const hasMenu = menuActions && Object.values(menuActions).some(Boolean);
|
||||
|
||||
return (
|
||||
<Group justify="space-between" align="flex-start" wrap="wrap" gap="md">
|
||||
<Stack gap={8} miw={0}>
|
||||
@@ -30,58 +51,90 @@ export function PageHeader({
|
||||
<Text fz="26px" fw={800} c="#10202F">
|
||||
{booking.reference}
|
||||
</Text>
|
||||
<Group
|
||||
component="span"
|
||||
gap={7}
|
||||
align="center"
|
||||
wrap="nowrap"
|
||||
style={{
|
||||
display: "inline-flex",
|
||||
borderRadius: 999,
|
||||
padding: "6px 12px",
|
||||
fontSize: 12,
|
||||
fontWeight: 700,
|
||||
backgroundColor: pillBg,
|
||||
border: `1px solid ${pillBorder}`,
|
||||
color: pillText,
|
||||
}}
|
||||
|
||||
<span
|
||||
className="inline-flex items-center gap-[7px] rounded-full px-3 py-1.5 text-xs font-bold"
|
||||
style={{ backgroundColor: pillBg, border: `1px solid ${pillBorder}`, color: pillText }}
|
||||
>
|
||||
<Box
|
||||
component="span"
|
||||
style={{
|
||||
width: 7,
|
||||
height: 7,
|
||||
borderRadius: 999,
|
||||
backgroundColor: dotColor,
|
||||
}}
|
||||
<span
|
||||
className="shrink-0 rounded-full"
|
||||
style={{ width: 7, height: 7, backgroundColor: dotColor }}
|
||||
/>
|
||||
{status.replace(/_/g, " ").replace(/\b\w/g, (m) => m.toUpperCase())}
|
||||
</Group>
|
||||
<Group
|
||||
component="span"
|
||||
gap={6}
|
||||
align="center"
|
||||
wrap="nowrap"
|
||||
style={{
|
||||
display: "inline-flex",
|
||||
borderRadius: 999,
|
||||
backgroundColor: "#F1F4F7",
|
||||
padding: "6px 11px",
|
||||
fontSize: 12,
|
||||
fontWeight: 700,
|
||||
color: "#475569",
|
||||
}}
|
||||
>
|
||||
</span>
|
||||
|
||||
<span className="inline-flex items-center gap-[6px] rounded-full bg-[#F1F4F7] px-[11px] py-1.5 text-xs font-bold text-[#475569]">
|
||||
{isExport ? <ArrowUpRight size={14} /> : <ArrowDownLeft size={14} />}
|
||||
{isExport ? "Export" : "Import"}
|
||||
</Group>
|
||||
</span>
|
||||
</Group>
|
||||
<Text fz="14px" c="#6B7C8E">
|
||||
{bookingSubtitle(booking)}
|
||||
</Text>
|
||||
</Stack>
|
||||
<Group gap={12} wrap="wrap">
|
||||
|
||||
<Group gap={8} wrap="nowrap" align="center">
|
||||
{actions}
|
||||
{hasMenu && (
|
||||
<Menu shadow="md" radius={12} position="bottom-end">
|
||||
<Menu.Target>
|
||||
<ActionIcon
|
||||
variant="default"
|
||||
size={42}
|
||||
radius={10}
|
||||
aria-label="More options"
|
||||
>
|
||||
<MoreHorizontal size={18} />
|
||||
</ActionIcon>
|
||||
</Menu.Target>
|
||||
<Menu.Dropdown miw={210}>
|
||||
{menuActions!.onViewContract && (
|
||||
<Menu.Item
|
||||
leftSection={<FileText size={15} />}
|
||||
onClick={menuActions!.onViewContract}
|
||||
>
|
||||
View contract
|
||||
</Menu.Item>
|
||||
)}
|
||||
{menuActions!.onEdit && (
|
||||
<Menu.Item
|
||||
leftSection={<Edit2 size={15} />}
|
||||
onClick={menuActions!.onEdit}
|
||||
>
|
||||
Edit
|
||||
</Menu.Item>
|
||||
)}
|
||||
{menuActions!.onSupport && (
|
||||
<Menu.Item
|
||||
leftSection={<HelpCircle size={15} />}
|
||||
onClick={menuActions!.onSupport}
|
||||
>
|
||||
Contact customer support
|
||||
</Menu.Item>
|
||||
)}
|
||||
{menuActions!.onRebook && (
|
||||
<Menu.Item
|
||||
leftSection={<RefreshCw size={15} />}
|
||||
onClick={menuActions!.onRebook}
|
||||
>
|
||||
Rebook similar schedule
|
||||
</Menu.Item>
|
||||
)}
|
||||
{menuActions!.onCancel && (
|
||||
<>
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
color="red"
|
||||
leftSection={<XCircle size={15} />}
|
||||
onClick={menuActions!.onCancel}
|
||||
>
|
||||
Cancel booking
|
||||
</Menu.Item>
|
||||
</>
|
||||
)}
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
)}
|
||||
</Group>
|
||||
</Group>
|
||||
);
|
||||
|
||||
@@ -43,20 +43,12 @@ export function StatusHero({
|
||||
<SectionCard p={28}>
|
||||
<Group justify="space-between" align="center" wrap="wrap" gap="md">
|
||||
<Group gap={16} align="center" wrap="nowrap">
|
||||
<Box
|
||||
style={{
|
||||
width: 56,
|
||||
height: 56,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
borderRadius: 16,
|
||||
backgroundColor: tileBg,
|
||||
color: tileFg,
|
||||
}}
|
||||
<div
|
||||
className="flex items-center justify-center rounded-2xl shrink-0"
|
||||
style={{ width: 56, height: 56, backgroundColor: tileBg, color: tileFg }}
|
||||
>
|
||||
<HeroIcon size={26} />
|
||||
</Box>
|
||||
</div>
|
||||
<Box>
|
||||
<Text fz="21px" fw={800} c="#10202F">
|
||||
{cfg.title}
|
||||
@@ -72,11 +64,7 @@ export function StatusHero({
|
||||
wrap="nowrap"
|
||||
px="md"
|
||||
py="sm"
|
||||
style={{
|
||||
borderRadius: 14,
|
||||
border: "1px solid #E6ECF2",
|
||||
backgroundColor: "#F7FAFC",
|
||||
}}
|
||||
className="rounded-[14px] border border-[#E6ECF2] bg-[#F7FAFC]"
|
||||
>
|
||||
<History size={22} color="#64748B" />
|
||||
<Box>
|
||||
@@ -85,7 +73,7 @@ export function StatusHero({
|
||||
fw={700}
|
||||
c="#9AA8B5"
|
||||
tt="uppercase"
|
||||
style={{ letterSpacing: 0.6 }}
|
||||
className="tracking-[0.6px]"
|
||||
>
|
||||
{chipLabel}
|
||||
</Text>
|
||||
@@ -124,104 +112,97 @@ function ProgressTracker({
|
||||
const activeSub = tone === "ink" ? "#475569" : "#0A6F4D";
|
||||
|
||||
return (
|
||||
<Group align="flex-start" gap={0} wrap="nowrap" w="100%">
|
||||
{PROGRESS_STAGES.map((stage, idx) => {
|
||||
const state =
|
||||
idx < current ? "done" : idx === current ? "active" : "idle";
|
||||
const Icon = stage.icon;
|
||||
const reachedLeft = current >= idx && current >= 0;
|
||||
const reachedRight = current > idx && current >= 0;
|
||||
/* Scrollable on mobile so 5 stages never overflow */
|
||||
<Box
|
||||
className="overflow-x-auto"
|
||||
style={{ scrollbarWidth: "none", WebkitOverflowScrolling: "touch" } as React.CSSProperties}
|
||||
>
|
||||
<div className="flex items-start" style={{ minWidth: 440 }}>
|
||||
{PROGRESS_STAGES.map((stage, idx) => {
|
||||
const state =
|
||||
idx < current ? "done" : idx === current ? "active" : "idle";
|
||||
const Icon = stage.icon;
|
||||
const reachedLeft = current >= idx && current >= 0;
|
||||
const reachedRight = current > idx && current >= 0;
|
||||
|
||||
const circleStyle: React.CSSProperties =
|
||||
state === "idle"
|
||||
? { backgroundColor: "#EEF2F6", border: "1px solid #E1E7EE" }
|
||||
: {
|
||||
backgroundColor: state === "active" ? activeFill : "#0EA371",
|
||||
boxShadow:
|
||||
state === "active" ? `0 0 0 4px ${activeRing}` : undefined,
|
||||
};
|
||||
const circleBg =
|
||||
state === "idle"
|
||||
? "#EEF2F6"
|
||||
: state === "active"
|
||||
? activeFill
|
||||
: "#0EA371";
|
||||
const circleBorder = state === "idle" ? "1px solid #E1E7EE" : undefined;
|
||||
const circleShadow =
|
||||
state === "active" ? `0 0 0 4px ${activeRing}` : undefined;
|
||||
|
||||
return (
|
||||
<Box
|
||||
key={stage.label}
|
||||
flex={1}
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
gap: 10,
|
||||
}}
|
||||
>
|
||||
<Box style={{ display: "flex", alignItems: "center", width: "100%" }}>
|
||||
<Box
|
||||
flex={1}
|
||||
style={{
|
||||
height: 3,
|
||||
borderRadius: 999,
|
||||
background:
|
||||
idx === 0
|
||||
? "transparent"
|
||||
: reachedLeft
|
||||
? "#0EA371"
|
||||
: "#E1E7EE",
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
style={{
|
||||
width: 40,
|
||||
height: 40,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
borderRadius: 999,
|
||||
...circleStyle,
|
||||
}}
|
||||
return (
|
||||
<div
|
||||
key={stage.label}
|
||||
className="flex flex-1 flex-col items-center gap-[10px]"
|
||||
>
|
||||
<div className="flex w-full items-center">
|
||||
{/* left connector */}
|
||||
<div
|
||||
className="flex-1 rounded-full"
|
||||
style={{
|
||||
height: 3,
|
||||
background:
|
||||
idx === 0 ? "transparent" : reachedLeft ? "#0EA371" : "#E1E7EE",
|
||||
}}
|
||||
/>
|
||||
{/* stage circle */}
|
||||
<div
|
||||
className="flex items-center justify-center rounded-full shrink-0"
|
||||
style={{
|
||||
width: 40,
|
||||
height: 40,
|
||||
backgroundColor: circleBg,
|
||||
border: circleBorder,
|
||||
boxShadow: circleShadow,
|
||||
}}
|
||||
>
|
||||
{state === "done" ? (
|
||||
<Check size={16} color="#fff" />
|
||||
) : state === "active" ? (
|
||||
<Icon size={16} color="#fff" />
|
||||
) : null}
|
||||
</div>
|
||||
{/* right connector */}
|
||||
<div
|
||||
className="flex-1 rounded-full"
|
||||
style={{
|
||||
height: 3,
|
||||
background:
|
||||
idx === last ? "transparent" : reachedRight ? "#0EA371" : "#E1E7EE",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<Text
|
||||
fz="13.5px"
|
||||
fw={state === "active" ? 800 : 700}
|
||||
ta="center"
|
||||
c={state === "idle" ? "#9AA8B5" : "#10202F"}
|
||||
>
|
||||
{state === "done" ? (
|
||||
<Check size={16} color="#fff" />
|
||||
) : state === "active" ? (
|
||||
<Icon size={16} color="#fff" />
|
||||
) : null}
|
||||
</Box>
|
||||
<Box
|
||||
flex={1}
|
||||
style={{
|
||||
height: 3,
|
||||
borderRadius: 999,
|
||||
background:
|
||||
idx === last
|
||||
? "transparent"
|
||||
: reachedRight
|
||||
? "#0EA371"
|
||||
: "#E1E7EE",
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Text
|
||||
fz="13.5px"
|
||||
fw={state === "active" ? 800 : 700}
|
||||
ta="center"
|
||||
c={state === "idle" ? "#9AA8B5" : "#10202F"}
|
||||
>
|
||||
{stage.label}
|
||||
</Text>
|
||||
<Text
|
||||
fz="11.5px"
|
||||
fw={state === "active" ? 700 : 500}
|
||||
ta="center"
|
||||
c={state === "active" ? activeSub : "#9AA8B5"}
|
||||
>
|
||||
{state === "done"
|
||||
? "Completed"
|
||||
: state === "active"
|
||||
? negative
|
||||
? "Stopped"
|
||||
: "In progress"
|
||||
: "Pending"}
|
||||
</Text>
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Group>
|
||||
{stage.label}
|
||||
</Text>
|
||||
<Text
|
||||
fz="11.5px"
|
||||
fw={state === "active" ? 700 : 500}
|
||||
ta="center"
|
||||
c={state === "active" ? activeSub : "#9AA8B5"}
|
||||
>
|
||||
{state === "done"
|
||||
? "Completed"
|
||||
: state === "active"
|
||||
? negative
|
||||
? "Stopped"
|
||||
: "In progress"
|
||||
: "Pending"}
|
||||
</Text>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@ export function BodyGrid({ left, right }: { left: ReactNode; right: ReactNode })
|
||||
align={{ base: "stretch", lg: "flex-start" }}
|
||||
gap={24}
|
||||
>
|
||||
<Box flex={1} miw={0} display="flex" style={{ flexDirection: "column", gap: 24 }}>
|
||||
{/* Left column: capped at 700px on tablet so it doesn't bleed edge-to-edge */}
|
||||
<Box flex={1} miw={0} maw={700} className="flex flex-col gap-6 lg:max-w-none">
|
||||
{left}
|
||||
</Box>
|
||||
<Box
|
||||
w={360}
|
||||
maw="100%"
|
||||
display="flex"
|
||||
style={{ flexDirection: "column", gap: 24, flexShrink: 0 }}
|
||||
className="flex flex-col gap-6 shrink-0"
|
||||
>
|
||||
{right}
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user