ui improvemnt

This commit is contained in:
Marshal
2026-06-06 21:17:20 +00:00
parent b62ea3f95f
commit 08b46c306f
35 changed files with 2731 additions and 1604 deletions

View File

@@ -1,20 +1,28 @@
import {
Check,
CheckCircle2,
FileSignature,
FileText,
Train,
Wallet,
type LucideIcon,
} from "lucide-react";
import { Paper, Group, Stack, Text, Box } from "@mantine/core";
import { cn } from "@/lib/utils";
import {
getWorkflowStageIndex,
WORKFLOW_STAGES,
} from "@/features/bookings/booking-status.config";
import { bookingGlass, bookingSurface } from "./booking-ui.styles";
import { SectionCard } from "./detail/SectionCard";
import { BRAND_GREEN } from "./detail/booking-detail.styles";
const STAGE_ICONS = [FileText, FileSignature, FileSignature, Wallet, Train, Check];
const STAGE_ICONS: LucideIcon[] = [
FileText,
FileSignature,
FileSignature,
Wallet,
Train,
Check,
];
interface BookingWorkflowStepperProps {
status: string;
@@ -27,104 +35,99 @@ export function BookingWorkflowStepper({
status,
title,
description,
titleColor,
}: BookingWorkflowStepperProps) {
const currentStage = getWorkflowStageIndex(status);
const isTerminal = currentStage < 0;
return (
<div className={bookingSurface.sectionCard}>
<div className={bookingSurface.sectionHeader}>
<div className={bookingSurface.sectionIcon}>
<Train className="size-4" strokeWidth={1.75} />
</div>
<div>
<h2 className="text-sm font-semibold text-foreground">
Workflow progress
</h2>
<p className="text-xs text-muted-foreground">
Customer submission through completion
</p>
</div>
</div>
<div className="space-y-8 px-5 py-6">
<div className="relative px-2">
<div className="absolute left-4 right-4 top-5 h-px bg-border/60" />
<div
className="absolute left-4 top-5 h-px bg-emerald-500/40 transition-all duration-700 ease-out"
style={{
width:
!isTerminal && currentStage >= 0
? `calc(${(currentStage / (WORKFLOW_STAGES.length - 1)) * 100}% - 2rem)`
: "0%",
}}
/>
<div className="relative flex justify-between">
{WORKFLOW_STAGES.map((stage, idx) => {
const Icon = STAGE_ICONS[idx] ?? FileText;
const isCompleted = !isTerminal && idx < currentStage;
const isActive = !isTerminal && idx === currentStage;
return (
<div
key={stage.label}
className="flex max-w-[4.5rem] flex-col items-center gap-2.5 sm:max-w-none"
>
<div
className={cn(
"flex size-10 items-center justify-center rounded-full border-2 bg-card/80 backdrop-blur-sm transition-all duration-300",
isCompleted &&
cn(bookingGlass.iconWellGreen, "border-emerald-500/30 text-black"),
isActive &&
cn(
bookingGlass.activeTab,
"scale-105 border-emerald-500/30 text-black shadow-sm",
),
!isCompleted &&
!isActive &&
"border-border/60 text-muted-foreground",
)}
<SectionCard icon={Train} title="Workflow progress">
<Group gap={0} wrap="nowrap" align="flex-start" mb="lg">
{WORKFLOW_STAGES.map((stage, index) => {
const Icon = STAGE_ICONS[index] ?? FileText;
const isComplete = !isTerminal && index < currentStage;
const isActive = !isTerminal && index === currentStage;
const isLast = index === WORKFLOW_STAGES.length - 1;
return (
<Box key={stage.label} style={{ flex: isLast ? "0 0 auto" : 1, minWidth: 0 }}>
<Group gap={0} wrap="nowrap" align="center">
<Stack gap={6} align="center" style={{ flexShrink: 0 }}>
<Box
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
width: 34,
height: 34,
borderRadius: "50%",
background: isComplete
? BRAND_GREEN
: isActive
? "white"
: "var(--mantine-color-gray-1)",
border: isActive
? `2px solid ${BRAND_GREEN}`
: isComplete
? "2px solid transparent"
: "2px solid var(--mantine-color-gray-2)",
color: isComplete
? "white"
: isActive
? "var(--mantine-color-green-7)"
: "var(--mantine-color-gray-5)",
transition: "all 0.2s ease",
}}
>
{isCompleted ? (
<CheckCircle2 className="size-4" />
) : (
<Icon className="size-4" />
)}
</div>
<span
className={cn(
"text-center text-[10px] font-semibold uppercase leading-tight tracking-wide",
isActive ? "text-black" : "text-muted-foreground",
)}
{isComplete ? <Check size={16} strokeWidth={3} /> : <Icon size={15} />}
</Box>
<Text
size="xs"
fw={isActive ? 600 : 500}
c={isActive ? "green.7" : isComplete ? "dark" : "dimmed"}
ta="center"
style={{ whiteSpace: "nowrap" }}
>
{stage.label}
</span>
</div>
);
})}
</div>
</div>
</Text>
</Stack>
{!isLast && (
<Box
style={{
flex: 1,
height: 2,
marginInline: 8,
marginBottom: 20,
borderRadius: 2,
background: isComplete ? BRAND_GREEN : "var(--mantine-color-gray-2)",
}}
/>
)}
</Group>
</Box>
);
})}
</Group>
<div
className={cn(
"rounded-xl border px-5 py-4 backdrop-blur-sm",
isTerminal
? "border-destructive/20 bg-destructive/5"
: bookingGlass.activeTab,
)}
>
<h4
className={cn(
"text-sm font-semibold tracking-tight",
isTerminal ? titleColor : "text-black",
)}
>
{title}
</h4>
<p className="mt-1.5 text-sm leading-relaxed text-muted-foreground">
{description}
</p>
</div>
</div>
</div>
<Paper
radius="md"
withBorder
p="md"
style={{
background: isTerminal
? "var(--mantine-color-red-0)"
: "var(--mantine-color-green-0)",
borderColor: isTerminal
? "var(--mantine-color-red-2)"
: "var(--mantine-color-green-2)",
}}
>
<Text size="sm" fw={600} c={isTerminal ? "red.7" : "green.8"}>
{title}
</Text>
<Text size="sm" c="dimmed" mt={4}>
{description}
</Text>
</Paper>
</SectionCard>
);
}