Merge version_4 into main #5
@@ -9,8 +9,8 @@ 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 { useState, useEffect } from "react";
|
||||
import { Star, Sparkles, Award, Heart, Mail, CheckCircle } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import React from "react";
|
||||
|
||||
interface TimeSlot {
|
||||
@@ -50,31 +50,38 @@ 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">
|
||||
{Array.from({ length: 30 }).map((_, i) => {
|
||||
const randomDelay = Math.random() * 2;
|
||||
const randomDuration = 3 + Math.random() * 2;
|
||||
const randomX = Math.random() * 100;
|
||||
const randomY = Math.random() * 100;
|
||||
const randomSize = 2 + Math.random() * 4;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={i}
|
||||
className="absolute rounded-full bg-magenta-500 opacity-60"
|
||||
style={{
|
||||
width: `${randomSize}px`,
|
||||
height: `${randomSize}px`,
|
||||
left: `${randomX}%`,
|
||||
top: `${randomY}%`,
|
||||
animation: `float-dots ${randomDuration}s ease-in-out ${randomDelay}s infinite`,
|
||||
backgroundColor: '#ff00ff',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{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% {
|
||||
@@ -82,7 +89,7 @@ function FloatingDotsAnimation() {
|
||||
opacity: 0.3;
|
||||
}
|
||||
50% {
|
||||
transform: translate(${Math.random() * 100 - 50}px, ${Math.random() * 100 - 50}px) scale(1.2);
|
||||
transform: translate(var(--tx), var(--ty)) scale(1.2);
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
@@ -151,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++) {
|
||||
@@ -183,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>
|
||||
|
||||
@@ -241,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>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user