Skip to content

Commit 6af187b

Browse files
authored
Merge pull request #21108 from itisAliRH/enhance-confirm-dialog-typescript
Enhance Confirm Dialog Types and More
2 parents 9495aa9 + 9e8b680 commit 6af187b

File tree

4 files changed

+276
-50
lines changed

4 files changed

+276
-50
lines changed

client/src/components/Common/GCard.types.ts

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,11 @@
11
import type { SizeProp } from "@fortawesome/fontawesome-svg-core";
22
import type { IconDefinition } from "@fortawesome/free-solid-svg-icons";
33

4+
import type { BootstrapVariant } from "@/components/Common";
5+
46
/** Card badge display styles */
57
export type CardBadgeType = "pill" | "badge";
68

7-
/** Bootstrap color variants for theming */
8-
export type BootstrapVariant =
9-
| "danger"
10-
| "dark"
11-
| "info"
12-
| "light"
13-
| "link"
14-
| "primary"
15-
| "secondary"
16-
| "success"
17-
| "warning"
18-
| "outline-danger"
19-
| "outline-dark"
20-
| "outline-info"
21-
| "outline-light"
22-
| "outline-primary"
23-
| "outline-secondary"
24-
| "outline-success"
25-
| "outline-warning";
26-
279
/** Bootstrap component sizes */
2810
export type BootstrapSize = "xs" | "sm" | "md" | "lg" | "xl";
2911

client/src/components/Common/index.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,29 @@
11
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
22
import type { RawLocation } from "vue-router";
33

4-
// TODO: Not sure if this is the best place for this type
4+
/**
5+
* Basic color variants for components that only support
6+
* color-based styling like alerts, badges, and backgrounds (no outline variants).
7+
*/
58
export type ColorVariant = "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "light" | "dark";
69

10+
/**
11+
* Bootstrap Vue variants for styling components.
12+
* Includes basic color variants plus outline variants for buttons and modals.
13+
*/
14+
export type BootstrapVariant =
15+
| ColorVariant
16+
| "link"
17+
| "outline-primary"
18+
| "outline-secondary"
19+
| "outline-success"
20+
| "outline-danger"
21+
| "outline-warning"
22+
| "outline-info"
23+
| "outline-light"
24+
| "outline-link"
25+
| "outline-dark";
26+
727
/**
828
* Represents a breadcrumb item in the BreadcrumbHeading component.
929
* Each item can have a title, an optional URL to navigate to, and optional additional text

client/src/composables/confirmDialog.js

Lines changed: 0 additions & 29 deletions
This file was deleted.
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
import { type Ref, ref } from "vue";
2+
3+
import type { BootstrapVariant } from "@/components/Common";
4+
5+
/**
6+
* Bootstrap Vue modal message box options interface.
7+
* Based on https://bootstrap-vue.org/docs/components/modal#modal-message-boxes
8+
*/
9+
export interface ConfirmDialogOptions {
10+
/**
11+
* Unique identifier for the modal
12+
*/
13+
id?: string;
14+
/**
15+
* Modal title
16+
* @default "Please Confirm"
17+
*/
18+
title?: string;
19+
/**
20+
* CSS classes for title
21+
* @default "h-md"
22+
*/
23+
titleClass?: string;
24+
/**
25+
* Modal size: 'sm', 'lg', 'xl'
26+
* @default undefined (medium)
27+
*/
28+
size?: "sm" | "lg" | "xl";
29+
/**
30+
* Center modal vertically
31+
* @default true
32+
*/
33+
centered?: boolean;
34+
/**
35+
* Make modal body scrollable
36+
* @default false
37+
*/
38+
scrollable?: boolean;
39+
/**
40+
* Text for OK button
41+
* @default "OK"
42+
*/
43+
okTitle?: string;
44+
/**
45+
* Bootstrap variant for OK button
46+
* @default "primary"
47+
*/
48+
okVariant?: BootstrapVariant;
49+
/**
50+
* Text for cancel button
51+
* @default "Cancel"
52+
*/
53+
cancelTitle?: string;
54+
/**
55+
* Bootstrap variant for cancel button
56+
* @default "outline-primary"
57+
*/
58+
cancelVariant?: BootstrapVariant;
59+
/**
60+
* Footer button size: 'sm', 'lg'
61+
* @default undefined (normal)
62+
*/
63+
buttonSize?: "sm" | "lg";
64+
/**
65+
* Hide header close button
66+
* @default false
67+
*/
68+
hideHeaderClose?: boolean;
69+
/**
70+
* CSS classes for header
71+
*/
72+
headerClass?: string;
73+
/**
74+
* Background variant for header
75+
*/
76+
headerBgVariant?: BootstrapVariant;
77+
/**
78+
* Text variant for header
79+
*/
80+
headerTextVariant?: BootstrapVariant;
81+
/**
82+
* CSS classes for modal body
83+
*/
84+
bodyClass?: string;
85+
/**
86+
* Background variant for body
87+
*/
88+
bodyBgVariant?: BootstrapVariant;
89+
/**
90+
* Text variant for body
91+
*/
92+
bodyTextVariant?: BootstrapVariant;
93+
/**
94+
* CSS classes for footer
95+
*/
96+
footerClass?: string;
97+
/**
98+
* Background variant for footer
99+
*/
100+
footerBgVariant?: BootstrapVariant;
101+
/**
102+
* Text variant for footer
103+
*/
104+
footerTextVariant?: BootstrapVariant;
105+
/**
106+
* Prevent closing on backdrop click
107+
* @default false
108+
*/
109+
noCloseOnBackdrop?: boolean;
110+
/**
111+
* Prevent closing on ESC key
112+
* @default false
113+
*/
114+
noCloseOnEsc?: boolean;
115+
/**
116+
* Auto-focus button: 'ok', 'cancel', 'close'
117+
* @default undefined
118+
*/
119+
autoFocusButton?: "ok" | "cancel" | "close";
120+
/**
121+
* Element to return focus to
122+
* @default undefined
123+
*/
124+
returnFocus?: string | HTMLElement;
125+
/**
126+
* CSS classes for modal container
127+
* @default undefined
128+
*/
129+
modalClass?: string;
130+
/**
131+
* CSS classes for modal dialog wrapper
132+
* @default undefined
133+
*/
134+
dialogClass?: string;
135+
/**
136+
* CSS classes for modal content
137+
* @default undefined
138+
*/
139+
contentClass?: string;
140+
/**
141+
* Disable fade animation
142+
* @default false
143+
*/
144+
noFade?: boolean;
145+
/**
146+
* Hide modal backdrop
147+
* @default false
148+
*/
149+
hideBackdrop?: boolean;
150+
}
151+
152+
/**
153+
* Interface for the confirm dialog component reference.
154+
*/
155+
interface ConfirmDialogComponent {
156+
confirm(message: string, options?: ConfirmDialogOptions): Promise<boolean>;
157+
}
158+
159+
/**
160+
* Default configuration for confirm dialogs.
161+
* Can be modified to change application-wide defaults.
162+
*/
163+
export const DEFAULT_CONFIRM_OPTIONS: Partial<ConfirmDialogOptions> = {
164+
title: "Please Confirm",
165+
titleClass: "h-md",
166+
centered: true,
167+
okTitle: "OK",
168+
cancelTitle: "Cancel",
169+
okVariant: "primary",
170+
cancelVariant: "outline-primary",
171+
buttonSize: undefined, // Uses Bootstrap default size
172+
hideHeaderClose: false,
173+
noCloseOnBackdrop: false,
174+
noCloseOnEsc: false,
175+
noFade: false,
176+
hideBackdrop: false,
177+
scrollable: false,
178+
} as const;
179+
180+
/**
181+
* Reference to the confirm dialog component instance
182+
*/
183+
let confirmDialogRef: Ref<ConfirmDialogComponent | null> = ref(null);
184+
185+
/**
186+
* Sets the confirm dialog component reference.
187+
* @param newRef - The new component reference
188+
*/
189+
export const setConfirmDialogComponentRef = (newRef: ConfirmDialogComponent | null): void => {
190+
// eslint-disable-next-line vue/no-ref-as-operand
191+
confirmDialogRef = ref(newRef);
192+
};
193+
194+
/**
195+
* Internal function to validate and normalize confirm dialog options.
196+
* @param options - Raw options to normalize
197+
* @returns Normalized options with defaults applied
198+
*/
199+
function normalizeConfirmOptions(options: ConfirmDialogOptions | string): ConfirmDialogOptions {
200+
// Handle backward compatibility: if options is a string, treat it as title
201+
const baseOptions: ConfirmDialogOptions = typeof options === "string" ? { title: options } : options;
202+
203+
return {
204+
...DEFAULT_CONFIRM_OPTIONS,
205+
...baseOptions,
206+
};
207+
}
208+
209+
/**
210+
* Direct export for Options API components.
211+
* For Composition API, use `useConfirmDialog` instead.
212+
*/
213+
export const ConfirmDialog = {
214+
/**
215+
* Shows a confirmation dialog to the user.
216+
* @param message - The confirmation message to display
217+
* @param options - Dialog options object or title string (for backward compatibility)
218+
* @returns Promise resolving to `true` if confirmed, `false` if cancelled/closed
219+
* @throws {Error} When confirm dialog component reference is not set
220+
*/
221+
async confirm(message: string, options: ConfirmDialogOptions | string = {}): Promise<boolean> {
222+
if (!confirmDialogRef.value) {
223+
throw new Error(
224+
"Confirm dialog component reference not set. " +
225+
"Call setConfirmDialogComponentRef() during app initialization.",
226+
);
227+
}
228+
229+
if (typeof message !== "string" || message.trim().length === 0) {
230+
throw new Error("Confirm dialog message must be a non-empty string.");
231+
}
232+
233+
const normalizedOptions = normalizeConfirmOptions(options);
234+
235+
try {
236+
return await confirmDialogRef.value.confirm(message, normalizedOptions);
237+
} catch (error) {
238+
console.error("Confirm dialog error:", error);
239+
// Gracefully handle component errors by returning false (cancelled)
240+
return false;
241+
}
242+
},
243+
};
244+
245+
/**
246+
* Composable for using confirm dialog in Composition API components.
247+
* Returns a stable reference to avoid unnecessary re-renders.
248+
*
249+
* @returns Object containing confirm dialog methods
250+
*/
251+
export function useConfirmDialog() {
252+
return { ...ConfirmDialog };
253+
}

0 commit comments

Comments
 (0)