Merge version_2 into main #1

Merged
bender merged 2 commits from version_2 into main 2026-03-21 00:20:24 +00:00
2 changed files with 231 additions and 15 deletions

View File

@@ -0,0 +1,52 @@
import nodemailer from "nodemailer";
import { NextRequest, NextResponse } from "next/server";
const transporter = nodemailer.createTransport({
service: "gmail", auth: {
user: process.env.GMAIL_USER,
pass: process.env.GMAIL_PASSWORD,
},
});
export async function POST(request: NextRequest) {
try {
const data = await request.json();
const { name, email, phone, date, time, guests, message } = data;
if (!name || !email || !phone || !date || !time || !guests) {
return NextResponse.json(
{ error: "Missing required fields" },
{ status: 400 }
);
}
const mailOptions = {
from: process.env.GMAIL_USER,
to: "prezantime1@gmail.com", subject: `New Reservation Request from ${name}`,
html: `
<h2>Taverna Kala Reservation Request</h2>
<p><strong>Name:</strong> ${name}</p>
<p><strong>Email:</strong> ${email}</p>
<p><strong>Phone:</strong> ${phone}</p>
<p><strong>Date:</strong> ${date}</p>
<p><strong>Time:</strong> ${time}</p>
<p><strong>Number of Guests:</strong> ${guests}</p>
<p><strong>Special Requests:</strong> ${message || "None"}</p>
`,
};
await transporter.sendMail(mailOptions);
return NextResponse.json(
{ message: "Reservation request sent successfully" },
{ status: 200 }
);
} catch (error) {
console.error("Error sending reservation:", error);
return NextResponse.json(
{ error: "Failed to send reservation" },
{ status: 500 }
);
}
}

View File

@@ -10,8 +10,42 @@ import TestimonialCardTen from "@/components/sections/testimonial/TestimonialCar
import ContactCTA from "@/components/sections/contact/ContactCTA";
import FooterBase from "@/components/sections/footer/FooterBase";
import { BookOpen, Flame, Heart, Award, Star, Calendar, Castle } from "lucide-react";
import { useState } from "react";
import nodemailer from "nodemailer";
export default function LandingPage() {
const [reservationData, setReservationData] = useState({
name: "", email: "", phone: "", date: "", time: "", guests: "", message: ""
});
const [submitting, setSubmitting] = useState(false);
const [submitMessage, setSubmitMessage] = useState("");
const handleReservationSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setSubmitting(true);
setSubmitMessage("");
try {
const response = await fetch("/api/send-reservation", {
method: "POST", headers: {
"Content-Type": "application/json"},
body: JSON.stringify(reservationData),
});
if (response.ok) {
setSubmitMessage("Reservation request sent successfully! We'll confirm shortly.");
setReservationData({
name: "", email: "", phone: "", date: "", time: "", guests: "", message: ""
});
} else {
setSubmitMessage("Failed to send reservation. Please try again.");
}
} catch (error) {
setSubmitMessage("An error occurred. Please contact us directly.");
}
setSubmitting(false);
};
return (
<ThemeProvider
defaultButtonVariant="hover-bubble"
@@ -192,21 +226,151 @@ export default function LandingPage() {
</div>
<div id="contact" data-section="contact">
<ContactCTA
tag="Ready to Join Us?"
tagIcon={Calendar}
tagAnimation="slide-up"
title="Reserve Your Table at Taverna Kala"
description="Secure your spot in our intimate dining room and experience authentic Albanian heritage. Whether you're planning a quiet dinner for two, a family celebration, or a group event, we're ready to welcome you with warm hospitality and exceptional cuisine."
buttons={[
{ text: "Book a Reservation", href: "mailto:reservations@tavernakala.al?subject=Taverna%20Kala%20Reservation%20Request" },
{ text: "Call Us: +355 697 123 456", href: "tel:+355697123456" }
]}
buttonAnimation="slide-up"
background={{ variant: "radial-gradient" }}
useInvertedBackground={false}
ariaLabel="Reservation contact section"
/>
<div className="px-6 md:px-12 py-16 md:py-24 space-y-12">
<div className="max-w-2xl mx-auto text-center">
<h2 className="text-4xl md:text-5xl font-bold mb-6">Reserve Your Table</h2>
<p className="text-lg text-foreground/80 mb-10">
Book your dining experience at Taverna Kala. Fill out the form below and we'll confirm your reservation shortly.
</p>
</div>
<form
onSubmit={handleReservationSubmit}
className="max-w-2xl mx-auto bg-card p-8 rounded-lg shadow-lg space-y-6"
>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label className="block text-sm font-medium mb-2">Name *</label>
<input
type="text"
required
value={reservationData.name}
onChange={(e) =>
setReservationData({ ...reservationData, name: e.target.value })
}
className="w-full px-4 py-2 border border-foreground/20 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-cta"
placeholder="Your name"
/>
</div>
<div>
<label className="block text-sm font-medium mb-2">Email *</label>
<input
type="email"
required
value={reservationData.email}
onChange={(e) =>
setReservationData({ ...reservationData, email: e.target.value })
}
className="w-full px-4 py-2 border border-foreground/20 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-cta"
placeholder="your@email.com"
/>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label className="block text-sm font-medium mb-2">Phone *</label>
<input
type="tel"
required
value={reservationData.phone}
onChange={(e) =>
setReservationData({ ...reservationData, phone: e.target.value })
}
className="w-full px-4 py-2 border border-foreground/20 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-cta"
placeholder="+355 697 123 456"
/>
</div>
<div>
<label className="block text-sm font-medium mb-2">Number of Guests *</label>
<select
required
value={reservationData.guests}
onChange={(e) =>
setReservationData({ ...reservationData, guests: e.target.value })
}
className="w-full px-4 py-2 border border-foreground/20 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-cta"
>
<option value="">Select number of guests</option>
{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((num) => (
<option key={num} value={num.toString()}>
{num} {num === 1 ? "guest" : "guests"}
</option>
))}
<option value="10+">10+ guests (group event)</option>
</select>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label className="block text-sm font-medium mb-2">Preferred Date *</label>
<input
type="date"
required
value={reservationData.date}
onChange={(e) =>
setReservationData({ ...reservationData, date: e.target.value })
}
className="w-full px-4 py-2 border border-foreground/20 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-cta"
/>
</div>
<div>
<label className="block text-sm font-medium mb-2">Preferred Time *</label>
<input
type="time"
required
value={reservationData.time}
onChange={(e) =>
setReservationData({ ...reservationData, time: e.target.value })
}
className="w-full px-4 py-2 border border-foreground/20 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-cta"
/>
</div>
</div>
<div>
<label className="block text-sm font-medium mb-2">Special Requests</label>
<textarea
value={reservationData.message}
onChange={(e) =>
setReservationData({ ...reservationData, message: e.target.value })
}
className="w-full px-4 py-2 border border-foreground/20 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-cta resize-none"
placeholder="Any dietary restrictions, special occasions, or other requests?"
rows={4}
/>
</div>
<button
type="submit"
disabled={submitting}
className="w-full bg-primary-cta text-primary-cta-text font-semibold py-3 rounded-lg hover:opacity-90 transition-opacity disabled:opacity-50"
>
{submitting ? "Sending..." : "Submit Reservation Request"}
</button>
{submitMessage && (
<div
className={`p-4 rounded-lg text-center ${
submitMessage.includes("successfully")
? "bg-green-100 text-green-800"
: "bg-red-100 text-red-800"
}`}
>
{submitMessage}
</div>
)}
</form>
<div className="max-w-2xl mx-auto text-center text-foreground/70 text-sm">
<p>
Or contact us directly:<br />
<strong>Email:</strong> reservations@tavernakala.al<br />
<strong>Phone:</strong> +355 697 123 456
</p>
</div>
</div>
</div>
<div id="footer" data-section="footer">