Skip to content

Commit

Permalink
Merge pull request #18 from deetz99/manage-nr-modal-layout
Browse files Browse the repository at this point in the history
BRD -UI: Manage nr initial modal layout
  • Loading branch information
thorwolpert authored Aug 26, 2024
2 parents 0070a08 + d40c1d1 commit d12289f
Show file tree
Hide file tree
Showing 15 changed files with 540 additions and 21 deletions.
12 changes: 12 additions & 0 deletions business-registry-dashboard/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,18 @@ export default defineAppConfig({
primary: 'border-primary-500 placeholder-primary-500 border-b-2'
}
},
notification: {
title: 'text-sm font-medium text-white',
description: 'mt-1 text-sm leading-4 text-white',
background: 'bg-gray-700',
progress: {
base: 'hidden',
background: 'bg-{color}-500 dark:bg-{color}-400'
}
},
notifications: {
position: 'bottom-0 left-1/2 -translate-x-1/2'
},
pagination: {
wrapper: 'flex items-center -space-x-px',
base: '',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
<script setup lang="ts">
import type { MaskInputOptions } from 'maska'
import { z } from 'zod'
import type { FormError, FormSubmitEvent, Form } from '#ui/types'
const brdModal = useBrdModals()
const toast = useToast()
const { t } = useI18n()
const emit = defineEmits<{
showHelp: [void]
nameRequestError: [void]
}>()
const props = defineProps<{
nrNum: string
}>()
const alertText = ref('')
const formRef = ref<Form<NRSchema>>()
const formLoading = ref(false)
const state = reactive({
email: '',
phone: ''
})
const phoneMask: MaskInputOptions = ({
mask: '###-###-####',
eager: true
})
const nrSchema = z.object({
email: z.string(),
phone: z.string()
})
type NRSchema = z.infer<typeof nrSchema>
const validate = (state: NRSchema): FormError[] => {
alertText.value = ''
const errors = []
const phoneValid = z.string().regex(/^\d{3}-\d{3}-\d{4}$/).safeParse(state.phone).success
const emailValid = z.string().email().safeParse(state.email).success
if (!state.phone && !state.email) { // show alert if both fields are empty
alertText.value = t('form.manageNR.fields.alert.bothEmpty')
} else if (state.phone && !state.email) { // show phone error if phone populated but invalid
if (!phoneValid) {
errors.push({ path: 'phone', message: t('form.manageNR.fields.phone.error.invalid') })
}
} else if (!state.phone && state.email) { // show email error if email populated but invalid
if (!emailValid) {
errors.push({ path: 'email', message: t('form.manageNR.fields.email.error.invalid') })
}
} else if (state.phone && state.email) { // show alert and error text if both fields populated and both are invalid
if (!phoneValid && !emailValid) {
alertText.value = t('form.manageNR.fields.alert.bothInvalid')
errors.push({ path: 'phone', message: t('form.manageNR.fields.phone.error.invalid') })
errors.push({ path: 'email', message: t('form.manageNR.fields.email.error.invalid') })
}
}
return errors
}
async function onSubmit (event: FormSubmitEvent<NRSchema>) {
// emit('nameRequestError')
// Do something with data
try {
formLoading.value = true
const emailValid = z.string().email().safeParse(event.data.email).success
const phoneValid = z.string().regex(/^\d{3}-\d{3}-\d{4}$/).safeParse(event.data.phone).success
if (phoneValid) {
// make api request
console.log('submitting phone: ', event.data.phone)
await new Promise<void>((resolve) => {
setTimeout(() => {
// emit('nameRequestError')
toast.add({ title: t('form.manageNR.successToast', { nrNum: props.nrNum }) })
brdModal.manageNameRequest(false)
resolve()
}, 500)
})
} else if (emailValid) {
// make api request
console.log('submitting email: ', event.data.email)
await new Promise<void>((resolve) => {
setTimeout(() => {
emit('nameRequestError')
resolve()
}, 500)
})
}
} catch (e) {
emit('nameRequestError') // pass error?
} finally {
formLoading.value = false
}
}
</script>
<template>
<UForm
ref="formRef"
:state
:validate-on="['submit']"
:validate="validate"
class="space-y-4"
@submit="onSubmit"
@error="handleFormErrorEvent"
>
<fieldset>
<legend class="py-4">
{{ $t('form.manageNR.legend') }}
</legend>

<div class="flex flex-col gap-4">
<UFormGroup
name="phone"
:help="$t('form.manageNR.fields.phone.help')"
>
<UInput
v-model="state.phone"
v-maska="phoneMask"
:placeholder="$t('form.manageNR.fields.phone.placeholder')"
:aria-label="$t('form.manageNR.fields.phone.arialabel')"
variant="bcGovLg"
/>
</UFormGroup>

<span class="font-semibold">{{ $t('words.Or') }}</span>

<UFormGroup
name="email"
:help="$t('form.manageNR.fields.email.help')"
>
<UInput
v-model="state.email"
:placeholder="$t('form.manageNR.fields.email.placeholder')"
:aria-label="$t('form.manageNR.fields.email.arialabel')"
variant="bcGovLg"
/>
</UFormGroup>
</div>
</fieldset>

<UAlert
v-if="alertText !== ''"
icon="i-mdi-alert"
color="red"
variant="error"
:description="alertText"
/>

<div class="flex justify-between">
<UButton
:label="$t('btn.help')"
variant="ghost"
icon="i-mdi-help-circle-outline"
@click="$emit('showHelp')"
/>

<div class="flex gap-2">
<UButton
:label="$t('btn.cancel')"
variant="outline"
@click="brdModal.manageNameRequest(false)"
/>
<UButton
type="submit"
:label="$t('form.manageNR.submitBtn')"
:loading="formLoading"
/>
</div>
</div>
</UForm>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script setup lang="ts">
defineEmits<{
retryNameRequest: [void]
}>()
const brdModal = useBrdModals()
</script>
<template>
<div class="flex flex-col items-center gap-4 text-center">
<UIcon name="i-mdi-alert-circle-outline" class="mt-10 size-8 text-red-500" />
<h2 class="text-xl font-semibold">
{{ $t('form.manageNR.error.general.heading') }}
</h2>
<p>{{ $t('form.manageNR.error.general.description') }}</p>
<div class="flex gap-2">
<UButton
:label="$t('btn.cancel')"
variant="outline"
@click="brdModal.manageNameRequest(false)"
/>
<UButton
:label="$t('btn.tryAgain')"
@click="$emit('retryNameRequest')"
/>
</div>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script setup lang="ts">
defineEmits<{
hideHelp: [void]
}>()
</script>
<template>
<div class="flex flex-col gap-4">
<h2 class="mt-4 text-lg font-semibold">
{{ $t('form.manageNR.help.heading') }}
</h2>
<p>{{ $t('form.manageNR.help.description') }}</p>
<ul>
<li>{{ $t('contactInfo.bcRegGeneral.tollFree.title') }} <a class="text-blue-500 underline" href="tel:+1-877-370-1033">1-877-370-1033</a></li>
<li>{{ $t('contactInfo.bcRegGeneral.victoriaOffice.title') }} <a class="text-blue-500 underline" href="tel:+1-250-370-1033">1-250-370-1033</a></li>
<li>{{ $t('contactInfo.bcRegGeneral.email.title') }} <a class="text-blue-500 underline" href="mailto:[email protected]?subject=BC Registries and Online Services - Support Request">[email protected]</a></li>
</ul>
<div class="flex flex-col">
<span class="font-semibold">{{ $t('contactInfo.bcRegGeneral.hours.title') }}</span>
<span>{{ $t('contactInfo.bcRegGeneral.hours.value') }}</span>
</div>
<UButton
class="self-start"
:label="$t('btn.hideHelp')"
variant="ghost"
icon="i-mdi-help-circle-outline"
@click="$emit('hideHelp')"
/>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<script setup lang="ts">
import { FormAddNameRequestBase, FormAddNameRequestHelp, FormAddNameRequestError } from '#components'
defineProps<{
nrNum: string
}>()
type Form = typeof FormAddNameRequestBase
type Help = typeof FormAddNameRequestHelp
type Error = typeof FormAddNameRequestError
type Comp = Form | Help | Error
const state: Record<string, Comp> = {
FormAddNameRequestBase,
FormAddNameRequestHelp,
FormAddNameRequestError
}
const currentState = ref('FormAddNameRequestBase')
</script>
<template>
<!-- TODO: add state for when name is already added to table -->
<transition name="fade" mode="out-in">
<component
:is="state[currentState]"
:nr-num="nrNum"
@show-help="currentState = 'FormAddNameRequestHelp'"
@hide-help="currentState = 'FormAddNameRequestBase'"
@retry-name-request="currentState = 'FormAddNameRequestBase'"
@name-request-error="currentState = 'FormAddNameRequestError'"
/>
</transition>
</template>
<style scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.2s ease-out;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ const modalModel = defineModel({ type: Boolean, default: false })
defineProps<{
title: string
content: string
actions: { label: string, handler:() => void }[]
content?: string
actions?: { label: string, handler:() => void }[]
}>()
</script>
<template>
Expand All @@ -13,30 +13,33 @@ defineProps<{
<template #header>
<div class="flex items-center justify-between">
<span class="text-xl font-semibold text-bcGovColor-darkGray">{{ title }}</span>
<!-- eslint-disable vue/attribute-hyphenation -->
<UButton
:ui="{ icon: { base: 'shrink-0 scale-150' } }"
icon="i-mdi-close"
color="primary"
:ariaLabel="$t('btn.close')"
:aria-label="$t('btn.close')"
square
variant="ghost"
@click="modalModel = false"
/>
</div>
</template>
<p class="text-bcGovColor-midGray">
{{ content }}
</p>
<template #footer>
<div class="flex items-center justify-center gap-4">
<UButton
v-for="(action, index) in actions"
:key="index"
:label="action.label"
@click="action.handler"
/>
</div>
<slot>
<p class="text-bcGovColor-midGray">
{{ content }}
</p>
</slot>
<template v-if="actions !== undefined || $slots.footer" #footer>
<slot name="footer">
<div v-if="actions !== undefined" class="flex items-center justify-center gap-4">
<UButton
v-for="(action, index) in actions"
:key="index"
:label="action.label"
@click="action.handler"
/>
</div>
</slot>
</template>
</UCard>
</UModal>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<script setup lang="ts">
defineProps<{
nameRequest: {
names: string[]
nrNum: string
}
}>()
</script>
<template>
<ModalBase
:title="$t('form.manageNR.heading')"
>
<!-- nr info section -->
<div class="-mt-4 flex flex-col gap-2">
<!-- nr names display -->
<div class="flex gap-8">
<span class="font-semibold">{{ $t('form.manageNR.requestedNames', nameRequest.names.length) }}</span>
<ul>
<li v-for="name in nameRequest.names" :key="name">
{{ name }}
</li>
</ul>
</div>
<!-- nr number display -->
<div class="flex gap-8">
<span class="font-semibold">{{ $t('form.manageNR.nrNum') }}</span>
<span>{{ nameRequest.nrNum }}</span>
</div>
</div>
<FormAddNameRequest :nr-num="nameRequest.nrNum" />
</ModalBase>
</template>
Loading

0 comments on commit d12289f

Please sign in to comment.