Merge version_2 into main

Merge version_2 into main
This commit was merged in pull request #1.
This commit is contained in:
2026-05-30 18:45:20 +00:00
5 changed files with 632 additions and 195 deletions

83
src/app/admin/layout.tsx Normal file
View File

@@ -0,0 +1,83 @@
"use client";
import { useEffect } from "react";
import { useRouter } from "next/navigation";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import ReactLenis from "lenis/react";
import NavbarStyleApple from '@/components/navbar/NavbarStyleApple/NavbarStyleApple';
import FooterCard from '@/components/sections/footer/FooterCard';
import { Facebook, Instagram, Twitter } from "lucide-react";
export default function AdminLayout({
children,
}: {
children: React.ReactNode;
}) {
const router = useRouter();
useEffect(() => {
if (typeof window !== 'undefined') {
const isLoggedIn = localStorage.getItem("adminLoggedIn");
if (!isLoggedIn) {
router.push("/login");
}
}
}, [router]);
const handleLogout = () => {
localStorage.removeItem("adminLoggedIn");
router.push("/login");
};
return (
<ThemeProvider
defaultButtonVariant="text-shift"
defaultTextAnimation="background-highlight"
borderRadius="soft"
contentWidth="mediumLarge"
sizing="mediumLargeSizeMediumTitles"
background="aurora"
cardStyle="gradient-bordered"
primaryButtonStyle="primary-glow"
secondaryButtonStyle="glass"
headingFontWeight="extrabold"
>
<ReactLenis root>
<div id="nav" data-section="nav">
<NavbarStyleApple
navItems={[
{
name: "Home", href: "/"},
{
name: "Admin Dashboard", href: "/admin"},
{
name: "Logout", onClick: handleLogout,
},
]}
brandName="Admin Panel"
/>
</div>
<main className="flex-grow p-8">
{children}
</main>
<div id="footer" data-section="footer">
<FooterCard
logoText="Product Platform Admin"
copyrightText="© 2024 Product Platform. All rights reserved."
socialLinks={[
{
icon: Twitter,
href: "#", ariaLabel: "Twitter"},
{
icon: Facebook,
href: "#", ariaLabel: "Facebook"},
{
icon: Instagram,
href: "#", ariaLabel: "Instagram"},
]}
/>
</div>
</ReactLenis>
</ThemeProvider>
);
}

33
src/app/admin/page.tsx Normal file
View File

@@ -0,0 +1,33 @@
"use client";
import React from "react";
import { useRouter } from "next/navigation";
export default function AdminDashboardPage() {
const router = useRouter();
return (
<div className="flex flex-col items-center justify-center p-8">
<h1 className="mb-4 text-4xl font-extrabold text-gray-900 dark:text-white">
Welcome to the Admin Dashboard!
</h1>
<p className="mb-8 text-lg text-gray-700 dark:text-gray-300">
Here you can manage your products, orders, and other platform settings.
</p>
<div className="flex space-x-4">
<button
onClick={() => alert("Manage Products clicked!")}
className="rounded-md bg-indigo-600 px-6 py-3 text-white shadow-md transition hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
>
Manage Products
</button>
<button
onClick={() => alert("View Orders clicked!")}
className="rounded-md bg-gray-200 px-6 py-3 text-gray-800 shadow-md transition hover:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 dark:bg-gray-700 dark:text-gray-200 dark:hover:bg-gray-600"
>
View Orders
</button>
</div>
</div>
);
}

98
src/app/login/page.tsx Normal file
View File

@@ -0,0 +1,98 @@
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import ReactLenis from "lenis/react";
export default function LoginPage() {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const router = useRouter();
const handleLogin = (e: React.FormEvent) => {
e.preventDefault();
setError("");
// Hardcoded credentials for demonstration
if (username === "admin" && password === "admin123") {
localStorage.setItem("adminLoggedIn", "true");
router.push("/admin");
} else {
setError("Invalid username or password");
}
};
return (
<ThemeProvider
defaultButtonVariant="text-shift"
defaultTextAnimation="background-highlight"
borderRadius="soft"
contentWidth="mediumLarge"
sizing="mediumLargeSizeMediumTitles"
background="aurora"
cardStyle="gradient-bordered"
primaryButtonStyle="primary-glow"
secondaryButtonStyle="glass"
headingFontWeight="extrabold"
>
<ReactLenis root>
<div className="flex min-h-screen items-center justify-center p-4">
<div className="w-full max-w-md rounded-lg border border-gray-200 bg-white p-8 shadow-lg dark:border-gray-700 dark:bg-gray-800">
<h2 className="mb-6 text-center text-3xl font-extrabold text-gray-900 dark:text-white">
Admin Login
</h2>
<form onSubmit={handleLogin} className="space-y-6">
<div>
<label
htmlFor="username"
className="block text-sm font-medium text-gray-700 dark:text-gray-300"
>
Username
</label>
<input
id="username"
name="username"
type="text"
autoComplete="username"
required
className="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white sm:text-sm"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
</div>
<div>
<label
htmlFor="password"
className="block text-sm font-medium text-gray-700 dark:text-gray-300"
>
Password
</label>
<input
id="password"
name="password"
type="password"
autoComplete="current-password"
required
className="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white sm:text-sm"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
{error && <p className="text-center text-sm text-red-500">{error}</p>}
<div>
<button
type="submit"
className="flex w-full justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-indigo-500 dark:hover:bg-indigo-600"
>
Log In
</button>
</div>
</form>
</div>
</div>
</ReactLenis>
</ThemeProvider>
);
}

368
src/app/order/page.tsx Normal file
View File

@@ -0,0 +1,368 @@
"use client";
import ButtonHoverBubble from "@/components/button/ButtonHoverBubble";
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
import FooterCard from "@/components/sections/footer/FooterCard";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import { CheckCircle, XCircle } from "lucide-react";
import React, { useState, useEffect, useRef } from "react";
import ReactLenis from "lenis/react";
interface Wilaya {
code: string;
name: string;
communes: string[];
}
const AlgerianWilayas: Wilaya[] = [
{ "code": "01", "name": "Adrar", "communes": ["Adrar", "Tamest", "Reggane", "Bourg Haouas"] },
{ "code": "02", "name": "Chlef", "communes": ["Chlef", "El Karimia", "Ouled Fares", "Ténès"] },
{ "code": "03", "name": "Laghouat", "communes": ["Laghouat", "Aflou", "Ksar El Hirane", "Brida"] },
{ "code": "04", "name": "Oum El Bouaghi", "communes": ["Oum El Bouaghi", "Ain Beida", "Ain M'lila", "Meskhiana"] },
{ "code": "05", "name": "Batna", "communes": ["Batna", "Barika", "Arris", "Menaa"] },
{ "code": "06", "name": "Béjaïa", "communes": ["Béjaïa", "Akbou", "Amizour", "Kherrata"] },
{ "code": "07", "name": "Biskra", "communes": ["Biskra", "Ouled Djellal", "Tolga", "Sidi Okba"] },
{ "code": "08", "name": "Béchar", "communes": ["Béchar", "Abadla", "Taghit", "Béni Ounif"] },
{ "code": "09", "name": "Blida", "communes": ["Blida", "Boufarik", "Meftah", "Larbaa"] },
{ "code": "10", "name": "Bouira", "communes": ["Bouira", "Lakhdaria", "Sour El Ghozlane", "Ain Bessem"] },
{ "code": "11", "name": "Tamanrasset", "communes": ["Tamanrasset", "In Salah", "In Guezzam", "Idlès"] },
{ "code": "12", "name": "Tébessa", "communes": ["Tébessa", "Bir El Ater", "Ouenza", "El Ma Labiodh"] },
{ "code": "13", "name": "Tlemcen", "communes": ["Tlemcen", "Ghazaouet", "Maghnia", "Remchi"] },
{ "code": "14", "name": "Tiaret", "communes": ["Tiaret", "Frenda", "Mahdia", "Rahouia"] },
{ "code": "15", "name": "Tizi Ouzou", "communes": ["Tizi Ouzou", "Larbaâ Nath Irathen", "Azazga", "Bouzeguene"] },
{ "code": "16", "name": "Alger", "communes": ["Alger Centre", "Bab El Oued", "Bir Mourad Raïs", "Hussein Dey"] },
{ "code": "17", "name": "Djelfa", "communes": ["Djelfa", "Messaad", "Ain Oussara", "Hassi Bahbah"] },
{ "code": "18", "name": "Jijel", "communes": ["Jijel", "Taher", "El Milia", "Chekfa"] },
{ "code": "19", "name": "Sétif", "communes": ["Sétif", "El Eulma", "Ain Oulmene", "Bougaa"] },
{ "code": "20", "name": "Saïda", "communes": ["Saïda", "Ain El Hadjar", "Sidi Boubkeur", "Youb"] },
{ "code": "21", "name": "Skikda", "communes": ["Skikda", "Collo", "Azzaba", "El Harrouch"] },
{ "code": "22", "name": "Sidi Bel Abbès", "communes": ["Sidi Bel Abbès", "Sfisef", "Telagh", "Ras El Ma"] },
{ "code": "23", "name": "Annaba", "communes": ["Annaba", "El Bouni", "Sidi Amar", "Berrahal"] },
{ "code": "24", "name": "Guelma", "communes": ["Guelma", "Hammam Debagh", "Ain Makhlouf", "Oued Zenati"] },
{ "code": "25", "name": "Constantine", "communes": ["Constantine", "El Khroub", "Hamma Bouziane", "Didouche Mourad"] },
{ "code": "26", "name": "Médéa", "communes": ["Médéa", "Berrouaghia", "Ksar Boukhari", "Chahbounia"] },
{ "code": "27", "name": "Mostaganem", "communes": ["Mostaganem", "Ain Tedles", "Hassi Mameche", "Bouguirat"] },
{ "code": "28", "name": "M'Sila", "communes": ["M'Sila", "Bou Saada", "Magra", "Sidi Aïssa"] },
{ "code": "29", "name": "Mascara", "communes": ["Mascara", "Mohammadia", "Sig", "Bou Hanifia"] },
{ "code": "30", "name": "Ouargla", "communes": ["Ouargla", "Touggourt", "Hassi Messaoud", "N'Goussa"] },
{ "code": "31", "name": "Oran", "communes": ["Oran", "Es Sénia", "Bir El Djir", "Arzew"] },
{ "code": "32", "name": "El Bayadh", "communes": ["El Bayadh", "Bougtoub", "Brezina", "Chellala"] },
{ "code": "33", "name": "Illizi", "communes": ["Illizi", "Djanet", "Bordj Omar Driss", "Debdeb"] },
{ "code": "34", "name": "Bordj Bou Arréridj", "communes": ["Bordj Bou Arréridj", "Ras El Oued", "Ain Taghrout", "El Hamadia"] },
{ "code": "35", "name": "Boumerdès", "communes": ["Boumerdès", "Dellys", "Boudouaou", "Khemis El Khechna"] },
{ "code": "36", "name": "El Tarf", "communes": ["El Tarf", "El Kala", "Ben M'hidi", "Drean"] },
{ "code": "37", "name": "Tindouf", "communes": ["Tindouf", "Oum El Assel"] },
{ "code": "38", "name": "Tissemsilt", "communes": ["Tissemsilt", "Théniet El Had", "Lardjem", "Bordj Bounaama"] },
{ "code": "39", "name": "El Oued", "communes": ["El Oued", "Guemar", "Robbah", "Hassani Abdelkrim"] },
{ "code": "40", "name": "Khenchela", "communes": ["Khenchela", "Chechar", "Kais", "Djellal"] },
{ "code": "41", "name": "Souk Ahras", "communes": ["Souk Ahras", "Sedrata", "Taoura", "Merahna"] },
{ "code": "42", "name": "Tipaza", "communes": ["Tipaza", "Cherchell", "Hadjout", "Kolea"] },
{ "code": "43", "name": "Mila", "communes": ["Mila", "Chelghoum Laid", "Grarem Gouga", "Rouached"] },
{ "code": "44", "name": "Aïn Defla", "communes": ["Aïn Defla", "Khemis Miliana", "El Attaf", "Miliana"] },
{ "code": "45", "name": "Naâma", "communes": ["Naâma", "Mécheria", "Ain Sefra", "Sfissifa"] },
{ "code": "46", "name": "Aïn Témouchent", "communes": ["Aïn Témouchent", "Hammam Bou Hadjar", "Beni Saf", "El Amria"] },
{ "code": "47", "name": "Ghardaïa", "communes": ["Ghardaïa", "El Guerrara", "Bounoura", "Daya Ben Dahoua"] },
{ "code": "48", "name": "Relizane", "communes": ["Relizane", "Oued Rhiou", "Mazouna", "Zemmoura"] },
{ "code": "49", "name": "El M'ghair", "communes": ["El M'ghair", "Djamaa", "M'ghair", "Sidi Khelil"] },
{ "code": "50", "name": "El Menia", "communes": ["El Menia", "Hassi Gara", "Hassi Fehal"] },
{ "code": "51", "name": "Ouled Djellal", "communes": ["Ouled Djellal", "Sidi Khaled", "Besbes", "Ras El Mia"] },
{ "code": "52", "name": "Bordj Baji Mokhtar", "communes": ["Bordj Baji Mokhtar", "Timiaouine"] },
{ "code": "53", "name": "Béni Abbès", "communes": ["Béni Abbès", "Kerzaz", "Tabelbala", "Ouled Khoudir"] },
{ "code": "54", "name": "Timimoun", "communes": ["Timimoun", "Aougrout", "Charouin", "Deladla"] },
{ "code": "55", "name": "Touggourt", "communes": ["Touggourt", "Temacine", "Blidet Amor", "M'Rara"] },
{ "code": "56", "name": "Djanet", "communes": ["Djanet", "Bordj El Houasse"] },
{ "code": "57", "name": "In Salah", "communes": ["In Salah", "Foggaret Ezzoua", "Ain Ghar"] },
{ "code": "58", "name": "In Guezzam", "communes": ["In Guezzam", "Tin Zaouatine"] }
];
interface OrderFormData {
firstName: string;
lastName: string;
phoneNumber: string;
wilaya: string;
commune: string;
quantity: number;
}
const OrderFormPage = () => {
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [phoneNumber, setPhoneNumber] = useState("");
const [wilaya, setWilaya] = useState("");
const [commune, setCommune] = useState(""); const [quantity, setQuantity] = useState(1);
const [errors, setErrors] = useState<Record<string, string>>({});
const [submissionStatus, setSubmissionStatus] = useState<"idle" | "success" | "error">("idle");
const availableCommunes = wilaya
? AlgerianWilayas.find((w) => w.name === wilaya)?.communes || []
: [];
useEffect(() => {
// Reset commune when wilaya changes
setCommune("");
}, [wilaya]);
const validateForm = () => {
const newErrors: Record<string, string> = {};
if (!firstName) newErrors.firstName = "First Name is required.";
if (!lastName) newErrors.lastName = "Last Name is required.";
// Algerian phone number validation: starts with 05, 06, or 07, followed by 8 digits
if (!phoneNumber) {
newErrors.phoneNumber = "Phone Number is required.";
} else if (!/^(05|06|07)\d{8}$/.test(phoneNumber)) {
newErrors.phoneNumber = "Invalid Algerian phone number (e.g., 05XXXXXXXX).";
}
if (!wilaya) newErrors.wilaya = "Wilaya is required.";
if (!commune) newErrors.commune = "Commune is required.";
if (quantity < 1) newErrors.quantity = "Quantity must be at least 1.";
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
setSubmissionStatus("idle");
if (validateForm()) {
const formData: OrderFormData = {
firstName,
lastName,
phoneNumber,
wilaya,
commune,
quantity,
};
console.log("Form data submitted:", formData);
// Simulate backend saving and success animation
setTimeout(() => {
try {
localStorage.setItem("latestOrder", JSON.stringify(formData));
setSubmissionStatus("success");
// Reset form
setFirstName("");
setLastName("");
setPhoneNumber("");
setWilaya("");
setCommune("");
setQuantity(1);
setErrors({});
} catch (error) {
console.error("Error saving to local storage:", error);
setSubmissionStatus("error");
}
}, 1000);
} else {
setSubmissionStatus("error"); // Indicate form validation failed
}
};
const navItems = [
{ name: "Home", id: "/" },
{ name: "Features", id: "/#features" },
{ name: "Products", id: "/#products" },
{ name: "Testimonials", id: "/#testimonials" },
{ name: "FAQs", id: "/#faqs" },
{ name: "Order Now", id: "/order" },
];
return (
<ThemeProvider
defaultButtonVariant="text-shift"
defaultTextAnimation="background-highlight"
borderRadius="soft"
contentWidth="mediumLarge"
sizing="mediumLargeSizeMediumTitles"
background="aurora"
cardStyle="gradient-bordered"
primaryButtonStyle="primary-glow"
secondaryButtonStyle="glass"
headingFontWeight="extrabold"
>
<ReactLenis root>
<div id="nav" data-section="nav">
<NavbarStyleApple navItems={navItems} brandName="Product Platform" />
</div>
<div className="relative isolate py-24 sm:py-32">
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<div className="mx-auto max-w-xl text-center">
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl">
Place Your Order
</h2>
<p className="mt-2 text-lg leading-8 text-foreground/70">
Fill out the form below to complete your purchase.
</p>
</div>
<form onSubmit={handleSubmit} className="mx-auto mt-16 max-w-xl sm:mt-20">
<div className="grid grid-cols-1 gap-x-8 gap-y-6 sm:grid-cols-2">
<div>
<label htmlFor="first-name" className="block text-sm font-semibold leading-6 text-foreground">
First name
</label>
<div className="mt-2.5">
<input
type="text"
name="first-name"
id="first-name"
autoComplete="given-name"
className="block w-full rounded-md border-0 bg-background/50 px-3.5 py-2 text-foreground shadow-sm ring-1 ring-inset ring-foreground/20 placeholder:text-foreground/50 focus:ring-2 focus:ring-inset focus:ring-primary-cta sm:text-sm sm:leading-6"
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
{errors.firstName && <p className="mt-1 text-xs text-red-500">{errors.firstName}</p>}
</div>
</div>
<div>
<label htmlFor="last-name" className="block text-sm font-semibold leading-6 text-foreground">
Last name
</label>
<div className="mt-2.5">
<input
type="text"
name="last-name"
id="last-name"
autoComplete="family-name"
className="block w-full rounded-md border-0 bg-background/50 px-3.5 py-2 text-foreground shadow-sm ring-1 ring-inset ring-foreground/20 placeholder:text-foreground/50 focus:ring-2 focus:ring-inset focus:ring-primary-cta sm:text-sm sm:leading-6"
value={lastName}
onChange={(e) => setLastName(e.target.value)}
/>
{errors.lastName && <p className="mt-1 text-xs text-red-500">{errors.lastName}</p>}
</div>
</div>
<div className="sm:col-span-2">
<label htmlFor="phone-number" className="block text-sm font-semibold leading-6 text-foreground">
Phone number (Algeria)
</label>
<div className="mt-2.5">
<input
type="tel"
name="phone-number"
id="phone-number"
autoComplete="tel"
className="block w-full rounded-md border-0 bg-background/50 px-3.5 py-2 text-foreground shadow-sm ring-1 ring-inset ring-foreground/20 placeholder:text-foreground/50 focus:ring-2 focus:ring-inset focus:ring-primary-cta sm:text-sm sm:leading-6"
placeholder="e.g., 05XXXXXXXX, 06XXXXXXXX, 07XXXXXXXX"
value={phoneNumber}
onChange={(e) => setPhoneNumber(e.target.value)}
/>
{errors.phoneNumber && <p className="mt-1 text-xs text-red-500">{errors.phoneNumber}</p>}
</div>
</div>
<div className="sm:col-span-2">
<label htmlFor="wilaya" className="block text-sm font-semibold leading-6 text-foreground">
Wilaya
</label>
<div className="mt-2.5">
<select
id="wilaya"
name="wilaya"
className="block w-full rounded-md border-0 bg-background/50 px-3.5 py-2 text-foreground shadow-sm ring-1 ring-inset ring-foreground/20 focus:ring-2 focus:ring-inset focus:ring-primary-cta sm:text-sm sm:leading-6"
value={wilaya}
onChange={(e) => setWilaya(e.target.value)}
>
<option value="">Select a Wilaya</option>
{AlgerianWilayas.map((w) => (
<option key={w.code} value={w.name}>
{w.name}
</option>
))}
</select>
{errors.wilaya && <p className="mt-1 text-xs text-red-500">{errors.wilaya}</p>}
</div>
</div>
<div className="sm:col-span-2">
<label htmlFor="commune" className="block text-sm font-semibold leading-6 text-foreground">
Commune
</label>
<div className="mt-2.5">
<select
id="commune"
name="commune"
className="block w-full rounded-md border-0 bg-background/50 px-3.5 py-2 text-foreground shadow-sm ring-1 ring-inset ring-foreground/20 focus:ring-2 focus:ring-inset focus:ring-primary-cta sm:text-sm sm:leading-6"
value={commune}
onChange={(e) => setCommune(e.target.value)}
disabled={!wilaya}
>
<option value="">Select a Commune</option>
{availableCommunes.map((c) => (
<option key={c} value={c}>
{c}
</option>
))}
</select>
{errors.commune && <p className="mt-1 text-xs text-red-500">{errors.commune}</p>}
</div>
</div>
<div className="sm:col-span-2">
<label htmlFor="quantity" className="block text-sm font-semibold leading-6 text-foreground">
Quantity
</label>
<div className="mt-2.5">
<input
type="number"
name="quantity"
id="quantity"
min="1"
className="block w-full rounded-md border-0 bg-background/50 px-3.5 py-2 text-foreground shadow-sm ring-1 ring-inset ring-foreground/20 placeholder:text-foreground/50 focus:ring-2 focus:ring-inset focus:ring-primary-cta sm:text-sm sm:leading-6"
value={quantity}
onChange={(e) => setQuantity(Math.max(1, parseInt(e.target.value) || 1))}
/>
{errors.quantity && <p className="mt-1 text-xs text-red-500">{errors.quantity}</p>}
</div>
</div>
</div>
<div className="mt-10">
<ButtonHoverBubble
text="Submit Order"
type="submit"
className="w-full justify-center"
bgClassName="bg-primary-cta text-primary-cta-foreground"
/>
</div>
{submissionStatus === "success" && (
<div className="mt-4 flex items-center justify-center gap-2 rounded-md bg-green-500/10 p-3 text-green-600 animate-in fade-in duration-500">
<CheckCircle className="h-5 w-5" />
<p className="text-sm font-medium">Order placed successfully!</p>
</div>
)}
{submissionStatus === "error" && Object.keys(errors).length > 0 && (
<div className="mt-4 flex items-center justify-center gap-2 rounded-md bg-red-500/10 p-3 text-red-600 animate-in fade-in duration-500">
<XCircle className="h-5 w-5" />
<p className="text-sm font-medium">Please correct the errors above.</p>
</div>
)}
</form>
</div>
</div>
{/* Sticky 'Order Now' button for mobile */}
<div className="fixed bottom-4 left-0 right-0 z-50 px-4 md:hidden">
<ButtonHoverBubble
text="Order Now"
href="/order"
className="w-full justify-center"
bgClassName="bg-primary-cta text-primary-cta-foreground"
/>
</div>
<div id="footer" data-section="footer">
<FooterCard
logoText="Product Platform"
copyrightText="© 2024 Product Platform. All rights reserved."
socialLinks={[
{ icon: XCircle, href: "#", ariaLabel: "Twitter" },
{ icon: CheckCircle, href: "#", ariaLabel: "Facebook" },
{ icon: XCircle, href: "#", ariaLabel: "Instagram" },
]} // Temporarily replaced with XCircle/CheckCircle as Facebook/Instagram/Twitter not imported in this specific file
/>
</div>
</ReactLenis>
</ThemeProvider>
);
};
export const metadata = {
title: "Place Your Order - Product Platform", description: "Complete your order with our secure and easy-to-use order form. Select your wilaya and commune for quick delivery."};
export default OrderFormPage;

View File

@@ -33,29 +33,19 @@ export default function LandingPage() {
<NavbarStyleApple
navItems={[
{
name: "Home",
id: "#hero",
},
name: "Home", id: "/"},
{
name: "Features",
id: "#features",
},
name: "Features", id: "/#features"},
{
name: "Products",
id: "#products",
},
name: "Products", id: "/#products"},
{
name: "Testimonials",
id: "#testimonials",
},
name: "Testimonials", id: "/#testimonials"},
{
name: "FAQs",
id: "#faqs",
},
name: "FAQs", id: "/#faqs"},
{
name: "Order Now",
id: "#order",
},
name: "Order Now", id: "/#order"},
{
name: "Admin", id: "/admin"},
]}
brandName="Product Platform"
/>
@@ -64,20 +54,15 @@ export default function LandingPage() {
<div id="hero" data-section="hero">
<HeroSplit
background={{
variant: "animated-grid",
}}
variant: "animated-grid"}}
imagePosition="right"
title="Unleash the Power of Our Platform"
description="Discover a seamless experience for managing your products and client orders with our cutting-edge platform. Simplify operations, boost sales, and drive growth."
buttons={[
{
text: "Explore Products",
href: "#products",
},
text: "Explore Products", href: "/#products"},
{
text: "Contact Sales",
href: "#order",
},
text: "Contact Sales", href: "/#order"},
]}
imageSrc="http://img.b2bpic.net/free-photo/customer-relationship-management-concept_23-2150038414.jpg"
imageAlt="Product dashboard interface"
@@ -85,53 +70,28 @@ export default function LandingPage() {
fixedMediaHeight={true}
avatars={[
{
src: "http://img.b2bpic.net/free-photo/portrait-young-attractive-redhead-female-student-sits-armchair-leaning-arms-smiling_197531-22962.jpg",
alt: "Sarah Johnson, CEO",
},
src: "http://img.b2bpic.net/free-photo/portrait-young-attractive-redhead-female-student-sits-armchair-leaning-arms-smiling_197531-22962.jpg", alt: "Sarah Johnson, CEO"},
{
src: "http://img.b2bpic.net/free-photo/tired-people-office-working-late_23-2149006105.jpg",
alt: "Michael Chen, Founder",
},
src: "http://img.b2bpic.net/free-photo/tired-people-office-working-late_23-2149006105.jpg", alt: "Michael Chen, Founder"},
{
src: "http://img.b2bpic.net/free-photo/portrait-curly-black-woman-smiling-camera-home_197531-33133.jpg",
alt: "Emily Rodriguez, Marketing Lead",
},
src: "http://img.b2bpic.net/free-photo/portrait-curly-black-woman-smiling-camera-home_197531-33133.jpg", alt: "Emily Rodriguez, Marketing Lead"},
{
src: "http://img.b2bpic.net/free-photo/man-with-fingers-intertwined-leaning-his-chin_1187-3066.jpg",
alt: "David Kim, Product Manager",
},
src: "http://img.b2bpic.net/free-photo/man-with-fingers-intertwined-leaning-his-chin_1187-3066.jpg", alt: "David Kim, Product Manager"},
{
src: "http://img.b2bpic.net/free-photo/side-view-smiley-man-with-copy-space_23-2148612949.jpg",
alt: "Alex Miller, Lead Developer",
},
src: "http://img.b2bpic.net/free-photo/side-view-smiley-man-with-copy-space_23-2148612949.jpg", alt: "Alex Miller, Lead Developer"},
]}
avatarText="Join 10,000+ satisfied businesses"
marqueeItems={[
{
type: "image",
src: "http://img.b2bpic.net/free-vector/flat-design-geometric-business-card_23-2149292245.jpg",
alt: "Innovate Solutions Logo",
},
type: "image", src: "http://img.b2bpic.net/free-vector/flat-design-geometric-business-card_23-2149292245.jpg", alt: "Innovate Solutions Logo"},
{
type: "image",
src: "http://img.b2bpic.net/free-photo/light-leak-overlay-effect-with-blur-blue-light-leak-noisy-retro-film_474888-8016.jpg",
alt: "Quantum Dynamics Logo",
},
type: "image", src: "http://img.b2bpic.net/free-photo/light-leak-overlay-effect-with-blur-blue-light-leak-noisy-retro-film_474888-8016.jpg", alt: "Quantum Dynamics Logo"},
{
type: "image",
src: "http://img.b2bpic.net/free-vector/abstract-globe-technology-logo-with-global-tech-text-purple-tone_53876-117490.jpg",
alt: "Nexus Tech Logo",
},
type: "image", src: "http://img.b2bpic.net/free-vector/abstract-globe-technology-logo-with-global-tech-text-purple-tone_53876-117490.jpg", alt: "Nexus Tech Logo"},
{
type: "image",
src: "http://img.b2bpic.net/free-photo/top-view-offul-toy-construction-designed-light-desk-toy-plastic_140725-33873.jpg",
alt: "Synergy Systems Logo",
},
type: "image", src: "http://img.b2bpic.net/free-photo/top-view-offul-toy-construction-designed-light-desk-toy-plastic_140725-33873.jpg", alt: "Synergy Systems Logo"},
{
type: "image",
src: "http://img.b2bpic.net/free-photo/abstract-light-painting-dark_23-2149627920.jpg",
alt: "Fusion Innovations Logo",
},
type: "image", src: "http://img.b2bpic.net/free-photo/abstract-light-painting-dark_23-2149627920.jpg", alt: "Fusion Innovations Logo"},
]}
marqueeSpeed={40}
showMarqueeCard={true}
@@ -147,29 +107,11 @@ export default function LandingPage() {
carouselMode="buttons"
features={[
{
title: "Responsive Product Grid",
description: "Showcase your products beautifully on any device with our fully responsive design. Your customers will enjoy a seamless browsing experience.",
imageSrc: "http://img.b2bpic.net/free-photo/summer-holiday_53876-31164.jpg",
imageAlt: "Responsive design across devices",
titleImageSrc: "http://img.b2bpic.net/free-photo/close-up-modern-laptop-with-rate-charts-display-while-man-woman-working-business-project-design-computer-screen-with-data-chart-information-finance-analysis-desk_482257-40065.jpg",
buttonText: "See it in action",
},
title: "Responsive Product Grid", description: "Showcase your products beautifully on any device with our fully responsive design. Your customers will enjoy a seamless browsing experience.", imageSrc: "http://img.b2bpic.net/free-photo/summer-holiday_53876-31164.jpg", imageAlt: "Responsive design across devices", titleImageSrc: "http://img.b2bpic.net/free-photo/close-up-modern-laptop-with-rate-charts-display-while-man-woman-working-business-project-design-computer-screen-with-data-chart-information-finance-analysis-desk_482257-40065.jpg", buttonText: "See it in action"},
{
title: "Intuitive Order Forms",
description: "Simplify the ordering process with dynamic forms. Customers can easily select products and provide their details, accelerating conversions.",
imageSrc: "http://img.b2bpic.net/free-photo/e-commerce-online-shopping-website-technology-concept_53876-133666.jpg",
imageAlt: "Customer order form",
titleImageSrc: "http://img.b2bpic.net/free-photo/digital-banking-transparent-screen_53876-105382.jpg",
buttonText: "Place an order",
},
title: "Intuitive Order Forms", description: "Simplify the ordering process with dynamic forms. Customers can easily select products and provide their details, accelerating conversions.", imageSrc: "http://img.b2bpic.net/free-photo/e-commerce-online-shopping-website-technology-concept_53876-133666.jpg", imageAlt: "Customer order form", titleImageSrc: "http://img.b2bpic.net/free-photo/digital-banking-transparent-screen_53876-105382.jpg", buttonText: "Place an order"},
{
title: "Secure Admin Panel",
description: "Gain full control over your inventory and client orders with our secure, easy-to-use admin panel. Manage everything from one centralized location.",
imageSrc: "http://img.b2bpic.net/free-photo/female-depot-staff-tracking-orders-controlling-warehouse-merchandise_482257-130861.jpg",
imageAlt: "Admin panel interface",
titleImageSrc: "http://img.b2bpic.net/free-photo/open-laptop-with-glowing-screen-notepad-table-night_169016-53665.jpg",
buttonText: "Manage products",
},
title: "Secure Admin Panel", description: "Gain full control over your inventory and client orders with our secure, easy-to-use admin panel. Manage everything from one centralized location.", imageSrc: "http://img.b2bpic.net/free-photo/female-depot-staff-tracking-orders-controlling-warehouse-merchandise_482257-130861.jpg", imageAlt: "Admin panel interface", titleImageSrc: "http://img.b2bpic.net/free-photo/open-laptop-with-glowing-screen-notepad-table-night_169016-53665.jpg", buttonText: "Manage products"},
]}
title="Features Designed for Your Success"
description="Our platform is built to streamline your workflow, enhance customer engagement, and provide robust control over your business operations."
@@ -185,53 +127,17 @@ export default function LandingPage() {
carouselMode="buttons"
products={[
{
id: "1",
name: "Quantum Smartwatch",
price: "$299",
variant: "Midnight Black",
imageSrc: "http://img.b2bpic.net/free-photo/close-up-woman-bandaging-her-arms_23-2148322435.jpg",
imageAlt: "Quantum Smartwatch",
},
id: "1", name: "Quantum Smartwatch", price: "$299", variant: "Midnight Black", imageSrc: "http://img.b2bpic.net/free-photo/close-up-woman-bandaging-her-arms_23-2148322435.jpg", imageAlt: "Quantum Smartwatch"},
{
id: "2",
name: "Aura Wireless Earbuds",
price: "$129",
variant: "Cloud White",
imageSrc: "http://img.b2bpic.net/free-photo/modern-wireless-earphones-with-case-displayed-round-podium-with-soft-shadows_23-2150808020.jpg",
imageAlt: "Aura Wireless Earbuds",
},
id: "2", name: "Aura Wireless Earbuds", price: "$129", variant: "Cloud White", imageSrc: "http://img.b2bpic.net/free-photo/modern-wireless-earphones-with-case-displayed-round-podium-with-soft-shadows_23-2150808020.jpg", imageAlt: "Aura Wireless Earbuds"},
{
id: "3",
name: "Echo Smart Speaker",
price: "$199",
variant: "Space Grey",
imageSrc: "http://img.b2bpic.net/free-photo/still-life-tech-device_23-2150722637.jpg",
imageAlt: "Echo Smart Speaker",
},
id: "3", name: "Echo Smart Speaker", price: "$199", variant: "Space Grey", imageSrc: "http://img.b2bpic.net/free-photo/still-life-tech-device_23-2150722637.jpg", imageAlt: "Echo Smart Speaker"},
{
id: "4",
name: "Volt Portable Charger",
price: "$49",
variant: "Metallic Silver",
imageSrc: "http://img.b2bpic.net/free-photo/blue-cell-phone-connected-usb-cable-type-charging_58702-4479.jpg",
imageAlt: "Volt Portable Charger",
},
id: "4", name: "Volt Portable Charger", price: "$49", variant: "Metallic Silver", imageSrc: "http://img.b2bpic.net/free-photo/blue-cell-phone-connected-usb-cable-type-charging_58702-4479.jpg", imageAlt: "Volt Portable Charger"},
{
id: "5",
name: "SkyDrone Pro",
price: "$899",
variant: "Stealth Black",
imageSrc: "http://img.b2bpic.net/free-photo/technologically-savvy-hipster-young-generation-millennial-professional-photographer-uses-remote-control-pilot-drone-quadrocopter-gadget-air_346278-15.jpg",
imageAlt: "SkyDrone Pro",
},
id: "5", name: "SkyDrone Pro", price: "$899", variant: "Stealth Black", imageSrc: "http://img.b2bpic.net/free-photo/technologically-savvy-hipster-young-generation-millennial-professional-photographer-uses-remote-control-pilot-drone-quadrocopter-gadget-air_346278-15.jpg", imageAlt: "SkyDrone Pro"},
{
id: "6",
name: "Vision VR Headset",
price: "$599",
variant: "Deep Blue",
imageSrc: "http://img.b2bpic.net/free-photo/amazed-businesswoman-watching-virtual-presentation_74855-1093.jpg",
imageAlt: "Vision VR Headset",
},
id: "6", name: "Vision VR Headset", price: "$599", variant: "Deep Blue", imageSrc: "http://img.b2bpic.net/free-photo/amazed-businesswoman-watching-virtual-presentation_74855-1093.jpg", imageAlt: "Vision VR Headset"},
]}
title="Our Featured Products"
description="Explore a selection of our most popular products, each designed with quality and innovation in mind. Find what you need to enhance your digital life."
@@ -246,25 +152,15 @@ export default function LandingPage() {
author="Sarah Johnson, CEO of TechCorp"
avatars={[
{
src: "http://img.b2bpic.net/free-photo/portrait-young-woman-digital-nomad-standing-office-with-laptop-smiling-working-her_1258-195350.jpg",
alt: "Sarah Johnson",
},
src: "http://img.b2bpic.net/free-photo/portrait-young-woman-digital-nomad-standing-office-with-laptop-smiling-working-her_1258-195350.jpg", alt: "Sarah Johnson"},
{
src: "http://img.b2bpic.net/free-photo/smiling-senior-businessman-pointing-with-finger_1262-3108.jpg",
alt: "Michael Chen",
},
src: "http://img.b2bpic.net/free-photo/smiling-senior-businessman-pointing-with-finger_1262-3108.jpg", alt: "Michael Chen"},
{
src: "http://img.b2bpic.net/free-photo/model-with-curly-hair-posing_23-2148323715.jpg",
alt: "Emily Rodriguez",
},
src: "http://img.b2bpic.net/free-photo/model-with-curly-hair-posing_23-2148323715.jpg", alt: "Emily Rodriguez"},
{
src: "http://img.b2bpic.net/free-photo/disabled-business-manager-wheelchair-looking-tired-front_482257-2229.jpg",
alt: "David Kim",
},
src: "http://img.b2bpic.net/free-photo/disabled-business-manager-wheelchair-looking-tired-front_482257-2229.jpg", alt: "David Kim"},
{
src: "http://img.b2bpic.net/free-photo/corporate-workers-brainstorming-together_23-2148804509.jpg",
alt: "Alex Miller",
},
src: "http://img.b2bpic.net/free-photo/corporate-workers-brainstorming-together_23-2148804509.jpg", alt: "Alex Miller"},
]}
ratingAnimation="blur-reveal"
avatarsAnimation="slide-up"
@@ -280,25 +176,13 @@ export default function LandingPage() {
carouselMode="buttons"
metrics={[
{
id: "m1",
value: "99.9%",
description: "Uptime Reliability",
},
id: "m1", value: "99.9%", description: "Uptime Reliability"},
{
id: "m2",
value: "+25%",
description: "Average Sales Increase",
},
id: "m2", value: "+25%", description: "Average Sales Increase"},
{
id: "m3",
value: "10K+",
description: "Products Managed",
},
id: "m3", value: "10K+", description: "Products Managed"},
{
id: "m4",
value: "5-Star",
description: "Customer Satisfaction",
},
id: "m4", value: "5-Star", description: "Customer Satisfaction"},
]}
title="Driving Success with Key Metrics"
description="Our platform's impact is quantifiable. See how we help businesses achieve outstanding results."
@@ -310,30 +194,15 @@ export default function LandingPage() {
useInvertedBackground={true}
faqs={[
{
id: "faq1",
title: "How does the order form work?",
content: "Our order form is dynamic, allowing customers to select products from a dropdown. It also features dynamic Wilaya and Commune dropdowns for precise delivery details, ensuring a smooth ordering experience.",
},
id: "faq1", title: "How does the order form work?", content: "Our order form is dynamic, allowing customers to select products from a dropdown. It also features dynamic Wilaya and Commune dropdowns for precise delivery details, ensuring a smooth ordering experience."},
{
id: "faq2",
title: "Is the admin panel secure?",
content: "Yes, the admin panel is secured with session-based authentication. Default login credentials are 'admin' / 'admin123', but we strongly recommend changing these immediately after the first login.",
},
id: "faq2", title: "Is the admin panel secure?", content: "Yes, the admin panel is secured with session-based authentication. Default login credentials are 'admin' / 'admin123', but we strongly recommend changing these immediately after the first login."},
{
id: "faq3",
title: "Can I add product videos?",
content: "Absolutely! Each product entry in the admin panel supports both image URLs and optional video URLs. You can showcase your products with compelling visuals and videos.",
},
id: "faq3", title: "Can I add product videos?", content: "Absolutely! Each product entry in the admin panel supports both image URLs and optional video URLs. You can showcase your products with compelling visuals and videos."},
{
id: "faq4",
title: "What database is used?",
content: "The backend utilizes a lightweight SQLite database to store product information and client orders. The database is automatically created on the first run if it doesn't already exist.",
},
id: "faq4", title: "What database is used?", content: "The backend utilizes a lightweight SQLite database to store product information and client orders. The database is automatically created on the first run if it doesn't already exist."},
{
id: "faq5",
title: "Is the landing page responsive?",
content: "Yes, the customer-facing landing page features a responsive design with a product grid, ensuring optimal viewing and interaction across all devices, from desktops to mobile phones.",
},
id: "faq5", title: "Is the landing page responsive?", content: "Yes, the customer-facing landing page features a responsive design with a product grid, ensuring optimal viewing and interaction across all devices, from desktops to mobile phones."},
]}
sideTitle="Frequently Asked Questions"
sideDescription="Find quick answers to common questions about our platform, product features, and ordering process."
@@ -347,14 +216,7 @@ export default function LandingPage() {
textboxLayout="default"
useInvertedBackground={false}
names={[
"Innovate Solutions",
"Quantum Dynamics",
"Nexus Tech",
"Synergy Systems",
"Fusion Innovations",
"Pinnacle Labs",
"Aether Core",
]}
"Innovate Solutions", "Quantum Dynamics", "Nexus Tech", "Synergy Systems", "Fusion Innovations", "Pinnacle Labs", "Aether Core"]}
title="Trusted by Leading Innovators"
description="Our platform is the choice for businesses pushing the boundaries of technology and customer satisfaction."
speed={40}
@@ -366,8 +228,7 @@ export default function LandingPage() {
<ContactCenter
useInvertedBackground={true}
background={{
variant: "radial-gradient",
}}
variant: "radial-gradient"}}
tag="Place Your Order"
title="Ready to Get Started?"
description="Fill out the form below to place your order or get in touch with our sales team for more information about our products and services."
@@ -384,23 +245,17 @@ export default function LandingPage() {
socialLinks={[
{
icon: Twitter,
href: "#",
ariaLabel: "Twitter",
},
href: "#", ariaLabel: "Twitter"},
{
icon: Facebook,
href: "#",
ariaLabel: "Facebook",
},
href: "#", ariaLabel: "Facebook"},
{
icon: Instagram,
href: "#",
ariaLabel: "Instagram",
},
href: "#", ariaLabel: "Instagram"},
]}
/>
</div>
</ReactLenis>
</ThemeProvider>
);
}
}