style: improve mobile responsiveness across layout and UI components
This commit is contained in:
@@ -1,3 +1,17 @@
|
||||
<html lang="pt-BR"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Smart Agenda</title> <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@400;500;600;700&display=swap" rel="stylesheet" /> </head> <body> <div id="root"></div> <script type="module" src="/src/main.tsx"></script> </body> </html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<title>Smart Agenda</title>
|
||||
<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@400;500;600;700&display=swap" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
|
||||
@@ -12,33 +12,33 @@ export const ProductList = ({
|
||||
products: Product[];
|
||||
onAdd?: (id: string) => void;
|
||||
}) => (
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
|
||||
<div className="grid grid-cols-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-3 sm:gap-6">
|
||||
{products.map((p) => {
|
||||
const lowStock = p.stock <= 3;
|
||||
return (
|
||||
<Card key={p.id} className="relative overflow-hidden border-none glass-card rounded-[2rem] group hover:shadow-2xl transition-all duration-300 flex flex-col">
|
||||
<div className="aspect-square bg-slate-50 flex items-center justify-center p-8 group-hover:bg-indigo-50 transition-colors">
|
||||
<Card key={p.id} className="relative overflow-hidden border-none glass-card rounded-2xl sm:rounded-[2rem] group hover:shadow-2xl transition-all duration-300 flex flex-col">
|
||||
<div className="aspect-square bg-slate-50 flex items-center justify-center p-4 sm:p-8 group-hover:bg-indigo-50 transition-colors">
|
||||
<Package size={48} className="text-slate-200 group-hover:text-indigo-200 transition-all group-hover:scale-110 duration-500" />
|
||||
|
||||
{lowStock && (
|
||||
<div className="absolute top-4 left-4">
|
||||
<Badge color="indigo" variant="solid" className="text-[9px] px-2 py-0.5 font-black uppercase tracking-widest shadow-lg animate-pulse">
|
||||
Últimas Unidades
|
||||
<div className="absolute top-2 left-2 sm:top-4 sm:left-4">
|
||||
<Badge color="indigo" variant="solid" className="text-[8px] sm:text-[9px] px-1.5 sm:px-2 py-0.5 font-black uppercase tracking-widest shadow-lg animate-pulse">
|
||||
Últimas
|
||||
</Badge>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="p-5 flex-1 flex flex-col gap-4">
|
||||
<div className="p-3 sm:p-5 flex-1 flex flex-col gap-3 sm:gap-4">
|
||||
<div className="space-y-1">
|
||||
<h3 className="font-black text-slate-900 text-base tracking-tight leading-tight group-hover:text-indigo-600 transition-colors uppercase italic truncate">{p.name}</h3>
|
||||
<div className="text-xs font-bold text-slate-400 uppercase tracking-widest">
|
||||
<h3 className="font-black text-slate-900 text-sm sm:text-base tracking-tight leading-tight group-hover:text-indigo-600 transition-colors uppercase italic truncate">{p.name}</h3>
|
||||
<div className="text-[10px] sm:text-xs font-bold text-slate-400 uppercase tracking-widest">
|
||||
{p.stock} em stock
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-auto pt-4 border-t border-slate-50 flex flex-col gap-3">
|
||||
<div className="text-xl font-black text-slate-900 tracking-tighter">
|
||||
<div className="mt-auto pt-3 sm:pt-4 border-t border-slate-50 flex flex-col gap-2 sm:gap-3">
|
||||
<div className="text-lg sm:text-xl font-black text-slate-900 tracking-tighter">
|
||||
{currency(p.price)}
|
||||
</div>
|
||||
|
||||
@@ -46,7 +46,7 @@ export const ProductList = ({
|
||||
<Button
|
||||
onClick={() => onAdd(p.id)}
|
||||
disabled={p.stock <= 0}
|
||||
className="w-full h-10 bg-slate-900 hover:bg-slate-800 text-indigo-400 font-black rounded-xl shadow-lg shadow-slate-200 transition-all active:scale-95 uppercase tracking-widest text-[10px]"
|
||||
className="w-full h-9 sm:h-10 bg-slate-900 hover:bg-slate-800 text-indigo-400 font-black rounded-xl shadow-lg shadow-slate-200 transition-all active:scale-95 uppercase tracking-wider sm:tracking-widest text-[9px] sm:text-[10px]"
|
||||
>
|
||||
{p.stock > 0 ? 'Adicionar' : 'Esgotado'}
|
||||
</Button>
|
||||
@@ -58,8 +58,3 @@ export const ProductList = ({
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -11,12 +11,12 @@ export const ServiceList = ({
|
||||
services: Service[];
|
||||
onSelect?: (id: string) => void;
|
||||
}) => (
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
<div className="grid md:grid-cols-2 gap-4 sm:gap-6">
|
||||
{services.map((s) => (
|
||||
<Card key={s.id} className="p-6 border-none glass-card rounded-[2rem] group hover:shadow-2xl transition-all duration-300">
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<div className="flex-1 space-y-2">
|
||||
<h3 className="font-black text-slate-900 text-xl tracking-tight leading-tight group-hover:text-indigo-600 transition-colors uppercase italic">{s.name}</h3>
|
||||
<Card key={s.id} className="p-4 sm:p-6 border-none glass-card rounded-2xl sm:rounded-[2rem] group hover:shadow-2xl transition-all duration-300">
|
||||
<div className="flex items-start justify-between gap-3 sm:gap-4">
|
||||
<div className="flex-1 min-w-0 space-y-2">
|
||||
<h3 className="font-black text-slate-900 text-lg sm:text-xl tracking-tight leading-tight group-hover:text-indigo-600 transition-colors uppercase italic truncate">{s.name}</h3>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex items-center gap-1.5 px-2 py-1 bg-slate-100 rounded-lg text-xs font-bold text-slate-500 uppercase">
|
||||
<Clock size={12} />
|
||||
@@ -24,19 +24,19 @@ export const ServiceList = ({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-2xl font-black text-slate-900 tracking-tighter bg-indigo-50 px-3 py-1 rounded-xl border border-indigo-100">
|
||||
<div className="text-xl sm:text-2xl font-black text-slate-900 tracking-tighter bg-indigo-50 px-2 sm:px-3 py-1 rounded-xl border border-indigo-100 whitespace-nowrap shrink-0">
|
||||
{currency(s.price)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{onSelect && (
|
||||
<div className="mt-6 pt-6 border-t border-slate-100 flex items-center justify-between gap-4">
|
||||
<p className="text-xs font-medium text-slate-400 max-w-[150px]">Lugar disponível hoje</p>
|
||||
<div className="mt-4 sm:mt-6 pt-4 sm:pt-6 border-t border-slate-100 flex items-center justify-between gap-3 sm:gap-4">
|
||||
<p className="text-xs font-medium text-slate-400 max-w-[100px] sm:max-w-[150px] shrink-0">Lugar disponível hoje</p>
|
||||
<Button
|
||||
onClick={() => onSelect(s.id)}
|
||||
className="flex-1 h-11 bg-slate-900 hover:bg-slate-800 text-indigo-400 font-black rounded-xl shadow-lg shadow-slate-200 transition-all active:scale-95 uppercase tracking-widest text-xs"
|
||||
className="flex-1 min-w-0 h-10 sm:h-11 bg-slate-900 hover:bg-slate-800 text-indigo-400 font-black rounded-xl shadow-lg shadow-slate-200 transition-all active:scale-95 uppercase tracking-wider sm:tracking-widest text-[10px] sm:text-xs truncate px-3 sm:px-4"
|
||||
>
|
||||
Reservar Agora
|
||||
Reservar
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
@@ -44,4 +44,3 @@ export const ServiceList = ({
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ import { Button } from './ui/button';
|
||||
|
||||
export const ShopCard = ({ shop }: { shop: BarberShop }) => {
|
||||
return (
|
||||
<Card className="overflow-hidden border-none glass-card rounded-[2.5rem] group hover:shadow-2xl hover:shadow-slate-200/60 transition-all duration-500">
|
||||
<div className="relative h-44 overflow-hidden">
|
||||
<Card className="overflow-hidden border-none glass-card rounded-2xl sm:rounded-[2.5rem] group hover:shadow-2xl hover:shadow-slate-200/60 transition-all duration-500">
|
||||
<div className="relative h-36 sm:h-44 overflow-hidden">
|
||||
{shop.imageUrl ? (
|
||||
<img
|
||||
src={shop.imageUrl}
|
||||
@@ -22,42 +22,42 @@ export const ShopCard = ({ shop }: { shop: BarberShop }) => {
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-slate-900/80 via-transparent to-transparent opacity-60 group-hover:opacity-40 transition-opacity" />
|
||||
|
||||
{/* Rating Badge */}
|
||||
<div className="absolute top-4 right-4 bg-slate-900/90 backdrop-blur-md border border-white/10 px-3 py-1 rounded-full flex items-center gap-1.5 shadow-xl">
|
||||
<Star size={14} className="fill-indigo-500 text-indigo-500" />
|
||||
<span className="text-white text-xs font-black tracking-wider">
|
||||
<div className="absolute top-3 right-3 sm:top-4 sm:right-4 bg-slate-900/90 backdrop-blur-md border border-white/10 px-2 sm:px-3 py-1 rounded-full flex items-center gap-1.5 shadow-xl">
|
||||
<Star size={12} className="fill-indigo-500 text-indigo-500" />
|
||||
<span className="text-white text-[10px] sm:text-xs font-black tracking-wider">
|
||||
{shop.rating ? shop.rating.toFixed(1) : '0.0'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-6 space-y-4">
|
||||
<div className="p-4 sm:p-6 space-y-3 sm:space-y-4">
|
||||
<div>
|
||||
<h2 className="text-slate-900 text-xl font-black tracking-tight group-hover:text-indigo-600 transition-colors truncate">
|
||||
<h2 className="text-slate-900 text-lg sm:text-xl font-black tracking-tight group-hover:text-indigo-600 transition-colors truncate">
|
||||
{shop.name}
|
||||
</h2>
|
||||
<div className="flex items-center gap-1.5 text-slate-500 mt-1">
|
||||
<MapPin size={14} className="text-indigo-600" />
|
||||
<MapPin size={14} className="text-indigo-600 shrink-0" />
|
||||
<p className="text-sm font-medium line-clamp-1">
|
||||
{shop.address || 'Endereço Indisponível'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between pt-2">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex -space-x-2">
|
||||
<div className="flex items-center justify-between pt-2 gap-2">
|
||||
<div className="flex items-center gap-2 sm:gap-3 min-w-0">
|
||||
<div className="flex -space-x-2 shrink-0">
|
||||
{[1, 2, 3].map(i => (
|
||||
<div key={i} className="w-7 h-7 rounded-full border-2 border-white bg-slate-100 flex items-center justify-center overflow-hidden">
|
||||
<User size={12} className="text-slate-400" />
|
||||
<div key={i} className="w-6 h-6 sm:w-7 sm:h-7 rounded-full border-2 border-white bg-slate-100 flex items-center justify-center overflow-hidden">
|
||||
<User size={10} className="text-slate-400" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<span className="text-xs font-bold text-slate-400 uppercase tracking-widest">
|
||||
<span className="text-[10px] sm:text-xs font-bold text-slate-400 uppercase tracking-wider sm:tracking-widest truncate">
|
||||
+{(shop.barbers || []).length} Barbeiros
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<Button asChild className="rounded-xl bg-slate-900 hover:bg-slate-800 text-indigo-400 font-bold px-5 h-10 shadow-lg shadow-slate-200 transition-all active:scale-95">
|
||||
<Button asChild className="rounded-xl bg-slate-900 hover:bg-slate-800 text-indigo-400 font-bold px-3 sm:px-5 h-9 sm:h-10 shadow-lg shadow-slate-200 transition-all active:scale-95 text-xs sm:text-sm shrink-0">
|
||||
<Link to={`/barbearia/${shop.id}`}>Reservar</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,7 @@ export const Header = () => {
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-30 bg-white/70 backdrop-blur-lg border-b border-slate-200/50 shadow-sm shadow-slate-200/20">
|
||||
<div className="mx-auto flex h-20 max-w-6xl items-center justify-between px-6">
|
||||
<div className="mx-auto flex h-16 sm:h-20 max-w-6xl items-center justify-between px-3 sm:px-6">
|
||||
<Link
|
||||
to="/"
|
||||
className="text-2xl font-black tracking-tighter text-slate-900 group flex items-center gap-2"
|
||||
|
||||
@@ -5,7 +5,7 @@ export function Shell() {
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<main className="mx-auto max-w-5xl px-4 py-6">
|
||||
<main className="mx-auto max-w-5xl px-3 sm:px-4 py-4 sm:py-6 overflow-x-hidden">
|
||||
<Outlet />
|
||||
</main>
|
||||
</>
|
||||
|
||||
@@ -15,6 +15,13 @@
|
||||
|
||||
* {
|
||||
@apply border-slate-200;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html, body {
|
||||
overflow-x: hidden;
|
||||
width: 100%;
|
||||
max-width: 100vw;
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -62,8 +69,3 @@
|
||||
@apply bg-gradient-to-br from-slate-800 via-slate-900 to-slate-950;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -101,14 +101,14 @@ export default function Booking() {
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto space-y-10 py-4 pb-20">
|
||||
<div className="max-w-4xl mx-auto space-y-6 sm:space-y-10 py-2 sm:py-4 pb-12 sm:pb-20">
|
||||
<header className="space-y-4 text-center">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-indigo-100 text-indigo-700 text-[10px] font-black uppercase tracking-widest">
|
||||
<Calendar size={10} fill="currentColor" />
|
||||
<span>Reserva Exclusiva</span>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<h1 className="text-4xl md:text-5xl font-black text-slate-900 tracking-tighter uppercase italic">
|
||||
<h1 className="text-2xl sm:text-4xl md:text-5xl font-black text-slate-900 tracking-tighter uppercase italic">
|
||||
Reservar em <span className="text-indigo-600 block md:inline">{shop.name}</span>
|
||||
</h1>
|
||||
<div className="flex items-center justify-center gap-2 text-slate-500 font-medium">
|
||||
@@ -129,7 +129,7 @@ export default function Booking() {
|
||||
if (s.completed || s.id < step) setStep(s.id);
|
||||
}}
|
||||
disabled={!s.completed && s.id > step}
|
||||
className={`w-12 h-12 rounded-2xl flex items-center justify-center border-2 transition-all duration-500 scale-100 active:scale-90 ${
|
||||
className={`w-10 h-10 sm:w-12 sm:h-12 rounded-xl sm:rounded-2xl flex items-center justify-center border-2 transition-all duration-500 scale-100 active:scale-90 ${
|
||||
s.active
|
||||
? 'bg-slate-900 border-slate-900 text-indigo-400 shadow-2xl shadow-slate-300 -translate-y-2'
|
||||
: s.completed
|
||||
@@ -137,9 +137,9 @@ export default function Booking() {
|
||||
: 'bg-white border-slate-200 text-slate-400'
|
||||
}`}
|
||||
>
|
||||
{s.completed && !s.active ? <CheckCircle2 size={24} /> : <s.icon size={24} />}
|
||||
{s.completed && !s.active ? <CheckCircle2 size={20} /> : <s.icon size={20} />}
|
||||
</button>
|
||||
<div className={`mt-3 text-[10px] font-black uppercase tracking-widest ${s.active ? 'text-slate-900' : 'text-slate-400'}`}>
|
||||
<div className={`mt-2 sm:mt-3 text-[8px] sm:text-[10px] font-black uppercase tracking-widest ${s.active ? 'text-slate-900' : 'text-slate-400'}`}>
|
||||
{s.label}
|
||||
</div>
|
||||
</div>
|
||||
@@ -147,9 +147,9 @@ export default function Booking() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Card className="p-2 border-none glass-card rounded-[3rem] shadow-2xl shadow-slate-200/50 overflow-hidden">
|
||||
<Card className="p-1.5 sm:p-2 border-none glass-card rounded-2xl sm:rounded-[3rem] shadow-2xl shadow-slate-200/50 overflow-hidden">
|
||||
{/* Dynamic Step Content */}
|
||||
<div className="p-8 md:p-12 space-y-10">
|
||||
<div className="p-4 sm:p-8 md:p-12 space-y-6 sm:space-y-10">
|
||||
|
||||
{/* Step Back Button */}
|
||||
{step > 1 && (
|
||||
@@ -166,7 +166,7 @@ export default function Booking() {
|
||||
{step === 1 && (
|
||||
<div className="space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500">
|
||||
<div className="space-y-2 text-center md:text-left">
|
||||
<h3 className="text-3xl font-black text-slate-900 tracking-tighter uppercase italic">1. Selecione o <span className="text-indigo-600">Serviço</span></h3>
|
||||
<h3 className="text-xl sm:text-3xl font-black text-slate-900 tracking-tighter uppercase italic">1. Selecione o <span className="text-indigo-600">Serviço</span></h3>
|
||||
<p className="text-slate-500 font-medium italic">O primeiro passo para o seu agendamento.</p>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
@@ -177,7 +177,7 @@ export default function Booking() {
|
||||
setService(s.id);
|
||||
setStep(2);
|
||||
}}
|
||||
className={`group p-6 rounded-[2rem] border-2 text-left transition-all duration-300 flex flex-col gap-4 ${
|
||||
className={`group p-4 sm:p-6 rounded-2xl sm:rounded-[2rem] border-2 text-left transition-all duration-300 flex flex-col gap-3 sm:gap-4 ${
|
||||
serviceId === s.id
|
||||
? 'border-slate-900 bg-slate-900 text-white shadow-2xl translate-y-[-4px]'
|
||||
: 'border-slate-50 bg-slate-50 hover:border-indigo-200 hover:bg-indigo-50/50'
|
||||
@@ -206,7 +206,7 @@ export default function Booking() {
|
||||
{step === 2 && (
|
||||
<div className="space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500">
|
||||
<div className="space-y-2 text-center md:text-left">
|
||||
<h3 className="text-3xl font-black text-slate-900 tracking-tighter uppercase italic">2. Escolha o <span className="text-indigo-600">Mestre</span></h3>
|
||||
<h3 className="text-xl sm:text-3xl font-black text-slate-900 tracking-tighter uppercase italic">2. Escolha o <span className="text-indigo-600">Mestre</span></h3>
|
||||
<p className="text-slate-500 font-medium italic">Selecione o artista que cuidará do seu visual.</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-6">
|
||||
@@ -217,13 +217,13 @@ export default function Booking() {
|
||||
setBarber(b.id);
|
||||
setStep(3);
|
||||
}}
|
||||
className={`group p-6 rounded-[2.5rem] border-2 text-center transition-all duration-300 flex flex-col items-center gap-5 ${
|
||||
className={`group p-4 sm:p-6 rounded-2xl sm:rounded-[2.5rem] border-2 text-center transition-all duration-300 flex flex-col items-center gap-3 sm:gap-5 ${
|
||||
barberId === b.id
|
||||
? 'border-slate-900 bg-slate-900 text-white shadow-2xl translate-y-[-4px]'
|
||||
: 'border-slate-50 bg-slate-50 hover:border-indigo-200 hover:bg-indigo-50/50'
|
||||
}`}
|
||||
>
|
||||
<div className={`w-32 h-32 rounded-[2rem] overflow-hidden border-4 transition-all duration-500 ${barberId === b.id ? 'border-indigo-500 rotate-3' : 'border-white group-hover:border-indigo-100'}`}>
|
||||
<div className={`w-20 h-20 sm:w-32 sm:h-32 rounded-2xl sm:rounded-[2rem] overflow-hidden border-4 transition-all duration-500 ${barberId === b.id ? 'border-indigo-500 rotate-3' : 'border-white group-hover:border-indigo-100'}`}>
|
||||
{b.imageUrl ? (
|
||||
<img src={b.imageUrl} alt={b.name} className="w-full h-full object-cover" />
|
||||
) : (
|
||||
@@ -247,7 +247,7 @@ export default function Booking() {
|
||||
{step === 3 && (
|
||||
<div className="space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500">
|
||||
<div className="space-y-2 text-center md:text-left">
|
||||
<h3 className="text-3xl font-black text-slate-900 tracking-tighter uppercase italic">3. Escolha o <span className="text-indigo-600">Horário</span></h3>
|
||||
<h3 className="text-xl sm:text-3xl font-black text-slate-900 tracking-tighter uppercase italic">3. Escolha o <span className="text-indigo-600">Horário</span></h3>
|
||||
<p className="text-slate-500 font-medium italic">Seu tempo é valioso. Escolha a data perfeita.</p>
|
||||
</div>
|
||||
<div className="max-w-md mx-auto relative">
|
||||
@@ -271,14 +271,14 @@ export default function Booking() {
|
||||
{step === 4 && (
|
||||
<div className="space-y-10 animate-in fade-in slide-in-from-bottom-4 duration-500">
|
||||
<div className="space-y-2 text-center md:text-left">
|
||||
<h3 className="text-3xl font-black text-slate-900 tracking-tighter uppercase italic">4. Escolha o <span className="text-indigo-600">Horário Privilegiado</span></h3>
|
||||
<h3 className="text-xl sm:text-3xl font-black text-slate-900 tracking-tighter uppercase italic">4. Escolha o <span className="text-indigo-600">Horário Privilegiado</span></h3>
|
||||
<p className="text-slate-500 font-medium italic">A pontualidade é a cortesia dos reis.</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col md:flex-row gap-6">
|
||||
{/* Left Side: Summary Sidebar */}
|
||||
<div className="w-full md:w-80 space-y-4">
|
||||
<div className="p-6 bg-slate-900 text-white rounded-[2rem] space-y-6 shadow-xl relative overflow-hidden">
|
||||
<div className="p-4 sm:p-6 bg-slate-900 text-white rounded-2xl sm:rounded-[2rem] space-y-4 sm:space-y-6 shadow-xl relative overflow-hidden">
|
||||
<div className="absolute top-0 right-0 w-32 h-32 bg-indigo-500/5 rounded-full blur-3xl -translate-y-1/2 translate-x-1/2" />
|
||||
<div className="space-y-4 relative z-10">
|
||||
<div className="space-y-1 border-b border-white/10 pb-4">
|
||||
|
||||
@@ -53,7 +53,7 @@ export default function Explore() {
|
||||
}, [shops, query, filter, sortBy]);
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto space-y-10 py-6">
|
||||
<div className="max-w-6xl mx-auto space-y-6 sm:space-y-10 py-4 sm:py-6">
|
||||
<section className="space-y-4 text-center md:text-left">
|
||||
<div className="flex flex-col gap-4 md:flex-row md:items-end md:justify-between">
|
||||
<div className="space-y-1">
|
||||
@@ -61,7 +61,7 @@ export default function Explore() {
|
||||
<Star size={10} fill="currentColor" />
|
||||
<span>As Nossas Barbearias</span>
|
||||
</div>
|
||||
<h1 className="text-4xl md:text-5xl font-black text-slate-900 tracking-tighter uppercase italic">
|
||||
<h1 className="text-2xl sm:text-4xl md:text-5xl font-black text-slate-900 tracking-tighter uppercase italic">
|
||||
Ver <span className="text-indigo-600">Barbearias</span>
|
||||
</h1>
|
||||
<p className="text-slate-500 font-medium max-w-md">Descubra barbearias exclusivas e reserve o seu próximo corte em segundos.</p>
|
||||
@@ -73,7 +73,7 @@ export default function Explore() {
|
||||
</section>
|
||||
|
||||
<div className="grid gap-8">
|
||||
<Card className="p-2 border-none glass-card rounded-[2.5rem] shadow-2xl shadow-slate-200/50">
|
||||
<Card className="p-1.5 sm:p-2 border-none glass-card rounded-2xl sm:rounded-[2.5rem] shadow-2xl shadow-slate-200/50">
|
||||
<div className="flex flex-col md:flex-row items-center gap-2 p-1">
|
||||
<div className="relative flex-1 w-full">
|
||||
<Search size={20} className="absolute left-5 top-1/2 -translate-y-1/2 text-slate-400" />
|
||||
@@ -81,24 +81,24 @@ export default function Explore() {
|
||||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
placeholder="Pesquisar por nome ou endereço..."
|
||||
className="h-14 pl-14 pr-6 bg-transparent border-none text-lg font-medium focus:ring-0 placeholder:text-slate-400"
|
||||
className="h-12 sm:h-14 pl-12 sm:pl-14 pr-4 sm:pr-6 bg-transparent border-none text-base sm:text-lg font-medium focus:ring-0 placeholder:text-slate-400"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="h-10 w-px bg-slate-200 hidden md:block" />
|
||||
|
||||
<div className="flex flex-wrap items-center gap-2 px-4 py-2 w-full md:w-auto">
|
||||
<div className="flex flex-wrap items-center gap-2 px-2 sm:px-4 py-2 w-full md:w-auto">
|
||||
<Chip
|
||||
active={filter === 'todas'}
|
||||
onClick={() => setFilter('todas')}
|
||||
className={`h-11 px-6 rounded-2xl font-bold uppercase tracking-tight transition-all ${filter === 'todas' ? '!bg-slate-900 !text-indigo-400 border-none shadow-lg' : 'bg-slate-100 text-slate-500 hover:bg-slate-200'}`}
|
||||
className={`h-9 sm:h-11 px-4 sm:px-6 rounded-xl sm:rounded-2xl font-bold uppercase tracking-tight transition-all text-xs sm:text-sm ${filter === 'todas' ? '!bg-slate-900 !text-indigo-400 border-none shadow-lg' : 'bg-slate-100 text-slate-500 hover:bg-slate-200'}`}
|
||||
>
|
||||
Todas
|
||||
</Chip>
|
||||
<Chip
|
||||
active={filter === 'top'}
|
||||
onClick={() => setFilter('top')}
|
||||
className={`h-11 px-6 rounded-2xl font-bold uppercase tracking-tight transition-all ${filter === 'top' ? '!bg-slate-900 !text-indigo-400 border-none shadow-lg' : 'bg-slate-100 text-slate-500 hover:bg-slate-200'}`}
|
||||
className={`h-9 sm:h-11 px-4 sm:px-6 rounded-xl sm:rounded-2xl font-bold uppercase tracking-tight transition-all text-xs sm:text-sm ${filter === 'top' ? '!bg-slate-900 !text-indigo-400 border-none shadow-lg' : 'bg-slate-100 text-slate-500 hover:bg-slate-200'}`}
|
||||
>
|
||||
Top Avaliadas
|
||||
</Chip>
|
||||
@@ -106,7 +106,7 @@ export default function Explore() {
|
||||
<select
|
||||
value={sortBy}
|
||||
onChange={(e) => setSortBy(e.target.value as typeof sortBy)}
|
||||
className="h-11 rounded-2xl border-none bg-slate-100 px-4 text-sm font-bold text-slate-700 focus:ring-2 focus:ring-indigo-500/20"
|
||||
className="h-9 sm:h-11 rounded-xl sm:rounded-2xl border-none bg-slate-100 px-3 sm:px-4 text-xs sm:text-sm font-bold text-slate-700 focus:ring-2 focus:ring-indigo-500/20"
|
||||
>
|
||||
<option value="avaliacao">Melhor avaliação</option>
|
||||
<option value="servicos">Mais serviços</option>
|
||||
@@ -134,7 +134,7 @@ export default function Explore() {
|
||||
</Button>
|
||||
</Card>
|
||||
) : (
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-2 gap-8 lg:gap-10">
|
||||
<div className="grid sm:grid-cols-2 lg:grid-cols-2 gap-4 sm:gap-8 lg:gap-10">
|
||||
{filtered.map((shop) => (
|
||||
<ShopCard key={shop.id} shop={shop} />
|
||||
))}
|
||||
|
||||
@@ -31,9 +31,9 @@ export default function Landing() {
|
||||
const featuredShops = shops.slice(0, 3);
|
||||
|
||||
return (
|
||||
<div className="space-y-24 md:space-y-32 pb-24">
|
||||
<div className="space-y-12 sm:space-y-24 md:space-y-32 pb-12 sm:pb-24">
|
||||
{/* Hero Section - Midnight Luxury Style */}
|
||||
<section className="relative overflow-hidden rounded-[3rem] obsidian-gradient text-white px-8 py-20 md:px-16 md:py-32 shadow-[0_20px_50px_rgba(0,0,0,0.3)] border border-white/5">
|
||||
<section className="relative overflow-hidden rounded-2xl sm:rounded-[3rem] obsidian-gradient text-white px-4 py-10 sm:px-8 sm:py-20 md:px-16 md:py-32 shadow-[0_20px_50px_rgba(0,0,0,0.3)] border border-white/5">
|
||||
<div className="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/carbon-fibre.png')] opacity-20 pointer-events-none"></div>
|
||||
<div className="absolute top-0 right-0 w-[500px] h-[500px] bg-indigo-500/10 rounded-full blur-[120px] -translate-y-1/2 translate-x-1/2"></div>
|
||||
<div className="absolute bottom-0 left-0 w-[500px] h-[500px] bg-slate-500/10 rounded-full blur-[120px] translate-y-1/2 -translate-x-1/2"></div>
|
||||
@@ -44,41 +44,41 @@ export default function Landing() {
|
||||
<span>A Solução Completa para a Sua Barbearia</span>
|
||||
</div>
|
||||
|
||||
<h1 className="text-6xl md:text-8xl font-black leading-[0.9] tracking-tighter text-balance uppercase italic">
|
||||
<h1 className="text-3xl sm:text-5xl md:text-8xl font-black leading-[0.9] tracking-tighter text-balance uppercase italic">
|
||||
Gestão Simplificada da sua <br />
|
||||
<span className="text-indigo-400 italic">Barbearia</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-xl md:text-2xl text-slate-300 max-w-2xl leading-relaxed font-medium">
|
||||
<p className="text-base sm:text-xl md:text-2xl text-slate-300 max-w-2xl leading-relaxed font-medium">
|
||||
Organize a sua barbearia com facilidade.
|
||||
Simples, rápido e eficiente.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap gap-6 pt-6">
|
||||
<Button asChild size="lg" className="h-16 px-10 bg-white text-slate-950 hover:bg-indigo-600 hover:text-white font-black uppercase tracking-widest text-xs transition-all duration-300 rounded-2xl shadow-2xl">
|
||||
<div className="flex flex-wrap gap-3 sm:gap-6 pt-4 sm:pt-6">
|
||||
<Button asChild size="lg" className="h-12 sm:h-16 px-6 sm:px-10 bg-white text-slate-950 hover:bg-indigo-600 hover:text-white font-black uppercase tracking-widest text-[10px] sm:text-xs transition-all duration-300 rounded-xl sm:rounded-2xl shadow-2xl">
|
||||
<Link to="/explorar" className="flex items-center gap-3">
|
||||
Ver Barbearias
|
||||
<ArrowRight size={18} strokeWidth={3} />
|
||||
</Link>
|
||||
</Button>
|
||||
<Button asChild variant="outline" size="lg" className="h-16 px-10 bg-transparent text-white border-white/20 hover:bg-white/5 hover:border-white/40 font-black uppercase tracking-widest text-xs rounded-2xl backdrop-blur-sm">
|
||||
<Button asChild variant="outline" size="lg" className="h-12 sm:h-16 px-6 sm:px-10 bg-transparent text-white border-white/20 hover:bg-white/5 hover:border-white/40 font-black uppercase tracking-widest text-[10px] sm:text-xs rounded-xl sm:rounded-2xl backdrop-blur-sm">
|
||||
<Link to="/registo">Parceiro Profissional</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Stats Bar */}
|
||||
<div className="grid grid-cols-3 gap-10 pt-12 border-t border-white/10 max-w-2xl">
|
||||
<div className="grid grid-cols-3 gap-4 sm:gap-10 pt-8 sm:pt-12 border-t border-white/10 max-w-2xl">
|
||||
<div className="space-y-1">
|
||||
<div className="text-4xl md:text-5xl font-black tracking-tighter italic">500+</div>
|
||||
<div className="text-[10px] font-black text-slate-400 uppercase tracking-widest">Lojas Registadas</div>
|
||||
<div className="text-2xl sm:text-4xl md:text-5xl font-black tracking-tighter italic">500+</div>
|
||||
<div className="text-[8px] sm:text-[10px] font-black text-slate-400 uppercase tracking-widest">Lojas Registadas</div>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<div className="text-4xl md:text-5xl font-black tracking-tighter italic">10K+</div>
|
||||
<div className="text-[10px] font-black text-slate-400 uppercase tracking-widest">Cortes Marcados</div>
|
||||
<div className="text-2xl sm:text-4xl md:text-5xl font-black tracking-tighter italic">10K+</div>
|
||||
<div className="text-[8px] sm:text-[10px] font-black text-slate-400 uppercase tracking-widest">Cortes Marcados</div>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<div className="text-4xl md:text-5xl font-black tracking-tighter indigo-gradient bg-clip-text text-transparent italic">4.9</div>
|
||||
<div className="text-[10px] font-black text-slate-400 uppercase tracking-widest">Média de Avaliação</div>
|
||||
<div className="text-2xl sm:text-4xl md:text-5xl font-black tracking-tighter indigo-gradient bg-clip-text text-transparent italic">4.9</div>
|
||||
<div className="text-[8px] sm:text-[10px] font-black text-slate-400 uppercase tracking-widest">Média de Avaliação</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -86,10 +86,10 @@ export default function Landing() {
|
||||
|
||||
|
||||
{/* Features - Minimalist & Bold */}
|
||||
<section className="max-w-7xl mx-auto px-6">
|
||||
<section className="max-w-7xl mx-auto px-3 sm:px-6">
|
||||
<div className="text-center md:text-left mb-16 flex flex-col md:flex-row md:items-end justify-between gap-6">
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-5xl md:text-6xl font-black text-slate-900 tracking-tighter uppercase italic pr-8 border-l-[12px] border-indigo-600 pl-8">
|
||||
<h2 className="text-3xl sm:text-5xl md:text-6xl font-black text-slate-900 tracking-tighter uppercase italic pr-4 sm:pr-8 border-l-[8px] sm:border-l-[12px] border-indigo-600 pl-4 sm:pl-8">
|
||||
Tudo para o <br /> <span className="text-indigo-700">Seu Negócio</span>
|
||||
</h2>
|
||||
<p className="text-xl text-slate-500 font-medium max-w-xl">
|
||||
@@ -98,7 +98,7 @@ export default function Landing() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-10">
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-10">
|
||||
{[
|
||||
{
|
||||
icon: Clock,
|
||||
@@ -116,7 +116,7 @@ export default function Landing() {
|
||||
desc: 'Saiba exatamente quanto a barbearia está faturando e quais os serviços mais procurados.',
|
||||
},
|
||||
].map((feature) => (
|
||||
<Card key={feature.title} className="p-10 space-y-6 rounded-[2.5rem] transition-all duration-500 hover:-translate-y-2 group bg-white border-2 border-slate-50 shadow-sm hover:shadow-xl">
|
||||
<Card key={feature.title} className="p-6 sm:p-10 space-y-4 sm:space-y-6 rounded-2xl sm:rounded-[2.5rem] transition-all duration-500 hover:-translate-y-2 group bg-white border-2 border-slate-50 shadow-sm hover:shadow-xl">
|
||||
<div className="w-16 h-16 rounded-2xl flex items-center justify-center bg-indigo-50 text-indigo-600 group-hover:bg-indigo-600 group-hover:text-white transition-colors duration-300">
|
||||
<feature.icon size={32} />
|
||||
</div>
|
||||
@@ -130,17 +130,17 @@ export default function Landing() {
|
||||
</section>
|
||||
|
||||
{/* How it Works - Immersive */}
|
||||
<section className="bg-slate-950 py-24 md:py-32 overflow-hidden relative">
|
||||
<section className="bg-slate-950 py-12 sm:py-24 md:py-32 overflow-hidden relative">
|
||||
<div className="absolute top-0 left-0 w-full h-full bg-[radial-gradient(circle_at_center,_var(--tw-gradient-stops))] from-slate-900 via-slate-950 to-slate-950 opacity-50" />
|
||||
<div className="max-w-6xl mx-auto px-6 relative z-10">
|
||||
<div className="text-center mb-20">
|
||||
<h2 className="text-5xl md:text-6xl font-black text-white tracking-tighter uppercase italic mb-6">
|
||||
<div className="max-w-6xl mx-auto px-3 sm:px-6 relative z-10">
|
||||
<div className="text-center mb-10 sm:mb-20">
|
||||
<h2 className="text-3xl sm:text-5xl md:text-6xl font-black text-white tracking-tighter uppercase italic mb-4 sm:mb-6">
|
||||
Como <span className="text-indigo-400">Funciona</span>
|
||||
</h2>
|
||||
<div className="w-24 h-1 bg-indigo-500 mx-auto rounded-full shadow-[0_0_20px_rgba(99,102,241,0.5)]" />
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-16 relative">
|
||||
<div className="grid md:grid-cols-3 gap-8 sm:gap-16 relative">
|
||||
{[
|
||||
{ step: '01', title: 'Explorar', desc: 'Encontre as barbearias mais próximas e veja as fotos e avaliações reais.' },
|
||||
{ step: '02', title: 'Agendar', desc: 'Escolha o seu barbeiro e o serviço. Marque o dia e hora que preferir.' },
|
||||
@@ -166,10 +166,10 @@ export default function Landing() {
|
||||
</section>
|
||||
|
||||
{/* Featured Shops - Premium Row */}
|
||||
<section className="max-w-7xl mx-auto px-6">
|
||||
<section className="max-w-7xl mx-auto px-3 sm:px-6">
|
||||
<div className="flex flex-col md:flex-row items-center justify-between mb-16 gap-6">
|
||||
<div className="space-y-2 text-center md:text-left">
|
||||
<h1 className="text-4xl md:text-5xl font-black text-slate-900 tracking-tighter uppercase italic">
|
||||
<h1 className="text-2xl sm:text-4xl md:text-5xl font-black text-slate-900 tracking-tighter uppercase italic">
|
||||
Descobrir <span className="text-indigo-600">Barbearias</span>
|
||||
</h1>
|
||||
<p className="text-slate-500 font-bold uppercase tracking-[0.2em] text-xs">As melhores barbearias do país</p>
|
||||
@@ -182,7 +182,7 @@ export default function Landing() {
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-10">
|
||||
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-10">
|
||||
{featuredShops.map((shop) => (
|
||||
<ShopCard key={shop.id} shop={shop} />
|
||||
))}
|
||||
@@ -190,13 +190,13 @@ export default function Landing() {
|
||||
</section>
|
||||
|
||||
{/* Final CTA - Immersive Dark */}
|
||||
<section className="px-6">
|
||||
<div className="max-w-6xl mx-auto relative overflow-hidden rounded-[4rem] obsidian-gradient text-white px-8 py-20 md:px-20 md:py-24 shadow-2xl border border-white/5">
|
||||
<section className="px-3 sm:px-6">
|
||||
<div className="max-w-6xl mx-auto relative overflow-hidden rounded-2xl sm:rounded-[4rem] obsidian-gradient text-white px-4 py-12 sm:px-8 sm:py-20 md:px-20 md:py-24 shadow-2xl border border-white/5">
|
||||
<div className="absolute top-0 right-0 w-[400px] h-[400px] bg-indigo-500/10 rounded-full blur-[100px]" />
|
||||
<div className="absolute bottom-0 left-0 w-[400px] h-[400px] bg-slate-500/10 rounded-full blur-[100px]" />
|
||||
|
||||
<div className="relative text-center space-y-12 max-w-3xl mx-auto">
|
||||
<h2 className="text-5xl md:text-7xl font-black tracking-tighter uppercase italic leading-[0.9]">
|
||||
<h2 className="text-3xl sm:text-5xl md:text-7xl font-black tracking-tighter uppercase italic leading-[0.9]">
|
||||
Registe a <br /> sua <span className="text-indigo-400">Barbearia</span>
|
||||
</h2>
|
||||
<p className="text-xl text-slate-400 font-medium leading-relaxed">
|
||||
@@ -204,13 +204,13 @@ export default function Landing() {
|
||||
A sua barbearia merece o melhor.
|
||||
</p>
|
||||
<div className="flex flex-wrap justify-center gap-6 pt-4">
|
||||
<Button asChild size="lg" className="h-16 px-10 bg-white text-slate-950 hover:bg-indigo-600 hover:text-white font-black uppercase tracking-widest text-xs rounded-2xl transition-all shadow-2xl">
|
||||
<Button asChild size="lg" className="h-12 sm:h-16 px-6 sm:px-10 bg-white text-slate-950 hover:bg-indigo-600 hover:text-white font-black uppercase tracking-widest text-[10px] sm:text-xs rounded-xl sm:rounded-2xl transition-all shadow-2xl">
|
||||
<Link to="/registo" className="flex items-center gap-3">
|
||||
Criar Conta
|
||||
<ArrowRight size={18} />
|
||||
</Link>
|
||||
</Button>
|
||||
<Button asChild variant="outline" size="lg" className="h-16 px-10 border-white/20 text-white font-black uppercase tracking-widest text-xs rounded-2xl hover:bg-white/5">
|
||||
<Button asChild variant="outline" size="lg" className="h-12 sm:h-16 px-6 sm:px-10 border-white/20 text-white font-black uppercase tracking-widest text-[10px] sm:text-xs rounded-xl sm:rounded-2xl hover:bg-white/5">
|
||||
<Link to="/explorar">Navegar agora</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -135,15 +135,16 @@ export default function Profile() {
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="max-w-4xl mx-auto space-y-12 pb-20">
|
||||
<div className="max-w-4xl mx-auto space-y-8 sm:space-y-12 pb-12 sm:pb-20">
|
||||
{/* Cabeçalho do Perfil */}
|
||||
<section className="relative overflow-hidden rounded-[3rem] obsidian-gradient text-white p-8 md:p-12 shadow-2xl border border-white/5">
|
||||
<section className="relative overflow-hidden rounded-2xl sm:rounded-[3rem] obsidian-gradient text-white p-4 sm:p-8 md:p-12 shadow-2xl border border-white/5">
|
||||
<div className="absolute top-0 right-0 w-64 h-64 bg-indigo-500/10 rounded-full blur-[80px] -translate-y-1/2 translate-x-1/2" />
|
||||
<div className="relative z-10 flex flex-col md:flex-row items-center gap-8 md:text-left text-center">
|
||||
<div className="relative group">
|
||||
<div className="absolute inset-0 bg-indigo-500 blur-2xl opacity-20 group-hover:opacity-40 transition-opacity" />
|
||||
<div className="w-24 h-24 bg-white/10 backdrop-blur-xl border-2 border-white/20 rounded-[2rem] flex items-center justify-center text-indigo-400 shadow-2xl relative z-10 transition-transform duration-500 hover:rotate-6">
|
||||
<User size={48} />
|
||||
<div className="w-16 h-16 sm:w-24 sm:h-24 bg-white/10 backdrop-blur-xl border-2 border-white/20 rounded-2xl sm:rounded-[2rem] flex items-center justify-center text-indigo-400 shadow-2xl relative z-10 transition-transform duration-500 hover:rotate-6">
|
||||
<User size={36} className="sm:hidden" />
|
||||
<User size={48} className="hidden sm:block" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
@@ -151,7 +152,7 @@ export default function Profile() {
|
||||
<Star size={12} fill="currentColor" />
|
||||
<span>Utilizador Registado</span>
|
||||
</div>
|
||||
<h1 className="text-4xl md:text-5xl font-black tracking-tighter uppercase italic leading-[0.9]">
|
||||
<h1 className="text-2xl sm:text-4xl md:text-5xl font-black tracking-tighter uppercase italic leading-[0.9]">
|
||||
{displayName}
|
||||
</h1>
|
||||
<p className="text-slate-400 font-medium italic">{authEmail}</p>
|
||||
@@ -257,8 +258,8 @@ export default function Profile() {
|
||||
const canReview = a.status === 'concluido' && !reviewedAppointments.has(a.id)
|
||||
|
||||
return (
|
||||
<Card key={a.id} className="p-2 border-none glass-card rounded-[2.5rem] shadow-lg shadow-slate-200/50">
|
||||
<div className="p-6 space-y-4">
|
||||
<Card key={a.id} className="p-1.5 sm:p-2 border-none glass-card rounded-2xl sm:rounded-[2.5rem] shadow-lg shadow-slate-200/50">
|
||||
<div className="p-4 sm:p-6 space-y-3 sm:space-y-4">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center gap-3">
|
||||
|
||||
@@ -38,59 +38,66 @@ export default function ShopDetails() {
|
||||
)}`;
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto space-y-8 py-4">
|
||||
<div className="relative overflow-hidden rounded-[2.5rem] border-none shadow-2xl shadow-slate-200/50">
|
||||
<div className="max-w-6xl mx-auto space-y-6 sm:space-y-8 py-2 sm:py-4">
|
||||
<div className="relative overflow-hidden rounded-2xl sm:rounded-[2.5rem] border-none shadow-2xl shadow-slate-200/50">
|
||||
{shop.imageUrl ? (
|
||||
<img src={shop.imageUrl} alt={`Foto de ${shop.name}`} className="h-64 w-full object-cover md:h-96 transition-transform duration-1000 hover:scale-105" />
|
||||
<img src={shop.imageUrl} alt={`Foto de ${shop.name}`} className="h-48 sm:h-64 w-full object-cover md:h-96 transition-transform duration-1000 hover:scale-105" />
|
||||
) : (
|
||||
<div className="h-64 w-full obsidian-gradient md:h-96" />
|
||||
<div className="h-48 sm:h-64 w-full obsidian-gradient md:h-96" />
|
||||
)}
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-slate-950/80 via-slate-950/20 to-transparent" />
|
||||
|
||||
<div className="absolute right-6 top-6 flex gap-3">
|
||||
<div className="absolute right-3 top-3 sm:right-6 sm:top-6 flex gap-2 sm:gap-3">
|
||||
<a
|
||||
href={mapUrl}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="w-12 h-12 flex items-center justify-center rounded-2xl bg-white/90 backdrop-blur-md text-slate-900 shadow-xl hover:bg-white hover:scale-110 transition-all"
|
||||
className="w-10 h-10 sm:w-12 sm:h-12 flex items-center justify-center rounded-xl sm:rounded-2xl bg-white/90 backdrop-blur-md text-slate-900 shadow-xl hover:bg-white hover:scale-110 transition-all"
|
||||
title="Ver no Mapa"
|
||||
>
|
||||
<MapPin size={22} />
|
||||
<MapPin size={18} className="sm:hidden" />
|
||||
<MapPin size={22} className="hidden sm:block" />
|
||||
</a>
|
||||
<button
|
||||
onClick={() => toggleFavorite(shop.id)}
|
||||
className="w-12 h-12 flex items-center justify-center rounded-2xl bg-white/90 backdrop-blur-md text-slate-900 shadow-xl hover:bg-white hover:scale-110 transition-all font-bold"
|
||||
className="w-10 h-10 sm:w-12 sm:h-12 flex items-center justify-center rounded-xl sm:rounded-2xl bg-white/90 backdrop-blur-md text-slate-900 shadow-xl hover:bg-white hover:scale-110 transition-all font-bold"
|
||||
type="button"
|
||||
>
|
||||
<Heart
|
||||
size={18}
|
||||
className={`sm:hidden ${isFavorite(shop.id) ? 'fill-rose-500 text-rose-500' : 'text-slate-900'}`}
|
||||
/>
|
||||
<Heart
|
||||
size={22}
|
||||
className={isFavorite(shop.id) ? 'fill-rose-500 text-rose-500' : 'text-slate-900'}
|
||||
className={`hidden sm:block ${isFavorite(shop.id) ? 'fill-rose-500 text-rose-500' : 'text-slate-900'}`}
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setImageOpen(true)}
|
||||
className="w-12 h-12 flex items-center justify-center rounded-2xl bg-white/90 backdrop-blur-md text-slate-900 shadow-xl hover:bg-white hover:scale-110 transition-all"
|
||||
className="w-10 h-10 sm:w-12 sm:h-12 flex items-center justify-center rounded-xl sm:rounded-2xl bg-white/90 backdrop-blur-md text-slate-900 shadow-xl hover:bg-white hover:scale-110 transition-all"
|
||||
type="button"
|
||||
>
|
||||
<Maximize2 size={22} />
|
||||
<Maximize2 size={18} className="sm:hidden" />
|
||||
<Maximize2 size={22} className="hidden sm:block" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="absolute bottom-10 left-10 space-y-3">
|
||||
<div className="flex items-center gap-2 bg-slate-900/40 backdrop-blur-md border border-white/20 w-fit px-3 py-1 rounded-full">
|
||||
<Star size={14} className="fill-indigo-500 text-indigo-500" />
|
||||
<span className="text-white text-xs font-black tracking-widest">{(shop.rating || 0).toFixed(1)} EXCELENTE</span>
|
||||
<div className="absolute bottom-4 left-4 sm:bottom-10 sm:left-10 space-y-2 sm:space-y-3 max-w-[calc(100%-2rem)]">
|
||||
<div className="flex items-center gap-2 bg-slate-900/40 backdrop-blur-md border border-white/20 w-fit px-2 sm:px-3 py-1 rounded-full">
|
||||
<Star size={12} className="fill-indigo-500 text-indigo-500 sm:hidden" />
|
||||
<Star size={14} className="fill-indigo-500 text-indigo-500 hidden sm:block" />
|
||||
<span className="text-white text-[10px] sm:text-xs font-black tracking-widest">{(shop.rating || 0).toFixed(1)} EXCELENTE</span>
|
||||
</div>
|
||||
<h1 className="text-4xl md:text-5xl font-black text-white tracking-tighter">{shop.name}</h1>
|
||||
<h1 className="text-2xl sm:text-4xl md:text-5xl font-black text-white tracking-tighter truncate">{shop.name}</h1>
|
||||
<div className="flex items-center gap-2 text-white/90">
|
||||
<MapPin size={16} className="text-indigo-600" />
|
||||
<p className="text-base font-medium">{shop.address}</p>
|
||||
<MapPin size={14} className="text-indigo-600 shrink-0" />
|
||||
<p className="text-sm sm:text-base font-medium truncate">{shop.address}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-8">
|
||||
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4 bg-white/50 backdrop-blur-sm p-2 rounded-[2rem] border border-white/50">
|
||||
<div className="grid gap-4 sm:gap-8">
|
||||
<div className="flex flex-col gap-3 sm:gap-4 bg-white/50 backdrop-blur-sm p-1.5 sm:p-2 rounded-2xl sm:rounded-[2rem] border border-white/50">
|
||||
<Tabs
|
||||
tabs={[
|
||||
{ id: 'servicos', label: 'Serviços' },
|
||||
@@ -102,7 +109,7 @@ export default function ShopDetails() {
|
||||
onChange={(v) => setTab(v as typeof tab)}
|
||||
className="border-none bg-transparent"
|
||||
/>
|
||||
<div className="px-6 py-2 text-xs font-black text-slate-400 uppercase tracking-widest bg-white rounded-2xl border border-slate-100 shadow-sm">
|
||||
<div className="px-3 sm:px-6 py-2 text-[10px] sm:text-xs font-black text-slate-400 uppercase tracking-widest bg-white rounded-xl sm:rounded-2xl border border-slate-100 shadow-sm text-center sm:text-left">
|
||||
{(shop.services || []).length} SERVIÇOS · {(shop.barbers || []).length} BARBEIROS
|
||||
</div>
|
||||
</div>
|
||||
@@ -116,11 +123,11 @@ export default function ShopDetails() {
|
||||
}}
|
||||
/>
|
||||
) : tab === 'barbeiros' ? (
|
||||
<div className="bg-white/30 backdrop-blur-md p-8 rounded-[3rem] border border-white/50">
|
||||
<div className="bg-white/30 backdrop-blur-md p-4 sm:p-8 rounded-2xl sm:rounded-[3rem] border border-white/50">
|
||||
<BarberList barbers={shop.barbers} />
|
||||
</div>
|
||||
) : tab === 'detalhes' ? (
|
||||
<div className="bg-white/30 backdrop-blur-md p-8 rounded-[3rem] border border-white/50">
|
||||
<div className="bg-white/30 backdrop-blur-md p-4 sm:p-8 rounded-2xl sm:rounded-[3rem] border border-white/50">
|
||||
<ShopDetailsTab shop={shop} />
|
||||
</div>
|
||||
) : (
|
||||
@@ -131,15 +138,11 @@ export default function ShopDetails() {
|
||||
|
||||
<Dialog open={imageOpen} title={shop.name} onClose={() => setImageOpen(false)}>
|
||||
{shop.imageUrl ? (
|
||||
<img src={shop.imageUrl} alt={`Foto de ${shop.name}`} className="w-full rounded-[2rem] object-cover shadow-2xl" />
|
||||
<img src={shop.imageUrl} alt={`Foto de ${shop.name}`} className="w-full rounded-2xl sm:rounded-[2rem] object-cover shadow-2xl" />
|
||||
) : (
|
||||
<div className="h-96 w-full rounded-[2rem] obsidian-gradient" />
|
||||
<div className="h-96 w-full rounded-2xl sm:rounded-[2rem] obsidian-gradient" />
|
||||
)}
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user