Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion strr-host-pm-web/app/components/document/upload/Select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const props = defineProps({
isDisabled: { type: Boolean, default: false },
isRequired: { type: Boolean, default: false },
isInvalid: { type: Boolean, default: false },
docOptions: { type: Array<{ label: string; value: DocumentUploadType }>, default: undefined },
label: { type: String, default: '' },
size: { type: String, default: 'lg' },
helpId: { type: String, default: undefined },
Expand Down Expand Up @@ -78,7 +79,7 @@ onChange((files) => {
v-model="docStore.selectedDocType"
size="lg"
:color="'gray'"
:options="docStore.docTypeOptions"
:options="docOptions ?? docStore.docTypeOptions"
:aria-label="label"
:aria-required="isRequired"
:aria-invalid="isInvalid"
Expand Down
78 changes: 78 additions & 0 deletions strr-host-pm-web/app/components/document/upload/Type.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<script lang="ts" setup>

const { t } = useI18n()
const docStore = useDocumentStore()
const strrModal = useStrrModals()

const props = defineProps<{
title: string,
formFieldName: string,
docUploadType: DocumentUploadTypeEnum // document types for upload for the dropdown
docUploadStep: DocumentUploadStep,
hasError: boolean
}>()

const { storedDocuments } = storeToRefs(docStore)

const docUploadHelpId = useId() // id for aria-describedby on doc select

const allowedDocumentTypes = Object.values(props.docUploadType) as DocumentUploadType[]

const uploadedDocuments = computed(() =>
storedDocuments.value.filter(doc => allowedDocumentTypes.includes(doc.type))) // filter all uploaded docs based on allowed types

const docOptions = computed(() =>
allowedDocumentTypes.map(type => ({
label: t(`form.pr.docType.${type}`),
value: type
}))
)

</script>

<template>
<ConnectFormSection
:title="props.title"
:error="props.hasError"
>
<div class="max-w-bcGovInput space-y-5">
<UFormGroup
:name="props.formFieldName"
:ui="{ help: 'mt-2 ml-10' }"
>
<DocumentUploadSelect
id="supporting-documents-type-select"
:label="$t('label.chooseDocs')"
:is-invalid="props.hasError"
:error="props.hasError"
:is-required="docStore.requiredDocs.length > 0"
:help-id="docUploadHelpId"
:doc-options="docOptions"
accept="application/pdf,image/jpeg"
@change="docStore.addStoredDocument($event, docUploadStep)"
@cancel="docStore.selectedDocType = undefined"
@error="e => strrModal.openErrorModal(
$t(`error.docUpload.${e}.title`), $t(`error.docUpload.${e}.description`), false
)"
@reset="docStore.selectedDocType = undefined"
/>

<template #help>
<span :id="docUploadHelpId">
{{ $t('hint.docUpload') }}
</span>
</template>

<template #error="{ error }">
<span :id="docUploadHelpId">
{{ error }}
</span>
</template>
</UFormGroup>
<DocumentListItem
:documents="uploadedDocuments"
@remove="docStore.removeStoredDocument"
/>
</div>
</ConnectFormSection>
</template>
131 changes: 126 additions & 5 deletions strr-host-pm-web/app/components/form/AddDocuments/index.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
<script setup lang="ts">
import type { Form } from '#ui/types'
import {
ProofOfIdentityDocuments, ProofOfTenancyDocuments, ProofOfPrincipalResidenceDocuments, BusinessLicenceDocuments,
ProofOfFractionalOwnershipDocuments, StrataDocuments
} from '~/enums/document-upload-type'

const { t } = useI18n()
const config = useRuntimeConfig().public
const reqStore = usePropertyReqStore()
const docStore = useDocumentStore()
const propStore = useHostPropertyStore()
const strrModal = useStrrModals()
const { openSupportingDocumentsHelpModal } = useHostPmModals()
const { isNewPrDocumentsListEnabled } = useHostFeatureFlags()
const { isNewPrDocumentsListEnabled, isEnhancedDocumentUploadEnabled } = useHostFeatureFlags()

const { propertyReqs, prRequirements } = storeToRefs(reqStore)
const { unitDetails } = storeToRefs(propStore)

const props = defineProps<{
docUploadStep: DocumentUploadStep,
Expand All @@ -34,6 +42,92 @@ watch(
{ immediate: true, deep: true }
)

const showEnhancedDocumentUpload = computed(() =>
isEnhancedDocumentUploadEnabled.value && isNewPrDocumentsListEnabled.value
)

// display conditions for document upload types

const isPrRequiredWithoutExemption = computed(() =>
propertyReqs.value.isPrincipalResidenceRequired &&
prRequirements.value.prExemptionReason === undefined
)

const showProofOfIdentity = computed(() => isPrRequiredWithoutExemption.value &&
unitDetails.value.hostType !== undefined)

const showProofOfPr = computed(() =>
isPrRequiredWithoutExemption.value ||
prRequirements.value.prExemptionReason === PrExemptionReason.FARM_LAND
)

const showProofOfFractionalOwnership = computed(() =>
prRequirements.value.prExemptionReason === PrExemptionReason.FRACTIONAL_OWNERSHIP
)

const showBusinessLicence = computed(() =>
propertyReqs.value.isBusinessLicenceRequired && !blExempt.value
)

const showProofOfTenancy = computed(() =>
unitDetails.value.hostType === PropertyHostType.LONG_TERM_TENANT &&
isPrRequiredWithoutExemption.value
)

const showStrataDocs = computed(() =>
prRequirements.value.prExemptionReason === PrExemptionReason.STRATA_HOTEL
)

// configurations for document upload dropdowns
const documentUploadConfig = computed<DocumentUploadConfig[]>(() => {
const config: DocumentUploadConfig[] = [
{
testId: 'proof-of-identity-upload',
title: t('label.proofOfIdentity'),
fieldName: 'identityDocUpload',
uploadType: ProofOfIdentityDocuments,
isDisplayed: showProofOfIdentity.value
},
{
testId: 'proof-of-pr-upload',
title: t('label.proofOfPr'),
fieldName: 'prDocUpload',
uploadType: ProofOfPrincipalResidenceDocuments,
isDisplayed: showProofOfPr.value
},
{
testId: 'proof-of-fractional-ownership-upload',
title: t('label.proofOfFractionalOwnership'),
fieldName: 'fractionalOwnerDocUpload',
uploadType: ProofOfFractionalOwnershipDocuments,
isDisplayed: showProofOfFractionalOwnership.value
},
{
testId: 'business-licence-upload',
title: t('label.localGovBL'),
fieldName: 'blDocUpload',
uploadType: BusinessLicenceDocuments,
isDisplayed: showBusinessLicence.value
},
{
testId: 'proof-of-tenancy-upload',
title: t('label.proofOfTenancy'),
fieldName: 'tenancyDocUpload',
uploadType: ProofOfTenancyDocuments,
isDisplayed: showProofOfTenancy.value
},
{
testId: 'strata-docs-upload',
title: t('label.supportingStrataDocs'),
fieldName: 'strataDocUpload',
uploadType: StrataDocuments,
isDisplayed: showStrataDocs.value
}
]

return config.filter(docConfig => docConfig.isDisplayed)
})

onMounted(async () => {
// validate form if step marked as complete
if (props.isComplete) {
Expand Down Expand Up @@ -112,10 +206,34 @@ onMounted(async () => {
<UForm
ref="docFormRef"
:state="docStore.requiredDocs"
:validate="docStore.validateRequiredDocuments"
:validate="showEnhancedDocumentUpload
? docStore.validateDocumentDropdowns
: docStore.validateRequiredDocuments
"
:validate-on="['submit']"
class="pb-10"
>
<div class="py-10">
<div
v-if="showEnhancedDocumentUpload"
data-testid="enhanced-doc-upload"
>
<DocumentUploadType
v-for="docConfig in documentUploadConfig"
:key="docConfig.fieldName"
:data-testid="docConfig.testId"
:title="docConfig.title"
:form-field-name="docConfig.fieldName"
:doc-upload-type="docConfig.uploadType"
:doc-upload-step="docUploadStep"
:has-error="isComplete && hasFormErrors(docFormRef, [docConfig.fieldName])"
class="pt-10"
/>
</div>
<div
v-else
class="pt-10"
data-testid="standard-doc-upload"
>
<ConnectFormSection
:title="$t('label.fileUpload')"
:error="isComplete && hasFormErrors(docFormRef, ['documentUpload'])"
Expand All @@ -128,6 +246,7 @@ onMounted(async () => {
>
<DocumentUploadSelect
id="supporting-documents"
data-testid="document-upload-select"
:label="$t('label.chooseDocs')"
:is-invalid="isComplete && hasFormErrors(docFormRef, ['documentUpload'])"
:error="isComplete && hasFormErrors(docFormRef, ['documentUpload'])"
Expand Down Expand Up @@ -177,8 +296,10 @@ onMounted(async () => {
}"
/>

<!-- TODO: add aria label to page section ?? -->
<ConnectPageSection v-if="!blExempt">
<ConnectPageSection
v-if="!blExempt"
data-testid="bl-section-info"
>
<UForm
ref="blFormRef"
:schema="propStore.blInfoSchema"
Expand Down
4 changes: 3 additions & 1 deletion strr-host-pm-web/app/composables/useHostFeatureFlags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export const useHostFeatureFlags = () => {
isNewRentalUnitSetupEnabled: isFeatureEnabled('enable-host-new-rental-unit-setup'),
isNewPrDocumentsListEnabled: isFeatureEnabled('enable-host-new-pr-documents'),
isDashboardTableSortingEnabled: isFeatureEnabled('enable-host-dashboard-table-sorting'),
isNewDashboardEnabled: isFeatureEnabled('enable-new-host-dashboard')
isNewDashboardEnabled: isFeatureEnabled('enable-new-host-dashboard'),
isBusinessLicenseDocumentUploadEnabled: isFeatureEnabled('enable-business-license-document-upload'),
isEnhancedDocumentUploadEnabled: isFeatureEnabled('enable-host-enhanced-document-upload')
}
}
41 changes: 41 additions & 0 deletions strr-host-pm-web/app/enums/document-upload-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,44 @@ export enum DocumentUploadType {
ASSESSMENT_ACT_NOTICE = 'ASSESSMENT_ACT_NOTICE',
MORTGAGE_STATEMENT_OR_SAVINGS_DOC = 'MORTGAGE_STATEMENT_OR_SAVINGS_DOC'
}

export enum ProofOfIdentityDocuments {
BC_DRIVERS_LICENSE = 'BC_DRIVERS_LICENSE',
BCSC = 'BCSC',
COMBINED_BCSC_LICENSE = 'COMBINED_BCSC_LICENSE'
}

export enum ProofOfPrincipalResidenceDocuments {
PROPERTY_ASSESSMENT_NOTICE = 'PROPERTY_ASSESSMENT_NOTICE',
ICBC_CERTIFICATE_OF_INSURANCE = 'ICBC_CERTIFICATE_OF_INSURANCE',
HOME_INSURANCE_SUMMARY = 'HOME_INSURANCE_SUMMARY',
PROPERTY_TAX_NOTICE = 'PROPERTY_TAX_NOTICE',
GOVT_OR_CROWN_CORP_OFFICIAL_NOTICE = 'GOVT_OR_CROWN_CORP_OFFICIAL_NOTICE',
TITLE_CERTIFICATE_OR_SEARCH = 'TITLE_CERTIFICATE_OR_SEARCH',
SPECULATION_VACANCY_TAX_DECLARATION = 'SPECULATION_VACANCY_TAX_DECLARATION',
HOME_OWNER_GRANT_APPROVAL = 'HOME_OWNER_GRANT_APPROVAL',
NOTARIZED_REAL_ESTATE_DOC = 'NOTARIZED_REAL_ESTATE_DOC',
PROPERTY_TRANSFER_TAX_RETURN = 'PROPERTY_TRANSFER_TAX_RETURN',
AFFIDAVIT_PRINCIPAL_RESIDENCE = 'AFFIDAVIT_PRINCIPAL_RESIDENCE',
ASSESSMENT_ACT_NOTICE = 'ASSESSMENT_ACT_NOTICE',
MORTGAGE_STATEMENT_OR_SAVINGS_DOC = 'MORTGAGE_STATEMENT_OR_SAVINGS_DOC',
OTHERS = 'OTHERS'
}

export enum ProofOfTenancyDocuments {
TENANCY_AGREEMENT = 'TENANCY_AGREEMENT',
RENT_RECEIPT_OR_BANK_STATEMENT = 'RENT_RECEIPT_OR_BANK_STATEMENT'
}

export enum ProofOfFractionalOwnershipDocuments {
FRACTIONAL_OWNERSHIP_AGREEMENT = 'FRACTIONAL_OWNERSHIP_AGREEMENT',
PROPERTY_TITLE_WITH_FRACTIONAL_OWNERSHIP = 'PROPERTY_TITLE_WITH_FRACTIONAL_OWNERSHIP'
}

export enum BusinessLicenceDocuments {
LOCAL_GOVT_BUSINESS_LICENSE = 'LOCAL_GOVT_BUSINESS_LICENSE'
}

export enum StrataDocuments {
STRATA_HOTEL_DOCUMENTATION = 'STRATA_HOTEL_DOCUMENTATION'
}
8 changes: 8 additions & 0 deletions strr-host-pm-web/app/interfaces/document-upload-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// interface to configure enhanced multi-dropdown document upload
export interface DocumentUploadConfig {
testId: string // unique id for tests
title: string // title for dropdown section
fieldName: string // form field name for the uploaded document (used for validation)
uploadType: DocumentUploadTypeEnum // category/type of document being uploaded
isDisplayed: boolean // show or hide the dropdown based on requirements in propStore, reqStore, etc.
}
Loading
Loading