Skip to content

Commit

Permalink
[Release] Version 0.2.0 (#337)
Browse files Browse the repository at this point in the history
* [Improvement] Update donation receipt spacing (#326)
* Fix validation schema for other gender field (#327)
* Adjust schema to evaluate date at validation time (#328)
* [Fix] Make replacement requests clearer (#325)
* Add new contributor to seeding script (#330)
* ignore the .yarn file for > v2.0.0 (#331)
* [Misc] Create initial baseline migration file (#333)
* [Doc] Update README with prisma migrate deploy command (#334)
* [Fix] Fix replacement request otherGender and lostTimestamp form validations (#335)
* [Misc] Add holiday closure banner (#336)
  • Loading branch information
leogjhuang authored Dec 11, 2023
1 parent c8afba7 commit 6ef89aa
Show file tree
Hide file tree
Showing 12 changed files with 579 additions and 82 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

# dependencies
/node_modules
/.yarn*
/.pnp
.pnp.js

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ yarn dev
3. Deploy prisma schema

```bash
npx prisma db push
npx prisma migrate deploy
```

4. Seed database
Expand Down
2 changes: 0 additions & 2 deletions components/admin/requests/permit-holder-information/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@ const Card: FC<Props> = props => {
| null;
if (type === 'NEW') {
const validatedData = await permitHolderInformationSchema.validate(permitHolderData);
// TODO: Remove this once schema is updated
validatedData.otherGender = '';

({ data } = await updateNewPermitHolderInformation({
variables: { input: { id: applicationId, ...validatedData } },
Expand Down
48 changes: 38 additions & 10 deletions components/admin/requests/reason-for-replacement/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import NumberField from '@components/form/NumberField';
import RadioGroupField from '@components/form/RadioGroupField';
import TextArea from '@components/form/TextAreaField';
import TextField from '@components/form/TextField';
import { formatDate } from '@lib/utils/date'; // Date formatter util
import { formatDateYYYYMMDDLocal } from '@lib/utils/date'; // Date formatter util
import { ReasonForReplacementFormData } from '@tools/admin/requests/reason-for-replacement';
import { useFormikContext } from 'formik';
import moment from 'moment';

type ReasonForReplacementProps = {
readonly reasonForReplacement: ReasonForReplacementFormData;
Expand All @@ -36,9 +37,30 @@ export default function ReasonForReplacementForm({
<Box paddingBottom="24px">
<RadioGroupField name="reasonForReplacement.reason" label="Reason" required>
<Stack>
<Radio value={'LOST'}>{'Lost'}</Radio>
<Radio value={'STOLEN'}>{'Stolen'}</Radio>
<Radio value={'OTHER'}>{'Other'}</Radio>
<Radio
value={'LOST'}
onChange={() => {
setFieldValue('paymentInformation.processingFee', '31');
}}
>
{'Lost'}
</Radio>
<Radio
value={'STOLEN'}
onChange={() => {
setFieldValue('paymentInformation.processingFee', '31');
}}
>
{'Stolen'}
</Radio>
<Radio
value={'OTHER'}
onChange={() => {
setFieldValue('paymentInformation.processingFee', '0');
}}
>
{'Mail Lost'}
</Radio>
</Stack>
</RadioGroupField>
</Box>
Expand All @@ -54,7 +76,10 @@ export default function ReasonForReplacementForm({
required
value={
reasonForReplacement.lostTimestamp
? formatDate(new Date(reasonForReplacement.lostTimestamp), true)
? // lostTimestamp is the date in the LOCAL TIMEZONE, in YYYY-MM-DD format
// use moment to get Date object in local timezone as
// Date constructor defaults to UTC when given YYYY-MM-DD string
formatDateYYYYMMDDLocal(moment(reasonForReplacement.lostTimestamp).toDate())
: ''
}
/>
Expand All @@ -70,18 +95,21 @@ export default function ReasonForReplacementForm({
<Input
type="time"
value={
new Date(reasonForReplacement.lostTimestamp).toLocaleTimeString('en-US', {
moment(reasonForReplacement.lostTimestamp).toDate().toLocaleTimeString('en-US', {
hour12: false,
hour: '2-digit',
minute: '2-digit',
}) || ''
}
onChange={event => {
const updatedlostTimestamp = new Date(reasonForReplacement.lostTimestamp);
updatedlostTimestamp.setHours(parseInt(event.target.value.substring(0, 2)));
updatedlostTimestamp.setMinutes(parseInt(event.target.value.substring(3, 5)));
const updatedlostTimestamp = moment(reasonForReplacement.lostTimestamp);
updatedlostTimestamp.set('hour', parseInt(event.target.value.substring(0, 2)));
updatedlostTimestamp.set('minute', parseInt(event.target.value.substring(3, 5)));

setFieldValue('reasonForReplacement.lostTimestamp', updatedlostTimestamp);
setFieldValue(
'reasonForReplacement.lostTimestamp',
updatedlostTimestamp.toDate()
);
}}
/>
<FormHelperText color="text.secondary">{'Example: HH:MM AM/PM'}</FormHelperText>
Expand Down
2 changes: 1 addition & 1 deletion lib/applications/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1192,7 +1192,7 @@ export const updateNewApplicationGeneralInformation: Resolver<
const { input } = args;

try {
await requestPermitHolderInformationMutationSchema.validate(input);
await requestPermitHolderInformationMutationSchema.validate({ type: 'NEW', ...input });
} catch (err) {
if (err instanceof ValidationError) {
return {
Expand Down
20 changes: 12 additions & 8 deletions lib/applications/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ import {
requestPhysicianInformationSchema,
} from '@lib/physicians/validation';
import { PaymentType, Province, ReasonForReplacement, ShopifyPaymentStatus } from '@prisma/client';
import { bool, date, mixed, number, object, string } from 'yup';
import { bool, date, lazy, mixed, number, object, string } from 'yup';
import {
AccessibleConvertedVanLoadingMethod,
RequiresWiderParkingSpaceReason,
} from '@lib/graphql/types';
import { monetaryValueRegex, phoneNumberRegex, postalCodeRegex } from '@lib/utils/validation';
import moment from 'moment';

/**
* Additional Questions form validation schema
Expand Down Expand Up @@ -215,13 +216,16 @@ export const reasonForReplacementFormSchema = object({
.default(null)
.when('reason', {
is: 'LOST',
then: date()
.transform((_value, originalValue) => {
return new Date(originalValue);
})
.typeError('Please enter date APP was lost')
.max(new Date(), 'Date must be in the past')
.required('Please enter date APP was lost'),
then: lazy(() =>
date()
.transform((_value, originalValue) => {
// convert YYYY-MM-DD string in local timezone to a Date object in UTC
return moment.utc(moment(originalValue).toDate()).toDate();
})
.typeError('Please enter date APP was lost')
.max(new Date(), 'Date must be in the past')
.required('Please enter date APP was lost')
),
otherwise: date()
.transform(_ => null)
.nullable(),
Expand Down
114 changes: 64 additions & 50 deletions lib/invoices/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,57 +404,74 @@ const donationPdfDefinition = (input: {
pageBreak: 'before',
text: [
{ text: 'RICHMOND CENTRE FOR DISABILITY', style: 'header' },
'\n\n',
'\n',
{
text: `Official Donation Receipt for Income Tax Purposes - ${dateIssued.getFullYear()}`,
style: 'subheaderDonation',
style: 'subheader',
},
],
},

{
columns: [
{
table: {
heights: 20,
body: [
[
{ text: 'Tax Receipt #:' },
`PPD_${dateIssued.getFullYear()}${dateIssued.getMonth()}${dateIssued.getDate()}_${appNumber}`,
],
[
{ text: 'Donated by:' },
{
text: [
`${applicantName}\n`,
`${address.addressLine2 ? `${address.addressLine2} - ` : ''}${
address.addressLine1
}\n`,
`${address.city} ${address.province} ${formatPostalCode(address.postalCode)}`,
stack: [
{
table: {
heights: 18,
body: [
[
{ text: 'Tax Receipt #:' },
`PPD_${dateIssued.getFullYear()}${dateIssued.getMonth()}${dateIssued.getDate()}_${appNumber}`,
],
fontSize: 12,
lineHeight: 1.5,
},
],
[{ text: '' }, ''],
[{ text: '' }, ''],
[{ text: '' }, ''],
[{ text: 'Email:' }, nonNullEmail],
[{ text: 'Date Receipt Issued:' }, formatDateYYYYMMDD(dateIssued)],
[{ text: 'Location Receipt Issued:' }, 'Richmond, BC'],
[{ text: 'Authorized Signature:' }, { image: 'signature', width: 150 }],
],
},
layout: 'noBorders',
margin: [0, 0, 20, 0],
[
{ text: 'Donated by:' },
{
text: [
`${applicantName}\n`,
`${address.addressLine2 ? `${address.addressLine2} - ` : ''}${
address.addressLine1
}\n`,
`${address.city} ${address.province} ${formatPostalCode(
address.postalCode
)}`,
],
lineHeight: 1.4,
},
],
],
},
layout: 'noBorders',
margin: [0, 0, 0, 40],
},
{
text: [`Email: ${nonNullEmail}`],
margin: [0, 0, 0, 8],
},
{
table: {
heights: 18,
body: [
[{ text: 'Date Receipt Issued:' }, formatDateYYYYMMDD(dateIssued)],
[{ text: 'Location Receipt Issued:' }, 'Richmond, BC'],
],
},
margin: [0, 0, 0, 15],
layout: 'noBorders',
},
{ image: 'signature', width: 200, margin: [0, 0, 0, 5] },
{ text: 'Authorized Signature:' },
],
},

{
table: {
heights: 20,
heights: 18,
body: [
[{ text: 'Date Donation Received:' }, formatDateYYYYMMDD(dateDonationRecevied)],
[{ text: 'Donor Number:' }, `P${appNumber}`],
[{ text: 'Total Amount:' }, `$${donationAmount.toString()}`],
[{ text: 'Value of Product / Services:' }, ''],
[{ text: 'Value of Product / Services:\n\n' }, ''],
[
{ text: 'Eligible Amount of Donation for Tax Purposes:' },
`$${donationAmount.toString()}`,
Expand All @@ -469,26 +486,26 @@ const donationPdfDefinition = (input: {
'Address of Appraiser:\n\n',
],
},
{ image: 'stamp', width: 85 },
{ image: 'stamp', width: 80 },
],
],
},
layout: 'noBorders',
margin: [20, 0, 0, 0],
margin: [15, 0, 0, 0],
},
],
margin: [0, 35, 0, 25],
margin: [0, 25, 0, 0],
},
{
text: [
`Dear ${applicantName}\n\n`,
`Dear ${applicantName}\n\n\n`,
'On behalf of the Richmond Centre for Disability (RCD), we would like to extend our sincere and\n',
'heartfelt thanks and appreciation for your donation. Please find your official tax receipt enclosed.\n\n',
'Through RCD services and support, we have seen the lives of people with disabilities and their\n',
'families changed for the better. Your generosity does make a difference in the delivery of much\n',
'coveted services to people with disabilities. The work being undertaken through the RCD is only\n',
'possible because of caring people like you.\n\n',
'Thank you again for your valued support.\n\n',
'possible because of caring people like you.\n\n\n',
'Thank you again for your valued support.\n\n\n',
'Sincerely,\n\n\n',
'RICHMOND CENTRE FOR DISABILITY\n',
'(Charity Number: 88832-8432-RR0001)\n',
Expand All @@ -498,35 +515,32 @@ const donationPdfDefinition = (input: {
'Website:www.rcdrichmond.org\n',
],
margin: [0, 15, 0, 0],
fontSize: 12,
},
]),
styles: {
header: {
fontSize: 28,
fontSize: 25.5,
bold: true,
alignment: 'center',
lineHeight: 1.5,
},
tableHeader: {
bold: true,
alignment: 'center',
},
subheader: {
fontSize: 20,
bold: false,
alignment: 'center',
},
subheaderDonation: {
fontSize: 19,
fontSize: 17.5,
alignment: 'center',
},
footer: {
fontSize: 8,
fontSize: 7.5,
alignment: 'center',
},
},
defaultStyle: {
font: 'Helvetica',
fontSize: 11,
lineHeight: 1.2,
},
images: {
rcd: 'public/assets/logo.png',
Expand Down
16 changes: 9 additions & 7 deletions lib/physicians/validation.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { phoneNumberRegex, postalCodeRegex } from '@lib/utils/validation';
import { MobilityAid, PatientCondition, PermitType } from '@prisma/client';
import { date, mixed, object, string, array, number } from 'yup';
import { date, lazy, mixed, object, string, array, number } from 'yup';

/**
* Validation schema for physician assessment form
*/
export const physicianAssessmentSchema = object({
disability: string().required('Please enter a disabling condition'),
disabilityCertificationDate: date()
.transform((_value, originalValue) => {
return new Date(originalValue);
})
.max(new Date(), 'Date must be in the past')
.required('Please enter a valid certification date'),
disabilityCertificationDate: lazy(() =>
date()
.transform((_value, originalValue) => {
return new Date(originalValue);
})
.max(new Date(), 'Date must be in the past')
.required('Please enter a valid certification date')
),
patientCondition: array(
mixed<PatientCondition>()
.oneOf(Object.values(PatientCondition))
Expand Down
8 changes: 5 additions & 3 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ export default function Landing() {

return (
<Layout>
{Date.now() < new Date('2023-11-23T06:00:00.000Z').getTime() && (
{Date.now() < new Date('2024-01-02T08:00:00.000Z').getTime() && (
<GridItem colSpan={12} colStart={1}>
<Alert status="warning" variant="top-accent">
<AlertIcon />
<AlertDescription>
Please note that this site will be offline for planned maintenance on Nov 22, 2023
from 7:00pm to 10:00pm PST. We apologize for any inconvenience.
Please note that the RCD office will be closed between Dec 18 and Jan 1 and will
resume regular business hours on Jan 2. We will process applications received during
the holidays, but all other services will be unavailable. We apologize for any
inconvenience.
</AlertDescription>
</Alert>
</GridItem>
Expand Down
Loading

0 comments on commit 6ef89aa

Please sign in to comment.