versione 1.0
This commit is contained in:
@@ -1,65 +1,76 @@
|
||||
/*
|
||||
* DESIGN: "Clinical Warmth"
|
||||
* Sezione registrazione/login: tabs con form eleganti
|
||||
* Sfondo bianco, accenti blu petrolio e verde acqua
|
||||
* Sezione registrazione/login visibile ma non ancora attiva.
|
||||
* Gli elementi restano leggibili, ma ogni interazione mostra
|
||||
* il messaggio "Servizio in corso di attivazione".
|
||||
*/
|
||||
import { useState } from "react";
|
||||
import { motion } from "framer-motion";
|
||||
import { useInView } from "framer-motion";
|
||||
import { motion, useInView } from "framer-motion";
|
||||
import { useRef } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { User, Mail, Lock, Eye, EyeOff, CheckCircle2, PawPrint } from "lucide-react";
|
||||
import { User, Mail, Lock, Eye, CheckCircle2, PawPrint, Clock3 } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
const benefits = [
|
||||
"Storico visite e referti digitali",
|
||||
"Promemoria vaccinazioni automatici",
|
||||
"Prenotazioni online prioritarie",
|
||||
"Comunicazioni dirette con il veterinario",
|
||||
"Gestione di piu animali domestici",
|
||||
];
|
||||
|
||||
function showActivationToast() {
|
||||
toast.info("Servizio in corso di attivazione", {
|
||||
description: "L'area riservata sara disponibile a breve.",
|
||||
});
|
||||
}
|
||||
|
||||
function DisabledInput({
|
||||
icon,
|
||||
type,
|
||||
placeholder,
|
||||
}: {
|
||||
icon: React.ComponentType<{ size?: number; className?: string }>;
|
||||
type: string;
|
||||
placeholder: string;
|
||||
}) {
|
||||
const Icon = icon;
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<Icon size={15} className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400" />
|
||||
<input
|
||||
type={type}
|
||||
placeholder={placeholder}
|
||||
disabled
|
||||
className="w-full cursor-not-allowed rounded-lg border border-gray-200 bg-gray-50/90 py-2.5 pl-9 pr-3 text-sm text-gray-400 opacity-90"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function AuthSection() {
|
||||
const ref = useRef(null);
|
||||
const isInView = useInView(ref, { once: true, margin: "-80px" });
|
||||
const [tab, setTab] = useState<"login" | "register">("register");
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const [registered, setRegistered] = useState(false);
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (tab === "register") {
|
||||
setRegistered(true);
|
||||
toast.success("Registrazione completata!", {
|
||||
description: "Benvenuto nella Clinica Veterinaria Formiginese.",
|
||||
});
|
||||
} else {
|
||||
toast.success("Accesso effettuato!", {
|
||||
description: "Bentornato nella tua area personale.",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const benefits = [
|
||||
"Storico visite e referti digitali",
|
||||
"Promemoria vaccinazioni automatici",
|
||||
"Prenotazioni online prioritarie",
|
||||
"Comunicazioni dirette con il veterinario",
|
||||
"Gestione di più animali domestici",
|
||||
];
|
||||
|
||||
return (
|
||||
<section id="registrazione" className="py-20 md:py-28 bg-white">
|
||||
<section id="registrazione" className="bg-white py-20 md:py-28">
|
||||
<div className="container">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center">
|
||||
{/* Colonna sinistra: benefici */}
|
||||
<div className="grid grid-cols-1 items-center gap-16 lg:grid-cols-2">
|
||||
<motion.div
|
||||
ref={ref}
|
||||
initial={{ opacity: 0, x: -30 }}
|
||||
animate={isInView ? { opacity: 1, x: 0 } : {}}
|
||||
transition={{ duration: 0.8 }}
|
||||
>
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="w-12 h-0.5 bg-[#4ECDC4]" />
|
||||
<span className="text-[#4ECDC4] text-sm font-semibold uppercase tracking-widest">
|
||||
<div className="mb-4 flex items-center gap-3">
|
||||
<div className="h-0.5 w-12 bg-[#4ECDC4]" />
|
||||
<span className="text-sm font-semibold uppercase tracking-widest text-[#4ECDC4]">
|
||||
Area Personale
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<h2
|
||||
className="text-[#1B4F72] mb-6"
|
||||
className="mb-6 text-[#1B4F72]"
|
||||
style={{
|
||||
fontFamily: "'Cormorant Garamond', serif",
|
||||
fontSize: "clamp(2rem, 4vw, 3rem)",
|
||||
@@ -67,210 +78,148 @@ export default function AuthSection() {
|
||||
lineHeight: 1.2,
|
||||
}}
|
||||
>
|
||||
Registrati e gestisci{" "}
|
||||
Accedi e gestisci{" "}
|
||||
<span className="italic">la salute del tuo animale</span>
|
||||
</h2>
|
||||
|
||||
<p className="text-gray-600 leading-relaxed mb-8 text-base">
|
||||
Crea il tuo profilo personale per accedere a tutti i servizi digitali della clinica.
|
||||
Tieni traccia della storia clinica del tuo animale, ricevi promemoria e prenota
|
||||
le visite in pochi click.
|
||||
<p className="mb-8 text-base leading-relaxed text-gray-600">
|
||||
L'area riservata e la registrazione online sono in fase di attivazione.
|
||||
Qui i clienti potranno gestire i propri dati, consultare lo storico e accedere
|
||||
ai servizi digitali della clinica in uno spazio personale dedicato.
|
||||
</p>
|
||||
|
||||
{/* Benefits list */}
|
||||
<div className="space-y-3 mb-8">
|
||||
<div className="mb-8 space-y-3">
|
||||
{benefits.map((benefit) => (
|
||||
<div key={benefit} className="flex items-center gap-3">
|
||||
<div className="w-6 h-6 rounded-full bg-[#4ECDC4]/15 flex items-center justify-center flex-shrink-0">
|
||||
<div className="flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-full bg-[#4ECDC4]/15">
|
||||
<CheckCircle2 size={14} className="text-[#4ECDC4]" />
|
||||
</div>
|
||||
<span className="text-gray-700 text-sm">{benefit}</span>
|
||||
<span className="text-sm text-gray-700">{benefit}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Decorazione */}
|
||||
<div className="bg-[#F5F0E8] rounded-2xl p-6 flex items-center gap-4">
|
||||
<div className="w-14 h-14 rounded-full bg-[#1B4F72] flex items-center justify-center flex-shrink-0">
|
||||
<div className="flex items-center gap-4 rounded-2xl bg-[#F5F0E8] p-6">
|
||||
<div className="flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-full bg-[#1B4F72]">
|
||||
<PawPrint size={24} className="text-[#4ECDC4]" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-[#1B4F72] font-semibold text-sm">Già più di 500 famiglie</p>
|
||||
<p className="text-gray-600 text-xs mt-0.5">
|
||||
si affidano alla nostra clinica per la cura dei loro animali
|
||||
<p className="text-sm font-semibold text-[#1B4F72]">Servizio in attivazione</p>
|
||||
<p className="mt-0.5 text-xs text-gray-600">
|
||||
La clinica sta completando la configurazione dell'area riservata per offrirti
|
||||
un accesso semplice e sicuro.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* Colonna destra: form */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: 30 }}
|
||||
animate={isInView ? { opacity: 1, x: 0 } : {}}
|
||||
transition={{ duration: 0.8, delay: 0.2 }}
|
||||
>
|
||||
{registered ? (
|
||||
<div className="bg-[#F5F0E8] rounded-2xl p-8 text-center shadow-sm">
|
||||
<div className="w-16 h-16 rounded-full bg-[#4ECDC4]/15 flex items-center justify-center mx-auto mb-4">
|
||||
<CheckCircle2 size={32} className="text-[#4ECDC4]" />
|
||||
</div>
|
||||
<h3
|
||||
className="text-[#1B4F72] mb-2"
|
||||
style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: "1.8rem" }}
|
||||
<div className="relative overflow-hidden rounded-2xl border border-gray-100 bg-white shadow-lg">
|
||||
<div className="flex border-b border-gray-100">
|
||||
<button
|
||||
type="button"
|
||||
disabled
|
||||
className="flex-1 cursor-not-allowed border-b-2 border-[#4ECDC4] bg-[#F5F0E8]/50 py-4 text-sm font-semibold text-[#1B4F72]"
|
||||
>
|
||||
Benvenuto!
|
||||
</h3>
|
||||
<p className="text-gray-600 text-sm mb-6">
|
||||
La tua registrazione è avvenuta con successo. Ora puoi accedere a tutti i servizi
|
||||
della tua area personale.
|
||||
</p>
|
||||
<Button
|
||||
className="bg-[#1B4F72] hover:bg-[#163d5a] text-white"
|
||||
onClick={() => setRegistered(false)}
|
||||
Registrati
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
disabled
|
||||
className="flex-1 cursor-not-allowed py-4 text-sm font-semibold text-gray-400"
|
||||
>
|
||||
Vai all'area personale
|
||||
</Button>
|
||||
Accedi
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-white rounded-2xl shadow-lg border border-gray-100 overflow-hidden">
|
||||
{/* Tabs */}
|
||||
<div className="flex border-b border-gray-100">
|
||||
{(["register", "login"] as const).map((t) => (
|
||||
<button
|
||||
key={t}
|
||||
onClick={() => setTab(t)}
|
||||
className={`flex-1 py-4 text-sm font-semibold transition-all duration-200 ${
|
||||
tab === t
|
||||
? "text-[#1B4F72] border-b-2 border-[#4ECDC4] bg-[#F5F0E8]/50"
|
||||
: "text-gray-400 hover:text-gray-600"
|
||||
}`}
|
||||
>
|
||||
{t === "register" ? "Registrati" : "Accedi"}
|
||||
</button>
|
||||
))}
|
||||
|
||||
<div className="p-6 md:p-8">
|
||||
<div className="mb-5 flex items-center gap-3 rounded-xl border border-[#E4D7C6] bg-[#FFF9F1] px-4 py-3">
|
||||
<div className="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full bg-[#A95F3A]/12">
|
||||
<Clock3 size={18} className="text-[#A95F3A]" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-semibold text-[#1B4F72]">Servizio in corso di attivazione</p>
|
||||
<p className="text-xs text-gray-600">
|
||||
Registrazione e accesso saranno disponibili a breve.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="p-6 md:p-8 space-y-4">
|
||||
{tab === "register" && (
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="text-xs font-semibold text-gray-600 uppercase tracking-wide block mb-1.5">
|
||||
Nome
|
||||
</label>
|
||||
<div className="relative">
|
||||
<User size={15} className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400" />
|
||||
<input
|
||||
type="text"
|
||||
required
|
||||
placeholder="Mario"
|
||||
className="w-full pl-9 pr-3 py-2.5 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-[#4ECDC4] focus:border-transparent transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-xs font-semibold text-gray-600 uppercase tracking-wide block mb-1.5">
|
||||
Cognome
|
||||
</label>
|
||||
<div className="relative">
|
||||
<User size={15} className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400" />
|
||||
<input
|
||||
type="text"
|
||||
required
|
||||
placeholder="Rossi"
|
||||
className="w-full pl-9 pr-3 py-2.5 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-[#4ECDC4] focus:border-transparent transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-4 opacity-75">
|
||||
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||
<div>
|
||||
<label className="mb-1.5 block text-xs font-semibold uppercase tracking-wide text-gray-600">
|
||||
Nome
|
||||
</label>
|
||||
<DisabledInput icon={User} type="text" placeholder="Mario" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<label className="text-xs font-semibold text-gray-600 uppercase tracking-wide block mb-1.5">
|
||||
Email
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Mail size={15} className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400" />
|
||||
<input
|
||||
type="email"
|
||||
required
|
||||
placeholder="mario.rossi@email.it"
|
||||
className="w-full pl-9 pr-3 py-2.5 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-[#4ECDC4] focus:border-transparent transition-all"
|
||||
/>
|
||||
<div>
|
||||
<label className="mb-1.5 block text-xs font-semibold uppercase tracking-wide text-gray-600">
|
||||
Cognome
|
||||
</label>
|
||||
<DisabledInput icon={User} type="text" placeholder="Rossi" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="text-xs font-semibold text-gray-600 uppercase tracking-wide block mb-1.5">
|
||||
<label className="mb-1.5 block text-xs font-semibold uppercase tracking-wide text-gray-600">
|
||||
Email
|
||||
</label>
|
||||
<DisabledInput icon={Mail} type="email" placeholder="mario.rossi@email.it" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="mb-1.5 block text-xs font-semibold uppercase tracking-wide text-gray-600">
|
||||
Password
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Lock size={15} className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400" />
|
||||
<input
|
||||
type={showPassword ? "text" : "password"}
|
||||
required
|
||||
type="password"
|
||||
placeholder="••••••••"
|
||||
className="w-full pl-9 pr-10 py-2.5 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-[#4ECDC4] focus:border-transparent transition-all"
|
||||
disabled
|
||||
className="w-full cursor-not-allowed rounded-lg border border-gray-200 bg-gray-50/90 py-2.5 pl-9 pr-10 text-sm text-gray-400 opacity-90"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600"
|
||||
>
|
||||
{showPassword ? <EyeOff size={15} /> : <Eye size={15} />}
|
||||
</button>
|
||||
<span className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400">
|
||||
<Eye size={15} />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{tab === "register" && (
|
||||
<div className="flex items-start gap-2 pt-1">
|
||||
<input
|
||||
type="checkbox"
|
||||
required
|
||||
id="privacy"
|
||||
className="mt-0.5 accent-[#4ECDC4]"
|
||||
/>
|
||||
<label htmlFor="privacy" className="text-xs text-gray-500 leading-relaxed">
|
||||
Accetto la{" "}
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#4ECDC4] hover:underline"
|
||||
onClick={() => toast.info("Privacy policy in arrivo")}
|
||||
>
|
||||
Privacy Policy
|
||||
</button>{" "}
|
||||
e i{" "}
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#4ECDC4] hover:underline"
|
||||
onClick={() => toast.info("Termini di servizio in arrivo")}
|
||||
>
|
||||
Termini di Servizio
|
||||
</button>
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-start gap-2 pt-1">
|
||||
<input
|
||||
type="checkbox"
|
||||
disabled
|
||||
className="mt-0.5 cursor-not-allowed accent-[#4ECDC4]"
|
||||
/>
|
||||
<p className="text-xs leading-relaxed text-gray-500">
|
||||
Accetto la Privacy Policy e i Termini di Servizio.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
className="w-full bg-[#1B4F72] hover:bg-[#163d5a] text-white font-bold py-3 text-base transition-all duration-300"
|
||||
type="button"
|
||||
disabled
|
||||
className="w-full cursor-not-allowed bg-[#1B4F72] py-3 text-base font-bold text-white opacity-70"
|
||||
>
|
||||
{tab === "register" ? "Crea il tuo account" : "Accedi all'area personale"}
|
||||
Crea il tuo account
|
||||
</Button>
|
||||
|
||||
{tab === "login" && (
|
||||
<p className="text-center text-xs text-gray-400">
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#4ECDC4] hover:underline"
|
||||
onClick={() => toast.info("Recupero password in arrivo")}
|
||||
>
|
||||
Password dimenticata?
|
||||
</button>
|
||||
</p>
|
||||
)}
|
||||
</form>
|
||||
<p className="text-center text-xs text-gray-400">Password dimenticata?</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Servizio in corso di attivazione"
|
||||
onClick={showActivationToast}
|
||||
className="absolute inset-0 z-10"
|
||||
/>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user