diff --git a/web/src/pages/Requests.tsx b/web/src/pages/Requests.tsx index 42095945..d7d1d050 100644 --- a/web/src/pages/Requests.tsx +++ b/web/src/pages/Requests.tsx @@ -14,7 +14,13 @@ import { } from "@/components/ui/select"; import { Skeleton } from "@/components/ui/skeleton"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import type { MediaRequest, RequestDiscoverySection, RequestMediaResult } from "@/api/types"; +import type { + MediaRequest, + MediaRequestOutcome, + MediaRequestStatus, + RequestDiscoverySection, + RequestMediaResult, +} from "@/api/types"; import { useCreateMediaRequest, useMyMediaRequests, @@ -23,9 +29,13 @@ import { } from "@/hooks/queries/requests"; import { useDocumentTitle } from "@/hooks/useDocumentTitle"; import { cn } from "@/lib/utils"; -import { requestInputFromMediaResult } from "@/lib/mediaRequests"; +import { formatRequestStatus, requestInputFromMediaResult } from "@/lib/mediaRequests"; type MineBucketKey = "motion" | "completed" | "issues"; +type StatusGuideItem = { + description: string; + tone: string; +}; const MINE_BUCKET_META: Record = { @@ -46,6 +56,61 @@ const MINE_BUCKET_META: Record = [ + { + status: "pending", + description: "Waiting for an admin to approve the request.", + tone: "bg-amber-500/15 text-amber-100 ring-amber-400/40", + }, + { + status: "approved", + description: "Approved, but not yet sent to the download automation.", + tone: "bg-emerald-500/15 text-emerald-100 ring-emerald-400/40", + }, + { + status: "queued", + description: "Sent to the request automation and waiting for download/import activity.", + tone: "bg-sky-500/15 text-sky-100 ring-sky-400/40", + }, + { + status: "downloading", + description: "Downloading or importing now.", + tone: "bg-sky-500/20 text-sky-100 ring-sky-400/50", + }, + { + status: "completed", + description: "In your Silo library and ready to watch.", + tone: "bg-emerald-500/20 text-emerald-100 ring-emerald-400/40", + }, +]; + +const REQUEST_ISSUE_GUIDE: Array< + StatusGuideItem & { + outcome: Extract; + label: string; + } +> = [ + { + outcome: "declined", + label: "Declined", + description: "An admin declined the request.", + tone: "bg-zinc-700/60 text-zinc-200 ring-zinc-500/40", + }, + { + outcome: "cancelled", + label: "Cancelled", + description: "The request was cancelled before completion.", + tone: "bg-zinc-700/60 text-zinc-200 ring-zinc-500/40", + }, + { + outcome: "failed", + label: "Failed", + description: + "Silo or the external request automation hit an error. If details are available, they appear on the request card.", + tone: "bg-red-500/15 text-red-100 ring-red-400/40", + }, +]; + export default function Requests() { useDocumentTitle("Requests"); @@ -164,6 +229,7 @@ export default function Requests() { ) : ( <> +
{(Object.keys(MINE_BUCKET_META) as MineBucketKey[]).map((key) => { const items = buckets[key]; @@ -179,6 +245,83 @@ export default function Requests() { ); } +function RequestStatusGuide() { + return ( +
+
+
+
+

+ Status guide +

+

+ Statuses update automatically as Silo checks the library and connected request + integrations. +

+
+
+ + {REQUEST_PROGRESS_GUIDE.map((item) => ( + + ))} + + + {REQUEST_ISSUE_GUIDE.map((item) => ( + + ))} + +
+
+
+
+ ); +} + +function StatusGuideGroup({ title, children }: { title: string; children: React.ReactNode }) { + return ( +
+

{title}

+
{children}
+
+ ); +} + +function StatusGuideRow({ + label, + description, + tone, +}: { + label: string; + description: string; + tone: string; +}) { + return ( +
+
+ + {label} + +
+
{description}
+
+ ); +} + function PageHeader() { return (