Merge version_3 into main #5

Merged
bender merged 2 commits from version_3 into main 2026-03-08 15:54:57 +00:00
2 changed files with 313 additions and 7 deletions

View File

@@ -0,0 +1,71 @@
import { NextRequest, NextResponse } from 'next/server';
import nodemailer from 'nodemailer';
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.HOTEL_EMAIL,
pass: process.env.HOTEL_EMAIL_PASSWORD,
},
});
export async function POST(request: NextRequest) {
try {
const { recipientEmail, subject, htmlContent, bookingData, roomDetails } = await request.json();
// Validate required fields
if (!bookingData.phone || !bookingData.email || !bookingData.age || !bookingData.roomType) {
return NextResponse.json(
{ error: 'Missing required booking information' },
{ status: 400 }
);
}
// Send email to hotel
await transporter.sendMail({
from: process.env.HOTEL_EMAIL,
to: recipientEmail,
subject: subject,
html: htmlContent,
});
// Send confirmation email to customer
const confirmationHtml = `
<h2>Booking Confirmation - Hotel Shine Inn</h2>
<p>Dear Guest,</p>
<p>Thank you for your booking request! We have received your information and will contact you shortly to confirm your reservation.</p>
<h3>Booking Details:</h3>
<ul>
<li><strong>Room Type:</strong> ${roomDetails.name}</li>
<li><strong>Room Price:</strong> ${roomDetails.price}</li>
<li><strong>Payment Method:</strong> ${bookingData.paymentMethod === 'online' ? 'Online Payment' : 'Pay at Counter'}</li>
</ul>
<p><strong>Your Contact Information:</strong></p>
<ul>
<li><strong>Phone:</strong> ${bookingData.phone}</li>
<li><strong>Email:</strong> ${bookingData.email}</li>
</ul>
<p>If you have any questions, please don't hesitate to contact us at +91 81305 21617 or reply to this email.</p>
<p>We look forward to hosting you at Hotel Shine Inn!</p>
<p>Best regards,<br/>Hotel Shine Inn Team<br/>Sector 3, Rohini, Delhi</p>
`;
await transporter.sendMail({
from: process.env.HOTEL_EMAIL,
to: bookingData.email,
subject: 'Booking Confirmation - Hotel Shine Inn',
html: confirmationHtml,
});
return NextResponse.json(
{ message: 'Booking email sent successfully' },
{ status: 200 }
);
} catch (error) {
console.error('Email sending error:', error);
return NextResponse.json(
{ error: 'Failed to send booking email' },
{ status: 500 }
);
}
}

View File

@@ -10,13 +10,107 @@ import MetricCardThree from '@/components/sections/metrics/MetricCardThree';
import TestimonialCardTen from '@/components/sections/testimonial/TestimonialCardTen';
import ContactFaq from '@/components/sections/contact/ContactFaq';
import FooterLogoEmphasis from '@/components/sections/footer/FooterLogoEmphasis';
import { Sparkles, Star, Home, Wifi, Wind, ParkingCircle, Heart, Lock, Users, MessageCircle, Phone, TrendingUp, Award, CheckCircle } from 'lucide-react';
import { Sparkles, Star, Home, Wifi, Wind, ParkingCircle, Heart, Lock, Users, MessageCircle, Phone, TrendingUp, Award, CheckCircle, X } from 'lucide-react';
import { useState } from 'react';
export default function LandingPage() {
const [isBookingModalOpen, setIsBookingModalOpen] = useState(false);
const [formData, setFormData] = useState({
phone: '',
email: '',
age: '',
roomType: 'deluxe',
paymentMethod: 'online'
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitMessage, setSubmitMessage] = useState('');
const handleCallNow = () => {
window.location.href = 'tel:+918130521617';
};
const handleBookNowClick = () => {
setIsBookingModalOpen(true);
setFormData({
phone: '',
email: '',
age: '',
roomType: 'deluxe',
paymentMethod: 'online'
});
setSubmitMessage('');
};
const handleFormChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value
}));
};
const handleFormSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setIsSubmitting(true);
setSubmitMessage('');
try {
const roomDetails = {
'deluxe': { name: 'Deluxe Couple Room', price: '₹1,950/night' },
'standard': { name: 'Standard AC Room', price: '₹1,450/night' },
'premium': { name: 'Premium Comfort Room', price: '₹2,250/night' }
};
const selectedRoom = roomDetails[formData.roomType as keyof typeof roomDetails];
const emailContent = `
<h2>New Booking Request</h2>
<p><strong>Phone:</strong> ${formData.phone}</p>
<p><strong>Email:</strong> ${formData.email}</p>
<p><strong>Age:</strong> ${formData.age}</p>
<p><strong>Room Type:</strong> ${selectedRoom.name}</p>
<p><strong>Room Price:</strong> ${selectedRoom.price}</p>
<p><strong>Payment Method:</strong> ${formData.paymentMethod === 'online' ? 'Online Payment' : 'Pay at Counter'}</p>
<p><strong>Booking Date:</strong> ${new Date().toLocaleString()}</p>
`;
const response = await fetch('/api/send-booking-email', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
recipientEmail: 'contact@hotelshineinn.com',
subject: 'New Booking Request - Hotel Shine Inn',
htmlContent: emailContent,
bookingData: formData,
roomDetails: selectedRoom
})
});
if (response.ok) {
setSubmitMessage('✓ Booking request submitted successfully! We will contact you soon.');
setFormData({
phone: '',
email: '',
age: '',
roomType: 'deluxe',
paymentMethod: 'online'
});
setTimeout(() => {
setIsBookingModalOpen(false);
}, 2000);
} else {
setSubmitMessage('✗ Failed to submit booking. Please try again.');
}
} catch (error) {
setSubmitMessage('✗ Error submitting booking. Please try again or call us directly.');
console.error('Booking submission error:', error);
} finally {
setIsSubmitting(false);
}
};
return (
<ThemeProvider
defaultButtonVariant="hover-magnetic"
@@ -40,10 +134,151 @@ export default function LandingPage() {
{ name: "Reviews", id: "reviews" },
{ name: "Contact", id: "contact" }
]}
button={{ text: "Book Room", href: "#contact" }}
button={{ text: "Book Now", onClick: handleBookNowClick }}
/>
</div>
{/* Booking Modal */}
{isBookingModalOpen && (
<div className="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4">
<div className="bg-white rounded-lg shadow-lg max-w-md w-full max-h-[90vh] overflow-y-auto">
<div className="sticky top-0 bg-white border-b border-gray-200 p-6 flex justify-between items-center">
<h2 className="text-2xl font-bold text-gray-900">Book Your Room</h2>
<button
onClick={() => setIsBookingModalOpen(false)}
className="text-gray-500 hover:text-gray-700 transition"
>
<X size={24} />
</button>
</div>
<form onSubmit={handleFormSubmit} className="p-6 space-y-4">
{/* Phone Number */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Phone Number *
</label>
<input
type="tel"
name="phone"
value={formData.phone}
onChange={handleFormChange}
placeholder="+91 XXXXX XXXXX"
required
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition"
/>
</div>
{/* Email */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Email Address *
</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleFormChange}
placeholder="your.email@example.com"
required
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition"
/>
</div>
{/* Age */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Age *
</label>
<input
type="number"
name="age"
value={formData.age}
onChange={handleFormChange}
placeholder="Enter your age"
min="18"
max="120"
required
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition"
/>
</div>
{/* Room Type */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Select Room Type *
</label>
<select
name="roomType"
value={formData.roomType}
onChange={handleFormChange}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition"
>
<option value="deluxe">Deluxe Couple Room - 1,950/night</option>
<option value="standard">Standard AC Room - 1,450/night</option>
<option value="premium">Premium Comfort Room - 2,250/night</option>
</select>
</div>
{/* Payment Method */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Payment Method *
</label>
<div className="space-y-2">
<label className="flex items-center">
<input
type="radio"
name="paymentMethod"
value="online"
checked={formData.paymentMethod === 'online'}
onChange={handleFormChange}
className="w-4 h-4 text-blue-600 border-gray-300 focus:ring-blue-500"
/>
<span className="ml-3 text-sm text-gray-700">Online Payment</span>
</label>
<label className="flex items-center">
<input
type="radio"
name="paymentMethod"
value="counter"
checked={formData.paymentMethod === 'counter'}
onChange={handleFormChange}
className="w-4 h-4 text-blue-600 border-gray-300 focus:ring-blue-500"
/>
<span className="ml-3 text-sm text-gray-700">Pay at Counter</span>
</label>
</div>
</div>
{/* Submit Message */}
{submitMessage && (
<div className={`p-3 rounded-lg text-sm ${
submitMessage.includes('✓')
? 'bg-green-100 text-green-800'
: 'bg-red-100 text-red-800'
}`}>
{submitMessage}
</div>
)}
{/* Submit Button */}
<button
type="submit"
disabled={isSubmitting}
className="w-full bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 text-white font-semibold py-3 rounded-lg transition duration-200"
>
{isSubmitting ? 'Submitting...' : 'Confirm Booking'}
</button>
<p className="text-xs text-gray-500 text-center">
By booking, you agree to our terms and conditions
</p>
</form>
</div>
</div>
)}
<div id="hero" data-section="hero">
<HeroBillboardDashboard
background={{ variant: "radial-gradient" }}
@@ -53,7 +288,7 @@ export default function LandingPage() {
title="Hotel Shine Inn Comfortable Couple-Friendly Stay in Rohini"
description="Affordable, comfortable and private rooms near Rohini West Metro Station. Experience modern luxury with exceptional hospitality tailored for couples and travelers."
buttons={[
{ text: "Book Room", href: "#contact" },
{ text: "Book Room", onClick: handleBookNowClick },
{ text: "Call Now", onClick: handleCallNow }
]}
buttonAnimation="slide-up"
@@ -139,15 +374,15 @@ export default function LandingPage() {
products={[
{
id: "1", brand: "Hotel Shine Inn", name: "Deluxe Couple Room", price: "₹1,950/night", rating: 5,
reviewCount: "156", imageSrc: "http://img.b2bpic.net/free-photo/weekend-photo-couple-playing-with-labrador-sunny-bedroom-guy-girl-are-stroking-belly-big-dog_197531-13742.jpg", imageAlt: "Deluxe Couple Room"
reviewCount: "156", imageSrc: "http://img.b2bpic.net/free-photo/weekend-photo-couple-playing-with-labrador-sunny-bedroom-guy-girl-are-stroking-belly-big-dog_197531-13742.jpg", imageAlt: "Deluxe Couple Room", onProductClick: handleBookNowClick
},
{
id: "2", brand: "Hotel Shine Inn", name: "Standard AC Room", price: "₹1,450/night", rating: 4,
reviewCount: "203", imageSrc: "http://img.b2bpic.net/free-photo/bed-with-armchair_1203-741.jpg", imageAlt: "Standard AC Room"
reviewCount: "203", imageSrc: "http://img.b2bpic.net/free-photo/bed-with-armchair_1203-741.jpg", imageAlt: "Standard AC Room", onProductClick: handleBookNowClick
},
{
id: "3", brand: "Hotel Shine Inn", name: "Premium Comfort Room", price: "₹2,250/night", rating: 5,
reviewCount: "98", imageSrc: "http://img.b2bpic.net/free-photo/modern-sauna-with-panoramic-windows-wooden-design_169016-70021.jpg", imageAlt: "Premium Comfort Room"
reviewCount: "98", imageSrc: "http://img.b2bpic.net/free-photo/modern-sauna-with-panoramic-windows-wooden-design_169016-70021.jpg", imageAlt: "Premium Comfort Room", onProductClick: handleBookNowClick
}
]}
textboxLayout="default"
@@ -267,4 +502,4 @@ export default function LandingPage() {
</div>
</ThemeProvider>
);
}
}