This commit is contained in:
2025-10-17 08:59:44 +02:00
parent 4c2c19152b
commit 98c7ce8f87
13 changed files with 229 additions and 70 deletions

View File

@@ -6,6 +6,7 @@
"dependencies": {
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-slot": "^1.2.3",
"bun-plugin-tailwind": "^0.1.2",
@@ -89,6 +90,8 @@
"@radix-ui/react-label": ["@radix-ui/react-label@2.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ=="],
"@radix-ui/react-popover": ["@radix-ui/react-popover@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA=="],
"@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.8", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-rect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw=="],
"@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ=="],

View File

@@ -11,6 +11,7 @@
"dependencies": {
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-slot": "^1.2.3",
"bun-plugin-tailwind": "^0.1.2",

View File

@@ -1,10 +1,10 @@
import Header from './components/Header';
import Hero from './components/Hero';
import About from './components/About';
import Menu from './components/Menu';
import Reservations from './components/Reservations';
import Delivery from './components/Delivery';
import Footer from './components/Footer';
import Header from '@/components/Header';
import Hero from '@/components/Hero';
import About from '@/components/About';
import Menu from '@/components/Menu';
import Reservations from '@/components/Reservations';
import Delivery from '@/components/Delivery';
import Footer from '@/components/Footer';
export function App() {
return (

View File

@@ -1,11 +1,11 @@
import rolunk from "@/public/rolunk.png";
function About() {
export default function About() {
return (
<section id="rolunk" className="bg-slate-900 py-24 sm:py-32">
<div className="container mx-auto grid grid-cols-1 items-center gap-12 px-6 lg:grid-cols-2">
<div>
<h2 className="text-4xl font-bold tracking-tight text-amber-400">Történetünk</h2>
<h2 className="text-4xl font-bold tracking-tight text-amber-400">Rólunk</h2>
<p className="mt-6 text-lg leading-8 text-slate-300">
Az autentikus magyar ízek iránti szenvedélyből született a <strong>Budapest Bisztró</strong>, hogy elhozza kultúránk melegségét és gazdagságát az Ön asztalára. Séfjeink generációkon át örökített családi recepteket követnek, a legjobb helyi alapanyagokat felhasználva, hogy ételeink egyszerre legyenek hagyományosak és újszerűek.
</p>
@@ -22,5 +22,3 @@ function About() {
</section>
);
}
export default About;

View File

@@ -1,4 +1,4 @@
function Contact() {
export default function Contact() {
return (
<section id="kapcsolat" className="py-24 bg-slate-900">
<div className="container mx-auto px-6 text-center">
@@ -10,5 +10,3 @@ function Contact() {
</section>
);
}
export default Contact;

View File

@@ -1,7 +1,7 @@
import wolt from "@/public/wolt.png";
import foodora from "@/public/foodora.png";
function Delivery() {
export default function Delivery() {
return (
<section id="szallitas" className="py-24 text-center bg-slate-900">
<div className="container mx-auto px-6">
@@ -44,5 +44,3 @@ function Delivery() {
</section>
);
}
export default Delivery;

View File

@@ -1,4 +1,4 @@
function Footer() {
export default function Footer() {
return (
<footer className="border-t border-slate-800 bg-slate-900 py-12">
<div className="container mx-auto px-6 text-center text-slate-400">
@@ -8,5 +8,3 @@ function Footer() {
</footer>
);
}
export default Footer;

View File

@@ -1,4 +1,4 @@
function Header() {
export default function Header() {
return (
<header className="fixed top-0 z-50 w-full bg-black/20 backdrop-blur-lg">
<nav className="container mx-auto flex h-20 items-center justify-between px-6">
@@ -15,5 +15,3 @@ function Header() {
</header>
);
}
export default Header;

View File

@@ -9,7 +9,7 @@ const heroImages = [
hero3
];
function Hero() {
export default function Hero() {
const [currentIndex, setCurrentIndex] = useState(0);
const nextSlide = useCallback(() => {
@@ -55,5 +55,3 @@ function Hero() {
</section>
);
}
export default Hero;

View File

@@ -30,7 +30,7 @@ const menuItems = [
},
];
function Menu() {
export default function Menu() {
return (
<section id="menu" className="py-24 sm:py-32">
<div className="container mx-auto px-6">
@@ -59,5 +59,3 @@ function Menu() {
</section>
);
}
export default Menu;

View File

@@ -1,58 +1,157 @@
import { Button } from './ui/button';
import { Calendar } from './ui/calendar';
import { Input } from './ui/input';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select';
import { useState } from 'react';
import { format } from 'date-fns';
import { hu } from 'date-fns/locale';
import { Calendar as CalendarIcon, CheckCircle2, AlertTriangle } from 'lucide-react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Calendar } from '@/components/ui/calendar';
import { Input } from '@/components/ui/input';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Label } from '@/components/ui/label';
import foglalas from '@/public/foglalas.png';
function Foglalas() {
type SubmissionStatus = 'idle' | 'error' | 'success' | 'loading';
export default function Reservations() {
const [date, setDate] = useState<Date | undefined>();
const [formData, setFormData] = useState({
name: '',
email: '',
partySize: '',
time: '18:00',
});
const [status, setStatus] = useState<SubmissionStatus>('idle');
const [message, setMessage] = useState('');
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData((prev) => ({ ...prev, [name]: value }));
};
const handleSelectChange = (name: 'partySize') => (value: string) => {
setFormData((prev) => ({ ...prev, [name]: value }));
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
setMessage('');
if (!date || !formData.name || !formData.email || !formData.partySize || !formData.time) {
setMessage('Kérjük, töltse ki az összes mezőt a folytatáshoz.');
setStatus('error');
return;
}
setStatus('loading');
setTimeout(() => {
const reservationData = {
...formData,
date: format(date, 'yyyy-MM-dd'),
};
console.log('Foglalási adatok:', reservationData);
setStatus('success');
setMessage(`Köszönjük a foglalást, ${formData.name}! Hamarosan emailben is megerősítjük.`);
}, 1000);
};
const resetForm = () => {
setFormData({ name: '', email: '', partySize: '', time: '18:00' });
setDate(undefined);
setStatus('idle');
setMessage('');
};
return (
<section id="foglalas" className="bg-slate-900 py-24 sm:py-32">
<div className="container mx-auto grid grid-cols-1 items-center gap-12 px-6 lg:grid-cols-2">
<section id="foglalas" className="scroll-mt-20 bg-slate-900 py-24 sm:py-32">
<div className="container mx-auto grid grid-cols-1 items-center gap-x-16 gap-y-12 px-6 lg:grid-cols-2">
<div className="text-center lg:text-left">
<h2 className="text-4xl font-bold tracking-tight text-amber-400">Foglaljon Asztalt</h2>
<p className="mt-4 text-lg text-slate-300">
<p className="mt-4 text-lg leading-8 text-slate-300">
Biztosítsa helyét egy felejthetetlen gasztronómiai élményhez. Örömmel látjuk vendégül!
</p>
<img
src={foglalas}
alt="Étterem belső"
className="mt-8 rounded-lg shadow-2xl"
alt="Hangulatos étterem belső tere asztalokkal"
className="mt-8 w-full rounded-lg object-cover shadow-2xl"
/>
</div>
<div className="rounded-lg bg-slate-950 p-8 shadow-2xl">
<form className="space-y-6">
<Input placeholder="Teljes Név" />
<Input type="email" placeholder="Email Cím" />
<div className="flex min-h-[550px] items-center justify-center rounded-lg bg-slate-950 p-8 shadow-2xl">
{status === 'success' ? (
<div className="text-center">
<CheckCircle2 className="mx-auto h-16 w-16 text-green-500" />
<h3 className="mt-4 text-2xl font-semibold text-white">Foglalás elküldve!</h3>
<p className="mt-2 text-slate-300">{message}</p>
<Button onClick={resetForm} size="lg" className="mt-8 bg-amber-500 text-slate-900 hover:bg-amber-400">
Új foglalás
</Button>
</div>
) : (
<form onSubmit={handleSubmit} className="flex w-full flex-col space-y-6">
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="name">Teljes Név</Label>
<Input id="name" name="name" value={formData.name} onChange={handleChange} />
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="email">Email Cím</Label>
<Input id="email" name="email" type="email" value={formData.email} onChange={handleChange} />
</div>
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
<Select>
<SelectTrigger><SelectValue placeholder="Vendégek száma" /></SelectTrigger>
<SelectContent>
<div className="grid w-full items-center gap-1.5">
<Label>Vendégek száma</Label>
<Select onValueChange={handleSelectChange('partySize')} value={formData.partySize}>
<SelectTrigger><SelectValue placeholder="Válasszon..." /></SelectTrigger>
<SelectContent className="dark">
<SelectItem value="1">1 </SelectItem>
<SelectItem value="2">2 </SelectItem>
<SelectItem value="3">3 </SelectItem>
<SelectItem value="4">4 </SelectItem>
<SelectItem value="5">5+ </SelectItem>
</SelectContent>
</Select>
<Select>
<SelectTrigger><SelectValue placeholder="Időpont" /></SelectTrigger>
<SelectContent>
<SelectItem value="18:00">18:00</SelectItem>
<SelectItem value="19:00">19:00</SelectItem>
<SelectItem value="20:00">20:00</SelectItem>
<SelectItem value="21:00">21:00</SelectItem>
<SelectItem value="5+">5+ </SelectItem>
</SelectContent>
</Select>
</div>
<Calendar mode="single" className="rounded-md border border-slate-800" />
<Button type="submit" size="lg" className="w-full bg-amber-500 text-slate-900 hover:bg-amber-400">
Foglalás
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="time">Időpont</Label>
<Input id="time" name="time" type="time" value={formData.time} onChange={handleChange} />
</div>
</div>
<div className="grid w-full items-center gap-1.5">
<Label>Dátum</Label>
<Popover>
<PopoverTrigger asChild>
<Button variant={'outline'} className={cn('w-full justify-start text-left font-normal', !date && 'text-muted-foreground')}>
<CalendarIcon className="mr-2 h-4 w-4" />
{date ? format(date, 'PPP', { locale: hu }) : <span>Válasszon dátumot</span>}
</Button>
</PopoverTrigger>
<PopoverContent className="dark w-auto p-0">
<Calendar mode="single" selected={date} onSelect={setDate} autoFocus disabled={(day) => day < new Date(new Date().setDate(new Date().getDate() - 1))} />
</PopoverContent>
</Popover>
</div>
<div className="h-14">
{status === 'error' && message && (
<div className="flex items-center space-x-2 rounded-md border border-red-500/50 bg-red-500/10 p-3 text-sm text-red-400">
<AlertTriangle className="h-4 w-4 flex-shrink-0" />
<p>{message}</p>
</div>
)}
</div>
<Button type="submit" size="lg" className="w-full bg-amber-500 text-slate-900 hover:bg-amber-400 !mt-8" disabled={status === 'loading'}>
{status === 'loading' ? 'Küldés...' : 'Asztalfoglalás'}
</Button>
</form>
)}
</div>
</div>
</section>
);
}
export default Foglalas;

View File

@@ -0,0 +1,22 @@
import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label"
import { cn } from "@/lib/utils"
function Label({
className,
...props
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
return (
<LabelPrimitive.Root
data-slot="label"
className={cn(
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
className
)}
{...props}
/>
)
}
export { Label }

View File

@@ -0,0 +1,48 @@
"use client"
import * as React from "react"
import * as PopoverPrimitive from "@radix-ui/react-popover"
import { cn } from "@/lib/utils"
function Popover({
...props
}: React.ComponentProps<typeof PopoverPrimitive.Root>) {
return <PopoverPrimitive.Root data-slot="popover" {...props} />
}
function PopoverTrigger({
...props
}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
}
function PopoverContent({
className,
align = "center",
sideOffset = 4,
...props
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
return (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
data-slot="popover-content"
align={align}
sideOffset={sideOffset}
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
className
)}
{...props}
/>
</PopoverPrimitive.Portal>
)
}
function PopoverAnchor({
...props
}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />
}
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }