Refactor ChoiceButtonDialog.vue: streamline template, improve typing

- Extracted all long/repeated CSS class strings in template to computed properties for maintainability
- Added/updated file-level and method-level documentation with comprehensive JSDoc comments
- Replaced $notify type from 'any' to 'unknown' for improved type safety
- Confirmed notification usage is already modern and follows project standards
- No databaseUtil or SQL abstraction required (pure UI component)
- Lint validation successful (no errors, only unrelated warnings remain)
- Migration tracking documents updated with timing and performance metrics

Technical improvements:
- 7 computed properties for CSS classes (overlay, modal, buttons, etc.)
- Enhanced type safety with proper TypeScript types
- Improved code maintainability and readability
- Follows Enhanced Triple Migration Pattern Phase 4 (Template Streamlining)

Migration completed in 7 minutes (13% faster than 8-12 min estimate)
This commit is contained in:
Matthew Raymer
2025-07-09 08:21:03 +00:00
parent 94fa14e9a3
commit be19c58d68
7 changed files with 173 additions and 40 deletions

View File

@@ -18,39 +18,35 @@
class="w-full"
role="alert"
>
<div
class="absolute inset-0 h-screen flex flex-col items-center justify-center bg-slate-900/50"
>
<div
class="flex w-11/12 max-w-sm mx-auto mb-3 overflow-hidden bg-white rounded-lg shadow-lg"
>
<div class="w-full px-6 py-6 text-slate-900 text-center">
<span class="font-semibold text-lg">{{ title }}</span>
<p class="text-sm mb-2">{{ text }}</p>
<div :class="overlayClasses">
<div :class="modalContainerClasses">
<div :class="modalContentClasses">
<span :class="titleClasses">{{ title }}</span>
<p :class="textClasses">{{ text }}</p>
<button
class="block w-full text-center text-md font-bold capitalize bg-blue-800 text-white px-2 py-2 rounded-md mb-2"
:class="option1ButtonClasses"
@click="handleOption1(close)"
>
{{ option1Text }}
</button>
<button
class="block w-full text-center text-md font-bold capitalize bg-blue-700 text-white px-2 py-2 rounded-md mb-2"
:class="option2ButtonClasses"
@click="handleOption2(close)"
>
{{ option2Text }}
</button>
<button
class="block w-full text-center text-md font-bold capitalize bg-blue-600 text-white px-2 py-2 rounded-md mb-2"
:class="option3ButtonClasses"
@click="handleOption3(close)"
>
{{ option3Text }}
</button>
<button
class="block w-full text-center text-md font-bold capitalize bg-slate-600 text-white px-2 py-2 rounded-md"
:class="cancelButtonClasses"
@click="handleCancel(close)"
>
Cancel
@@ -68,9 +64,23 @@
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: any, timeout?: number) => void;
$notify!: (notification: unknown, timeout?: number) => void;
notify!: ReturnType<typeof createNotifyHelpers>;
title = "";
@@ -87,6 +97,74 @@ export default class PromptDialog extends Vue {
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;
@@ -115,6 +193,11 @@ export default class PromptDialog extends Vue {
);
}
/**
* Handles the primary action button click
*
* @param close - Function to close the notification
*/
handleOption1(close: (id: string) => void) {
if (this.onOption1) {
this.onOption1();
@@ -122,6 +205,11 @@ export default class PromptDialog extends Vue {
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();
@@ -129,6 +217,11 @@ export default class PromptDialog extends Vue {
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();
@@ -136,6 +229,11 @@ export default class PromptDialog extends Vue {
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();