fix : call button #26
File diff suppressed because one or more lines are too long
|
|
@ -170,12 +170,12 @@ export function BookingConfirmation({
|
|||
{bookingData.dropoff.includes("Airport Taxi") ? "Airport Taxi Fee" : "Customize Price"}
|
||||
</span>
|
||||
<span className="text-xl font-semibold text-green-600">
|
||||
{bookingData.dropoff.includes("Airport Taxi") ? "₹1099" : "Call for Quote"}
|
||||
{bookingData.dropoff.includes("Airport Taxi") ? "₹999" : "Call for Quote"}
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-sm text-muted-foreground text-center">
|
||||
{bookingData.dropoff.includes("Airport Taxi")
|
||||
? `₹1099 fixed rate for airport taxi. Driver will contact you at ${bookingData.contactNumber} for pickup details.`
|
||||
? `₹999 fixed rate for airport taxi. Driver will contact you at ${bookingData.contactNumber} for pickup details.`
|
||||
: `Driver will contact you at ${bookingData.contactNumber} for final pricing and trip details.`}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ export function BookingForm({ onSubmit }: BookingFormProps) {
|
|||
|
||||
const currentDate = new Date().toISOString().split('T')[0];
|
||||
const currentTime = new Date().toTimeString().slice(0, 5);
|
||||
|
||||
|
||||
|
||||
|
||||
return (
|
||||
|
|
@ -48,248 +48,248 @@ export function BookingForm({ onSubmit }: BookingFormProps) {
|
|||
className="w-full max-w-2xl mx-auto"
|
||||
>
|
||||
<Card className="w-full bg-white border-0 shadow-none">
|
||||
<CardHeader className="text-center pb-4 sm:pb-6 lg:pb-8 bg-transparent px-4 sm:px-6 rounded-[0px]">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: -20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6 }}
|
||||
>
|
||||
<CardTitle className="flex flex-col sm:flex-row items-center justify-center gap-2 text-center text-lg sm:text-xl lg:text-2xl bg-gradient-to-r from-primary to-primary/80 bg-clip-text text-transparent">
|
||||
<div className="mb-1 sm:mb-0">
|
||||
<MapPin className="h-5 w-5 sm:h-6 sm:w-6 text-primary" />
|
||||
</div>
|
||||
<span className="font-bold leading-tight text-[32px]">Book Your Airport Taxi Now</span>
|
||||
</CardTitle>
|
||||
</motion.div>
|
||||
<motion.div
|
||||
className="w-16 sm:w-20 lg:w-24 h-1 bg-gradient-to-r from-primary/30 via-primary to-primary/30 mx-auto mt-2 sm:mt-3 lg:mt-4 rounded-full"
|
||||
initial={{ scaleX: 0 }}
|
||||
animate={{ scaleX: 1 }}
|
||||
transition={{ delay: 0.3, duration: 0.8 }}
|
||||
/>
|
||||
<CardHeader className="text-center pb-4 sm:pb-6 lg:pb-8 bg-transparent px-4 sm:px-6 rounded-[0px]">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: -20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6 }}
|
||||
>
|
||||
<CardTitle className="flex flex-col sm:flex-row items-center justify-center gap-2 text-center text-lg sm:text-xl lg:text-2xl bg-gradient-to-r from-primary to-primary/80 bg-clip-text text-transparent">
|
||||
<div className="mb-1 sm:mb-0">
|
||||
<MapPin className="h-5 w-5 sm:h-6 sm:w-6 text-primary" />
|
||||
</div>
|
||||
<span className="font-bold leading-tight text-[32px]">Book Your Airport Taxi Now</span>
|
||||
</CardTitle>
|
||||
</motion.div>
|
||||
<motion.div
|
||||
className="w-16 sm:w-20 lg:w-24 h-1 bg-gradient-to-r from-primary/30 via-primary to-primary/30 mx-auto mt-2 sm:mt-3 lg:mt-4 rounded-full"
|
||||
initial={{ scaleX: 0 }}
|
||||
animate={{ scaleX: 1 }}
|
||||
transition={{ delay: 0.3, duration: 0.8 }}
|
||||
/>
|
||||
|
||||
</CardHeader>
|
||||
<CardContent className="bg-transparent px-4 sm:px-6 pt-[0px] pr-[21px] pb-[21px] pl-[21px]">
|
||||
<form onSubmit={handleSubmit} className="space-y-4 sm:space-y-6">
|
||||
{/* Location Inputs */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
|
||||
</CardHeader>
|
||||
<CardContent className="bg-transparent px-4 sm:px-6 pt-[0px] pr-[21px] pb-[21px] pl-[21px]">
|
||||
<form onSubmit={handleSubmit} className="space-y-4 sm:space-y-6">
|
||||
{/* Location Inputs */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="pickup" className="text-sm sm:text-base">Pickup Location</Label>
|
||||
<Select value={formData.pickup} onValueChange={(value) => handleInputChange("pickup", value)} required>
|
||||
<SelectTrigger className="h-10 sm:h-11">
|
||||
<SelectValue placeholder="Select pickup city" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="max-h-48">
|
||||
{indiaLocations.map((location) => (
|
||||
<SelectItem key={location} value={location}>
|
||||
{location}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="dropoff" className="text-sm sm:text-base">Drop-off Location / Service</Label>
|
||||
<Select value={formData.dropoff} onValueChange={(value) => handleInputChange("dropoff", value)} required>
|
||||
<SelectTrigger className="h-10 sm:h-11">
|
||||
<SelectValue placeholder="Select destination or service" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="max-h-48">
|
||||
<div className="px-2 py-1 text-xs text-muted-foreground border-b">Services</div>
|
||||
{serviceTypes.map((service) => (
|
||||
<SelectItem key={service} value={service}>
|
||||
{service}
|
||||
</SelectItem>
|
||||
))}
|
||||
<div className="px-2 py-1 text-xs text-muted-foreground border-b">All India Locations</div>
|
||||
{indiaLocations.map((location) => (
|
||||
<SelectItem key={location} value={location}>
|
||||
{location}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Date and Time */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="date" className="flex items-center gap-2 text-sm sm:text-base">
|
||||
<Calendar className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||
Date
|
||||
</Label>
|
||||
<Input
|
||||
id="date"
|
||||
type="date"
|
||||
min={currentDate}
|
||||
value={formData.date}
|
||||
onChange={(e) => handleInputChange("date", e.target.value)}
|
||||
className="h-10 sm:h-11"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="time" className="flex items-center gap-2 text-sm sm:text-base">
|
||||
<Clock className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||
Time
|
||||
</Label>
|
||||
<Input
|
||||
id="time"
|
||||
type="time"
|
||||
value={formData.time}
|
||||
onChange={(e) => handleInputChange("time", e.target.value)}
|
||||
className="h-10 sm:h-11"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Contact Information */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="contactName" className="flex items-center gap-2 text-sm sm:text-base">
|
||||
<User className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||
Contact Name
|
||||
</Label>
|
||||
<Input
|
||||
id="contactName"
|
||||
type="text"
|
||||
placeholder="Enter your name"
|
||||
value={formData.contactName}
|
||||
onChange={(e) => handleInputChange("contactName", e.target.value)}
|
||||
className="h-10 sm:h-11"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="contactNumber" className="flex items-center gap-2 text-sm sm:text-base">
|
||||
<Phone className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||
Contact Number
|
||||
</Label>
|
||||
<Input
|
||||
id="contactNumber"
|
||||
type="tel"
|
||||
placeholder="Enter your contact number"
|
||||
value={formData.contactNumber}
|
||||
onChange={(e) => handleInputChange("contactNumber", e.target.value)}
|
||||
className="h-10 sm:h-11"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Email (Optional) */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="pickup" className="text-sm sm:text-base">Pickup Location</Label>
|
||||
<Select value={formData.pickup} onValueChange={(value) => handleInputChange("pickup", value)} required>
|
||||
<SelectTrigger className="h-10 sm:h-11">
|
||||
<SelectValue placeholder="Select pickup city" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="max-h-48">
|
||||
{indiaLocations.map((location) => (
|
||||
<SelectItem key={location} value={location}>
|
||||
{location}
|
||||
<Label htmlFor="customerEmail" className="flex items-center gap-2 text-sm sm:text-base">
|
||||
<Mail className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||
Email Address <span className="text-xs text-muted-foreground">(For booking confirmation)</span>
|
||||
</Label>
|
||||
<Input
|
||||
id="customerEmail"
|
||||
type="email"
|
||||
placeholder="Enter your email address"
|
||||
// value={formData.customerEmail}
|
||||
onChange={(e) => handleInputChange("customerEmail", e.target.value)}
|
||||
className="h-10 sm:h-11"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Passengers and Vehicle Type */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label className="flex items-center gap-2 text-sm sm:text-base">
|
||||
<Users className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||
Passengers
|
||||
</Label>
|
||||
<Select value={formData.passengers} onValueChange={(value) => handleInputChange("passengers", value)}>
|
||||
<SelectTrigger className="h-10 sm:h-11">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="1">1 Passenger</SelectItem>
|
||||
<SelectItem value="2">2 Passengers</SelectItem>
|
||||
<SelectItem value="3">3 Passengers</SelectItem>
|
||||
<SelectItem value="4">4 Passengers</SelectItem>
|
||||
<SelectItem value="5">5 Passengers</SelectItem>
|
||||
<SelectItem value="6">6 Passengers</SelectItem>
|
||||
<SelectItem value="7">7 Passengers</SelectItem>
|
||||
<SelectItem value="8">8+ Passengers</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label className="text-sm sm:text-base">Vehicle Type</Label>
|
||||
<Select value={formData.vehicleType} onValueChange={(value) => handleInputChange("vehicleType", value)} required>
|
||||
<SelectTrigger className="h-10 sm:h-11">
|
||||
<SelectValue placeholder="Select vehicle" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="5-seater">
|
||||
<span className="text-xs sm:text-sm">5 Seater - Airport Taxi </span>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="dropoff" className="text-sm sm:text-base">Drop-off Location / Service</Label>
|
||||
<Select value={formData.dropoff} onValueChange={(value) => handleInputChange("dropoff", value)} required>
|
||||
<SelectTrigger className="h-10 sm:h-11">
|
||||
<SelectValue placeholder="Select destination or service" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="max-h-48">
|
||||
<div className="px-2 py-1 text-xs text-muted-foreground border-b">Services</div>
|
||||
{serviceTypes.map((service) => (
|
||||
<SelectItem key={service} value={service}>
|
||||
{service}
|
||||
<SelectItem value="7-seater">
|
||||
<span className="text-xs sm:text-sm">7 Seater (Ertiga) - Airport Taxi </span>
|
||||
</SelectItem>
|
||||
))}
|
||||
<div className="px-2 py-1 text-xs text-muted-foreground border-b">All India Locations</div>
|
||||
{indiaLocations.map((location) => (
|
||||
<SelectItem key={location} value={location}>
|
||||
{location}
|
||||
<SelectItem value="innova">
|
||||
<span className="text-xs sm:text-sm">Innova - Airport Taxi </span>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Date and Time */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="date" className="flex items-center gap-2 text-sm sm:text-base">
|
||||
<Calendar className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||
Date
|
||||
</Label>
|
||||
<Input
|
||||
id="date"
|
||||
type="date"
|
||||
min={currentDate}
|
||||
value={formData.date}
|
||||
onChange={(e) => handleInputChange("date", e.target.value)}
|
||||
className="h-10 sm:h-11"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="time" className="flex items-center gap-2 text-sm sm:text-base">
|
||||
<Clock className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||
Time
|
||||
</Label>
|
||||
<Input
|
||||
id="time"
|
||||
type="time"
|
||||
value={formData.time}
|
||||
onChange={(e) => handleInputChange("time", e.target.value)}
|
||||
className="h-10 sm:h-11"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Contact Information */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="contactName" className="flex items-center gap-2 text-sm sm:text-base">
|
||||
<User className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||
Contact Name
|
||||
</Label>
|
||||
<Input
|
||||
id="contactName"
|
||||
type="text"
|
||||
placeholder="Enter your name"
|
||||
value={formData.contactName}
|
||||
onChange={(e) => handleInputChange("contactName", e.target.value)}
|
||||
className="h-10 sm:h-11"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="contactNumber" className="flex items-center gap-2 text-sm sm:text-base">
|
||||
<Phone className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||
Contact Number
|
||||
</Label>
|
||||
<Input
|
||||
id="contactNumber"
|
||||
type="tel"
|
||||
placeholder="Enter your contact number"
|
||||
value={formData.contactNumber}
|
||||
onChange={(e) => handleInputChange("contactNumber", e.target.value)}
|
||||
className="h-10 sm:h-11"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Email (Optional) */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="customerEmail" className="flex items-center gap-2 text-sm sm:text-base">
|
||||
<Mail className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||
Email Address <span className="text-xs text-muted-foreground">(For booking confirmation)</span>
|
||||
</Label>
|
||||
<Input
|
||||
id="customerEmail"
|
||||
type="email"
|
||||
placeholder="Enter your email address"
|
||||
value={formData.customerEmail}
|
||||
onChange={(e) => handleInputChange("customerEmail", e.target.value)}
|
||||
className="h-10 sm:h-11"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Passengers and Vehicle Type */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label className="flex items-center gap-2 text-sm sm:text-base">
|
||||
<Users className="h-3 w-3 sm:h-4 sm:w-4" />
|
||||
Passengers
|
||||
</Label>
|
||||
<Select value={formData.passengers} onValueChange={(value) => handleInputChange("passengers", value)}>
|
||||
<SelectTrigger className="h-10 sm:h-11">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="1">1 Passenger</SelectItem>
|
||||
<SelectItem value="2">2 Passengers</SelectItem>
|
||||
<SelectItem value="3">3 Passengers</SelectItem>
|
||||
<SelectItem value="4">4 Passengers</SelectItem>
|
||||
<SelectItem value="5">5 Passengers</SelectItem>
|
||||
<SelectItem value="6">6 Passengers</SelectItem>
|
||||
<SelectItem value="7">7 Passengers</SelectItem>
|
||||
<SelectItem value="8">8+ Passengers</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label className="text-sm sm:text-base">Vehicle Type</Label>
|
||||
<Select value={formData.vehicleType} onValueChange={(value) => handleInputChange("vehicleType", value)} required>
|
||||
<SelectTrigger className="h-10 sm:h-11">
|
||||
<SelectValue placeholder="Select vehicle" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="5-seater">
|
||||
<span className="text-xs sm:text-sm">5 Seater - Airport Taxi </span>
|
||||
</SelectItem>
|
||||
<SelectItem value="7-seater">
|
||||
<span className="text-xs sm:text-sm">7 Seater (Ertiga) - Airport Taxi </span>
|
||||
</SelectItem>
|
||||
<SelectItem value="innova">
|
||||
<span className="text-xs sm:text-sm">Innova - Airport Taxi </span>
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3 sm:space-y-4">
|
||||
<motion.div
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
<Button type="submit" className="w-full h-11 sm:h-12 text-sm sm:text-base shadow-lg hover:shadow-xl transition-all duration-300 rounded-[8px]">
|
||||
<span className="font-semibold">
|
||||
Book Your Airport Taxi
|
||||
</span>
|
||||
</Button>
|
||||
</motion.div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-px bg-border flex-1"></div>
|
||||
<span className="text-xs text-muted-foreground px-2">OR</span>
|
||||
<div className="h-px bg-border flex-1"></div>
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
className="relative"
|
||||
>
|
||||
<div className="space-y-3 sm:space-y-4">
|
||||
<motion.div
|
||||
className="absolute inset-0 bg-gradient-to-r from-green-400 to-green-600 rounded-lg"
|
||||
animate={{
|
||||
opacity: [0.8, 1, 0.8],
|
||||
scale: [1, 1.02, 1]
|
||||
}}
|
||||
transition={{
|
||||
duration: 2,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut"
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
className="w-full h-11 sm:h-12 relative z-10 bg-gradient-to-r from-green-500 to-green-600 hover:from-green-600 hover:to-green-700 text-white border-0 shadow-lg"
|
||||
onClick={() => window.open('tel:+91-7477247488', '_self')}
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
<Phone className="h-3 w-3 sm:h-4 sm:w-4 mr-2" />
|
||||
<div className="text-center">
|
||||
<div className="font-semibold text-sm sm:text-base">Call to Book Taxi</div>
|
||||
<div className="text-xs opacity-90">7477247488</div>
|
||||
</div>
|
||||
</Button>
|
||||
</motion.div>
|
||||
</div>
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Button type="submit" className="w-full h-11 sm:h-12 text-sm sm:text-base shadow-lg hover:shadow-xl transition-all duration-300 rounded-[8px]">
|
||||
<span className="font-semibold">
|
||||
Book Your Airport Taxi
|
||||
</span>
|
||||
</Button>
|
||||
</motion.div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-px bg-border flex-1"></div>
|
||||
<span className="text-xs text-muted-foreground px-2">OR</span>
|
||||
<div className="h-px bg-border flex-1"></div>
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
className="relative"
|
||||
>
|
||||
<motion.div
|
||||
className="absolute inset-0 bg-gradient-to-r from-green-400 to-green-600 rounded-lg"
|
||||
animate={{
|
||||
opacity: [0.8, 1, 0.8],
|
||||
scale: [1, 1.02, 1]
|
||||
}}
|
||||
transition={{
|
||||
duration: 2,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut"
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
className="w-full h-11 sm:h-12 relative z-10 bg-gradient-to-r from-green-500 to-green-600 hover:from-green-600 hover:to-green-700 text-white border-0 shadow-lg"
|
||||
onClick={() => window.open('tel:+91-7477247488', '_self')}
|
||||
>
|
||||
<Phone className="h-3 w-3 sm:h-4 sm:w-4 mr-2" />
|
||||
<div className="text-center">
|
||||
<div className="font-semibold text-sm sm:text-base">Call to Book Taxi</div>
|
||||
<div className="text-xs opacity-90">7477247488</div>
|
||||
</div>
|
||||
</Button>
|
||||
</motion.div>
|
||||
</div>
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
|
@ -8,11 +8,11 @@ export function FloatingCallButton() {
|
|||
className="fixed bottom-4 right-4 sm:bottom-6 sm:right-6 z-50"
|
||||
initial={{ scale: 0, opacity: 0 }}
|
||||
animate={{ scale: 1, opacity: 1 }}
|
||||
transition={{
|
||||
transition={{
|
||||
delay: 1,
|
||||
type: "spring",
|
||||
stiffness: 200,
|
||||
damping: 20
|
||||
damping: 20,
|
||||
}}
|
||||
whileHover={{ scale: 1.05 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
|
|
@ -21,31 +21,34 @@ export function FloatingCallButton() {
|
|||
<Button
|
||||
size="lg"
|
||||
className="bg-transparent hover:bg-white/10 border-0 px-3 py-2 sm:px-4 sm:py-2 h-auto rounded-full"
|
||||
onClick={() => window.open('tel:+91-7477247488', '_self')}
|
||||
onClick={() => {
|
||||
// Opens dialpad directly on mobile
|
||||
window.location.href = "tel:+917477247488";
|
||||
}}
|
||||
>
|
||||
<div className="mr-1 sm:mr-2">
|
||||
<Phone className="h-4 w-4 sm:h-5 sm:w-5 text-white" />
|
||||
</div>
|
||||
<div className="text-white">
|
||||
<div className="text-white text-left">
|
||||
<div className="text-xs sm:text-sm font-bold">Call to Book</div>
|
||||
<div className="text-xs opacity-90">7477247488</div>
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
{/* Simple pulse effect */}
|
||||
|
||||
{/* Simple pulse animation */}
|
||||
<motion.div
|
||||
className="absolute inset-0 rounded-full bg-green-400/50"
|
||||
animate={{
|
||||
scale: [1, 1.5, 1],
|
||||
opacity: [0.7, 0, 0.7]
|
||||
opacity: [0.7, 0, 0.7],
|
||||
}}
|
||||
transition={{
|
||||
duration: 2,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut"
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ export function HeroSection({ children }: HeroSectionProps) {
|
|||
transition={{ duration: 0.8, delay: 0.4 }}
|
||||
className="block text-white"
|
||||
>
|
||||
Durg/Bhilai-Raipur Airport Drop(Oneway)
|
||||
Durg/Bhilai-Raipur Airport Drop(Oneway)
|
||||
</motion.span>
|
||||
<motion.span
|
||||
className="block text-yellow-400 text-xl sm:text-3xl md:text-4xl lg:text-5xl"
|
||||
|
|
@ -112,7 +112,7 @@ export function HeroSection({ children }: HeroSectionProps) {
|
|||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8, delay: 0.6 }}
|
||||
>
|
||||
₹1099
|
||||
₹999
|
||||
</motion.span>
|
||||
</motion.h1>
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ const services = [
|
|||
icon: Plane,
|
||||
title: "Airport Taxi",
|
||||
description: "Comfortable and punctual airport taxi services. Never miss a flight with our dedicated airport service.",
|
||||
features: ["Flight monitoring", "Meet & greet service", "Fixed rate ₹1099"],
|
||||
price: "₹1099",
|
||||
features: ["Flight monitoring", "Meet & greet service", "Fixed rate ₹999"],
|
||||
price: "₹999",
|
||||
image: "https://images.unsplash.com/photo-1733222012917-e9e74636080c?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxhaXJwb3J0JTIwdHJhbnNmZXIlMjBjYXIlMjBzZXJ2aWNlfGVufDF8fHx8MTc1NTYwMDgwM3ww&ixlib=rb-4.1.0&q=80&w=1080&utm_source=figma&utm_medium=referral",
|
||||
imageAlt: "Premium car at airport terminal"
|
||||
},
|
||||
|
|
@ -91,7 +91,7 @@ export function ServicesSection() {
|
|||
return (
|
||||
<div className="py-8 sm:py-12 lg:py-16">
|
||||
<div className="container mx-auto px-4">
|
||||
<motion.div
|
||||
<motion.div
|
||||
className="text-center mb-8 sm:mb-10 lg:mb-12"
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
|
|
@ -100,13 +100,13 @@ export function ServicesSection() {
|
|||
>
|
||||
<h1 className="mb-3 sm:mb-4 text-2xl sm:text-3xl lg:text-4xl font-normal font-bold">Our Services</h1>
|
||||
<p className="text-base sm:text-lg lg:text-xl text-muted-foreground max-w-3xl mx-auto px-4">
|
||||
From daily commutes to special occasions, we provide reliable transportation solutions
|
||||
From daily commutes to special occasions, we provide reliable transportation solutions
|
||||
tailored to your needs with professional drivers and well-maintained vehicles.
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
|
||||
{/* Main Services */}
|
||||
<motion.div
|
||||
<motion.div
|
||||
className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4 sm:gap-6 lg:gap-8 mb-8 sm:mb-10 lg:mb-12"
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
|
|
@ -117,7 +117,7 @@ export function ServicesSection() {
|
|||
<motion.div
|
||||
key={index}
|
||||
variants={cardVariants}
|
||||
whileHover={{
|
||||
whileHover={{
|
||||
y: -8,
|
||||
transition: { duration: 0.3 }
|
||||
}}
|
||||
|
|
@ -137,9 +137,9 @@ export function ServicesSection() {
|
|||
/>
|
||||
</motion.div>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent" />
|
||||
|
||||
|
||||
{/* Icon overlay */}
|
||||
<motion.div
|
||||
<motion.div
|
||||
className="absolute bottom-4 left-4"
|
||||
initial={{ scale: 0, opacity: 0 }}
|
||||
whileInView={{ scale: 1, opacity: 1 }}
|
||||
|
|
@ -148,11 +148,11 @@ export function ServicesSection() {
|
|||
>
|
||||
<div className="w-12 h-12 bg-white/90 backdrop-blur-sm rounded-lg flex items-center justify-center">
|
||||
<motion.div
|
||||
animate={{
|
||||
animate={{
|
||||
rotate: [0, 10, -10, 0],
|
||||
scale: [1, 1.1, 1]
|
||||
}}
|
||||
transition={{
|
||||
transition={{
|
||||
duration: 4,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut"
|
||||
|
|
@ -162,9 +162,9 @@ export function ServicesSection() {
|
|||
</motion.div>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
|
||||
{/* Price badge */}
|
||||
<motion.div
|
||||
<motion.div
|
||||
className="absolute top-4 right-4"
|
||||
initial={{ x: 50, opacity: 0 }}
|
||||
whileInView={{ x: 0, opacity: 1 }}
|
||||
|
|
@ -189,9 +189,9 @@ export function ServicesSection() {
|
|||
</CardTitle>
|
||||
</motion.div>
|
||||
</CardHeader>
|
||||
|
||||
|
||||
<CardContent className="pt-0 px-4 sm:px-6">
|
||||
<motion.p
|
||||
<motion.p
|
||||
className="text-muted-foreground mb-3 sm:mb-4 text-sm sm:text-base"
|
||||
initial={{ opacity: 0 }}
|
||||
whileInView={{ opacity: 1 }}
|
||||
|
|
@ -200,8 +200,8 @@ export function ServicesSection() {
|
|||
>
|
||||
{service.description}
|
||||
</motion.p>
|
||||
|
||||
<motion.div
|
||||
|
||||
<motion.div
|
||||
className="space-y-2"
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
|
|
@ -211,21 +211,21 @@ export function ServicesSection() {
|
|||
<h4>Features:</h4>
|
||||
<ul className="space-y-1">
|
||||
{service.features.map((feature, featureIndex) => (
|
||||
<motion.li
|
||||
key={featureIndex}
|
||||
<motion.li
|
||||
key={featureIndex}
|
||||
className="flex items-center gap-2 text-sm text-muted-foreground"
|
||||
initial={{ opacity: 0, x: -10 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: index * 0.2 + 0.7 + featureIndex * 0.1 }}
|
||||
>
|
||||
<motion.div
|
||||
<motion.div
|
||||
className="w-1.5 h-1.5 bg-primary rounded-full"
|
||||
animate={{
|
||||
animate={{
|
||||
scale: [1, 1.5, 1],
|
||||
opacity: [0.7, 1, 0.7]
|
||||
}}
|
||||
transition={{
|
||||
transition={{
|
||||
duration: 2,
|
||||
repeat: Infinity,
|
||||
delay: featureIndex * 0.3
|
||||
|
|
@ -243,14 +243,14 @@ export function ServicesSection() {
|
|||
</motion.div>
|
||||
|
||||
{/* Additional Services */}
|
||||
<motion.div
|
||||
<motion.div
|
||||
className="bg-muted/50 rounded-lg p-8"
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: 0.2 }}
|
||||
>
|
||||
<motion.h2
|
||||
<motion.h2
|
||||
className="mb-6 text-center"
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
|
|
@ -261,8 +261,8 @@ export function ServicesSection() {
|
|||
</motion.h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{additionalServices.map((service, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
<motion.div
|
||||
key={index}
|
||||
className="flex items-center gap-4 p-4 rounded-lg hover:bg-background/50 transition-colors group"
|
||||
initial={{ opacity: 0, x: index % 2 === 0 ? -20 : 20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
|
|
@ -270,12 +270,12 @@ export function ServicesSection() {
|
|||
transition={{ delay: 0.4 + index * 0.1 }}
|
||||
whileHover={{ x: 5 }}
|
||||
>
|
||||
<motion.div
|
||||
<motion.div
|
||||
className="w-10 h-10 bg-primary/10 rounded-lg flex items-center justify-center flex-shrink-0 group-hover:bg-primary/20 transition-colors"
|
||||
animate={{
|
||||
animate={{
|
||||
rotate: [0, 360],
|
||||
}}
|
||||
transition={{
|
||||
transition={{
|
||||
duration: 20,
|
||||
repeat: Infinity,
|
||||
ease: "linear"
|
||||
|
|
@ -293,14 +293,14 @@ export function ServicesSection() {
|
|||
</motion.div>
|
||||
|
||||
{/* Service Areas */}
|
||||
<motion.div
|
||||
<motion.div
|
||||
className="mt-12 text-center"
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: 0.4 }}
|
||||
>
|
||||
<motion.h2
|
||||
<motion.h2
|
||||
className="mb-6"
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
|
|
@ -317,7 +317,7 @@ export function ServicesSection() {
|
|||
whileInView={{ opacity: 1, scale: 1 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: 0.6 + index * 0.05 }}
|
||||
whileHover={{
|
||||
whileHover={{
|
||||
scale: 1.05,
|
||||
transition: { duration: 0.2 }
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -6,27 +6,27 @@ export const indiaLocations = [
|
|||
"Jaipur", "Jodhpur", "Udaipur", "Ajmer", "Kota", "Bikaner", "Alwar",
|
||||
"Lucknow", "Kanpur", "Agra", "Varanasi", "Allahabad", "Meerut", "Bareilly", "Aligarh",
|
||||
"Dehradun", "Haridwar", "Rishikesh", "Mussoorie", "Nainital", "Shimla", "Manali", "Dharamshala",
|
||||
|
||||
|
||||
// East India
|
||||
"Kolkata", "Howrah", "Durgapur", "Asansol", "Siliguri", "Darjeeling",
|
||||
"Bhubaneswar", "Cuttack", "Rourkela", "Puri",
|
||||
"Patna", "Gaya", "Muzaffarpur", "Bhagalpur", "Darbhanga",
|
||||
"Guwahati", "Silchar", "Dibrugarh", "Jorhat", "Tezpur",
|
||||
|
||||
|
||||
// West India
|
||||
"Ahmedabad", "Surat", "Vadodara", "Rajkot", "Bhavnagar", "Jamnagar", "Gandhinagar",
|
||||
"Thane", "Navi Mumbai", "Kalyan", "Vasai-Virar", "Solapur", "Nagpur", "Kolhapur",
|
||||
|
||||
|
||||
// South India
|
||||
"Bangalore", "Mysore", "Mangalore", "Hubli", "Belgaum", "Gulbarga", "Davangere",
|
||||
"Chennai", "Coimbatore", "Madurai", "Tiruchirappalli", "Salem", "Tirunelveli", "Erode", "Tiruppur", "Vellore",
|
||||
"Hyderabad", "Secunderabad", "Warangal", "Nizamabad", "Karimnagar", "Khammam", "Ramagundam",
|
||||
"Kochi", "Thiruvananthapuram", "Kozhikode", "Kollam", "Thrissur", "Alappuzha", "Palakkad", "Kannur",
|
||||
|
||||
|
||||
// Central India
|
||||
"Indore", "Bhopal", "Jabalpur", "Gwalior", "Ujjain", "Sagar", "Dewas", "Satna",
|
||||
"Raipur", "Bhilai", "Bilaspur", "Korba", "Durg", "Rajnandgaon",
|
||||
|
||||
|
||||
// Union Territories
|
||||
"Pondicherry", "Port Blair", "Panaji", "Margao", "Vasco da Gama", "Daman", "Silvassa"
|
||||
];
|
||||
|
|
@ -34,7 +34,7 @@ export const indiaLocations = [
|
|||
// Service types for drop-off options
|
||||
export const serviceTypes = [
|
||||
"City Ride - Customize Price",
|
||||
"Airport Taxi - ₹1099",
|
||||
"Airport Taxi - ₹999",
|
||||
"Outstation - Customize Price",
|
||||
"Mover and Packer - Customize Price",
|
||||
"Corporate Services - Customize Price"
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ export const mockVehicles: Vehicle[] = [
|
|||
id: "1",
|
||||
type: "5-seater",
|
||||
name: "5 Seater",
|
||||
price: 1099,
|
||||
price: 999,
|
||||
capacity: 5,
|
||||
rating: 4.5,
|
||||
estimatedTime: "Rider will contact you soon",
|
||||
features: ["AC", "Music System", "Comfortable", "Airport Taxi ₹1099"],
|
||||
features: ["AC", "Music System", "Comfortable", "Airport Taxi ₹999"],
|
||||
image: ""
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ app.get("/make-server-10d555e8/health", (c) => {
|
|||
// Test email configuration endpoint
|
||||
app.get("/make-server-10d555e8/test-email-config", (c) => {
|
||||
const resendApiKey = Deno.env.get('RESEND_API_KEY');
|
||||
|
||||
return c.json({
|
||||
|
||||
return c.json({
|
||||
emailConfigured: !!resendApiKey,
|
||||
apiKeyFormat: resendApiKey ? (resendApiKey.startsWith('re_') ? 'valid' : 'invalid') : 'missing',
|
||||
apiKeyLength: resendApiKey?.length || 0
|
||||
|
|
@ -40,7 +40,7 @@ app.post("/make-server-10d555e8/send-booking-email", async (c) => {
|
|||
try {
|
||||
const bookingData = await c.req.json();
|
||||
console.log('Received booking data:', JSON.stringify(bookingData, null, 2));
|
||||
|
||||
|
||||
// Store booking in KV store
|
||||
const bookingId = `booking_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||
await kv.set(bookingId, {
|
||||
|
|
@ -55,7 +55,7 @@ app.post("/make-server-10d555e8/send-booking-email", async (c) => {
|
|||
console.log('API Key exists:', !!resendApiKey);
|
||||
console.log('API Key length:', resendApiKey?.length || 0);
|
||||
console.log('API Key prefix:', resendApiKey?.substring(0, 7) || 'none');
|
||||
|
||||
|
||||
if (!resendApiKey) {
|
||||
console.error('RESEND_API_KEY environment variable not found');
|
||||
throw new Error('RESEND_API_KEY not configured - please set up your Resend API key');
|
||||
|
|
@ -69,9 +69,9 @@ app.post("/make-server-10d555e8/send-booking-email", async (c) => {
|
|||
|
||||
// Get vehicle pricing
|
||||
const getVehiclePrice = (vehicleType) => {
|
||||
switch(vehicleType) {
|
||||
case '5-seater': return '₹1099';
|
||||
case '7-seater': return '₹1600';
|
||||
switch (vehicleType) {
|
||||
case '5-seater': return '₹999';
|
||||
case '7-seater': return '₹1600';
|
||||
case 'innova': return '₹2000';
|
||||
default: return 'Contact for pricing';
|
||||
}
|
||||
|
|
@ -193,8 +193,8 @@ app.post("/make-server-10d555e8/send-booking-email", async (c) => {
|
|||
|
||||
console.log('Booking email sent successfully:', bookingId);
|
||||
|
||||
return c.json({
|
||||
success: true,
|
||||
return c.json({
|
||||
success: true,
|
||||
message: 'Booking confirmed and emails sent successfully',
|
||||
bookingId: bookingId,
|
||||
emailsSent: {
|
||||
|
|
@ -205,19 +205,19 @@ app.post("/make-server-10d555e8/send-booking-email", async (c) => {
|
|||
|
||||
} catch (error) {
|
||||
console.error('Error processing booking:', error);
|
||||
|
||||
|
||||
// If it's an API key issue, provide specific guidance
|
||||
if (error.message.includes('API key') || error.message.includes('validation_error')) {
|
||||
return c.json({
|
||||
success: false,
|
||||
return c.json({
|
||||
success: false,
|
||||
message: `Email service configuration error: ${error.message}. Please check your Resend API key setup.`,
|
||||
error: 'EMAIL_CONFIG_ERROR'
|
||||
}, 400);
|
||||
}
|
||||
|
||||
|
||||
// For other errors, still save the booking but indicate email failure
|
||||
return c.json({
|
||||
success: false,
|
||||
return c.json({
|
||||
success: false,
|
||||
message: `Booking saved but email notification failed: ${error.message}`,
|
||||
error: 'EMAIL_SEND_FAILED'
|
||||
}, 500);
|
||||
|
|
|
|||
Loading…
Reference in New Issue