Skip to content

Commit

Permalink
UI - finished drafts
Browse files Browse the repository at this point in the history
Signed-off-by: Kial Jinnah <[email protected]>
  • Loading branch information
kialj876 committed Jan 10, 2025
1 parent b42c3cc commit d5f8691
Show file tree
Hide file tree
Showing 22 changed files with 271 additions and 131 deletions.
1 change: 1 addition & 0 deletions strr-base-web/app/interfaces/strr-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export interface ApplicationHeader {
isCertificateIssued: boolean
name: string
paymentAccount: string
paymentMethod: ConnectPaymentMethod
paymentStatus: string
paymentToken: number // invoice id
status: ApplicationStatus
Expand Down
1 change: 1 addition & 0 deletions strr-base-web/app/locales/en-CA.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default {
inactiveAccount: 'INACTIVE ACCOUNT'
},
btn: {
ariaResumeDraft: 'Resume Draft for {number}',
done: 'Done',
getStarted: 'Get Started',
goHome: 'Go Home',
Expand Down
6 changes: 3 additions & 3 deletions strr-base-web/app/utils/formattingHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ export function formatParty <T extends Contact> (party: T): ApiParty {

export function formatPartyUI <T extends ApiParty> (party: T): Contact {
return {
lastName: party.lastName,
firstName: party.firstName || '',
lastName: party.lastName || '',
middleName: party.middleName || '',
emailAddress: party.emailAddress,
phone: formatPhoneNumberUI(party),
...(party.firstName ? { firstName: party.firstName } : {}),
...(party.middleName ? { middleName: party.middleName } : {}),
...(party.preferredName ? { preferredName: party.preferredName } : {}),
...(party.faxNumber ? { faxNumber: party.faxNumber } : {})
}
Expand Down
5 changes: 4 additions & 1 deletion strr-base-web/app/utils/todoItems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ export const getTodoApplication = (
if (applicationInfo) { // TODO: alert if no application info
// pass application number so that the application form can load in the saved data
await navigateTo(
{ path: localePath(applicationPath), query: { applicationId: applicationInfo.applicationNumber } }
{
path: localePath(applicationPath),
query: { override: 'true', applicationId: applicationInfo.applicationNumber }
}
)
}
}
Expand Down
3 changes: 2 additions & 1 deletion strr-host-pm-web/app/interfaces/host-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ export interface ApiHostApplication {
}

export interface HostApplicationPayload {
registration: ApiHostApplication
// Draft applications will not have all fields defined yet
registration: Partial<ApiHostApplication>
}

export interface HostApplicationResp extends HostApplicationPayload {
Expand Down
1 change: 0 additions & 1 deletion strr-host-pm-web/app/locales/en-CA.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,6 @@ export default {
showDetails: 'Show Details',
hideDetails: 'Hide Details',
returnToStep: 'Return to the step to finish it',
ariaResumeDraft: 'Resume Draft for {number}',
ariaViewDetails: 'View details for property: {name}, {address}',
registerAStr: 'Register a Short-Term Rental'
},
Expand Down
11 changes: 6 additions & 5 deletions strr-host-pm-web/app/pages/application.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const {
} = useHostApplicationStore()
const permitStore = useHostPermitStore()
const applicationId = route.query.applicationId as string
const applicationId = ref(route.query.applicationId as string)
const loading = ref(false)
// fee stuff
Expand All @@ -42,8 +42,8 @@ const hostFee3 = ref<ConnectFeeItem | undefined>(undefined)
onMounted(async () => {
loading.value = true
applicationReset()
if (applicationId) {
await permitStore.loadHostData(applicationId, true)
if (applicationId.value) {
await permitStore.loadHostData(applicationId.value, true)
}
const [fee1, fee2] = await Promise.all([
getFee(StrrFeeEntityType.STRR, StrrFeeCode.STR_HOST_1),
Expand Down Expand Up @@ -140,10 +140,11 @@ const saveApplication = async (resumeLater = false) => {
handleButtonLoading(false, 'left', resumeLater ? 1 : 2)
// prevent flicker of buttons by waiting half a second
try {
await Promise.all([
const [, { filingId }] = await Promise.all([
new Promise(resolve => setTimeout(resolve, 500)),
submitApplication(true, applicationId)
submitApplication(true, applicationId.value)
])
applicationId.value = filingId
if (resumeLater) {
await navigateTo(localePath('/dashboard'))
}
Expand Down
5 changes: 4 additions & 1 deletion strr-host-pm-web/app/stores/hostApplication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ export const useHostApplicationStore = defineStore('host/application', () => {
return {
registration: {
registrationType: ApplicationType.HOST,
primaryContact: formatOwnerHostAPI(host as HostOwner),
...(host
? { primaryContact: formatOwnerHostAPI(host as HostOwner) }
: {}
),
...(cohost
? { secondaryContact: formatOwnerHostAPI(cohost) }
: {}
Expand Down
16 changes: 9 additions & 7 deletions strr-host-pm-web/app/stores/hostPermit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ export const useHostPermitStore = defineStore('host/permit', () => {
await loadPermitData(applicationId)
if (showPermitDetails.value || loadDraft) {
// set sub store values
hostOwners.value.push(formatOwnerHostUI(
permitDetails.value.primaryContact,
!permitDetails.value.propertyManager?.initiatedByPropertyManager
))
if (permitDetails.value.primaryContact) {
hostOwners.value.push(formatOwnerHostUI(
permitDetails.value.primaryContact,
!permitDetails.value.propertyManager?.initiatedByPropertyManager
))
}
if (permitDetails.value.secondaryContact) {
hostOwners.value.push(formatOwnerHostUI(permitDetails.value.secondaryContact, false, true))
}
Expand All @@ -43,10 +45,10 @@ export const useHostPermitStore = defineStore('host/permit', () => {
unitDetails.value = formatHostUnitDetailsUI(permitDetails.value.unitDetails)
blInfo.value = formatHostUnitDetailsBlInfoUI(permitDetails.value.unitDetails)
unitAddress.value = { address: formatHostUnitAddressUI(permitDetails.value.unitAddress) }
showUnitDetailsForm.value = !!unitAddress.value?.address?.streetName
showUnitDetailsForm.value = !!unitAddress.value.address.street || !!unitAddress.value.address.streetAdditional
prRequirements.value.isPropertyPrExempt = !!permitDetails.value.unitDetails.prExemptReason
prRequirements.value.prExemptionReason = permitDetails.value.unitDetails.prExemptReason
if (application.value?.registration.strRequirements && unitAddress.value?.address?.streetName) {
if (application.value?.registration.strRequirements && showUnitDetailsForm.value) {
propertyReqs.value = application.value?.registration.strRequirements
if (Object.keys(application.value.registration.strRequirements).length === 0) {
// run the requirements check again in case it has errors (errors are not saved by the api)
Expand Down Expand Up @@ -75,7 +77,7 @@ export const useHostPermitStore = defineStore('host/permit', () => {
}).then((response) => {
if (response) {
return (response as HostApplicationResp[]).map(app => ({
name: app.registration.unitAddress.nickname || t('label.unnamed'),
name: app.registration.unitAddress?.nickname || t('label.unnamed'),
address: app.registration.unitAddress,
number: app.header.registrationNumber || app.header.applicationNumber,
date: app.header.registrationStartDate || app.header.applicationDateTime,
Expand Down
2 changes: 1 addition & 1 deletion strr-host-pm-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "strr-host-pm-web",
"private": true,
"type": "module",
"version": "0.0.33",
"version": "0.0.34",
"scripts": {
"build-check": "nuxt build",
"build": "nuxt generate",
Expand Down
1 change: 1 addition & 0 deletions strr-platform-web/app/interfaces/platform-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface PlatformRegistrationResp extends ApiBasePlatformRegistration, A
}

export interface PlatformApplicationPayload {
header: { paymentMethod: ConnectPaymentMethod }
registration: ApiBasePlatformApplication
}

Expand Down
92 changes: 51 additions & 41 deletions strr-platform-web/app/pages/platform/application.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
import { ConnectStepper, FormPlatformReviewConfirm } from '#components'
const { t } = useI18n()
const route = useRoute()
const localePath = useLocalePath()
const strrModal = useStrrModals()
const { handlePaymentRedirect } = useConnectNav()
const { setButtonControl } = useButtonControl()
const { setButtonControl, handleButtonLoading } = useButtonControl()
const ldStore = useConnectLaunchdarklyStore()
const { validateContact } = useStrrContactStore()
const { validatePlatformBusiness } = useStrrPlatformBusiness()
Expand All @@ -15,6 +17,11 @@ const {
validatePlatformConfirmation,
$reset: applicationReset
} = useStrrPlatformApplication()
const permitStore = useStrrPlatformStore()
const applicationId = ref(route.query.applicationId as string)
const loading = ref(false)
// fee stuff
const {
addReplaceFee,
Expand All @@ -31,9 +38,13 @@ const platFeeSm = ref<ConnectFeeItem | undefined>(undefined)
const platFeeLg = ref<ConnectFeeItem | undefined>(undefined)
const platFeeWv = ref<ConnectFeeItem | undefined>(undefined)
onMounted(async () => {
loading.value = true
await initAlternatePaymentMethod()
applicationReset()
if (applicationId.value) {
await permitStore.loadPlatform(applicationId.value, true)
}
const [smallFeeResp, largeFeeResp, waivedFeeResp] = await Promise.all([
getFee(StrrFeeEntityType.STRR, StrrFeeCode.STR_PLAT_SM),
getFee(StrrFeeEntityType.STRR, StrrFeeCode.STR_PLAT_LG),
Expand All @@ -51,6 +62,7 @@ onMounted(async () => {
platFeeWv.value.serviceFees = platFeeSm.value.serviceFees
setPlaceholderServiceFee(platFeeSm.value.serviceFees)
}
loading.value = false
})
const { platformDetails } = storeToRefs(useStrrPlatformDetails())
Expand Down Expand Up @@ -122,31 +134,31 @@ const activeStep = ref<Step>(steps.value[activeStepIndex.value] as Step)
const stepperRef = shallowRef<InstanceType<typeof ConnectStepper> | null>(null)
const reviewFormRef = shallowRef<InstanceType<typeof FormPlatformReviewConfirm> | null>(null)
// need to cleanup the setButtonControl somehow
const saveApplication = async (resumeLater = false) => {
handleButtonLoading(false, 'left', resumeLater ? 1 : 2)
// prevent flicker of buttons by waiting half a second
try {
const [, { filingId }] = await Promise.all([
new Promise(resolve => setTimeout(resolve, 500)),
submitPlatformApplication(true, applicationId.value)
])
applicationId.value = filingId
if (resumeLater) {
await navigateTo(localePath('/platform/dashboard'))
}
} catch (e) {
logFetchError(e, 'Error saving host application')
strrModal.openAppSubmitError(e)
} finally {
handleButtonLoading(true)
}
}
const handlePlatformSubmit = async () => {
let formErrors: MultiFormValidationResult = []
try {
// TODO: move button management into composable ?
// set buttons to loading state
setButtonControl({
leftButtons: [],
rightButtons: [
{
action: () => undefined, // is disabled
icon: 'i-mdi-chevron-left',
label: t('btn.back'),
variant: 'outline',
disabled: true
},
{
action: () => undefined, // is disabled
icon: 'i-mdi-chevron-right',
label: t('btn.submitAndPay'),
trailing: true,
loading: true
}
]
})
handleButtonLoading(false, 'right', 1)
activeStep.value.complete = true // set final review step as active before validation
reviewFormRef.value?.validateConfirmation() // validate confirmation checkboxes on submit
Expand Down Expand Up @@ -180,23 +192,7 @@ const handlePlatformSubmit = async () => {
strrModal.openAppSubmitError(e)
} finally {
// set buttons back to non loading state
setButtonControl({
leftButtons: [],
rightButtons: [
{
action: () => stepperRef.value?.setPreviousStep(),
icon: 'i-mdi-chevron-left',
label: t('btn.back'),
variant: 'outline'
},
{
action: handlePlatformSubmit,
icon: 'i-mdi-chevron-right',
label: t('btn.submitAndPay'),
trailing: true
}
]
})
handleButtonLoading(true)
}
}
Expand All @@ -218,7 +214,20 @@ watch(activeStepIndex, (val) => {
trailing: true
})
setButtonControl({ leftButtons: [], rightButtons: buttons })
setButtonControl({
leftButtons: ldStore.getStoredFlag('enable-save-draft')
? [
{
action: () => navigateTo(localePath('/platform/dashboard')),
label: t('btn.cancel'),
variant: 'outline'
},
{ action: () => saveApplication(true), label: t('btn.saveExit'), variant: 'outline' },
{ action: saveApplication, label: t('btn.save'), variant: 'outline' }
]
: [],
rightButtons: buttons
})
}, { immediate: true })
// page stuff
Expand All @@ -244,7 +253,8 @@ setBreadcrumbs([
])
</script>
<template>
<div class="space-y-8 py-8 sm:py-10">
<ConnectSpinner v-if="loading" overlay />
<div v-else class="space-y-8 py-8 sm:py-10">
<ConnectTypographyH1 :text="$t('strr.title.application')" class="my-5" />
<ModalGroupHelpAndInfo />
<ConnectStepper
Expand Down
32 changes: 26 additions & 6 deletions strr-platform-web/app/stores/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export const useStrrPlatformStore = defineStore('strr/platform', () => {
const contactStore = useStrrContactStore()
const businessStore = useStrrPlatformBusiness()
const detailsStore = useStrrPlatformDetails()
const { completingParty, primaryRep, secondaryRep } = storeToRefs(contactStore)
const { completingParty, primaryRep, secondaryRep, isCompletingPartyRep } = storeToRefs(contactStore)
const { platformBusiness } = storeToRefs(businessStore)
const { platformDetails } = storeToRefs(detailsStore)

Expand All @@ -16,23 +16,43 @@ export const useStrrPlatformStore = defineStore('strr/platform', () => {
loadPermitData
} = useStrrBasePermit<PlatformRegistrationResp, PlatformApplicationResp, ApiBasePlatformApplication>()

const loadPlatform = async () => {
const loadPlatform = async (applicationId?: string, loadDraft = false) => {
$reset()
await loadPermitData(undefined, ApplicationType.PLATFORM)
await loadPermitData(applicationId, ApplicationType.PLATFORM)
if (application.value) {
// set completing party info (this data is only in the application)
completingParty.value = formatPartyUI(application.value.registration.completingParty)
}
if (showPermitDetails.value) {
if (showPermitDetails.value || loadDraft) {
// set relevant sub store values to active platform data
// @ts-expect-error - platformRepresentatives[0] will always be defined here
primaryRep.value = formatRepresentativeUI(permitDetails.value.platformRepresentatives[0])
if (permitDetails.value.platformRepresentatives?.length > 0) {
// @ts-expect-error - platformRepresentatives[0] will always be defined here
primaryRep.value = formatRepresentativeUI(permitDetails.value.platformRepresentatives[0])
// set isCompletingPartyRep if primary rep contact info is the same as the completing party info
isCompletingPartyRep.value = primaryRep.value.firstName === completingParty.value.firstName &&
primaryRep.value.middleName === completingParty.value.middleName &&
primaryRep.value.lastName === completingParty.value.lastName &&
primaryRep.value.emailAddress === completingParty.value.emailAddress &&
primaryRep.value.phone.countryCode === completingParty.value.phone.countryCode &&
primaryRep.value.phone.number === completingParty.value.phone.number &&
primaryRep.value.phone.extension === completingParty.value.phone.extension
}
// should only ever be 2 reps at most
if (permitDetails.value.platformRepresentatives?.length > 1) {
// @ts-expect-error - platformRepresentatives[1] will always be defined here
secondaryRep.value = formatRepresentativeUI(permitDetails.value.platformRepresentatives[1])
}
platformBusiness.value = formatBusinessDetailsUI(permitDetails.value.businessDetails)
if (loadDraft) {
if (!platformBusiness.value.hasCpbc) {
// api does not save this value so we have to assume it was not selected yet for drafts
platformBusiness.value.hasCpbc = undefined
}
if (!platformBusiness.value.hasRegOffAtt) {
// api does not save this value so we have to assume it was not selected yet for drafts
platformBusiness.value.hasRegOffAtt = undefined
}
}
platformDetails.value = permitDetails.value.platformDetails
}
}
Expand Down
8 changes: 6 additions & 2 deletions strr-platform-web/app/stores/platformApplication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,15 @@ export const useStrrPlatformApplication = defineStore('strr/platformApplication'
return applicationBody
}

const submitPlatformApplication = async () => {
const submitPlatformApplication = async (isDraft = false, applicationId?: string) => {
const body = createApplicationBody()

// console.info('submitting application: ', body)
const res = await postApplication<PlatformApplicationPayload, PlatformApplicationResp>(body)
const res = await postApplication<PlatformApplicationPayload, PlatformApplicationResp>(
body,
isDraft,
applicationId
)

const paymentToken = res.header.paymentToken
const filingId = res.header.applicationNumber
Expand Down
Loading

0 comments on commit d5f8691

Please sign in to comment.