develop #3
@@ -1,738 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Connexion - AperoNight | Plateforme Événementielle Premium</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="aperonight_premium_light_theme.css">
|
||||
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--font-sans) !important;
|
||||
background: var(--background) !important;
|
||||
min-height: 100vh !important;
|
||||
position: relative !important;
|
||||
overflow-x: hidden !important;
|
||||
color: var(--foreground) !important;
|
||||
}
|
||||
|
||||
/* Light theme background patterns */
|
||||
body::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-image:
|
||||
radial-gradient(circle at 2px 2px, var(--dot-color) 1px, transparent 1px);
|
||||
background-size: 40px 40px;
|
||||
opacity: 0.3;
|
||||
z-index: 0;
|
||||
animation: dotFlow 30s linear infinite;
|
||||
}
|
||||
|
||||
body::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background:
|
||||
linear-gradient(90deg, transparent 48%, var(--connection-color) 50%, transparent 52%),
|
||||
linear-gradient(0deg, transparent 48%, var(--connection-color) 50%, transparent 52%);
|
||||
background-size: 100px 100px;
|
||||
opacity: 0.12;
|
||||
z-index: 0;
|
||||
animation: connectionFlow 20s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes dotFlow {
|
||||
0% { transform: translate(0, 0); }
|
||||
100% { transform: translate(40px, 40px); }
|
||||
}
|
||||
|
||||
@keyframes connectionFlow {
|
||||
0% { transform: translate(0, 0); }
|
||||
100% { transform: translate(100px, 100px); }
|
||||
}
|
||||
|
||||
/* Page entrance orchestration */
|
||||
.page-container {
|
||||
animation: pageLoad 1000ms cubic-bezier(0.23, 1, 0.32, 1) forwards;
|
||||
opacity: 0;
|
||||
transform: translateY(50px);
|
||||
}
|
||||
|
||||
@keyframes pageLoad {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Brand reveal animation */
|
||||
.brand-container {
|
||||
animation: brandReveal 1400ms ease-out 300ms forwards;
|
||||
opacity: 0;
|
||||
transform: scale(0.7);
|
||||
}
|
||||
|
||||
@keyframes brandReveal {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Premium card elevation - light theme */
|
||||
.login-card {
|
||||
background: var(--glass-bg) !important;
|
||||
backdrop-filter: var(--glass-backdrop) !important;
|
||||
border: 1px solid var(--glass-border) !important;
|
||||
border-radius: var(--radius-2xl) !important;
|
||||
box-shadow: var(--shadow-2xl) !important;
|
||||
animation: cardElevate 800ms cubic-bezier(0.34, 1.56, 0.64, 1) 600ms forwards;
|
||||
opacity: 0;
|
||||
transform: translateY(40px);
|
||||
transition: all 400ms ease-out;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.login-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent,
|
||||
rgba(59, 130, 246, 0.05),
|
||||
transparent
|
||||
);
|
||||
transition: left 0.6s ease;
|
||||
}
|
||||
|
||||
.login-card:hover::before {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
.login-card:hover {
|
||||
transform: var(--hover-lift) var(--hover-scale);
|
||||
box-shadow: var(--shadow-2xl), var(--shadow-electric);
|
||||
}
|
||||
|
||||
@keyframes cardElevate {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Professional input styling - light theme */
|
||||
.input-group {
|
||||
position: relative;
|
||||
margin-bottom: 1.75rem;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
width: 100%;
|
||||
padding: 1.25rem 3.5rem 1.25rem 1.25rem;
|
||||
border: 2px solid var(--input-border);
|
||||
border-radius: var(--radius-lg);
|
||||
background: var(--input);
|
||||
color: var(--card-foreground);
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
transition: all 250ms ease-out;
|
||||
outline: none;
|
||||
font-family: var(--font-sans);
|
||||
}
|
||||
|
||||
.input-field:focus {
|
||||
border-color: var(--primary);
|
||||
box-shadow: var(--shadow-electric), var(--focus-ring);
|
||||
transform: scale(1.01);
|
||||
background: white;
|
||||
}
|
||||
|
||||
.input-field:focus + .floating-label {
|
||||
transform: translateY(-12px) scale(0.85);
|
||||
color: var(--primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.floating-label {
|
||||
position: absolute;
|
||||
left: 1.25rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: var(--input);
|
||||
padding: 0 0.75rem;
|
||||
color: var(--muted-foreground);
|
||||
pointer-events: none;
|
||||
transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
font-weight: 500;
|
||||
font-family: var(--font-sans);
|
||||
}
|
||||
|
||||
.input-field:not(:placeholder-shown) + .floating-label {
|
||||
transform: translateY(-12px) scale(0.85);
|
||||
background: white;
|
||||
}
|
||||
|
||||
/* Security toggle with premium feel - light theme */
|
||||
.security-toggle {
|
||||
position: absolute;
|
||||
right: 1.25rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--muted-foreground);
|
||||
cursor: pointer;
|
||||
transition: all 200ms ease-out;
|
||||
opacity: 0.7;
|
||||
padding: 0.5rem;
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.security-toggle:hover {
|
||||
opacity: 1;
|
||||
color: var(--primary);
|
||||
background: var(--primary-light);
|
||||
transform: translateY(-50%) rotate(180deg);
|
||||
}
|
||||
|
||||
/* Flat button styling - light theme */
|
||||
.login-button {
|
||||
width: 100%;
|
||||
padding: 1.25rem;
|
||||
background: var(--primary) !important;
|
||||
border: none;
|
||||
border-radius: var(--radius-lg);
|
||||
color: var(--primary-foreground);
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
font-family: var(--font-display);
|
||||
cursor: pointer;
|
||||
transition: all 300ms ease-out;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.login-button:hover {
|
||||
transform: var(--hover-lift);
|
||||
box-shadow: var(--shadow-lg);
|
||||
background: var(--primary-hover) !important;
|
||||
}
|
||||
|
||||
.login-button:active {
|
||||
transform: scale(0.97);
|
||||
}
|
||||
|
||||
/* Premium ripple effect */
|
||||
.login-button::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
transition: width 600ms cubic-bezier(0.25, 0.46, 0.45, 0.94),
|
||||
height 600ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.login-button:active::before {
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
/* Sophisticated checkbox - light theme */
|
||||
.premium-checkbox {
|
||||
appearance: none;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
border: 2px solid var(--input-border);
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--input);
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
transition: all 200ms ease-out;
|
||||
}
|
||||
|
||||
.premium-checkbox:checked {
|
||||
background: var(--primary);
|
||||
border-color: var(--primary);
|
||||
animation: securityCheck 400ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
}
|
||||
|
||||
.premium-checkbox:checked::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 5px;
|
||||
width: 6px;
|
||||
height: 10px;
|
||||
border: solid white;
|
||||
border-width: 0 2px 2px 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
@keyframes securityCheck {
|
||||
0% { transform: scale(0); }
|
||||
50% { transform: scale(1.2); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
/* Professional link styling - light theme */
|
||||
.premium-link {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
transition: all 250ms ease-out;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.premium-link::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -2px;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
background: var(--accent);
|
||||
transition: width 250ms ease-out;
|
||||
}
|
||||
|
||||
.premium-link:hover {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.premium-link:hover::after {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Validation states - light theme */
|
||||
.input-error {
|
||||
border-color: var(--destructive) !important;
|
||||
animation: errorShake 400ms cubic-bezier(0.36, 0, 0.66, -0.56);
|
||||
}
|
||||
|
||||
@keyframes errorShake {
|
||||
0%, 100% { transform: translateX(0); }
|
||||
25% { transform: translateX(-10px); }
|
||||
75% { transform: translateX(10px); }
|
||||
}
|
||||
|
||||
.input-success {
|
||||
border-color: var(--success) !important;
|
||||
box-shadow: 0 0 0 3px var(--success-light);
|
||||
animation: validationSuccess 500ms cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
@keyframes validationSuccess {
|
||||
0% { transform: scale(1); }
|
||||
50% { transform: scale(1.02); border-color: var(--success); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
/* Premium loading states - light theme */
|
||||
.skeleton {
|
||||
background: var(--muted);
|
||||
animation: skeletonPulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes skeletonPulse {
|
||||
0%, 100% { opacity: 0.8; }
|
||||
50% { opacity: 0.4; }
|
||||
}
|
||||
|
||||
/* Logo styling - light theme */
|
||||
.logo-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.logo-glow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Trust indicators - light theme */
|
||||
.trust-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem 1rem;
|
||||
background: var(--success-light);
|
||||
color: var(--success);
|
||||
border-radius: var(--radius-full);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
border: 1px solid var(--success);
|
||||
transition: all 300ms ease-out;
|
||||
}
|
||||
|
||||
.trust-badge:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
/* Professional footer - light theme */
|
||||
.pro-footer {
|
||||
background: rgba(59, 130, 246, 0.08);
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 1rem;
|
||||
margin-top: 2rem;
|
||||
border: 1px solid rgba(59, 130, 246, 0.1);
|
||||
}
|
||||
|
||||
/* Light theme brand colors */
|
||||
.brand-text-primary {
|
||||
color: var(--primary) !important;
|
||||
}
|
||||
|
||||
.brand-text-secondary {
|
||||
color: var(--primary-dark) !important;
|
||||
}
|
||||
|
||||
.brand-text-muted {
|
||||
color: var(--muted-foreground) !important;
|
||||
}
|
||||
|
||||
.footer-link {
|
||||
color: var(--primary) !important;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.footer-link:hover {
|
||||
opacity: 1;
|
||||
color: var(--primary-hover) !important;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
color: var(--muted-foreground) !important;
|
||||
}
|
||||
|
||||
/* Responsive enhancements */
|
||||
@media (max-width: 640px) {
|
||||
.login-card {
|
||||
margin: 1rem;
|
||||
padding: 2rem 1.5rem;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
padding: 1rem 3rem 1rem 1rem;
|
||||
}
|
||||
|
||||
.login-button {
|
||||
font-size: 1rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Advanced accessibility */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*, *::before, *::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* High contrast mode support */
|
||||
@media (prefers-contrast: high) {
|
||||
.login-card {
|
||||
border: 3px solid var(--primary);
|
||||
}
|
||||
|
||||
.input-field:focus {
|
||||
outline: 3px solid var(--primary);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-container relative z-10 flex items-center justify-center min-h-screen p-4">
|
||||
<div class="w-full max-w-lg">
|
||||
<!-- Premium Brand Section - Light Theme -->
|
||||
<div class="brand-container text-center mb-10">
|
||||
<div class="relative inline-block mb-6">
|
||||
<div class="logo-glow"></div>
|
||||
<div class="relative w-20 h-20 mx-auto bg-blue-600 rounded-2xl flex items-center justify-center logo-container">
|
||||
<i data-lucide="calendar-check" class="w-10 h-10 text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="text-3xl font-bold brand-text-primary mb-2 font-display">AperoNight</h1>
|
||||
<p class="brand-text-secondary text-lg font-medium mb-2">Plateforme Événementielle Premium</p>
|
||||
<p class="brand-text-muted text-sm opacity-90">Connexion sécurisée • Interface professionnelle</p>
|
||||
|
||||
<div class="flex justify-center mt-4">
|
||||
<div class="trust-badge">
|
||||
<i data-lucide="shield-check" class="w-4 h-4"></i>
|
||||
<span>Connexion Sécurisée</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Premium Login Card -->
|
||||
<div class="login-card p-8">
|
||||
<div class="text-center mb-8">
|
||||
<h2 class="text-xl font-bold text-gray-800 mb-2 font-display">Accès Dashboard</h2>
|
||||
<p class="text-gray-600 text-sm">Gérez vos événements en toute simplicité</p>
|
||||
</div>
|
||||
|
||||
<form class="space-y-6">
|
||||
<!-- Email professionnel -->
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="email"
|
||||
class="input-field"
|
||||
placeholder=" "
|
||||
required
|
||||
id="email"
|
||||
>
|
||||
<label class="floating-label" for="email">Email professionnel</label>
|
||||
<div class="absolute right-3 top-1/2 transform -translate-y-1/2">
|
||||
<i data-lucide="mail" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mot de passe sécurisé -->
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="password"
|
||||
class="input-field"
|
||||
placeholder=" "
|
||||
required
|
||||
id="password"
|
||||
>
|
||||
<label class="floating-label" for="password">Mot de passe sécurisé</label>
|
||||
<button type="button" class="security-toggle" onclick="togglePassword()">
|
||||
<i data-lucide="lock" class="w-5 h-5"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Options de connexion -->
|
||||
<div class="flex items-center justify-between">
|
||||
<label class="flex items-center space-x-3 cursor-pointer group">
|
||||
<input type="checkbox" class="premium-checkbox" id="remember">
|
||||
<span class="text-sm text-gray-700 group-hover:text-gray-900 transition-colors">
|
||||
Maintenir la connexion
|
||||
</span>
|
||||
</label>
|
||||
<div class="flex items-center space-x-1 text-xs text-gray-500">
|
||||
<i data-lucide="timer" class="w-3 h-3"></i>
|
||||
<span>30 jours</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bouton de connexion premium -->
|
||||
<button type="submit" class="login-button group">
|
||||
<span class="relative z-10 flex items-center justify-center gap-2">
|
||||
<i data-lucide="log-in" class="w-5 h-5"></i>
|
||||
Accéder au Dashboard
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!-- Options de récupération -->
|
||||
<div class="text-center space-y-3">
|
||||
<a href="#" class="premium-link text-sm">Mot de passe oublié ?</a>
|
||||
<div class="flex items-center justify-center space-x-4 text-xs text-gray-500">
|
||||
<span class="flex items-center gap-1">
|
||||
<i data-lucide="smartphone" class="w-3 h-3"></i>
|
||||
2FA disponible
|
||||
</span>
|
||||
<span class="flex items-center gap-1">
|
||||
<i data-lucide="key" class="w-3 h-3"></i>
|
||||
SSO Enterprise
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Professional Footer - Light Theme -->
|
||||
<div class="pro-footer text-center space-y-3">
|
||||
<div class="flex items-center justify-center space-x-6 text-sm">
|
||||
<a href="#" class="footer-link transition-colors flex items-center gap-1">
|
||||
<i data-lucide="life-buoy" class="w-4 h-4"></i>
|
||||
Support Pro
|
||||
</a>
|
||||
<a href="#" class="footer-link transition-colors flex items-center gap-1">
|
||||
<i data-lucide="shield" class="w-4 h-4"></i>
|
||||
Sécurité Renforcée
|
||||
</a>
|
||||
<a href="#" class="footer-link transition-colors flex items-center gap-1">
|
||||
<i data-lucide="zap" class="w-4 h-4"></i>
|
||||
API Premium
|
||||
</a>
|
||||
</div>
|
||||
<p class="text-xs status-text">© 2024 AperoNight • Plateforme Événementielle Premium • Tous droits réservés</p>
|
||||
<div class="flex items-center justify-center space-x-2 text-xs status-text">
|
||||
<span class="flex items-center gap-1">
|
||||
<div class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
|
||||
Système opérationnel
|
||||
</span>
|
||||
<span>•</span>
|
||||
<span>99.9% uptime</span>
|
||||
<span>•</span>
|
||||
<span>GDPR compliant</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Initialize Lucide icons
|
||||
lucide.createIcons();
|
||||
|
||||
// Enhanced password toggle
|
||||
function togglePassword() {
|
||||
const passwordField = document.getElementById('password');
|
||||
const toggleIcon = document.querySelector('.security-toggle i');
|
||||
|
||||
if (passwordField.type === 'password') {
|
||||
passwordField.type = 'text';
|
||||
toggleIcon.setAttribute('data-lucide', 'unlock');
|
||||
} else {
|
||||
passwordField.type = 'password';
|
||||
toggleIcon.setAttribute('data-lucide', 'lock');
|
||||
}
|
||||
|
||||
lucide.createIcons();
|
||||
}
|
||||
|
||||
// Professional form validation
|
||||
const form = document.querySelector('form');
|
||||
const emailField = document.getElementById('email');
|
||||
const passwordField = document.getElementById('password');
|
||||
|
||||
form.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Reset states
|
||||
emailField.classList.remove('input-error', 'input-success');
|
||||
passwordField.classList.remove('input-error', 'input-success');
|
||||
|
||||
let isValid = true;
|
||||
|
||||
// Professional email validation
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(emailField.value)) {
|
||||
emailField.classList.add('input-error');
|
||||
isValid = false;
|
||||
showNotification('Email invalide', 'error');
|
||||
} else {
|
||||
emailField.classList.add('input-success');
|
||||
}
|
||||
|
||||
// Secure password validation
|
||||
if (passwordField.value.length < 8) {
|
||||
passwordField.classList.add('input-error');
|
||||
isValid = false;
|
||||
showNotification('Mot de passe trop court (min. 8 caractères)', 'error');
|
||||
} else {
|
||||
passwordField.classList.add('input-success');
|
||||
}
|
||||
|
||||
if (isValid) {
|
||||
// Premium loading state
|
||||
const button = document.querySelector('.login-button');
|
||||
const originalContent = button.innerHTML;
|
||||
button.innerHTML = `
|
||||
<div class="flex items-center justify-center space-x-2">
|
||||
<div class="animate-spin w-5 h-5 border-2 border-white border-t-transparent rounded-full"></div>
|
||||
<span>Connexion sécurisée...</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
setTimeout(() => {
|
||||
showNotification('Connexion réussie ! Redirection...', 'success');
|
||||
setTimeout(() => {
|
||||
button.innerHTML = originalContent;
|
||||
}, 1500);
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
|
||||
// Real-time validation
|
||||
emailField.addEventListener('input', function() {
|
||||
this.classList.remove('input-error', 'input-success');
|
||||
});
|
||||
|
||||
passwordField.addEventListener('input', function() {
|
||||
this.classList.remove('input-error', 'input-success');
|
||||
});
|
||||
|
||||
// Professional notification system
|
||||
function showNotification(message, type) {
|
||||
const notification = document.createElement('div');
|
||||
notification.className = `
|
||||
fixed top-4 right-4 z-50 p-4 rounded-lg shadow-2xl max-w-sm
|
||||
${type === 'success' ? 'bg-green-500 text-white' : 'bg-red-500 text-white'}
|
||||
transform transition-all duration-300 ease-out translate-x-full
|
||||
`;
|
||||
notification.innerHTML = `
|
||||
<div class="flex items-center space-x-2">
|
||||
<i data-lucide="${type === 'success' ? 'check-circle' : 'alert-circle'}" class="w-5 h-5"></i>
|
||||
<span class="font-medium">${message}</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(notification);
|
||||
lucide.createIcons();
|
||||
|
||||
setTimeout(() => {
|
||||
notification.style.transform = 'translateX(0)';
|
||||
}, 100);
|
||||
|
||||
setTimeout(() => {
|
||||
notification.style.transform = 'translateX(100%)';
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(notification);
|
||||
}, 300);
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// Enhanced floating label behavior
|
||||
document.querySelectorAll('.input-field').forEach(input => {
|
||||
input.addEventListener('focus', function() {
|
||||
this.nextElementSibling.style.background = 'white';
|
||||
});
|
||||
|
||||
input.addEventListener('blur', function() {
|
||||
if (!this.value) {
|
||||
this.nextElementSibling.style.background = 'var(--input)';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Professional interaction tracking
|
||||
console.log('🌟 AperoNight Premium Light Login Interface Loaded');
|
||||
console.log('✅ Security features: 2FA, SSO, GDPR compliance');
|
||||
console.log('🎨 Theme: Professional Event Platform - Light Mode');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,125 +0,0 @@
|
||||
:root {
|
||||
/* AperoNight Premium Light Theme - Professional Event Platform */
|
||||
|
||||
/* Base Colors - Clean Light Background with Professional Accents */
|
||||
--background: oklch(0.9800 0.0050 240);
|
||||
--foreground: oklch(0.1500 0.0200 240);
|
||||
--surface: oklch(0.9600 0.0080 240);
|
||||
--surface-elevated: oklch(0.9400 0.0120 240);
|
||||
|
||||
/* Card & Dialog surfaces */
|
||||
--card: oklch(1.0000 0 0);
|
||||
--card-foreground: oklch(0.1500 0.0200 240);
|
||||
--popover: oklch(1.0000 0 0);
|
||||
--popover-foreground: oklch(0.1500 0.0200 240);
|
||||
|
||||
/* Primary - Professional Electric Blue */
|
||||
--primary: oklch(0.5200 0.2200 220);
|
||||
--primary-foreground: oklch(0.9900 0.0050 220);
|
||||
--primary-hover: oklch(0.4600 0.2400 220);
|
||||
--primary-light: oklch(0.9200 0.1000 220);
|
||||
--primary-dark: oklch(0.3800 0.2600 220);
|
||||
|
||||
/* Secondary - Sophisticated Light Gray */
|
||||
--secondary: oklch(0.9200 0.0100 240);
|
||||
--secondary-foreground: oklch(0.3000 0.0300 240);
|
||||
--secondary-hover: oklch(0.8800 0.0150 240);
|
||||
|
||||
/* Accent - Vibrant Cyan (Events Energy) */
|
||||
--accent: oklch(0.6500 0.2400 200);
|
||||
--accent-foreground: oklch(0.9900 0.0050 200);
|
||||
--accent-light: oklch(0.9400 0.1200 200);
|
||||
--accent-dark: oklch(0.5000 0.2800 200);
|
||||
|
||||
/* Success - Event Success Green */
|
||||
--success: oklch(0.6000 0.2000 140);
|
||||
--success-foreground: oklch(0.9800 0.0100 140);
|
||||
--success-light: oklch(0.9600 0.0800 140);
|
||||
|
||||
/* Warning - Premium Amber */
|
||||
--warning: oklch(0.7200 0.1800 60);
|
||||
--warning-foreground: oklch(0.2500 0.0400 60);
|
||||
--warning-light: oklch(0.9600 0.0800 60);
|
||||
|
||||
/* Error - Professional Red */
|
||||
--destructive: oklch(0.5600 0.2200 20);
|
||||
--destructive-foreground: oklch(0.9800 0.0100 20);
|
||||
--destructive-light: oklch(0.9600 0.1000 20);
|
||||
|
||||
/* Muted tones */
|
||||
--muted: oklch(0.9400 0.0100 240);
|
||||
--muted-foreground: oklch(0.5200 0.0300 240);
|
||||
--muted-dark: oklch(0.8800 0.0200 240);
|
||||
|
||||
/* Borders and inputs */
|
||||
--border: oklch(0.8800 0.0200 240);
|
||||
--input: oklch(0.9800 0.0080 240);
|
||||
--input-border: oklch(0.8600 0.0300 240);
|
||||
--ring: oklch(0.5200 0.2200 220);
|
||||
|
||||
/* Typography - Premium Event Platform */
|
||||
--font-sans: 'Inter', 'Plus Jakarta Sans', system-ui, sans-serif;
|
||||
--font-display: 'Space Grotesk', 'Outfit', system-ui, sans-serif;
|
||||
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
|
||||
|
||||
/* Spacing and layout */
|
||||
--radius: 0.75rem;
|
||||
--spacing: 1rem;
|
||||
|
||||
/* Light theme shadow system */
|
||||
--shadow-xs: 0 1px 3px 0 hsl(240 15% 15% / 0.08), 0 1px 2px -1px hsl(240 15% 15% / 0.06);
|
||||
--shadow-sm: 0 2px 6px -1px hsl(240 15% 15% / 0.10), 0 2px 4px -2px hsl(240 15% 15% / 0.08);
|
||||
--shadow: 0 4px 8px -2px hsl(240 15% 15% / 0.12), 0 2px 4px -2px hsl(240 15% 15% / 0.08);
|
||||
--shadow-md: 0 8px 16px -4px hsl(240 15% 15% / 0.14), 0 4px 6px -2px hsl(240 15% 15% / 0.10);
|
||||
--shadow-lg: 0 16px 24px -4px hsl(240 15% 15% / 0.16), 0 8px 8px -4px hsl(240 15% 15% / 0.08);
|
||||
--shadow-xl: 0 20px 32px -8px hsl(240 15% 15% / 0.18), 0 8px 16px -8px hsl(240 15% 15% / 0.10);
|
||||
--shadow-2xl: 0 32px 64px -12px hsl(240 15% 15% / 0.22);
|
||||
|
||||
/* Subtle accent shadows for light theme */
|
||||
--shadow-electric: 0 4px 16px -2px hsl(220 80% 60% / 0.15), 0 2px 8px -2px hsl(220 80% 60% / 0.10);
|
||||
--shadow-accent: 0 4px 16px -2px hsl(200 80% 60% / 0.18), 0 2px 8px -2px hsl(200 80% 60% / 0.12);
|
||||
|
||||
/* Light theme gradients */
|
||||
--gradient-primary: linear-gradient(135deg, var(--primary) 0%, var(--accent) 100%);
|
||||
--gradient-background: linear-gradient(135deg,
|
||||
oklch(0.9800 0.0050 240) 0%,
|
||||
oklch(0.9600 0.0080 235) 25%,
|
||||
oklch(0.9400 0.0120 230) 50%,
|
||||
oklch(0.9600 0.0080 225) 75%,
|
||||
oklch(0.9800 0.0050 220) 100%);
|
||||
--gradient-card: linear-gradient(135deg,
|
||||
oklch(1.0000 0 0) 0%,
|
||||
oklch(0.9900 0.0050 235) 100%);
|
||||
|
||||
/* Light theme pattern overlays */
|
||||
--grid-color: oklch(0.8500 0.0300 240);
|
||||
--dot-color: oklch(0.8000 0.0400 220);
|
||||
--connection-color: oklch(0.7500 0.0800 210);
|
||||
|
||||
/* Light glassmorphism */
|
||||
--glass-bg: oklch(1.0000 0 0 / 0.85);
|
||||
--glass-border: oklch(0.8800 0.0200 240 / 0.25);
|
||||
--glass-backdrop: blur(16px) saturate(180%);
|
||||
|
||||
/* Professional interaction states */
|
||||
--hover-lift: translateY(-2px);
|
||||
--hover-scale: scale(1.02);
|
||||
--focus-ring: 0 0 0 3px var(--ring);
|
||||
|
||||
/* Event-specific colors for light theme */
|
||||
--event-vip: oklch(0.6800 0.2200 45);
|
||||
--event-premium: oklch(0.5800 0.2000 280);
|
||||
--event-standard: oklch(0.6200 0.1600 160);
|
||||
--event-available: oklch(0.6000 0.1800 140);
|
||||
--event-limited: oklch(0.7000 0.1800 50);
|
||||
--event-sold-out: oklch(0.5800 0.2000 15);
|
||||
|
||||
/* Radius variations */
|
||||
--radius-xs: calc(var(--radius) - 4px);
|
||||
--radius-sm: calc(var(--radius) - 2px);
|
||||
--radius-md: var(--radius);
|
||||
--radius-lg: calc(var(--radius) + 4px);
|
||||
--radius-xl: calc(var(--radius) + 8px);
|
||||
--radius-2xl: calc(var(--radius) + 12px);
|
||||
--radius-full: 9999px;
|
||||
}
|
||||
@@ -1,710 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Connexion - AperoNight | Plateforme Événementielle Premium</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="aperonight_premium_theme.css">
|
||||
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--font-sans) !important;
|
||||
background: oklch(0.1200 0.0300 240) !important;
|
||||
min-height: 100vh !important;
|
||||
position: relative !important;
|
||||
overflow-x: hidden !important;
|
||||
color: var(--foreground) !important;
|
||||
}
|
||||
|
||||
/* Advanced background patterns */
|
||||
body::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-image:
|
||||
radial-gradient(circle at 2px 2px, var(--dot-color) 1px, transparent 1px);
|
||||
background-size: 40px 40px;
|
||||
opacity: 0.4;
|
||||
z-index: 0;
|
||||
animation: dotFlow 30s linear infinite;
|
||||
}
|
||||
|
||||
body::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background:
|
||||
linear-gradient(90deg, transparent 48%, var(--connection-color) 50%, transparent 52%),
|
||||
linear-gradient(0deg, transparent 48%, var(--connection-color) 50%, transparent 52%);
|
||||
background-size: 100px 100px;
|
||||
opacity: 0.15;
|
||||
z-index: 0;
|
||||
animation: connectionFlow 20s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes dotFlow {
|
||||
0% { transform: translate(0, 0); }
|
||||
100% { transform: translate(40px, 40px); }
|
||||
}
|
||||
|
||||
@keyframes connectionFlow {
|
||||
0% { transform: translate(0, 0); }
|
||||
100% { transform: translate(100px, 100px); }
|
||||
}
|
||||
|
||||
/* Page entrance orchestration */
|
||||
.page-container {
|
||||
animation: pageLoad 1000ms cubic-bezier(0.23, 1, 0.32, 1) forwards;
|
||||
opacity: 0;
|
||||
transform: translateY(50px);
|
||||
}
|
||||
|
||||
@keyframes pageLoad {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Brand reveal animation */
|
||||
.brand-container {
|
||||
animation: brandReveal 1400ms ease-out 300ms forwards;
|
||||
opacity: 0;
|
||||
transform: scale(0.7);
|
||||
}
|
||||
|
||||
@keyframes brandReveal {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Premium card elevation */
|
||||
.login-card {
|
||||
background: var(--glass-bg) !important;
|
||||
backdrop-filter: var(--glass-backdrop) !important;
|
||||
border: 1px solid var(--glass-border) !important;
|
||||
border-radius: var(--radius-2xl) !important;
|
||||
box-shadow: var(--shadow-2xl) !important;
|
||||
animation: cardElevate 800ms cubic-bezier(0.34, 1.56, 0.64, 1) 600ms forwards;
|
||||
opacity: 0;
|
||||
transform: translateY(40px);
|
||||
transition: all 400ms ease-out;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.login-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent,
|
||||
rgba(255, 255, 255, 0.1),
|
||||
transparent
|
||||
);
|
||||
transition: left 0.6s ease;
|
||||
}
|
||||
|
||||
.login-card:hover::before {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
.login-card:hover {
|
||||
transform: var(--hover-lift) var(--hover-scale);
|
||||
box-shadow: var(--shadow-2xl), var(--shadow-electric);
|
||||
}
|
||||
|
||||
@keyframes cardElevate {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Professional input styling */
|
||||
.input-group {
|
||||
position: relative;
|
||||
margin-bottom: 1.75rem;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
width: 100%;
|
||||
padding: 1.25rem 3.5rem 1.25rem 1.25rem;
|
||||
border: 2px solid var(--input-border);
|
||||
border-radius: var(--radius-lg);
|
||||
background: var(--input);
|
||||
color: var(--card-foreground);
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
transition: all 250ms ease-out;
|
||||
outline: none;
|
||||
font-family: var(--font-sans);
|
||||
}
|
||||
|
||||
.input-field:focus {
|
||||
border-color: var(--primary);
|
||||
box-shadow: var(--shadow-electric), var(--focus-ring);
|
||||
transform: scale(1.01);
|
||||
background: white;
|
||||
}
|
||||
|
||||
.input-field:focus + .floating-label {
|
||||
transform: translateY(-12px) scale(0.85);
|
||||
color: var(--primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.floating-label {
|
||||
position: absolute;
|
||||
left: 1.25rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: var(--input);
|
||||
padding: 0 0.75rem;
|
||||
color: var(--muted-foreground);
|
||||
pointer-events: none;
|
||||
transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
font-weight: 500;
|
||||
font-family: var(--font-sans);
|
||||
}
|
||||
|
||||
.input-field:not(:placeholder-shown) + .floating-label {
|
||||
transform: translateY(-12px) scale(0.85);
|
||||
background: white;
|
||||
}
|
||||
|
||||
/* Security toggle with premium feel */
|
||||
.security-toggle {
|
||||
position: absolute;
|
||||
right: 1.25rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--muted-foreground);
|
||||
cursor: pointer;
|
||||
transition: all 200ms ease-out;
|
||||
opacity: 0.7;
|
||||
padding: 0.5rem;
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.security-toggle:hover {
|
||||
opacity: 1;
|
||||
color: var(--primary);
|
||||
background: var(--primary-light);
|
||||
transform: translateY(-50%) rotate(180deg);
|
||||
}
|
||||
|
||||
/* Flat button styling */
|
||||
.login-button {
|
||||
width: 100%;
|
||||
padding: 1.25rem;
|
||||
background: var(--primary) !important;
|
||||
border: none;
|
||||
border-radius: var(--radius-lg);
|
||||
color: var(--primary-foreground);
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
font-family: var(--font-display);
|
||||
cursor: pointer;
|
||||
transition: all 300ms ease-out;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.login-button:hover {
|
||||
transform: var(--hover-lift);
|
||||
box-shadow: var(--shadow-lg);
|
||||
background: var(--primary-hover) !important;
|
||||
}
|
||||
|
||||
.login-button:active {
|
||||
transform: scale(0.97);
|
||||
}
|
||||
|
||||
/* Premium ripple effect */
|
||||
.login-button::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
transition: width 600ms cubic-bezier(0.25, 0.46, 0.45, 0.94),
|
||||
height 600ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.login-button:active::before {
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
/* Sophisticated checkbox */
|
||||
.premium-checkbox {
|
||||
appearance: none;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
border: 2px solid var(--input-border);
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--input);
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
transition: all 200ms ease-out;
|
||||
}
|
||||
|
||||
.premium-checkbox:checked {
|
||||
background: var(--primary);
|
||||
border-color: var(--primary);
|
||||
animation: securityCheck 400ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
}
|
||||
|
||||
.premium-checkbox:checked::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 5px;
|
||||
width: 6px;
|
||||
height: 10px;
|
||||
border: solid white;
|
||||
border-width: 0 2px 2px 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
@keyframes securityCheck {
|
||||
0% { transform: scale(0); }
|
||||
50% { transform: scale(1.2); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
/* Professional link styling */
|
||||
.premium-link {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
transition: all 250ms ease-out;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.premium-link::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -2px;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
background: var(--accent);
|
||||
transition: width 250ms ease-out;
|
||||
}
|
||||
|
||||
.premium-link:hover {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.premium-link:hover::after {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Validation states */
|
||||
.input-error {
|
||||
border-color: var(--destructive) !important;
|
||||
animation: errorShake 400ms cubic-bezier(0.36, 0, 0.66, -0.56);
|
||||
}
|
||||
|
||||
@keyframes errorShake {
|
||||
0%, 100% { transform: translateX(0); }
|
||||
25% { transform: translateX(-10px); }
|
||||
75% { transform: translateX(10px); }
|
||||
}
|
||||
|
||||
.input-success {
|
||||
border-color: var(--success) !important;
|
||||
box-shadow: 0 0 0 3px var(--success-light);
|
||||
animation: validationSuccess 500ms cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
@keyframes validationSuccess {
|
||||
0% { transform: scale(1); }
|
||||
50% { transform: scale(1.02); border-color: var(--success); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
/* Premium loading states */
|
||||
.skeleton {
|
||||
background: var(--muted);
|
||||
animation: skeletonPulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes skeletonPulse {
|
||||
0%, 100% { opacity: 0.8; }
|
||||
50% { opacity: 0.4; }
|
||||
}
|
||||
|
||||
/* Logo styling */
|
||||
.logo-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.logo-glow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Trust indicators */
|
||||
.trust-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem 1rem;
|
||||
background: var(--success-light);
|
||||
color: var(--success);
|
||||
border-radius: var(--radius-full);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
border: 1px solid var(--success);
|
||||
transition: all 300ms ease-out;
|
||||
}
|
||||
|
||||
.trust-badge:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
/* Professional footer */
|
||||
.pro-footer {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 1rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
/* Responsive enhancements */
|
||||
@media (max-width: 640px) {
|
||||
.login-card {
|
||||
margin: 1rem;
|
||||
padding: 2rem 1.5rem;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
padding: 1rem 3rem 1rem 1rem;
|
||||
}
|
||||
|
||||
.login-button {
|
||||
font-size: 1rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Advanced accessibility */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*, *::before, *::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* High contrast mode support */
|
||||
@media (prefers-contrast: high) {
|
||||
.login-card {
|
||||
border: 3px solid var(--primary);
|
||||
}
|
||||
|
||||
.input-field:focus {
|
||||
outline: 3px solid var(--primary);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-container relative z-10 flex items-center justify-center min-h-screen p-4">
|
||||
<div class="w-full max-w-lg">
|
||||
<!-- Premium Brand Section -->
|
||||
<div class="brand-container text-center mb-10">
|
||||
<div class="relative inline-block mb-6">
|
||||
<div class="logo-glow"></div>
|
||||
<div class="relative w-20 h-20 mx-auto bg-blue-600 rounded-2xl flex items-center justify-center logo-container">
|
||||
<i data-lucide="calendar-check" class="w-10 h-10 text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="text-3xl font-bold text-white mb-2 font-display">AperoNight</h1>
|
||||
<p class="text-blue-200 text-lg font-medium mb-2">Plateforme Événementielle Premium</p>
|
||||
<p class="text-blue-300 text-sm opacity-90">Connexion sécurisée • Interface professionnelle</p>
|
||||
|
||||
<div class="flex justify-center mt-4">
|
||||
<div class="trust-badge">
|
||||
<i data-lucide="shield-check" class="w-4 h-4"></i>
|
||||
<span>Connexion Sécurisée</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Premium Login Card -->
|
||||
<div class="login-card p-8">
|
||||
<div class="text-center mb-8">
|
||||
<h2 class="text-xl font-bold text-gray-800 mb-2 font-display">Accès Dashboard</h2>
|
||||
<p class="text-gray-600 text-sm">Gérez vos événements en toute simplicité</p>
|
||||
</div>
|
||||
|
||||
<form class="space-y-6">
|
||||
<!-- Email professionnel -->
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="email"
|
||||
class="input-field"
|
||||
placeholder=" "
|
||||
required
|
||||
id="email"
|
||||
>
|
||||
<label class="floating-label" for="email">Email professionnel</label>
|
||||
<div class="absolute right-3 top-1/2 transform -translate-y-1/2">
|
||||
<i data-lucide="mail" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mot de passe sécurisé -->
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="password"
|
||||
class="input-field"
|
||||
placeholder=" "
|
||||
required
|
||||
id="password"
|
||||
>
|
||||
<label class="floating-label" for="password">Mot de passe sécurisé</label>
|
||||
<button type="button" class="security-toggle" onclick="togglePassword()">
|
||||
<i data-lucide="lock" class="w-5 h-5"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Options de connexion -->
|
||||
<div class="flex items-center justify-between">
|
||||
<label class="flex items-center space-x-3 cursor-pointer group">
|
||||
<input type="checkbox" class="premium-checkbox" id="remember">
|
||||
<span class="text-sm text-gray-700 group-hover:text-gray-900 transition-colors">
|
||||
Maintenir la connexion
|
||||
</span>
|
||||
</label>
|
||||
<div class="flex items-center space-x-1 text-xs text-gray-500">
|
||||
<i data-lucide="timer" class="w-3 h-3"></i>
|
||||
<span>30 jours</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bouton de connexion premium -->
|
||||
<button type="submit" class="login-button group">
|
||||
<span class="relative z-10 flex items-center justify-center gap-2">
|
||||
<i data-lucide="log-in" class="w-5 h-5"></i>
|
||||
Accéder au Dashboard
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!-- Options de récupération -->
|
||||
<div class="text-center space-y-3">
|
||||
<a href="#" class="premium-link text-sm">Mot de passe oublié ?</a>
|
||||
<div class="flex items-center justify-center space-x-4 text-xs text-gray-500">
|
||||
<span class="flex items-center gap-1">
|
||||
<i data-lucide="smartphone" class="w-3 h-3"></i>
|
||||
2FA disponible
|
||||
</span>
|
||||
<span class="flex items-center gap-1">
|
||||
<i data-lucide="key" class="w-3 h-3"></i>
|
||||
SSO Enterprise
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Professional Footer -->
|
||||
<div class="pro-footer text-center space-y-3">
|
||||
<div class="flex items-center justify-center space-x-6 text-sm text-blue-200">
|
||||
<a href="#" class="hover:text-white transition-colors flex items-center gap-1">
|
||||
<i data-lucide="life-buoy" class="w-4 h-4"></i>
|
||||
Support Pro
|
||||
</a>
|
||||
<a href="#" class="hover:text-white transition-colors flex items-center gap-1">
|
||||
<i data-lucide="shield" class="w-4 h-4"></i>
|
||||
Sécurité Renforcée
|
||||
</a>
|
||||
<a href="#" class="hover:text-white transition-colors flex items-center gap-1">
|
||||
<i data-lucide="zap" class="w-4 h-4"></i>
|
||||
API Premium
|
||||
</a>
|
||||
</div>
|
||||
<p class="text-xs text-blue-300">© 2024 AperoNight • Plateforme Événementielle Premium • Tous droits réservés</p>
|
||||
<div class="flex items-center justify-center space-x-2 text-xs text-blue-400">
|
||||
<span class="flex items-center gap-1">
|
||||
<div class="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
|
||||
Système opérationnel
|
||||
</span>
|
||||
<span>•</span>
|
||||
<span>99.9% uptime</span>
|
||||
<span>•</span>
|
||||
<span>GDPR compliant</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Initialize Lucide icons
|
||||
lucide.createIcons();
|
||||
|
||||
// Enhanced password toggle
|
||||
function togglePassword() {
|
||||
const passwordField = document.getElementById('password');
|
||||
const toggleIcon = document.querySelector('.security-toggle i');
|
||||
|
||||
if (passwordField.type === 'password') {
|
||||
passwordField.type = 'text';
|
||||
toggleIcon.setAttribute('data-lucide', 'unlock');
|
||||
} else {
|
||||
passwordField.type = 'password';
|
||||
toggleIcon.setAttribute('data-lucide', 'lock');
|
||||
}
|
||||
|
||||
lucide.createIcons();
|
||||
}
|
||||
|
||||
// Professional form validation
|
||||
const form = document.querySelector('form');
|
||||
const emailField = document.getElementById('email');
|
||||
const passwordField = document.getElementById('password');
|
||||
|
||||
form.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Reset states
|
||||
emailField.classList.remove('input-error', 'input-success');
|
||||
passwordField.classList.remove('input-error', 'input-success');
|
||||
|
||||
let isValid = true;
|
||||
|
||||
// Professional email validation
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(emailField.value)) {
|
||||
emailField.classList.add('input-error');
|
||||
isValid = false;
|
||||
showNotification('Email invalide', 'error');
|
||||
} else {
|
||||
emailField.classList.add('input-success');
|
||||
}
|
||||
|
||||
// Secure password validation
|
||||
if (passwordField.value.length < 8) {
|
||||
passwordField.classList.add('input-error');
|
||||
isValid = false;
|
||||
showNotification('Mot de passe trop court (min. 8 caractères)', 'error');
|
||||
} else {
|
||||
passwordField.classList.add('input-success');
|
||||
}
|
||||
|
||||
if (isValid) {
|
||||
// Premium loading state
|
||||
const button = document.querySelector('.login-button');
|
||||
const originalContent = button.innerHTML;
|
||||
button.innerHTML = `
|
||||
<div class="flex items-center justify-center space-x-2">
|
||||
<div class="animate-spin w-5 h-5 border-2 border-white border-t-transparent rounded-full"></div>
|
||||
<span>Connexion sécurisée...</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
setTimeout(() => {
|
||||
showNotification('Connexion réussie ! Redirection...', 'success');
|
||||
setTimeout(() => {
|
||||
button.innerHTML = originalContent;
|
||||
}, 1500);
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
|
||||
// Real-time validation
|
||||
emailField.addEventListener('input', function() {
|
||||
this.classList.remove('input-error', 'input-success');
|
||||
});
|
||||
|
||||
passwordField.addEventListener('input', function() {
|
||||
this.classList.remove('input-error', 'input-success');
|
||||
});
|
||||
|
||||
// Professional notification system
|
||||
function showNotification(message, type) {
|
||||
const notification = document.createElement('div');
|
||||
notification.className = `
|
||||
fixed top-4 right-4 z-50 p-4 rounded-lg shadow-2xl max-w-sm
|
||||
${type === 'success' ? 'bg-green-500 text-white' : 'bg-red-500 text-white'}
|
||||
transform transition-all duration-300 ease-out translate-x-full
|
||||
`;
|
||||
notification.innerHTML = `
|
||||
<div class="flex items-center space-x-2">
|
||||
<i data-lucide="${type === 'success' ? 'check-circle' : 'alert-circle'}" class="w-5 h-5"></i>
|
||||
<span class="font-medium">${message}</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(notification);
|
||||
lucide.createIcons();
|
||||
|
||||
setTimeout(() => {
|
||||
notification.style.transform = 'translateX(0)';
|
||||
}, 100);
|
||||
|
||||
setTimeout(() => {
|
||||
notification.style.transform = 'translateX(100%)';
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(notification);
|
||||
}, 300);
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// Enhanced floating label behavior
|
||||
document.querySelectorAll('.input-field').forEach(input => {
|
||||
input.addEventListener('focus', function() {
|
||||
this.nextElementSibling.style.background = 'white';
|
||||
});
|
||||
|
||||
input.addEventListener('blur', function() {
|
||||
if (!this.value) {
|
||||
this.nextElementSibling.style.background = 'var(--input)';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Professional interaction tracking
|
||||
console.log('🚀 AperoNight Premium Login Interface Loaded');
|
||||
console.log('✅ Security features: 2FA, SSO, GDPR compliance');
|
||||
console.log('🎨 Theme: Professional Event Platform');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,125 +0,0 @@
|
||||
:root {
|
||||
/* AperoNight Premium Theme - Telecom Inspired */
|
||||
|
||||
/* Base Colors - Sophisticated Navy & Electric Accents */
|
||||
--background: oklch(0.1200 0.0300 240);
|
||||
--foreground: oklch(0.9500 0.0100 240);
|
||||
--surface: oklch(0.1600 0.0400 240);
|
||||
--surface-elevated: oklch(0.2000 0.0500 240);
|
||||
|
||||
/* Card & Dialog surfaces */
|
||||
--card: oklch(0.9800 0.0100 240);
|
||||
--card-foreground: oklch(0.1500 0.0200 240);
|
||||
--popover: oklch(0.9800 0.0100 240);
|
||||
--popover-foreground: oklch(0.1500 0.0200 240);
|
||||
|
||||
/* Primary - Premium Electric Blue */
|
||||
--primary: oklch(0.5500 0.2400 220);
|
||||
--primary-foreground: oklch(0.9800 0.0100 220);
|
||||
--primary-hover: oklch(0.4800 0.2600 220);
|
||||
--primary-light: oklch(0.8500 0.1200 220);
|
||||
--primary-dark: oklch(0.3500 0.2800 220);
|
||||
|
||||
/* Secondary - Sophisticated Slate */
|
||||
--secondary: oklch(0.8800 0.0200 240);
|
||||
--secondary-foreground: oklch(0.2500 0.0300 240);
|
||||
--secondary-hover: oklch(0.8200 0.0300 240);
|
||||
|
||||
/* Accent - Vibrant Cyan (Events Energy) */
|
||||
--accent: oklch(0.6800 0.2600 200);
|
||||
--accent-foreground: oklch(0.9800 0.0100 200);
|
||||
--accent-light: oklch(0.8800 0.1400 200);
|
||||
--accent-dark: oklch(0.4500 0.3000 200);
|
||||
|
||||
/* Success - Event Success Green */
|
||||
--success: oklch(0.6200 0.2200 140);
|
||||
--success-foreground: oklch(0.9600 0.0200 140);
|
||||
--success-light: oklch(0.9200 0.1000 140);
|
||||
|
||||
/* Warning - Premium Gold */
|
||||
--warning: oklch(0.7500 0.2000 60);
|
||||
--warning-foreground: oklch(0.2000 0.0300 60);
|
||||
--warning-light: oklch(0.9400 0.1000 60);
|
||||
|
||||
/* Error - Professional Red */
|
||||
--destructive: oklch(0.5800 0.2400 20);
|
||||
--destructive-foreground: oklch(0.9700 0.0200 20);
|
||||
--destructive-light: oklch(0.9300 0.1200 20);
|
||||
|
||||
/* Muted tones */
|
||||
--muted: oklch(0.8800 0.0200 240);
|
||||
--muted-foreground: oklch(0.4800 0.0400 240);
|
||||
--muted-dark: oklch(0.7500 0.0300 240);
|
||||
|
||||
/* Borders and inputs */
|
||||
--border: oklch(0.8400 0.0300 240);
|
||||
--input: oklch(0.9600 0.0200 240);
|
||||
--input-border: oklch(0.8200 0.0400 240);
|
||||
--ring: oklch(0.5500 0.2400 220);
|
||||
|
||||
/* Typography - Premium Event Platform */
|
||||
--font-sans: 'Inter', 'Plus Jakarta Sans', system-ui, sans-serif;
|
||||
--font-display: 'Space Grotesk', 'Outfit', system-ui, sans-serif;
|
||||
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
|
||||
|
||||
/* Spacing and layout */
|
||||
--radius: 0.75rem;
|
||||
--spacing: 1rem;
|
||||
|
||||
/* Premium shadow system */
|
||||
--shadow-xs: 0 1px 3px 0 hsl(240 30% 8% / 0.08), 0 1px 2px -1px hsl(240 30% 8% / 0.06);
|
||||
--shadow-sm: 0 2px 6px -1px hsl(240 30% 8% / 0.10), 0 2px 4px -2px hsl(240 30% 8% / 0.08);
|
||||
--shadow: 0 4px 8px -2px hsl(240 30% 8% / 0.12), 0 2px 4px -2px hsl(240 30% 8% / 0.08);
|
||||
--shadow-md: 0 8px 16px -4px hsl(240 30% 8% / 0.14), 0 4px 6px -2px hsl(240 30% 8% / 0.10);
|
||||
--shadow-lg: 0 16px 24px -4px hsl(240 30% 8% / 0.16), 0 8px 8px -4px hsl(240 30% 8% / 0.08);
|
||||
--shadow-xl: 0 20px 32px -8px hsl(240 30% 8% / 0.20), 0 8px 16px -8px hsl(240 30% 8% / 0.12);
|
||||
--shadow-2xl: 0 32px 64px -12px hsl(240 30% 8% / 0.25);
|
||||
|
||||
/* Electric/Glow shadows for premium effects */
|
||||
--shadow-electric: 0 4px 16px -2px hsl(220 100% 70% / 0.20), 0 2px 8px -2px hsl(220 100% 70% / 0.15);
|
||||
--shadow-accent: 0 4px 16px -2px hsl(200 100% 70% / 0.25), 0 2px 8px -2px hsl(200 100% 70% / 0.20);
|
||||
|
||||
/* Premium gradients */
|
||||
--gradient-primary: linear-gradient(135deg, var(--primary) 0%, var(--accent) 100%);
|
||||
--gradient-background: linear-gradient(135deg,
|
||||
oklch(0.1200 0.0300 240) 0%,
|
||||
oklch(0.1000 0.0400 235) 25%,
|
||||
oklch(0.0800 0.0500 230) 50%,
|
||||
oklch(0.1000 0.0400 225) 75%,
|
||||
oklch(0.1200 0.0300 220) 100%);
|
||||
--gradient-card: linear-gradient(135deg,
|
||||
oklch(0.9900 0.0100 240) 0%,
|
||||
oklch(0.9700 0.0200 235) 100%);
|
||||
|
||||
/* Tech pattern overlays */
|
||||
--grid-color: oklch(0.3000 0.0500 240);
|
||||
--dot-color: oklch(0.2500 0.0600 220);
|
||||
--connection-color: oklch(0.4000 0.1200 210);
|
||||
|
||||
/* Glass morphism for premium feel */
|
||||
--glass-bg: oklch(0.9800 0.0100 240 / 0.80);
|
||||
--glass-border: oklch(0.8500 0.0300 240 / 0.30);
|
||||
--glass-backdrop: blur(16px) saturate(200%);
|
||||
|
||||
/* Professional states */
|
||||
--hover-lift: translateY(-2px);
|
||||
--hover-scale: scale(1.02);
|
||||
--focus-ring: 0 0 0 3px var(--ring);
|
||||
|
||||
/* Event-specific colors */
|
||||
--event-vip: oklch(0.6500 0.2500 45);
|
||||
--event-premium: oklch(0.5500 0.2200 280);
|
||||
--event-standard: oklch(0.6000 0.1800 160);
|
||||
--event-available: oklch(0.6200 0.2000 140);
|
||||
--event-limited: oklch(0.7200 0.2000 50);
|
||||
--event-sold-out: oklch(0.5500 0.2200 15);
|
||||
|
||||
/* Radius variations */
|
||||
--radius-xs: calc(var(--radius) - 4px);
|
||||
--radius-sm: calc(var(--radius) - 2px);
|
||||
--radius-md: var(--radius);
|
||||
--radius-lg: calc(var(--radius) + 4px);
|
||||
--radius-xl: calc(var(--radius) + 8px);
|
||||
--radius-2xl: calc(var(--radius) + 12px);
|
||||
--radius-full: 9999px;
|
||||
}
|
||||
@@ -1,385 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Dashboard - Minimalist Typography Design</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--primary: #1a1a1a;
|
||||
--secondary: #6b7280;
|
||||
--accent: #3b82f6;
|
||||
--background: #fafafa;
|
||||
--surface: #ffffff;
|
||||
--border: #e5e7eb;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Inter', sans-serif;
|
||||
background-color: var(--background);
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.mono { font-family: 'JetBrains Mono', monospace; }
|
||||
|
||||
.minimal-card {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.minimal-card:hover {
|
||||
border-color: var(--accent);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.metric-number {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.fade-in {
|
||||
animation: fadeIn 0.6s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(20px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
.text-subtle { color: var(--secondary); }
|
||||
.bg-subtle { background-color: #f8fafc; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="min-h-screen">
|
||||
<!-- Navigation -->
|
||||
<nav class="border-b border-gray-200 bg-white">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex justify-between items-center h-16">
|
||||
<div class="flex items-center space-x-8">
|
||||
<h1 class="text-xl font-semibold">ApéroNight</h1>
|
||||
<div class="flex space-x-6">
|
||||
<a href="#" class="text-gray-900 border-b-2 border-blue-500 pb-1">Dashboard</a>
|
||||
<a href="#" class="text-gray-500 hover:text-gray-900">Événements</a>
|
||||
<a href="#" class="text-gray-500 hover:text-gray-900">Profil</a>
|
||||
</div>
|
||||
</div>
|
||||
<button class="p-2 rounded-lg hover:bg-gray-100">
|
||||
<i data-lucide="bell" class="w-5 h-5"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
|
||||
<!-- Header -->
|
||||
<div class="mb-12 fade-in">
|
||||
<h1 class="text-4xl font-bold mb-2">Bonjour, Marie</h1>
|
||||
<p class="text-lg text-subtle">Voici un aperçu de vos activités et événements</p>
|
||||
</div>
|
||||
|
||||
<!-- Critical Alert - Draft Tickets -->
|
||||
<div class="minimal-card rounded-lg p-6 mb-8 border-l-4 border-orange-400 bg-orange-50 fade-in">
|
||||
<div class="flex items-start justify-between">
|
||||
<div class="flex items-start space-x-3">
|
||||
<div class="p-2 bg-orange-100 rounded-lg">
|
||||
<i data-lucide="clock" class="w-5 h-5 text-orange-600"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-semibold text-gray-900 mb-1">Action requise</h3>
|
||||
<p class="text-sm text-gray-600 mb-3">2 billets en attente de paiement expirent dans 25 minutes</p>
|
||||
|
||||
<!-- Ticket Details -->
|
||||
<div class="bg-white rounded-lg p-3 mb-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<span class="font-medium text-sm">Soirée Jazz au Sunset</span>
|
||||
<span class="text-xs text-gray-500 ml-2">2 billets • €70</span>
|
||||
</div>
|
||||
<span class="mono text-xs bg-orange-100 text-orange-800 px-2 py-1 rounded">1/3 tentatives</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="bg-orange-600 text-white px-4 py-2 rounded-lg text-sm font-medium hover:bg-orange-700 transition-colors">
|
||||
Payer maintenant
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Metrics Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-12 fade-in">
|
||||
<div class="minimal-card rounded-lg p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="text-sm font-medium text-subtle">Réservations</span>
|
||||
<i data-lucide="calendar-check" class="w-4 h-4 text-green-500"></i>
|
||||
</div>
|
||||
<div class="metric-number text-3xl text-gray-900 mb-1">05</div>
|
||||
<div class="text-xs text-subtle">+2 ce mois</div>
|
||||
</div>
|
||||
|
||||
<div class="minimal-card rounded-lg p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="text-sm font-medium text-subtle">Aujourd'hui</span>
|
||||
<i data-lucide="clock" class="w-4 h-4 text-blue-500"></i>
|
||||
</div>
|
||||
<div class="metric-number text-3xl text-gray-900 mb-1">03</div>
|
||||
<div class="text-xs text-subtle">événements</div>
|
||||
</div>
|
||||
|
||||
<div class="minimal-card rounded-lg p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="text-sm font-medium text-subtle">Demain</span>
|
||||
<i data-lucide="calendar" class="w-4 h-4 text-purple-500"></i>
|
||||
</div>
|
||||
<div class="metric-number text-3xl text-gray-900 mb-1">07</div>
|
||||
<div class="text-xs text-subtle">événements</div>
|
||||
</div>
|
||||
|
||||
<div class="minimal-card rounded-lg p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="text-sm font-medium text-subtle">À venir</span>
|
||||
<i data-lucide="trending-up" class="w-4 h-4 text-orange-500"></i>
|
||||
</div>
|
||||
<div class="metric-number text-3xl text-gray-900 mb-1">15</div>
|
||||
<div class="text-xs text-subtle">cette semaine</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Content Sections -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
|
||||
<!-- My Events -->
|
||||
<div class="lg:col-span-2">
|
||||
<div class="minimal-card rounded-lg p-6 fade-in">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<h2 class="text-xl font-semibold">Mes événements</h2>
|
||||
<button class="text-accent text-sm font-medium hover:underline">Voir tout</button>
|
||||
</div>
|
||||
|
||||
<div class="space-y-3">
|
||||
<!-- Event Row -->
|
||||
<div class="flex items-center space-x-4 py-3 border-b border-gray-100 last:border-b-0">
|
||||
<div class="w-2 h-12 bg-red-400 rounded-full"></div>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="font-medium">Concert Rock Alternative</h3>
|
||||
<span class="mono text-xs bg-green-100 text-green-800 px-2 py-1 rounded">CONFIRMÉ</span>
|
||||
</div>
|
||||
<p class="text-sm text-subtle">Aujourd'hui 21:00 • Salle Pleyel</p>
|
||||
</div>
|
||||
<button class="p-2 hover:bg-gray-100 rounded-lg">
|
||||
<i data-lucide="download" class="w-4 h-4 text-gray-500"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-4 py-3 border-b border-gray-100 last:border-b-0">
|
||||
<div class="w-2 h-12 bg-blue-400 rounded-full"></div>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="font-medium">Networking Tech</h3>
|
||||
<span class="mono text-xs bg-blue-100 text-blue-800 px-2 py-1 rounded">DEMAIN</span>
|
||||
</div>
|
||||
<p class="text-sm text-subtle">19:00 • WeWork République</p>
|
||||
</div>
|
||||
<button class="p-2 hover:bg-gray-100 rounded-lg">
|
||||
<i data-lucide="map-pin" class="w-4 h-4 text-gray-500"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-4 py-3 border-b border-gray-100 last:border-b-0">
|
||||
<div class="w-2 h-12 bg-green-400 rounded-full"></div>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="font-medium">Brunch du Dimanche</h3>
|
||||
<span class="mono text-xs bg-yellow-100 text-yellow-800 px-2 py-1 rounded">DIMANCHE</span>
|
||||
</div>
|
||||
<p class="text-sm text-subtle">11:00 • Café de Flore</p>
|
||||
</div>
|
||||
<button class="p-2 hover:bg-gray-100 rounded-lg">
|
||||
<i data-lucide="calendar" class="w-4 h-4 text-gray-500"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Actions & Today -->
|
||||
<div class="space-y-6">
|
||||
<!-- Quick Actions -->
|
||||
<div class="minimal-card rounded-lg p-6 fade-in">
|
||||
<h3 class="font-semibold mb-4">Actions rapides</h3>
|
||||
<div class="space-y-3">
|
||||
<button class="w-full flex items-center space-x-3 p-3 rounded-lg hover:bg-gray-50 transition-colors text-left">
|
||||
<div class="p-2 bg-blue-100 rounded-lg">
|
||||
<i data-lucide="plus" class="w-4 h-4 text-blue-600"></i>
|
||||
</div>
|
||||
<span class="font-medium text-sm">Nouvel événement</span>
|
||||
</button>
|
||||
|
||||
<button class="w-full flex items-center space-x-3 p-3 rounded-lg hover:bg-gray-50 transition-colors text-left">
|
||||
<div class="p-2 bg-green-100 rounded-lg">
|
||||
<i data-lucide="search" class="w-4 h-4 text-green-600"></i>
|
||||
</div>
|
||||
<span class="font-medium text-sm">Rechercher</span>
|
||||
</button>
|
||||
|
||||
<button class="w-full flex items-center space-x-3 p-3 rounded-lg hover:bg-gray-50 transition-colors text-left">
|
||||
<div class="p-2 bg-purple-100 rounded-lg">
|
||||
<i data-lucide="heart" class="w-4 h-4 text-purple-600"></i>
|
||||
</div>
|
||||
<span class="font-medium text-sm">Favoris</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Today's Schedule -->
|
||||
<div class="minimal-card rounded-lg p-6 fade-in">
|
||||
<h3 class="font-semibold mb-4">Aujourd'hui</h3>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-start space-x-3">
|
||||
<div class="mono text-xs bg-gray-100 px-2 py-1 rounded mt-1">14:00</div>
|
||||
<div class="flex-1">
|
||||
<h4 class="font-medium text-sm">Cours de Cuisine</h4>
|
||||
<p class="text-xs text-subtle">École Ducasse</p>
|
||||
</div>
|
||||
<span class="w-2 h-2 bg-yellow-400 rounded-full mt-2"></span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-start space-x-3">
|
||||
<div class="mono text-xs bg-gray-100 px-2 py-1 rounded mt-1">20:30</div>
|
||||
<div class="flex-1">
|
||||
<h4 class="font-medium text-sm">Festival de Cinéma</h4>
|
||||
<p class="text-xs text-subtle">MK2 Bibliothèque</p>
|
||||
</div>
|
||||
<span class="w-2 h-2 bg-red-400 rounded-full mt-2"></span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-start space-x-3">
|
||||
<div class="mono text-xs bg-gray-100 px-2 py-1 rounded mt-1">22:00</div>
|
||||
<div class="flex-1">
|
||||
<h4 class="font-medium text-sm">Soirée Jazz</h4>
|
||||
<p class="text-xs text-subtle">Le Sunset</p>
|
||||
</div>
|
||||
<span class="w-2 h-2 bg-blue-400 rounded-full mt-2"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Stats -->
|
||||
<div class="minimal-card rounded-lg p-6 fade-in">
|
||||
<h3 class="font-semibold mb-4">Statistiques</h3>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-subtle">Total participations</span>
|
||||
<span class="mono font-medium">127</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-subtle">Événements créés</span>
|
||||
<span class="mono font-medium">12</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-subtle">Note moyenne</span>
|
||||
<span class="mono font-medium">4.8/5</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Upcoming Events Grid -->
|
||||
<div class="mt-12">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<h2 class="text-2xl font-semibold">Événements à venir</h2>
|
||||
<div class="flex items-center space-x-4">
|
||||
<button class="text-sm text-subtle hover:text-gray-900 flex items-center space-x-1">
|
||||
<i data-lucide="filter" class="w-4 h-4"></i>
|
||||
<span>Filtrer</span>
|
||||
</button>
|
||||
<button class="text-sm text-subtle hover:text-gray-900 flex items-center space-x-1">
|
||||
<i data-lucide="grid-3x3" class="w-4 h-4"></i>
|
||||
<span>Vue</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<!-- Event Card -->
|
||||
<div class="minimal-card rounded-lg overflow-hidden fade-in">
|
||||
<div class="aspect-video bg-gradient-to-br from-purple-400 to-purple-600 flex items-center justify-center">
|
||||
<i data-lucide="music" class="w-12 h-12 text-white"></i>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<div class="flex items-start justify-between mb-2">
|
||||
<h3 class="font-semibold">Concert Électro</h3>
|
||||
<span class="mono text-xs bg-gray-100 px-2 py-1 rounded">€45</span>
|
||||
</div>
|
||||
<p class="text-sm text-subtle mb-3">Samedi 21 Sept • Berghain</p>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-xs text-green-600 bg-green-100 px-2 py-1 rounded">12 places restantes</span>
|
||||
<button class="text-accent text-sm font-medium hover:underline">Réserver</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="minimal-card rounded-lg overflow-hidden fade-in">
|
||||
<div class="aspect-video bg-gradient-to-br from-green-400 to-teal-600 flex items-center justify-center">
|
||||
<i data-lucide="leaf" class="w-12 h-12 text-white"></i>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<div class="flex items-start justify-between mb-2">
|
||||
<h3 class="font-semibold">Marché Bio</h3>
|
||||
<span class="mono text-xs bg-green-100 text-green-600 px-2 py-1 rounded">GRATUIT</span>
|
||||
</div>
|
||||
<p class="text-sm text-subtle mb-3">Dimanche 22 Sept • Place des Vosges</p>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-xs text-blue-600 bg-blue-100 px-2 py-1 rounded">Accès libre</span>
|
||||
<button class="text-accent text-sm font-medium hover:underline">Voir détails</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="minimal-card rounded-lg overflow-hidden fade-in">
|
||||
<div class="aspect-video bg-gradient-to-br from-orange-400 to-red-600 flex items-center justify-center">
|
||||
<i data-lucide="book-open" class="w-12 h-12 text-white"></i>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<div class="flex items-start justify-between mb-2">
|
||||
<h3 class="font-semibold">Salon du Livre</h3>
|
||||
<span class="mono text-xs bg-gray-100 px-2 py-1 rounded">€15</span>
|
||||
</div>
|
||||
<p class="text-sm text-subtle mb-3">Lundi 23 Sept • Grand Palais</p>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-xs text-yellow-600 bg-yellow-100 px-2 py-1 rounded">Populaire</span>
|
||||
<button class="text-accent text-sm font-medium hover:underline">Réserver</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Load More -->
|
||||
<div class="text-center mt-8">
|
||||
<button class="text-accent font-medium hover:underline">Charger plus d'événements</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
lucide.createIcons();
|
||||
|
||||
// Stagger animations
|
||||
const fadeElements = document.querySelectorAll('.fade-in');
|
||||
fadeElements.forEach((el, index) => {
|
||||
el.style.animationDelay = `${index * 0.1}s`;
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,556 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Dashboard - Data Visualization Enhanced</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body { font-family: 'Inter', sans-serif; }
|
||||
|
||||
.progress-ring {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
.progress-ring__circle {
|
||||
transition: stroke-dashoffset 0.35s;
|
||||
transform-origin: 50% 50%;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.8) 100%);
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.gradient-bg {
|
||||
background: linear-gradient(135deg, #1e3a8a 0%, #3b82f6 50%, #06b6d4 100%);
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
position: relative;
|
||||
height: 200px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.timeline-item::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background: currentColor;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="min-h-screen bg-gray-50">
|
||||
<div class="min-h-screen">
|
||||
<!-- Header -->
|
||||
<div class="gradient-bg px-6 py-8">
|
||||
<div class="max-w-7xl mx-auto">
|
||||
<div class="flex items-center justify-between mb-8">
|
||||
<div>
|
||||
<h1 class="text-4xl font-bold text-white mb-2">Dashboard Analytics</h1>
|
||||
<p class="text-blue-100">Analyse détaillée de vos événements et participations</p>
|
||||
</div>
|
||||
<div class="flex items-center space-x-4">
|
||||
<select class="bg-white/20 backdrop-blur-lg border border-white/30 rounded-lg px-4 py-2 text-white text-sm">
|
||||
<option>7 derniers jours</option>
|
||||
<option>30 derniers jours</option>
|
||||
<option>3 derniers mois</option>
|
||||
</select>
|
||||
<button class="bg-white/20 backdrop-blur-lg border border-white/30 rounded-lg px-4 py-2 text-white text-sm font-medium hover:bg-white/30 transition-all">
|
||||
<i data-lucide="download" class="w-4 h-4 inline mr-2"></i>
|
||||
Exporter
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- KPI Cards with Progress -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
<!-- Participation Rate -->
|
||||
<div class="stat-card rounded-2xl p-6">
|
||||
<div class="flex items-start justify-between mb-4">
|
||||
<div>
|
||||
<h3 class="text-sm font-medium text-gray-600">Taux de participation</h3>
|
||||
<p class="text-3xl font-bold text-gray-900 mt-2">87%</p>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<svg class="progress-ring w-16 h-16" viewBox="0 0 40 40">
|
||||
<circle class="progress-ring__circle" stroke="#e5e7eb" stroke-width="3" fill="transparent" r="16" cx="20" cy="20"/>
|
||||
<circle class="progress-ring__circle" stroke="#10b981" stroke-width="3" fill="transparent" r="16" cx="20" cy="20"
|
||||
stroke-dasharray="87 13" stroke-linecap="round"/>
|
||||
</svg>
|
||||
<div class="absolute inset-0 flex items-center justify-center">
|
||||
<i data-lucide="trending-up" class="w-6 h-6 text-green-600"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center text-sm">
|
||||
<span class="text-green-600 font-medium">+5%</span>
|
||||
<span class="text-gray-500 ml-1">vs. mois dernier</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Événements créés -->
|
||||
<div class="stat-card rounded-2xl p-6">
|
||||
<div class="flex items-start justify-between mb-4">
|
||||
<div>
|
||||
<h3 class="text-sm font-medium text-gray-600">Événements créés</h3>
|
||||
<p class="text-3xl font-bold text-gray-900 mt-2">12</p>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<svg class="progress-ring w-16 h-16" viewBox="0 0 40 40">
|
||||
<circle class="progress-ring__circle" stroke="#e5e7eb" stroke-width="3" fill="transparent" r="16" cx="20" cy="20"/>
|
||||
<circle class="progress-ring__circle" stroke="#3b82f6" stroke-width="3" fill="transparent" r="16" cx="20" cy="20"
|
||||
stroke-dasharray="60 40" stroke-linecap="round"/>
|
||||
</svg>
|
||||
<div class="absolute inset-0 flex items-center justify-center">
|
||||
<i data-lucide="plus-circle" class="w-6 h-6 text-blue-600"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center text-sm">
|
||||
<span class="text-blue-600 font-medium">+3</span>
|
||||
<span class="text-gray-500 ml-1">ce mois</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Revenus -->
|
||||
<div class="stat-card rounded-2xl p-6">
|
||||
<div class="flex items-start justify-between mb-4">
|
||||
<div>
|
||||
<h3 class="text-sm font-medium text-gray-600">Revenus</h3>
|
||||
<p class="text-3xl font-bold text-gray-900 mt-2">€2,340</p>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<svg class="progress-ring w-16 h-16" viewBox="0 0 40 40">
|
||||
<circle class="progress-ring__circle" stroke="#e5e7eb" stroke-width="3" fill="transparent" r="16" cx="20" cy="20"/>
|
||||
<circle class="progress-ring__circle" stroke="#8b5cf6" stroke-width="3" fill="transparent" r="16" cx="20" cy="20"
|
||||
stroke-dasharray="78 22" stroke-linecap="round"/>
|
||||
</svg>
|
||||
<div class="absolute inset-0 flex items-center justify-center">
|
||||
<i data-lucide="euro" class="w-6 h-6 text-purple-600"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center text-sm">
|
||||
<span class="text-purple-600 font-medium">+18%</span>
|
||||
<span class="text-gray-500 ml-1">vs. mois dernier</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Satisfaction -->
|
||||
<div class="stat-card rounded-2xl p-6">
|
||||
<div class="flex items-start justify-between mb-4">
|
||||
<div>
|
||||
<h3 class="text-sm font-medium text-gray-600">Satisfaction</h3>
|
||||
<p class="text-3xl font-bold text-gray-900 mt-2">4.8</p>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<svg class="progress-ring w-16 h-16" viewBox="0 0 40 40">
|
||||
<circle class="progress-ring__circle" stroke="#e5e7eb" stroke-width="3" fill="transparent" r="16" cx="20" cy="20"/>
|
||||
<circle class="progress-ring__circle" stroke="#f59e0b" stroke-width="3" fill="transparent" r="16" cx="20" cy="20"
|
||||
stroke-dasharray="96 4" stroke-linecap="round"/>
|
||||
</svg>
|
||||
<div class="absolute inset-0 flex items-center justify-center">
|
||||
<i data-lucide="star" class="w-6 h-6 text-yellow-500 fill-current"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center text-sm">
|
||||
<span class="text-yellow-600 font-medium">+0.2</span>
|
||||
<span class="text-gray-500 ml-1">vs. mois dernier</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="max-w-7xl mx-auto px-6 py-8">
|
||||
|
||||
<!-- Critical Alert -->
|
||||
<div class="bg-red-50 border border-red-200 rounded-2xl p-6 mb-8">
|
||||
<div class="flex items-start space-x-4">
|
||||
<div class="p-3 bg-red-100 rounded-xl">
|
||||
<i data-lucide="alert-circle" class="w-6 h-6 text-red-600"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<h3 class="text-lg font-semibold text-red-900 mb-2">Paiements en attente - Action urgente</h3>
|
||||
<p class="text-red-700 mb-4">2 billets expirent dans les 25 prochaines minutes</p>
|
||||
|
||||
<div class="bg-white rounded-xl p-4 border border-red-200">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<div>
|
||||
<h4 class="font-semibold text-gray-900">Soirée Jazz au Sunset</h4>
|
||||
<p class="text-sm text-gray-600">2 billets • Tentative 1/3</p>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<p class="text-2xl font-bold text-gray-900">€70</p>
|
||||
<div class="w-24 bg-red-200 rounded-full h-2 mt-1">
|
||||
<div class="bg-red-600 h-2 rounded-full transition-all" style="width: 15%"></div>
|
||||
</div>
|
||||
<p class="text-xs text-red-600 mt-1">25min restantes</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="bg-red-600 hover:bg-red-700 text-white px-6 py-3 rounded-xl font-medium transition-colors">
|
||||
Payer maintenant
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Charts and Analytics -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-8">
|
||||
|
||||
<!-- Event Participation Chart -->
|
||||
<div class="bg-white rounded-2xl p-6 shadow-sm">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900">Participation aux événements</h3>
|
||||
<div class="flex items-center space-x-2">
|
||||
<button class="text-sm bg-blue-100 text-blue-700 px-3 py-1 rounded-full">7j</button>
|
||||
<button class="text-sm text-gray-500 px-3 py-1 rounded-full">30j</button>
|
||||
<button class="text-sm text-gray-500 px-3 py-1 rounded-full">3m</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<canvas id="participationChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Event Categories Pie Chart -->
|
||||
<div class="bg-white rounded-2xl p-6 shadow-sm">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-6">Catégories d'événements</h3>
|
||||
<div class="chart-container">
|
||||
<canvas id="categoriesChart"></canvas>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4 mt-4">
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="w-3 h-3 bg-blue-500 rounded-full"></div>
|
||||
<span class="text-sm text-gray-600">Concert (40%)</span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="w-3 h-3 bg-green-500 rounded-full"></div>
|
||||
<span class="text-sm text-gray-600">Cuisine (25%)</span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="w-3 h-3 bg-yellow-500 rounded-full"></div>
|
||||
<span class="text-sm text-gray-600">Tech (20%)</span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="w-3 h-3 bg-purple-500 rounded-full"></div>
|
||||
<span class="text-sm text-gray-600">Art (15%)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Timeline and Events -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
|
||||
<!-- Event Timeline -->
|
||||
<div class="lg:col-span-2">
|
||||
<div class="bg-white rounded-2xl p-6 shadow-sm">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900">Timeline des événements</h3>
|
||||
<button class="text-blue-600 text-sm font-medium hover:underline">Voir tout</button>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<div class="absolute left-4 top-0 bottom-0 w-px bg-gray-200"></div>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Timeline Item -->
|
||||
<div class="relative pl-10 pb-6">
|
||||
<div class="timeline-item text-green-600">
|
||||
<div class="flex items-start justify-between">
|
||||
<div>
|
||||
<h4 class="font-semibold text-gray-900">Concert Rock Alternative</h4>
|
||||
<p class="text-sm text-gray-600 mt-1">Aujourd'hui 21:00 • Salle Pleyel</p>
|
||||
<div class="flex items-center space-x-4 mt-2">
|
||||
<div class="flex items-center text-xs">
|
||||
<i data-lucide="users" class="w-3 h-3 mr-1"></i>
|
||||
<span>156 participants</span>
|
||||
</div>
|
||||
<div class="flex items-center text-xs">
|
||||
<i data-lucide="star" class="w-3 h-3 mr-1 fill-current text-yellow-500"></i>
|
||||
<span>4.7/5</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="bg-green-100 text-green-800 px-3 py-1 rounded-full text-xs font-medium">CONFIRMÉ</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative pl-10 pb-6">
|
||||
<div class="timeline-item text-blue-600">
|
||||
<div class="flex items-start justify-between">
|
||||
<div>
|
||||
<h4 class="font-semibold text-gray-900">Networking Tech</h4>
|
||||
<p class="text-sm text-gray-600 mt-1">Demain 19:00 • WeWork République</p>
|
||||
<div class="flex items-center space-x-4 mt-2">
|
||||
<div class="flex items-center text-xs">
|
||||
<i data-lucide="users" class="w-3 h-3 mr-1"></i>
|
||||
<span>42/50 participants</span>
|
||||
</div>
|
||||
<div class="w-16 bg-gray-200 rounded-full h-1">
|
||||
<div class="bg-blue-600 h-1 rounded-full" style="width: 84%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="bg-blue-100 text-blue-800 px-3 py-1 rounded-full text-xs font-medium">DEMAIN</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative pl-10 pb-6">
|
||||
<div class="timeline-item text-purple-600">
|
||||
<div class="flex items-start justify-between">
|
||||
<div>
|
||||
<h4 class="font-semibold text-gray-900">Brunch du Dimanche</h4>
|
||||
<p class="text-sm text-gray-600 mt-1">Dimanche 11:00 • Café de Flore</p>
|
||||
<div class="flex items-center space-x-4 mt-2">
|
||||
<div class="flex items-center text-xs">
|
||||
<i data-lucide="users" class="w-3 h-3 mr-1"></i>
|
||||
<span>8/12 participants</span>
|
||||
</div>
|
||||
<div class="w-16 bg-gray-200 rounded-full h-1">
|
||||
<div class="bg-purple-600 h-1 rounded-full" style="width: 67%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="bg-yellow-100 text-yellow-800 px-3 py-1 rounded-full text-xs font-medium">EN COURS</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative pl-10 pb-6">
|
||||
<div class="timeline-item text-gray-400">
|
||||
<div class="flex items-start justify-between">
|
||||
<div>
|
||||
<h4 class="font-semibold text-gray-900">Cours de Photographie</h4>
|
||||
<p class="text-sm text-gray-600 mt-1">Mercredi 18:00 • Studio Martin</p>
|
||||
<div class="flex items-center space-x-4 mt-2">
|
||||
<div class="flex items-center text-xs">
|
||||
<i data-lucide="calendar" class="w-3 h-3 mr-1"></i>
|
||||
<span>Dans 3 jours</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="bg-gray-100 text-gray-600 px-3 py-1 rounded-full text-xs font-medium">PLANIFIÉ</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Sidebar -->
|
||||
<div class="space-y-6">
|
||||
<!-- Performance Metrics -->
|
||||
<div class="bg-white rounded-2xl p-6 shadow-sm">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Performance</h3>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-gray-600">Taux de réussite</span>
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="w-20 bg-gray-200 rounded-full h-2">
|
||||
<div class="bg-green-600 h-2 rounded-full" style="width: 94%"></div>
|
||||
</div>
|
||||
<span class="text-sm font-medium">94%</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-gray-600">Engagement</span>
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="w-20 bg-gray-200 rounded-full h-2">
|
||||
<div class="bg-blue-600 h-2 rounded-full" style="width: 78%"></div>
|
||||
</div>
|
||||
<span class="text-sm font-medium">78%</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-gray-600">Recommandations</span>
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="w-20 bg-gray-200 rounded-full h-2">
|
||||
<div class="bg-purple-600 h-2 rounded-full" style="width: 89%"></div>
|
||||
</div>
|
||||
<span class="text-sm font-medium">89%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Top Categories -->
|
||||
<div class="bg-white rounded-2xl p-6 shadow-sm">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Top catégories</h3>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="w-8 h-8 bg-blue-100 rounded-lg flex items-center justify-center">
|
||||
<i data-lucide="music" class="w-4 h-4 text-blue-600"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="font-medium text-sm">Concert</span>
|
||||
<span class="text-sm text-gray-500">40%</span>
|
||||
</div>
|
||||
<div class="w-full bg-gray-200 rounded-full h-1 mt-1">
|
||||
<div class="bg-blue-600 h-1 rounded-full" style="width: 40%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="w-8 h-8 bg-green-100 rounded-lg flex items-center justify-center">
|
||||
<i data-lucide="utensils" class="w-4 h-4 text-green-600"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="font-medium text-sm">Cuisine</span>
|
||||
<span class="text-sm text-gray-500">25%</span>
|
||||
</div>
|
||||
<div class="w-full bg-gray-200 rounded-full h-1 mt-1">
|
||||
<div class="bg-green-600 h-1 rounded-full" style="width: 25%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="w-8 h-8 bg-yellow-100 rounded-lg flex items-center justify-center">
|
||||
<i data-lucide="laptop" class="w-4 h-4 text-yellow-600"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="font-medium text-sm">Tech</span>
|
||||
<span class="text-sm text-gray-500">20%</span>
|
||||
</div>
|
||||
<div class="w-full bg-gray-200 rounded-full h-1 mt-1">
|
||||
<div class="bg-yellow-600 h-1 rounded-full" style="width: 20%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="w-8 h-8 bg-purple-100 rounded-lg flex items-center justify-center">
|
||||
<i data-lucide="palette" class="w-4 h-4 text-purple-600"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="font-medium text-sm">Art</span>
|
||||
<span class="text-sm text-gray-500">15%</span>
|
||||
</div>
|
||||
<div class="w-full bg-gray-200 rounded-full h-1 mt-1">
|
||||
<div class="bg-purple-600 h-1 rounded-full" style="width: 15%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Stats -->
|
||||
<div class="bg-white rounded-2xl p-6 shadow-sm">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Statistiques rapides</h3>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-gray-600">Événements créés</span>
|
||||
<span class="font-medium">127</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-gray-600">Participants totaux</span>
|
||||
<span class="font-medium">2,456</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-gray-600">Note moyenne</span>
|
||||
<span class="font-medium">4.8/5</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-gray-600">Revenus</span>
|
||||
<span class="font-medium">€12,340</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
lucide.createIcons();
|
||||
|
||||
// Participation Chart
|
||||
const participationCtx = document.getElementById('participationChart').getContext('2d');
|
||||
new Chart(participationCtx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ['Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam', 'Dim'],
|
||||
datasets: [{
|
||||
label: 'Participations',
|
||||
data: [12, 19, 8, 15, 24, 18, 22],
|
||||
borderColor: '#3b82f6',
|
||||
backgroundColor: 'rgba(59, 130, 246, 0.1)',
|
||||
fill: true,
|
||||
tension: 0.4
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
grid: {
|
||||
display: false
|
||||
}
|
||||
},
|
||||
x: {
|
||||
grid: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Categories Chart
|
||||
const categoriesCtx = document.getElementById('categoriesChart').getContext('2d');
|
||||
new Chart(categoriesCtx, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: ['Concert', 'Cuisine', 'Tech', 'Art'],
|
||||
datasets: [{
|
||||
data: [40, 25, 20, 15],
|
||||
backgroundColor: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6'],
|
||||
borderWidth: 0
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,521 +0,0 @@
|
||||
/* ========================================
|
||||
Dark Mode UI Framework
|
||||
A beautiful dark mode design system
|
||||
======================================== */
|
||||
|
||||
/* ========================================
|
||||
CSS Variables & Theme
|
||||
======================================== */
|
||||
:root {
|
||||
/* Dark Mode Color Palette */
|
||||
--background: oklch(0.145 0 0);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.205 0 0);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.922 0 0);
|
||||
--primary-foreground: oklch(0.205 0 0);
|
||||
--secondary: oklch(0.269 0 0);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.269 0 0);
|
||||
--muted-foreground: oklch(0.708 0 0);
|
||||
--accent: oklch(0.269 0 0);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.556 0 0);
|
||||
|
||||
/* Spacing & Layout */
|
||||
--radius: 0.625rem;
|
||||
--spacing-xs: 0.25rem;
|
||||
--spacing-sm: 0.5rem;
|
||||
--spacing-md: 0.75rem;
|
||||
--spacing-lg: 1rem;
|
||||
--spacing-xl: 1.5rem;
|
||||
--spacing-2xl: 2rem;
|
||||
--spacing-3xl: 3rem;
|
||||
|
||||
/* Typography */
|
||||
--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
--font-size-xs: 0.75rem;
|
||||
--font-size-sm: 0.875rem;
|
||||
--font-size-base: 1rem;
|
||||
--font-size-lg: 1.125rem;
|
||||
--font-size-xl: 1.25rem;
|
||||
--font-size-2xl: 1.5rem;
|
||||
--font-size-3xl: 1.875rem;
|
||||
--font-size-4xl: 2.25rem;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Base Styles
|
||||
======================================== */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--background);
|
||||
color: var(--foreground);
|
||||
font-family: var(--font-family);
|
||||
line-height: 1.6;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
html.dark {
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Layout Components
|
||||
======================================== */
|
||||
.container {
|
||||
max-width: 64rem;
|
||||
margin: 0 auto;
|
||||
padding: var(--spacing-2xl) var(--spacing-lg);
|
||||
}
|
||||
|
||||
.container-sm {
|
||||
max-width: 42rem;
|
||||
}
|
||||
|
||||
.container-lg {
|
||||
max-width: 80rem;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
|
||||
.grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
||||
.grid-cols-auto { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
|
||||
|
||||
.gap-sm { gap: var(--spacing-sm); }
|
||||
.gap-md { gap: var(--spacing-md); }
|
||||
.gap-lg { gap: var(--spacing-lg); }
|
||||
.gap-xl { gap: var(--spacing-xl); }
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.flex-col {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.items-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.justify-center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.justify-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Card Components
|
||||
======================================== */
|
||||
.card {
|
||||
background-color: var(--card);
|
||||
color: var(--card-foreground);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: calc(var(--radius) + 4px);
|
||||
padding: var(--spacing-xl);
|
||||
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Button Components
|
||||
======================================== */
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--spacing-sm);
|
||||
white-space: nowrap;
|
||||
border-radius: var(--radius);
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: 500;
|
||||
transition: all 0.2s;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: var(--spacing-sm) var(--spacing-lg);
|
||||
min-height: 2.25rem;
|
||||
outline: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: var(--primary);
|
||||
color: var(--primary-foreground);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: rgba(236, 236, 236, 0.9);
|
||||
}
|
||||
|
||||
.btn-outline {
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--border);
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
.btn-outline:hover {
|
||||
background-color: var(--accent);
|
||||
}
|
||||
|
||||
.btn-ghost {
|
||||
background-color: transparent;
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
.btn-ghost:hover {
|
||||
background-color: var(--accent);
|
||||
}
|
||||
|
||||
.btn-destructive {
|
||||
background-color: var(--destructive);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-destructive:hover {
|
||||
background-color: rgba(220, 38, 38, 0.9);
|
||||
}
|
||||
|
||||
/* Button Sizes */
|
||||
.btn-sm {
|
||||
padding: var(--spacing-xs) var(--spacing-md);
|
||||
font-size: var(--font-size-xs);
|
||||
min-height: 2rem;
|
||||
}
|
||||
|
||||
.btn-lg {
|
||||
padding: var(--spacing-md) var(--spacing-xl);
|
||||
font-size: var(--font-size-base);
|
||||
min-height: 2.75rem;
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
padding: var(--spacing-sm);
|
||||
width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Form Components
|
||||
======================================== */
|
||||
.form-input {
|
||||
width: 100%;
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
padding: var(--spacing-sm) var(--spacing-md);
|
||||
color: var(--foreground);
|
||||
font-size: var(--font-size-sm);
|
||||
outline: none;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
border-color: var(--ring);
|
||||
box-shadow: 0 0 0 3px rgba(136, 136, 136, 0.5);
|
||||
}
|
||||
|
||||
.form-input::placeholder {
|
||||
color: var(--muted-foreground);
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Badge Components
|
||||
======================================== */
|
||||
.badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: var(--radius);
|
||||
border: 1px solid;
|
||||
padding: 0.125rem var(--spacing-sm);
|
||||
font-size: var(--font-size-xs);
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Priority Badge Variants */
|
||||
.badge-priority-high {
|
||||
background: rgba(127, 29, 29, 0.3);
|
||||
color: rgb(252, 165, 165);
|
||||
border: 1px solid rgba(153, 27, 27, 0.5);
|
||||
}
|
||||
|
||||
.badge-priority-medium {
|
||||
background: rgba(120, 53, 15, 0.3);
|
||||
color: rgb(252, 211, 77);
|
||||
border: 1px solid rgba(146, 64, 14, 0.5);
|
||||
}
|
||||
|
||||
.badge-priority-low {
|
||||
background: rgba(20, 83, 45, 0.3);
|
||||
color: rgb(134, 239, 172);
|
||||
border: 1px solid rgba(22, 101, 52, 0.5);
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Tab Components
|
||||
======================================== */
|
||||
.tab-list {
|
||||
display: flex;
|
||||
gap: var(--spacing-sm);
|
||||
margin-bottom: var(--spacing-xl);
|
||||
}
|
||||
|
||||
.tab-button {
|
||||
background-color: transparent;
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
color: var(--foreground);
|
||||
text-transform: capitalize;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s ease;
|
||||
padding: var(--spacing-sm) var(--spacing-md);
|
||||
border-radius: var(--radius);
|
||||
cursor: pointer;
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.tab-button:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
border-color: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
.tab-button.active {
|
||||
background-color: #f8f9fa !important;
|
||||
color: #1a1a1a !important;
|
||||
border-color: #f8f9fa !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tab-button.active:hover {
|
||||
background-color: #e9ecef !important;
|
||||
border-color: #e9ecef !important;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Typography
|
||||
======================================== */
|
||||
.text-xs { font-size: var(--font-size-xs); }
|
||||
.text-sm { font-size: var(--font-size-sm); }
|
||||
.text-base { font-size: var(--font-size-base); }
|
||||
.text-lg { font-size: var(--font-size-lg); }
|
||||
.text-xl { font-size: var(--font-size-xl); }
|
||||
.text-2xl { font-size: var(--font-size-2xl); }
|
||||
.text-3xl { font-size: var(--font-size-3xl); }
|
||||
.text-4xl { font-size: var(--font-size-4xl); }
|
||||
|
||||
.font-normal { font-weight: 400; }
|
||||
.font-medium { font-weight: 500; }
|
||||
.font-semibold { font-weight: 600; }
|
||||
.font-bold { font-weight: 700; }
|
||||
|
||||
.text-primary { color: var(--primary); }
|
||||
.text-muted { color: var(--muted-foreground); }
|
||||
.text-destructive { color: var(--destructive); }
|
||||
|
||||
.gradient-text {
|
||||
background: linear-gradient(to right, var(--primary), rgba(236, 236, 236, 0.6));
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Icon System
|
||||
======================================== */
|
||||
.icon {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
fill: currentColor;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.icon-sm { width: 0.875rem; height: 0.875rem; }
|
||||
.icon-lg { width: 1.25rem; height: 1.25rem; }
|
||||
.icon-xl { width: 1.5rem; height: 1.5rem; }
|
||||
.icon-2xl { width: 2rem; height: 2rem; }
|
||||
|
||||
/* ========================================
|
||||
Interactive Components
|
||||
======================================== */
|
||||
.checkbox {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.checkbox:hover {
|
||||
border-color: var(--ring);
|
||||
}
|
||||
|
||||
.checkbox.checked {
|
||||
background-color: rgb(22, 163, 74);
|
||||
border-color: rgb(22, 163, 74);
|
||||
}
|
||||
|
||||
.checkbox.checked::after {
|
||||
content: '✓';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: white;
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
List Components
|
||||
======================================== */
|
||||
.list-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-lg);
|
||||
padding: var(--spacing-lg);
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.list-item:hover {
|
||||
background-color: rgba(255, 255, 255, 0.025);
|
||||
}
|
||||
|
||||
.list-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.list-item.completed {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Empty State Component
|
||||
======================================== */
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: var(--spacing-3xl) var(--spacing-lg);
|
||||
color: var(--muted-foreground);
|
||||
}
|
||||
|
||||
.empty-state .icon {
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
margin: 0 auto var(--spacing-lg);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Utility Classes
|
||||
======================================== */
|
||||
.hidden { display: none; }
|
||||
.block { display: block; }
|
||||
.flex { display: flex; }
|
||||
.inline-flex { display: inline-flex; }
|
||||
|
||||
.w-full { width: 100%; }
|
||||
.h-full { height: 100%; }
|
||||
.min-h-screen { min-height: 100vh; }
|
||||
|
||||
.opacity-50 { opacity: 0.5; }
|
||||
.opacity-60 { opacity: 0.6; }
|
||||
.opacity-75 { opacity: 0.75; }
|
||||
|
||||
.transition-all { transition: all 0.2s ease; }
|
||||
.transition-colors { transition: color 0.2s ease, background-color 0.2s ease; }
|
||||
.transition-opacity { transition: opacity 0.2s ease; }
|
||||
|
||||
/* ========================================
|
||||
Responsive Design
|
||||
======================================== */
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
padding: var(--spacing-lg);
|
||||
}
|
||||
|
||||
.grid-cols-auto {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.flex-col-mobile {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.text-center-mobile {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.gap-sm-mobile { gap: var(--spacing-sm); }
|
||||
|
||||
.hidden-mobile { display: none; }
|
||||
.block-mobile { display: block; }
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.text-2xl { font-size: var(--font-size-xl); }
|
||||
.text-3xl { font-size: var(--font-size-2xl); }
|
||||
.text-4xl { font-size: var(--font-size-3xl); }
|
||||
|
||||
.container {
|
||||
padding: var(--spacing-lg) var(--spacing-sm);
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Animation Utilities
|
||||
======================================== */
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(10px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
.animate-fade-in {
|
||||
animation: fadeIn 0.3s ease-out;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Focus & Accessibility
|
||||
======================================== */
|
||||
.focus-visible:focus-visible {
|
||||
outline: 2px solid var(--ring);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
* {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
:root {
|
||||
--background: oklch(0.9961 0.0039 106.7952);
|
||||
--foreground: oklch(0.0902 0.0203 286.0532);
|
||||
--card: oklch(0.9961 0.0039 106.7952);
|
||||
--card-foreground: oklch(0.0902 0.0203 286.0532);
|
||||
--popover: oklch(0.9961 0.0039 106.7952);
|
||||
--popover-foreground: oklch(0.0902 0.0203 286.0532);
|
||||
--primary: oklch(0.4902 0.2314 320.7094);
|
||||
--primary-foreground: oklch(0.9961 0.0039 106.7952);
|
||||
--secondary: oklch(0.6471 0.1686 342.5570);
|
||||
--secondary-foreground: oklch(0.0902 0.0203 286.0532);
|
||||
--muted: oklch(0.9412 0.0196 106.7952);
|
||||
--muted-foreground: oklch(0.4706 0.0157 286.0532);
|
||||
--accent: oklch(0.7255 0.1451 51.2345);
|
||||
--accent-foreground: oklch(0.0902 0.0203 286.0532);
|
||||
--destructive: oklch(0.5765 0.2314 27.3319);
|
||||
--destructive-foreground: oklch(0.9961 0.0039 106.7952);
|
||||
--border: oklch(0.8824 0.0157 106.7952);
|
||||
--input: oklch(0.8824 0.0157 106.7952);
|
||||
--ring: oklch(0.4902 0.2314 320.7094);
|
||||
--chart-1: oklch(0.4902 0.2314 320.7094);
|
||||
--chart-2: oklch(0.6471 0.1686 342.5570);
|
||||
--chart-3: oklch(0.7255 0.1451 51.2345);
|
||||
--chart-4: oklch(0.5490 0.2157 142.4953);
|
||||
--chart-5: oklch(0.6157 0.2275 328.3634);
|
||||
--sidebar: oklch(0.9412 0.0196 106.7952);
|
||||
--sidebar-foreground: oklch(0.0902 0.0203 286.0532);
|
||||
--sidebar-primary: oklch(0.4902 0.2314 320.7094);
|
||||
--sidebar-primary-foreground: oklch(0.9961 0.0039 106.7952);
|
||||
--sidebar-accent: oklch(0.6471 0.1686 342.5570);
|
||||
--sidebar-accent-foreground: oklch(0.0902 0.0203 286.0532);
|
||||
--sidebar-border: oklch(0.8824 0.0157 106.7952);
|
||||
--sidebar-ring: oklch(0.4902 0.2314 320.7094);
|
||||
--font-sans: 'Inter', sans-serif;
|
||||
--font-serif: 'Playfair Display', serif;
|
||||
--font-mono: 'Fira Code', monospace;
|
||||
--radius: 1rem;
|
||||
--shadow-2xs: 0 1px 2px 0px hsl(320 70% 20% / 0.08);
|
||||
--shadow-xs: 0 1px 3px 0px hsl(320 70% 20% / 0.10);
|
||||
--shadow-sm: 0 2px 4px 0px hsl(320 70% 20% / 0.10), 0 1px 2px -1px hsl(320 70% 20% / 0.06);
|
||||
--shadow: 0 4px 6px 0px hsl(320 70% 20% / 0.12), 0 2px 4px -1px hsl(320 70% 20% / 0.08);
|
||||
--shadow-md: 0 6px 8px 0px hsl(320 70% 20% / 0.15), 0 4px 6px -1px hsl(320 70% 20% / 0.10);
|
||||
--shadow-lg: 0 10px 15px 0px hsl(320 70% 20% / 0.20), 0 6px 8px -1px hsl(320 70% 20% / 0.15);
|
||||
--shadow-xl: 0 20px 25px 0px hsl(320 70% 20% / 0.25), 0 10px 15px -1px hsl(320 70% 20% / 0.20);
|
||||
--shadow-2xl: 0 25px 50px 0px hsl(320 70% 20% / 0.30);
|
||||
--tracking-normal: 0em;
|
||||
--spacing: 0.25rem;
|
||||
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
}
|
||||
@@ -1,538 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Fête de l'Humanité 2025 - Billets</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;500;600;700&family=Fira+Code:wght@300;400;500&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="festival_theme.css">
|
||||
|
||||
<style>
|
||||
* {
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
box-sizing: border-box !important;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--font-sans) !important;
|
||||
background: var(--background) !important;
|
||||
color: var(--foreground) !important;
|
||||
line-height: 1.6 !important;
|
||||
}
|
||||
|
||||
.festival-gradient {
|
||||
background: linear-gradient(135deg,
|
||||
oklch(0.4902 0.2314 320.7094) 0%,
|
||||
oklch(0.6471 0.1686 342.5570) 50%,
|
||||
oklch(0.7255 0.1451 51.2345) 100%) !important;
|
||||
}
|
||||
|
||||
.ticket-card {
|
||||
background: var(--card) !important;
|
||||
border: 2px solid var(--border) !important;
|
||||
border-radius: var(--radius-lg) !important;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
|
||||
box-shadow: var(--shadow) !important;
|
||||
}
|
||||
|
||||
.ticket-card:hover {
|
||||
transform: translateY(-4px) !important;
|
||||
box-shadow: var(--shadow-lg) !important;
|
||||
border-color: var(--primary) !important;
|
||||
}
|
||||
|
||||
.ticket-card.selected {
|
||||
border-color: var(--primary) !important;
|
||||
background: linear-gradient(135deg, var(--card), oklch(0.4902 0.2314 320.7094 / 0.05)) !important;
|
||||
box-shadow: var(--shadow-lg) !important;
|
||||
}
|
||||
|
||||
.quantity-control {
|
||||
background: var(--muted) !important;
|
||||
border: 1px solid var(--border) !important;
|
||||
border-radius: var(--radius) !important;
|
||||
transition: all 0.2s ease !important;
|
||||
}
|
||||
|
||||
.quantity-control:hover {
|
||||
background: var(--accent) !important;
|
||||
transform: scale(1.05) !important;
|
||||
}
|
||||
|
||||
.cart-summary {
|
||||
background: linear-gradient(135deg,
|
||||
var(--card),
|
||||
oklch(0.4902 0.2314 320.7094 / 0.03)) !important;
|
||||
border: 2px solid var(--primary) !important;
|
||||
border-radius: var(--radius-xl) !important;
|
||||
box-shadow: var(--shadow-md) !important;
|
||||
}
|
||||
|
||||
.checkout-button {
|
||||
background: var(--primary) !important;
|
||||
color: var(--primary-foreground) !important;
|
||||
border: none !important;
|
||||
border-radius: var(--radius-lg) !important;
|
||||
font-weight: 600 !important;
|
||||
transition: all 0.3s ease !important;
|
||||
box-shadow: var(--shadow) !important;
|
||||
}
|
||||
|
||||
.checkout-button:hover:not(:disabled) {
|
||||
background: oklch(0.4302 0.2314 320.7094) !important;
|
||||
transform: translateY(-2px) !important;
|
||||
box-shadow: var(--shadow-lg) !important;
|
||||
}
|
||||
|
||||
.checkout-button:disabled {
|
||||
background: var(--muted) !important;
|
||||
color: var(--muted-foreground) !important;
|
||||
cursor: not-allowed !important;
|
||||
opacity: 0.5 !important;
|
||||
}
|
||||
|
||||
.festival-info {
|
||||
background: linear-gradient(45deg,
|
||||
oklch(0.7255 0.1451 51.2345 / 0.1),
|
||||
oklch(0.6471 0.1686 342.5570 / 0.1)) !important;
|
||||
border-radius: var(--radius-lg) !important;
|
||||
border: 1px solid var(--accent) !important;
|
||||
}
|
||||
|
||||
.hero-section {
|
||||
background: linear-gradient(135deg,
|
||||
oklch(0.4902 0.2314 320.7094 / 0.9) 0%,
|
||||
oklch(0.6471 0.1686 342.5570 / 0.9) 50%,
|
||||
oklch(0.7255 0.1451 51.2345 / 0.9) 100%),
|
||||
url('https://images.unsplash.com/photo-1493225457124-a3eb161ffa5f?w=1200&h=600&fit=crop') !important;
|
||||
background-size: cover !important;
|
||||
background-position: center !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.animate-bounce-slow {
|
||||
animation: bounce 2s infinite !important;
|
||||
}
|
||||
|
||||
.animate-pulse-slow {
|
||||
animation: pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite !important;
|
||||
}
|
||||
|
||||
.ripple-effect {
|
||||
position: relative !important;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.ripple-effect::after {
|
||||
content: '' !important;
|
||||
position: absolute !important;
|
||||
top: 50% !important;
|
||||
left: 50% !important;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
border-radius: 50% !important;
|
||||
background: rgba(255, 255, 255, 0.3) !important;
|
||||
transform: translate(-50%, -50%) !important;
|
||||
transition: width 0.4s, height 0.4s !important;
|
||||
}
|
||||
|
||||
.ripple-effect:hover::after {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-50">
|
||||
<!-- Hero Section -->
|
||||
<section class="hero-section h-96 flex items-center justify-center relative overflow-hidden">
|
||||
<div class="absolute inset-0 bg-black bg-opacity-40"></div>
|
||||
<div class="relative z-10 text-center max-w-4xl mx-auto px-4">
|
||||
<h1 class="text-5xl md:text-6xl font-bold mb-4 font-serif animate-pulse-slow">Fête de l'Humanité 2025</h1>
|
||||
<p class="text-xl md:text-2xl mb-2 opacity-90">14-16 Septembre • La Courneuve</p>
|
||||
<p class="text-lg opacity-80 max-w-2xl mx-auto">Trois jours de musique, débats, culture et solidarité au cœur du plus grand festival populaire de France</p>
|
||||
<div class="flex justify-center items-center mt-6 space-x-6">
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="calendar" class="w-5 h-5 mr-2"></i>
|
||||
<span>3 jours</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="music" class="w-5 h-5 mr-2"></i>
|
||||
<span>100+ concerts</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="users" class="w-5 h-5 mr-2"></i>
|
||||
<span>500k visiteurs</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute bottom-4 left-1/2 transform -translate-x-1/2 animate-bounce-slow">
|
||||
<i data-lucide="chevron-down" class="w-8 h-8 text-white opacity-70"></i>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||
<!-- Ticket Selection Hub -->
|
||||
<div class="mb-12">
|
||||
<div class="text-center mb-10">
|
||||
<h2 class="text-4xl font-bold text-gray-900 mb-4 font-serif">Choisissez vos billets</h2>
|
||||
<p class="text-xl text-gray-600 max-w-2xl mx-auto">Découvrez nos différentes formules pour profiter pleinement du festival</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
<!-- Left Column: Tickets -->
|
||||
<div class="lg:col-span-2">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6 mb-8">
|
||||
<!-- Pass 3 Jours -->
|
||||
<div class="ticket-card p-6 cursor-pointer ripple-effect" onclick="selectTicket('pass3j', 45, 'Pass 3 jours')">
|
||||
<div class="text-center">
|
||||
<div class="festival-gradient w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<i data-lucide="star" class="w-8 h-8 text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-2">Pass 3 Jours</h3>
|
||||
<p class="text-sm text-gray-600 mb-4">Accès complet au festival</p>
|
||||
<div class="text-3xl font-bold text-primary mb-4">45€</div>
|
||||
<div class="text-sm text-green-600 font-medium mb-4">✓ Disponible</div>
|
||||
|
||||
<div class="flex items-center justify-center space-x-3">
|
||||
<button class="quantity-control w-10 h-10 flex items-center justify-center" onclick="event.stopPropagation(); changeQuantity('pass3j', -1)">
|
||||
<i data-lucide="minus" class="w-4 h-4"></i>
|
||||
</button>
|
||||
<span class="w-8 text-center font-medium" id="pass3j-qty">0</span>
|
||||
<button class="quantity-control w-10 h-10 flex items-center justify-center" onclick="event.stopPropagation(); changeQuantity('pass3j', 1)">
|
||||
<i data-lucide="plus" class="w-4 h-4"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Samedi 14 -->
|
||||
<div class="ticket-card p-6 cursor-pointer ripple-effect" onclick="selectTicket('samedi', 18, 'Samedi 14 Sept')">
|
||||
<div class="text-center">
|
||||
<div class="bg-gradient-to-br from-purple-500 to-pink-500 w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<i data-lucide="calendar-days" class="w-8 h-8 text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-2">Samedi 14</h3>
|
||||
<p class="text-sm text-gray-600 mb-4">Journée complète</p>
|
||||
<div class="text-3xl font-bold text-primary mb-4">18€</div>
|
||||
<div class="text-sm text-green-600 font-medium mb-4">✓ Disponible</div>
|
||||
|
||||
<div class="flex items-center justify-center space-x-3">
|
||||
<button class="quantity-control w-10 h-10 flex items-center justify-center" onclick="event.stopPropagation(); changeQuantity('samedi', -1)">
|
||||
<i data-lucide="minus" class="w-4 h-4"></i>
|
||||
</button>
|
||||
<span class="w-8 text-center font-medium" id="samedi-qty">0</span>
|
||||
<button class="quantity-control w-10 h-10 flex items-center justify-center" onclick="event.stopPropagation(); changeQuantity('samedi', 1)">
|
||||
<i data-lucide="plus" class="w-4 h-4"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dimanche 15 -->
|
||||
<div class="ticket-card p-6 cursor-pointer ripple-effect" onclick="selectTicket('dimanche', 18, 'Dimanche 15 Sept')">
|
||||
<div class="text-center">
|
||||
<div class="bg-gradient-to-br from-orange-500 to-red-500 w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<i data-lucide="sun" class="w-8 h-8 text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-2">Dimanche 15</h3>
|
||||
<p class="text-sm text-gray-600 mb-4">Journée complète</p>
|
||||
<div class="text-3xl font-bold text-primary mb-4">18€</div>
|
||||
<div class="text-sm text-green-600 font-medium mb-4">✓ Disponible</div>
|
||||
|
||||
<div class="flex items-center justify-center space-x-3">
|
||||
<button class="quantity-control w-10 h-10 flex items-center justify-center" onclick="event.stopPropagation(); changeQuantity('dimanche', -1)">
|
||||
<i data-lucide="minus" class="w-4 h-4"></i>
|
||||
</button>
|
||||
<span class="w-8 text-center font-medium" id="dimanche-qty">0</span>
|
||||
<button class="quantity-control w-10 h-10 flex items-center justify-center" onclick="event.stopPropagation(); changeQuantity('dimanche', 1)">
|
||||
<i data-lucide="plus" class="w-4 h-4"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lundi 16 -->
|
||||
<div class="ticket-card p-6 cursor-pointer ripple-effect" onclick="selectTicket('lundi', 18, 'Lundi 16 Sept')">
|
||||
<div class="text-center">
|
||||
<div class="bg-gradient-to-br from-green-500 to-blue-500 w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<i data-lucide="moon" class="w-8 h-8 text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-2">Lundi 16</h3>
|
||||
<p class="text-sm text-gray-600 mb-4">Journée complète</p>
|
||||
<div class="text-3xl font-bold text-primary mb-4">18€</div>
|
||||
<div class="text-sm text-green-600 font-medium mb-4">✓ Disponible</div>
|
||||
|
||||
<div class="flex items-center justify-center space-x-3">
|
||||
<button class="quantity-control w-10 h-10 flex items-center justify-center" onclick="event.stopPropagation(); changeQuantity('lundi', -1)">
|
||||
<i data-lucide="minus" class="w-4 h-4"></i>
|
||||
</button>
|
||||
<span class="w-8 text-center font-medium" id="lundi-qty">0</span>
|
||||
<button class="quantity-control w-10 h-10 flex items-center justify-center" onclick="event.stopPropagation(); changeQuantity('lundi', 1)">
|
||||
<i data-lucide="plus" class="w-4 h-4"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tarif Réduit -->
|
||||
<div class="ticket-card p-6 cursor-pointer ripple-effect" onclick="selectTicket('reduit', 12, 'Tarif Réduit')">
|
||||
<div class="text-center">
|
||||
<div class="bg-gradient-to-br from-yellow-500 to-orange-500 w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<i data-lucide="percent" class="w-8 h-8 text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-2">Tarif Réduit</h3>
|
||||
<p class="text-sm text-gray-600 mb-4">Étudiants, -26 ans, RSA</p>
|
||||
<div class="text-3xl font-bold text-primary mb-4">12€</div>
|
||||
<div class="text-sm text-green-600 font-medium mb-4">✓ Disponible</div>
|
||||
|
||||
<div class="flex items-center justify-center space-x-3">
|
||||
<button class="quantity-control w-10 h-10 flex items-center justify-center" onclick="event.stopPropagation(); changeQuantity('reduit', -1)">
|
||||
<i data-lucide="minus" class="w-4 h-4"></i>
|
||||
</button>
|
||||
<span class="w-8 text-center font-medium" id="reduit-qty">0</span>
|
||||
<button class="quantity-control w-10 h-10 flex items-center justify-center" onclick="event.stopPropagation(); changeQuantity('reduit', 1)">
|
||||
<i data-lucide="plus" class="w-4 h-4"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gratuit -12 ans -->
|
||||
<div class="ticket-card p-6 cursor-pointer ripple-effect" onclick="selectTicket('gratuit', 0, 'Gratuit -12 ans')">
|
||||
<div class="text-center">
|
||||
<div class="bg-gradient-to-br from-green-600 to-emerald-600 w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<i data-lucide="gift" class="w-8 h-8 text-white"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 mb-2">Gratuit</h3>
|
||||
<p class="text-sm text-gray-600 mb-4">Enfants -12 ans</p>
|
||||
<div class="text-3xl font-bold text-green-600 mb-4">Gratuit</div>
|
||||
<div class="text-sm text-green-600 font-medium mb-4">✓ Disponible</div>
|
||||
|
||||
<div class="flex items-center justify-center space-x-3">
|
||||
<button class="quantity-control w-10 h-10 flex items-center justify-center" onclick="event.stopPropagation(); changeQuantity('gratuit', -1)">
|
||||
<i data-lucide="minus" class="w-4 h-4"></i>
|
||||
</button>
|
||||
<span class="w-8 text-center font-medium" id="gratuit-qty">0</span>
|
||||
<button class="quantity-control w-10 h-10 flex items-center justify-center" onclick="event.stopPropagation(); changeQuantity('gratuit', 1)">
|
||||
<i data-lucide="plus" class="w-4 h-4"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Column: Cart & Info -->
|
||||
<div class="lg:col-span-1">
|
||||
<!-- Cart Summary -->
|
||||
<div class="cart-summary p-6 mb-8 sticky top-4">
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-6 text-center">Récapitulatif</h3>
|
||||
|
||||
<div id="cart-items" class="space-y-3 mb-6 min-h-[100px]">
|
||||
<div class="text-center text-gray-500 py-8">
|
||||
<i data-lucide="shopping-cart" class="w-12 h-12 mx-auto mb-4 opacity-50"></i>
|
||||
<p>Votre panier est vide</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-gray-200 pt-4 space-y-2">
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-gray-600">Total billets:</span>
|
||||
<span class="font-medium" id="total-quantity">0</span>
|
||||
</div>
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-gray-600">Sous-total:</span>
|
||||
<span class="font-medium" id="subtotal">€0.00</span>
|
||||
</div>
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-gray-600">Frais de service:</span>
|
||||
<span class="font-medium" id="service-fee">€0.00</span>
|
||||
</div>
|
||||
<div class="border-t border-gray-300 pt-2 mt-4">
|
||||
<div class="flex justify-between text-lg font-bold">
|
||||
<span>TOTAL:</span>
|
||||
<span class="text-primary" id="total-amount">€0.00</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button id="checkout-btn" class="checkout-button w-full py-4 px-6 text-lg font-semibold mt-6 disabled" disabled>
|
||||
<i data-lucide="credit-card" class="w-5 h-5 inline-block mr-2"></i>
|
||||
Finaliser la commande
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Festival Info -->
|
||||
<div class="festival-info p-6">
|
||||
<h4 class="text-xl font-bold text-gray-900 mb-4 text-center">🎪 Festival Highlights</h4>
|
||||
<div class="space-y-3 text-sm">
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="music" class="w-5 h-5 mr-3 text-purple-600"></i>
|
||||
<span>100+ concerts et spectacles</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="mic" class="w-5 h-5 mr-3 text-purple-600"></i>
|
||||
<span>Débats et conférences</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="utensils" class="w-5 h-5 mr-3 text-purple-600"></i>
|
||||
<span>Village gastronomique</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="heart" class="w-5 h-5 mr-3 text-purple-600"></i>
|
||||
<span>Village solidaire</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="gamepad-2" class="w-5 h-5 mr-3 text-purple-600"></i>
|
||||
<span>Animations jeunesse</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="train" class="w-5 h-5 mr-3 text-purple-600"></i>
|
||||
<span>Accès RER B La Courneuve</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Initialize Lucide icons
|
||||
lucide.createIcons();
|
||||
|
||||
// Cart state
|
||||
let cart = {};
|
||||
const serviceFeeRate = 0.05; // 5% service fee
|
||||
|
||||
function selectTicket(id, price, name) {
|
||||
// Visual selection effect
|
||||
const cards = document.querySelectorAll('.ticket-card');
|
||||
cards.forEach(card => card.classList.remove('selected'));
|
||||
event.currentTarget.classList.add('selected');
|
||||
|
||||
// Auto-add one ticket if none selected
|
||||
if (!cart[id] || cart[id].quantity === 0) {
|
||||
changeQuantity(id, 1, price, name);
|
||||
}
|
||||
}
|
||||
|
||||
function changeQuantity(id, delta, price, name) {
|
||||
if (!cart[id]) {
|
||||
cart[id] = { quantity: 0, price: price || 0, name: name || '' };
|
||||
}
|
||||
|
||||
// Get price and name from ticket data if not provided
|
||||
if (!price) {
|
||||
const ticketPrices = {
|
||||
'pass3j': { price: 45, name: 'Pass 3 jours' },
|
||||
'samedi': { price: 18, name: 'Samedi 14 Sept' },
|
||||
'dimanche': { price: 18, name: 'Dimanche 15 Sept' },
|
||||
'lundi': { price: 18, name: 'Lundi 16 Sept' },
|
||||
'reduit': { price: 12, name: 'Tarif Réduit' },
|
||||
'gratuit': { price: 0, name: 'Gratuit -12 ans' }
|
||||
};
|
||||
price = ticketPrices[id].price;
|
||||
name = ticketPrices[id].name;
|
||||
cart[id].price = price;
|
||||
cart[id].name = name;
|
||||
}
|
||||
|
||||
cart[id].quantity = Math.max(0, cart[id].quantity + delta);
|
||||
|
||||
// Update quantity display
|
||||
document.getElementById(id + '-qty').textContent = cart[id].quantity;
|
||||
|
||||
// Remove from cart if quantity is 0
|
||||
if (cart[id].quantity === 0) {
|
||||
delete cart[id];
|
||||
}
|
||||
|
||||
updateCartSummary();
|
||||
}
|
||||
|
||||
function updateCartSummary() {
|
||||
const cartItemsContainer = document.getElementById('cart-items');
|
||||
const totalQuantityEl = document.getElementById('total-quantity');
|
||||
const subtotalEl = document.getElementById('subtotal');
|
||||
const serviceFeeEl = document.getElementById('service-fee');
|
||||
const totalAmountEl = document.getElementById('total-amount');
|
||||
const checkoutBtn = document.getElementById('checkout-btn');
|
||||
|
||||
let totalQuantity = 0;
|
||||
let subtotal = 0;
|
||||
let cartItemsHtml = '';
|
||||
|
||||
// Check if cart is empty
|
||||
const hasItems = Object.keys(cart).some(id => cart[id].quantity > 0);
|
||||
|
||||
if (!hasItems) {
|
||||
cartItemsHtml = `
|
||||
<div class="text-center text-gray-500 py-8">
|
||||
<i data-lucide="shopping-cart" class="w-12 h-12 mx-auto mb-4 opacity-50"></i>
|
||||
<p>Votre panier est vide</p>
|
||||
</div>
|
||||
`;
|
||||
checkoutBtn.disabled = true;
|
||||
checkoutBtn.classList.add('disabled');
|
||||
} else {
|
||||
// Build cart items
|
||||
Object.keys(cart).forEach(id => {
|
||||
if (cart[id].quantity > 0) {
|
||||
totalQuantity += cart[id].quantity;
|
||||
subtotal += cart[id].quantity * cart[id].price;
|
||||
|
||||
cartItemsHtml += `
|
||||
<div class="flex justify-between items-center py-2 border-b border-gray-100 last:border-b-0">
|
||||
<div class="flex-1">
|
||||
<div class="font-medium text-sm">${cart[id].name}</div>
|
||||
<div class="text-xs text-gray-500">${cart[id].quantity} × €${cart[id].price.toFixed(2)}</div>
|
||||
</div>
|
||||
<div class="font-medium text-sm">€${(cart[id].quantity * cart[id].price).toFixed(2)}</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
});
|
||||
|
||||
checkoutBtn.disabled = false;
|
||||
checkoutBtn.classList.remove('disabled');
|
||||
}
|
||||
|
||||
const serviceFee = subtotal * serviceFeeRate;
|
||||
const totalAmount = subtotal + serviceFee;
|
||||
|
||||
cartItemsContainer.innerHTML = cartItemsHtml;
|
||||
totalQuantityEl.textContent = totalQuantity;
|
||||
subtotalEl.textContent = `€${subtotal.toFixed(2)}`;
|
||||
serviceFeeEl.textContent = `€${serviceFee.toFixed(2)}`;
|
||||
totalAmountEl.textContent = `€${totalAmount.toFixed(2)}`;
|
||||
|
||||
// Recreate icons for newly added elements
|
||||
lucide.createIcons();
|
||||
}
|
||||
|
||||
// Checkout button click handler
|
||||
document.getElementById('checkout-btn').addEventListener('click', function() {
|
||||
if (this.disabled) return;
|
||||
|
||||
// Simulate checkout process
|
||||
this.innerHTML = '<i data-lucide="loader-2" class="w-5 h-5 inline-block mr-2 animate-spin"></i>Traitement...';
|
||||
this.disabled = true;
|
||||
|
||||
setTimeout(() => {
|
||||
alert('Redirection vers le paiement sécurisé...');
|
||||
this.innerHTML = '<i data-lucide="credit-card" class="w-5 h-5 inline-block mr-2"></i>Finaliser la commande';
|
||||
this.disabled = Object.keys(cart).length === 0;
|
||||
lucide.createIcons();
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
// Initial setup
|
||||
updateCartSummary();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,480 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Connexion - Quantic Telecom</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="quantic_telecom_theme.css">
|
||||
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--font-sans) !important;
|
||||
background: var(--gradient-background) !important;
|
||||
min-height: 100vh !important;
|
||||
position: relative !important;
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
|
||||
/* Background grid pattern */
|
||||
body::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-image:
|
||||
linear-gradient(var(--grid-color) 1px, transparent 1px),
|
||||
linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
|
||||
background-size: 50px 50px;
|
||||
opacity: 0.3;
|
||||
z-index: 0;
|
||||
animation: gridShift 20s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes gridShift {
|
||||
0% { transform: translate(0, 0); }
|
||||
100% { transform: translate(50px, 50px); }
|
||||
}
|
||||
|
||||
/* Page entrance animation */
|
||||
.page-container {
|
||||
animation: pageLoad 800ms ease-out forwards;
|
||||
opacity: 0;
|
||||
transform: translateY(40px);
|
||||
}
|
||||
|
||||
@keyframes pageLoad {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Logo animation */
|
||||
.logo-container {
|
||||
animation: logoFade 1200ms ease-out 200ms forwards;
|
||||
opacity: 0;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
|
||||
@keyframes logoFade {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Card slide animation */
|
||||
.login-card {
|
||||
background: var(--glass-bg) !important;
|
||||
backdrop-filter: var(--glass-backdrop) !important;
|
||||
border: 1px solid var(--glass-border) !important;
|
||||
border-radius: var(--radius-lg) !important;
|
||||
box-shadow: var(--shadow-xl) !important;
|
||||
animation: cardSlide 600ms cubic-bezier(0.4, 0, 0.2, 1) 400ms forwards;
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
transition: all 300ms ease-out;
|
||||
}
|
||||
|
||||
.login-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-2xl);
|
||||
}
|
||||
|
||||
@keyframes cardSlide {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Input field styling */
|
||||
.input-group {
|
||||
position: relative;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
width: 100%;
|
||||
padding: 1rem 3rem 1rem 1rem;
|
||||
border: 2px solid var(--border);
|
||||
border-radius: var(--radius-md);
|
||||
background: var(--input);
|
||||
color: var(--foreground);
|
||||
font-size: 1rem;
|
||||
transition: all 200ms ease-out;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.input-field:focus {
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 0 0 3px var(--ring);
|
||||
transform: scale(1.01);
|
||||
}
|
||||
|
||||
.input-field:focus + .floating-label {
|
||||
transform: translateY(-10px) scale(0.75);
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.floating-label {
|
||||
position: absolute;
|
||||
left: 1rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: var(--input);
|
||||
padding: 0 0.5rem;
|
||||
color: var(--muted-foreground);
|
||||
pointer-events: none;
|
||||
transition: all 200ms ease-out;
|
||||
}
|
||||
|
||||
.input-field:not(:placeholder-shown) + .floating-label {
|
||||
transform: translateY(-10px) scale(0.75);
|
||||
}
|
||||
|
||||
/* Password toggle */
|
||||
.password-toggle {
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--muted-foreground);
|
||||
cursor: pointer;
|
||||
transition: all 150ms ease-out;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.password-toggle:hover {
|
||||
opacity: 1;
|
||||
transform: translateY(-50%) rotate(90deg);
|
||||
}
|
||||
|
||||
/* Button styling */
|
||||
.login-button {
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
background: var(--gradient-primary) !important;
|
||||
border: none;
|
||||
border-radius: var(--radius-md);
|
||||
color: var(--primary-foreground);
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 200ms ease-out;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.login-button:hover {
|
||||
transform: scale(1.02);
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.login-button:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
/* Ripple effect */
|
||||
.login-button::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
transition: width 400ms ease-out, height 400ms ease-out;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.login-button:active::before {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
/* Checkbox styling */
|
||||
.custom-checkbox {
|
||||
appearance: none;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
border: 2px solid var(--border);
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--input);
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
transition: all 200ms ease-out;
|
||||
}
|
||||
|
||||
.custom-checkbox:checked {
|
||||
background: var(--primary);
|
||||
border-color: var(--primary);
|
||||
animation: checkboxTick 250ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
}
|
||||
|
||||
.custom-checkbox:checked::before {
|
||||
content: '✓';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: var(--primary-foreground);
|
||||
font-size: 0.875rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@keyframes checkboxTick {
|
||||
0% { transform: scale(0); }
|
||||
50% { transform: scale(1.2); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
/* Link styling */
|
||||
.forgot-link {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
transition: all 200ms ease-out;
|
||||
}
|
||||
|
||||
.forgot-link::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -2px;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
background: var(--accent);
|
||||
transition: width 200ms ease-out;
|
||||
}
|
||||
|
||||
.forgot-link:hover::after {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Validation states */
|
||||
.input-error {
|
||||
border-color: var(--destructive) !important;
|
||||
animation: errorShake 300ms ease-out;
|
||||
}
|
||||
|
||||
@keyframes errorShake {
|
||||
0%, 100% { transform: translateX(0); }
|
||||
25% { transform: translateX(-8px); }
|
||||
75% { transform: translateX(8px); }
|
||||
}
|
||||
|
||||
.input-success {
|
||||
border-color: var(--success) !important;
|
||||
animation: successPulse 500ms ease-out;
|
||||
}
|
||||
|
||||
@keyframes successPulse {
|
||||
0% { transform: scale(1); }
|
||||
50% { transform: scale(1.1); opacity: 0.8; }
|
||||
100% { transform: scale(1); opacity: 1; }
|
||||
}
|
||||
|
||||
/* Loading states */
|
||||
.skeleton {
|
||||
background: linear-gradient(90deg, var(--muted) 25%, var(--accent) 50%, var(--muted) 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: skeleton 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes skeleton {
|
||||
0% { background-position: -200% 0; }
|
||||
100% { background-position: 200% 0; }
|
||||
}
|
||||
|
||||
/* Responsive design */
|
||||
@media (max-width: 640px) {
|
||||
.login-card {
|
||||
margin: 1rem;
|
||||
padding: 2rem 1.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-container relative z-10 flex items-center justify-center min-h-screen p-4">
|
||||
<div class="w-full max-w-md">
|
||||
<!-- Logo and Header -->
|
||||
<div class="logo-container text-center mb-8">
|
||||
<div class="mb-4">
|
||||
<div class="w-16 h-16 mx-auto bg-gradient-to-br from-blue-600 to-blue-800 rounded-xl flex items-center justify-center">
|
||||
<i data-lucide="wifi" class="w-8 h-8 text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="text-2xl font-bold text-gray-900 mb-2">Quantic Telecom</h1>
|
||||
<p class="text-gray-600 text-sm">Connexion Espace Client</p>
|
||||
<p class="text-gray-500 text-xs mt-1">Votre espace client sécurisé</p>
|
||||
</div>
|
||||
|
||||
<!-- Login Card -->
|
||||
<div class="login-card p-8">
|
||||
<form class="space-y-6">
|
||||
<!-- Email Field -->
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="email"
|
||||
class="input-field"
|
||||
placeholder=" "
|
||||
required
|
||||
id="email"
|
||||
>
|
||||
<label class="floating-label" for="email">Adresse e-mail</label>
|
||||
<div class="absolute right-3 top-1/2 transform -translate-y-1/2">
|
||||
<i data-lucide="mail" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Password Field -->
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="password"
|
||||
class="input-field"
|
||||
placeholder=" "
|
||||
required
|
||||
id="password"
|
||||
>
|
||||
<label class="floating-label" for="password">Mot de passe</label>
|
||||
<button type="button" class="password-toggle" onclick="togglePassword()">
|
||||
<i data-lucide="eye" class="w-5 h-5"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Remember Me -->
|
||||
<div class="flex items-center justify-between">
|
||||
<label class="flex items-center space-x-3 cursor-pointer">
|
||||
<input type="checkbox" class="custom-checkbox" id="remember">
|
||||
<span class="text-sm text-gray-700">Se souvenir de moi</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Login Button -->
|
||||
<button type="submit" class="login-button">
|
||||
<span class="relative z-10">SE CONNECTER</span>
|
||||
</button>
|
||||
|
||||
<!-- Forgot Password -->
|
||||
<div class="text-center">
|
||||
<a href="#" class="forgot-link text-sm">Mot de passe oublié ?</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Support Footer -->
|
||||
<div class="text-center mt-8 space-y-2">
|
||||
<p class="text-xs text-gray-500">
|
||||
Besoin d'aide ?
|
||||
<a href="#" class="text-blue-600 hover:text-blue-800 transition-colors">Support technique</a>
|
||||
</p>
|
||||
<p class="text-xs text-gray-400">© 2024 Quantic Telecom - Tous droits réservés</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Initialize Lucide icons
|
||||
lucide.createIcons();
|
||||
|
||||
// Password toggle functionality
|
||||
function togglePassword() {
|
||||
const passwordField = document.getElementById('password');
|
||||
const toggleIcon = document.querySelector('.password-toggle i');
|
||||
|
||||
if (passwordField.type === 'password') {
|
||||
passwordField.type = 'text';
|
||||
toggleIcon.setAttribute('data-lucide', 'eye-off');
|
||||
} else {
|
||||
passwordField.type = 'password';
|
||||
toggleIcon.setAttribute('data-lucide', 'eye');
|
||||
}
|
||||
|
||||
lucide.createIcons();
|
||||
}
|
||||
|
||||
// Form validation
|
||||
const form = document.querySelector('form');
|
||||
const emailField = document.getElementById('email');
|
||||
const passwordField = document.getElementById('password');
|
||||
|
||||
form.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Reset validation states
|
||||
emailField.classList.remove('input-error', 'input-success');
|
||||
passwordField.classList.remove('input-error', 'input-success');
|
||||
|
||||
let isValid = true;
|
||||
|
||||
// Email validation
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(emailField.value)) {
|
||||
emailField.classList.add('input-error');
|
||||
isValid = false;
|
||||
} else {
|
||||
emailField.classList.add('input-success');
|
||||
}
|
||||
|
||||
// Password validation
|
||||
if (passwordField.value.length < 6) {
|
||||
passwordField.classList.add('input-error');
|
||||
isValid = false;
|
||||
} else {
|
||||
passwordField.classList.add('input-success');
|
||||
}
|
||||
|
||||
if (isValid) {
|
||||
// Simulate login process
|
||||
const button = document.querySelector('.login-button');
|
||||
button.innerHTML = '<div class="flex items-center justify-center"><div class="animate-spin w-5 h-5 border-2 border-white border-t-transparent rounded-full mr-2"></div>Connexion...</div>';
|
||||
|
||||
setTimeout(() => {
|
||||
alert('Connexion réussie ! (Demo)');
|
||||
button.innerHTML = '<span class="relative z-10">SE CONNECTER</span>';
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
|
||||
// Real-time input validation
|
||||
emailField.addEventListener('input', function() {
|
||||
this.classList.remove('input-error', 'input-success');
|
||||
});
|
||||
|
||||
passwordField.addEventListener('input', function() {
|
||||
this.classList.remove('input-error', 'input-success');
|
||||
});
|
||||
|
||||
// Add floating label behavior for better UX
|
||||
document.querySelectorAll('.input-field').forEach(input => {
|
||||
input.addEventListener('focus', function() {
|
||||
this.nextElementSibling.classList.add('focused');
|
||||
});
|
||||
|
||||
input.addEventListener('blur', function() {
|
||||
if (!this.value) {
|
||||
this.nextElementSibling.classList.remove('focused');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,71 +0,0 @@
|
||||
:root {
|
||||
/* Quantic Telecom Brand Colors */
|
||||
--background: oklch(0.9800 0.0050 240);
|
||||
--foreground: oklch(0.1500 0.0100 240);
|
||||
--card: oklch(1.0000 0 0);
|
||||
--card-foreground: oklch(0.1500 0.0100 240);
|
||||
--popover: oklch(1.0000 0 0);
|
||||
--popover-foreground: oklch(0.1500 0.0100 240);
|
||||
|
||||
/* Primary - Telecom Blue */
|
||||
--primary: oklch(0.4800 0.2000 240);
|
||||
--primary-foreground: oklch(0.9800 0.0050 240);
|
||||
--primary-hover: oklch(0.4200 0.2200 240);
|
||||
|
||||
/* Secondary - Tech Gray */
|
||||
--secondary: oklch(0.9200 0.0100 240);
|
||||
--secondary-foreground: oklch(0.2500 0.0150 240);
|
||||
|
||||
/* Accent - Electric Blue */
|
||||
--accent: oklch(0.6500 0.2800 220);
|
||||
--accent-foreground: oklch(0.9800 0.0050 240);
|
||||
|
||||
/* Muted tones */
|
||||
--muted: oklch(0.9600 0.0080 240);
|
||||
--muted-foreground: oklch(0.4500 0.0120 240);
|
||||
|
||||
/* Success/Error states */
|
||||
--success: oklch(0.5500 0.2000 140);
|
||||
--success-foreground: oklch(0.9800 0.0050 140);
|
||||
--destructive: oklch(0.5500 0.2200 20);
|
||||
--destructive-foreground: oklch(0.9800 0.0050 20);
|
||||
|
||||
/* Borders and inputs */
|
||||
--border: oklch(0.8800 0.0150 240);
|
||||
--input: oklch(0.9600 0.0080 240);
|
||||
--ring: oklch(0.4800 0.2000 240);
|
||||
|
||||
/* Typography */
|
||||
--font-sans: 'Inter', 'Segoe UI', system-ui, sans-serif;
|
||||
--font-serif: 'Inter', 'Segoe UI', system-ui, serif;
|
||||
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
|
||||
|
||||
/* Spacing and layout */
|
||||
--radius: 0.5rem;
|
||||
--spacing: 1rem;
|
||||
|
||||
/* Modern shadows for depth */
|
||||
--shadow-xs: 0 1px 3px 0 hsl(240 25% 3% / 0.06);
|
||||
--shadow-sm: 0 1px 3px 0 hsl(240 25% 3% / 0.08), 0 1px 2px -1px hsl(240 25% 3% / 0.08);
|
||||
--shadow: 0 4px 8px -2px hsl(240 25% 3% / 0.08), 0 2px 4px -2px hsl(240 25% 3% / 0.06);
|
||||
--shadow-md: 0 8px 16px -4px hsl(240 25% 3% / 0.08), 0 4px 6px -2px hsl(240 25% 3% / 0.06);
|
||||
--shadow-lg: 0 16px 24px -4px hsl(240 25% 3% / 0.08), 0 8px 8px -4px hsl(240 25% 3% / 0.04);
|
||||
--shadow-xl: 0 20px 32px -8px hsl(240 25% 3% / 0.12), 0 8px 16px -8px hsl(240 25% 3% / 0.08);
|
||||
|
||||
/* Gradients for modern appeal */
|
||||
--gradient-primary: linear-gradient(135deg, var(--primary) 0%, var(--accent) 100%);
|
||||
--gradient-background: linear-gradient(135deg, oklch(0.9900 0.0030 240) 0%, oklch(0.9700 0.0080 220) 100%);
|
||||
|
||||
/* Grid overlay for tech aesthetic */
|
||||
--grid-color: oklch(0.9400 0.0100 240);
|
||||
|
||||
/* Glass morphism effects */
|
||||
--glass-bg: oklch(1.0000 0 0 / 0.70);
|
||||
--glass-border: oklch(0.9000 0.0200 240 / 0.20);
|
||||
--glass-backdrop: blur(12px) saturate(180%);
|
||||
|
||||
--radius-sm: calc(var(--radius) - 2px);
|
||||
--radius-md: var(--radius);
|
||||
--radius-lg: calc(var(--radius) + 4px);
|
||||
--radius-xl: calc(var(--radius) + 8px);
|
||||
}
|
||||
@@ -1,40 +1,92 @@
|
||||
<div class="grid gap-6 mb-6 md:grid-cols-2 lg:grid-cols-4">
|
||||
<div class="grid gap-8 mb-8 md:grid-cols-2 lg:grid-cols-4">
|
||||
<div>
|
||||
<h3 class="font-bold text-lg text-white mb-3">À propos</h3>
|
||||
<ul class="space-y-2">
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Je suis organisateur</a></li>
|
||||
<%# <li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Pour les artistes</a></li> %>
|
||||
<%# <li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Kit presse</a></li> %>
|
||||
<%# <li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Artistes</a></li> %>
|
||||
<h3 class="font-bold text-lg text-white mb-4 flex items-center">
|
||||
<i data-lucide="info" class="w-5 h-5 mr-2 text-yellow-400"></i>
|
||||
À propos
|
||||
</h3>
|
||||
<ul class="space-y-3">
|
||||
<li><a href="#" class="text-gray-400 text-sm hover:text-yellow-400 transition-colors duration-300 flex items-center">
|
||||
<i data-lucide="briefcase" class="w-4 h-4 mr-2"></i>
|
||||
Je suis organisateur
|
||||
</a></li>
|
||||
<li><a href="#" class="text-gray-400 text-sm hover:text-yellow-400 transition-colors duration-300 flex items-center">
|
||||
<i data-lucide="users" class="w-4 h-4 mr-2"></i>
|
||||
Communauté
|
||||
</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 class="font-bold text-lg text-white mb-3">Villes</h3>
|
||||
<ul class="space-y-2">
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Paris</a></li>
|
||||
<%# <li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Lyon</a></li> %>
|
||||
<%# <li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Marseille / Aix-en-Provence</a></li> %>
|
||||
<%# <li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Toulouse</a></li> %>
|
||||
<h3 class="font-bold text-lg text-white mb-4 flex items-center">
|
||||
<i data-lucide="map-pin" class="w-5 h-5 mr-2 text-yellow-400"></i>
|
||||
Villes
|
||||
</h3>
|
||||
<ul class="space-y-3">
|
||||
<li><a href="#" class="text-gray-400 text-sm hover:text-yellow-400 transition-colors duration-300 flex items-center">
|
||||
<i data-lucide="map" class="w-4 h-4 mr-2"></i>
|
||||
Paris
|
||||
</a></li>
|
||||
<li><a href="#" class="text-gray-400 text-sm hover:text-yellow-400 transition-colors duration-300 flex items-center">
|
||||
<i data-lucide="map" class="w-4 h-4 mr-2"></i>
|
||||
Lyon (bientôt)
|
||||
</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<%# <div>
|
||||
<h3 class="font-bold text-lg text-white mb-3">Organisateurs</h3>
|
||||
<ul class="space-y-2">
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Help Center</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Contact Us</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Safety Guidelines</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Cancellation Policy</a></li>
|
||||
</ul>
|
||||
</div> %>
|
||||
|
||||
<div>
|
||||
<h3 class="font-bold text-lg text-white mb-3">Support</h3>
|
||||
<ul class="space-y-2">
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Aide</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Nous contacter</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Signaler un contenu inapproprié</a></li>
|
||||
<h3 class="font-bold text-lg text-white mb-4 flex items-center">
|
||||
<i data-lucide="calendar" class="w-5 h-5 mr-2 text-yellow-400"></i>
|
||||
Événements
|
||||
</h3>
|
||||
<ul class="space-y-3">
|
||||
<li><a href="<%= events_path %>" class="text-gray-400 text-sm hover:text-yellow-400 transition-colors duration-300 flex items-center">
|
||||
<i data-lucide="glass-water" class="w-4 h-4 mr-2"></i>
|
||||
Afterworks
|
||||
</a></li>
|
||||
<li><a href="#" class="text-gray-400 text-sm hover:text-yellow-400 transition-colors duration-300 flex items-center">
|
||||
<i data-lucide="music" class="w-4 h-4 mr-2"></i>
|
||||
Concerts
|
||||
</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 class="font-bold text-lg text-white mb-4 flex items-center">
|
||||
<i data-lucide="help-circle" class="w-5 h-5 mr-2 text-yellow-400"></i>
|
||||
Support
|
||||
</h3>
|
||||
<ul class="space-y-3">
|
||||
<li><a href="#" class="text-gray-400 text-sm hover:text-yellow-400 transition-colors duration-300 flex items-center">
|
||||
<i data-lucide="life-buoy" class="w-4 h-4 mr-2"></i>
|
||||
Aide
|
||||
</a></li>
|
||||
<li><a href="#" class="text-gray-400 text-sm hover:text-yellow-400 transition-colors duration-300 flex items-center">
|
||||
<i data-lucide="mail" class="w-4 h-4 mr-2"></i>
|
||||
Nous contacter
|
||||
</a></li>
|
||||
<li><a href="#" class="text-gray-400 text-sm hover:text-yellow-400 transition-colors duration-300 flex items-center">
|
||||
<i data-lucide="flag" class="w-4 h-4 mr-2"></i>
|
||||
Signaler un contenu
|
||||
</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-t border-neutral-700 pt-4 text-center text-neutral-400 text-sm">
|
||||
<p>© 2025 Aperonight. All rights reserved. • <a href="#" class="text-accent-400 hover:text-accent-300 transition-colors">Privacy Policy</a> • <a href="#" class="text-accent-400 hover:text-accent-300 transition-colors">Terms of Service</a></p>
|
||||
|
||||
<div class="border-t border-gray-700 pt-6 text-center">
|
||||
<div class="flex flex-col sm:flex-row justify-between items-center">
|
||||
<p class="text-gray-400 text-sm mb-4 sm:mb-0">
|
||||
© 2025 Aperonight. Tous droits réservés.
|
||||
</p>
|
||||
<div class="flex space-x-6">
|
||||
<a href="#" class="text-gray-400 hover:text-yellow-400 transition-colors text-sm">
|
||||
Politique de confidentialité
|
||||
</a>
|
||||
<a href="#" class="text-gray-400 hover:text-yellow-400 transition-colors text-sm">
|
||||
Conditions d'utilisation
|
||||
</a>
|
||||
<a href="#" class="text-gray-400 hover:text-yellow-400 transition-colors text-sm">
|
||||
Mentions légales
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,22 +1,28 @@
|
||||
<header class="bg-neutral-800 border-b border-neutral-700">
|
||||
<header class="bg-white shadow-lg border-b border-gray-200 sticky top-0 z-50">
|
||||
<nav data-controller="header" class="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex items-center h-16 justify-between">
|
||||
<!-- Logo -->
|
||||
<div class="flex-shrink-0 flex items-center">
|
||||
<%= link_to Rails.application.config.app_name, current_user ? "/dashboard" : "/",
|
||||
class: "text-xl font-bold text-white" %>
|
||||
class: "text-2xl font-display font-bold text-gray-900 hover:text-brand-primary transition-colors" %>
|
||||
</div>
|
||||
|
||||
<!-- Desktop Navigation -->
|
||||
<div class="hidden sm:flex items-center space-x-6 w-full justify-start">
|
||||
<%= link_to "Afterworks", events_path,
|
||||
class: "mx-4 text-gray-100 hover:text-purple-200 py-2 rounded-md text-sm font-medium transition-colors duration-200" %>
|
||||
<div class="hidden sm:flex items-center space-x-8 w-full justify-center">
|
||||
<%= link_to events_path,
|
||||
class: "text-gray-700 hover:text-brand-primary py-2 text-sm font-medium transition-colors duration-200 relative after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-0 hover:after:w-full after:bg-brand-primary after:transition-all after:duration-200" do %>
|
||||
Événements
|
||||
<% end %>
|
||||
|
||||
<%= link_to "Évenements", "#",
|
||||
class: "mx-4 text-gray-100 hover:text-purple-200 py-2 rounded-md text-sm font-medium transition-colors duration-200" %>
|
||||
<%= link_to events_path,
|
||||
class: "text-gray-700 hover:text-brand-primary py-2 text-sm font-medium transition-colors duration-200 relative after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-0 hover:after:w-full after:bg-brand-primary after:transition-all after:duration-200" do %>
|
||||
Afterworks
|
||||
<% end %>
|
||||
|
||||
<%= link_to "Concerts", "#",
|
||||
class: "mx-4 text-gray-100 hover:text-purple-200 py-2 rounded-md text-sm font-medium transition-colors duration-200" %>
|
||||
<%= link_to "#",
|
||||
class: "text-gray-700 hover:text-brand-primary py-2 text-sm font-medium transition-colors duration-200 relative after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-0 hover:after:w-full after:bg-brand-primary after:transition-all after:duration-200" do %>
|
||||
Concerts
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<!-- Authentication -->
|
||||
@@ -24,84 +30,116 @@
|
||||
<% if user_signed_in? %>
|
||||
<div class="relative" data-header-target="userMenuButton">
|
||||
<button data-action="click->header#toggleUserMenu"
|
||||
class="bg-purple-700 text-white border border-purple-800 font-medium py-2 px-4 rounded-lg hover:bg-purple-800 transition-colors duration-200 flex items-center space-x-2">
|
||||
class="bg-gray-900 text-white font-medium py-2 px-4 rounded-full hover:bg-gray-800 transition-colors duration-200 flex items-center space-x-2">
|
||||
<span><%= current_user.email.length > 20 ? current_user.email[0,20] + "..." : current_user.email %></span>
|
||||
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
<i data-lucide="chevron-down" class="w-4 h-4"></i>
|
||||
</button>
|
||||
|
||||
<!-- User Dropdown Menu -->
|
||||
<div data-header-target="userMenu" class="hidden absolute right-0 mt-2 w-56 bg-white rounded-lg shadow-lg border border-gray-200 py-1 z-50">
|
||||
<div class="px-4 py-2 text-sm text-gray-900 border-b border-gray-100">
|
||||
<div class="font-medium"><%= current_user.first_name || current_user.email %></div>
|
||||
<div data-header-target="userMenu" class="hidden absolute right-0 mt-2 w-56 bg-white rounded-2xl shadow-xl border border-gray-100 py-2 z-50">
|
||||
<div class="px-4 py-3 text-sm text-gray-900 border-b border-gray-100">
|
||||
<div class="font-semibold"><%= current_user.first_name || current_user.email %></div>
|
||||
<div class="text-gray-500"><%= current_user.email %></div>
|
||||
</div>
|
||||
<%= link_to "Reservations", "#",
|
||||
class: "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors duration-200" %>
|
||||
<%= link_to "#",
|
||||
class: "flex items-center px-4 py-3 text-sm text-gray-700 hover:bg-gray-50 transition-colors duration-200" do %>
|
||||
<i data-lucide="calendar" class="w-4 h-4 mr-3"></i>
|
||||
Réservations
|
||||
<% end %>
|
||||
<%= link_to edit_user_registration_path,
|
||||
class: "flex items-center px-4 py-3 text-sm text-gray-700 hover:bg-gray-50 transition-colors duration-200" do %>
|
||||
<i data-lucide="settings" class="w-4 h-4 mr-3"></i>
|
||||
Sécurité
|
||||
<% end %>
|
||||
<div class="border-t border-gray-100">
|
||||
<%= link_to "Sécurité", edit_user_registration_path,
|
||||
class: "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors duration-200" %>
|
||||
</div>
|
||||
<div class="border-t border-gray-100">
|
||||
<%= link_to "Sign out", destroy_user_session_path,
|
||||
<%= link_to destroy_user_session_path,
|
||||
data: { controller: "logout", action: "click->logout#signOut", logout_url_value: destroy_user_session_path, login_url_value: new_user_session_path, turbo: false },
|
||||
class: "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors duration-200" %>
|
||||
class: "flex items-center px-4 py-3 text-sm text-gray-700 hover:bg-gray-50 transition-colors duration-200" do %>
|
||||
<i data-lucide="log-out" class="w-4 h-4 mr-3"></i>
|
||||
Déconnexion
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= link_to t("header.login"), new_user_session_path,
|
||||
class: "text-gray-100 hover:text-purple-200 px-3 py-2 rounded-md text-sm font-medium transition-colors duration-200" %>
|
||||
<%= link_to t("header.register"), new_user_registration_path,
|
||||
class: "bg-purple-600 text-white font-medium py-2 px-4 rounded-lg hover:bg-purple-700 transition-colors duration-200" %>
|
||||
<%= link_to new_user_session_path,
|
||||
class: "text-gray-700 hover:text-brand-primary px-4 py-2 rounded-full text-sm font-medium transition-colors duration-200" do %>
|
||||
Se connecter
|
||||
<% end %>
|
||||
<%= link_to new_user_registration_path,
|
||||
class: "bg-gray-900 text-white font-semibold py-2 px-6 rounded-full hover:bg-gray-800 transition-colors duration-200 shadow-lg hover:shadow-xl" do %>
|
||||
S'inscrire
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<!-- Mobile menu button -->
|
||||
<div class="flex-shrink-0 sm:hidden">
|
||||
<button data-action="click->header#toggleMobileMenu" data-header-target="mobileMenuButton" class="p-2 rounded-md text-neutral-300 hover:text-white hover:bg-purple-700">
|
||||
<svg data-menu-icon="open" class="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
</svg>
|
||||
<svg data-menu-icon="close" class="h-6 w-6 hidden" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
<button data-action="click->header#toggleMobileMenu" data-header-target="mobileMenuButton" class="p-2 rounded-lg text-gray-600 hover:text-gray-900 hover:bg-gray-100">
|
||||
<i data-menu-icon="open" data-lucide="menu" class="w-6 h-6"></i>
|
||||
<i data-menu-icon="close" data-lucide="x" class="w-6 h-6 hidden"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Menu -->
|
||||
<div data-header-target="mobileMenu" class="hidden sm:hidden">
|
||||
<div class="px-2 pt-2 pb-3 space-y-1">
|
||||
<%= link_to t("header.parties"), events_path,
|
||||
class: "block px-3 py-2 rounded-md text-base font-medium text-gray-100 hover:text-purple-200 hover:bg-purple-700" %>
|
||||
<%= link_to t("header.concerts"), "#",
|
||||
class: "block px-3 py-2 rounded-md text-base font-medium text-gray-100 hover:text-purple-200 hover:bg-purple-700" %>
|
||||
<div data-header-target="mobileMenu" class="hidden sm:hidden border-t border-gray-200">
|
||||
<div class="px-4 pt-4 pb-3 space-y-2">
|
||||
<%= link_to events_path,
|
||||
class: "flex items-center px-3 py-2 rounded-lg text-base font-medium text-gray-700 hover:text-brand-primary hover:bg-gray-50" do %>
|
||||
<i data-lucide="calendar" class="w-4 h-4 mr-3"></i>
|
||||
Événements
|
||||
<% end %>
|
||||
<%= link_to events_path,
|
||||
class: "flex items-center px-3 py-2 rounded-lg text-base font-medium text-gray-700 hover:text-brand-primary hover:bg-gray-50" do %>
|
||||
<i data-lucide="glass-water" class="w-4 h-4 mr-3"></i>
|
||||
Afterworks
|
||||
<% end %>
|
||||
<%= link_to "#",
|
||||
class: "flex items-center px-3 py-2 rounded-lg text-base font-medium text-gray-700 hover:text-brand-primary hover:bg-gray-50" do %>
|
||||
<i data-lucide="music" class="w-4 h-4 mr-3"></i>
|
||||
Concerts
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="pt-4 pb-3 border-t border-gray-700">
|
||||
<div class="pt-4 pb-4 border-t border-gray-200">
|
||||
<% if user_signed_in? %>
|
||||
<div class="px-4 mb-3">
|
||||
<div class="text-base font-medium text-white">
|
||||
<div class="text-base font-semibold text-gray-900">
|
||||
<%= current_user.first_name || current_user.email %>
|
||||
</div>
|
||||
<div class="text-sm text-gray-500"><%= current_user.email %></div>
|
||||
</div>
|
||||
<div class="px-2 space-y-1">
|
||||
<%= link_to "Réservations", "#",
|
||||
class: "block px-3 py-2 rounded-md text-base font-medium text-gray-100 hover:text-purple-200 hover:bg-purple-700" %>
|
||||
<%= link_to "Sécurité", edit_user_registration_path,
|
||||
class: "block px-3 py-2 rounded-md text-base font-medium text-gray-100 hover:text-purple-200 hover:bg-purple-700" %>
|
||||
<%= link_to "Déconnexion", destroy_user_session_path,
|
||||
<div class="px-4 space-y-2">
|
||||
<%= link_to "#",
|
||||
class: "flex items-center px-3 py-2 rounded-lg text-base font-medium text-gray-700 hover:text-brand-primary hover:bg-gray-50" do %>
|
||||
<i data-lucide="calendar" class="w-4 h-4 mr-3"></i>
|
||||
Réservations
|
||||
<% end %>
|
||||
<%= link_to edit_user_registration_path,
|
||||
class: "flex items-center px-3 py-2 rounded-lg text-base font-medium text-gray-700 hover:text-brand-primary hover:bg-gray-50" do %>
|
||||
<i data-lucide="settings" class="w-4 h-4 mr-3"></i>
|
||||
Sécurité
|
||||
<% end %>
|
||||
<%= link_to destroy_user_session_path,
|
||||
data: { controller: "logout", action: "click->logout#signOut", logout_url_value: destroy_user_session_path, login_url_value: new_user_session_path, turbo: false },
|
||||
class: "block px-3 py-2 rounded-md text-base font-medium text-gray-100 hover:text-purple-200 hover:bg-purple-700" %>
|
||||
class: "flex items-center px-3 py-2 rounded-lg text-base font-medium text-gray-700 hover:text-brand-primary hover:bg-gray-50" do %>
|
||||
<i data-lucide="log-out" class="w-4 h-4 mr-3"></i>
|
||||
Déconnexion
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="px-2 space-y-1">
|
||||
<%= link_to t("header.login"), new_user_session_path,
|
||||
class: "block px-3 py-2 rounded-md text-base font-medium text-gray-100 hover:text-purple-200 hover:bg-purple-700" %>
|
||||
<%= link_to t("header.register"), new_user_registration_path,
|
||||
class: "block px-3 py-2 rounded-md text-base font-medium bg-purple-600 text-white hover:bg-purple-700" %>
|
||||
<div class="px-4 space-y-2">
|
||||
<%= link_to new_user_session_path,
|
||||
class: "flex items-center justify-center px-3 py-2 rounded-lg text-base font-medium text-gray-700 hover:text-brand-primary hover:bg-gray-50" do %>
|
||||
<i data-lucide="log-in" class="w-4 h-4 mr-3"></i>
|
||||
Se connecter
|
||||
<% end %>
|
||||
<%= link_to new_user_registration_path,
|
||||
class: "flex items-center justify-center px-3 py-2 rounded-lg text-base font-semibold bg-gray-900 text-white hover:bg-gray-800" do %>
|
||||
<i data-lucide="user-plus" class="w-4 h-4 mr-3"></i>
|
||||
S'inscrire
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -16,16 +16,12 @@
|
||||
<div class="<%= 'order-2 sm:order-1' unless sold_out %>">
|
||||
<% if sold_out %>
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800">
|
||||
<svg class="-ml-0.5 mr-1 h-2 w-2 text-red-400" fill="currentColor" viewBox="0 0 8 8">
|
||||
<circle cx="4" cy="4" r="3" />
|
||||
</svg>
|
||||
<i data-lucide="x" class="w-2 h-2 mr-1 text-red-400"></i>
|
||||
Épuisé
|
||||
</span>
|
||||
<% else %>
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
|
||||
<svg class="-ml-0.5 mr-1 h-2 w-2 text-green-400" fill="currentColor" viewBox="0 0 8 8">
|
||||
<circle cx="4" cy="4" r="3" />
|
||||
</svg>
|
||||
<i data-lucide="check-circle" class="w-2 h-2 mr-1 text-green-400"></i>
|
||||
<%= remaining %> disponibles
|
||||
</span>
|
||||
<% end %>
|
||||
@@ -59,9 +55,7 @@
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="text-sm text-gray-500 font-medium order-1 sm:order-2">
|
||||
<svg class="w-5 h-5 inline-block mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<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"></path>
|
||||
</svg>
|
||||
<i data-lucide="lock" class="w-5 h-5 inline-block mr-1"></i>
|
||||
Indisponible
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -1,34 +1,52 @@
|
||||
<div class="flex items-center justify-center bg-neutral-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="min-h-screen max-w-md w-full space-y-8">
|
||||
<div>
|
||||
<div class="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="max-w-md w-full space-y-8">
|
||||
<!-- Header -->
|
||||
<div class="text-center">
|
||||
<%= link_to "/" do %>
|
||||
<img class="mx-auto h-12 w-auto" src="/icon.svg" alt="Aperonight" />
|
||||
<div class="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-br from-purple-600 to-blue-600 rounded-2xl mb-6">
|
||||
<i data-lucide="calendar" class="w-8 h-8 text-white"></i>
|
||||
</div>
|
||||
<% end %>
|
||||
<h2 class="mt-6 text-center text-3xl font-extrabold text-neutral-900">
|
||||
<%= t('devise.confirmations.new.title') %>
|
||||
</h2>
|
||||
<p class="mt-2 text-center text-sm text-neutral-600">
|
||||
<h2 class="text-3xl font-bold text-gray-900"><%= t('devise.confirmations.new.title') %></h2>
|
||||
<p class="mt-2 text-gray-600">
|
||||
<%= t('devise.confirmations.new.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post, class: "mt-8 space-y-6" }) do |f| %>
|
||||
|
||||
<!-- Form -->
|
||||
<div class="bg-white py-8 px-6 shadow-xl rounded-2xl">
|
||||
<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post, class: "space-y-6" }) do |f| %>
|
||||
<div class="space-y-5">
|
||||
<div>
|
||||
<%= f.label :email, class: "block text-sm font-medium text-neutral-700" %>
|
||||
<div class="mt-1">
|
||||
<%= f.label :email, class: "block text-sm font-semibold text-gray-700 mb-2" %>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<i data-lucide="mail" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
<%= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email),
|
||||
class: "appearance-none block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm",
|
||||
placeholder: "Email" %>
|
||||
placeholder: "votre@email.com",
|
||||
class: "block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-colors" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= f.submit t('devise.confirmations.new.submit'),
|
||||
class: "group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-neutral-50 focus:ring-purple-500" %>
|
||||
<div class="pt-4">
|
||||
<%= f.button type: "submit", class: "group relative w-full flex justify-center items-center py-3 px-4 border border-transparent text-sm font-semibold rounded-xl text-white bg-gray-900 hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 transition-all duration-200 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5" do %>
|
||||
<i data-lucide="send" class="w-4 h-4 mr-2"></i>
|
||||
<%= t('devise.confirmations.new.submit') %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render "devise/shared/links" %>
|
||||
<!-- Additional Links -->
|
||||
<div class="mt-6 pt-6 border-t border-gray-200">
|
||||
<div class="text-center">
|
||||
<p class="text-sm text-gray-600">
|
||||
Vous vous souvenez de votre mot de passe ?
|
||||
<a href="<%= new_user_session_path %>" class="font-semibold text-purple-600 hover:text-purple-500 transition-colors">Se connecter</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,43 +1,69 @@
|
||||
<div class="flex items-center justify-center bg-neutral-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="min-h-screen max-w-md w-full space-y-8">
|
||||
<div>
|
||||
<div class="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="max-w-md w-full space-y-8">
|
||||
<!-- Header -->
|
||||
<div class="text-center">
|
||||
<%= link_to "/" do %>
|
||||
<img class="mx-auto h-12 w-auto" src="/icon.svg" alt="Aperonight" />
|
||||
<div class="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-br from-purple-600 to-blue-600 rounded-2xl mb-6">
|
||||
<i data-lucide="calendar" class="w-8 h-8 text-white"></i>
|
||||
</div>
|
||||
<% end %>
|
||||
<h2 class="mt-6 text-center text-3xl font-extrabold text-neutral-900">
|
||||
<%= t('devise.passwords.edit.title') %>
|
||||
</h2>
|
||||
<p class="mt-2 text-center text-sm text-neutral-600">
|
||||
<h2 class="text-3xl font-bold text-gray-900"><%= t('devise.passwords.edit.title') %></h2>
|
||||
<p class="mt-2 text-gray-600">
|
||||
<%= t('devise.passwords.edit.description') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put, class: "mt-8 space-y-6" }) do |f| %>
|
||||
<!-- Form -->
|
||||
<div class="bg-white py-8 px-6 shadow-xl rounded-2xl">
|
||||
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put, class: "space-y-6" }) do |f| %>
|
||||
<%= f.hidden_field :reset_password_token %>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="space-y-5">
|
||||
<div>
|
||||
<%= f.label :password, t('devise.passwords.edit.new_password'), class: "block text-sm font-medium text-neutral-700" %>
|
||||
<%= f.label :password, t('devise.passwords.edit.new_password'), class: "block text-sm font-semibold text-gray-700 mb-2" %>
|
||||
<% if @minimum_password_length %>
|
||||
<em class="text-sm text-neutral-500">(<%= t('devise.registrations.new.minimum_password_length', count: @minimum_password_length) %>)</em>
|
||||
<p class="text-xs text-gray-500 mb-2">(<%= t('devise.registrations.new.minimum_password_length', count: @minimum_password_length) %>)</p>
|
||||
<% end %>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<i data-lucide="lock" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
<%= f.password_field :password, autofocus: true, autocomplete: "new-password",
|
||||
class: "mt-1 block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm" %>
|
||||
placeholder: "Votre nouveau mot de passe",
|
||||
class: "block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-colors" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= f.label :password_confirmation, t('devise.passwords.edit.confirm_new_password'), class: "block text-sm font-medium text-neutral-700" %>
|
||||
<%= f.label :password_confirmation, t('devise.passwords.edit.confirm_new_password'), class: "block text-sm font-semibold text-gray-700 mb-2" %>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<i data-lucide="lock" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
<%= f.password_field :password_confirmation, autocomplete: "new-password",
|
||||
class: "mt-1 block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm" %>
|
||||
placeholder: "Confirmez votre nouveau mot de passe",
|
||||
class: "block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-colors" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<%= f.submit t('devise.passwords.edit.submit'),
|
||||
class: "group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-neutral-50 focus:ring-purple-500" %>
|
||||
<div class="pt-4">
|
||||
<%= f.button type: "submit", class: "group relative w-full flex justify-center items-center py-3 px-4 border border-transparent text-sm font-semibold rounded-xl text-white bg-gray-900 hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 transition-all duration-200 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5" do %>
|
||||
<i data-lucide="refresh-ccw" class="w-4 h-4 mr-2"></i>
|
||||
<%= t('devise.passwords.edit.submit') %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render "devise/shared/links" %>
|
||||
<!-- Additional Links -->
|
||||
<div class="mt-6 pt-6 border-t border-gray-200">
|
||||
<div class="text-center">
|
||||
<p class="text-sm text-gray-600">
|
||||
Vous vous souvenez de votre mot de passe ?
|
||||
<a href="<%= new_user_session_path %>" class="font-semibold text-purple-600 hover:text-purple-500 transition-colors">Se connecter</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,45 +1,51 @@
|
||||
<div class="flex items-center justify-center bg-neutral-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="min-h-screen max-w-md w-full space-y-8">
|
||||
<div>
|
||||
<div class="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="max-w-md w-full space-y-8">
|
||||
<!-- Header -->
|
||||
<div class="text-center">
|
||||
<%= link_to "/" do %>
|
||||
<img class="mx-auto h-12 w-auto" src="/icon.svg" alt="Aperonight" />
|
||||
<div class="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-br from-purple-600 to-blue-600 rounded-2xl mb-6">
|
||||
<i data-lucide="calendar" class="w-8 h-8 text-white"></i>
|
||||
</div>
|
||||
<% end %>
|
||||
<h2 class="mt-6 text-center text-3xl font-extrabold text-neutral-900">
|
||||
Mot de passe oublié ?
|
||||
</h2>
|
||||
<p class="mt-2 text-center text-sm text-neutral-600">
|
||||
<h2 class="text-3xl font-bold text-gray-900">Mot de passe oublié ?</h2>
|
||||
<p class="mt-2 text-gray-600">
|
||||
Entrez votre adresse email ci-dessous et nous vous enverrons un lien pour réinitialiser votre mot de passe.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post, class: "mt-8 space-y-6" }) do |f| %>
|
||||
|
||||
<!-- Form -->
|
||||
<div class="bg-white py-8 px-6 shadow-xl rounded-2xl">
|
||||
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post, class: "space-y-6" }) do |f| %>
|
||||
<div class="space-y-5">
|
||||
<div>
|
||||
<%= f.label :email, "Adresse Email", class: "block text-sm font-medium text-neutral-700" %>
|
||||
<div class="mt-1">
|
||||
<%= f.label :email, "Adresse email", class: "block text-sm font-semibold text-gray-700 mb-2" %>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<i data-lucide="mail" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
<%= f.email_field :email, autofocus: true, autocomplete: "email",
|
||||
class: "appearance-none block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm",
|
||||
placeholder: t('devise.passwords.new.email_placeholder') %>
|
||||
placeholder: "votre@email.com",
|
||||
class: "block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-colors" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= f.submit "Envoyer le lien de réinitialisation",
|
||||
class: "group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-neutral-50 focus:ring-purple-500" %>
|
||||
<div class="pt-4">
|
||||
<%= f.button type: "submit", class: "group relative w-full flex justify-center items-center py-3 px-4 border border-transparent text-sm font-semibold rounded-xl text-white bg-gray-900 hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 transition-all duration-200 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5" do %>
|
||||
<i data-lucide="send" class="w-4 h-4 mr-2"></i>
|
||||
Envoyer le lien de réinitialisation
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="mt-6">
|
||||
<div class="relative">
|
||||
<div class="absolute inset-0 flex items-center">
|
||||
<div class="w-full border-t border-neutral-300"></div>
|
||||
<!-- Additional Links -->
|
||||
<div class="mt-6 pt-6 border-t border-gray-200">
|
||||
<div class="text-center">
|
||||
<p class="text-sm text-gray-600">
|
||||
Vous vous souvenez de votre mot de passe ?
|
||||
<a href="<%= new_user_session_path %>" class="font-semibold text-purple-600 hover:text-purple-500 transition-colors">Se connecter</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="relative flex justify-center text-sm">
|
||||
<span class="px-2 bg-neutral-50 text-neutral-600">Continuer avec</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render "devise/shared/links" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,68 +1,120 @@
|
||||
<div class="min-h-screen flex items-center justify-center bg-neutral-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="max-w-2xl w-full space-y-8">
|
||||
<div>
|
||||
<div class="min-h-screen bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="max-w-2xl mx-auto space-y-8">
|
||||
<!-- Header -->
|
||||
<div class="text-center">
|
||||
<%= link_to "/" do %>
|
||||
<img class="mx-auto h-12 w-auto" src="/icon.svg" alt="Aperonight" />
|
||||
<div class="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-br from-purple-600 to-blue-600 rounded-2xl mb-6 mx-auto">
|
||||
<i data-lucide="calendar" class="w-8 h-8 text-white"></i>
|
||||
</div>
|
||||
<% end %>
|
||||
<h2 class="mt-6 text-center text-3xl font-extrabold text-neutral-900">
|
||||
Modifier votre compte
|
||||
</h2>
|
||||
<p class="mt-2 text-center text-sm text-neutral-600">
|
||||
<h2 class="text-3xl font-bold text-gray-900">Modifier votre compte</h2>
|
||||
<p class="mt-2 text-gray-600">
|
||||
Gérez vos informations et préférences
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, class: "mt-8 space-y-6" }) do |f| %>
|
||||
<!-- Profile Form -->
|
||||
<div class="bg-white py-8 px-6 shadow-xl rounded-2xl">
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-6">Informations du compte</h3>
|
||||
|
||||
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, class: "space-y-6" }) do |f| %>
|
||||
<%= render "devise/shared/error_messages", resource: resource %>
|
||||
|
||||
<div class="space-y-6">
|
||||
<div class="space-y-5">
|
||||
<div>
|
||||
<%= f.label :email, class: "block text-sm font-medium text-neutral-700" %>
|
||||
<%= f.label :email, class: "block text-sm font-semibold text-gray-700 mb-2" %>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<i data-lucide="mail" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
<%= f.email_field :email, autofocus: true, autocomplete: "email",
|
||||
class: "mt-1 block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm" %>
|
||||
class: "block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-colors" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
|
||||
<div class="text-sm text-neutral-600">
|
||||
<div class="text-sm text-gray-600 bg-yellow-50 border border-yellow-200 rounded-lg p-4">
|
||||
<i data-lucide="alert-circle" class="w-5 h-5 text-yellow-500 inline mr-2"></i>
|
||||
En attente de confirmation pour : <%= resource.unconfirmed_email %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<%= f.label :password, "Nouveau mot de passe", class: "block text-sm font-medium text-neutral-700" %>
|
||||
<%= f.label :password, "Nouveau mot de passe", class: "block text-sm font-semibold text-gray-700 mb-2" %>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<i data-lucide="lock" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
<%= f.password_field :password, autocomplete: "new-password",
|
||||
class: "mt-1 block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm" %>
|
||||
placeholder: "Laisser vide si vous ne souhaitez pas le changer",
|
||||
class: "block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-colors" %>
|
||||
</div>
|
||||
<% if @minimum_password_length %>
|
||||
<p class="mt-2 text-sm text-gray-500"><%= t('devise.registrations.new.minimum_password_length', count: @minimum_password_length) %></p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= f.label :password_confirmation, "Confirmer le nouveau mot de passe", class: "block text-sm font-medium text-neutral-700" %>
|
||||
<%= f.label :password_confirmation, "Confirmer le nouveau mot de passe", class: "block text-sm font-semibold text-gray-700 mb-2" %>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<i data-lucide="lock" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
<%= f.password_field :password_confirmation, autocomplete: "new-password",
|
||||
class: "mt-1 block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm" %>
|
||||
placeholder: "Confirmez votre nouveau mot de passe",
|
||||
class: "block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-colors" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= f.label :current_password, "Mot de passe actuel", class: "block text-sm font-medium text-neutral-700" %>
|
||||
<%= f.label :current_password, "Mot de passe actuel", class: "block text-sm font-semibold text-gray-700 mb-2" %>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<i data-lucide="key" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
<%= f.password_field :current_password, autocomplete: "current-password",
|
||||
class: "mt-1 block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-400 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm" %>
|
||||
placeholder: "Requis pour confirmer vos changements",
|
||||
class: "block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-colors" %>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-gray-500">Requis pour confirmer vos changements</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<%= f.submit "Mettre à jour",
|
||||
class: "group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-neutral-50 focus:ring-purple-500" %>
|
||||
<div class="pt-4">
|
||||
<%= f.button type: "submit", class: "group relative w-full flex justify-center items-center py-3 px-4 border border-transparent text-sm font-semibold rounded-xl text-white bg-gray-900 hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 transition-all duration-200 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5" do %>
|
||||
<i data-lucide="save" class="w-4 h-4 mr-2"></i>
|
||||
Mettre à jour
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<h3 class="text-center text-lg font-medium text-neutral-900"><%= t('devise.registrations.edit.delete_account') %></h3>
|
||||
<div class="text-center">
|
||||
<p class="text-sm text-neutral-600">
|
||||
<%= t('devise.registrations.edit.unhappy') %> <%= button_to t('devise.registrations.edit.delete_account'), registration_path(resource_name),
|
||||
data: { confirm: t('devise.registrations.edit.confirm_delete'), turbo_confirm: t('devise.registrations.edit.confirm_delete') },
|
||||
method: :delete,
|
||||
class: "font-medium text-red-600 hover:text-red-500" %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<%= link_to t('devise.registrations.edit.back'), :back, class: "text-center block text-purple-600 hover:text-purple-500" %>
|
||||
<!-- Delete Account Section -->
|
||||
<div class="bg-white py-8 px-6 shadow-xl rounded-2xl">
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-4">Supprimer mon compte</h3>
|
||||
<p class="text-gray-600 mb-6">
|
||||
<%= t('devise.registrations.edit.unhappy') %> Cette action est irréversible.
|
||||
</p>
|
||||
<%= button_to registration_path(resource_name),
|
||||
data: {
|
||||
confirm: t('devise.registrations.edit.confirm_delete'),
|
||||
turbo_confirm: t('devise.registrations.edit.confirm_delete')
|
||||
},
|
||||
method: :delete,
|
||||
class: "group relative w-full flex justify-center items-center py-3 px-4 border border-red-300 text-sm font-semibold rounded-xl text-red-700 bg-red-50 hover:bg-red-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 transition-all duration-200" do %>
|
||||
<i data-lucide="trash-2" class="w-4 h-4 mr-2"></i>
|
||||
<%= t('devise.registrations.edit.delete_account') %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<!-- Back Link -->
|
||||
<div class="text-center">
|
||||
<%= link_to :back, class: "inline-flex items-center text-purple-600 hover:text-purple-500 transition-colors" do %>
|
||||
<i data-lucide="arrow-left" class="w-4 h-4 mr-2"></i>
|
||||
<%= t('devise.registrations.edit.back') %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,58 +1,91 @@
|
||||
<div class="flex items-center justify-center bg-neutral-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="min-h-screen max-w-md w-full space-y-8">
|
||||
<div>
|
||||
<div class="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="max-w-md w-full space-y-8">
|
||||
<!-- Header -->
|
||||
<div class="text-center">
|
||||
<%= link_to "/" do %>
|
||||
<img class="mx-auto h-12 w-auto" src="/icon.svg" alt="Aperonight" />
|
||||
<div class="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-br from-purple-600 to-blue-600 rounded-2xl mb-6">
|
||||
<i data-lucide="calendar" class="w-8 h-8 text-white"></i>
|
||||
</div>
|
||||
<% end %>
|
||||
<h2 class="mt-6 text-center text-3xl font-extrabold text-neutral-900">Créer un compte</h2>
|
||||
<p class="mt-2 text-center text-sm text-neutral-600">
|
||||
ou <a href="<%= new_user_session_path %>" class="font-medium text-purple-600 hover:text-purple-500">se connecter à votre compte</a>
|
||||
<h2 class="text-3xl font-bold text-gray-900">Créer un compte</h2>
|
||||
<p class="mt-2 text-gray-600">
|
||||
ou <a href="<%= new_user_session_path %>" class="font-semibold text-purple-600 hover:text-purple-500 transition-colors">se connecter à votre compte existant</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { class: "mt-8 space-y-6" }) do |f| %>
|
||||
<!-- Form -->
|
||||
<div class="bg-white py-8 px-6 shadow-xl rounded-2xl">
|
||||
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { class: "space-y-6" }) do |f| %>
|
||||
<%= render "devise/shared/error_messages", resource: resource %>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="space-y-5">
|
||||
<div>
|
||||
<%= f.label :email, "Adresse email", class: "block text-sm font-medium text-neutral-700" %>
|
||||
<%= f.email_field :email, autofocus: true, autocomplete: "email",
|
||||
class: "mt-1 block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-500 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm" %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= f.label :password, "Mot de passe", class: "block text-sm font-medium text-neutral-700" %>
|
||||
<% if @minimum_password_length %>
|
||||
<em class="text-sm text-neutral-500">(<%= t('devise.registrations.new.minimum_password_length', count: @minimum_password_length) %>)</em>
|
||||
<% end %>
|
||||
<%= f.password_field :password, autocomplete: "new-password",
|
||||
class: "mt-1 block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-500 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm" %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= f.label :password_confirmation, "Confirmation du mot de passe", class: "block text-sm font-medium text-neutral-700" %>
|
||||
<%= f.password_field :password_confirmation, autocomplete: "new-password",
|
||||
class: "mt-1 block w-full px-3 py-2 border border-neutral-300 rounded-md shadow-sm placeholder-neutral-500 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="acthons">
|
||||
<%= f.submit "Créer un compte", class: "group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-neutral-50 focus:ring-purple-500" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="mt-6">
|
||||
<%= f.label :email, "Adresse email", class: "block text-sm font-semibold text-gray-700 mb-2" %>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-0 flex items-center">
|
||||
<div class="w-full border-t border-neutral-300"></div>
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<i data-lucide="mail" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
<div class="relative flex justify-center text-sm">
|
||||
<span class="px-2 bg-neutral-50 text-neutral-600">Continuer avec</span>
|
||||
<%= f.email_field :email, autofocus: true, autocomplete: "email",
|
||||
placeholder: "votre@email.com",
|
||||
class: "block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-colors" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<%= render "devise/shared/links" %>
|
||||
<div>
|
||||
<%= f.label :password, "Mot de passe", class: "block text-sm font-semibold text-gray-700 mb-2" %>
|
||||
<% if @minimum_password_length %>
|
||||
<p class="text-xs text-gray-500 mb-2"><%= t('devise.registrations.new.minimum_password_length', count: @minimum_password_length) %></p>
|
||||
<% end %>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<i data-lucide="lock" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
<%= f.password_field :password, autocomplete: "new-password",
|
||||
placeholder: "Votre mot de passe",
|
||||
class: "block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-colors" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= f.label :password_confirmation, "Confirmation du mot de passe", class: "block text-sm font-semibold text-gray-700 mb-2" %>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<i data-lucide="lock" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
<%= f.password_field :password_confirmation, autocomplete: "new-password",
|
||||
placeholder: "Confirmez votre mot de passe",
|
||||
class: "block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-colors" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pt-4">
|
||||
<%= f.button type: "submit", class: "group relative w-full flex justify-center items-center py-3 px-4 border border-transparent text-sm font-semibold rounded-xl text-white bg-gray-900 hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 transition-all duration-200 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5" do %>
|
||||
<i data-lucide="user-plus" class="w-4 h-4 mr-2"></i>
|
||||
Créer un compte
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<!-- Additional Links -->
|
||||
<div class="mt-6 pt-6 border-t border-gray-200">
|
||||
<div class="text-center">
|
||||
<p class="text-sm text-gray-600">
|
||||
Vous avez déjà un compte?
|
||||
<a href="<%= new_user_session_path %>" class="font-semibold text-purple-600 hover:text-purple-500 transition-colors">Se connecter</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="text-center">
|
||||
<p class="text-xs text-gray-500">
|
||||
En créant un compte, vous acceptez nos
|
||||
<a href="#" class="text-purple-600 hover:text-purple-500">conditions d'utilisation</a>
|
||||
et notre
|
||||
<a href="#" class="text-purple-600 hover:text-purple-500">politique de confidentialité</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,64 +1,74 @@
|
||||
<div class="flex items-center justify-center bg-neutral-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="min-h-screen max-w-md w-full space-y-8">
|
||||
<div>
|
||||
<div class="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="max-w-md w-full space-y-8">
|
||||
<!-- Header -->
|
||||
<div class="text-center">
|
||||
<%= link_to "/" do %>
|
||||
<img class="mx-auto h-12 w-auto" src="/icon.svg" alt="Aperonight" />
|
||||
<div class="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-br from-purple-600 to-blue-600 rounded-2xl mb-6">
|
||||
<i data-lucide="calendar" class="w-8 h-8 text-white"></i>
|
||||
</div>
|
||||
<% end %>
|
||||
<h2 class="mt-6 text-center text-3xl font-extrabold text-neutral-900">
|
||||
Se connecter à votre compte
|
||||
</h2>
|
||||
<p class="mt-2 text-center text-sm text-neutral-600">
|
||||
ou
|
||||
<a href="<%= new_user_registration_path %>" class="font-medium text-purple-600 hover:text-purple-500">
|
||||
créer un compte
|
||||
</a>
|
||||
<h2 class="text-3xl font-bold text-gray-900">Connexion à votre compte</h2>
|
||||
<p class="mt-2 text-gray-600">
|
||||
ou <a href="<%= new_user_registration_path %>" class="font-semibold text-purple-600 hover:text-purple-500 transition-colors">créer un compte</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<%= form_for(resource, as: resource_name, url: session_path(resource_name), html: { class: "mt-8 space-y-6" }) do |f| %>
|
||||
|
||||
<div class="rounded-md shadow-sm -space-y-px">
|
||||
<div class="field">
|
||||
<%= f.label :email, "Email", class: "sr-only" %>
|
||||
<!-- Form -->
|
||||
<div class="bg-white py-8 px-6 shadow-xl rounded-2xl">
|
||||
<%= form_for(resource, as: resource_name, url: session_path(resource_name), html: { class: "space-y-6" }) do |f| %>
|
||||
<div class="space-y-5">
|
||||
<div>
|
||||
<%= f.label :email, "Adresse email", class: "block text-sm font-semibold text-gray-700 mb-2" %>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<i data-lucide="mail" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
<%= f.email_field :email, autofocus: true, autocomplete: "email",
|
||||
class: "appearance-none rounded-none relative block w-full px-3 py-2 border border-neutral-300 placeholder-neutral-500 text-neutral-900 bg-white rounded-t-md focus:outline-none focus:ring-purple-500 focus:border-purple-500 focus:z-10 sm:text-sm",
|
||||
placeholder: "Adresse email" %>
|
||||
placeholder: "votre@email.com",
|
||||
class: "block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-colors" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<%= f.label :password, "Mot de passe", class: "sr-only" %>
|
||||
<div>
|
||||
<%= f.label :password, "Mot de passe", class: "block text-sm font-semibold text-gray-700 mb-2" %>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<i data-lucide="lock" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
<%= f.password_field :password, autocomplete: "current-password",
|
||||
class: "appearance-none rounded-none relative block w-full px-3 py-2 border border-neutral-300 placeholder-neutral-500 text-neutral-900 bg-white rounded-b-md focus:outline-none focus:ring-purple-500 focus:border-purple-500 focus:z-10 sm:text-sm",
|
||||
placeholder: "Mot de passe" %>
|
||||
placeholder: "Votre mot de passe",
|
||||
class: "block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-colors" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if devise_mapping.rememberable? %>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
<%= f.check_box :remember_me, class: "h-4 w-4 text-purple-600 focus:ring-purple-500 border-neutral-300 rounded bg-white" %>
|
||||
<label for="user_remember_me" class="ml-2 block text-sm text-neutral-700"> Se souvenir de moi </label>
|
||||
</div>
|
||||
|
||||
<%= f.check_box :remember_me, class: "h-4 w-4 text-purple-600 focus:ring-purple-500 border-gray-300 rounded bg-white" %>
|
||||
<%= f.label :remember_me, "Se souvenir de moi", class: "ml-2 block text-sm text-gray-700" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="actions">
|
||||
<%= f.submit "Se connecter", class: "group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-neutral-50 focus:ring-purple-500" %>
|
||||
<div class="pt-4">
|
||||
<%= f.button type: "submit", class: "group relative w-full flex justify-center items-center py-3 px-4 border border-transparent text-sm font-semibold rounded-xl text-white bg-gray-900 hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 transition-all duration-200 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5" do %>
|
||||
<i data-lucide="log-in" class="w-4 h-4 mr-2"></i>
|
||||
Se connecter
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="mt-6">
|
||||
<div class="relative">
|
||||
<div class="absolute inset-0 flex items-center">
|
||||
<div class="w-full border-t border-neutral-300"></div>
|
||||
</div>
|
||||
<div class="relative flex justify-center text-sm">
|
||||
<span class="px-2 bg-neutral-50 text-neutral-600">Continuer avec</span>
|
||||
<!-- Additional Links -->
|
||||
<div class="mt-6 pt-6 border-t border-gray-200">
|
||||
<div class="text-center space-y-3">
|
||||
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
|
||||
<%= link_to "Mot de passe oublié ?", new_password_path(resource_name), class: "text-sm text-purple-600 hover:text-purple-500 transition-colors" %>
|
||||
<% end %>
|
||||
<p class="text-sm text-gray-600">
|
||||
Vous n'avez pas encore de compte?
|
||||
<a href="<%= new_user_registration_path %>" class="font-semibold text-purple-600 hover:text-purple-500 transition-colors">S'inscrire</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render "devise/shared/links" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,5 +1,20 @@
|
||||
<% if resource.errors.any? %>
|
||||
<div class="bg-red-50 border border-red-200 text-red-800 rounded-xl p-4 mb-6" data-controller="flash-message">
|
||||
<div class="flex items-start">
|
||||
<div class="flex-shrink-0">
|
||||
<i data-lucide="x-circle" class="w-5 h-5"></i>
|
||||
</div>
|
||||
<div class="ml-3 flex-1">
|
||||
<h3 class="text-sm font-medium mb-2">Veuillez corriger les erreurs suivantes :</h3>
|
||||
<ul class="list-disc list-inside space-y-1 text-sm">
|
||||
<% resource.errors.full_messages.each do |message| %>
|
||||
<% flash.now[:error] = message %>
|
||||
<li><%= message %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
<button data-action="click->flash-message#close" class="bg-transparent border-none cursor-pointer p-1 text-inherit opacity-70 transition-opacity duration-200">
|
||||
<i data-lucide="x" class="w-4 h-4"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -1,39 +1,58 @@
|
||||
<div class="mt-4 space-y-4">
|
||||
<%- if controller_name != "sessions" %>
|
||||
<div class="w-full flex justify-center py-2 px-4 border border-neutral-300 rounded-md shadow-sm text-sm font-medium text-purple-600 bg-white hover:bg-neutral-50 hover:border-purple-500 transition-all duration-200">
|
||||
<%= link_to "Se connecter", new_session_path(resource_name), class: "block" %>
|
||||
<div class="mt-6">
|
||||
<div class="relative">
|
||||
<div class="absolute inset-0 flex items-center">
|
||||
<div class="w-full border-t border-gray-200"></div>
|
||||
</div>
|
||||
<div class="relative flex justify-center text-sm">
|
||||
<span class="px-2 bg-white text-gray-500">Ou continuer avec</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 grid grid-cols-2 gap-3">
|
||||
<%- if controller_name != "sessions" %>
|
||||
<%= link_to new_session_path(resource_name), class: "w-full inline-flex justify-center py-2 px-4 border border-gray-300 rounded-xl shadow-sm bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 transition-all duration-200" do %>
|
||||
<i data-lucide="log-in" class="w-4 h-4 mr-2"></i>
|
||||
Se connecter
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%- if devise_mapping.registerable? && controller_name != "registrations" %>
|
||||
<div class="w-full flex justify-center mt-4 py-2 px-4 border border-neutral-300 rounded-md shadow-sm text-sm font-medium text-purple-600 bg-white hover:bg-neutral-50 hover:border-purple-500 transition-all duration-200">
|
||||
<%= link_to "Créer un compte", new_registration_path(resource_name), class: "block" %>
|
||||
</div>
|
||||
<%= link_to new_registration_path(resource_name), class: "w-full inline-flex justify-center py-2 px-4 border border-gray-300 rounded-xl shadow-sm bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 transition-all duration-200" do %>
|
||||
<i data-lucide="user-plus" class="w-4 h-4 mr-2"></i>
|
||||
S'inscrire
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%- if devise_mapping.recoverable? && controller_name != "passwords" && controller_name != "registrations" %>
|
||||
<div class="w-full flex justify-center mt-4 py-2 px-4 border border-neutral-300 rounded-md shadow-sm text-sm font-medium text-purple-600 bg-white hover:bg-neutral-50 hover:border-purple-500 transition-all duration-200">
|
||||
<%= link_to "Mot de passe oublié ?", new_password_path(resource_name), class: "block" %>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 grid grid-cols-1 gap-3">
|
||||
<%- if devise_mapping.recoverable? && controller_name != "passwords" && controller_name != "registrations" %>
|
||||
<%= link_to new_password_path(resource_name), class: "w-full inline-flex justify-center py-2 px-4 border border-gray-300 rounded-xl shadow-sm bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 transition-all duration-200" do %>
|
||||
<i data-lucide="help-circle" class="w-4 h-4 mr-2"></i>
|
||||
Mot de passe oublié ?
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%- if devise_mapping.confirmable? && controller_name != "confirmations" %>
|
||||
<div class="w-full flex justify-center mt-4 py-2 px-4 border border-neutral-300 rounded-md shadow-sm text-sm font-medium text-purple-600 bg-white hover:bg-neutral-50 hover:border-purple-500 transition-all duration-200">
|
||||
<%= link_to "Renvoyer le lien de confirmation", new_confirmation_path(resource_name), class: "block" %>
|
||||
</div>
|
||||
<%= link_to new_confirmation_path(resource_name), class: "w-full inline-flex justify-center py-2 px-4 border border-gray-300 rounded-xl shadow-sm bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 transition-all duration-200" do %>
|
||||
<i data-lucide="mail" class="w-4 h-4 mr-2"></i>
|
||||
Renvoyer le lien de confirmation
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != "unlocks" %>
|
||||
<div class="w-full flex justify-center mt-4 py-2 px-4 border border-neutral-300 rounded-md shadow-sm text-sm font-medium text-purple-600 bg-white hover:bg-neutral-50 hover:border-purple-500 transition-all duration-200">
|
||||
<%= link_to "Renvoyer le lien de déblocage", new_unlock_path(resource_name), class: "block" %>
|
||||
</div>
|
||||
<%= link_to new_unlock_path(resource_name), class: "w-full inline-flex justify-center py-2 px-4 border border-gray-300 rounded-xl shadow-sm bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 transition-all duration-200" do %>
|
||||
<i data-lucide="unlock" class="w-4 h-4 mr-2"></i>
|
||||
Renvoyer le lien de déblocage
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%- if devise_mapping.omniauthable? %>
|
||||
<%- resource_class.omniauth_providers.each do |provider| %>
|
||||
<div class="w-full flex justify-center mt-4 py-2 px-4 border border-neutral-300 rounded-md shadow-sm text-sm font-medium text-purple-600 bg-white hover:bg-neutral-50 hover:border-purple-500 transition-all duration-200">
|
||||
<%= button_to "Se connecter avec #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), data: { turbo: false }, class: "block" %>
|
||||
<%= button_to omniauth_authorize_path(resource_name, provider), data: { turbo: false }, class: "w-full inline-flex justify-center py-2 px-4 border border-gray-300 rounded-xl shadow-sm bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 transition-all duration-200" do %>
|
||||
<i data-lucide="external-link" class="w-4 h-4 mr-2"></i>
|
||||
Se connecter avec <%= OmniAuth::Utils.camelize(provider) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -1,15 +1,52 @@
|
||||
<h2>Resend unlock instructions</h2>
|
||||
|
||||
<%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %>
|
||||
|
||||
<div class="field">
|
||||
<%= f.label :email %><br />
|
||||
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
|
||||
<div class="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="max-w-md w-full space-y-8">
|
||||
<!-- Header -->
|
||||
<div class="text-center">
|
||||
<%= link_to "/" do %>
|
||||
<div class="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-br from-purple-600 to-blue-600 rounded-2xl mb-6">
|
||||
<i data-lucide="calendar" class="w-8 h-8 text-white"></i>
|
||||
</div>
|
||||
<% end %>
|
||||
<h2 class="text-3xl font-bold text-gray-900">Renvoyer les instructions de déverrouillage</h2>
|
||||
<p class="mt-2 text-gray-600">
|
||||
Entrez votre adresse email et nous vous enverrons les instructions de déverrouillage
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<%= f.submit "Resend unlock instructions" %>
|
||||
<!-- Form -->
|
||||
<div class="bg-white py-8 px-6 shadow-xl rounded-2xl">
|
||||
<%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post, class: "space-y-6" }) do |f| %>
|
||||
<div class="space-y-5">
|
||||
<div>
|
||||
<%= f.label :email, "Adresse email", class: "block text-sm font-semibold text-gray-700 mb-2" %>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<i data-lucide="mail" class="w-5 h-5 text-gray-400"></i>
|
||||
</div>
|
||||
<%= f.email_field :email, autofocus: true, autocomplete: "email",
|
||||
placeholder: "votre@email.com",
|
||||
class: "block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-colors" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render "devise/shared/links" %>
|
||||
<div class="pt-4">
|
||||
<%= f.button type: "submit", class: "group relative w-full flex justify-center items-center py-3 px-4 border border-transparent text-sm font-semibold rounded-xl text-white bg-gray-900 hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 transition-all duration-200 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5" do %>
|
||||
<i data-lucide="send" class="w-4 h-4 mr-2"></i>
|
||||
Renvoyer les instructions de déverrouillage
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<!-- Additional Links -->
|
||||
<div class="mt-6 pt-6 border-t border-gray-200">
|
||||
<div class="text-center">
|
||||
<p class="text-sm text-gray-600">
|
||||
Vous vous souvenez de votre mot de passe ?
|
||||
<a href="<%= new_user_session_path %>" class="font-semibold text-purple-600 hover:text-purple-500 transition-colors">Se connecter</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,135 +1,117 @@
|
||||
<div class="container">
|
||||
<div class="container mx-auto px-4 py-8">
|
||||
<!-- Breadcrumb -->
|
||||
<nav class="breadcrumb" aria-label="Breadcrumb">
|
||||
<div class="breadcrumb-item">
|
||||
<%= link_to "Accueil", root_path %>
|
||||
</div>
|
||||
<div class="breadcrumb-item breadcrumb-current">
|
||||
Événements
|
||||
</div>
|
||||
</nav>
|
||||
<!-- Breadcrumb -->
|
||||
<%= render 'components/breadcrumb', crumbs: [
|
||||
{ name: 'Accueil', path: root_path },
|
||||
{ name: 'Événements', path: events_path }
|
||||
] %>
|
||||
|
||||
<!-- Page Header -->
|
||||
<header class="page-header">
|
||||
<header class="flex flex-col sm:flex-row justify-between items-start sm:items-center mb-8 gap-4">
|
||||
<div>
|
||||
<h1 class="page-title">Événements à venir</h1>
|
||||
<h1 class="text-3xl lg:text-4xl font-bold text-gray-900">Événements à venir</h1>
|
||||
<p class="text-gray-600 mt-2">Découvrez les meilleurs afterworks et événements de Paris</p>
|
||||
</div>
|
||||
<div class="page-meta">
|
||||
<%= @events.total_count %>
|
||||
événements trouvés
|
||||
<div class="bg-purple-100 text-purple-800 px-4 py-2 rounded-full text-sm font-medium">
|
||||
<%= @events.total_count %> événements trouvés
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Events Grid -->
|
||||
<% if @events.any? %>
|
||||
<div class="events-grid">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<% @events.each do |event| %>
|
||||
<article class="event-card">
|
||||
<article class="group bg-white rounded-2xl shadow-lg hover:shadow-2xl transition-all duration-300 overflow-hidden transform hover:-translate-y-1">
|
||||
<%= link_to event_path(event.slug, event), class: "block" do %>
|
||||
<% if event.image.present? %>
|
||||
<div class="event-card-image">
|
||||
<%= link_to event_path(event.slug, event) do %>
|
||||
<div class="relative overflow-hidden aspect-[4/3]">
|
||||
<img
|
||||
src="<%= event.image %>"
|
||||
alt="<%= event.name %>"
|
||||
class="featured-event-image"
|
||||
data-featured-event-target="animated"
|
||||
class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
|
||||
>
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="event-card-placeholder">
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<!-- Event featured badge -->
|
||||
<% if event.featured? %>
|
||||
<div class="absolute top-4 left-4">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-medium shadow-lg">
|
||||
★ En vedette
|
||||
</span>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="event-card-content">
|
||||
<div class="event-card-header">
|
||||
<div>
|
||||
<h2 class="event-card-title"><%= event.name %></h2>
|
||||
<p class="event-card-venue">
|
||||
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"
|
||||
/>
|
||||
</svg>
|
||||
<%= event.venue_name.truncate(20) %>
|
||||
</p>
|
||||
</div>
|
||||
<span class="event-card-date">
|
||||
<!-- Date badge -->
|
||||
<div class="absolute bottom-4 right-4">
|
||||
<span class="bg-white/90 backdrop-blur-sm text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<%= event.start_time.strftime("%d/%m") %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="relative overflow-hidden aspect-[4/3] bg-gradient-to-br from-purple-600 to-blue-600 flex items-center justify-center">
|
||||
<i data-lucide="calendar" class="w-16 h-16 text-white"></i>
|
||||
<!-- Date badge -->
|
||||
<div class="absolute bottom-4 right-4">
|
||||
<span class="bg-white/90 backdrop-blur-sm text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
<%= event.start_time.strftime("%d/%m") %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<p class="event-card-description">
|
||||
<div class="p-6">
|
||||
<div class="mb-4">
|
||||
<h2 class="text-xl font-bold text-gray-900 mb-2 group-hover:text-purple-600 transition-colors line-clamp-2"><%= event.name %></h2>
|
||||
<p class="text-sm text-gray-500 flex items-center">
|
||||
<i data-lucide="map-pin" class="w-4 h-4 mr-2"></i>
|
||||
<%= event.venue_name.truncate(25) %>
|
||||
</p>
|
||||
<p class="text-sm text-gray-500 flex items-center mt-1">
|
||||
<i data-lucide="clock" class="w-4 h-4 mr-2"></i>
|
||||
<%= l(event.start_time, format: '%A %d %B • %H:%M') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p class="text-gray-600 text-sm mb-4 line-clamp-2">
|
||||
<%= event.description.truncate(100) %>
|
||||
</p>
|
||||
|
||||
<div class="event-card-footer">
|
||||
<div class="flex justify-between items-center pt-4 border-t border-gray-100">
|
||||
<div>
|
||||
<% if event.ticket_types.any? %>
|
||||
<p class="event-card-price">
|
||||
<p class="text-sm font-semibold text-gray-900">
|
||||
À partir de <%= format_price(event.ticket_types.minimum(:price_cents)) %>€
|
||||
</p>
|
||||
<% else %>
|
||||
<p class="event-card-price-unavailable">Pas de billets disponibles</p>
|
||||
<p class="text-sm text-gray-500">Pas de billets disponibles</p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= link_to event_path(event.slug, event), class: "event-card-link" do %>
|
||||
Détails
|
||||
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
<div class="inline-flex items-center text-purple-600 font-medium text-sm group-hover:text-purple-700">
|
||||
Voir détails
|
||||
<i data-lucide="arrow-right" class="w-4 h-4 ml-1 group-hover:translate-x-1 transition-transform"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
<div class="pagination">
|
||||
<div class="flex justify-center mt-12">
|
||||
<%= paginate @events, theme: "tailwind" %>
|
||||
</div>
|
||||
<% else %>
|
||||
<!-- Empty State -->
|
||||
<div class="empty-state">
|
||||
<div class="empty-state-icon">
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<div class="text-center py-16">
|
||||
<div class="w-24 h-24 bg-gradient-to-br from-purple-100 to-blue-100 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<i data-lucide="calendar-x" class="w-12 h-12 text-purple-600"></i>
|
||||
</div>
|
||||
<h3 class="empty-state-title">Aucun événement disponible</h3>
|
||||
<p class="empty-state-description">Il n'y a aucun événement à venir pour le moment.</p>
|
||||
<%= link_to "Retour à l'accueil", root_path, class: "btn btn-primary" %>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-4">Aucun événement disponible</h3>
|
||||
<p class="text-gray-600 mb-8 max-w-md mx-auto">Il n'y a aucun événement à venir pour le moment. Revenez bientôt pour découvrir de nouvelles sorties!</p>
|
||||
<%= link_to "Retour à l'accueil", root_path, class: "inline-flex items-center bg-purple-600 text-white px-6 py-3 rounded-full font-semibold hover:bg-purple-700 transition-all duration-200 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5" do %>
|
||||
<i data-lucide="home" class="w-4 h-4 mr-2"></i>
|
||||
Retour à l'accueil
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
|
||||
<div class="flex items-center space-x-2">
|
||||
<%= link_to ticket_download_path(ticket.qr_code, format: :pdf),
|
||||
class: "inline-flex items-center px-4 py-2 bg-gradient-to-r from-purple-600 to-indigo-600 text-white rounded-lg hover:from-purple-700 hover:to-indigo-700 transition-all duration-200 text-sm font-medium shadow-sm" do %>
|
||||
class: "inline-flex items-center px-4 py-2 btn btn-primary rounded-lg transition-all duration-200 text-sm font-medium shadow-sm" do %>
|
||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
|
||||
</svg>
|
||||
@@ -129,7 +129,7 @@
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<%= link_to dashboard_path,
|
||||
class: "inline-flex items-center justify-center px-6 py-3 bg-gradient-to-r from-purple-600 to-indigo-600 text-white rounded-xl hover:from-purple-700 hover:to-indigo-700 transition-all duration-200 font-medium shadow-sm" do %>
|
||||
class: "inline-flex items-center justify-center px-6 py-3 btn btn-primary rounded-xl transition-all duration-200 font-medium shadow-sm" do %>
|
||||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path>
|
||||
</svg>
|
||||
|
||||
@@ -12,9 +12,33 @@
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=Outfit:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=DM+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Lucide Icons loaded via npm package -->
|
||||
<!-- TailwindCSS -->
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
'brand-primary': '#667eea',
|
||||
'brand-secondary': '#764ba2',
|
||||
'brand-accent': '#facc15'
|
||||
},
|
||||
fontFamily: {
|
||||
'sans': ['Inter', 'system-ui', 'sans-serif'],
|
||||
'display': ['DM Sans', 'system-ui', 'sans-serif']
|
||||
},
|
||||
backgroundImage: {
|
||||
'gradient-primary': 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Lucide Icons -->
|
||||
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
|
||||
|
||||
<%# Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!) %>
|
||||
<%#= tag.link rel: "manifest", href: pwa_manifest_path(format: :json) %>
|
||||
@@ -28,21 +52,19 @@
|
||||
<%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>
|
||||
|
||||
</head>
|
||||
<body data-user-authenticated="<%= user_signed_in? %>" data-event-slug="<%= @event&.slug %>">
|
||||
<body data-user-authenticated="<%= user_signed_in? %>" data-event-slug="<%= @event&.slug %>" class="font-sans bg-white text-gray-900">
|
||||
<div class="app-wrapper">
|
||||
<%= render "components/header" %>
|
||||
|
||||
<!-- Flash messages positioned between header and content -->
|
||||
<%= render "shared/flash_messages" %>
|
||||
|
||||
<main class="">
|
||||
<div class="yield">
|
||||
<main class="flex-1">
|
||||
<%= yield %>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="bg-neutral-800 text-neutral-300 py-8 pb-4">
|
||||
<div class="container">
|
||||
<footer class="bg-gray-900 text-white py-16">
|
||||
<div class="container mx-auto px-4">
|
||||
<%= render "components/footer" %>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
<!-- Header -->
|
||||
<div class="text-center mb-8">
|
||||
<div class="mx-auto w-20 h-20 bg-purple-100 rounded-full flex items-center justify-center mb-6">
|
||||
<svg class="w-10 h-10 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h1m4 0h1m-7 4h12a3 3 0 003-3V7a3 3 0 00-3-3H6a3 3 0 00-3 3v4a3 3 0 003 3z"/>
|
||||
</svg>
|
||||
<i data-lucide="user" class="w-10 h-10 text-purple-600"></i>
|
||||
</div>
|
||||
<h1 class="text-3xl font-bold text-gray-900 mb-3">Bienvenue sur <%= Rails.application.config.app_name %> !</h1>
|
||||
<p class="text-lg text-gray-600 max-w-lg mx-auto">
|
||||
@@ -34,9 +32,7 @@
|
||||
<!-- Personal Information Section -->
|
||||
<div>
|
||||
<h2 class="text-xl font-semibold text-gray-900 mb-4 flex items-center">
|
||||
<svg class="w-5 h-5 mr-2 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<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>
|
||||
<i data-lucide="user" class="w-5 h-5 mr-2 text-purple-600"></i>
|
||||
Informations personnelles
|
||||
</h2>
|
||||
|
||||
@@ -71,8 +67,10 @@
|
||||
<p class="text-sm text-gray-500">
|
||||
Vous pourrez modifier ces informations plus tard.
|
||||
</p>
|
||||
<%= form.submit "Compléter mon profil",
|
||||
class: "w-full px-8 py-3 bg-purple-600 text-white font-semibold rounded-lg hover:bg-purple-700 focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 transition-colors cursor-pointer" %>
|
||||
<%= form.button type: "submit", class: "w-full px-8 py-3 bg-purple-600 text-white font-semibold rounded-lg hover:bg-purple-700 focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 transition-colors cursor-pointer flex items-center justify-center" do %>
|
||||
<i data-lucide="check" class="w-4 h-4 mr-2"></i>
|
||||
Compléter mon profil
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -86,21 +84,15 @@
|
||||
</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div class="flex items-center p-3 bg-green-50 rounded-lg">
|
||||
<svg class="w-6 h-6 text-green-600 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
|
||||
</svg>
|
||||
<i data-lucide="calendar" class="w-6 h-6 text-green-600 mr-3"></i>
|
||||
<span class="text-sm font-medium text-green-800">Réserver des billets</span>
|
||||
</div>
|
||||
<div class="flex items-center p-3 bg-blue-50 rounded-lg">
|
||||
<svg class="w-6 h-6 text-blue-600 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
<i data-lucide="clock" class="w-6 h-6 text-blue-600 mr-3"></i>
|
||||
<span class="text-sm font-medium text-blue-800">Gérer vos commandes</span>
|
||||
</div>
|
||||
<div class="flex items-center p-3 bg-purple-50 rounded-lg">
|
||||
<svg class="w-6 h-6 text-purple-600 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4"/>
|
||||
</svg>
|
||||
<i data-lucide="settings" class="w-6 h-6 text-purple-600 mr-3"></i>
|
||||
<span class="text-sm font-medium text-purple-800">Créer des événements</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,36 +1,29 @@
|
||||
<div class="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 py-8">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<!-- Breadcrumb -->
|
||||
<nav class="flex mb-6" aria-label="Breadcrumb">
|
||||
<ol class="inline-flex items-center space-x-1 md:space-x-2 rounded-lg bg-white px-4 py-2 shadow-sm">
|
||||
<li class="inline-flex items-center">
|
||||
<%= link_to "Accueil", root_path, class: "inline-flex items-center text-sm font-medium text-gray-700 hover:text-purple-600" %>
|
||||
</li>
|
||||
<li>
|
||||
<div class="flex items-center">
|
||||
<svg class="w-4 h-4 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
<%= link_to "Événements", events_path, class: "ml-1 text-sm font-medium text-gray-700 hover:text-purple-600 md:ml-2" %>
|
||||
<nav class="inline-flex items-center gap-2 bg-white px-4 py-3 rounded-xl shadow-sm border border-gray-100 mb-8" aria-label="Breadcrumb">
|
||||
<div class="inline-flex items-center text-sm font-medium">
|
||||
<%= link_to root_path, class: "text-gray-700 hover:text-purple-600 transition-colors" do %>
|
||||
<i data-lucide="home" class="w-4 h-4 mr-2"></i>
|
||||
Accueil
|
||||
<% end %>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="flex items-center">
|
||||
<svg class="w-4 h-4 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
<%= link_to @order.event.name, event_path(@order.event.slug, @order.event), class: "ml-1 text-sm font-medium text-gray-700 hover:text-purple-600 md:ml-2" %>
|
||||
<i data-lucide="chevron-right" class="w-4 h-4 text-gray-400"></i>
|
||||
<div class="inline-flex items-center text-sm font-medium">
|
||||
<%= link_to events_path, class: "text-gray-700 hover:text-purple-600 transition-colors" do %>
|
||||
Événements
|
||||
<% end %>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="flex items-center">
|
||||
<svg class="w-4 h-4 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
<span class="ml-1 text-sm font-medium text-purple-600 md:ml-2">Commande #<%= @order.id %></span>
|
||||
<i data-lucide="chevron-right" class="w-4 h-4 text-gray-400"></i>
|
||||
<div class="inline-flex items-center text-sm font-medium">
|
||||
<%= link_to @order.event.name, event_path(@order.event.slug, @order.event), class: "text-gray-700 hover:text-purple-600 transition-colors" do %>
|
||||
<%= @order.event.name %>
|
||||
<% end %>
|
||||
</div>
|
||||
<i data-lucide="chevron-right" class="w-4 h-4 text-gray-400"></i>
|
||||
<div class="text-sm font-medium text-purple-600">
|
||||
Commande #<%= @order.id %>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
@@ -40,9 +33,7 @@
|
||||
<% if @expiring_soon %>
|
||||
<div class="mb-6 bg-orange-50 border border-orange-200 rounded-lg p-4">
|
||||
<div class="flex items-start">
|
||||
<svg class="w-5 h-5 text-orange-600 mr-2 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
<i data-lucide="alert-triangle" class="w-5 h-5 text-orange-600 mr-2 mt-0.5 flex-shrink-0"></i>
|
||||
<div>
|
||||
<h3 class="font-medium text-orange-800 mb-1">Attention - Commande bientôt expirée</h3>
|
||||
<p class="text-orange-700 text-sm">Votre commande va expirer dans quelques minutes. Veuillez procéder rapidement au paiement pour éviter son expiration automatique.</p>
|
||||
@@ -55,9 +46,7 @@
|
||||
<% if @order.payment_attempts > 0 %>
|
||||
<div class="mb-6 bg-blue-50 border border-blue-200 rounded-lg p-4">
|
||||
<div class="flex items-start">
|
||||
<svg class="w-5 h-5 text-blue-600 mr-2 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
<i data-lucide="info" class="w-5 h-5 text-blue-600 mr-2 mt-0.5 flex-shrink-0"></i>
|
||||
<div>
|
||||
<h3 class="font-medium text-blue-800 mb-1">Nouvelle tentative de paiement</h3>
|
||||
<p class="text-blue-700 text-sm">
|
||||
@@ -75,17 +64,13 @@
|
||||
<h1 class="text-2xl font-bold text-gray-900 mb-2">Commande pour <%= @order.event.name %></h1>
|
||||
<div class="flex items-center text-sm text-gray-600 space-x-4">
|
||||
<div class="flex items-center">
|
||||
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
<i data-lucide="clock" class="w-4 h-4 mr-1"></i>
|
||||
<% if @order.expires_at %>
|
||||
Expire dans <%= time_ago_in_words(@order.expires_at, include_seconds: true) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
|
||||
</svg>
|
||||
<i data-lucide="file-text" class="w-4 h-4 mr-1"></i>
|
||||
Commande #<%= @order.id %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -100,9 +85,7 @@
|
||||
<div class="flex-1 min-w-0">
|
||||
<h4 class="text-sm font-medium text-gray-900 truncate"><%= ticket.ticket_type.name %></h4>
|
||||
<div class="flex items-center text-xs text-gray-500 mt-1">
|
||||
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<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>
|
||||
<i data-lucide="user" class="w-3 h-3 mr-1"></i>
|
||||
<%= ticket.first_name %> <%= ticket.last_name %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -148,9 +131,7 @@
|
||||
<div class="space-y-6">
|
||||
<div class="bg-gradient-to-r from-purple-50 to-pink-50 rounded-lg p-4 border border-purple-200">
|
||||
<div class="flex items-start">
|
||||
<svg class="w-5 h-5 text-purple-600 mr-2 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
|
||||
</svg>
|
||||
<i data-lucide="shield" class="w-5 h-5 text-purple-600 mr-2 mt-0.5 flex-shrink-0"></i>
|
||||
<div>
|
||||
<h3 class="font-medium text-purple-800 mb-1">Paiement 100% sécurisé</h3>
|
||||
<p class="text-purple-700 text-sm">Vos données bancaires sont protégées par le cryptage SSL et traitées par Stripe, leader mondial du paiement en ligne.</p>
|
||||
@@ -160,33 +141,25 @@
|
||||
|
||||
<button
|
||||
id="checkout-button"
|
||||
class="w-full bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-700 hover:to-pink-700 text-white font-bold py-4 px-6 rounded-xl transition-all duration-200 transform hover:scale-105 active:scale-95 shadow-lg hover:shadow-xl"
|
||||
class="w-full btn btn-primary py-4 px-6 rounded-xl transition-all duration-200 transform hover:scale-105 active:scale-95 shadow-lg hover:shadow-xl"
|
||||
>
|
||||
<div class="flex items-center justify-center">
|
||||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"/>
|
||||
</svg>
|
||||
<i data-lucide="credit-card" class="w-5 h-5 mr-2"></i>
|
||||
Payer <%= @order.total_amount_euros %>€
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div class="flex items-center justify-center space-x-4 text-xs text-gray-500">
|
||||
<span class="flex items-center">
|
||||
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"/>
|
||||
</svg>
|
||||
<i data-lucide="credit-card" class="w-4 h-4 mr-1"></i>
|
||||
Visa
|
||||
</span>
|
||||
<span class="flex items-center">
|
||||
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"/>
|
||||
</svg>
|
||||
<i data-lucide="credit-card" class="w-4 h-4 mr-1"></i>
|
||||
Mastercard
|
||||
</span>
|
||||
<span class="flex items-center">
|
||||
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
|
||||
</svg>
|
||||
<i data-lucide="shield" class="w-4 h-4 mr-1"></i>
|
||||
Sécurisé par Stripe
|
||||
</span>
|
||||
</div>
|
||||
@@ -269,9 +242,7 @@
|
||||
button.disabled = false;
|
||||
button.innerHTML = `
|
||||
<div class="flex items-center justify-center">
|
||||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"/>
|
||||
</svg>
|
||||
<i data-lucide="credit-card" class="w-5 h-5 mr-2"></i>
|
||||
Payer <%= @order.total_amount_euros %>€
|
||||
</div>
|
||||
`;
|
||||
@@ -292,9 +263,7 @@
|
||||
<!-- No Stripe Configuration -->
|
||||
<div class="text-center py-8">
|
||||
<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-6">
|
||||
<svg class="w-12 h-12 text-yellow-600 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
<i data-lucide="alert-triangle" class="w-12 h-12 text-yellow-600 mx-auto mb-4"></i>
|
||||
<h3 class="font-semibold text-yellow-800 mb-2">Paiement temporairement indisponible</h3>
|
||||
<p class="text-yellow-700 text-sm">Le système de paiement n'est pas encore configuré. Veuillez contacter l'organisateur pour plus d'informations.</p>
|
||||
</div>
|
||||
@@ -306,9 +275,7 @@
|
||||
<div class="space-y-3">
|
||||
<%= link_to event_path(@order.event.slug, @order.event), class: "block w-full text-center py-3 px-4 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 transition-colors" do %>
|
||||
<div class="flex items-center justify-center">
|
||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
|
||||
</svg>
|
||||
<i data-lucide="arrow-left" class="w-4 h-4 mr-2"></i>
|
||||
Retour à l'événement
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
|
||||
<div class="flex flex-col sm:flex-row gap-4 pt-6">
|
||||
<%= link_to "Retour", event_path(@event.slug, @event), class: "px-6 py-3 border border-gray-300 text-gray-700 rounded-xl hover:bg-gray-50 text-center font-medium transition-colors duration-200" %>
|
||||
<%= form.submit "Procéder au paiement", class: "flex-1 bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-700 hover:to-indigo-700 text-white font-medium py-3 px-6 rounded-xl shadow-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 transform hover:-translate-y-0.5" %>
|
||||
<%= form.button "Procéder au paiement", type: "submit", class: "flex-1 btn btn-primary py-3 px-6 rounded-xl shadow-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 transform hover:-translate-y-0.5" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
<div class="container mx-auto px-4 sm:px-6 lg:px-8 py-4 sm:py-6">
|
||||
<!-- Simplified header -->
|
||||
<div class="my-6 sm:my-8">
|
||||
<div class="container mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<!-- Page Header -->
|
||||
<div class="mb-8">
|
||||
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
||||
<div>
|
||||
<h1 class="text-2xl sm:text-3xl font-bold text-slate-900 dark:text-slate-100">Mon tableau de bord</h1>
|
||||
<p class="text-sm sm:text-base text-slate-600 dark:text-slate-400 mt-1">Gérez vos commandes et accédez à vos billets</p>
|
||||
<h1 class="text-3xl font-bold text-gray-900">Mon tableau de bord</h1>
|
||||
<p class="text-gray-600 mt-1">Gérez vos commandes et accédez à vos billets</p>
|
||||
</div>
|
||||
|
||||
<!-- Promoter Actions -->
|
||||
<% if current_user.promoter? %>
|
||||
<div class="flex flex-col xs:flex-row items-stretch xs:items-center gap-2">
|
||||
<%= link_to promoter_events_path, class: "inline-flex items-center justify-center px-3 py-2 sm:px-4 sm:py-2 bg-purple-600 text-white font-medium rounded-lg hover:bg-purple-700 transition-colors duration-200 text-sm" do %>
|
||||
<i data-lucide="calendar-plus" class="w-4 h-4 mr-1 sm:mr-2"></i>
|
||||
<span class="whitespace-nowrap">Mes Événements</span>
|
||||
<%= link_to promoter_events_path, class: "inline-flex items-center justify-center px-4 py-2 bg-purple-600 text-white font-medium rounded-lg hover:bg-purple-700 transition-colors duration-200" do %>
|
||||
<i data-lucide="calendar-plus" class="w-4 h-4 mr-2"></i>
|
||||
Mes Événements
|
||||
<% end %>
|
||||
<%= link_to new_promoter_event_path, class: "inline-flex items-center justify-center px-3 py-2 sm:px-4 sm:py-2 bg-black text-white font-medium rounded-lg hover:bg-gray-800 transition-colors duration-200 text-sm" do %>
|
||||
<i data-lucide="plus" class="w-4 h-4 mr-1 sm:mr-2"></i>
|
||||
<span class="whitespace-nowrap">Créer un Événement</span>
|
||||
<%= link_to new_promoter_event_path, class: "inline-flex items-center justify-center px-4 py-2 bg-gray-900 text-white font-medium rounded-lg hover:bg-gray-800 transition-colors duration-200" do %>
|
||||
<i data-lucide="plus" class="w-4 h-4 mr-2"></i>
|
||||
Créer un Événement
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= link_to events_path, class: "inline-flex items-center justify-center px-3 py-2 sm:px-4 sm:py-2 bg-purple-600 text-white font-medium rounded-lg hover:bg-purple-700 transition-colors duration-200 text-sm" do %>
|
||||
<i data-lucide="search" class="w-4 h-4 mr-1 sm:mr-2"></i>
|
||||
<span class="whitespace-nowrap">Découvrir des Événements</span>
|
||||
<%= link_to events_path, class: "inline-flex items-center justify-center px-4 py-2 bg-purple-600 text-white font-medium rounded-lg hover:bg-purple-700 transition-colors duration-200" do %>
|
||||
<i data-lucide="search" class="w-4 h-4 mr-2"></i>
|
||||
Découvrir des Événements
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -30,40 +30,34 @@
|
||||
|
||||
<!-- Draft orders needing payment -->
|
||||
<% if @draft_orders.any? %>
|
||||
<div class="card mb-6 sm:mb-8 border-orange-200 bg-orange-50">
|
||||
<div class="card-header bg-orange-100 rounded-lg">
|
||||
<div class="mx-4 py-3 sm:py-4">
|
||||
<h2 class="text-lg sm:text-2xl font-bold text-orange-900 flex items-center">
|
||||
<svg class="w-5 h-5 sm:w-6 sm:h-6 mr-2 text-orange-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
<div class="bg-orange-50 border border-orange-200 rounded-2xl shadow-lg mb-8">
|
||||
<div class="bg-orange-100 rounded-t-2xl p-4 sm:p-6">
|
||||
<h2 class="text-xl sm:text-2xl font-bold text-orange-900 flex items-center">
|
||||
<i data-lucide="alert-triangle" class="w-5 h-5 sm:w-6 sm:h-6 mr-2 text-orange-600"></i>
|
||||
Commandes en Attente de Paiement
|
||||
</h2>
|
||||
<p class="text-sm sm:text-base text-orange-700 mt-1">Vous avez des commandes qui nécessitent un paiement</p>
|
||||
<p class="text-gray-700 mt-1">Vous avez des commandes qui nécessitent un paiement</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="p-4 sm:p-6">
|
||||
<div class="space-y-4">
|
||||
<% @draft_orders.each do |order| %>
|
||||
<div class="bg-white rounded-lg p-3 sm:p-4 border border-orange-200">
|
||||
<div class="bg-white rounded-xl p-4 border border-orange-200">
|
||||
<div class="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-3 mb-3">
|
||||
<div>
|
||||
<h3 class="font-semibold text-gray-900 text-sm sm:text-base"><%= order.event.name %></h3>
|
||||
<p class="text-xs sm:text-sm text-gray-600 mt-1">
|
||||
<svg class="w-3 h-3 sm:w-4 sm:h-4 inline mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
|
||||
</svg>
|
||||
<h3 class="font-semibold text-gray-900 text-base sm:text-lg"><%= order.event.name %></h3>
|
||||
<p class="text-sm text-gray-600 mt-1 flex items-center">
|
||||
<i data-lucide="calendar" class="w-4 h-4 mr-2"></i>
|
||||
<%= order.event.start_time.strftime("%d %B %Y à %H:%M") %>
|
||||
</p>
|
||||
</div>
|
||||
<span class="text-xs sm:text-sm font-medium text-orange-600 bg-orange-100 px-2 py-1 rounded-full whitespace-nowrap">
|
||||
<span class="text-sm font-medium text-orange-600 bg-orange-100 px-3 py-1 rounded-full whitespace-nowrap">
|
||||
Order #<%= order.id %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-2 mb-4">
|
||||
<% order.tickets.each do |ticket| %>
|
||||
<div class="flex flex-col sm:flex-row sm:items-center justify-between text-xs sm:text-sm bg-gray-50 rounded p-2 gap-2">
|
||||
<div class="flex flex-col sm:flex-row sm:items-center justify-between text-sm bg-gray-50 rounded-lg p-3 gap-2">
|
||||
<div>
|
||||
<span class="font-medium"><%= ticket.ticket_type.name %></span>
|
||||
<span class="text-gray-600">- <%= ticket.first_name %> <%= ticket.last_name %></span>
|
||||
@@ -76,7 +70,7 @@
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3">
|
||||
<div class="text-xs sm:text-sm text-gray-600">
|
||||
<div class="text-sm text-gray-600">
|
||||
<div class="mb-1 sm:mb-0">
|
||||
Tentatives: <%= order.payment_attempts %>/3
|
||||
</div>
|
||||
@@ -88,7 +82,8 @@
|
||||
</div>
|
||||
|
||||
<%= link_to retry_payment_order_path(order), method: :post,
|
||||
class: "inline-flex items-center px-3 py-2 sm:px-4 sm:py-2 bg-orange-600 text-white text-xs sm:text-sm font-medium rounded-lg hover:bg-orange-700 transition-colors duration-200 whitespace-nowrap" do %>
|
||||
class: "inline-flex items-center px-4 py-2 bg-orange-600 text-white text-sm font-medium rounded-lg hover:bg-orange-700 transition-colors duration-200 whitespace-nowrap" do %>
|
||||
<i data-lucide="credit-card" class="w-4 h-4 mr-2"></i>
|
||||
Reprendre le Paiement (€<%= order.total_amount_euros %>)
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -100,78 +95,78 @@
|
||||
<% end %>
|
||||
|
||||
<!-- User's Orders Section -->
|
||||
<div class="card mb-6 sm:mb-8">
|
||||
<div class="card-header">
|
||||
<div class="bg-white rounded-2xl shadow-lg mb-8">
|
||||
<div class="border-b border-gray-100 p-4 sm:p-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-xl sm:text-2xl font-bold text-slate-900 dark:text-slate-100">Mes Commandes</h2>
|
||||
<span class="text-xs sm:text-sm text-slate-600 dark:text-slate-400 bg-slate-100 dark:bg-slate-700 px-2 py-1 sm:px-3 sm:py-1 rounded-full">
|
||||
<h2 class="text-xl sm:text-2xl font-bold text-gray-900">Mes Commandes</h2>
|
||||
<span class="text-sm text-gray-600 bg-gray-100 px-3 py-1 rounded-full">
|
||||
<%= pluralize(@user_orders.count, 'commande') %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="p-4 sm:p-6">
|
||||
<% if @user_orders.any? %>
|
||||
<div class="space-y-4">
|
||||
<% @user_orders.each do |order| %>
|
||||
<div class="bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg p-3 sm:p-4 hover:shadow-md transition-shadow">
|
||||
<div class="bg-gray-50 rounded-xl p-4 hover:shadow-md transition-shadow">
|
||||
<div class="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-3 mb-3">
|
||||
<div class="flex-1">
|
||||
<div class="flex flex-wrap items-center gap-2 mb-2">
|
||||
<h3 class="font-semibold text-slate-900 dark:text-slate-100 text-sm sm:text-base"><%= order.event.name %></h3>
|
||||
<span class="text-xs px-2 py-1 rounded-full <%= order.status == 'paid' ? 'bg-green-100 text-green-800 dark:bg-green-800 dark:text-green-100' : order.status == 'completed' ? 'bg-blue-100 text-blue-800 dark:bg-blue-800 dark:text-blue-100' : 'bg-yellow-100 text-yellow-800 dark:bg-yellow-800 dark:text-yellow-100' %>">
|
||||
<h3 class="font-semibold text-gray-900 text-base sm:text-lg"><%= order.event.name %></h3>
|
||||
<span class="text-xs px-2 py-1 rounded-full <%= order.status == 'paid' ? 'bg-green-100 text-green-800' : order.status == 'completed' ? 'bg-blue-100 text-blue-800' : 'bg-yellow-100 text-yellow-800' %>">
|
||||
<%= order.status.humanize %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-3 text-xs sm:text-sm text-slate-600 dark:text-slate-400 mb-2">
|
||||
<div class="flex flex-wrap items-center gap-3 text-sm text-gray-600 mb-2">
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="calendar" class="w-3 h-3 sm:w-4 sm:h-4 mr-1"></i>
|
||||
<i data-lucide="calendar" class="w-4 h-4 mr-2"></i>
|
||||
<%= order.event.start_time.strftime("%d %B %Y à %H:%M") %>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="map-pin" class="w-3 h-3 sm:w-4 sm:h-4 mr-1"></i>
|
||||
<i data-lucide="map-pin" class="w-4 h-4 mr-2"></i>
|
||||
<%= order.event.venue_name %>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="shopping-bag" class="w-3 h-3 sm:w-4 sm:h-4 mr-1"></i>
|
||||
<i data-lucide="shopping-bag" class="w-4 h-4 mr-2"></i>
|
||||
<%= pluralize(order.tickets.count, 'billet') %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-xs sm:text-sm text-slate-500 dark:text-slate-400 mt-2">
|
||||
<div class="text-sm text-gray-500 mt-2">
|
||||
Order #<%= order.id %> • <%= order.created_at.strftime("%m/%d/%Y") %> • €<%= order.total_amount_euros %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<%= link_to order_path(order),
|
||||
class: "inline-flex items-center px-3 py-2 bg-purple-600 hover:bg-purple-700 text-white text-xs sm:text-sm font-medium rounded-lg transition-colors duration-200 whitespace-nowrap" do %>
|
||||
<i data-lucide="eye" class="w-3 h-3 sm:w-4 sm:h-4 mr-1"></i>
|
||||
class: "inline-flex items-center px-4 py-2 bg-purple-600 hover:bg-purple-700 text-white text-sm font-medium rounded-lg transition-colors duration-200 whitespace-nowrap" do %>
|
||||
<i data-lucide="eye" class="w-4 h-4 mr-2"></i>
|
||||
Voir les Détails
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick tickets preview -->
|
||||
<div class="border-t border-slate-200 dark:border-slate-600 pt-3">
|
||||
<div class="border-t border-gray-200 pt-3">
|
||||
<div class="grid gap-2">
|
||||
<% order.tickets.limit(3).each do |ticket| %>
|
||||
<div class="flex flex-col sm:flex-row sm:items-center justify-between text-xs sm:text-sm bg-slate-50 dark:bg-slate-700 rounded p-2 gap-2">
|
||||
<div class="flex flex-col sm:flex-row sm:items-center justify-between text-sm bg-white rounded-lg p-3 gap-2">
|
||||
<div class="flex items-center space-x-2">
|
||||
<span class="w-2 h-2 bg-green-500 rounded-full"></span>
|
||||
<span class="font-medium"><%= ticket.ticket_type.name %></span>
|
||||
<span class="text-slate-500 text-xs">- <%= ticket.first_name %> <%= ticket.last_name %></span>
|
||||
<span class="text-gray-500 text-sm">- <%= ticket.first_name %> <%= ticket.last_name %></span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<%= link_to ticket_download_path(ticket.qr_code),
|
||||
class: "text-purple-600 hover:text-purple-800 dark:text-purple-400 dark:hover:text-purple-200" do %>
|
||||
<i data-lucide="download" class="w-3 h-3"></i>
|
||||
class: "text-purple-600 hover:text-purple-800" do %>
|
||||
<i data-lucide="download" class="w-4 h-4"></i>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if order.tickets.count > 3 %>
|
||||
<div class="text-xs text-slate-500 text-center">
|
||||
<div class="text-xs text-gray-500 text-center">
|
||||
et <%= pluralize(order.tickets.count - 3, 'autre billet') %>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -182,19 +177,19 @@
|
||||
</div>
|
||||
|
||||
<% if @user_orders.count >= 10 %>
|
||||
<div class="mt-4 sm:mt-6 text-center">
|
||||
<%= link_to "Voir Toutes Mes Commandes", orders_path, class: "text-purple-600 dark:text-purple-400 hover:text-purple-800 dark:hover:text-purple-200 font-medium transition-colors duration-200 text-sm" %>
|
||||
<div class="mt-6 text-center">
|
||||
<%= link_to "Voir Toutes Mes Commandes", orders_path, class: "text-purple-600 hover:text-purple-800 font-medium transition-colors duration-200" %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="text-center py-8 sm:py-12">
|
||||
<div class="w-12 h-12 sm:w-16 sm:h-16 bg-slate-100 dark:bg-slate-700 rounded-full flex items-center justify-center mx-auto mb-3 sm:mb-4">
|
||||
<i data-lucide="shopping-bag" class="w-6 h-6 sm:w-8 sm:h-8 text-slate-400"></i>
|
||||
<div class="text-center py-12">
|
||||
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<i data-lucide="shopping-bag" class="w-8 h-8 text-gray-400"></i>
|
||||
</div>
|
||||
<h3 class="text-base sm:text-lg font-medium text-slate-900 dark:text-slate-100 mb-1 sm:mb-2">Aucune Commande</h3>
|
||||
<p class="text-sm sm:text-base text-slate-600 dark:text-slate-400 mb-4 sm:mb-6">Vous n'avez pas encore passé de commandes.</p>
|
||||
<%= link_to events_path, class: "inline-flex items-center px-3 py-2 sm:px-4 sm:py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors duration-200 text-sm" do %>
|
||||
<i data-lucide="search" class="w-3 h-3 sm:w-4 sm:h-4 mr-1 sm:mr-2"></i>
|
||||
<h3 class="text-lg font-medium text-gray-900 mb-2">Aucune Commande</h3>
|
||||
<p class="text-gray-600 mb-6">Vous n'avez pas encore passé de commandes.</p>
|
||||
<%= link_to events_path, class: "inline-flex items-center px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors duration-200" do %>
|
||||
<i data-lucide="search" class="w-4 h-4 mr-2"></i>
|
||||
Découvrir des Événements
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -202,35 +197,35 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Events Preview - Simplified -->
|
||||
<!-- Quick Events Preview -->
|
||||
<% if @user_orders.any? %>
|
||||
<div class="my-6 sm:my-8 card">
|
||||
<div class="card-header">
|
||||
<div class="bg-white rounded-2xl shadow-lg">
|
||||
<div class="border-b border-gray-100 p-4 sm:p-6">
|
||||
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
|
||||
<h2 class="text-lg sm:text-xl font-bold text-slate-900 dark:text-slate-100">Découvrir d'autres événements</h2>
|
||||
<%= link_to events_path, class: "text-purple-600 dark:text-purple-400 hover:text-purple-800 dark:hover:text-purple-200 font-medium text-sm transition-colors duration-200 whitespace-nowrap" do %>
|
||||
<h2 class="text-lg sm:text-xl font-bold text-gray-900">Découvrir d'autres événements</h2>
|
||||
<%= link_to events_path, class: "text-purple-600 hover:text-purple-800 font-medium transition-colors duration-200 whitespace-nowrap" do %>
|
||||
Voir tout →
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="p-4 sm:p-6">
|
||||
<% if @upcoming_preview_events.any? %>
|
||||
<div class="grid gap-3 sm:gap-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<div class="grid gap-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<% @upcoming_preview_events.each do |event| %>
|
||||
<div class="bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg p-3 sm:p-4 hover:shadow-md transition-shadow">
|
||||
<h4 class="font-medium text-slate-900 dark:text-slate-100 mb-2 text-sm sm:text-base"><%= event.name %></h4>
|
||||
<div class="text-xs sm:text-sm text-slate-600 dark:text-slate-400 space-y-1">
|
||||
<div class="bg-gray-50 rounded-xl p-4 hover:shadow-md transition-shadow">
|
||||
<h4 class="font-medium text-gray-900 mb-2 text-base"><%= event.name %></h4>
|
||||
<div class="text-sm text-gray-600 space-y-1">
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="calendar" class="w-3 h-3 mr-1"></i>
|
||||
<i data-lucide="calendar" class="w-4 h-4 mr-2"></i>
|
||||
<%= event.start_time.strftime("%d %B") %>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="map-pin" class="w-3 h-3 mr-1"></i>
|
||||
<i data-lucide="map-pin" class="w-4 h-4 mr-2"></i>
|
||||
<%= event.venue_name %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 sm:mt-3">
|
||||
<%= link_to event_path(event.slug, event), class: "text-purple-600 dark:text-purple-400 hover:text-purple-800 dark:hover:text-purple-200 text-xs sm:text-sm font-medium" do %>
|
||||
<div class="mt-3">
|
||||
<%= link_to event_path(event.slug, event), class: "text-purple-600 hover:text-purple-800 text-sm font-medium" do %>
|
||||
Voir l'Événement →
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -238,7 +233,7 @@
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
<p class="text-slate-600 dark:text-slate-400 text-sm">Aucun événement à venir pour le moment.</p>
|
||||
<p class="text-gray-600">Aucun événement à venir pour le moment.</p>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
<% content_for :title, "Aperonight - Découvrez les meilleurs événements après-travail" %>
|
||||
|
||||
<!-- Hero Section inspired by Shotgun -->
|
||||
<section class="hero-landing">
|
||||
<div class="hero-gradient my-8">
|
||||
<div class="container mx-auto px-4 py-16 lg:py-24">
|
||||
<!-- Hero Section -->
|
||||
<section class="relative bg-gradient-primary min-h-screen flex items-center overflow-hidden">
|
||||
<!-- Background overlay -->
|
||||
<div class="absolute inset-0 bg-black bg-opacity-30 z-10"></div>
|
||||
|
||||
<div class="relative z-20 container mx-auto px-4 py-16 lg:py-24">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||
<!-- Hero Content -->
|
||||
<div class="text-center lg:text-left">
|
||||
<h1 class="text-4xl lg:text-6xl font-bold text-white mb-6 leading-tight">
|
||||
<div class="text-center lg:text-left text-white">
|
||||
<h1 class="text-4xl lg:text-6xl font-bold mb-6 leading-tight">
|
||||
Découvrez les
|
||||
<span class="text-yellow-400">meilleurs événements</span>
|
||||
afterworks
|
||||
@@ -19,7 +21,7 @@
|
||||
<!-- CTA Buttons -->
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center lg:justify-start max-w-lg">
|
||||
<%= link_to events_path,
|
||||
class: "w-full sm:flex-1 bg-white text-gray-900 px-6 py-3 rounded-full font-semibold text-base hover:bg-gray-100 transition-all duration-200 inline-flex items-center justify-center shadow-lg hover:shadow-xl" do %>
|
||||
class: "w-full sm:flex-1 bg-white text-gray-900 px-6 py-3 rounded-full font-semibold text-base hover:bg-gray-100 transition-all duration-200 inline-flex items-center justify-center shadow-lg hover:shadow-xl transform hover:-translate-y-0.5" do %>
|
||||
<i data-lucide="calendar" class="w-4 h-4 mr-2"></i>
|
||||
Voir tous les événements
|
||||
<% end %>
|
||||
@@ -36,7 +38,7 @@
|
||||
|
||||
<!-- Hero Visual -->
|
||||
<div class="relative">
|
||||
<div class="bg-gray-800 rounded-3xl p-8 shadow-2xl">
|
||||
<div class="bg-gray-800 rounded-3xl p-8 shadow-2xl backdrop-blur-sm bg-opacity-90">
|
||||
<div class="text-center text-white">
|
||||
<div class="w-16 h-16 bg-yellow-400 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<i data-lucide="calendar" class="w-8 h-8 text-gray-900"></i>
|
||||
@@ -62,7 +64,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Featured Events Section -->
|
||||
@@ -82,10 +83,12 @@
|
||||
<% if @featured_events.any? %>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mb-12">
|
||||
<% @featured_events.each do |event| %>
|
||||
<div class="group cursor-pointer">
|
||||
<div class="group cursor-pointer transform transition-all duration-300 hover:-translate-y-2">
|
||||
<%= link_to event_path(event.slug, event), class: "block" do %>
|
||||
<!-- Event Card -->
|
||||
<div class="bg-white rounded-2xl shadow-lg hover:shadow-2xl transition-all duration-300 overflow-hidden">
|
||||
<!-- Event Image -->
|
||||
<div class="relative overflow-hidden rounded-2xl mb-6 aspect-[4/3]">
|
||||
<div class="relative overflow-hidden aspect-[4/3]">
|
||||
<% if event.image.present? %>
|
||||
<img src="<%= event.image %>"
|
||||
alt="<%= event.name %>"
|
||||
@@ -99,7 +102,7 @@
|
||||
<!-- Event Badge -->
|
||||
<% if event.featured? %>
|
||||
<div class="absolute top-4 left-4">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-medium">
|
||||
<span class="bg-yellow-400 text-gray-900 px-3 py-1 rounded-full text-sm font-medium shadow-lg">
|
||||
★ En vedette
|
||||
</span>
|
||||
</div>
|
||||
@@ -108,7 +111,7 @@
|
||||
<!-- Price Badge -->
|
||||
<% if event.ticket_types.any? %>
|
||||
<div class="absolute bottom-4 right-4">
|
||||
<span class="bg-white/90 backdrop-blur-sm text-gray-900 px-3 py-1 rounded-full text-sm font-bold">
|
||||
<span class="bg-white/90 backdrop-blur-sm text-gray-900 px-3 py-1 rounded-full text-sm font-bold shadow-lg">
|
||||
À partir de €<%= event.ticket_types.minimum(:price_cents).to_f / 100 %>
|
||||
</span>
|
||||
</div>
|
||||
@@ -116,7 +119,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Event Info -->
|
||||
<div class="text-center">
|
||||
<div class="p-6 text-center">
|
||||
<h3 class="text-2xl lg:text-3xl font-bold text-gray-900 mb-2 group-hover:text-purple-600 transition-colors">
|
||||
<%= event.name.upcase %>
|
||||
</h3>
|
||||
@@ -137,6 +140,7 @@
|
||||
<%= truncate(event.description, length: 100) %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -145,19 +149,20 @@
|
||||
<!-- More Events CTA -->
|
||||
<div class="text-center">
|
||||
<%= link_to events_path,
|
||||
class: "inline-flex items-center bg-gray-900 text-white px-8 py-4 rounded-full font-semibold text-lg hover:bg-gray-800 transition-colors" do %>
|
||||
class: "inline-flex items-center bg-gray-900 text-white px-8 py-4 rounded-full font-semibold text-lg hover:bg-gray-800 transition-all duration-200 shadow-lg hover:shadow-xl transform hover:-translate-y-0.5" do %>
|
||||
Plus d'événements à Paris
|
||||
<i data-lucide="arrow-right" class="w-5 h-5 ml-2"></i>
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="text-center py-12">
|
||||
<div class="w-24 h-24 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<i data-lucide="calendar-x" class="w-12 h-12 text-gray-400"></i>
|
||||
<!-- Empty State -->
|
||||
<div class="text-center py-16">
|
||||
<div class="w-24 h-24 bg-gradient-to-br from-purple-100 to-blue-100 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<i data-lucide="calendar-x" class="w-12 h-12 text-purple-600"></i>
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold text-gray-900 mb-4">Aucun événement disponible</h3>
|
||||
<p class="text-gray-600 mb-6">Les événements arrivent bientôt. Inscrivez-vous pour être notifié!</p>
|
||||
<%= link_to new_user_registration_path, class: "bg-purple-600 text-white px-8 py-4 rounded-full font-semibold text-lg hover:bg-purple-700 transition-colors inline-flex items-center justify-center" do %>
|
||||
<p class="text-gray-600 mb-8 max-w-md mx-auto">Les événements arrivent bientôt. Inscrivez-vous pour être notifié des prochaines sorties!</p>
|
||||
<%= link_to new_user_registration_path, class: "bg-purple-600 text-white px-8 py-4 rounded-full font-semibold text-lg hover:bg-purple-700 transition-all duration-200 inline-flex items-center justify-center shadow-lg hover:shadow-xl transform hover:-translate-y-0.5" do %>
|
||||
<i data-lucide="bell" class="w-5 h-5 mr-2"></i>
|
||||
Être notifié
|
||||
<% end %>
|
||||
@@ -179,29 +184,29 @@
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 lg:grid-cols-4 gap-8 text-center">
|
||||
<div class="group">
|
||||
<div class="text-4xl lg:text-5xl font-bold text-purple-600 mb-2">
|
||||
<div class="group transform transition-all duration-300 hover:scale-105">
|
||||
<div class="text-4xl lg:text-5xl font-bold text-purple-600 mb-2 transition-colors group-hover:text-purple-700">
|
||||
<%= @total_events %>+
|
||||
</div>
|
||||
<div class="text-gray-600 font-medium">Événements organisés</div>
|
||||
</div>
|
||||
|
||||
<div class="group">
|
||||
<div class="text-4xl lg:text-5xl font-bold text-purple-600 mb-2">
|
||||
<div class="group transform transition-all duration-300 hover:scale-105">
|
||||
<div class="text-4xl lg:text-5xl font-bold text-purple-600 mb-2 transition-colors group-hover:text-purple-700">
|
||||
<%= (@total_users / 100.0).round(1) %>k+
|
||||
</div>
|
||||
<div class="text-gray-600 font-medium">Membres actifs</div>
|
||||
</div>
|
||||
|
||||
<div class="group">
|
||||
<div class="text-4xl lg:text-5xl font-bold text-purple-600 mb-2">
|
||||
<div class="group transform transition-all duration-300 hover:scale-105">
|
||||
<div class="text-4xl lg:text-5xl font-bold text-purple-600 mb-2 transition-colors group-hover:text-purple-700">
|
||||
<%= @events_this_month %>
|
||||
</div>
|
||||
<div class="text-gray-600 font-medium">Ce mois-ci</div>
|
||||
</div>
|
||||
|
||||
<div class="group">
|
||||
<div class="text-4xl lg:text-5xl font-bold text-purple-600 mb-2">
|
||||
<div class="group transform transition-all duration-300 hover:scale-105">
|
||||
<div class="text-4xl lg:text-5xl font-bold text-purple-600 mb-2 transition-colors group-hover:text-purple-700">
|
||||
98%
|
||||
</div>
|
||||
<div class="text-gray-600 font-medium">Satisfaction</div>
|
||||
@@ -211,8 +216,11 @@
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="py-16 bg-gray-900">
|
||||
<div class="container mx-auto px-4 text-center">
|
||||
<section class="py-16 bg-gray-900 relative overflow-hidden">
|
||||
<!-- Background decoration -->
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-gray-900 via-gray-800 to-gray-900"></div>
|
||||
|
||||
<div class="relative container mx-auto px-4 text-center">
|
||||
<h2 class="text-3xl lg:text-4xl font-bold text-white mb-6">
|
||||
Prêt à découvrir votre prochain événement ?
|
||||
</h2>
|
||||
@@ -222,14 +230,14 @@
|
||||
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center max-w-lg mx-auto">
|
||||
<%= link_to events_path,
|
||||
class: "w-full sm:flex-1 bg-white text-gray-900 px-6 py-3 rounded-full font-semibold text-base hover:bg-gray-100 transition-all duration-200 inline-flex items-center justify-center shadow-lg" do %>
|
||||
class: "w-full sm:flex-1 bg-white text-gray-900 px-6 py-3 rounded-full font-semibold text-base hover:bg-gray-100 transition-all duration-200 inline-flex items-center justify-center shadow-lg hover:shadow-xl transform hover:-translate-y-0.5" do %>
|
||||
<i data-lucide="search" class="w-4 h-4 mr-2"></i>
|
||||
Découvrir les événements
|
||||
<% end %>
|
||||
|
||||
<% unless user_signed_in? %>
|
||||
<%= link_to new_user_registration_path,
|
||||
class: "w-full sm:flex-1 border-2 border-white text-white px-6 py-3 rounded-full font-semibold text-base hover:bg-white hover:text-gray-900 transition-all duration-200 inline-flex items-center justify-center" do %>
|
||||
class: "w-full sm:flex-1 border-2 border-white text-white px-6 py-3 rounded-full font-semibold text-base hover:bg-white hover:text-gray-900 transition-all duration-200 inline-flex items-center justify-center transform hover:-translate-y-0.5" do %>
|
||||
<i data-lucide="user-plus" class="w-4 h-4 mr-2"></i>
|
||||
Créer mon compte
|
||||
<% end %>
|
||||
@@ -238,26 +246,3 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.hero-landing {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero-landing::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.hero-gradient {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
<h1 class="text-3xl font-bold text-gray-900 mb-2">Mes événements</h1>
|
||||
<p class="text-gray-600">Gérez tous vos événements depuis cette interface</p>
|
||||
</div>
|
||||
<%= link_to new_promoter_event_path, class: "inline-flex items-center px-6 py-3 bg-black text-white font-medium rounded-lg hover:bg-gray-800 transition-colors duration-200" do %>
|
||||
<%= link_to new_promoter_event_path, class: "inline-flex items-center px-6 py-3 bg-gray-900 text-white font-medium rounded-lg hover:bg-gray-800 transition-colors duration-200" do %>
|
||||
<i data-lucide="plus" class="w-4 h-4 mr-2"></i>
|
||||
Créer un événement
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if @events.any? %>
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
|
||||
<div class="bg-white rounded-2xl shadow-xl border border-gray-200 overflow-hidden">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full">
|
||||
<thead class="bg-gray-50 border-b border-gray-200">
|
||||
@@ -121,13 +121,13 @@
|
||||
<%= paginate @events if respond_to?(:paginate) %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="bg-white rounded-lg border-2 border-dashed border-gray-300 p-12 text-center">
|
||||
<div class="bg-white rounded-2xl border-2 border-dashed border-gray-300 p-12 text-center">
|
||||
<div class="mx-auto h-24 w-24 rounded-full bg-gray-100 flex items-center justify-center mb-6">
|
||||
<i data-lucide="calendar-plus" class="w-12 h-12 text-gray-400"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2">Aucun événement</h3>
|
||||
<p class="text-gray-500 mb-6">Vous n'avez pas encore créé d'événement. Commencez dès maintenant !</p>
|
||||
<%= link_to new_promoter_event_path, class: "inline-flex items-center px-6 py-3 bg-black text-white font-medium rounded-lg hover:bg-gray-800 transition-colors duration-200" do %>
|
||||
<%= link_to new_promoter_event_path, class: "inline-flex items-center px-6 py-3 bg-gray-900 text-white font-medium rounded-lg hover:bg-gray-800 transition-colors duration-200" do %>
|
||||
<i data-lucide="plus" class="w-4 h-4 mr-2"></i>
|
||||
Créer mon premier événement
|
||||
<% end %>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<div class="mb-8">
|
||||
<% case @event.state %>
|
||||
<% when "draft" %>
|
||||
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4">
|
||||
<div class="bg-gray-50 border border-gray-200 rounded-2xl p-4">
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="edit-3" class="w-5 h-5 text-gray-400 mr-3"></i>
|
||||
<div>
|
||||
@@ -64,7 +64,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<% when "published" %>
|
||||
<div class="bg-green-50 border border-green-200 rounded-lg p-4">
|
||||
<div class="bg-green-50 border border-green-200 rounded-2xl p-4">
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="eye" class="w-5 h-5 text-green-400 mr-3"></i>
|
||||
<div>
|
||||
@@ -79,7 +79,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<% when "canceled" %>
|
||||
<div class="bg-red-50 border border-red-200 rounded-lg p-4">
|
||||
<div class="bg-red-50 border border-red-200 rounded-2xl p-4">
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="x-circle" class="w-5 h-5 text-red-400 mr-3"></i>
|
||||
<div>
|
||||
@@ -89,7 +89,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<% when "sold_out" %>
|
||||
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4">
|
||||
<div class="bg-blue-50 border border-blue-200 rounded-2xl p-4">
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="users" class="w-5 h-5 text-blue-400 mr-3"></i>
|
||||
<div>
|
||||
@@ -101,7 +101,7 @@
|
||||
<% end %>
|
||||
|
||||
<% if @event.featured? %>
|
||||
<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-4 mt-4">
|
||||
<div class="bg-yellow-50 border border-yellow-200 rounded-2xl p-4 mt-4">
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="star" class="w-5 h-5 text-yellow-400 mr-3"></i>
|
||||
<div>
|
||||
@@ -119,13 +119,13 @@
|
||||
<div class="lg:col-span-2 space-y-8">
|
||||
<!-- Event image -->
|
||||
<% if @event.image.present? %>
|
||||
<div class="aspect-video bg-gray-100 rounded-lg overflow-hidden">
|
||||
<div class="aspect-video bg-gray-100 rounded-2xl overflow-hidden">
|
||||
<img src="<%= @event.image %>" alt="<%= @event.name %>" class="w-full h-full object-cover">
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<!-- Description -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<div class="bg-white rounded-2xl border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Description</h3>
|
||||
<div class="prose prose-gray max-w-none">
|
||||
<%= simple_format(@event.description) %>
|
||||
@@ -133,7 +133,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Location details -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<div class="bg-white rounded-2xl border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Lieu</h3>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-start space-x-3">
|
||||
@@ -154,7 +154,7 @@
|
||||
<!-- Sidebar -->
|
||||
<div class="space-y-6">
|
||||
<!-- Event stats -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<div class="bg-white rounded-2xl border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Statistiques</h3>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
@@ -175,7 +175,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Event info -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<div class="bg-white rounded-2xl border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Informations</h3>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
@@ -206,7 +206,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Quick actions -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<div class="bg-white rounded-2xl border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Actions rapides</h3>
|
||||
<div class="space-y-3">
|
||||
<%= link_to promoter_event_ticket_types_path(@event), class: "w-full inline-flex items-center px-4 py-2 bg-purple-600 text-white font-medium rounded-lg hover:bg-purple-700 transition-colors duration-200" do %>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<%= link_to @event.name, promoter_event_path(@event), class: "text-purple-600 hover:text-purple-800" %>
|
||||
</p>
|
||||
</div>
|
||||
<%= link_to new_promoter_event_ticket_type_path(@event), class: "inline-flex items-center px-6 py-3 bg-black text-white font-medium rounded-lg hover:bg-gray-800 transition-colors duration-200" do %>
|
||||
<%= link_to new_promoter_event_ticket_type_path(@event), class: "inline-flex items-center px-6 py-3 bg-gray-900 text-white font-medium rounded-lg hover:bg-gray-800 transition-colors duration-200" do %>
|
||||
<i data-lucide="plus" class="w-4 h-4 mr-2"></i>
|
||||
Nouveau type
|
||||
<% end %>
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
<!-- Event status info -->
|
||||
<% if @event.draft? %>
|
||||
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4 mb-6">
|
||||
<div class="bg-gray-50 border border-gray-200 rounded-2xl p-4 mb-6">
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="info" class="w-5 h-5 text-gray-400 mr-3"></i>
|
||||
<p class="text-sm text-gray-600">
|
||||
@@ -34,7 +34,7 @@
|
||||
<% if @ticket_types.any? %>
|
||||
<div class="grid gap-6">
|
||||
<% @ticket_types.each do |ticket_type| %>
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6 hover:shadow-md transition-shadow duration-200">
|
||||
<div class="bg-white rounded-2xl border border-gray-200 p-6 hover:shadow-md transition-shadow duration-200">
|
||||
<div class="flex items-start justify-between">
|
||||
<!-- Ticket type info -->
|
||||
<div class="flex-1">
|
||||
@@ -155,13 +155,13 @@
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="bg-white rounded-lg border-2 border-dashed border-gray-300 p-12 text-center">
|
||||
<div class="bg-white rounded-2xl border-2 border-dashed border-gray-300 p-12 text-center">
|
||||
<div class="mx-auto h-24 w-24 rounded-full bg-gray-100 flex items-center justify-center mb-6">
|
||||
<i data-lucide="ticket" class="w-12 h-12 text-gray-400"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2">Aucun type de billet</h3>
|
||||
<p class="text-gray-500 mb-6">Créez des types de billets pour permettre aux utilisateurs d'acheter des places pour votre événement.</p>
|
||||
<%= link_to new_promoter_event_ticket_type_path(@event), class: "inline-flex items-center px-6 py-3 bg-black text-white font-medium rounded-lg hover:bg-gray-800 transition-colors duration-200" do %>
|
||||
<%= link_to new_promoter_event_ticket_type_path(@event), class: "inline-flex items-center px-6 py-3 bg-gray-900 text-white font-medium rounded-lg hover:bg-gray-800 transition-colors duration-200" do %>
|
||||
<i data-lucide="plus" class="w-4 h-4 mr-2"></i>
|
||||
Créer mon premier type de billet
|
||||
<% end %>
|
||||
|
||||
@@ -206,7 +206,7 @@
|
||||
</script>
|
||||
|
||||
<button onclick="redirectToCheckout(this)"
|
||||
class="w-full bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-700 hover:to-indigo-700 text-white font-medium py-4 px-6 rounded-xl shadow-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 transform hover:-translate-y-0.5">
|
||||
class="w-full btn btn-primary py-4 px-6 rounded-xl shadow-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 transform hover:-translate-y-0.5">
|
||||
<span class="flex items-center justify-center">
|
||||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"/>
|
||||
|
||||
@@ -185,7 +185,7 @@
|
||||
"px-6 py-3 border border-gray-300 text-gray-700 rounded-xl hover:bg-gray-50 text-center font-medium transition-colors duration-200" %>
|
||||
<%= form.submit "Procéder au paiement",
|
||||
class:
|
||||
"flex-1 bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-700 hover:to-indigo-700 text-white font-medium py-3 px-6 rounded-xl shadow-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 transform hover:-translate-y-0.5" %>
|
||||
"flex-1 btn btn-primary py-3 px-6 rounded-xl shadow-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 transform hover:-translate-y-0.5" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
|
||||
<div class="flex items-center space-x-2">
|
||||
<%= link_to ticket_download_path(ticket.qr_code, format: :pdf),
|
||||
class: "inline-flex items-center px-4 py-2 bg-gradient-to-r from-purple-600 to-indigo-600 text-white rounded-lg hover:from-purple-700 hover:to-indigo-700 transition-all duration-200 text-sm font-medium shadow-sm" do %>
|
||||
class: "inline-flex items-center px-4 py-2 btn btn-primary rounded-lg transition-all duration-200 text-sm font-medium shadow-sm" do %>
|
||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
|
||||
</svg>
|
||||
@@ -129,7 +129,7 @@
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<%= link_to dashboard_path,
|
||||
class: "inline-flex items-center justify-center px-6 py-3 bg-gradient-to-r from-purple-600 to-indigo-600 text-white rounded-xl hover:from-purple-700 hover:to-indigo-700 transition-all duration-200 font-medium shadow-sm" do %>
|
||||
class: "inline-flex items-center justify-center px-6 py-3 btn btn-primary rounded-xl transition-all duration-200 font-medium shadow-sm" do %>
|
||||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path>
|
||||
</svg>
|
||||
|
||||
0
rule-tests/.gitkeep
Normal file
0
rule-tests/.gitkeep
Normal file
0
rules/.gitkeep
Normal file
0
rules/.gitkeep
Normal file
Reference in New Issue
Block a user