diff --git a/package-lock.json b/package-lock.json index d50055c1..79f50b29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "pusher-js": "^8.3.0", "svg-sprite": "^2.0.2", "typescript-eslint": "^8.34.0", + "uuid": "^11.1.0", "vite": "^4.5.2", "vue": "^3.3.4", "vue-toastification": "^2.0.0-rc.5", @@ -4830,6 +4831,18 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/vinyl": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", diff --git a/package.json b/package.json index 92189186..17c10520 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "pusher-js": "^8.3.0", "svg-sprite": "^2.0.2", "typescript-eslint": "^8.34.0", + "uuid": "^11.1.0", "vite": "^4.5.2", "vue": "^3.3.4", "vue-toastification": "^2.0.0-rc.5", diff --git a/resources/js/components/components.d.ts b/resources/js/components/components.d.ts index 569cf765..3cf9770f 100644 --- a/resources/js/components/components.d.ts +++ b/resources/js/components/components.d.ts @@ -25,6 +25,7 @@ declare module 'vue' { PageFullLayout: typeof import('@/components/page/FullLayout.vue')['default'] PageHeader: typeof import('@/components/page/Header.vue')['default'] PageLayout: typeof import('@/components/page/Layout.vue')['default'] + PagePopups: typeof import('@/components/page/Popups.vue')['default'] PageSearchModal: typeof import('@/components/page/SearchModal.vue')['default'] PageTitle: typeof import('@/components/page/Title.vue')['default'] PageToolbarButton: typeof import('@/components/page/ToolbarButton.vue')['default'] diff --git a/resources/js/components/page/Popups.vue b/resources/js/components/page/Popups.vue new file mode 100644 index 00000000..fc47ab08 --- /dev/null +++ b/resources/js/components/page/Popups.vue @@ -0,0 +1,18 @@ + + + + + + + {{ popup.confirmButton }} + {{ popup.cancelButton }} + + + + + + + diff --git a/resources/js/layouts/AppLayout.vue b/resources/js/layouts/AppLayout.vue index 0b39def8..5d68a588 100644 --- a/resources/js/layouts/AppLayout.vue +++ b/resources/js/layouts/AppLayout.vue @@ -32,6 +32,8 @@ + + diff --git a/resources/js/stores/swalStore.ts b/resources/js/stores/swalStore.ts new file mode 100644 index 00000000..3aecf810 --- /dev/null +++ b/resources/js/stores/swalStore.ts @@ -0,0 +1,46 @@ +import { defineStore } from 'pinia'; +import { v4 as uuidv4 } from 'uuid'; + + +interface Popup { + id: string; + title: string; + body: string; + confirmButton: string; + cancelButton: string; + resolve: (id: string) => void; + reject: (id: string) => void; +} + +export default defineStore('swal', { + state: () => ({ + popups: [] as Popup[], + }), + actions: { + confirm(title: string, body: string): Promise { + return new Promise((resolve, reject) => { + new Promise((resolve, reject) => { + this.popups.push({ + title, + body, + confirmButton: 'Okay', + cancelButton: 'Abbrechen', + resolve, + reject, + id: uuidv4(), + }); + }).then((id) => { + this.remove(id); + resolve(); + }).catch((id) => { + this.remove(id); + reject(); + }); + }); + }, + + remove(id: string) { + this.popups = this.popups.filter(p => p.id !== id); + } + }, +}); diff --git a/resources/js/views/form/Index.vue b/resources/js/views/form/Index.vue index 073d81d0..92c8f541 100644 --- a/resources/js/views/form/Index.vue +++ b/resources/js/views/form/Index.vue @@ -198,6 +198,7 @@ import Participants from './Participants.vue'; import Conditions from './Conditions.vue'; import ConditionsForm from './ConditionsForm.vue'; import { useToast } from 'vue-toastification'; +import useSwal from '@/stores/swalStore.ts'; const props = defineProps(indexProps); const { meta, data, reloadPage, reload, create, single, edit, cancel, submit, remove, getFilter, setFilter } = useIndex(props.data, 'form'); @@ -212,6 +213,7 @@ const active = ref(0); const activeMailTab = ref(0); const tabs = [{ title: 'Allgemeines' }, { title: 'Beschreibung' }, { title: 'Formular' }, { title: 'Bestätigungs-E-Mail' }, { title: 'Export' }, { title: 'Prävention' }]; const mailTabs = [{ title: 'vor Daten' }, { title: 'nach Daten' }]; +const swal = useSwal(); const allFields = computed(() => { if (!single.value) { @@ -229,6 +231,7 @@ const allFields = computed(() => { }); async function onCopy(form) { + await swal.confirm('Diese Veranstaltung kopieren?', 'Nach dem Kopieren wird die Veranstaltung auf inaktiv gesetzt. Bitte aktiviere den Filter "inaktive zeigen", um die kopierte Veranstaltung zu sehen.'); await axios.post(form.links.copy, {}); reload(false); }