diff --git a/frontend/src/Admin/HomeAdmin.jsx b/frontend/src/Admin/HomeAdmin.jsx index 2730b86..b66167c 100644 --- a/frontend/src/Admin/HomeAdmin.jsx +++ b/frontend/src/Admin/HomeAdmin.jsx @@ -1,202 +1,213 @@ -// src/Admin/HomeAdmin.jsx - 100% WORKING (react-icons/fa only) -import React, { useEffect, useState } from "react"; +import React, { useEffect, useRef } from "react"; import { motion } from "framer-motion"; -import { useAuth } from "../utils/auth"; import { useNavigate } from "react-router-dom"; -import { FaShoppingCart, FaUsers, FaBox, FaRupeeSign, FaChartLine, FaChartBar, FaSignOutAlt, FaUser } from "react-icons/fa"; +import { useAuth } from "../utils/auth"; +import { + FaShoppingCart, + FaUsers, + FaBox, + FaRupeeSign, + FaChartBar, + FaArrowUp, + FaArrowDown, +} from "react-icons/fa"; + +/* -------------------- DATA -------------------- */ + +const ICON_COLORS = { + indigo: "bg-indigo-600", + emerald: "bg-emerald-600", + purple: "bg-purple-600", + orange: "bg-orange-600", +}; const stats = [ - { title: "Revenue", value: "₹2,45,000", change: "+12%", icon: FaRupeeSign, color: "emerald" }, - { title: "Orders", value: "1,240", change: "+8%", icon: FaShoppingCart, color: "blue" }, - { title: "Customers", value: "860", change: "+15%", icon: FaUsers, color: "purple" }, - { title: "Products", value: "320", icon: FaBox, color: "orange" }, + { title: "Total Revenue", value: "₹2.45L", change: "+12.4%", trend: "up", icon: FaRupeeSign, color: "indigo" }, + { title: "Orders", value: "1,240", change: "+8.2%", trend: "up", icon: FaShoppingCart, color: "emerald" }, + { title: "Customers", value: "860", change: "+15.1%", trend: "up", icon: FaUsers, color: "purple" }, + { title: "Products", value: "320", change: "-2.3%", trend: "down", icon: FaBox, color: "orange" }, ]; const recentOrders = [ - { id: "#1021", customer: "Rahul K.", amount: "₹4,500", status: "Delivered", date: "2025-12-26" }, - { id: "#1022", customer: "Sneha M.", amount: "₹2,200", status: "Pending", date: "2025-12-27" }, - { id: "#1023", customer: "Amit S.", amount: "₹6,800", status: "Cancelled", date: "2025-12-27" }, + { id: "#ORD-1021", customer: "Rahul Kumar", amount: "₹4,500", status: "completed" }, + { id: "#ORD-1022", customer: "Sneha M.", amount: "₹2,200", status: "pending" }, + { id: "#ORD-1023", customer: "Amit Singh", amount: "₹6,800", status: "cancelled" }, ]; +/* -------------------- COMPONENT -------------------- */ + const HomeAdmin = () => { - const { user, logout } = useAuth(); + const { user } = useAuth(); const navigate = useNavigate(); - const [time, setTime] = useState(new Date()); + const redirecting = useRef(false); + /* 🔐 NO FLICKER LOGOUT FIX */ useEffect(() => { - const interval = setInterval(() => setTime(new Date()), 60000); - return () => clearInterval(interval); - }, []); + if (!user && !redirecting.current) { + redirecting.current = true; + navigate("/login", { replace: true }); + } + }, [user, navigate]); - const handleLogout = () => { - logout(); - navigate("/"); - }; + if (!user) return null; return ( -
- {/* Header */} - -
-

- Admin Dashboard -

-

- Welcome back, {user?.username}! -

-
- -
-
- - {user?.username} - ADMIN -
- -
-
+
- {/* Stats Cards */} - - {stats.map(({ title, value, change, icon: Icon, color }, index) => ( + {/* HEADER */} +
+

+ Admin Dashboard +

+

+ Monitor business performance and activities +

+
+ + {/* STATS */} +
+ {stats.map(({ title, value, change, trend, icon: Icon, color }, i) => ( -
+
-

{title}

-

{value}

- {change && ( -

- - {change} from last month -

- )} +

+ {title} +

+

+ {value} +

+ + {trend === "up" ? : } + {change} +
-
- + +
+
))} - +
- {/* Main Content */} -
- {/* Sales Chart */} - + + {/* REVENUE */} + -
-

- Sales Overview - Live Data -

- +
+
+

+ Revenue Analytics +

+

Monthly overview

+
+ + Live +
-
-
- -

Interactive Sales Chart

-

Real-time analytics coming soon

+ +
+
+ +

Charts Coming Soon

+

Real-time analytics

- {/* Quick Stats */} - -

Top Products

-
- {[ - { name: "RO Water Purifier", sales: "120", trend: "+24%" }, - { name: "UV Filter Kit", sales: "95", trend: "+18%" }, - { name: "Service AMC", sales: "70", trend: "+12%" }, - { name: "Installation", sales: "58", trend: "+9%" }, - ].map((product, index) => ( - - {product.name} -
-

{product.sales}

-

{product.trend}

-
-
- ))} -
+

+ Quick Stats +

+ + {[ + { label: "Avg Order Value", value: "₹3,250", change: "+9.2%" }, + { label: "Conversion Rate", value: "4.2%", change: "+1.2%" }, + { label: "New Customers", value: "124", change: "+28%" }, + ].map((item) => ( +
+ + {item.label} + +
+

{item.value}

+

+ {item.change} +

+
+
+ ))}
- {/* Recent Orders Table */} - -
-

Recent Orders

- +
+

+ Recent Orders +

+

Latest transactions

- -
- - + +
+
+ - - - - - + + + + - - {recentOrders.map((order) => ( - - - - - + {recentOrders.map((o) => ( + + + + + - ))} diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 953821a..9b54840 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,56 +1,51 @@ -// src/App.jsx - PERFECT: ANY USER=LandingPage | ANY ADMIN=HomeAdmin +// src/App.jsx import { Routes, Route, Navigate } from "react-router-dom"; +import { useAuth } from "./utils/auth"; + +/* Pages */ import LandingPage from "./Pages/LandingPage"; -import Login from "./Authentication/Login"; -import Signup from "./Authentication/Signup"; import ProductsPage from "./Pages/ProductsPage"; import ProductDetails from "./Pages/ProductsDetails"; import Cart from "./Pages/Cart"; import AboutUs from "./Pages/About"; import Contact from "./Pages/Contact"; -import HomeAdmin from "./Admin/HomeAdmin"; -import ProtectedRoute from "./ProtectedRoutes/ProtectedRote"; -import Settings from "./Profile/ProfileSettings"; + +/* Auth Pages */ +import Login from "./Authentication/Login"; +import SignupUser from "./Authentication/SignupUser"; +import SignupAdmin from "./Authentication/SignupAdmin"; + +/* Profile */ import Profile from "./Profile/Profile"; +import Settings from "./Profile/ProfileSettings"; + +/* Admin */ +import HomeAdmin from "./Admin/HomeAdmin"; + +/* Components */ import Navbar from "./reusableComponents/Navbar"; -import { useAuth } from "./utils/auth"; +import AdminNavbar from "./reusableComponents/AdminNavbar"; +import ProtectedRoute from "./ProtectedRoutes/ProtectedRote"; +/* Loading Spinner */ function LoadingSpinner() { return (
-
+
); } -// ✅ PERFECT LOGIC: role="user" → LandingPage | role="admin" → HomeAdmin +/* ======================= + HOME PAGE LOGIC +======================= */ function HomePage() { const { user, loading } = useAuth(); - console.log("🎯 HomePage:", { - userId: user?.id, - role: user?.role, - isUser: user?.role === "user", - isAdmin: user?.role === "admin", - loading - }); - if (loading) return ; - // ✅ GUEST → LandingPage - if (!user) { - console.log("✅ GUEST → LANDING PAGE"); - return ( - <> - - - - ); - } - - // ✅ ANY USER (role="user") → LANDING PAGE - if (user.role === "user") { - console.log("✅ USER (", user.id, ") → LANDING PAGE"); + // 👤 Guest or User → Public Navbar + Landing + if (!user || user.role === "user") { return ( <> @@ -59,45 +54,100 @@ function HomePage() { ); } - // ✅ ANY ADMIN (role="admin") → HOMEADMIN + // 👑 Admin → Admin Navbar + Admin Home if (user.role === "admin") { - console.log("✅ ADMIN (", user.id, ") → HOMEADMIN"); return ( <> - + ); } - // ✅ FALLBACK → LANDING PAGE - console.log("✅ FALLBACK → LANDING PAGE"); - return ( - <> - - - - ); + return ; } +/* ======================= + APP ROUTES +======================= */ export default function App() { return ( + {/* 🌍 PUBLIC ROUTES */} } /> - } /> - } /> + } /> + } /> } /> } /> - - } /> - } /> - } /> - - } /> - - } /> - } /> - + + {/* 🔐 AUTH ROUTES */} + } /> + } /> + } /> + + {/* 👤 USER PROTECTED ROUTES */} + + <> + + + + + } + /> + + + <> + + + + + } + /> + + + <> + + + + + } + /> + + {/* 👑 ADMIN PROTECTED ROUTES */} + + <> + + + + + } + /> + + + <> + + + + + } + /> + + {/* ❌ FALLBACK */} } /> ); diff --git a/frontend/src/Authentication/Login.jsx b/frontend/src/Authentication/Login.jsx index ef39d0c..25e208d 100644 --- a/frontend/src/Authentication/Login.jsx +++ b/frontend/src/Authentication/Login.jsx @@ -1,174 +1,148 @@ -// src/Authentication/Login.jsx - FULL WORKING CODE import React, { useState, useEffect } from "react"; -import { useNavigate, Link, useLocation } from "react-router-dom"; -import Input from "../reusableComponents/Input"; +import { Link, useNavigate, useLocation } from "react-router-dom"; import { loginUser } from "../Services/authService"; import { useAuth } from "../utils/auth"; export default function Login() { const [form, setForm] = useState({ identifier: "", password: "" }); - const [errors, setErrors] = useState({}); - const [isSubmitting, setIsSubmitting] = useState(false); + const [error, setError] = useState(""); + const [loading, setLoading] = useState(false); + const navigate = useNavigate(); const location = useLocation(); const { login, user } = useAuth(); - // ✅ AUTO REDIRECT if already logged in + // Auto redirect if already logged in useEffect(() => { if (user) { - console.log("🔄 AUTO REDIRECT - Already logged in:", user.id, user.role); - navigate("/", { replace: true }); + navigate(user.role === "admin" ? "/admin/home" : "/", { replace: true }); } }, [user, navigate]); + const handleChange = (e) => { + setForm({ ...form, [e.target.name]: e.target.value }); + setError(""); + }; + const handleSubmit = async (e) => { e.preventDefault(); - setErrors({}); - - if (!form.identifier.trim() || !form.password.trim()) { - setErrors({ general: "Please fill all fields" }); - return; - } + setLoading(true); - setIsSubmitting(true); - try { - console.log("🔍 LOGIN API CALL..."); - const response = await loginUser(form); - console.log("🔍 LOGIN RESPONSE:", response.data); - - const token = response.data.tokens.access; - - // ✅ STORE BACKEND ROLE + USER INFO (CRITICAL!) - localStorage.setItem('userRole', response.data.role); - localStorage.setItem('username', response.data.username); - localStorage.setItem('fullname', response.data.fullname); - - console.log("💾 STORED ROLE:", response.data.role); - - // ✅ Trigger AuthProvider - login(token); - - // ✅ Wait for state update then redirect - setTimeout(() => { - console.log("✅ LOGIN COMPLETE - Redirecting..."); - navigate("/", { replace: true }); - }, 100); - - } catch (error) { - console.error("❌ LOGIN ERROR:", error.response?.data); - setErrors({ - general: error.response?.data?.error || - error.response?.data?.detail || - "Login failed. Please try again." - }); + const res = await loginUser(form); + login(res.data.tokens.access); + + navigate( + res.data.role === "admin" ? "/admin/home" : "/", + { replace: true } + ); + } catch (err) { + setError( + err.response?.data?.error || + err.response?.data?.detail || + "Invalid credentials" + ); } finally { - setIsSubmitting(false); + setLoading(false); } }; - const handleInputChange = (e) => { - const { name, value } = e.target; - setForm(prev => ({ ...prev, [name]: value })); - if (errors[name]) setErrors(prev => ({ ...prev, [name]: '' })); - }; - return ( -
-
- {/* Header */} +
+ + {/* CARD */} +
+ + {/* LOGO / TITLE */}
-
- - - +
+ S
-

- Welcome Back +

+ Sign in to ShopEase

-

Sign in to your account

+

+ Welcome back, please login +

- {/* Success Message */} + {/* SUCCESS MESSAGE */} {location.state?.message && ( -
+
{location.state.message}
)} - {/* Form */} -
- - - - - {/* Error Message */} - {errors.general && ( -
- {errors.general} -
- )} - - {/* Submit Button */} + {/* ERROR */} + {error && ( +
+ {error} +
+ )} + + {/* FORM */} + +
+ + +
+ +
+ + +
+ +
+ + Forgot password? + +
+ - {/* Footer */} -
-

- Don't have an account? - - Sign up here - -

-

- Forgot password? - - Reset now - -

+ {/* FOOTER */} +
+ Don’t have an account? + + Create account +
diff --git a/frontend/src/Authentication/Signup.jsx b/frontend/src/Authentication/Signup.jsx index a58aa00..3507ebb 100644 --- a/frontend/src/Authentication/Signup.jsx +++ b/frontend/src/Authentication/Signup.jsx @@ -1,8 +1,7 @@ -// src/Authentication/Signup.jsx - FULL PRODUCTION READY import React, { useState } from "react"; import { useNavigate, Link, useLocation } from "react-router-dom"; import Input from "../reusableComponents/Input"; -import { registerUser, registerAdmin } from "../Services/authService"; +import { registerUser } from "../Services/authService"; export default function Signup() { const [form, setForm] = useState({ @@ -10,20 +9,17 @@ export default function Signup() { }); const [errors, setErrors] = useState({}); const [isSubmitting, setIsSubmitting] = useState(false); - const [registeringAs, setRegisteringAs] = useState("user"); const navigate = useNavigate(); const location = useLocation(); const validateForm = () => { const newErrors = {}; - if (!form.fullname.trim()) newErrors.fullname = "Full name is required"; if (!form.username.trim()) newErrors.username = "Username is required"; if (!form.email.trim()) newErrors.email = "Email is required"; if (!form.mobile.trim()) newErrors.mobile = "Mobile number is required"; if (form.password.length < 6) newErrors.password = "Password must be at least 6 characters"; if (form.password !== form.confirm_password) newErrors.confirm_password = "Passwords don't match"; - setErrors(newErrors); return Object.keys(newErrors).length === 0; }; @@ -31,32 +27,14 @@ export default function Signup() { const handleSubmit = async (e) => { e.preventDefault(); if (!validateForm()) return; - setIsSubmitting(true); setErrors({}); - try { - console.log(`🔍 REGISTER ${registeringAs.toUpperCase()}...`); - - if (registeringAs === "admin") { - await registerAdmin(form); - } else { - await registerUser(form); - } - - console.log(`✅ ${registeringAs.toUpperCase()} REGISTERED!`); - navigate("/login", { - state: { - message: `${registeringAs.charAt(0).toUpperCase() + registeringAs.slice(1)} account created successfully! Please login.` - } - }); - + await registerUser(form); + navigate("/login", { state: { message: "User account created successfully! Please login." } }); } catch (error) { - console.error("❌ REGISTRATION ERROR:", error.response?.data); setErrors({ - general: error.response?.data?.detail || - error.response?.data?.error || - "Registration failed. Please try again." + general: error.response?.data?.detail || error.response?.data?.error || "Registration failed. Please try again." }); } finally { setIsSubmitting(false); @@ -71,173 +49,62 @@ export default function Signup() { return (
-
+
+ {/* Header */} -
-
- +
+
+
-

+

Create Account

-

Join ShopEase today

+

Join ShopEase as a user

{/* Success Message */} {location.state?.message && ( -
+
{location.state.message}
)} - {/* Role Toggle */} -
- - -
- {/* Form */} -
- - - - - - + + +
+ + +
+ +
+ + +
+ +
+ + +
- {/* Error Message */} {errors.general && ( -
-
- - - - {errors.general} -
+
+ {errors.general}
)} - {/* Submit Button */} -
- -
+ {/* Footer */} -
-

- Already have an account? - - Sign in now → - -

-

- By creating an account, you agree to our Terms of Service and Privacy Policy. +

+

+ Already have an account?{' '} + Sign in →

diff --git a/frontend/src/Authentication/SignupAdmin.jsx b/frontend/src/Authentication/SignupAdmin.jsx new file mode 100644 index 0000000..9c37e17 --- /dev/null +++ b/frontend/src/Authentication/SignupAdmin.jsx @@ -0,0 +1,143 @@ +// src/Authentication/SignupAdmin.jsx +import React, { useState } from "react"; +import { useNavigate, Link, useLocation } from "react-router-dom"; +import Input from "../reusableComponents/Input"; +import { registerAdmin } from "../Services/authService"; + +export default function SignupAdmin() { + const [form, setForm] = useState({ + fullname: "", username: "", email: "", mobile: "", password: "", confirm_password: "" + }); + const [errors, setErrors] = useState({}); + const [isSubmitting, setIsSubmitting] = useState(false); + const navigate = useNavigate(); + const location = useLocation(); + + const validateForm = () => { + const newErrors = {}; + if (!form.fullname.trim()) newErrors.fullname = "Full name is required"; + if (!form.username.trim()) newErrors.username = "Username is required"; + if (!form.email.trim()) newErrors.email = "Email is required"; + if (!form.mobile.trim()) newErrors.mobile = "Mobile number is required"; + if (form.password.length < 8) newErrors.password = "Admin password must be at least 8 characters"; + if (form.password !== form.confirm_password) newErrors.confirm_password = "Passwords don't match"; + setErrors(newErrors); + return Object.keys(newErrors).length === 0; + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + if (!validateForm()) return; + setIsSubmitting(true); + setErrors({}); + + try { + // ✅ Admin registration with role: "admin" + await registerAdmin({ + ...form, + role: "admin" + }); + navigate("/login", { + state: { + message: "Admin account created successfully! Please login to access admin dashboard." + } + }); + } catch (error) { + console.error("❌ ADMIN REGISTRATION ERROR:", error.response?.data); + setErrors({ + general: error.response?.data?.detail || + error.response?.data?.error || + "Admin registration failed. Please try again." + }); + } finally { + setIsSubmitting(false); + } + }; + + const handleInputChange = (e) => { + const { name, value } = e.target; + setForm(prev => ({ ...prev, [name]: value })); + if (errors[name]) setErrors(prev => ({ ...prev, [name]: '' })); + }; + + return ( +
+
+ + {/* Header */} +
+
+ + + +
+

+ Admin Registration +

+

Create your admin account

+
+ + {/* Success Message */} + {location.state?.message && ( +
+ {location.state.message} +
+ )} + + {/* Form */} +
+
+ + +
+ +
+ + +
+ +
+ + +
+ + {errors.general && ( +
+ {errors.general} +
+ )} + + + + + {/* Footer */} +
+

+ Already have an account?{" "} + + Sign in → + +

+
+ +
+
+ ); +} diff --git a/frontend/src/Authentication/SignupUser.jsx b/frontend/src/Authentication/SignupUser.jsx new file mode 100644 index 0000000..9cbffc6 --- /dev/null +++ b/frontend/src/Authentication/SignupUser.jsx @@ -0,0 +1,143 @@ +// src/Authentication/SignupUser.jsx +import React, { useState } from "react"; +import { useNavigate, Link, useLocation } from "react-router-dom"; +import Input from "../reusableComponents/Input"; +import { registerUser } from "../Services/authService"; + +export default function SignupUser() { + const [form, setForm] = useState({ + fullname: "", username: "", email: "", mobile: "", password: "", confirm_password: "" + }); + const [errors, setErrors] = useState({}); + const [isSubmitting, setIsSubmitting] = useState(false); + const navigate = useNavigate(); + const location = useLocation(); + + const validateForm = () => { + const newErrors = {}; + if (!form.fullname.trim()) newErrors.fullname = "Full name is required"; + if (!form.username.trim()) newErrors.username = "Username is required"; + if (!form.email.trim()) newErrors.email = "Email is required"; + if (!form.mobile.trim()) newErrors.mobile = "Mobile number is required"; + if (form.password.length < 6) newErrors.password = "Password must be at least 6 characters"; + if (form.password !== form.confirm_password) newErrors.confirm_password = "Passwords don't match"; + setErrors(newErrors); + return Object.keys(newErrors).length === 0; + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + if (!validateForm()) return; + setIsSubmitting(true); + setErrors({}); + + try { + // ✅ User registration with role: "user" + await registerUser({ + ...form, + role: "user" + }); + navigate("/login", { + state: { + message: "User account created successfully! Please login to continue shopping." + } + }); + } catch (error) { + console.error("❌ REGISTRATION ERROR:", error.response?.data); + setErrors({ + general: error.response?.data?.detail || + error.response?.data?.error || + "Registration failed. Please try again." + }); + } finally { + setIsSubmitting(false); + } + }; + + const handleInputChange = (e) => { + const { name, value } = e.target; + setForm(prev => ({ ...prev, [name]: value })); + if (errors[name]) setErrors(prev => ({ ...prev, [name]: '' })); + }; + + return ( +
+
+ + {/* Header */} +
+
+ + + +
+

+ Join ShopEase +

+

Create your shopper account

+
+ + {/* Success Message */} + {location.state?.message && ( +
+ {location.state.message} +
+ )} + + {/* Form */} +
+
+ + +
+ +
+ + +
+ +
+ + +
+ + {errors.general && ( +
+ {errors.general} +
+ )} + + + + + {/* Footer */} +
+

+ Already have an account?{" "} + + Sign in → + +

+
+ +
+
+ ); +} diff --git a/frontend/src/Pages/Cart.jsx b/frontend/src/Pages/Cart.jsx index 0679919..078b76e 100644 --- a/frontend/src/Pages/Cart.jsx +++ b/frontend/src/Pages/Cart.jsx @@ -1,125 +1,145 @@ import React from "react"; -import Navbar from "../reusableComponents/Navbar"; +import Footer from "../reusableComponents/Footer"; import { useCart } from "../context/CartContext"; +import { FaPlus, FaMinus, FaTrash } from "react-icons/fa"; import { useNavigate } from "react-router-dom"; -export default function Cart() { - const { cart, removeFromCart, increaseQty, decreaseQty } = useCart(); +export default function CartPage() { + const { cartItems, increaseQty, decreaseQty, removeFromCart, totalPrice } = useCart(); const navigate = useNavigate(); - const subtotal = cart.reduce( - (total, item) => total + item.price * item.qty, - 0 - ); + // EMPTY CART VIEW + if (cartItems.length === 0) { + return ( +
+
+

Your Cart is Empty

+

+ Add products to your cart to see them here. +

+ + +
+
+
+ ); + } + // CART WITH ITEMS return ( -
- - -
-

Your Cart

- - {cart.length === 0 ? ( -
-

Your cart is empty

- - -
- ) : ( -
- - {/* LEFT SIDE – CART LIST */} -
- {cart.map((item) => ( -
- {/* Product Image */} - {item.name} - - {/* Product Details */} -
-

{item.name}

-

- ₹{item.price.toLocaleString()} +

+
+ + {/* LEFT: Cart Items */} +
+

My Cart

+ +
+ {cartItems.map((item) => ( +
+ {item.name} + +
+
+

{item.name}

+ {item.brand &&

{item.brand}

} +

+ MRP: ₹{item.mrp || item.price}

+

₹{item.price}

- {/* Quantity Buttons */} -
+
- - {item.qty} - + {item.quantity}
+
- {/* Subtotal of this product */} -

- ₹{(item.qty * item.price).toLocaleString()} -

- - {/* Remove Button */} +
-
-
- ))} -
- {/* RIGHT SIDE – ORDER SUMMARY */} -
-

Order Summary

- -
- -
- Subtotal - ₹{subtotal.toLocaleString()} + +
+
+ ))} +
+
-
- Shipping - FREE -
+ {/* RIGHT: Order Summary */} +
+

Order Details

-
- Total - ₹{subtotal.toLocaleString()} -
+
+ {cartItems.map((item) => ( +
+ {item.name} x {item.quantity} + ₹{item.price * item.quantity}
+ ))} +
- +
+
+ Subtotal + ₹{totalPrice} +
+
+ Shipping + FREE +
+
+ Installation + FREE +
+
+ Total + ₹{totalPrice}
+
- )} +
+ +
); } diff --git a/frontend/src/Pages/CartCheckout.jsx b/frontend/src/Pages/CartCheckout.jsx new file mode 100644 index 0000000..a7fa485 --- /dev/null +++ b/frontend/src/Pages/CartCheckout.jsx @@ -0,0 +1,143 @@ +import { useState } from "react"; +import { useNavigate } from "react-router-dom"; +import Navbar from "../reusableComponents/Navbar"; +import { useCart } from "../context/CartContext"; + +export default function Checkout() { + const { cart, total, checkoutCart } = useCart(); + const navigate = useNavigate(); + + const [form, setForm] = useState({ + address_index: 0, + address: "", + payment_method: "COD", + technician_id: 1, + date_time_start: "", + date_time_end: "", + notes: "", + }); + + const [loading, setLoading] = useState(false); + const [error, setError] = useState(""); + + const handleChange = (e) => { + setForm({ ...form, [e.target.name]: e.target.value }); + }; + + const handleCheckout = async () => { + if (!form.address || !form.date_time_start || !form.date_time_end) { + setError("Please fill all required fields"); + return; + } + + setLoading(true); + setError(""); + + const payload = { + ...form, + payment_done: form.payment_method !== "COD", + }; + + const result = await checkoutCart(payload); + + setLoading(false); + + if (result.success) { + navigate("/order-success"); + } else { + setError("Checkout failed. Please try again."); + } + }; + + if (cart.length === 0) { + return ( +
+ Your cart is empty +
+ ); + } + + return ( + <> + +
+ {/* LEFT – FORM */} +
+

Checkout

+ + {error && ( +

{error}

+ )} + +
OrderCustomerAmountStatusDateORDERCUSTOMERAMOUNTSTATUS
{order.id} - {order.customer} - {order.amount} - - {order.status} +
{o.id}{o.customer}{o.amount} + + {o.status} {order.date}