foglalas
This commit is contained in:
3
bun.lock
3
bun.lock
@@ -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=="],
|
||||
|
||||
@@ -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",
|
||||
|
||||
14
src/App.tsx
14
src/App.tsx
@@ -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 (
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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="grid grid-cols-1 gap-6 sm:grid-cols-2">
|
||||
<Select>
|
||||
<SelectTrigger><SelectValue placeholder="Vendégek száma" /></SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="1">1 fő</SelectItem>
|
||||
<SelectItem value="2">2 fő</SelectItem>
|
||||
<SelectItem value="3">3 fő</SelectItem>
|
||||
<SelectItem value="4">4 fő</SelectItem>
|
||||
<SelectItem value="5">5+ fő</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>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<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>
|
||||
<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
|
||||
</Button>
|
||||
</form>
|
||||
) : (
|
||||
<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">
|
||||
<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 fő</SelectItem>
|
||||
<SelectItem value="2">2 fő</SelectItem>
|
||||
<SelectItem value="3">3 fő</SelectItem>
|
||||
<SelectItem value="4">4 fő</SelectItem>
|
||||
<SelectItem value="5+">5+ fő</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<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;
|
||||
|
||||
22
src/components/ui/label.tsx
Normal file
22
src/components/ui/label.tsx
Normal 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 }
|
||||
48
src/components/ui/popover.tsx
Normal file
48
src/components/ui/popover.tsx
Normal 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 }
|
||||
Reference in New Issue
Block a user