Add src/app/quote-calculator/page.tsx

This commit is contained in:
2026-03-23 22:00:01 +00:00
parent df06273162
commit 74f6c8ff33

View File

@@ -0,0 +1,227 @@
"use client";
import React, { useState, useCallback, useEffect } from "react";
import ReactLenis from "lenis/react";
import NavbarLayoutFloatingInline from "@/components/navbar/NavbarLayoutFloatingInline";
import FooterCard from "@/components/sections/footer/FooterCard";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import { Instagram, Facebook, Linkedin } from "lucide-react";
export default function QuoteCalculatorPage() {
const [departurePort, setDeparturePort] = useState("");
const [arrivalPort, setArrivalPort] = useState("");
const [cargoType, setCargoType] = useState("");
const [weight, setWeight] = useState(0);
const [volume, setVolume] = useState(0);
const [isCharter, setIsCharter] = useState(false);
const [estimatedCost, setEstimatedCost] = useState(0);
const calculateCost = useCallback(() => {
let baseCost = 1000; // Base cost
let factor = 1;
if (departurePort && arrivalPort) {
// Simple logic for demonstration
if (departurePort !== arrivalPort) {
factor *= 1.5;
}
if (departurePort === "Shanghai" && arrivalPort === "New York") factor *= 2.5;
if (departurePort === "Rotterdam" && arrivalPort === "Dubai") factor *= 2.0;
}
if (cargoType === "Perishable") factor *= 1.8;
if (cargoType === "Hazardous") factor *= 2.5;
factor += (weight / 1000) * 0.5; // Weight in tons
factor += (volume / 10) * 0.3; // Volume in CBM
if (isCharter) {
factor *= 3; // Charter is more expensive
}
setEstimatedCost(baseCost * factor);
}, [departurePort, arrivalPort, cargoType, weight, volume, isCharter]);
useEffect(() => {
calculateCost();
}, [calculateCost]);
const handleRequestDetailedOffer = () => {
alert("Your detailed offer request has been submitted! We will contact you soon.");
// In a real app, this would submit data to a backend or redirect to a contact form with pre-filled details.
};
const navbarNavItems = [
{ name: "About", id: "about" },
{ name: "Services", id: "services" },
{ name: "Destinations", id: "destinations" },
{ name: "Reviews", id: "reviews" },
{ name: "Get Quote", id: "/quote-calculator" }, // New link
{ name: "Contact", id: "contact" },
];
return (
<ThemeProvider
defaultButtonVariant="icon-arrow"
defaultTextAnimation="entrance-slide"
borderRadius="rounded"
contentWidth="medium"
sizing="medium"
background="none"
cardStyle="solid"
primaryButtonStyle="shadow"
secondaryButtonStyle="solid"
headingFontWeight="medium"
>
<ReactLenis root>
<NavbarLayoutFloatingInline
navItems={navbarNavItems}
brandName="Luxuria"
button={{ text: "Plan Your Trip", href: "#contact" }}
/>
<div id="quote-calculator" data-section="quote-calculator" className="py-20 md:py-32 lg:py-40 bg-background text-foreground">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<h1 className="text-4xl sm:text-5xl lg:text-6xl font-extrabold mb-6">
Intelligent Quote Calculator
</h1>
<p className="text-lg sm:text-xl text-muted-foreground mb-12">
Get an instant estimation for your cargo shipment.
</p>
<div className="bg-card p-8 rounded-lg shadow-xl space-y-6 text-left">
{/* Input Fields */}
<div>
<label htmlFor="departurePort" className="block text-sm font-medium text-foreground mb-2">
Departure Port
</label>
<select
id="departurePort"
className="block w-full p-3 border border-border rounded-md bg-input focus:outline-none focus:ring-2 focus:ring-primary-cta"
value={departurePort}
onChange={(e) => setDeparturePort(e.target.value)}
>
<option value="">Select Departure Port</option>
<option value="Shanghai">Shanghai</option>
<option value="Rotterdam">Rotterdam</option>
<option value="New York">New York</option>
<option value="Dubai">Dubai</option>
<option value="Singapore">Singapore</option>
</select>
</div>
<div>
<label htmlFor="arrivalPort" className="block text-sm font-medium text-foreground mb-2">
Arrival Port
</label>
<select
id="arrivalPort"
className="block w-full p-3 border border-border rounded-md bg-input focus:outline-none focus:ring-2 focus:ring-primary-cta"
value={arrivalPort}
onChange={(e) => setArrivalPort(e.target.value)}
>
<option value="">Select Arrival Port</option>
<option value="Shanghai">Shanghai</option>
<option value="Rotterdam">Rotterdam</option>
<option value="New York">New York</option>
<option value="Dubai">Dubai</option>
<option value="Singapore">Singapore</option>
</select>
</div>
<div>
<label htmlFor="cargoType" className="block text-sm font-medium text-foreground mb-2">
Cargo Type
</label>
<select
id="cargoType"
className="block w-full p-3 border border-border rounded-md bg-input focus:outline-none focus:ring-2 focus:ring-primary-cta"
value={cargoType}
onChange={(e) => setCargoType(e.target.value)}
>
<option value="">Select Cargo Type</option>
<option value="General">General Cargo</option>
<option value="Perishable">Perishable Goods</option>
<option value="Hazardous">Hazardous Materials</option>
<option value="Fragile">Fragile Items</option>
</select>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label htmlFor="weight" className="block text-sm font-medium text-foreground mb-2">
Weight (kg)
</label>
<input
type="number"
id="weight"
className="block w-full p-3 border border-border rounded-md bg-input focus:outline-none focus:ring-2 focus:ring-primary-cta"
value={weight}
onChange={(e) => setWeight(parseFloat(e.target.value))}
min="0"
/>
</div>
<div>
<label htmlFor="volume" className="block text-sm font-medium text-foreground mb-2">
Volume (CBM)
</label>
<input
type="number"
id="volume"
className="block w-full p-3 border border-border rounded-md bg-input focus:outline-none focus:ring-2 focus:ring-primary-cta"
value={volume}
onChange={(e) => setVolume(parseFloat(e.target.value))}
min="0"
/>
</div>
</div>
<div className="flex items-center space-x-2">
<input
type="checkbox"
id="isCharter"
className="h-5 w-5 text-primary-cta rounded border-border focus:ring-primary-cta"
checked={isCharter}
onChange={(e) => setIsCharter(e.target.checked)}
/>
<label htmlFor="isCharter" className="text-sm font-medium text-foreground">
Charter Option (Full Vessel)
</label>
</div>
{/* Instant Cost Estimation */}
<div className="mt-8 pt-6 border-t border-border">
<h3 className="text-2xl font-bold text-foreground mb-4">
Estimated Cost:
</h3>
<p className="text-4xl font-extrabold text-primary-cta">
${estimatedCost.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</p>
</div>
{/* Request Detailed Offer Button */}
<div className="mt-8 text-center">
<button
onClick={handleRequestDetailedOffer}
className="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 h-10 px-4 py-2 bg-primary-cta text-primary-cta-foreground hover:bg-primary-cta/90"
>
Request Detailed Offer
</button>
</div>
</div>
</div>
</div>
<FooterCard
logoText="Luxuria"
copyrightText="© 2025 Luxuria Travel | Luxury Journeys Worldwide"
socialLinks={[
{ icon: Instagram, href: "#", ariaLabel: "Instagram" },
{ icon: Facebook, href: "#", ariaLabel: "Facebook" },
{ icon: Linkedin, href: "#", ariaLabel: "LinkedIn" },
]}
/>
</ReactLenis>
</ThemeProvider>
);
}