Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | 72x 4x 72x 3x 72x 72x 72x 72x 8x 8x | import { CardWithTopBorder, ErrorAlert, LoadingSpinner } from "@/components"; import { useGetItem, useGetItemCache, getItem } from "@/api"; import { BreadCrumbs } from "@/components/BreadCrumb"; import { FC, PropsWithChildren } from "react"; import { PackageActivities } from "./package-activity"; import { AdminChanges } from "./admin-changes"; import { PackageDetails } from "./package-details"; import { PackageStatusCard } from "./package-status"; import { PackageActionsCard } from "./package-actions"; import { useDetailsSidebarLinks } from "./hooks"; import { Authority } from "shared-types"; import { LoaderFunctionArgs, useParams, useLoaderData, redirect } from "react-router"; import { detailsAndActionsCrumbs } from "@/utils"; export const DetailCardWrapper = ({ title, children, }: PropsWithChildren<{ title: string; }>) => ( <CardWithTopBorder> <div className="p-4 py-1 w-80 min-h-36"> <h2>{title}</h2> {children} </div> </CardWithTopBorder> ); export const DetailsContent: FC<{ id: string }> = ({ id }) => { const { data, isLoading, error } = useGetItem(id); if (isLoading) return <LoadingSpinner />; if (!data?._source) return <LoadingSpinner />; if (error) return <ErrorAlert error={error} />; return ( <div className="w-full py-1 px-4 lg:px-8"> <section id="package_overview" className="block md:flex space-x-0 md:space-x-8"> <PackageStatusCard data={data} /> <PackageActionsCard id={id} /> </section> <div className="flex flex-col gap-3"> <PackageDetails itemResult={data} /> <PackageActivities /> <AdminChanges /> </div> </div> ); }; type LoaderData = { id: string; authority: Authority; }; export const packageDetailsLoader = async ({ params, }: LoaderFunctionArgs): Promise<LoaderData | Response> => { const { id, authority } = params; if (id === undefined || authority === undefined) { return redirect("/dashboard"); } try { const packageResult = await getItem(id); if (!packageResult || packageResult?._source?.deleted === true) { return redirect("/dashboard"); } } catch (error) { if (error instanceof Error) { console.log("Error fetching package: ", error.message); } else { console.log("Unknown error fetching package: ", error); } return redirect("/dashboard"); } return { id, authority: authority as Authority }; }; export const Details = () => { const { id, authority } = useLoaderData<LoaderData>(); return ( <div className="max-w-screen-xl mx-auto flex flex-col lg:flex-row"> <div className="px-4 lg:px-8"> <BreadCrumbs options={detailsAndActionsCrumbs({ id, authority })} /> <div className="hidden lg:block pr-8"> <DetailsSidebar id={id} /> </div> </div> <DetailsContent id={id} /> </div> ); }; const DetailsSidebar: FC<{ id: string }> = ({ id }) => { const links = useDetailsSidebarLinks(id); return ( <aside className="min-w-56 flex-none font-semibold mt-6"> {links.map(({ id, href, displayName }) => ( <a className="block mb-2 text-blue-900" key={id} href={href}> {displayName} </a> ))} </aside> ); }; export const usePackageDetailsCache = () => { const { id } = useParams<{ id: string }>(); return useGetItemCache(id); }; |