3 Commits

Author SHA1 Message Date
79e16537c6 Update src/app/page.tsx 2026-03-07 16:41:20 +00:00
39d5c1f99c Update src/app/page.tsx 2026-03-07 16:39:23 +00:00
2476b1f9d4 Merge version_3 into main
Merge version_3 into main
2026-03-07 14:44:03 +00:00

View File

@@ -9,7 +9,7 @@ import FeatureCardOne from "@/components/sections/feature/FeatureCardOne";
import TestimonialCardSix from "@/components/sections/testimonial/TestimonialCardSix";
import ContactSplit from "@/components/sections/contact/ContactSplit";
import FooterBase from "@/components/sections/footer/FooterBase";
import { Star, Sparkles, Award, Heart, Mail, Calendar, X, Clock, Users, CheckCircle } from "lucide-react";
import { Star, Sparkles, Award, Heart, Mail, CheckCircle } from "lucide-react";
import { useState } from "react";
import React from "react";
@@ -50,6 +50,54 @@ const TIME_SLOTS: TimeSlot[] = [
{ time: '04:00 PM', available: true },
];
// Pre-generate random values outside of render to avoid impure function violations
const generateRandomValues = () => {
return Array.from({ length: 30 }).map(() => ({
delay: Math.random() * 2,
duration: 3 + Math.random() * 2,
x: Math.random() * 100,
y: Math.random() * 100,
size: 2 + Math.random() * 4,
offsetX: Math.random() * 100 - 50,
offsetY: Math.random() * 100 - 50,
}));
};
const RANDOM_VALUES = generateRandomValues();
function FloatingDotsAnimation() {
return (
<div className="fixed inset-0 pointer-events-none overflow-hidden">
{RANDOM_VALUES.map((values, i) => (
<div
key={i}
className="absolute rounded-full bg-magenta-500 opacity-60"
style={{
width: `${values.size}px`,
height: `${values.size}px`,
left: `${values.x}%`,
top: `${values.y}%`,
animation: `float-dots ${values.duration}s ease-in-out ${values.delay}s infinite`,
backgroundColor: '#ff00ff',
}}
/>
))}
<style>{`
@keyframes float-dots {
0%, 100% {
transform: translate(0, 0) scale(1);
opacity: 0.3;
}
50% {
transform: translate(var(--tx), var(--ty)) scale(1.2);
opacity: 0.8;
}
}
`}</style>
</div>
);
}
function BookingModal({ isOpen, onClose, onSubmit }: { isOpen: boolean; onClose: () => void; onSubmit: (data: any) => void }) {
const [state, setState] = React.useState<BookingState>({
isOpen,
@@ -110,12 +158,6 @@ function BookingModal({ isOpen, onClose, onSubmit }: { isOpen: boolean; onClose:
onClose();
};
const getNextAvailableDate = () => {
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
return tomorrow.toISOString().split('T')[0];
};
const getDateRangeOptions = () => {
const dates = [];
for (let i = 1; i <= 30; i++) {
@@ -142,7 +184,7 @@ function BookingModal({ isOpen, onClose, onSubmit }: { isOpen: boolean; onClose:
onClick={onClose}
className="p-2 hover:bg-blue-200 rounded-lg transition"
>
<X size={24} className="text-gray-600" />
<svg className="w-6 h-6 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" /></svg>
</button>
</div>
@@ -200,7 +242,7 @@ function BookingModal({ isOpen, onClose, onSubmit }: { isOpen: boolean; onClose:
>
<div className="font-semibold text-gray-900">{service.name}</div>
<div className="text-sm text-gray-500 flex items-center gap-1 mt-1">
<Clock size={14} /> {service.duration}
<svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg> {service.duration}
</div>
</button>
))}
@@ -358,7 +400,6 @@ export default function LandingPage() {
const handleBookingSubmit = (data: any) => {
console.log('Booking submitted:', data);
// Here you would typically send this to your backend
alert(`Booking confirmed for ${data.name} on ${data.date} at ${data.time}`);
};
@@ -375,6 +416,7 @@ export default function LandingPage() {
secondaryButtonStyle="solid"
headingFontWeight="light"
>
<FloatingDotsAnimation />
<BookingModal
isOpen={bookingOpen}
onClose={() => setBookingOpen(false)}