Nyavokevin 9a708da8ae
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
add image
2025-10-01 13:45:54 +03:00

305 lines
14 KiB
Vue

<script setup lang="ts">
import DatePicker from '@/components/DatePicker.vue';
import LandingLayout from '@/layouts/app/LandingLayout.vue';
import { loadStripe } from '@stripe/stripe-js';
import axios from 'axios';
import { ref } from 'vue';
interface UserForm {
fullname: string;
email: string;
}
const userForm = ref<UserForm>({
fullname: '',
email: '',
});
const selectedDate = ref(new Date());
const loading = ref<boolean>(false);
const handleAppointment = () => {
redirectToStipeCheckout();
};
const redirectToStipeCheckout = async () => {
loading.value = true;
try {
const res = await axios.post('/checkout-rendez-vous', {
userForm: userForm.value,
selectedDate: selectedDate.value,
});
const sessionId = res.data.sessionId;
const stripe = await loadStripe(import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY!);
if (stripe) {
const { error } = await stripe.redirectToCheckout({ sessionId });
if (error) {
console.error('Stripe redirect error:', error.message);
}
}
} catch (error) {
console.error('Error initiating Stripe checkout:', error);
} finally {
loading.value = false;
}
};
</script>
<template>
<LandingLayout>
<!-- Background container with dark mystic theme -->
<div class="relative min-h-screen bg-gradient-to-br from-purple-900 via-violet-900 to-indigo-900">
<!-- Animated background elements -->
<div class="absolute inset-0 overflow-hidden">
<!-- Floating particles -->
<div
v-for="i in 12"
:key="'particle-' + i"
class="floating-particle absolute rounded-full bg-white/10"
:style="{
width: `${Math.random() * 6 + 2}px`,
height: `${Math.random() * 6 + 2}px`,
top: `${Math.random() * 100}%`,
left: `${Math.random() * 100}%`,
animationDelay: `${Math.random() * 5}s`,
}"
></div>
<!-- Glow effects -->
<div class="glow-effect glow-1"></div>
<div class="glow-effect glow-2"></div>
<div class="glow-effect glow-3"></div>
</div>
<!-- Main content -->
<main class="relative z-10 flex flex-1 justify-center px-4 py-12 sm:px-6 sm:py-16 lg:px-8 lg:py-20">
<div class="layout-content-container flex w-full max-w-6xl flex-col items-center gap-12 lg:gap-16">
<!-- Header Section -->
<div class="max-w-3xl text-center">
<h1 class="mb-6 text-4xl font-bold text-white sm:text-5xl lg:text-6xl">Réservez votre consultation</h1>
<p class="mx-auto max-w-2xl text-lg text-white/80 sm:text-xl">
Choisissez la date de votre consultation spirituelle et laissez-vous guider vers l'éclaircissement
</p>
</div>
<!-- Main Content Container -->
<div class="flex w-full flex-col items-center justify-center gap-12 lg:flex-row lg:items-start lg:gap-16 xl:gap-20">
<!-- Date Picker Card -->
<div class="w-full max-w-md lg:max-w-lg">
<div class="rounded-2xl border border-white/20 bg-black/30 p-6 shadow-2xl backdrop-blur-sm">
<div class="mb-6 text-center">
<h2 class="text-2xl font-bold text-white">Choisissez votre date</h2>
<p class="mt-2 text-white/70">Sélectionnez le moment parfait pour votre guidance</p>
</div>
<date-picker v-model:selectedDate="selectedDate" />
</div>
</div>
<!-- Form Card -->
<div class="w-full max-w-md">
<div class="rounded-2xl border border-white/20 bg-black/30 p-8 shadow-2xl backdrop-blur-sm">
<div class="mb-8 text-center">
<div class="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-full bg-purple-500/20">
<svg class="h-6 w-6 text-purple-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
/>
</svg>
</div>
<h2 class="text-2xl font-bold text-white">Vos informations</h2>
<p class="mt-2 text-white/70">Remplissez vos coordonnées pour finaliser la réservation</p>
</div>
<form class="flex flex-col gap-6" @submit.prevent="handleAppointment">
<!-- Name Input -->
<div class="group">
<label class="mb-3 block text-sm font-semibold text-white" for="name"> Nom complet </label>
<div class="relative">
<input
class="w-full rounded-xl border-2 border-purple-500/30 bg-black/40 p-4 text-base text-white transition-all duration-300 placeholder:text-white/40 focus:border-purple-400 focus:bg-black/60 focus:shadow-lg focus:ring-2 focus:ring-purple-400/20"
id="name"
name="name"
placeholder="Votre nom complet"
type="text"
v-model="userForm.fullname"
required
/>
</div>
</div>
<!-- Email Input -->
<div class="group">
<label class="mb-3 block text-sm font-semibold text-white" for="email"> Adresse e-mail </label>
<div class="relative">
<input
class="w-full rounded-xl border-2 border-purple-500/30 bg-black/40 p-4 text-base text-white transition-all duration-300 placeholder:text-white/40 focus:border-purple-400 focus:bg-black/60 focus:shadow-lg focus:ring-2 focus:ring-purple-400/20"
id="email"
name="email"
placeholder="Votre adresse e-mail"
type="email"
v-model="userForm.email"
required
/>
</div>
</div>
<!-- Selected Date Display -->
<div class="rounded-xl border border-purple-500/20 bg-purple-900/20 p-4">
<p class="mb-1 text-sm font-medium text-white">Date sélectionnée :</p>
<p class="text-lg font-semibold text-purple-300">
{{
selectedDate.toLocaleDateString('fr-FR', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
})
}}
</p>
</div>
<!-- Submit Button -->
<button
class="group relative mt-4 flex h-14 w-full cursor-pointer items-center justify-center overflow-hidden rounded-xl bg-gradient-to-r from-purple-600 to-violet-600 px-8 text-lg font-bold tracking-wide text-white shadow-lg transition-all duration-500 hover:from-purple-500 hover:to-violet-500 hover:shadow-xl disabled:cursor-not-allowed disabled:opacity-50"
type="submit"
:disabled="loading || !userForm.fullname || !userForm.email"
>
<!-- Shine effect -->
<span
class="absolute inset-0 -translate-x-full -skew-x-12 transform bg-gradient-to-r from-transparent via-white/30 to-transparent transition-transform duration-700 group-hover:translate-x-full"
></span>
<!-- Button content -->
<span class="relative z-10 flex items-center gap-3">
<svg v-if="loading" class="h-5 w-5 animate-spin" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
<span>{{ loading ? 'Traitement...' : 'Confirmer et Payer' }}</span>
<svg
v-if="!loading"
class="h-5 w-5 transition-transform duration-300 group-hover:translate-x-1"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6" />
</svg>
</span>
</button>
<!-- Security Note -->
<p class="mt-4 text-center text-xs text-white/60">
🔒 Paiement sécurisé via Stripe. Vos informations sont protégées.
</p>
</form>
</div>
</div>
</div>
<!-- Additional Information -->
<div class="mt-8 max-w-2xl text-center">
<div
class="inline-flex items-center gap-4 rounded-2xl border border-white/20 bg-black/30 px-6 py-4 text-sm text-white/70 backdrop-blur-sm"
>
<svg class="h-5 w-5 text-purple-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
/>
</svg>
<span>Consultation confidentielle Guidance personnalisée Support après séance</span>
</div>
</div>
</div>
</main>
</div>
</LandingLayout>
</template>
<style scoped>
/* Floating particles animation */
@keyframes float {
0%,
100% {
transform: translateY(0) rotate(0deg);
opacity: 0;
}
50% {
opacity: 1;
}
100% {
transform: translateY(-100px) rotate(180deg);
opacity: 0;
}
}
.floating-particle {
animation: float 8s ease-in-out infinite;
}
/* Glow effects */
@keyframes glowPulse {
0%,
100% {
opacity: 0.3;
transform: scale(1);
}
50% {
opacity: 0.6;
transform: scale(1.1);
}
}
.glow-effect {
position: absolute;
border-radius: 50%;
filter: blur(60px);
animation: glowPulse 8s ease-in-out infinite;
pointer-events: none;
}
.glow-1 {
width: 300px;
height: 300px;
background: radial-gradient(circle, rgba(168, 85, 247, 0.4) 0%, transparent 70%);
top: 20%;
left: 10%;
animation-delay: 0s;
}
.glow-2 {
width: 400px;
height: 400px;
background: radial-gradient(circle, rgba(79, 70, 229, 0.3) 0%, transparent 70%);
bottom: 20%;
right: 10%;
animation-delay: 4s;
}
.glow-3 {
width: 250px;
height: 250px;
background: radial-gradient(circle, rgba(139, 92, 246, 0.3) 0%, transparent 70%);
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
animation-delay: 2s;
}
/* Smooth transitions for form elements */
* {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
</style>