Files
FEDEO/frontend/components/PageLeaveGuard.vue
florianfederspiel b35c991634
All checks were successful
Build and Push Docker Images / build-backend (push) Successful in 17s
Build and Push Docker Images / build-frontend (push) Successful in 5m52s
Fixed PageLeaveGuard.vue Dark Mode
2026-01-10 19:49:28 +01:00

168 lines
4.1 KiB
Vue

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue'
import { onBeforeRouteLeave } from 'vue-router'
const props = defineProps<{
when: boolean
}>()
const showModal = ref(false)
const pendingNext = ref<null | ((val?: boolean) => void)>(null)
// --- 1. Interne Navigation ---
onBeforeRouteLeave((to, from, next) => {
if (!props.when) {
next()
return
}
pendingNext.value = next
showModal.value = true
})
const confirmLeave = () => {
if (pendingNext.value) pendingNext.value()
showModal.value = false
}
const cancelLeave = () => {
showModal.value = false
// Navigation abbrechen (pendingNext verfällt)
}
// --- 2. Browser Tab schließen ---
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
if (props.when) {
e.preventDefault()
e.returnValue = ''
}
}
onMounted(() => window.addEventListener('beforeunload', handleBeforeUnload))
onBeforeUnmount(() => window.removeEventListener('beforeunload', handleBeforeUnload))
</script>
<template>
<Teleport to="body">
<div v-if="showModal" class="guard-overlay">
<div class="guard-modal">
<div class="guard-header">
<slot name="title">Seite verlassen?</slot>
</div>
<div class="guard-body">
<slot>
Du hast ungespeicherte Änderungen. Wenn du die Seite verlässt, gehen diese verloren.
</slot>
</div>
<div class="guard-actions">
<button @click="cancelLeave" class="btn-cancel">
Nein, bleiben
</button>
<button @click="confirmLeave" class="btn-confirm">
Ja, verwerfen
</button>
</div>
</div>
</div>
</Teleport>
</template>
<style scoped>
/* --- Layout & Animation --- */
.guard-overlay {
position: fixed; inset: 0;
background: rgba(0,0,0,0.5);
display: flex; align-items: center; justify-content: center;
z-index: 9999; backdrop-filter: blur(4px);
transition: opacity 0.2s;
}
.guard-modal {
width: 90%; max-width: 420px;
border-radius: 12px;
padding: 24px;
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
font-family: ui-sans-serif, system-ui, -apple-system, sans-serif;
}
.guard-header {
font-size: 1.125rem; font-weight: 600; margin-bottom: 0.75rem;
}
.guard-body {
margin-bottom: 1.5rem; font-size: 0.95rem; line-height: 1.5;
}
.guard-actions {
display: flex; justify-content: flex-end; gap: 12px;
}
/* --- Buttons Basis --- */
button {
padding: 8px 16px; border-radius: 6px; cursor: pointer; border: none; font-weight: 500; font-size: 0.9rem;
transition: background-color 0.2s;
}
/* --------------------------------------------------------- */
/* LIGHT MODE (Default) */
/* --------------------------------------------------------- */
.guard-modal {
background: white;
color: #1f2937; /* gray-800 */
}
.guard-body {
color: #4b5563; /* gray-600 */
}
.btn-cancel {
background: #f3f4f6; /* gray-100 */
color: #374151; /* gray-700 */
}
.btn-cancel:hover { background: #e5e7eb; }
.btn-confirm {
background: #ef4444; /* red-500 */
color: white;
}
.btn-confirm:hover { background: #dc2626; }
/* --------------------------------------------------------- */
/* DARK MODE OVERRIDES */
/* Wir nutzen :global(.dark), um auf die Klasse im <html>/<body> zuzugreifen */
/* --------------------------------------------------------- */
:global(.dark) .guard-overlay {
background: rgba(0,0,0,0.7);
}
:global(.dark) .guard-modal {
background: #1f2937; /* gray-800 */
color: #f3f4f6; /* gray-100 */
border: 1px solid #374151; /* gray-700 Border für Kontrast */
}
:global(.dark) .guard-body {
color: #9ca3af; /* gray-400 */
}
:global(.dark) .btn-cancel {
background: #374151; /* gray-700 */
color: #e5e7eb; /* gray-200 */
}
:global(.dark) .btn-cancel:hover {
background: #4b5563; /* gray-600 */
}
/* Confirm Button bleibt rot, aber evtl. leicht angepasst */
:global(.dark) .btn-confirm {
background: #b91c1c; /* red-700 (etwas dunkler für Darkmode angenehmer) */
color: #fecaca; /* red-100 Text */
}
:global(.dark) .btn-confirm:hover {
background: #991b1b;
}
</style>