1<template>
2 <Dialog v-model:open="isOpen" :title="title" @close="closeDialog">
3 <template #default>
4 <div class="space-y-4">
5 <p
6 class="text-p-base text-ink-gray-8"
7 v-if="message"
8 v-html="message"
9 />
10 </div>
11 </template>
12 <template #actions>
13 <Button
14 class="w-full"
15 label="Confirm"
16 variant="solid"
17 :loading="isLoading"
18 @click="onConfirm"
19 />
20 </template>
21 </Dialog>
22</template>
23<script>
24import { Button, Dialog } from "frappe-ui";
25
26export default {
27 name: "ConfirmDialog",
28 props: {
29 title: {
30 type: String,
31 },
32 message: {
33 type: String,
34 },
35 // Optional v-model; when absent, visibility falls back to the internal
36 // state (open on mount), preserving the `v-if` + `show()`/`hide()` mode.
37 modelValue: {
38 type: Boolean,
39 default: undefined,
40 },
41 onConfirm: {
42 type: Function,
43 default: null,
44 },
45 onCancel: {
46 type: Function,
47 default: null,
48 },
49 },
50 emits: ["update:modelValue"],
51 expose: ["show", "hide"],
52 components: {
53 Dialog,
54 Button,
55 },
56 data() {
57 return {
58 showDialog: true,
59 isLoading: false,
60 };
61 },
62 computed: {
63 isOpen: {
64 get() {
65 return this.modelValue !== undefined
66 ? this.modelValue
67 : this.showDialog;
68 },
69 set(value) {
70 this.showDialog = value;
71 this.$emit("update:modelValue", value);
72 },
73 },
74 },
75 methods: {
76 async handleConfirmation() {
77 if (this.isLoading) return;
78 this.isLoading = true;
79 try {
80 if (this.onConfirm) {
81 await this.onConfirm({
82 hideDialog: this.hide,
83 });
84 }
85 this.hide();
86 } catch (error) {
87 console.error("Error in confirmation:", error);
88 } finally {
89 this.isLoading = false;
90 }
91 },
92 show() {
93 this.isOpen = true;
94 },
95 closeDialog() {
96 this.hide();
97 this.onCancel?.();
98 },
99 hide() {
100 this.isOpen = false;
101 },
102 },
103};
104</script>
105