Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Host Details Page #451

Merged
merged 2 commits into from
Jan 13, 2025
Merged
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
7 changes: 5 additions & 2 deletions strr-base-web/app/utils/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,19 @@ export function dateToStringPacific (date: Date | string, format = 'y-MM-dd') {

/**
* Calculates the number of full days remaining until a given end date.
* If isElapsed is true, it calculates the number of full days since the end date.
*
* @param end - The ISO datestring for the end value.
* @returns The number of full days remaining until the end date.
*/
export function dayCountdown (end: string): number {
export function dayCountdown (end: string, isElapsed: boolean = false): number {
const startDate = DateTime.utc() // get current utc date
const endDate = DateTime.fromISO(end, { setZone: true }).toUTC() // get given end date and convert to utc

// get difference in days https://moment.github.io/luxon/#/math?id=diffs
const diff = endDate.diff(startDate, 'days').toObject().days
const diff = isElapsed
? startDate.diff(endDate, 'days').toObject().days ?? 0
: endDate.diff(startDate, 'days').toObject().days

// round difference down
return Math.floor(diff)
Expand Down
50 changes: 0 additions & 50 deletions strr-examiner-web/app/components/ApplicationDetails.vue

This file was deleted.

23 changes: 3 additions & 20 deletions strr-examiner-web/app/components/ApplicationDetailsSection.vue
Original file line number Diff line number Diff line change
@@ -1,34 +1,17 @@
<script setup lang="ts">

const props = defineProps<{ label: string, hideCheckbox?: boolean, hideChecklist?: boolean }>()
const props = defineProps<{ label: string }>()

</script>

<template>
<div class="flex items-center py-4 text-sm">
<div class="flex py-4 text-sm">
<div class="flex w-1/5 items-start justify-start">
<UCheckbox v-if="!hideCheckbox" name="checkbox">
<template #label>
<span class="text-sm font-bold">{{ props.label }}</span>
</template>
</UCheckbox>
<span class="text-sm font-bold">{{ props.label }}</span>
</div>
<div class="flex-auto">
<slot />
</div>
<div
v-if="!hideChecklist"
class="flex"
>
<UButton
label="Checklist"
variant="link"
class="p-0 text-sm"
icon="i-mdi-chevron-down"
size="sm"
trailing
/>
</div>
</div>
</template>

Expand Down
34 changes: 34 additions & 0 deletions strr-examiner-web/app/components/ApplicationInfoHeader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<script setup lang="ts">

const props = defineProps<{ application: ApiApplicationBaseResp }>()

const { t } = useI18n()
const { header, registration } = props.application

const displayApplicationType = {
[ApplicationType.HOST]: t('strr.label.host'),
[ApplicationType.PLATFORM]: t('strr.label.platform'),
[ApplicationType.STRATA_HOTEL]: t('strr.label.strataHotel')
}

</script>

<template>
<div class="border-b py-6">
<div class="mb-2 text-2xl">
<strong>
{{ header?.applicationNumber }} |
</strong>
{{ registration.unitAddress.nickname }}
</div>
<div class="text-sm">
<UBadge class="mr-3 font-bold" :label="header.examinerStatus" color="primary" />
<strong>Type:</strong>
{{ displayApplicationType[registration?.registrationType as keyof typeof displayApplicationType] }} |
<strong>Submitted:</strong> {{ dateToString(header.applicationDateTime, 'y-MM-dd t') }}
({{ dayCountdown(header.applicationDateTime.toString(), true) }} days ago)
</div>
</div>
</template>

<style scoped></style>
183 changes: 108 additions & 75 deletions strr-examiner-web/app/components/HostDetailsView.vue
Original file line number Diff line number Diff line change
@@ -1,116 +1,149 @@
<script setup lang="ts">
import { useExaminerStore } from '~/store/examiner'

const props = defineProps<{ application: HostApplicationResp }>()

const { t } = useI18n()
const { header, registration } = props.application
const { unitDetails } = registration

const emit = defineEmits<{
approveApplication: [],
rejectApplication: []
approveApplication: [],
rejectApplication: []
}>()

const { getDocument } = useExaminerStore()

const openDocInNewTab = async (supportingDocument: ApiDocument) => {
const file = await getDocument(header.applicationNumber, supportingDocument.fileKey)
const blob = new Blob([file], { type: 'application/pdf' })
const url = URL.createObjectURL(blob)
window.open(url, '_blank')
URL.revokeObjectURL(url)
}

</script>

<template>
<div>
<div class="mb-2 align-middle text-lg">
<strong>
{{ header?.applicationNumber }}
</strong>
<UButton label="View History" variant="link" size="sm" class="mx-2 underline" />
</div>
<div
v-if="registration?.registrationType === ApplicationType.HOST"
class="flex flex-row gap-x-5 divide-x text-sm"
>
<div>
<dl class="grid grid-cols-[repeat(2,auto)] gap-x-4">
<dt>Status:</dt>
<dd>{{ header?.hostStatus }}</dd>

<dt>Submitted:</dt>
<dd>{{ dateToString(header?.applicationDateTime || '') }}</dd>

<dt>Registration Type:</dt>
<dd>{{ registration?.registrationType }}</dd>
</dl>
</div>
<div>
<dl class="grid grid-cols-[repeat(2,auto)] gap-x-4 pl-5">
<dt>Unit Address:</dt>
<dd class="w-[150px]">
{{ displayFullUnitAddress(registration?.unitAddress) }}
</dd>

<dt>Municipality:</dt>
<dd>{{ registration?.strRequirements?.organizationNm }}</dd>
</dl>
<div class="text-bcGovColor-midGray grid grid-cols-4 gap-x-5 divide-x text-sm">
<div class="space-y-2">
<strong>RENTAL UNIT</strong>
<div class="w-[150px]">
<UIcon name="i-mdi-map-marker-outline" />
{{ displayFullUnitAddress(registration?.unitAddress) }}
</div>
<div v-if="registration?.strRequirements?.organizationNm">
<UIcon name="i-mdi-map-outline" />
{{ registration?.strRequirements?.organizationNm }}
</div>
</div>
<div>
<dl class="grid grid-cols-[repeat(2,auto)] gap-x-4 pl-5">
<dt>Host Address:</dt>
<dd class="w-[150px]">
{{ displayFullAddress(registration?.primaryContact.mailingAddress) }}
</dd>

<dt>Address Type:</dt>
<dd>Mailing</dd>

<dt>Same as Unit Address:</dt>
<dd>{{ registration?.unitDetails.hostResidence }}</dd>

<dt>Host Name:</dt>
<dd>{{ displayContactFullName(registration?.primaryContact || {}) }}</dd>

<dt>Host Type:</dt>
<dd>{{ registration?.primaryContact.contactType }}</dd>
<div class="space-y-2 pl-5">
<strong>HOST</strong>
<div class="w-[150px]">
<UIcon name="i-mdi-map-marker-outline" />
{{ displayFullAddress(registration?.primaryContact.mailingAddress) }}
</div>
<div>
<UIcon name="i-mdi-account" />
{{ displayContactFullName(registration?.primaryContact) }}
</div>
<div>
<UIcon name="i-mdi-at" />
{{ registration?.primaryContact.emailAddress }}
</div>
<div>
<strong>Host Type:</strong>
{{ registration?.primaryContact.contactType }}
</div>
<div>
<strong>Owner / Renter:</strong>
{{ unitDetails.ownershipType }}
</div>
</div>

<dt>Ownership Type:</dt>
<dd>{{ registration?.unitDetails.ownershipType }}</dd>
</dl>
<div class="space-y-2 pl-5">
<div>
{{ t(`propertyType.${unitDetails.propertyType}`) }}
</div>
<div>
{{ t(`rentalUnitType.${unitDetails.rentalUnitSpaceType}`) }} ({{ unitDetails.numberOfRoomsForRent }} Rooms)
</div>
<div>{{ t(`hostResidence.${unitDetails.hostResidence}`) }}</div>
<div><strong>PID:</strong> {{ unitDetails.parcelIdentifier }}</div>
<div>
<strong>PR Registered Rentals:</strong>
<!-- TODO: Get number of registered rentals for the host -->
</div>
</div>
<div>
<dl class="grid grid-cols-[repeat(2,auto)] gap-x-4 pl-5">
<dt>Property Type:</dt>
<dd>{{ registration?.unitDetails.propertyType }}</dd>

<dt>Configuration:</dt>
<dd>{{ registration?.unitDetails.rentalUnitSpaceType }}</dd>
<div class="space-y-2 pl-5">
<div>
<UIcon name="i-mdi-account-multiple-outline" />
{{ registration?.secondaryContact?.contactType === OwnerType.INDIVIDUAL
? displayContactFullName(registration?.secondaryContact) :
registration?.secondaryContact?.businessLegalName }}
</div>

<dt>Rooms:</dt>
<dd>{{ registration?.unitDetails.numberOfRoomsForRent }}</dd>
</dl>
<div>
<UIcon name="i-mdi-at" />
{{ registration?.propertyManager?.propertyManagerType === OwnerType.INDIVIDUAL
? displayContactFullName(registration?.propertyManager.contact) :
registration?.propertyManager?.business?.legalName }}
</div>
</div>
</div>

<!-- APPLICATION SECTIONS -->
<div class="mt-6 divide-y">
<ApplicationDetailsSection label="Short-term rentals prohibited" hide-checklist>
<ApplicationDetailsSection label="Short-term rentals prohibited">
<div class="flex items-center justify-between">
<div class="flex">
{{ registration?.strRequirements?.isStrProhibited ? 'Yes' : 'No' }}
</div>
<div class="flex items-start justify-end gap-x-2">
<UButton label="Quick send to supervisor" color="primary" />
</div>
</div>
</ApplicationDetailsSection>

<ApplicationDetailsSection label="Principal Residence">
<div>
{{ registration?.strRequirements?.isPrincipalResidenceRequired ?
'Required' : 'Not Required' }}
'Required.' : 'Not Required.' }} {{ registration?.strRequirements?.isStraaExempt ?
'Exempt.' : 'Not Exempt.' }}
</div>
<div>
<strong>STR Accommodations Act: </strong>
{{ registration?.strRequirements?.isStraaExempt ?
'Exempt' : 'Not Exempt' }}

<div class="mt-2">
<UButton
v-for="document in registration.documents"
:key="document.fileKey"
class="mr-4 gap-x-1 p-0"
variant="link"
icon="mdi-file-document-outline"
@click="openDocInNewTab(document)"
>
{{ t(`documentLabels.${document.documentType}`) }}
</UButton>
</div>
</ApplicationDetailsSection>

<ApplicationDetailsSection label="" hide-checkbox hide-checklist class="pt-8">
<ApplicationDetailsSection label="" hide-checkbox class="pt-8">
<div class="flex justify-end gap-x-2">
<UButton label="Approve" color="primary" @click="emit('approveApplication')" />
<UButton label="Reject" color="gray" @click="emit('rejectApplication')" />
<UButton
icon="i-mdi-close"
:label="t('btn.decline')"
color="red"
variant="outline"
size="lg"
@click="emit('rejectApplication')"
/>
<UButton
icon="i-mdi-check"
:label="t('btn.approve')"
color="green"
variant="outline"
size="lg"
@click="emit('approveApplication')"
/>
</div>
</ApplicationDetailsSection>
</div>
Expand Down
13 changes: 0 additions & 13 deletions strr-examiner-web/app/components/PlatformDetailsView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,6 @@ const { header, registration } = props.application

<template>
<div>
<div class="mb-2 align-middle text-lg">
<strong>
{{ header?.applicationNumber }}
</strong>
<UButton
label="View History"
variant="link"
size="sm"
class="mx-2 underline"
/>
</div>

<div
class="flex flex-row gap-x-5 divide-x text-sm"
>
Expand Down Expand Up @@ -69,7 +57,6 @@ const { header, registration } = props.application
<div class="mt-6 divide-y">
<ApplicationDetailsSection
label="Business Details"
hide-checklist
>
<div class="flex items-center justify-between">
<div class="flex">
Expand Down
Loading
Loading