Files
web-menu-react-version-/src/pages/order/components/Stepper.tsx

199 lines
5.8 KiB
TypeScript

import { Col, Row } from "antd";
import ProText from "components/ProText";
import { Status } from "pages/checkout/hooks/types";
import type { CSSProperties } from "react";
import { Fragment, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { colors } from "ThemeConstants";
interface StepperProps {
statuses?: Status[];
}
export default function Stepper({ statuses = [] }: StepperProps) {
const { t } = useTranslation();
// Check if order has canceled_by_customer status
const hasCanceledStatus = useMemo(
() => statuses.some((status) => status?.alias === "canceled_by_customer"),
[statuses],
);
// Get the canceled status if it exists
const canceledStatus = useMemo(
() => statuses.find((status) => status?.alias === "canceled_by_customer"),
[statuses],
);
const labels = useMemo(
() => [t("order.reserved"), t("order.prepare"), t("order.ready")],
[t],
);
// Determine number of steps: 2 if canceled, 3 otherwise
const stepCount = hasCanceledStatus ? 2 : 3;
const activeIndex = useMemo(() => {
if (hasCanceledStatus) {
// For canceled orders, the last step (index 1) is always active
return 1;
}
const reachedStatuses = statuses.length > 0 ? statuses.length - 1 : 0;
return Math.min(Math.max(reachedStatuses, 0), 2);
}, [statuses.length, hasCanceledStatus]);
const steps = useMemo(
() =>
Array.from({ length: stepCount }, (_, index) => {
let status;
let label;
let isCanceled = false;
if (hasCanceledStatus) {
if (index === 0) {
// First step: show first status or default label
status = statuses[0];
label = status?.name || status?.alias || labels[0] || "";
} else if (index === 1) {
// Second step: show canceled status
status = canceledStatus;
label = status?.name || status?.alias || t("order.canceled") || "";
isCanceled = true;
}
} else {
// Normal flow: 3 steps
status = statuses[index];
label = status?.name || status?.alias || labels[index] || "";
}
const isPending = index > activeIndex;
return {
key: status ? `status-${status.id}` : `placeholder-${index}`,
label,
isPending,
isCanceled,
};
}),
[activeIndex, labels, statuses, stepCount, hasCanceledStatus, canceledStatus, t],
);
return (
<>
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<Row
align={"middle"}
style={{
width: 330,
maxWidth: "100%",
position: "relative",
padding: "12px",
}}
>
{steps.map((step, index) => {
// Determine circle style based on state
const circleStyle: CSSProperties = step.isCanceled
? {
width: 12,
height: 12,
borderRadius: "50%",
backgroundColor: "#EF4444", // Red for canceled
border: "2px solid #EF4444",
}
: step.isPending
? {
width: 12,
height: 12,
borderRadius: "50%",
backgroundColor: "#FFF",
border: "2px solid #BDBDBD",
}
: {
width: 12,
height: 12,
borderRadius: "50%",
backgroundColor: colors.primary,
};
// Determine line style based on state
// Line should be red if the next step is canceled
const nextStep = index < steps.length - 1 ? steps[index + 1] : null;
const lineStyle: CSSProperties =
nextStep?.isCanceled
? {
height: 1.5,
backgroundColor: "#EF4444", // Red for canceled
margin: "0 8px",
}
: {
height: 1.5,
backgroundColor: step.isPending ? "#BDBDBD" : colors.primary,
margin: "0 8px",
};
return (
<Fragment key={step.key}>
<Col>
<div style={circleStyle}></div>
</Col>
{index < steps.length - 1 && (
<Col flex={"auto"}>
<div style={lineStyle}></div>
</Col>
)}
</Fragment>
);
})}
</Row>
</div>
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<Row
align={"middle"}
style={{
width: 330,
maxWidth: "100%",
position: "relative",
padding: "12px",
}}
>
{steps.map((step, index) => (
<Fragment key={`label-${step.key}`}>
<Col>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 14,
lineHeight: "140%",
letterSpacing: "0%",
textAlign: "center",
color: step.isCanceled
? "#EF4444" // Red for canceled
: step.isPending
? "#99A2AE"
: "#333333",
}}
>
{step.label}
</ProText>
</Col>
{index < steps.length - 1 && <Col flex={"auto"}></Col>}
</Fragment>
))}
</Row>
</div>
</>
);
}