Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] Fix View Permit Holder API Hookup integration bugs #56

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion components/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'react-day-picker/lib/style.css'; // React Day Picker default styling
type Props = {
readonly value: Date; // Date value
readonly onDateChange: (day: Date) => void; // Callback on date change
} & Pick<ChakraProps, 'width'>;
} & Partial<Pick<ChakraProps, 'width'>>;

/**
* Custom date picker component wrapping React Day Picker
Expand All @@ -20,6 +20,7 @@ export default function DatePicker(props: Props) {
return (
<>
<ReactDayPickerInput
style={width !== undefined ? { width } : undefined}
component={(props: any) => <Input width={width} {...props} />}
formatDate={date => date.toLocaleDateString('en-CA')}
value={value}
Expand Down
15 changes: 13 additions & 2 deletions components/internal/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ function Meta() {
/>
<meta charSet="utf-8" />
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
<link rel="icon" href="/assets/favicon.ico" />
</Head>
);
}
Expand Down Expand Up @@ -101,8 +102,18 @@ function Header() {
<TabList height="100%" borderBottomColor="transparent">
{authorize(session, [Role.Secretary]) && (
<>
<Tab path={InternalPagePath.Requests}>Requests</Tab>
<Tab path={InternalPagePath.PermitHolders}>Permit Holders</Tab>
<Tab
path={InternalPagePath.Requests}
additionalMatches={[InternalPagePath.Request]}
>
Requests
</Tab>
<Tab
path={InternalPagePath.PermitHolders}
additionalMatches={[InternalPagePath.PermitHolder]}
>
Permit Holders
</Tab>
</>
)}
{authorize(session, [Role.Accounting]) && (
Expand Down
12 changes: 8 additions & 4 deletions components/internal/navbar/Tab.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
import Link from 'next/link'; // Link component
import { useRouter } from 'next/router'; // Routing
import { Tab as ChakraTab } from '@chakra-ui/react'; // Chakra UI
import { InternalPagePath } from '@tools/components/internal/layout'; // Internal page paths
import { InternalPagePath } from '@tools/components/internal/layout'; // Internal page path

type Props = {
path: InternalPagePath;
additionalMatches?: ReadonlyArray<InternalPagePath>;
children: string;
};

/**
* Custom Tab component that handles client-side linking and conditional
* button text rendering based on current route
* @param props - Props
* @param path - Path that the tab links to
* @param additionalMatches - Paths in addition to `path` that trigger the selected state of the tab
* @param children - Name of the tab
* @returns custom tab
*/
export default function Tab(props: Props) {
const router = useRouter();
const { pathname } = router;
const { path, children } = props;
const { path, additionalMatches, children } = props;

// Tab is selected if its path is the current route
const isSelected = path === pathname;
const isSelected =
path === pathname || additionalMatches?.some(match => pathname.includes(match));

return (
<Link href={path}>
Expand Down
2 changes: 1 addition & 1 deletion components/permit-holders/PersonalInformationCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default function PersonalInformationCard(props: PersonalInformationProps)
</Text>
}
editModal={
<EditUserInformationModal applicantId={applicant.id} onSave={onSave}>
<EditUserInformationModal applicant={applicant} onSave={onSave}>
<Button color="primary" variant="ghost" textDecoration="underline">
<Text textStyle="body-bold">Edit</Text>
</Button>
Expand Down
20 changes: 0 additions & 20 deletions components/permit-holders/SuccessfulEditAlert.tsx

This file was deleted.

22 changes: 18 additions & 4 deletions components/permit-holders/modals/EditUserInformationModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,18 @@ import {
Select,
Divider,
} from '@chakra-ui/react'; // Chakra UI
import { useState, ReactNode, SyntheticEvent } from 'react'; // React
import { useState, useEffect, ReactNode, SyntheticEvent } from 'react'; // React
import { Gender, UpdateApplicantInput } from '@lib/graphql/types'; // Gender Enum
import { ApplicantData } from '@tools/pages/admin/permit-holders/types'; // Applicant data type

type EditUserInformationModalProps = {
applicantId: number;
applicant: ApplicantData;
children: ReactNode;
readonly onSave: (applicationData: UpdateApplicantInput) => void;
};

export default function EditUserInformationModal({
applicantId,
applicant,
children,
onSave,
}: EditUserInformationModalProps) {
Expand All @@ -53,14 +54,27 @@ export default function EditUserInformationModal({

const [loading, setLoading] = useState(false);

useEffect(() => {
setFirstName(applicant.firstName);
setLastName(applicant.lastName);
setDateOfBirth(new Date(applicant.dateOfBirth).toISOString().substring(0, 10));
setGender(applicant.gender);
setEmail(applicant.email || '');
setPhoneNumber(applicant.phone);
setAddressLine1(applicant.addressLine1);
setAddressLine2(applicant.addressLine2 || '');
setCity(applicant.city);
setPostalCode(applicant.postalCode);
}, [applicant]);

/**
* Handle edit submission
*/
const handleSubmit = async (event: SyntheticEvent) => {
setLoading(true);
event.preventDefault();
await onSave({
id: applicantId,
id: applicant.id,
firstName,
lastName,
dateOfBirth,
Expand Down
2 changes: 1 addition & 1 deletion lib/physicians/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default `
province: Province
postalCode: String!
phone: String!
status: PhysicianStatus!
status: PhysicianStatus
notes: String
}

Expand Down
21 changes: 8 additions & 13 deletions pages/admin/permit-holder/[permitHolderId].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { GET_PERMIT_HOLDER } from '@tools/pages/permit-holders/queries'; // Perm
import { useMutation, useQuery } from '@apollo/client'; // Apollo
import { useState } from 'react'; // React
import {
ApplicantData,
PermitData,
MedicalHistoryEntry,
PreviousPhysicianData,
Expand All @@ -26,7 +25,6 @@ import {
UpsertPhysicianResponse,
UPSERT_PHYSICIAN_MUTATION,
} from '@tools/pages/admin/permit-holders/upsert-physician'; // Upsert Physician types
import SuccessfulEditAlert from '@components/permit-holders/SuccessfulEditAlert'; // Successful Edit Alert component
import {
UpdateApplicantRequest,
UpdateApplicantResponse,
Expand All @@ -39,7 +37,6 @@ type Props = {

// Individual permit holder page
export default function PermitHolder({ permitHolderId }: Props) {
const [applicantData, setApplicantData] = useState<ApplicantData>();
const [permits, setPermits] = useState<PermitData[]>();
const [medicalHistoryData, setMedicalHistoryData] = useState<MedicalHistoryEntry[]>();
// TODO: uncomment when AWS is setup and we use real files
Expand All @@ -51,7 +48,6 @@ export default function PermitHolder({ permitHolderId }: Props) {
id: permitHolderId,
},
onCompleted: data => {
setApplicantData(data.applicant);
setPermits(
data.applicant.permits.map(permit => ({
rcdPermitId: permit.rcdPermitId,
Expand Down Expand Up @@ -100,9 +96,8 @@ export default function PermitHolder({ permitHolderId }: Props) {
onCompleted: data => {
if (data.upsertPhysician.ok) {
toast({
render: () => (
<SuccessfulEditAlert>{'Doctor’s information has been edited.'}</SuccessfulEditAlert>
),
status: 'success',
description: "Doctor's information has been edited.",
});
}
},
Expand All @@ -123,9 +118,8 @@ export default function PermitHolder({ permitHolderId }: Props) {
onCompleted: data => {
if (data.updateApplicant.ok) {
toast({
render: () => (
<SuccessfulEditAlert>{"User's information has been edited."}</SuccessfulEditAlert>
),
status: 'success',
description: "User's information has been edited.",
});
}
},
Expand All @@ -135,6 +129,7 @@ export default function PermitHolder({ permitHolderId }: Props) {
description: error.message,
});
},
refetchQueries: ['GetPermitHolder'],
});

/**
Expand All @@ -156,13 +151,13 @@ export default function PermitHolder({ permitHolderId }: Props) {
return (
<Layout>
<GridItem rowSpan={1} colSpan={12} marginTop={3}>
{applicantData && <PermitHolderHeader applicant={applicantData} />}
{data?.applicant && <PermitHolderHeader applicant={data.applicant} />}
</GridItem>
<GridItem rowSpan={12} colSpan={5} marginTop={5} textAlign="left">
<Stack spacing={5}>
{applicantData && (
{data?.applicant && (
<PersonalInformationCard
applicant={applicantData}
applicant={data.applicant}
onSave={handleUpdateUserInformation}
/>
)}
Expand Down
13 changes: 9 additions & 4 deletions pages/verify-identity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ import {
PopoverBody,
PopoverFooter,
AlertDescription,
Input,
useToast,
} from '@chakra-ui/react'; // Chakra UI
import { InfoOutlineIcon } from '@chakra-ui/icons'; // Chakra UI Icons
import Layout from '@components/applicant/Layout'; // Layout component
import TOSModal from '@components/applicant/renewals/TOSModal'; // TOS Modal
import DatePicker from '@components/DatePicker'; // Date picker component
import {
VERIFY_IDENTITY_MUTATION,
VerifyIdentityRequest,
Expand All @@ -47,7 +47,7 @@ export default function IdentityVerificationForm() {

const [userId, setUserId] = useState('');
const [phoneNumberSuffix, setPhoneNumberSuffix] = useState('');
const [dateOfBirth, setDateOfBirth] = useState(new Date());
const [dateOfBirth, setDateOfBirth] = useState(new Date().toISOString().substring(0, 10));

// Verify identity query
const [verifyIdentity, { data, loading }] = useMutation<
Expand Down Expand Up @@ -77,7 +77,7 @@ export default function IdentityVerificationForm() {
input: {
userId: parseInt(userId),
phoneNumberSuffix,
dateOfBirth: dateOfBirth.toISOString().substring(0, 10), // Strip time from DOB
dateOfBirth,
acceptedTos: acceptedTOSTimestamp,
},
},
Expand Down Expand Up @@ -135,7 +135,12 @@ export default function IdentityVerificationForm() {
</FormControl>
<FormControl isRequired textAlign="left" marginBottom="20px">
<FormLabel>{`Date of Birth`}</FormLabel>
<DatePicker width="184px" value={dateOfBirth} onDateChange={setDateOfBirth} />
<Input
type="date"
width="184px"
value={dateOfBirth}
onChange={event => setDateOfBirth(event.target.value)}
/>
<FormHelperText>
{`Please enter your date of birth in YYYY-MM-DD format. For example, if you were born on
20th August 1950, you would enter 20-08-1950`}
OustanDing marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
2 changes: 1 addition & 1 deletion prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -337,5 +337,5 @@ enum PermitType {
PERMANENT
TEMPORARY

@@map("permittype")
@@map("permittype")
}
38 changes: 20 additions & 18 deletions tools/components/internal/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { Role } from '@lib/types'; // Role enum
// Enum for internal page paths
export enum InternalPagePath {
Requests = '/admin',
Request = '/admin/request',
PermitHolders = '/admin/permit-holders',
PermitHolder = '/admin/permit-holder',
Reports = '/admin/reports',
AdminManagement = '/admin/admin-management',
}
Expand All @@ -17,30 +19,30 @@ export enum InternalPagePath {
export const getTabIndex = (path: string, role: Role): number => {
if (role === Role.Secretary) {
// Secretary
switch (path) {
case InternalPagePath.Requests:
return 0;
case InternalPagePath.PermitHolders:
return 1;
default:
return 0;
if (path === InternalPagePath.Requests || path.includes(InternalPagePath.Request)) {
return 0;
}
if (path === InternalPagePath.PermitHolders || path.includes(InternalPagePath.PermitHolder)) {
return 1;
}
return 0;
} else if (role === Role.Accounting) {
// Accounting
return 0; // Only has access to 1 tab
} else {
// Admin
switch (path) {
case InternalPagePath.Requests:
return 0;
case InternalPagePath.PermitHolders:
return 1;
case InternalPagePath.Reports:
return 2;
case InternalPagePath.AdminManagement:
return 3;
default:
return 0;
if (path === InternalPagePath.Requests || path.includes(InternalPagePath.Request)) {
return 0;
}
if (path === InternalPagePath.PermitHolders || path.includes(InternalPagePath.PermitHolder)) {
return 1;
}
if (path === InternalPagePath.Reports) {
return 2;
}
if (path === InternalPagePath.AdminManagement) {
return 3;
}
return 0;
}
};