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

Todo Section - Dialogs #28

Merged
merged 3 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 3 additions & 2 deletions src/components/bcros/dialog/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<UModal
:attach="attach || ''"
:model-value="display"
data-cy="bcros-dialog"
:data-cy="'bcros-dialog' + name ? `-${name}` : ''"
>
<div v-if="options" class="px-10 py-9">
<div class="flex">
Expand Down Expand Up @@ -33,7 +33,7 @@
<div class="pt-7">
<!-- can be replaced with <template v-slot:buttons> -->
<slot name="buttons" :options="options">
<div class="flex justify-center">
<div class="flex justify-center gap-5">
<div v-for="button, i in options.buttons" :key="'dialog-btn-' + i">
<slot :name="'dialog-btn-slot-' + button.slotId">
<dialog-button :button="button" data-cy="bcros-dialog-btn" @close="emit('close')" />
Expand All @@ -50,6 +50,7 @@
import { DialogButton, DialogContent } from './slot-templates'

const props = defineProps<{
name?: string,
attach?: string,
display: boolean,
options?: DialogOptionsI
Expand Down
126 changes: 124 additions & 2 deletions src/components/bcros/todo/Item.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
<script setup lang="ts">
import { FilingTypes } from '@bcrs-shared-components/enums'
import { filingTypeToName } from '~/utils/todo/task-filing/helper'

const todosStore = useBcrosTodos()
const business = useBcrosBusiness()

const showConfirmDialog = ref(false)
const hasDeleteError = ref(false)
const hasCancelPaymentError = ref(false)
const confirmDialog = ref<DialogOptionsI | null>(null)

defineEmits(['expand'])
const prop = defineProps({
item: { type: Object as PropType<TodoItemI>, required: true },
Expand All @@ -13,11 +19,75 @@ const prop = defineProps({
const checkboxChecked: Ref<boolean> = ref(false)
const inProcessFiling: Ref<number> = ref(null)

// errors and warnings from API calls for deleting a draft or cancelling a payment
const deleteErrors = ref([])
const deleteWarnings = ref([])
const cancelPaymentErrors = ref([])

const name = computed(() =>
// the 'name' attribute for affiliation invitation is null as there is no matching FilingTypes
prop.item.name ? prop.item.name : 'affiliation'
)

// dialog options config
const confirmDeleteDraft: DialogOptionsI = {
title: 'Delete Draft?',
text: `Delete your ${prop.item.draftTitle}? Any changes you've made will be lost.`,
hideClose: true,
buttons: [
{ text: 'Delete', slotId: 'delete', color: 'primary', onClick: () => deleteDraft() },
{ text: 'Cancel', slotId: 'cancel', color: 'primary', onClickClose: true }
]
}

const confirmDeleteApplication: DialogOptionsI = {
title: `Delete ${filingTypeToName(prop.item.name)}?`,
text: `Deleting this ${prop.item.draftTitle} will remove this application and all information ` +
'associated with this application.',
textExtra: ['You will be returned to the Business Registry page.'], // TO-DO: different text for name request
hideClose: true,
buttons: [
{ text: 'Delete', slotId: 'delete', color: 'primary', onClick: () => deleteApplication() },
{ text: 'Don\'t Delete', slotId: 'cancel', color: 'primary', onClickClose: true }
]
}

const confirmCancelPayment: DialogOptionsI = {
title: 'Cancel Payment?',
text: `Cancel payment for your ${prop.item.draftTitle}?`,
hideClose: true,
buttons: [
{ text: 'Cancel Payment', slotId: 'delete', color: 'primary', onClick: () => cancelPaymentAndSetToDraft() },
{ text: 'Don\'t Cancel', slotId: 'cancel', color: 'primary', onClickClose: true }
]
}

/** Handle the click event for the passed-in action button.
* Execute the action function if it exists, and open the dialog if needed.
*/
const handleClick = (button: ActionButtonI) => {
if (button.actionFn) {
button.actionFn(prop.item)
}

if (button.openDialog) {
const businessId = business.currentBusiness.identifier
const tempRegNumber = sessionStorage.getItem('TEMP_REG_NUMBER')

if (prop.item.status === FilingStatusE.DRAFT) {
// open the dialog for confirming deleting a draft filing (for existing businesses)
if (businessId) { confirmDialog.value = confirmDeleteDraft }
// open the dialog for confirming deleting a draft application (for temp business number)
if (tempRegNumber) { confirmDialog.value = confirmDeleteApplication }
} else if (prop.item.status === FilingStatusE.PENDING) {
// open the dialog for confirming cancelling a payment for a pending filing with payment error
confirmDialog.value = confirmCancelPayment
}

showConfirmDialog.value = true
}
}

/** Whether to show the error style for the button (red text and red hover background) and the top border (red). */
const useErrorStyle = (item: TodoItemI): boolean => {
if (item.status === FilingStatusE.DRAFT) {
Expand All @@ -30,10 +100,61 @@ const useErrorStyle = (item: TodoItemI): boolean => {

return false
}

/** Delete a draft; if refreshDashboard is set to true, refresh the page to reload data */
const deleteDraft = async (_refreshDashboard = true): Promise<void> => {
/* eslint-disable no-console */
console.log('Delete a draft')

// TO-DO: implement this function in ticket #22638; delete draft and handle errors
await Promise.resolve()
}

const deleteApplication = async (): Promise<void> => {
await deleteDraft(false)

/* eslint-disable no-console */
console.log('Redirecting after deleting an application')
// TO-DO: implement this function in ticket #22638
// go to My Business Registry page if it is a name request
// otherwise go to BCROS home page
}

/** Cancel the payment and set the filing status to draft; reload the page; handle errors if exist */
const cancelPaymentAndSetToDraft = async (_refreshDashboard = true): Promise<void> => {
/* eslint-disable no-console */
console.log('Cancel the payment and set the filing status to draft')

// TO-DO: implement this function in ticket #22638; delete draft and handle errors
await Promise.resolve()
}
</script>

<template>
<div class="flex flex-col gap-0 w-full">
<!-- confirm dialog -->
<BcrosDialog
attach="#todoList"
:display="showConfirmDialog"
:options="confirmDialog"
@close="showConfirmDialog = false"
/>

<!-- error dialog (deleting draft) -->
<BcrosTodoDialogDeleteError
:display="hasDeleteError"
:errors="deleteErrors"
:warnings="deleteWarnings"
@close="hasDeleteError = false"
/>

<!-- error dialog (cancelling payment) -->
<BcrosTodoDialogCancelPaymentError
:display="hasCancelPaymentError"
:errors="cancelPaymentErrors"
@close="hasCancelPaymentError = false"
/>

<div
class="flex flex-row w-full justify-between px-6 py-5 text-sm"
:class="useErrorStyle(item) ? 'border-0 border-t-2 border-t-red-600' : ''"
Expand Down Expand Up @@ -152,7 +273,7 @@ const useErrorStyle = (item: TodoItemI): boolean => {
:disabled="item.actionButton.disabled || (item.showAnnualReportCheckbox && !checkboxChecked)"
class="action-button"
:label="item.actionButton.label"
@click="() => item.actionButton.actionFn(item)"
@click="() => handleClick(item.actionButton)"
/>
<!-- dropdown menu -->
<UPopover
Expand All @@ -178,13 +299,14 @@ const useErrorStyle = (item: TodoItemI): boolean => {
:label="item.actionButton.menus[index].label"
:icon="button.icon"
:data-cy="'menu-button-' + index"
@click="()=>item.actionButton.menus[index].actionFn(item)"
@click="()=>handleClick(item.actionButton.menus[index])"
/>
</template>
</UPopover>
</div>
</div>
</div>

<transition name="slide-down">
<div
v-if="item.expansionContent && expanded"
Expand Down
38 changes: 38 additions & 0 deletions src/components/bcros/todo/List.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
<script setup lang="ts">
const todosStore = useBcrosTodos()

const prop = defineProps({
todos: { type: Array<TodoItemI>, required: true }
})

const authorizeAffiliationError = ref(todosStore.authorizeAffiliationsErrors.length > 0)
const loadAffiliationInvitationError = ref(todosStore.loadAffiliationsError.length > 0)

const authorizeAffiliationErrorOptions: DialogOptionsI = {
title: 'Error updating affiliation invitation.',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this going to be internationalized ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes I agree I think this should all be from the lang file

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many texts in the dashboard are from the imported enums or functions, so the content can't be fully internationalized until those texts from the external source are updated. But I agree that we need to use the lang file in the new dashboard.

I have updated the i18n stuff for the dialogs. There are many other places in the todo section that i18n need to be applied. I will change that later in a separate PR.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a ticket if you dont have it, for the next PR

text: 'An error happened while updating affiliation invitation.',
textExtra: ['Please try again later.'],
hideClose: true,
buttons: [{ text: 'Ok', slotId: 'ok', color: 'primary', onClickClose: true }]
}

const loadAffiliationInvitationErrorOptions: DialogOptionsI = {
title: 'Error fetching affiliation invitation.',
text: 'An error happened while fetching affiliation invitation.',
textExtra: ['Please try again later.'],
hideClose: true,
buttons: [{ text: 'Ok', slotId: 'ok', color: 'primary', onClickClose: true }]
}

const isExpandedInternal: Ref<boolean[]> = ref([])

const isExpanded = computed({
Expand All @@ -28,9 +49,26 @@ const expand = (index: number, expanded: boolean) => {

<template>
<div
id="todoList"
class="flex flex-col"
data-cy="todoItemList"
>
<!-- error dialog (fetching affiliation request) -->
<BcrosDialog
attach="#todoList"
:display="loadAffiliationInvitationError"
:options="loadAffiliationInvitationErrorOptions"
@close="loadAffiliationInvitationError = false"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to clear error queue if they are acknowledged and have this as a computed value ?
Was there a reason, why the errors should stay in the queue after closing the error dialog ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Updated

/>

<!-- error dialog (accepting affiliation request) -->
<BcrosDialog
attach="#todoList"
:display="authorizeAffiliationError"
:options="authorizeAffiliationErrorOptions"
@close="authorizeAffiliationError = false"
/>

<template v-if="todos.length > 0">
<BcrosTodoItem
v-for="(todoItem, index) in todos"
Expand Down
46 changes: 46 additions & 0 deletions src/components/bcros/todo/dialog/CancelPaymentError.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<script setup lang="ts">
defineEmits<{(e:'close'): void}>()

const prop = defineProps({
display: { type: Boolean, required: true },
errors: { type: Array<any>, required: true }
})

const { isStaffAccount } = useBcrosAccount()

const cancelPaymentDialogOptions = computed(() => {
const title = 'Unable to Cancel Payment'

const text = (prop.errors.length < 1)
? 'We were unable to cancel your payment.'
: 'We were unable to cancel your payment due to the following errors:'

return {
title, text, hideClose: true, buttons: [{ text: 'OK', slotId: 'ok', color: 'primary', onClickClose: true }]
} as DialogOptionsI
})
</script>

<template>
<BcrosDialog
attach="#todoList"
:display="display"
:options="cancelPaymentDialogOptions"
@close="$emit('close')"
>
<template #content>
<p v-for="(error, index) in errors" :key="index">
{{ error.error || error.message }}
</p>
<template v-if="!isStaffAccount">
<p>
If you need help, please contact us.
hfekete marked this conversation as resolved.
Show resolved Hide resolved
</p>
<BcrosContactInfo :contacts="getContactInfo('registries')" class="mt-5" />
</template>
</template>
</BcrosDialog>
</template>

<style scoped>
</style>
57 changes: 57 additions & 0 deletions src/components/bcros/todo/dialog/DeleteError.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<script setup lang="ts">
defineEmits<{(e:'close'): void}>()

const prop = defineProps({
display: { type: Boolean, required: true },
errors: { type: Array<any>, required: true },
warnings: { type: Array<any>, required: true }
})

const { isStaffAccount } = useBcrosAccount()

const deleteErrorDialogOptions = computed(() => {
const title = (prop.errors.length > 0 || prop.warnings.length < 1)
? 'Unable to Delete Filing'
: 'Filing Deleted with Warnings'

let text = ''
if (prop.errors.length + prop.warnings.length < 1) {
text = 'We were unable to delete your filing.'
} else if (prop.errors.length > 0) {
text = 'We were unable to delete your filing due to the following errors:'
} else {
text = 'Please note the following:'
}

return {
title, text, hideClose: true, buttons: [{ text: 'OK', slotId: 'ok', color: 'primary', onClickClose: true }]
} as DialogOptionsI
})
</script>

<template>
<BcrosDialog
attach="#todoList"
:display="display"
:options="deleteErrorDialogOptions"
@close="$emit('close')"
>
<template #content>
<p v-for="(error, index) in errors" :key="index">
{{ error.error || error.message }}
</p>
<p v-for="(warning, index) in warnings" :key="index">
{{ warning.warning || warning.message }}
</p>
<template v-if="!isStaffAccount">
<p>
If you need help, please contact us.
</p>
<BcrosContactInfo :contacts="getContactInfo('registries')" class="mt-5" />
</template>
</template>
</BcrosDialog>
</template>

<style scoped>
</style>
3 changes: 2 additions & 1 deletion src/interfaces/todo-i.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import type { FilingTypes } from '@bcrs-shared-components/enums'

export interface ActionButtonI {
label: string
actionFn: Function
actionFn?: Function
openDialog?: boolean
disabled?: boolean
menus?: ActionButtonI[]
icon?: string
Expand Down
Loading
Loading