60 lines
1.8 KiB
TypeScript
60 lines
1.8 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
|
|
const tips = [
|
|
{
|
|
title: "Responses update while you work",
|
|
description:
|
|
"Open form results can refresh automatically when a new response arrives.",
|
|
},
|
|
{
|
|
title: "Closed forms keep their history",
|
|
description:
|
|
"Closing a form stops new responses without removing its existing results.",
|
|
},
|
|
{
|
|
title: "Platform counts can be refreshed",
|
|
description:
|
|
"Use Backend when a YouTube, TikTok, Discord, or Roblox count looks stale.",
|
|
},
|
|
{
|
|
title: "Preview before sharing",
|
|
description:
|
|
"Every form editor includes a preview of what respondents will see.",
|
|
},
|
|
] as const;
|
|
|
|
export function AdminWelcome() {
|
|
const [tipIndex, setTipIndex] = useState<number | null>(null);
|
|
|
|
useEffect(() => {
|
|
const frame = requestAnimationFrame(() => {
|
|
setTipIndex(Math.floor(Math.random() * tips.length));
|
|
});
|
|
return () => cancelAnimationFrame(frame);
|
|
}, []);
|
|
|
|
const tip = tipIndex === null ? null : tips[tipIndex];
|
|
|
|
return (
|
|
<main className="flex min-h-[calc(100svh-3rem)] w-full items-center justify-center p-6 md:min-h-svh">
|
|
<div className="flex max-w-2xl flex-col items-center gap-1 text-center">
|
|
<h1 className="text-4xl font-bold tracking-tight">Welcome back!</h1>
|
|
{tip ? (
|
|
<div className="flex flex-col items-center gap-0.5">
|
|
<p className="text-sm font-medium">{tip.title}</p>
|
|
<p className="text-xs text-muted-foreground">{tip.description}</p>
|
|
</div>
|
|
) : (
|
|
<div className="flex w-full max-w-md flex-col items-center gap-1.5 pt-1">
|
|
<Skeleton className="h-4 w-40" />
|
|
<Skeleton className="h-3 w-full" />
|
|
</div>
|
|
)}
|
|
</div>
|
|
</main>
|
|
);
|
|
}
|