Skip to content

Commit

Permalink
Merge pull request #139 from dimak1/feat/breadcrumb
Browse files Browse the repository at this point in the history
Add Breadcrumb Across the App
  • Loading branch information
dimak1 authored Sep 16, 2024
2 parents 199b609 + 0564ddc commit fd3ca50
Show file tree
Hide file tree
Showing 21 changed files with 307 additions and 20 deletions.
4 changes: 4 additions & 0 deletions strr-web/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ export default defineAppConfig({
ring: 'before:ring-1 before:ring-gray-700',
background: 'before:bg-gray-700'
}
},
breadcrumb: {
label: 'text-white font-normal text-decoration-line',
base: 'text-white font-normal hover:text-white'
}
}
})
27 changes: 27 additions & 0 deletions strr-web/components/Breadcrumb.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script setup lang="ts">
const { getBreadcrumbLinks, isDashboardButtonDisabled, isBreadcrumbVisible, dashboardButtonLink } = useBreadcrumb()
</script>

<template>
<div
v-if="isBreadcrumbVisible"
class="flex justify-center min-h-[52px] bg-bcGovColor-nonClickable"
data-test-id="breadcrumb-trail"
>
<div class="flex max-w-[1360px] grow px-4 items-center gap-3">
<router-link
:to="isDashboardButtonDisabled ? '' : dashboardButtonLink"
class="flex"
:class="{ 'pointer-events-none': isDashboardButtonDisabled }"
>
<UIcon
name="i-mdi-arrow-left-circle"
class="size-7"
:class="isDashboardButtonDisabled ? 'text-blue-200' : 'text-white'"
/>
</router-link>
<UDivider orientation="vertical" class="h-6" />
<UBreadcrumb :links="getBreadcrumbLinks" class="flex" />
</div>
</div>
</template>
110 changes: 110 additions & 0 deletions strr-web/composables/useBreadcrumb.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import {
hostBreadcrumbs,
examinerBreadcrumbs
} from '~/page-data/breadcrumbs'

export const useBreadcrumb = () => {
const route = useRoute()
const strrStore = useStrrStore()
const { getApplicationId, getApplicationNickname, getRegistrationNumber } = storeToRefs(strrStore)
const { isExaminer } = useBcrosKeycloak()
const { t } = useTranslation()

const { setApplicationId, setApplicationNickname, setRegistrationNumber } = useStrrStore()

const NO_BREADCRUMB_ROUTES = [
RouteNamesE.TERMS_OF_SERVICE,
RouteNamesE.FINALIZATION,
RouteNamesE.ACCOUNT_SELECT,
RouteNamesE.APPLICATION_SUBMITTED
]

// set store values for breadcrumb
const setupBreadcrumbData = (application: ApplicationI) => {
setApplicationId(application?.header.id.toString())
setApplicationNickname(application?.registration.unitAddress.nickname)
setRegistrationNumber(application?.header.registrationNumber)
}

// Remove '-id' suffix and language codes (e.g., '___en') from route names to match RouteNamesE enum values
const cleanupRoute = (routeName: string) => {
return routeName?.replace(/(-id|___\w{2}$)/g, '') as RouteNamesE
}

/**
* Create breadcrumb links for the current route, including dynamic labels based on
* application or registration details.
*
* @returns {BreadcrumbI[]} An array of breadcrumb objects for the current route
*/
const getBreadcrumbLinks = computed((): BreadcrumbI[] => {
const routeName = route.name?.toString()

// cleanup route from locale and id suffix
const currentRouteName = cleanupRoute(routeName as RouteNamesE)

// get nickname or set as empty string
const nickname = getApplicationNickname.value ? `${getApplicationNickname.value}, ` : ''

// set base Breadcrumb based on role
const breadcrumbLinks = isExaminer
? [...(examinerBreadcrumbs[currentRouteName] || [])]
: [...(hostBreadcrumbs[currentRouteName] || [])]

// add custom Breadcrumb info based on current route
switch (currentRouteName) {
case RouteNamesE.APPLICATION_DETAILS:
breadcrumbLinks[1] = {
label: `${nickname}Application #${getApplicationId.value}`
}
break
case RouteNamesE.APPLICATION_DETAILS_LTSA:
case RouteNamesE.APPLICATION_DETAILS_AUTO_APPROVAL:
breadcrumbLinks[1] = {
label: `${nickname}Application #${getApplicationId.value}`,
to: `/${RouteNamesE.APPLICATION_DETAILS}/${getApplicationId.value}`
}
breadcrumbLinks[2] = {
label:
currentRouteName === RouteNamesE.APPLICATION_DETAILS_LTSA
? t('ltsa.ltsaDetails')
: t('autoApproval.automaticDetails')
}
break
case RouteNamesE.REGISTRATION_DETAILS:
breadcrumbLinks[1] = {
label: `${nickname}Registration #${getRegistrationNumber.value}`
}
break
}

return breadcrumbLinks
})

// Disable Dashboard Back Button when already at top route (eg Dashboard route)
const isDashboardButtonDisabled = computed((): boolean => {
return [RouteNamesE.REGISTRY_DASHBOARD, RouteNamesE.APPLICATION_STATUS].includes(
cleanupRoute(route.name?.toString() ?? '')
)
})

// Check if breadcrumbs should be visible on certain routes
const isBreadcrumbVisible = computed((): boolean =>
NO_BREADCRUMB_ROUTES.every(routeName => !route.name?.toString().startsWith(routeName))
)

// Set the back button link to navigate one level up in breadcrumb
const dashboardButtonLink = computed(():string => {
const breadcrumbLinks = getBreadcrumbLinks.value
// return second to last link for one level up
return breadcrumbLinks[breadcrumbLinks.length - 2]?.to || ''
})

return {
setupBreadcrumbData,
getBreadcrumbLinks,
isDashboardButtonDisabled,
dashboardButtonLink,
isBreadcrumbVisible
}
}
5 changes: 0 additions & 5 deletions strr-web/enums/route-name-e.ts

This file was deleted.

15 changes: 15 additions & 0 deletions strr-web/enums/route-names-e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export enum RouteNamesE {
CREATE_ACCOUNT = 'create-account',
APPLICATION_DETAILS = 'application-details',
APPLICATION_STATUS = 'application-status',
REGISTRY_DASHBOARD = 'registry-dashboard',
REGISTRATION_DETAILS = 'registration-details',
APPLICATION_DETAILS_LTSA = 'application-details-ltsa',
APPLICATION_DETAILS_AUTO_APPROVAL = 'application-details-auto-approval',

// No Breadcrumb routes
ACCOUNT_SELECT = 'account-select',
TERMS_OF_SERVICE = 'terms-of-service',
FINALIZATION = 'finalization',
APPLICATION_SUBMITTED = 'success'
}
8 changes: 8 additions & 0 deletions strr-web/interfaces/breadcrumb-i.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface BreadcrumbI {
label: string
to?: string
}

export type BreadcrumbsI = {
[key in RouteNamesE]: BreadcrumbI[]
}
3 changes: 1 addition & 2 deletions strr-web/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"autoApproval": {
"autoApprovalDetails": "Automatic Approval Details",
"automaticLogic": "Automatic Approval Logic",
"automaticDetails": "Automatic Approval Details",
"provisionalLogic": "Provisional Approval Logic",
"renting": "Renting",
"accommodationSelected": "Accommodation Service Provider Selected",
Expand Down Expand Up @@ -175,8 +176,6 @@
"links": "Helpful Links",
"status": "View your application status",
"dashboard": "in your dashboard",
"bcrosLink": "Visit your BC Registries Online Services profile page",
"update": "to update your profile information",
"haveAnotherProperty": "Have another rental property?",
"startNewApplication": "Start a new application"
},
Expand Down
1 change: 1 addition & 0 deletions strr-web/layouts/default.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<div data-test-id="default-layout">
<div class="flex justify-between flex-col min-h-screen">
<BcrosHeader />
<Breadcrumb />
<div class="flex grow justify-center relative">
<div class="w-[848px] py-[75px] mobile:py-[20px]">
<NuxtPage />
Expand Down
1 change: 1 addition & 0 deletions strr-web/layouts/wide.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<div data-test-id="default-layout">
<div class="flex justify-between flex-col min-h-screen">
<BcrosHeader />
<Breadcrumb />
<div class="flex grow justify-center">
<div class="grow pt-[75px] mobile:pt-[20px]">
<NuxtPage />
Expand Down
1 change: 1 addition & 0 deletions strr-web/layouts/wideNoSpace.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<div data-test-id="default-layout">
<div class="flex justify-between flex-col min-h-screen">
<BcrosHeader />
<Breadcrumb />
<div class="flex grow justify-center">
<div class="grow px-4 pt-[75px] mobile:pt-[20px] max-w-[1360px]">
<NuxtPage />
Expand Down
65 changes: 65 additions & 0 deletions strr-web/page-data/breadcrumbs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { RouteNamesE } from '~/enums/route-names-e'
import { BreadcrumbsI } from '~/interfaces/breadcrumb-i'

export const hostDashboardBreadcrumb: Array<BreadcrumbI> = [
{
label: 'My STR Registry Dashboard'
}
]

export const examinerDashboardBreadcrumb: Array<BreadcrumbI> = [
{
label: 'My CEU STR Registry Dashboard'
}
]

export const strRegistrationBreadcrumb: Array<BreadcrumbI> = [
{
label: 'My STR Registry Dashboard',
to: '/' + RouteNamesE.APPLICATION_STATUS
},
{
label: 'Short-Term Rental Registration'
}
]

export const applicationDetailsBreadcrumb: Array<BreadcrumbI> = [
{
label: 'My STR Registry Dashboard',
to: '/' + RouteNamesE.APPLICATION_STATUS
}
]

export const examinerApplicationDetailsBreadcrumb: Array<BreadcrumbI> = [
{
label: 'My CEU STR Registry Dashboard',
to: '/' + RouteNamesE.REGISTRY_DASHBOARD
}
]

export const examinerStrRegistrationBreadcrumb: Array<BreadcrumbI> = [
{
label: 'My CEU STR Registry Dashboard',
to: '/' + RouteNamesE.REGISTRY_DASHBOARD
},
{
label: 'Short-Term Rental Registration'
}
]

export const hostBreadcrumbs: Partial<BreadcrumbsI> = {
[RouteNamesE.APPLICATION_STATUS]: hostDashboardBreadcrumb,
[RouteNamesE.APPLICATION_DETAILS]: applicationDetailsBreadcrumb,
[RouteNamesE.CREATE_ACCOUNT]: strRegistrationBreadcrumb,
[RouteNamesE.REGISTRATION_DETAILS]: applicationDetailsBreadcrumb
}

export const examinerBreadcrumbs: Partial<BreadcrumbsI> = {
[RouteNamesE.APPLICATION_STATUS]: examinerDashboardBreadcrumb,
[RouteNamesE.REGISTRY_DASHBOARD]: examinerDashboardBreadcrumb,
[RouteNamesE.APPLICATION_DETAILS]: examinerApplicationDetailsBreadcrumb,
[RouteNamesE.APPLICATION_DETAILS_LTSA]: examinerApplicationDetailsBreadcrumb,
[RouteNamesE.APPLICATION_DETAILS_AUTO_APPROVAL]: examinerApplicationDetailsBreadcrumb,
[RouteNamesE.CREATE_ACCOUNT]: examinerStrRegistrationBreadcrumb,
[RouteNamesE.REGISTRATION_DETAILS]: examinerDashboardBreadcrumb
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,16 @@ const automaticRows = ref<{ [key: string]: string }[]>([])
const provisionalRows = ref<{ [key: string]: string }[]>([])
const { getAutoApproval, getApplication } = useApplications()
const { setupBreadcrumbData } = useBreadcrumb()
const applicationId = route.params.id.toString()
const application = await getApplication(applicationId)
const data: AutoApprovalDataI[] = await getAutoApproval(applicationId) || {} as AutoApprovalDataI[]
const applicationDetails: ApplicationDetailsI = application.registration
setupBreadcrumbData(application)
const buildAutomaticRows = (rowsData: AutoApprovalDataI[]) => {
if (!rowsData.length || !rowsData[0].record) {
return
Expand Down
6 changes: 6 additions & 0 deletions strr-web/pages/application-details/[id]/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,17 @@ const {
getDocument
} = useApplications()
const {
setupBreadcrumbData
} = useBreadcrumb()
const [application, applicationHistory]: [ApplicationI, FilingHistoryEventI[]] = await Promise.all([
getApplication(applicationId),
getApplicationHistory(applicationId)
])
setupBreadcrumbData(application)
const applicationDetails: ApplicationDetailsI = application.registration
// Get Supporting Documents from the Application response
Expand Down
3 changes: 3 additions & 0 deletions strr-web/pages/application-details/[id]/ltsa/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,15 @@ const tLtsa = (translationKey: string) => t(`ltsa.${translationKey}`)
const applicationId = route.params.id.toString()
const { getLtsa, getApplication } = useApplications()
const { setupBreadcrumbData } = useBreadcrumb()
const application = await getApplication(applicationId)
const formatDate = (date: Date) => date.toLocaleDateString('en-US')
const data: LtsaDataI[] = await getLtsa(applicationId) || {} as LtsaDataI[]
const applicationDetails: ApplicationDetailsI = application.registration
setupBreadcrumbData(application)
const ownerRows = data.length > 0
? [{
'Given Name': data[0].record.ownershipGroups[0].titleOwners[0].givenName,
Expand Down
4 changes: 0 additions & 4 deletions strr-web/pages/listing-details/[listingId].vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@
<!-- eslint-disable-next-line max-len -->
<a @click="navigateTo('/application-status')">{{ tApplicationConfirm('status') }}</a> {{ tApplicationConfirm('dashboard') }}
</p>
<p class="mb-[24px]">
<!-- eslint-disable-next-line max-len -->
<a @click="goToAccountInfo">{{ tApplicationConfirm('bcrosLink') }}</a> {{ tApplicationConfirm('update') }}
</p>
<p class="mb-[24px]">
{{ tApplicationConfirm('haveAnotherProperty') }}
</p>
Expand Down
8 changes: 8 additions & 0 deletions strr-web/pages/registration-details/[id]/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,11 @@ const regionNamesInEnglish = new Intl.DisplayNames(['en'], { type: 'region' })
const registrationId = route.params.id.toString()
const {
setRegistrationNumber,
setApplicationNickname
} = useStrrStore()
const downloadEventTypes = ['CERTIFICATE_ISSUED']
const {
Expand Down Expand Up @@ -282,6 +287,9 @@ const [application, history]: [RegistrationI, FilingHistoryEventI[]] = await Pro
getRegistrationHistory(registrationId)
])
setApplicationNickname(application.unitAddress.nickname)
setRegistrationNumber(application.registration_number || '')
// Get Supporting Documents from the Application response
const documents: DocumentUploadI[] = application.documents || []
Expand Down
8 changes: 0 additions & 8 deletions strr-web/pages/success/[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@
<!-- eslint-disable-next-line max-len -->
<a @click="navigateTo('/application-status')">{{ tApplicationConfirm('status') }}</a> {{ tApplicationConfirm('dashboard') }}
</p>
<p class="mb-[24px]">
<!-- eslint-disable-next-line max-len -->
<a @click="goToAccountInfo">{{ tApplicationConfirm('bcrosLink') }}</a> {{ tApplicationConfirm('update') }}
</p>
<p class="mb-[24px]">
{{ tApplicationConfirm('haveAnotherProperty') }}
</p>
Expand All @@ -53,10 +49,6 @@ const fetchedRegistration = ref()
const { t } = useTranslation()
const tApplicationConfirm = (translationKey: string) => t(`createAccount.applicationConfirm.${translationKey}`)
const {
goToAccountInfo
} = useBcrosNavigate()
const id = route.params.id
const apiURL = useRuntimeConfig().public.strrApiURL
Expand Down
Loading

0 comments on commit fd3ca50

Please sign in to comment.