You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
6.6 KiB
250 lines
6.6 KiB
<template>
|
|
<NotificationGroup group="customModal">
|
|
<div class="fixed z-[100] top-0 inset-x-0 w-full">
|
|
<Notification
|
|
v-slot="{ notifications, close }"
|
|
enter="transform ease-out duration-300 transition"
|
|
enter-from="translate-y-2 opacity-0 sm:translate-y-4"
|
|
enter-to="translate-y-0 opacity-100 sm:translate-y-0"
|
|
leave="transition ease-in duration-500"
|
|
leave-from="opacity-100"
|
|
leave-to="opacity-0"
|
|
move="transition duration-500"
|
|
move-delay="delay-300"
|
|
>
|
|
<div
|
|
v-for="notification in notifications"
|
|
:key="notification.id"
|
|
class="w-full"
|
|
role="alert"
|
|
>
|
|
<div :class="overlayClasses">
|
|
<div :class="modalContainerClasses">
|
|
<div :class="modalContentClasses">
|
|
<span :class="titleClasses">{{ title }}</span>
|
|
<p :class="textClasses">{{ text }}</p>
|
|
|
|
<button
|
|
:class="option1ButtonClasses"
|
|
@click="handleOption1(close)"
|
|
>
|
|
{{ option1Text }}
|
|
</button>
|
|
|
|
<button
|
|
:class="option2ButtonClasses"
|
|
@click="handleOption2(close)"
|
|
>
|
|
{{ option2Text }}
|
|
</button>
|
|
|
|
<button
|
|
:class="option3ButtonClasses"
|
|
@click="handleOption3(close)"
|
|
>
|
|
{{ option3Text }}
|
|
</button>
|
|
|
|
<button
|
|
:class="cancelButtonClasses"
|
|
@click="handleCancel(close)"
|
|
>
|
|
Cancel
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Notification>
|
|
</div>
|
|
</NotificationGroup>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { Component, Vue } from "vue-facing-decorator";
|
|
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
|
|
|
|
/**
|
|
* ChoiceButtonDialog Component
|
|
*
|
|
* A modal dialog component that displays a custom notification with multiple
|
|
* action buttons. This component uses the notification system to display
|
|
* a modal overlay with custom content and button handlers.
|
|
*
|
|
* Features:
|
|
* - Custom modal overlay with backdrop
|
|
* - Up to 3 action buttons with custom text and handlers
|
|
* - Cancel button with optional handler
|
|
* - Responsive design with proper z-indexing
|
|
* - Smooth enter/leave animations
|
|
*/
|
|
@Component
|
|
export default class PromptDialog extends Vue {
|
|
$notify!: (notification: unknown, timeout?: number) => void;
|
|
notify!: ReturnType<typeof createNotifyHelpers>;
|
|
|
|
title = "";
|
|
text = "";
|
|
option1Text = "";
|
|
option2Text = "";
|
|
option3Text = "";
|
|
onOption1?: () => void;
|
|
onOption2?: () => void;
|
|
onOption3?: () => void;
|
|
onCancel?: () => Promise<void>;
|
|
|
|
created() {
|
|
this.notify = createNotifyHelpers(this.$notify);
|
|
}
|
|
|
|
/**
|
|
* CSS classes for the modal overlay backdrop
|
|
*/
|
|
get overlayClasses(): string {
|
|
return "absolute inset-0 h-screen flex flex-col items-center justify-center bg-slate-900/50";
|
|
}
|
|
|
|
/**
|
|
* CSS classes for the modal container
|
|
*/
|
|
get modalContainerClasses(): string {
|
|
return "flex w-11/12 max-w-sm mx-auto mb-3 overflow-hidden bg-white rounded-lg shadow-lg";
|
|
}
|
|
|
|
/**
|
|
* CSS classes for the modal content area
|
|
*/
|
|
get modalContentClasses(): string {
|
|
return "w-full px-6 py-6 text-slate-900 text-center";
|
|
}
|
|
|
|
/**
|
|
* CSS classes for the modal title
|
|
*/
|
|
get titleClasses(): string {
|
|
return "font-semibold text-lg";
|
|
}
|
|
|
|
/**
|
|
* CSS classes for the modal text content
|
|
*/
|
|
get textClasses(): string {
|
|
return "text-sm mb-2";
|
|
}
|
|
|
|
/**
|
|
* CSS classes for the primary action button (option 1)
|
|
*/
|
|
get option1ButtonClasses(): string {
|
|
return "block w-full text-center text-md font-bold capitalize bg-blue-800 text-white px-2 py-2 rounded-md mb-2";
|
|
}
|
|
|
|
/**
|
|
* CSS classes for the secondary action button (option 2)
|
|
*/
|
|
get option2ButtonClasses(): string {
|
|
return "block w-full text-center text-md font-bold capitalize bg-blue-700 text-white px-2 py-2 rounded-md mb-2";
|
|
}
|
|
|
|
/**
|
|
* CSS classes for the tertiary action button (option 3)
|
|
*/
|
|
get option3ButtonClasses(): string {
|
|
return "block w-full text-center text-md font-bold capitalize bg-blue-600 text-white px-2 py-2 rounded-md mb-2";
|
|
}
|
|
|
|
/**
|
|
* CSS classes for the cancel button
|
|
*/
|
|
get cancelButtonClasses(): string {
|
|
return "block w-full text-center text-md font-bold capitalize bg-slate-600 text-white px-2 py-2 rounded-md";
|
|
}
|
|
|
|
/**
|
|
* Opens the choice button dialog with the specified options
|
|
*
|
|
* @param options - Configuration object containing dialog content and handlers
|
|
*/
|
|
open(options: {
|
|
title: string;
|
|
text: string;
|
|
option1Text?: string;
|
|
option2Text?: string;
|
|
option3Text?: string;
|
|
onOption1?: () => void;
|
|
onOption2?: () => void;
|
|
onOption3?: () => void;
|
|
onCancel?: () => Promise<void>;
|
|
}) {
|
|
this.title = options.title;
|
|
this.text = options.text;
|
|
this.option1Text = options.option1Text || "";
|
|
this.option2Text = options.option2Text || "";
|
|
this.option3Text = options.option3Text || "";
|
|
this.onOption1 = options.onOption1;
|
|
this.onOption2 = options.onOption2;
|
|
this.onOption3 = options.onOption3;
|
|
this.onCancel = options.onCancel;
|
|
|
|
// Use customModal notification type instead of confirm
|
|
this.$notify(
|
|
{
|
|
group: "customModal",
|
|
type: "custom",
|
|
title: this.title,
|
|
text: this.text,
|
|
id: "choice-button-dialog",
|
|
},
|
|
TIMEOUTS.MODAL,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Handles the primary action button click
|
|
*
|
|
* @param close - Function to close the notification
|
|
*/
|
|
handleOption1(close: (id: string) => void) {
|
|
if (this.onOption1) {
|
|
this.onOption1();
|
|
}
|
|
close("string that does not matter");
|
|
}
|
|
|
|
/**
|
|
* Handles the secondary action button click
|
|
*
|
|
* @param close - Function to close the notification
|
|
*/
|
|
handleOption2(close: (id: string) => void) {
|
|
if (this.onOption2) {
|
|
this.onOption2();
|
|
}
|
|
close("string that does not matter");
|
|
}
|
|
|
|
/**
|
|
* Handles the tertiary action button click
|
|
*
|
|
* @param close - Function to close the notification
|
|
*/
|
|
handleOption3(close: (id: string) => void) {
|
|
if (this.onOption3) {
|
|
this.onOption3();
|
|
}
|
|
close("string that does not matter");
|
|
}
|
|
|
|
/**
|
|
* Handles the cancel button click
|
|
*
|
|
* @param close - Function to close the notification
|
|
*/
|
|
handleCancel(close: (id: string) => void) {
|
|
if (this.onCancel) {
|
|
this.onCancel();
|
|
}
|
|
close("string that does not matter");
|
|
}
|
|
}
|
|
</script>
|
|
|