181 lines
5.4 KiB
TypeScript
181 lines
5.4 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import { CircleCheck } from "lucide-react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { Sheet, Typography, Chip, Button } from "@mui/joy";
|
|
|
|
export const SuccessPage = () => {
|
|
const { t } = useTranslation();
|
|
const [orderId, setOrderId] = useState<string | null>(null);
|
|
const [tickets, setTickets] = useState<number>(0);
|
|
const [animate, setAnimate] = useState(false);
|
|
const [seconds, setSeconds] = useState(30);
|
|
|
|
useEffect(() => {
|
|
const params = new URLSearchParams(window.location.search);
|
|
setOrderId(params.get("id"));
|
|
setTickets(parseInt(params.get("tickets") ?? "0", 10));
|
|
// Small delay so the CSS transition actually plays
|
|
setTimeout(() => setAnimate(true), 100);
|
|
|
|
document.body.classList.add("success-bg");
|
|
return () => {
|
|
document.body.classList.remove("success-bg");
|
|
};
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (seconds === 0) {
|
|
window.location.href = "/";
|
|
return;
|
|
}
|
|
const timer = setTimeout(() => setSeconds((s) => s - 1), 1000);
|
|
return () => clearTimeout(timer);
|
|
}, [seconds]);
|
|
|
|
// Returns a style object that slides the element up + fades it in.
|
|
// Each section gets a slightly later delay for a staggered entrance.
|
|
const fadeUp = (delay: string): React.CSSProperties => ({
|
|
transition: `opacity 0.5s ease-in-out ${delay}, transform 0.5s ease-in-out ${delay}`,
|
|
transform: animate ? "translateY(0)" : "translateY(20px)",
|
|
opacity: animate ? 1 : 0,
|
|
});
|
|
|
|
return (
|
|
<div className="flex-1 w-full flex items-center justify-center p-4">
|
|
<Sheet
|
|
variant="plain"
|
|
sx={{
|
|
position: "relative",
|
|
width: "100%",
|
|
maxWidth: 440,
|
|
borderRadius: "24px",
|
|
p: { xs: "2rem", sm: "2.5rem" },
|
|
boxShadow: "0 24px 64px -12px rgba(0,0,0,0.4)",
|
|
background: "#fff",
|
|
textAlign: "center",
|
|
overflow: "hidden",
|
|
}}
|
|
>
|
|
{/* Green accent bar at the top */}
|
|
<div
|
|
style={{
|
|
position: "absolute",
|
|
top: 0,
|
|
left: 0,
|
|
right: 0,
|
|
height: "4px",
|
|
background: "linear-gradient(90deg, #22c55e, #86efac)",
|
|
transition: "transform 0.8s ease-in-out 0.6s",
|
|
transform: animate ? "scaleX(1)" : "scaleX(0)",
|
|
transformOrigin: "left",
|
|
}}
|
|
/>
|
|
|
|
{/* Animated success icon */}
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
justifyContent: "center",
|
|
marginBottom: "1.5rem",
|
|
transition: "all 0.6s cubic-bezier(0.34, 1.56, 0.64, 1)",
|
|
transform: animate ? "scale(1)" : "scale(0)",
|
|
opacity: animate ? 1 : 0,
|
|
}}
|
|
>
|
|
<CircleCheck size={80} color="#22c55e" strokeWidth={2.5} />
|
|
</div>
|
|
|
|
{/* Headline */}
|
|
<div style={fadeUp("0.2s")}>
|
|
<Typography
|
|
level="h3"
|
|
sx={{ fontWeight: 700, color: "#15803d", mb: 1 }}
|
|
>
|
|
{t("form-submitted-successfully")}
|
|
</Typography>
|
|
</div>
|
|
|
|
{/* Subtitle */}
|
|
<div style={fadeUp("0.3s")}>
|
|
<Typography level="body-md" sx={{ color: "#6b7280", mb: 3 }}>
|
|
{t("ticket-payment", { count: tickets })}
|
|
</Typography>
|
|
</div>
|
|
|
|
{/* Tickets chip */}
|
|
{tickets > 0 && (
|
|
<div style={fadeUp("0.35s")} className="flex justify-center mb-3">
|
|
<Chip
|
|
size="lg"
|
|
variant="soft"
|
|
color="success"
|
|
sx={{ fontWeight: 700, fontSize: "1rem", px: 2, py: 1 }}
|
|
>
|
|
{tickets} {tickets === 1 ? t("ticket") : t("tickets")}
|
|
</Chip>
|
|
</div>
|
|
)}
|
|
|
|
{/* Order ID chip */}
|
|
{orderId && (
|
|
<div
|
|
style={fadeUp("0.4s")}
|
|
className="flex flex-col items-center gap-1 mb-4"
|
|
>
|
|
<Typography
|
|
level="body-xs"
|
|
sx={{
|
|
color: "#9ca3af",
|
|
textTransform: "uppercase",
|
|
letterSpacing: "0.08em",
|
|
}}
|
|
>
|
|
{t("entry-id")}
|
|
</Typography>
|
|
<Chip
|
|
size="lg"
|
|
variant="solid"
|
|
color="primary"
|
|
sx={{ fontWeight: 700, fontSize: "1.25rem", px: 3, py: 1.5 }}
|
|
>
|
|
#{orderId}
|
|
</Chip>
|
|
</div>
|
|
)}
|
|
|
|
{/* Return button with countdown */}
|
|
<div style={fadeUp("0.45s")} className="mb-4">
|
|
<Button
|
|
component="a"
|
|
href="/"
|
|
size="lg"
|
|
color="primary"
|
|
variant="solid"
|
|
fullWidth
|
|
sx={{
|
|
borderRadius: "12px",
|
|
fontWeight: 700,
|
|
background: "linear-gradient(135deg, #2563eb, #1d4ed8)",
|
|
"&:hover": {
|
|
background: "linear-gradient(135deg, #1d4ed8, #1e40af)",
|
|
},
|
|
}}
|
|
>
|
|
{seconds}s — {t("return-to-homepage")}
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Thank-you note */}
|
|
<div style={fadeUp("0.5s")} className="pt-4 border-t border-slate-100">
|
|
<Typography
|
|
level="body-sm"
|
|
sx={{ color: "#9ca3af", lineHeight: 1.6 }}
|
|
>
|
|
{t("thank-you")}
|
|
</Typography>
|
|
</div>
|
|
</Sheet>
|
|
</div>
|
|
);
|
|
};
|