Files
thrillwiki_django_no_react/frontend/src/components/auth/AuthModal.vue
pacnpal e62646bcf9 feat: major API restructure and Vue.js frontend integration
- Centralize API endpoints in dedicated api app with v1 versioning
- Remove individual API modules from parks and rides apps
- Add event tracking system with analytics functionality
- Integrate Vue.js frontend with Tailwind CSS v4 and TypeScript
- Add comprehensive database migrations for event tracking
- Implement user authentication and social provider setup
- Add API schema documentation and serializers
- Configure development environment with shared scripts
- Update project structure for monorepo with frontend/backend separation
2025-08-24 16:42:20 -04:00

104 lines
3.0 KiB
Vue

<template>
<Teleport to="body">
<Transition
enter-active-class="duration-300 ease-out"
enter-from-class="opacity-0"
enter-to-class="opacity-100"
leave-active-class="duration-200 ease-in"
leave-from-class="opacity-100"
leave-to-class="opacity-0"
>
<div
v-if="show"
class="fixed inset-0 z-50 overflow-y-auto"
@click="closeOnBackdrop && handleBackdropClick"
>
<!-- Backdrop -->
<div class="fixed inset-0 bg-black/50 backdrop-blur-sm"></div>
<!-- Modal Container -->
<div class="flex min-h-full items-center justify-center p-4">
<Transition
enter-active-class="duration-300 ease-out"
enter-from-class="opacity-0 scale-95"
enter-to-class="opacity-100 scale-100"
leave-active-class="duration-200 ease-in"
leave-from-class="opacity-100 scale-100"
leave-to-class="opacity-0 scale-95"
>
<div
v-if="show"
class="relative w-full max-w-md transform overflow-hidden rounded-2xl bg-white dark:bg-gray-800 shadow-2xl transition-all"
@click.stop
>
<!-- Header -->
<div class="flex items-center justify-between p-6 pb-4">
<h2 class="text-2xl font-bold text-gray-900 dark:text-white">
{{ title }}
</h2>
<button
@click="$emit('close')"
class="rounded-lg p-2 text-gray-400 hover:bg-gray-100 hover:text-gray-600 dark:hover:bg-gray-700 dark:hover:text-gray-300 transition-colors"
>
<svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
<!-- Content -->
<div class="px-6 pb-6">
<slot />
</div>
</div>
</Transition>
</div>
</div>
</Transition>
</Teleport>
</template>
<script setup lang="ts">
import { watch, toRefs, onUnmounted } from 'vue'
interface Props {
show: boolean
title: string
closeOnBackdrop?: boolean
}
const props = withDefaults(defineProps<Props>(), {
closeOnBackdrop: true,
})
const emit = defineEmits<{
close: []
}>()
const handleBackdropClick = (event: MouseEvent) => {
if (props.closeOnBackdrop && event.target === event.currentTarget) {
emit('close')
}
}
// Prevent body scroll when modal is open
const { show } = toRefs(props)
watch(show, (isShown) => {
if (isShown) {
document.body.style.overflow = 'hidden'
} else {
document.body.style.overflow = ''
}
})
// Clean up on unmount
onUnmounted(() => {
document.body.style.overflow = ''
})
</script>