Skip to content

Commit cea091b

Browse files
committed
Breadcrumb component
1 parent 6224a11 commit cea091b

File tree

1 file changed

+364
-6
lines changed
  • src/ECER.Clients.RegistryPortal/ecer.clients.registryportal.client/src/components

1 file changed

+364
-6
lines changed

src/ECER.Clients.RegistryPortal/ecer.clients.registryportal.client/src/components/Breadcrumb.vue

Lines changed: 364 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,383 @@
11
<template>
2-
<v-breadcrumbs class="pl-0" :items="items" color="primary">
2+
<v-breadcrumbs class="pl-0" :items="breadcrumbItems" color="primary">
33
<template #divider>/</template>
44
</v-breadcrumbs>
55
</template>
66

77
<script lang="ts">
8-
import { defineComponent, type PropType } from "vue";
8+
import { defineComponent } from "vue";
9+
import { useRoute } from "vue-router";
10+
import { useApplicationStore } from "@/store/application";
11+
import { useUserStore } from "@/store/user";
912
1013
export interface ItemsType {
1114
title: string;
1215
disabled: boolean;
1316
href: string;
1417
}
1518
19+
export interface BreadcrumbItem extends ItemsType {
20+
routeName?: string; // Add routeName to track which route this represents
21+
}
22+
1623
export default defineComponent({
1724
name: "Breadcrumb",
1825
components: {},
19-
props: {
20-
items: {
21-
type: Array as PropType<ItemsType[]>,
22-
required: true,
26+
setup() {
27+
const route = useRoute();
28+
const applicationStore = useApplicationStore();
29+
const userStore = useUserStore();
30+
31+
return { route, applicationStore, userStore };
32+
},
33+
computed: {
34+
isUnder19InApplication(): boolean {
35+
return (
36+
this.userStore.isUnder19 &&
37+
(this.applicationStore.hasDraftApplication ||
38+
this.route.name === "application-certification" ||
39+
this.route.name === "application-requirements" ||
40+
this.route.name === "declaration" ||
41+
this.route.name === "consent-required")
42+
);
43+
},
44+
baseItems(): ItemsType[] {
45+
return [{ title: "Home", disabled: false, href: "/" }];
46+
},
47+
addConsentStep() {
48+
return (items: ItemsType[]): ItemsType[] => {
49+
if (this.isUnder19InApplication) {
50+
// Find the index of the "Requirements" item
51+
const requirementsIndex = items.findIndex((item) => item.title === "Requirements");
52+
if (requirementsIndex !== -1) {
53+
// Insert "Consent required" immediately before "Requirements"
54+
const beforeRequirements = items.slice(0, requirementsIndex);
55+
const afterRequirements = items.slice(requirementsIndex);
56+
return [...beforeRequirements, { title: "Consent required", disabled: false, href: "/application/consent-required" }, ...afterRequirements];
57+
}
58+
}
59+
return items;
60+
};
61+
},
62+
63+
// Define the ranking for application pages
64+
applicationPageRankings(): Record<string, number> {
65+
return {
66+
"application-certification": 1,
67+
"application-transfer": 1, // Same rank as certification since they're alternatives
68+
"consent-required": 2,
69+
"application-requirements": 3,
70+
declaration: 4,
71+
};
72+
},
73+
// Helper to insert items at correct position based on ranking
74+
insertAtCorrectRank() {
75+
return (items: BreadcrumbItem[], newItem: BreadcrumbItem): BreadcrumbItem[] => {
76+
const rank = this.applicationPageRankings[newItem.routeName || ""];
77+
if (rank === undefined) {
78+
// If no rank, append to end
79+
return [...items, newItem];
80+
}
81+
82+
// Find the correct position based on rank
83+
let insertIndex = items.length;
84+
for (let i = 0; i < items.length; i++) {
85+
const itemRank = this.applicationPageRankings[items[i].routeName || ""];
86+
if (itemRank !== undefined && itemRank > rank) {
87+
insertIndex = i;
88+
break;
89+
}
90+
}
91+
92+
// Insert at the correct position
93+
const before = items.slice(0, insertIndex);
94+
const after = items.slice(insertIndex);
95+
return [...before, newItem, ...after];
96+
};
97+
},
98+
// Build application breadcrumbs using ranking
99+
buildApplicationBreadcrumbs(): ItemsType[] {
100+
let items: BreadcrumbItem[] = [...this.baseItems];
101+
102+
// Add pages based on current route and application state
103+
const pagesToAdd: BreadcrumbItem[] = [];
104+
const currentRouteName = this.route.name as string;
105+
106+
// Add certification type selection (for new applications)
107+
if (!this.applicationStore.isDraftApplicationRenewal && !this.applicationStore.isDraftApplicationLaborMobility) {
108+
const step = {
109+
title: "Apply for new certification",
110+
disabled: currentRouteName === "application-certification",
111+
href: "/application/certification",
112+
routeName: "application-certification",
113+
};
114+
pagesToAdd.push(step);
115+
if (currentRouteName === "application-certification") {
116+
// We're on this step, so stop adding future steps
117+
pagesToAdd.forEach((page) => {
118+
items = this.insertAtCorrectRank(items, page);
119+
});
120+
return items;
121+
}
122+
}
123+
124+
// Add transfer eligibility (for labor mobility)
125+
if (this.applicationStore.isDraftApplicationLaborMobility) {
126+
const step = {
127+
title: "Check your transfer eligibility",
128+
disabled: currentRouteName === "application-transfer",
129+
href: "/application/transfer",
130+
routeName: "application-transfer",
131+
};
132+
pagesToAdd.push(step);
133+
if (currentRouteName === "application-transfer") {
134+
pagesToAdd.forEach((page) => {
135+
items = this.insertAtCorrectRank(items, page);
136+
});
137+
return items;
138+
}
139+
}
140+
141+
// Add consent required (for under 19)
142+
if (this.isUnder19InApplication) {
143+
const step = {
144+
title: "Consent required",
145+
disabled: currentRouteName === "consent-required",
146+
href: "/application/consent-required",
147+
routeName: "consent-required",
148+
};
149+
pagesToAdd.push(step);
150+
if (currentRouteName === "consent-required") {
151+
pagesToAdd.forEach((page) => {
152+
items = this.insertAtCorrectRank(items, page);
153+
});
154+
return items;
155+
}
156+
}
157+
158+
// Add requirements
159+
const requirementsStep = {
160+
title: "Requirements",
161+
disabled: currentRouteName === "application-requirements",
162+
href: "/application/certification/requirements",
163+
routeName: "application-requirements",
164+
};
165+
pagesToAdd.push(requirementsStep);
166+
if (currentRouteName === "application-requirements") {
167+
pagesToAdd.forEach((page) => {
168+
items = this.insertAtCorrectRank(items, page);
169+
});
170+
return items;
171+
}
172+
173+
// Add declaration
174+
const declarationStep = {
175+
title: "Declaration",
176+
disabled: currentRouteName === "declaration",
177+
href: "/application/declaration",
178+
routeName: "declaration",
179+
};
180+
pagesToAdd.push(declarationStep);
181+
if (currentRouteName === "declaration") {
182+
pagesToAdd.forEach((page) => {
183+
items = this.insertAtCorrectRank(items, page);
184+
});
185+
return items;
186+
}
187+
188+
// If we get here, we're on a route that's not in our defined flow
189+
// Just add all the steps we've collected
190+
pagesToAdd.forEach((page) => {
191+
items = this.insertAtCorrectRank(items, page);
192+
});
193+
194+
return items;
195+
},
196+
197+
breadcrumbItems(): ItemsType[] {
198+
// For application-related routes, use the ranking system
199+
if (this.isApplicationRoute(this.route.name as string)) {
200+
return this.buildApplicationBreadcrumbs;
201+
}
202+
203+
// For other routes, use the existing switch statement
204+
return this.generateBreadcrumbs(this.route.name as string, this.route.params as Record<string, string>);
205+
},
206+
},
207+
methods: {
208+
generateBreadcrumbs(routeName: string, params: Record<string, string | string[]>): ItemsType[] {
209+
switch (routeName) {
210+
case "certification-requirements":
211+
return [...this.baseItems, { title: "Certification requirements", disabled: true, href: "/certification-requirements" }];
212+
213+
case "viewComprehensiveReport":
214+
return [
215+
...this.baseItems,
216+
{ title: "Application", disabled: false, href: `/manage-application/${params.applicationId}` },
217+
{
218+
title: "Comprehensive Report",
219+
disabled: true,
220+
href: `/manage-application/${params.applicationId}/transcript/${params.transcriptId}/comprehensive-evaluation`,
221+
},
222+
];
223+
224+
case "viewCourseOutline":
225+
return [
226+
...this.baseItems,
227+
{ title: "Application", disabled: false, href: `/manage-application/${params.applicationId}` },
228+
{
229+
title: "Course outlines or syllabi",
230+
disabled: true,
231+
href: `/manage-application/${params.applicationId}/transcript/${params.transcriptId}/course-outline`,
232+
},
233+
];
234+
235+
case "viewProgramConfirmation":
236+
return [
237+
...this.baseItems,
238+
{ title: "Application", disabled: false, href: `/manage-application/${params.applicationId}` },
239+
{
240+
title: "Program confirmation",
241+
disabled: true,
242+
href: `/manage-application/${params.applicationId}/transcript/${params.transcriptId}/program-confirmation`,
243+
},
244+
];
245+
246+
case "viewTranscriptDetails":
247+
return [
248+
...this.baseItems,
249+
{ title: "Application", disabled: false, href: `/manage-application/${params.applicationId}` },
250+
{ title: "Transcript", disabled: true, href: `/manage-application/${params.applicationId}/transcript/${params.transcriptId}` },
251+
];
252+
253+
case "view-character-reference":
254+
return [
255+
...this.baseItems,
256+
{ title: "Application", disabled: false, href: `/manage-application/${params.applicationId}` },
257+
{ title: "Character reference", disabled: true, href: `/manage-application/${params.applicationId}/character-reference/${params.referenceId}` },
258+
];
259+
260+
// Manage work experience references
261+
262+
case "addCharacterReference":
263+
return [
264+
...this.baseItems,
265+
{ title: "Application", disabled: false, href: `/manage-application/${params.applicationId}` },
266+
{ title: "Add", disabled: true, href: `/manage-application/${params.applicationId}/character-reference/add` },
267+
];
268+
case "updateCharacterReference":
269+
return [
270+
...this.baseItems,
271+
{ title: "Application", disabled: false, href: `/manage-application/${params.applicationId}` },
272+
{ title: "Character reference", disabled: false, href: `/manage-application/${params.applicationId}/character-reference/${params.referenceId}` },
273+
{ title: "Add", disabled: true, href: `/manage-application/${params.applicationId}/character-reference/${params.referenceId}/edit` },
274+
];
275+
276+
// Manage work experience references
277+
case "viewWorkExperienceReference":
278+
return [
279+
...this.baseItems,
280+
{ title: "Application", disabled: false, href: `/manage-application/${params.applicationId}` },
281+
{
282+
title: "Work experience reference",
283+
disabled: true,
284+
href: `/manage-application/${params.applicationId}/work-experience-reference/${params.referenceId}`,
285+
},
286+
];
287+
case "manageWorkExperienceReferences":
288+
return [
289+
...this.baseItems,
290+
{ title: "Application", disabled: false, href: `/manage-application/${params.applicationId}` },
291+
{ title: "Work experience references", disabled: true, href: `/manage-application/${params.applicationId}/work-experience-references` },
292+
];
293+
case "addWorkExperienceReference":
294+
return [
295+
...this.baseItems,
296+
{ title: "Application", disabled: false, href: `/manage-application/${params.applicationId}` },
297+
{
298+
title: "Work experience reference",
299+
disabled: false,
300+
href: `/manage-application/${params.applicationId}/work-experience-references`,
301+
},
302+
{ title: "Add", disabled: true, href: `/manage-application/${params.applicationId}/work-experience-reference/add` },
303+
];
304+
case "updateWorkExperienceReference":
305+
return [
306+
...this.baseItems,
307+
{ title: "Application", disabled: false, href: `/manage-application/${params.applicationId}` },
308+
{
309+
title: "Work experience reference",
310+
disabled: false,
311+
href: `/manage-application/${params.applicationId}/work-experience-reference/${params.referenceId}`,
312+
},
313+
{ title: "Add", disabled: true, href: `/manage-application/${params.applicationId}/work-experience-reference/${params.referenceId}/edit` },
314+
];
315+
case "manageProfessionalDevelopment":
316+
return [
317+
...this.baseItems,
318+
{ title: "Application", disabled: false, href: `/manage-application/${params.applicationId}` },
319+
{ title: "Professional development", disabled: true, href: `/manage-application/${params.applicationId}/professional-development` },
320+
];
321+
case "addProfessionalDevelopment":
322+
return [
323+
...this.baseItems,
324+
{ title: "Application", disabled: false, href: `/manage-application/${params.applicationId}` },
325+
{ title: "Professional development", disabled: false, href: `/manage-application/${params.applicationId}/professional-development` },
326+
{ title: "Add", disabled: true, href: `/manage-application/${params.applicationId}/professional-development/add` },
327+
];
328+
case "add-previous-name":
329+
return [
330+
...this.baseItems,
331+
{ title: "Profile", disabled: false, href: "/profile" },
332+
{ title: "Add previous name", disabled: true, href: "/profile/add-previous-name" },
333+
];
334+
335+
case "verify-previous-name":
336+
return [
337+
...this.baseItems,
338+
{ title: "Profile", disabled: false, href: "/profile" },
339+
{ title: "Verify previous name", disabled: true, href: `/profile/verify-previous-name/${params.previousNameId}` },
340+
];
341+
342+
case "edit-profile":
343+
return [...this.baseItems, { title: "Profile", disabled: false, href: "/profile" }, { title: "Edit profile", disabled: true, href: "/profile/edit" }];
344+
345+
case "verifyIdentification":
346+
return [...this.baseItems, { title: "Verify identification", disabled: true, href: "/verify-identification" }];
347+
348+
case "createAccount":
349+
return [...this.baseItems, { title: "Create account", disabled: true, href: "/create-account" }];
350+
351+
case "certificate-terms-and-conditions":
352+
return [...this.baseItems, { title: "Terms and conditions", disabled: true, href: `/certificate-terms-and-conditions/${params.certificationId}` }];
353+
354+
case "my-other-certifications":
355+
return [...this.baseItems, { title: "My other certifications", disabled: true, href: "/my-other-certifications" }];
356+
357+
case "profile":
358+
return [...this.baseItems, { title: "Profile", disabled: true, href: "/profile" }];
359+
360+
case "messages":
361+
return [...this.baseItems, { title: "Messages", disabled: true, href: "/messages" }];
362+
363+
case "replyToMessage":
364+
return [
365+
...this.baseItems,
366+
{ title: "Messages", disabled: false, href: "/messages" },
367+
{ title: "Reply to message", disabled: true, href: `/messages/${params.messageId}/reply` },
368+
];
369+
370+
case "manageApplication":
371+
return [...this.baseItems, { title: "Application", disabled: true, href: `/manage-application/${params.applicationId}` }];
372+
373+
default:
374+
return this.baseItems;
375+
}
376+
},
377+
378+
// Helper to check if current route is application-related
379+
isApplicationRoute(routeName: string): boolean {
380+
return ["application-certification", "application-transfer", "application-requirements", "consent-required", "declaration"].includes(routeName);
23381
},
24382
},
25383
});

0 commit comments

Comments
 (0)