Update src/app/page.tsx
This commit is contained in:
213
src/app/page.tsx
213
src/app/page.tsx
@@ -11,9 +11,75 @@ import SocialProofOne from "@/components/sections/socialProof/SocialProofOne";
|
||||
import FaqSplitText from "@/components/sections/faq/FaqSplitText";
|
||||
import FooterLogoEmphasis from "@/components/sections/footer/FooterLogoEmphasis";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import { Award, CheckCircle, Crown, Heart, Shield, Sparkles } from "lucide-react";
|
||||
import { Award, CheckCircle, Crown, Heart, Shield, Sparkles, Calendar, Clock, Users } from "lucide-react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
interface TimeSlot {
|
||||
time: string;
|
||||
available: boolean;
|
||||
}
|
||||
|
||||
interface DaySlots {
|
||||
date: string;
|
||||
day: string;
|
||||
slots: TimeSlot[];
|
||||
}
|
||||
|
||||
export default function LandingPage() {
|
||||
const [calendarData, setCalendarData] = useState<DaySlots[]>([]);
|
||||
const [selectedDate, setSelectedDate] = useState<string | null>(null);
|
||||
const [selectedSlot, setSelectedSlot] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// Generate availability calendar for next 7 days
|
||||
const generateCalendar = () => {
|
||||
const days: DaySlots[] = [];
|
||||
const today = new Date();
|
||||
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const date = new Date(today);
|
||||
date.setDate(date.getDate() + i);
|
||||
const dateStr = date.toISOString().split('T')[0];
|
||||
const dayName = date.toLocaleDateString('en-US', { weekday: 'short' });
|
||||
|
||||
const slots: TimeSlot[] = [];
|
||||
const hours = [9, 10, 11, 13, 14, 15, 16, 17];
|
||||
|
||||
for (const hour of hours) {
|
||||
// Simulate availability - 80% slots available
|
||||
const available = Math.random() > 0.2;
|
||||
slots.push({
|
||||
time: `${hour.toString().padStart(2, '0')}:00`,
|
||||
available,
|
||||
});
|
||||
}
|
||||
|
||||
days.push({
|
||||
date: dateStr,
|
||||
day: dayName,
|
||||
slots,
|
||||
});
|
||||
}
|
||||
|
||||
setCalendarData(days);
|
||||
if (days.length > 0) {
|
||||
setSelectedDate(days[0].date);
|
||||
}
|
||||
};
|
||||
|
||||
generateCalendar();
|
||||
}, []);
|
||||
|
||||
const getAvailableCount = (date: string): number => {
|
||||
const day = calendarData.find(d => d.date === date);
|
||||
return day ? day.slots.filter(s => s.available).length : 0;
|
||||
};
|
||||
|
||||
const getSelectedDaySlots = (): TimeSlot[] => {
|
||||
const day = calendarData.find(d => d.date === selectedDate);
|
||||
return day ? day.slots : [];
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="expand-hover"
|
||||
@@ -34,7 +100,7 @@ export default function LandingPage() {
|
||||
{ name: "Shop", id: "products" },
|
||||
{ name: "About", id: "about" },
|
||||
{ name: "Testimonials", id: "testimonials" },
|
||||
{ name: "Contact", id: "contact" },
|
||||
{ name: "Book Consultation", id: "availability" },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
@@ -206,6 +272,145 @@ export default function LandingPage() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="availability" data-section="availability" className="py-20">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
{/* Header */}
|
||||
<div className="mb-12 text-center">
|
||||
<div className="inline-flex items-center gap-2 mb-4 px-4 py-2 rounded-full bg-opacity-10 backdrop-blur">
|
||||
<Calendar className="w-4 h-4" />
|
||||
<span className="text-sm font-medium">Consultation Booking</span>
|
||||
</div>
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-4">Schedule Your Personal Consultation</h2>
|
||||
<p className="text-lg text-opacity-70 max-w-2xl mx-auto">Book a consultation with our beauty experts to find the perfect products and routine for your skin type.</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
{/* Calendar */}
|
||||
<div className="lg:col-span-2">
|
||||
<div className="rounded-lg border border-opacity-20 p-8 backdrop-blur">
|
||||
<h3 className="text-2xl font-bold mb-6 flex items-center gap-2">
|
||||
<Calendar className="w-6 h-6" />
|
||||
Available Dates
|
||||
</h3>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
|
||||
{calendarData.map((day) => (
|
||||
<button
|
||||
key={day.date}
|
||||
onClick={() => setSelectedDate(day.date)}
|
||||
className={`p-4 rounded-lg border-2 transition-all ${
|
||||
selectedDate === day.date
|
||||
? 'border-opacity-100 bg-opacity-20'
|
||||
: 'border-opacity-20 hover:border-opacity-40'
|
||||
}`}
|
||||
>
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="text-left">
|
||||
<p className="font-semibold">{day.day}</p>
|
||||
<p className="text-sm opacity-70">{new Date(day.date).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}</p>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<p className="font-bold text-lg">{getAvailableCount(day.date)}</p>
|
||||
<p className="text-xs opacity-70">slots</p>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Time Slots */}
|
||||
<div>
|
||||
<h4 className="text-xl font-bold mb-4 flex items-center gap-2">
|
||||
<Clock className="w-5 h-5" />
|
||||
Available Times
|
||||
</h4>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
||||
{getSelectedDaySlots().map((slot, idx) => (
|
||||
<button
|
||||
key={idx}
|
||||
onClick={() => slot.available && setSelectedSlot(slot.time)}
|
||||
disabled={!slot.available}
|
||||
className={`py-3 px-4 rounded-lg font-semibold transition-all ${
|
||||
!slot.available
|
||||
? 'opacity-30 cursor-not-allowed'
|
||||
: selectedSlot === slot.time
|
||||
? 'bg-opacity-100 text-white shadow-lg transform scale-105'
|
||||
: 'hover:bg-opacity-20'
|
||||
}`}
|
||||
>
|
||||
{slot.time}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Booking Summary */}
|
||||
<div className="lg:col-span-1">
|
||||
<div className="rounded-lg border border-opacity-20 p-8 backdrop-blur sticky top-20">
|
||||
<h3 className="text-xl font-bold mb-6 flex items-center gap-2">
|
||||
<Users className="w-5 h-5" />
|
||||
Booking Summary
|
||||
</h3>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<p className="text-sm opacity-70 mb-2">Selected Date</p>
|
||||
<p className="font-bold text-lg">
|
||||
{selectedDate
|
||||
? new Date(selectedDate).toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' })
|
||||
: 'No date selected'}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="text-sm opacity-70 mb-2">Selected Time</p>
|
||||
<p className="font-bold text-lg">
|
||||
{selectedSlot ? selectedSlot : 'No time selected'}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="text-sm opacity-70 mb-2">Consultation Type</p>
|
||||
<p className="font-bold">30-Minute Personal Consultation</p>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-opacity-20 pt-4 mt-6">
|
||||
<p className="text-sm opacity-70 mb-3">What to Expect:</p>
|
||||
<ul className="space-y-2 text-sm">
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle className="w-4 h-4 flex-shrink-0 mt-0.5" />
|
||||
<span>Personalized skin analysis</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle className="w-4 h-4 flex-shrink-0 mt-0.5" />
|
||||
<span>Product recommendations</span>
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle className="w-4 h-4 flex-shrink-0 mt-0.5" />
|
||||
<span>Custom routine guidance</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<button
|
||||
disabled={!selectedDate || !selectedSlot}
|
||||
className={`w-full py-3 px-4 rounded-lg font-bold transition-all mt-6 ${
|
||||
selectedDate && selectedSlot
|
||||
? 'hover:shadow-lg hover:scale-105'
|
||||
: 'opacity-50 cursor-not-allowed'
|
||||
}`}
|
||||
>
|
||||
Confirm Booking
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="socialproof" data-section="socialproof">
|
||||
<SocialProofOne
|
||||
title="Trusted by Beauty Experts"
|
||||
@@ -276,7 +481,7 @@ export default function LandingPage() {
|
||||
{
|
||||
items: [
|
||||
{ label: "Help Center", href: "#faq" },
|
||||
{ label: "Contact Us", href: "#" },
|
||||
{ label: "Book Consultation", href: "#availability" },
|
||||
{ label: "Shipping Info", href: "#" },
|
||||
{ label: "Track Order", href: "#" },
|
||||
],
|
||||
@@ -294,4 +499,4 @@ export default function LandingPage() {
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user