Skip to content

Commit

Permalink
[Release] Version 0.0.9 (#324)
Browse files Browse the repository at this point in the history
* [Feature] Create setEmployeeAsActive GraphQL endpoint (#322)
* [Fix] Save poaFormS3ObjectKey when updating guardian information in permit holders page (#319)
* [Fix] Postal Code Space Issue (#316)
* Set other gender field on permit holders page (#318)
* Add .nvmrc file (#317)
* [Feature] Implement applicant deletion (#310)
* [Feature] Implement application deletion (#315)
* Display other gender field on permit holders page (#314)
* Move wallet card task in application processing (#313)
* [Feature] Tax receipt (#311)
* [Fix] Fix expiry date for in-progress replacement applications (#274)
* [Fix] Fix APP history permit type badge (#273)
* [Improvement] Adjust spacing of address in invoice (#272)
* [Fix] Show validation error messages on form mount (#271)
  • Loading branch information
leogjhuang committed Oct 10, 2023
1 parent 389df7b commit 3468852
Show file tree
Hide file tree
Showing 56 changed files with 1,135 additions and 149 deletions.
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
14.17.0
29 changes: 29 additions & 0 deletions components/admin/permit-holders/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useRouter } from 'next/router';
import {
Alert,
AlertIcon,
Expand All @@ -18,6 +19,7 @@ import { ChevronDownIcon, ChevronLeftIcon } from '@chakra-ui/icons'; // Chakra U
import Link from 'next/link'; // Link
import { ApplicantStatus } from '@lib/graphql/types';
import PermitHolderStatusBadge from '@components/admin/PermitHolderStatusBadge';
import ConfirmDeleteApplicantModal from '@components/admin/permit-holders/table/ConfirmDeleteApplicantModal';
import SetPermitHolderToInactiveModal from '@components/admin/permit-holders/table/ConfirmSetInactiveModal';
import SetPermitHolderToActiveModal from '@components/admin/permit-holders/table/ConfirmSetActiveModal';
import AdditionalNotesModal from '@components/admin/permit-holders/additional-notes/Modal';
Expand All @@ -37,13 +39,22 @@ export default function PermitHolderHeader({
applicant: { id, name, status, inactiveReason, notes },
refetch,
}: PermitHolderHeaderProps) {
const router = useRouter();

// Set Permit Holder Inactive/Active modal state
const {
isOpen: isSetPermitHolderStatusModalOpen,
onOpen: onOpenSetPermitHolderStatusModal,
onClose: onCloseSetPermitHolderStatusModal,
} = useDisclosure();

// Delete applicant modal state
const {
isOpen: isDeleteApplicantModalOpen,
onOpen: onOpenDeleteApplicantModal,
onClose: onCloseDeleteApplicantModal,
} = useDisclosure();

// Additional notes modal state
const {
isOpen: isNotesModalOpen,
Expand Down Expand Up @@ -97,6 +108,13 @@ export default function PermitHolderHeader({
>
{`Set as ${status === 'ACTIVE' ? 'Inactive' : 'Active'}`}
</MenuItem>
<MenuItem
color="text.critical"
textStyle="button-regular"
onClick={onOpenDeleteApplicantModal}
>
{'Delete Permit Holder'}
</MenuItem>
</MenuList>
</Menu>
</Box>
Expand Down Expand Up @@ -143,6 +161,17 @@ export default function PermitHolderHeader({
onClose={onCloseSetPermitHolderStatusModal}
/>
)}
<ConfirmDeleteApplicantModal
isOpen={isDeleteApplicantModalOpen}
applicantId={id}
refetch={() => {
/* Do not refetch, redirect to permit holders page */
}}
onClose={() => {
onCloseDeleteApplicantModal();
router.push('/admin/permit-holders');
}}
/>

{/* Additional notes modal */}
<AdditionalNotesModal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export default function PermitHolderInformationCard(props: PersonalInformationPr
Date of Birth: {formatDateYYYYMMDD(new Date(dateOfBirth))}
</Text>
<Text as="p" textStyle="body-regular">
Gender: {gender === 'OTHER' ? otherGender : titlecase(gender)}
Gender: {gender === 'OTHER' && otherGender ? otherGender : titlecase(gender)}
</Text>
</VStack>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export default function EditUserInformationModal({
}}
validationSchema={permitHolderInformationSchema}
onSubmit={handleSubmit}
validateOnMount
>
{({ values, isValid }) => (
<Form noValidate>
Expand Down
115 changes: 115 additions & 0 deletions components/admin/permit-holders/table/ConfirmDeleteApplicantModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { SyntheticEvent } from 'react';
import {
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalFooter,
ModalBody,
Button,
Text,
useToast,
} from '@chakra-ui/react';
import { useMutation } from '@tools/hooks/graphql';
import {
DeleteApplicantRequest,
DeleteApplicantResponse,
DELETE_APPLICANT,
} from '@tools/admin/permit-holders/permit-holders-table';

type ConfirmDeleteApplicantModalProps = {
readonly isOpen: boolean;
readonly applicantId: number;
readonly refetch: () => void;
readonly onClose: () => void;
};

/**
* Delete applicant confirmation modal
*/
export default function ConfirmDeleteApplicantModal({
isOpen,
applicantId,
refetch,
onClose,
}: ConfirmDeleteApplicantModalProps) {
const toast = useToast();

// API call to deleteApplicant
const [deleteApplicant] = useMutation<DeleteApplicantResponse, DeleteApplicantRequest>(
DELETE_APPLICANT,
{
onCompleted: data => {
if (data.deleteApplicant.ok) {
toast({
status: 'success',
description: `Permit holder successfully deleted.`,
});
} else {
toast({
status: 'error',
description: `Failed to delete permit holder.`,
});
}
},
}
);

// Close modal handler
const handleClose = () => {
onClose();
};

// Sets permit holder status to inactive and closes modal
const handleSubmit = async (event: SyntheticEvent) => {
event.preventDefault();
await deleteApplicant({
variables: { input: { id: applicantId } },
});
refetch();
onClose();
};

return (
<Modal isCentered={true} isOpen={isOpen} onClose={handleClose} size="3xl">
<ModalOverlay />
<form onSubmit={handleSubmit}>
<ModalContent paddingX="20px">
<ModalHeader paddingTop="20px" paddingBottom="12px" paddingX="4px">
<Text as="h2" textStyle="display-medium-bold">
{`Delete Permit Holder`}
</Text>
</ModalHeader>
<ModalBody paddingBottom="0px" paddingX="4px">
<Text as="p" textStyle="body-regular" marginBottom="20px">
Are you sure you want to delete this permit holder? This action is irreversible.
</Text>
<Text as="p" textStyle="body-regular" marginBottom="20px">
<b>
All of this user&apos;s data, including associated applications and permits will be
permanently deleted.
</b>
</Text>
<Text as="p" textStyle="body-regular" marginBottom="20px">
If you would like to retain this data, please cancel and mark this user as inactive
instead.
</Text>
</ModalBody>
<ModalFooter paddingY="16px">
<Button onClick={onClose} colorScheme="gray" variant="solid">
{'Cancel'}
</Button>
<Button
bg="secondary.critical"
_hover={{ bg: 'secondary.criticalHover' }}
type="submit"
ml={'12px'}
>
{'Delete Permit Holder'}
</Button>
</ModalFooter>
</ModalContent>
</form>
</Modal>
);
}
67 changes: 65 additions & 2 deletions components/admin/requests/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,33 @@
import { Box, Flex, HStack, Text, Link, VStack, Alert, AlertIcon } from '@chakra-ui/react'; // Chakra UI
import { ChevronLeftIcon } from '@chakra-ui/icons'; // Chakra UI icon
import { useRouter } from 'next/router';
import {
Alert,
AlertIcon,
Box,
Button,
Flex,
HStack,
Link,
Menu,
MenuButton,
MenuItem,
MenuList,
Text,
useDisclosure,
VStack,
} from '@chakra-ui/react'; // Chakra UI
import { ChevronDownIcon, ChevronLeftIcon } from '@chakra-ui/icons'; // Chakra UI icon
import NextLink from 'next/link'; // Link
import RequestStatusBadge from '@components/admin/RequestStatusBadge'; // Request status badge
import ShopifyBadge from '@components/admin/ShopifyBadge';
import PermitTypeBadge from '@components/admin/PermitTypeBadge';
import ConfirmDeleteRequestModal from './delete/ConfirmDeleteRequestModal';
import { ApplicationStatus, ApplicationType, PermitType } from '@lib/graphql/types';
import { titlecase } from '@tools/string';
import { formatDateYYYYMMDD, formatDateYYYYMMDDLocal } from '@lib/utils/date';
import { getPermanentPermitExpiryDate } from '@lib/utils/permit-expiry';

type RequestHeaderProps = {
readonly id: number;
readonly applicationType: ApplicationType;
readonly permitType: PermitType;
readonly createdAt: Date;
Expand All @@ -24,6 +42,7 @@ type RequestHeaderProps = {

/**
* Header of View Request page
* @param id Application id
* @param applicationType Type of application
* @param permitType Type of permit
* @param createdAt Date permit was created at
Expand All @@ -36,6 +55,7 @@ type RequestHeaderProps = {
* @param reasonForRejection Reason for rejecting application
*/
export default function RequestHeader({
id,
applicationType,
permitType,
createdAt,
Expand All @@ -55,6 +75,8 @@ export default function RequestHeader({
expiryDateText = `Expiry date: ${formatDateYYYYMMDD(permitExpiry)}`;
} else if (permitType === 'TEMPORARY' && !!temporaryPermitExpiry) {
expiryDateText = `This permit will expire: ${formatDateYYYYMMDD(temporaryPermitExpiry)}`;
} else if (applicationType === 'REPLACEMENT' && !!permitExpiry) {
expiryDateText = `This permit will expire: ${formatDateYYYYMMDD(permitExpiry)}`;
} else if (permitType === 'PERMANENT') {
expiryDateText = `This permit will expire: ${formatDateYYYYMMDD(
getPermanentPermitExpiryDate()
Expand All @@ -63,6 +85,15 @@ export default function RequestHeader({
expiryDateText = null;
}

const router = useRouter();

// Delete application modal state
const {
isOpen: isDeleteApplicationModalOpen,
onOpen: onOpenDeleteApplicationModal,
onClose: onCloseDeleteApplicationModal,
} = useDisclosure();

return (
<Box textAlign="left">
<NextLink href="/admin" passHref>
Expand All @@ -88,6 +119,27 @@ export default function RequestHeader({
Received on {formatDateYYYYMMDDLocal(createdAt)} at{' '}
{createdAt.toLocaleTimeString('en-CA')}
</Text>
<Menu>
<MenuButton
as={Button}
rightIcon={<ChevronDownIcon />}
height="30px"
bg="background.gray"
_hover={{ bg: 'background.grayHover' }}
color="black"
>
<Text textStyle="caption">More Actions</Text>
</MenuButton>
<MenuList>
<MenuItem
color="text.critical"
textStyle="button-regular"
onClick={onOpenDeleteApplicationModal}
>
{'Delete Request'}
</MenuItem>
</MenuList>
</Menu>
</HStack>
{displayShopifyUrl && (
<Text textStyle="caption" as="p">
Expand Down Expand Up @@ -127,6 +179,17 @@ export default function RequestHeader({
</Text>
</Alert>
)}
<ConfirmDeleteRequestModal
isOpen={isDeleteApplicationModalOpen}
applicationId={id}
refetch={() => {
/* Do not refetch, redirect to main page */
}}
onClose={() => {
onCloseDeleteApplicationModal();
router.push('/admin');
}}
/>
</VStack>
</Box>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export default function EditAdditionalInformationModal({
initialValues={{ additionalInformation: additionalInformation }}
validationSchema={editAdditionalQuestionsSchema}
onSubmit={handleSubmit}
validateOnMount
>
{({ values, isValid }) => (
<Form style={{ width: '100%' }} noValidate>
Expand Down
Loading

0 comments on commit 3468852

Please sign in to comment.