All files / react-app/src/features/package index.tsx

41.66% Statements 10/24
0% Branches 0/10
50% Functions 3/6
41.66% Lines 10/24

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);
};