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 | 2x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 16x 16x 16x 16x 3x 2x | import { ChevronLeft } from "lucide-react";
import { useMemo } from "react";
import { Navigate, useNavigate, useSearchParams } from "react-router";
import { StateCode, UserDetails } from "shared-types";
import { UserRole } from "shared-types/events/legacy-user";
import { isStateRole } from "shared-utils";
import { useGetUserDetails, useGetUserProfile, useStateAccessMap } from "@/api";
import {
LoadingSpinner,
OptionCard,
OptionFieldset,
SimplePageContainer,
SubNavHeader,
} from "@/components";
import { useFeatureFlag } from "@/hooks/useFeatureFlag";
import { convertStateAbbrToFullName } from "@/utils";
type RoleOptions = {
key: UserRole;
title: string;
description: string;
link: string;
};
export const StateRoleSignup = () => {
const isNewUserRoleDisplay = useFeatureFlag("SHOW_USER_ROLE_UPDATE");
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const statesParam = searchParams.get("states") as StateCode;
const statesRequested = useMemo(() => statesParam?.split(",") ?? [], [statesParam]);
const { data, isLoading: isUserDetailsLoading } = useGetUserDetails();
const userDetails = data as UserDetails | null;
const { data: userProfile } = useGetUserProfile();
const stateAccessMap = useStateAccessMap(userProfile?.stateAccess);
const encodedStatesQuery = encodeURIComponent(statesParam ?? "");
const roleOptions = [
{
key: "statesubmitter",
title: "State Submitter",
description: "Responsible for submitting packages",
link: `/signup/state/role/confirm?role=statesubmitter&states=${encodedStatesQuery}`,
},
{
key: "statesystemadmin",
title: "State System Administrator",
description: "Ability to approve state submitters and submit packages",
link: `/signup/state/role/confirm?role=statesystemadmin&states=${encodedStatesQuery}`,
},
] satisfies RoleOptions[];
// Filter out role(s) if it already exists for every selected state
const filteredRoleOptions = useMemo(() => {
return roleOptions.filter((roleOption) => {
const hasRoleInAllStates = statesRequested.every((state) => {
const rolesForState = stateAccessMap[state];
return rolesForState?.has(roleOption.key as UserRole);
});
return !hasRoleInAllStates;
});
}, [roleOptions, statesRequested, stateAccessMap]);
if (!isNewUserRoleDisplay) return <Navigate to="/signup" replace />;
if (!statesParam) return <Navigate to="/signup/state" />;
if (isUserDetailsLoading) return <LoadingSpinner />;
if (!userDetails) return <Navigate to="/" />;
if (userDetails.role && !isStateRole(userDetails.role)) {
return <Navigate to="/profile" />;
}
return (
<div>
<SubNavHeader>
<div className="flex items-center">
<ChevronLeft
className="text-sky-700 w-6 h-6 mr-2 cursor-pointer"
onClick={() => navigate("/signup/state")}
/>
<h1 className="text-xl font-medium">Select A Role</h1>
</div>
</SubNavHeader>
<SimplePageContainer>
<section className="max-w-3xl mx-auto">
<div className="py-10">
<h2 className="text-xl font-bold">
{statesRequested.length > 1 ? "States / Territories:" : "State / Territory:"}
</h2>
<p className="text-xl italic">
{statesRequested.map((state) => convertStateAbbrToFullName(state)).join(", ")}
</p>
</div>
<div className="pb-10">
<h2 className="text-xl font-bold">Available roles to add</h2>
<OptionFieldset>
{filteredRoleOptions.map((role) => (
<OptionCard
description={role.description}
title={role.title}
to={role.link}
key={role.key}
/>
))}
</OptionFieldset>
</div>
</section>
</SimplePageContainer>
</div>
);
};
|