Skip to content

Commit f6993a4

Browse files
committed
feat: automate intake openning
1 parent 65619f0 commit f6993a4

26 files changed

+32690
-30185
lines changed

app/components/Admin/AddIntake.tsx

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { DateTime } from 'luxon';
1313
import styled from 'styled-components';
1414
import { IChangeEvent, ThemeProps } from '@rjsf/core';
1515
import { CustomValidator, RJSFValidationError } from '@rjsf/utils';
16+
import ALL_INTAKE_ZONES from 'data/intakeZones';
1617

1718
interface EditProps {
1819
isFormEditMode: boolean;
@@ -41,10 +42,10 @@ const StyledBtnContainer = styled.div<EditProps>`
4142

4243
const StyledForm = styled.section<EditProps>`
4344
overflow: hidden;
44-
max-height: ${({ isFormEditMode }) => (isFormEditMode ? '560px' : '0px')};
45+
max-height: ${({ isFormEditMode }) => (isFormEditMode ? '760px' : '0px')};
4546
transition: max-height 0.5s;
4647
padding-left: 4px;
47-
max-width: 480px;
48+
max-width: 680px;
4849
margin-top: ${({ isFormEditMode }) => (isFormEditMode ? '24px' : '0px')};
4950
5051
.datetime-widget {
@@ -160,12 +161,22 @@ const AddIntake: React.FC<Props> = ({
160161
setIsStartDateDisabled(false);
161162
setFormData({
162163
intakeNumber: newIntakeNumber,
164+
zones: [...ALL_INTAKE_ZONES],
165+
allowUnlistedFnLedZones: false,
163166
});
164167
};
165168

166169
const handleSubmit = (e) => {
167-
const { startDate, endDate, intakeNumber, description, rollingIntake } =
168-
e.formData;
170+
const {
171+
startDate,
172+
endDate,
173+
intakeNumber,
174+
description,
175+
rollingIntake,
176+
inviteOnlyIntake,
177+
zones,
178+
allowUnlistedFnLedZones,
179+
} = e.formData;
169180

170181
if (isIntakeEdit) {
171182
updateIntake({
@@ -176,6 +187,9 @@ const AddIntake: React.FC<Props> = ({
176187
endTime: endDate,
177188
intakeDescription: description,
178189
isRollingIntake: rollingIntake,
190+
intakeZones: zones,
191+
isAllowUnlistedFnLedZones: allowUnlistedFnLedZones ?? false,
192+
hiddenIntakeCode: inviteOnlyIntake ? crypto.randomUUID() : null,
179193
},
180194
},
181195
onCompleted: () => {
@@ -191,6 +205,9 @@ const AddIntake: React.FC<Props> = ({
191205
endTime: endDate,
192206
startTime: startDate,
193207
rollingIntake,
208+
zones,
209+
allowUnlistedFnLedZones: allowUnlistedFnLedZones ?? false,
210+
hiddenCode: inviteOnlyIntake ? crypto.randomUUID() : null,
194211
},
195212
},
196213
onCompleted: () => {
@@ -238,6 +255,10 @@ const AddIntake: React.FC<Props> = ({
238255
errors?.endDate.addError('End date & time must be entered');
239256
}
240257

258+
if ((!jsonData?.zones || jsonData.zones.length === 0) && isFormSubmitting) {
259+
errors?.zones.addError('At least one zone must be selected');
260+
}
261+
241262
if (isEdit && nextIntake && endDateTime >= nextIntakeStartDateTime) {
242263
errors?.endDate.addError(
243264
'End date & time must not overlap with the next intake'
@@ -283,6 +304,8 @@ const AddIntake: React.FC<Props> = ({
283304
setIsFormEditMode(true);
284305
setFormData({
285306
intakeNumber: newIntakeNumber,
307+
zones: [...ALL_INTAKE_ZONES],
308+
allowUnlistedFnLedZones: false,
286309
});
287310
}}
288311
variant="secondary"

app/components/Admin/Intake.tsx

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ const StyledEdit = styled.button`
6161
const StyledFlex = styled.div`
6262
display: flex;
6363
flex-direction: column;
64+
margin-bottom: 24px;
6465
6566
& div {
6667
margin-bottom: 16px;
@@ -88,9 +89,17 @@ const StyledFlex = styled.div`
8889
}
8990
`;
9091

91-
const StyledDescription = styled.h4`
92-
font-weight: 400;
93-
color: ${({ theme }) => theme.color.components};
92+
const StyledLinkFlex = styled.div`
93+
display: flex;
94+
flex-direction: column;
95+
96+
& div {
97+
margin-bottom: 16px;
98+
}
99+
100+
& h4 {
101+
margin-bottom: 4px;
102+
}
94103
`;
95104

96105
interface IntakeProps {
@@ -117,15 +126,23 @@ const Intake: React.FC<IntakeProps> = ({
117126
description
118127
closeTimestamp
119128
openTimestamp
129+
hiddenCode
120130
rollingIntake
131+
zones
121132
rowId
122133
}
123134
`,
124135
intake
125136
);
126137

127-
const { ccbcIntakeNumber, closeTimestamp, description, openTimestamp } =
128-
queryFragment;
138+
const {
139+
ccbcIntakeNumber,
140+
closeTimestamp,
141+
description,
142+
hiddenCode,
143+
openTimestamp,
144+
zones,
145+
} = queryFragment;
129146

130147
const [archiveIntake] = useArchiveIntakeMutation();
131148

@@ -136,6 +153,9 @@ const Intake: React.FC<IntakeProps> = ({
136153
const formattedCloseDate = DateTime.fromISO(closeTimestamp).toLocaleString(
137154
DateTime.DATETIME_FULL
138155
);
156+
const displayCloseDate = DateTime.fromISO(closeTimestamp)
157+
.minus({ minutes: 30 })
158+
.toLocaleString(DateTime.DATETIME_FULL);
139159

140160
const mockedDateCookie = cookie.get('mocks.mocked_date');
141161
const currentDateTime = mockedDateCookie
@@ -146,6 +166,10 @@ const Intake: React.FC<IntakeProps> = ({
146166
const endDateTime = DateTime.fromISO(closeTimestamp);
147167
const isAllowedDelete = currentDateTime <= startDateTime;
148168
const isAllowedEdit = currentDateTime <= endDateTime;
169+
const hiddenIntakeLink =
170+
origin && hiddenCode
171+
? `${window.location.origin}/api/intake?code=${hiddenCode}`
172+
: null;
149173

150174
const handleDelete = () => {
151175
archiveIntake({
@@ -191,16 +215,34 @@ const Intake: React.FC<IntakeProps> = ({
191215
<span>{formattedOpenDate}</span>
192216
</div>
193217
<div>
194-
<h4>End date & time</h4>
218+
<h4>Actual end date and time</h4>
195219
<span>{formattedCloseDate}</span>
196220
</div>
221+
<div>
222+
<h4>Display end date and time</h4>
223+
<span>{displayCloseDate}</span>
224+
</div>
197225
{description && (
198226
<div>
199-
<StyledDescription>Description</StyledDescription>
227+
<h4>Description</h4>
200228
<span>{description}</span>
201229
</div>
202230
)}
231+
{zones && (
232+
<div>
233+
<h4>Zones</h4>
234+
<span>{zones.length ? zones.join(', ') : 'None'}</span>
235+
</div>
236+
)}
203237
</StyledFlex>
238+
{!isFormEditMode && hiddenIntakeLink && (
239+
<StyledLinkFlex>
240+
<div>
241+
<h4>Applicant access link</h4>
242+
<em>{hiddenIntakeLink}</em>
243+
</div>
244+
</StyledLinkFlex>
245+
)}
204246
</StyledContainer>
205247
);
206248
};

app/components/Form/ApplicationForm.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { applicantBenefits } from 'formSchema/uiSchema/pages';
2222
import useModal from 'lib/helpers/useModal';
2323
import { RJSFSchema } from '@rjsf/utils';
2424
import GenericConfirmationModal from 'lib/theme/widgets/GenericConfirmationModal';
25+
import ALL_INTAKE_ZONES from 'data/intakeZones';
2526
import SubmitButtons from './SubmitButtons';
2627
import FormBase from './FormBase';
2728
import {
@@ -165,6 +166,7 @@ const ApplicationForm: React.FC<Props> = ({
165166
intakeByIntakeId {
166167
ccbcIntakeNumber
167168
closeTimestamp
169+
zones
168170
}
169171
...ApplicationFormStatus_application
170172
}
@@ -179,6 +181,7 @@ const ApplicationForm: React.FC<Props> = ({
179181
closeTimestamp
180182
ccbcIntakeNumber
181183
rollingIntake
184+
zones
182185
rowId
183186
}
184187
allIntakes(
@@ -189,6 +192,7 @@ const ApplicationForm: React.FC<Props> = ({
189192
edges {
190193
node {
191194
ccbcIntakeNumber
195+
zones
192196
}
193197
}
194198
}
@@ -244,9 +248,11 @@ const ApplicationForm: React.FC<Props> = ({
244248
allIntakes?.edges[0]?.node?.ccbcIntakeNumber;
245249
const isRollingIntake = openIntake?.rollingIntake ?? false;
246250

247-
const acceptedProjectAreas = useFeature('intake_zones_json');
248-
const acceptedProjectAreasArray =
249-
acceptedProjectAreas?.value?.[ccbcIntakeNumber ?? latestIntakeNumber] || [];
251+
const intakeZones =
252+
application.intakeByIntakeId?.zones ??
253+
openIntake?.zones ??
254+
allIntakes?.edges[0]?.node?.zones;
255+
const acceptedProjectAreasArray = intakeZones ?? ALL_INTAKE_ZONES;
250256

251257
let jsonSchema: any;
252258
let formSchemaId: number;
@@ -723,7 +729,8 @@ const ApplicationForm: React.FC<Props> = ({
723729
};
724730

725731
const handleTemplateNineCreation = () => {
726-
const templateNineUuid = jsonData.templateUploads?.geographicNames?.[0]?.uuid;
732+
const templateNineUuid =
733+
jsonData.templateUploads?.geographicNames?.[0]?.uuid;
727734
if (templateNineUuid) {
728735
createTemplateNineData(rowId, templateNineUuid);
729736
}

app/data/intakeZones.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const ALL_INTAKE_ZONES = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
2+
3+
export default ALL_INTAKE_ZONES;

app/formSchema/admin/intake.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { RJSFSchema } from '@rjsf/utils';
2+
import ALL_INTAKE_ZONES from 'data/intakeZones';
23

34
const intake: RJSFSchema = {
45
description: '',
56
type: 'object',
6-
required: ['startDate', 'endDate'],
7+
required: ['startDate', 'endDate', 'zones'],
78
properties: {
89
intakeNumber: {
910
title: 'Intake #',
@@ -21,9 +22,26 @@ const intake: RJSFSchema = {
2122
type: 'string',
2223
title: 'Description (optional)',
2324
},
25+
zones: {
26+
title: 'Zones',
27+
type: 'array',
28+
minItems: 1,
29+
items: {
30+
type: 'number',
31+
enum: ALL_INTAKE_ZONES,
32+
},
33+
uniqueItems: true,
34+
},
2435
rollingIntake: {
2536
type: 'boolean',
2637
},
38+
inviteOnlyIntake: {
39+
type: 'boolean',
40+
},
41+
allowUnlistedFnLedZones: {
42+
type: 'boolean',
43+
default: false,
44+
},
2745
},
2846
};
2947

app/formSchema/uiSchema/admin/intakeUiSchema.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ const intakeUiSchema = {
55
hideErrors: true,
66
},
77
},
8+
zones: {
9+
'ui:widget': 'CheckboxesWidget',
10+
'ui:options': {
11+
checkboxDirection: 'column',
12+
},
13+
},
814
startDate: {
915
'ui:widget': 'DateTimePickerWidget',
1016
},
@@ -24,6 +30,18 @@ const intakeUiSchema = {
2430
title: 'Is Rolling intake',
2531
},
2632
},
33+
inviteOnlyIntake: {
34+
'ui:widget': 'CheckboxWidget',
35+
'ui:options': {
36+
title: 'Invite only intake',
37+
},
38+
},
39+
allowUnlistedFnLedZones: {
40+
'ui:widget': 'CheckboxWidget',
41+
'ui:options': {
42+
title: 'Allow unlisted zones if FN based/led',
43+
},
44+
},
2745
};
2846

2947
export default intakeUiSchema;

app/lib/theme/templates/BasicFieldTemplate.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,15 @@ const StyledH4 = styled.h4`
77
margin-bottom: 8px;
88
`;
99

10-
const StyledContainer = styled.div`
10+
const StyledContainer = styled.div<{ isInline?: boolean }>`
1111
margin-bottom: 16px;
12+
13+
${({ isInline }) =>
14+
isInline &&
15+
`
16+
display: inline-flex;
17+
margin-right: 24px;
18+
`}
1219
`;
1320

1421
const StyledError = styled.div`
@@ -30,9 +37,10 @@ const BasicFieldTemplate: React.FC<FieldTemplateProps> = ({
3037
const uiTitle = uiSchema?.['ui:title'];
3138
const fieldTitle = uiTitle || title;
3239
const hideErrors = uiSchema?.['ui:options']?.hideErrors;
40+
const isInline = schema?.type === 'boolean';
3341

3442
return (
35-
<StyledContainer>
43+
<StyledContainer isInline={isInline}>
3644
{fieldTitle && <StyledH4>{fieldTitle}</StyledH4>}
3745
{children}
3846
{!hideErrors && <StyledError>{rawErrors}</StyledError>}

0 commit comments

Comments
 (0)