Skip to content

Commit

Permalink
Update UI to display form errors
Browse files Browse the repository at this point in the history
  • Loading branch information
wilwong89 committed May 17, 2024
1 parent d690a42 commit 04eeecc
Show file tree
Hide file tree
Showing 11 changed files with 249 additions and 136 deletions.
1 change: 1 addition & 0 deletions frontend/src/assets/variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ $app-primary: #036;
$app-link-text: #1a5a96;
$app-link-text-hover: #00f;
$app-outline-on-primary: #fff;
$app-error: #D8292F;

// highlighted sections, table rows
$app-highlight-background: #d9e1e8;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/form/Dropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const emit = defineEmits(['onChange']);
/>

<small :id="`${name}-help`">{{ helpText }}</small>
<div>
<div class="mt-1">
<ErrorMessage :name="name" />
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/form/InputMask.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const props = withDefaults(defineProps<Props>(), {
/>

<small :id="`${name}-help`">{{ helpText }}</small>
<div>
<div class="mt-1">
<ErrorMessage :name="name" />
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/form/InputNumber.vue
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const fieldActive: Ref<boolean> = ref(false);
>
{{ helpText }}
</small>
<div>
<div class="mt-1">
<ErrorMessage :name="name" />
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/form/InputText.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const fieldActive: Ref<boolean> = ref(false);
>
{{ helpText }}
</small>
<div>
<div class="mt-1">
<ErrorMessage :name="name" />
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/form/RadioList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ watch(value, () => {
</div>

<small :id="`${name}-help`">{{ helpText }}</small>
<div>
<div class="mt-1">
<ErrorMessage :name="name" />
</div>
</div>
Expand Down
108 changes: 90 additions & 18 deletions frontend/src/components/intake/ShasIntakeForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@ import { useTypeStore } from '@/store';
import {
ContactPreferenceList,
NumResidentialUnits,
ProjectLocation,
ProjectRelationshipList,
RouteNames,
YesNo,
YesNoUnsure
} from '@/utils/constants';
import { BASIC_RESPONSES } from '@/utils/enums';
import { BASIC_RESPONSES, INTAKE_FORM_CATEGORIES, PROJECT_LOCATION } from '@/utils/enums';
import { deepToRaw } from '@/utils/utils';
import { getIntakeSchema } from './ShasIntakeSchema';
import { intakeSchema } from './ShasIntakeSchema';
import type { Ref } from 'vue';
import Calendar from '../form/Calendar.vue';
Expand All @@ -52,26 +53,28 @@ const { getPermitTypes } = storeToRefs(typeStore);
const activeStep: Ref<number> = ref(0);
const assignedActivityId: Ref<string | undefined> = ref(undefined);
const editable: Ref<boolean> = ref(true);
const formRef: Ref<InstanceType<typeof Form> | null> = ref(null);
const geomarkAccordionIndex: Ref<number | undefined> = ref(undefined);
const isSubmittable: Ref<boolean> = ref(false);
const initialFormValues: Ref<any | undefined> = ref(undefined);
const parcelAccordionIndex: Ref<number | undefined> = ref(undefined);
const spacialAccordionIndex: Ref<number | undefined> = ref(undefined);
// Enums
const enum PROJECT_LOCATION {
STREET_ADDRESS = 'Street address',
LOCATION_COORDINATES = 'Location coordinates'
}
// Constants
const ProjectLocation = [PROJECT_LOCATION.STREET_ADDRESS, PROJECT_LOCATION.LOCATION_COORDINATES];
const formSchema = getIntakeSchema(ProjectLocation);
const validationErrors: Ref<string[]> = ref([]);
// Actions
const confirm = useConfirm();
const toast = useToast();
function confirmSubmit(data: any) {
const checkSubmittable = (stepNumber: number) => {
if (stepNumber === 3) isSubmittable.value = true;
};
function displayErrors(a: any) {
validationErrors.value = Array.from(new Set(a.errors ? Object.keys(a.errors).map((x) => x.split('.')[0]) : []));
document.getElementById('form')?.scrollIntoView({ behavior: 'smooth' });
}
function value(data: any) {
confirm.require({
message: 'Are you sure you wish to submit this form? Please review the form before submitting.',
header: 'Please confirm submission',
Expand Down Expand Up @@ -134,21 +137,26 @@ onBeforeMount(async () => {
typeStore.setPermitTypes((await permitService.getPermitTypes()).data);
});
const formRef: Ref<InstanceType<typeof Form> | null> = ref(null);
</script>

<template>
<div>{{ formRef?.meta }}</div>
<div v-if="!assignedActivityId">
<Form
v-if="initialFormValues"
id="form"
v-slot="{ setFieldValue, values }"
ref="formRef"
keep-values
:initial-values="initialFormValues"
:validation-schema="formSchema"
@submit="confirmSubmit"
:validation-schema="intakeSchema"
@invalid-submit="(e) => displayErrors(e)"
@submit="value"
>
<Stepper v-model:activeStep="activeStep">
<Stepper
v-model:activeStep="activeStep"
@update:active-step="checkSubmittable"
>
<!--
Basic info
-->
Expand All @@ -160,9 +168,24 @@ const formRef: Ref<InstanceType<typeof Form> | null> = ref(null);
:click-callback="clickCallback"
title="Basic info"
icon="fa-user"
:class="{
'p-red':
validationErrors.includes(INTAKE_FORM_CATEGORIES.APPLICANT) ||
validationErrors.includes(INTAKE_FORM_CATEGORIES.BASIC)
}"
/>
</template>
<template #content="{ nextCallback }">
<Message
v-if="validationErrors.length"
severity="error"
icon="pi pi-exclamation-circle"
:closable="false"
class="text-center mt-0"
>
One of more of the required fields are missing or contains invalid data. Please check the highlighted
fields.
</Message>
<Card>
<template #title>
<span class="section-header">Applicant Info</span>
Expand Down Expand Up @@ -301,9 +324,20 @@ const formRef: Ref<InstanceType<typeof Form> | null> = ref(null);
:click-callback="clickCallback"
title="Housing"
icon="fa-house"
:class="{ 'p-red': validationErrors.includes('housing') }"
/>
</template>
<template #content="{ prevCallback, nextCallback }">
<Message
v-if="validationErrors.length"
severity="error"
icon="pi pi-exclamation-circle"
:closable="false"
class="text-center mt-0"
>
One of more of the required fields are missing or contains invalid data. Please check the highlighted
fields.
</Message>
<Card>
<template #title>
<span class="section-header">Help us learn more about your housing project</span>
Expand Down Expand Up @@ -657,9 +691,22 @@ const formRef: Ref<InstanceType<typeof Form> | null> = ref(null);
:click-callback="clickCallback"
title="Location"
icon="fa-location-dot"
:class="{
'p-red': validationErrors.includes(INTAKE_FORM_CATEGORIES.LOCATION)
}"
/>
</template>
<template #content="{ prevCallback, nextCallback }">
<Message
v-if="validationErrors.length"
severity="error"
icon="pi pi-exclamation-circle"
:closable="false"
class="text-center mt-0"
>
One of more of the required fields are missing or contains invalid data. Please check the highlighted
fields.
</Message>
<Card>
<template #title>
<div class="flex">
Expand Down Expand Up @@ -908,9 +955,24 @@ const formRef: Ref<InstanceType<typeof Form> | null> = ref(null);
:click-callback="clickCallback"
title="Permits & Reports"
icon="fa-file"
:class="{
'p-red':
validationErrors.includes(INTAKE_FORM_CATEGORIES.PERMITS) ||
validationErrors.includes(INTAKE_FORM_CATEGORIES.APPLIED_PERMITS)
}"
/>
</template>
<template #content="{ prevCallback }">
<Message
v-if="validationErrors.length"
severity="error"
icon="pi pi-exclamation-circle"
:closable="false"
class="text-center mt-0"
>
One of more of the required fields are missing or contains invalid data. Please check the highlighted
fields.
</Message>
<Card>
<template #title>
<div class="flex">
Expand Down Expand Up @@ -1101,6 +1163,7 @@ const formRef: Ref<InstanceType<typeof Form> | null> = ref(null);
class="col-4"
:name="`investigatePermits[${idx}].permitTypeId`"
placeholder="Select Permit type"
`
:options="getPermitTypes"
:option-label="(e) => `${e.businessDomain}: ${e.name}`"
option-value="permitTypeId"
Expand Down Expand Up @@ -1169,7 +1232,7 @@ const formRef: Ref<InstanceType<typeof Form> | null> = ref(null);
label="Submit"
type="submit"
icon="pi pi-upload"
:disabled="!editable || activeStep !== 3"
:disabled="!editable || !isSubmittable"
/>
</div>
</Form>
Expand Down Expand Up @@ -1197,6 +1260,15 @@ const formRef: Ref<InstanceType<typeof Form> | null> = ref(null);
box-shadow: none;
}
:deep(.p-red) {
color: $app-error;
}
:deep(.p-invalid),
:deep(.p-card.p-component:has(.p-invalid)) {
border-color: $app-error !important;
}
.p-card {
border-color: rgb(242, 241, 241);
border-radius: 8px;
Expand Down
Loading

0 comments on commit 04eeecc

Please sign in to comment.