From f7140fb098b09ef5a6dfb42421fa96b3a0248ced Mon Sep 17 00:00:00 2001 From: Wilson Wong Date: Thu, 25 Jul 2024 11:47:33 -0700 Subject: [PATCH] Implement project detail view, updates to project list view --- app/src/controllers/submission.ts | 1 + frontend/src/assets/variables.scss | 2 + .../housing/enquiry/EnquiryIntakeForm.vue | 11 +- .../housing/projects/ProjectsList.vue | 26 +- frontend/src/components/roadmap/Roadmap.vue | 51 ++- frontend/src/router/index.ts | 11 +- frontend/src/utils/enums/application.ts | 1 + frontend/src/utils/utils.ts | 31 ++ .../housing/enquiry/EnquiryIntakeView.vue | 3 + .../ProjectListView.vue} | 23 +- .../src/views/housing/project/ProjectView.vue | 384 ++++++++++++++++++ .../housing/submission/SubmissionView.vue | 4 +- 12 files changed, 492 insertions(+), 56 deletions(-) rename frontend/src/views/housing/{ProjectsView.vue => project/ProjectListView.vue} (85%) create mode 100644 frontend/src/views/housing/project/ProjectView.vue diff --git a/app/src/controllers/submission.ts b/app/src/controllers/submission.ts index bfcb262c..c837c6ae 100644 --- a/app/src/controllers/submission.ts +++ b/app/src/controllers/submission.ts @@ -400,6 +400,7 @@ const controller = { next: NextFunction ) => { try { + // TBD: Implement filtering so proponents can only search for their own submissions const response = await submissionService.searchSubmissions({ ...req.query, includeUser: isTruthy(req.query.includeUser) diff --git a/frontend/src/assets/variables.scss b/frontend/src/assets/variables.scss index de1bbfaa..59140a82 100644 --- a/frontend/src/assets/variables.scss +++ b/frontend/src/assets/variables.scss @@ -14,6 +14,8 @@ $app-hover: #4696EC; $app-outline-on-primary: #fff; $app-out-of-focus: #ccc; $app-error: #D8292F; +$app-green: #2e8540; +$app-grey: #868585; // highlighted sections, table rows $app-highlight-background: #d9e1e8; diff --git a/frontend/src/components/housing/enquiry/EnquiryIntakeForm.vue b/frontend/src/components/housing/enquiry/EnquiryIntakeForm.vue index 85ce7498..daadd566 100644 --- a/frontend/src/components/housing/enquiry/EnquiryIntakeForm.vue +++ b/frontend/src/components/housing/enquiry/EnquiryIntakeForm.vue @@ -1,7 +1,7 @@ diff --git a/frontend/src/components/roadmap/Roadmap.vue b/frontend/src/components/roadmap/Roadmap.vue index 4f87c1ba..9b03fbc6 100644 --- a/frontend/src/components/roadmap/Roadmap.vue +++ b/frontend/src/components/roadmap/Roadmap.vue @@ -11,7 +11,12 @@ import { roadmapService, userService } from '@/services'; import { useConfigStore, useSubmissionStore, useTypeStore } from '@/store'; import { PermitNeeded, PermitStatus } from '@/utils/enums/housing'; import { roadmapTemplate } from '@/utils/templates'; -import { delimitEmails, setEmptyStringsToNull } from '@/utils/utils'; +import { + delimitEmails, + getPermitTypeNamesByNeeded, + getPermitTypeNamesByStatus, + setEmptyStringsToNull +} from '@/utils/utils'; import type { Ref } from 'vue'; import type { Document } from '@/types'; @@ -85,19 +90,19 @@ const confirmSubmit = (data: any) => { }); }; -function getPermitTypeNamesByStatus(status: string) { - return getPermits.value - .map((p) => getPermitTypes.value.find((pt) => pt.permitTypeId === p.permitTypeId && p.status === status)?.name) - .filter((pt) => !!pt) - .map((name) => name as string); -} +// function getPermitTypeNamesByStatus(status: string) { +// return getPermits.value +// .map((p) => getPermitTypes.value.find((pt) => pt.permitTypeId === p.permitTypeId && p.status === status)?.name) +// .filter((pt) => !!pt) +// .map((name) => name as string); +// } -function getPermitTypeNamesByNeeded(needed: string) { - return getPermits.value - .map((p) => getPermitTypes.value.find((pt) => pt.permitTypeId === p.permitTypeId && p.needed === needed)?.name) - .filter((pt) => !!pt) - .map((name) => name as string); -} +// function getPermitTypeNamesByNeeded(needed: string) { +// return getPermits.value +// .map((p) => getPermitTypes.value.find((pt) => pt.permitTypeId === p.permitTypeId && p.needed === needed)?.name) +// .filter((pt) => !!pt) +// .map((name) => name as string); +// } function onFileRemove(document: Document) { selectedFiles.value = selectedFiles.value.filter((x) => x.documentId !== document.documentId); @@ -132,14 +137,22 @@ watchEffect(async () => { } // Permits - const permitStateNew = getPermitTypeNamesByStatus(PermitStatus.NEW).filter((value) => - getPermitTypeNamesByNeeded(PermitNeeded.YES).includes(value) + const permitStateNew = getPermitTypeNamesByStatus(PermitStatus.NEW, getPermits.value, getPermitTypes.value).filter( + (value) => getPermitTypeNamesByNeeded(PermitNeeded.YES, getPermits.value, getPermitTypes.value).includes(value) + ); + const permitPossiblyNeeded = getPermitTypeNamesByStatus( + PermitStatus.NEW, + getPermits.value, + getPermitTypes.value + ).filter((value) => + getPermitTypeNamesByNeeded(PermitNeeded.UNDER_INVESTIGATION, getPermits.value, getPermitTypes.value).includes(value) ); - const permitPossiblyNeeded = getPermitTypeNamesByStatus(PermitStatus.NEW).filter((value) => - getPermitTypeNamesByNeeded(PermitNeeded.UNDER_INVESTIGATION).includes(value) + const permitStateApplied = getPermitTypeNamesByStatus(PermitStatus.APPLIED, getPermits.value, getPermitTypes.value); + const permitStateCompleted = getPermitTypeNamesByStatus( + PermitStatus.COMPLETED, + getPermits.value, + getPermitTypes.value ); - const permitStateApplied = getPermitTypeNamesByStatus(PermitStatus.APPLIED); - const permitStateCompleted = getPermitTypeNamesByStatus(PermitStatus.COMPLETED); const body = roadmapTemplate({ '{{ contactName }}': diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index a1d5c619..4d04dedf 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -101,7 +101,16 @@ const routes: Array = [ { path: 'projects', name: RouteName.HOUSING_PROJECTS, - component: () => import('@/views/housing/ProjectsView.vue'), + component: () => import('@/views/housing/project/ProjectListView.vue'), + meta: { + access: [Permissions.NAVIGATION_HOUSING] + } + }, + { + path: 'project', + name: RouteName.HOUSING_PROJECT, + component: () => import('@/views/housing/project/ProjectView.vue'), + props: createProps, meta: { access: [Permissions.NAVIGATION_HOUSING] } diff --git a/frontend/src/utils/enums/application.ts b/frontend/src/utils/enums/application.ts index 031282cd..114b4a66 100644 --- a/frontend/src/utils/enums/application.ts +++ b/frontend/src/utils/enums/application.ts @@ -44,6 +44,7 @@ export enum RouteName { HOUSING_ENQUIRY = 'housing_enquiry', HOUSING_ENQUIRY_INTAKE = 'housing_enquiry_intake', HOUSING_GUIDE = 'housing_guide', + HOUSING_PROJECT = 'housing_project', HOUSING_PROJECTS = 'housing_projects', HOUSING_SUBMISSION = 'housing_submission', HOUSING_SUBMISSION_INTAKE = 'housing_submission_intake', diff --git a/frontend/src/utils/utils.ts b/frontend/src/utils/utils.ts index 7c131d10..a8ae9a77 100644 --- a/frontend/src/utils/utils.ts +++ b/frontend/src/utils/utils.ts @@ -113,6 +113,37 @@ export function getFilenameAndExtension(filename: string): { filename: string; e return { filename, extension: undefined }; } } +import type { Permit, PermitType } from '@/types'; + +/** + * @function getPermitTypeNamesByStatus + * Returns an array of permits joined by permit types, filters by status, and returns the names + * @param {string} status permit status to be filtered for + * @param {Array} permits array of permits needing filtering for name + * @param {Array} permitTypes arry of permit types with names + * @returns {filename: string, extension: string} An object containing filename and extension + */ +export function getPermitTypeNamesByStatus(status: string, permits: Array, permitTypes: Array) { + return permits + .map((p) => permitTypes.find((pt) => pt.permitTypeId === p.permitTypeId && p.status === status)?.name) + .filter((pt) => !!pt) + .map((name) => name as string); +} + +/** + * @function getPermitTypeNamesByStatus + * Returns an array of permits joined by permit types, filters by needed, and returns the names + * @param {string} status permit status to be filtered for + * @param {Array} permits array of permits needing filtering for name + * @param {Array} permitTypes arry of permit types with names + * @returns {filename: string, extension: string} An object containing filename and extension + */ +export function getPermitTypeNamesByNeeded(needed: string, permits: Array, permitTypes: Array) { + return permits + .map((p) => permitTypes.find((pt) => pt.permitTypeId === p.permitTypeId && p.needed === needed)?.name) + .filter((pt) => !!pt) + .map((name) => name as string); +} /** * @function isDebugMode diff --git a/frontend/src/views/housing/enquiry/EnquiryIntakeView.vue b/frontend/src/views/housing/enquiry/EnquiryIntakeView.vue index 83d499f3..64233b84 100644 --- a/frontend/src/views/housing/enquiry/EnquiryIntakeView.vue +++ b/frontend/src/views/housing/enquiry/EnquiryIntakeView.vue @@ -8,11 +8,13 @@ import type { Ref } from 'vue'; // Props type Props = { activityId?: string; + confirmationId?: string; enquiryId?: string; }; const props = withDefaults(defineProps(), { activityId: undefined, + confirmationId: undefined, enquiryId: undefined }); @@ -29,6 +31,7 @@ onMounted(async () => { diff --git a/frontend/src/views/housing/ProjectsView.vue b/frontend/src/views/housing/project/ProjectListView.vue similarity index 85% rename from frontend/src/views/housing/ProjectsView.vue rename to frontend/src/views/housing/project/ProjectListView.vue index a2b3268d..c468db21 100644 --- a/frontend/src/views/housing/ProjectsView.vue +++ b/frontend/src/views/housing/project/ProjectListView.vue @@ -2,10 +2,10 @@ import { onMounted, ref } from 'vue'; import { useRouter } from 'vue-router'; +import ProjectsList from '@/components/housing/projects/ProjectsList.vue'; import { Button } from '@/lib/primevue'; import { RouteName } from '@/utils/enums/application'; import { ApplicationStatus, IntakeStatus, SubmissionType } from '@/utils/enums/housing'; -import ProjectsList from '@/components/housing/projects/ProjectsList.vue'; import { submissionService } from '@/services'; import type { Ref } from 'vue'; @@ -70,21 +70,22 @@ onMounted(async () => { / Applications and Permits -

Application and Permits

-
-

My Projects

-
-
{{ submissions.map((x) => x.submittedAt) }}
diff --git a/frontend/src/views/housing/submission/SubmissionView.vue b/frontend/src/views/housing/submission/SubmissionView.vue index f69fc594..61a2c65e 100644 --- a/frontend/src/views/housing/submission/SubmissionView.vue +++ b/frontend/src/views/housing/submission/SubmissionView.vue @@ -204,8 +204,8 @@ const onDeleteNote = (note: Note) => { :sort-field="SORT_TYPES.CREATED_AT" :sort-order="SORT_ORDER.DESCENDING" @update:sort-order=" - (order: number) => { - sortOrder = order; + (order: number | undefined) => { + sortOrder = order ?? SORT_ORDER.DESCENDING; } " @update:sort-field="