From 0c7b7bf47fc9f3af4ae29465d76f12cac9841fb6 Mon Sep 17 00:00:00 2001 From: "P.P.K.S Dilhara" Date: Thu, 19 Mar 2026 21:04:39 +0530 Subject: [PATCH 01/17] feat: add avatar component for user profile display in dashboard --- components/dashboard/dashboard-client.tsx | 35 ++++++- package-lock.json | 116 +++++++++++++--------- 2 files changed, 101 insertions(+), 50 deletions(-) diff --git a/components/dashboard/dashboard-client.tsx b/components/dashboard/dashboard-client.tsx index f4fde04..2ee271a 100644 --- a/components/dashboard/dashboard-client.tsx +++ b/components/dashboard/dashboard-client.tsx @@ -31,6 +31,7 @@ import { localStorageAPI } from "@/lib/storage/localStorage"; import { cancelBookings } from "@/app/APITriggers/cancelBookings.js"; import { rescheduleBooking } from "@/app/APITriggers/rescheduleBooking.js"; import { toast } from "sonner"; +import { Avatar, AvatarImage } from "../ui/avatar"; type Appointment = { id: string | number; @@ -281,13 +282,26 @@ export default function DashboardClient({ {/* User Welcome Section */}
-
+ {/*
{session?.user?.name ?.split(" ") .map((n) => n[0]) .join("") .toUpperCase() || "U"} -
+
*/} + + n[0]) + .join("") + .toUpperCase() || + "U" + } + /> +

Welcome back, {session?.user?.name || "User"}! @@ -852,13 +866,26 @@ export default function DashboardClient({
-
+ {/*
{session?.user?.name ?.split(" ") .map((n) => n[0]) .join("") .toUpperCase() || "U"} -
+
*/} + + n[0]) + .join("") + .toUpperCase() || + "U" + } + /> + {isEditingProfile && ( - - - {/* SOCIAL LOGIN BUTTONS SECTION */} - -
- - - -
-
- - - ); -} diff --git a/app/api/auth/[...nextauth]/route.ts b/app/api/auth/[...nextauth]/route.ts index 1bf56e0..28c8439 100644 --- a/app/api/auth/[...nextauth]/route.ts +++ b/app/api/auth/[...nextauth]/route.ts @@ -39,7 +39,7 @@ export const authOptions = { return { id: user.id, - name: user.name, + name: user.name, email: user.email, userType: "user", }; @@ -55,7 +55,6 @@ export const authOptions = { }, async authorize(credentials) { - if (!credentials?.email || !credentials?.password) return null; const admin = await prisma.admin.findUnique({ @@ -71,14 +70,14 @@ export const authOptions = { if (!ok) return null; - console.log("LOGIN ATTEMPT:", credentials); + console.log("LOGIN ATTEMPT:", credentials); return { id: admin.id, email: admin.email, userType: admin.role === "advisor" ? "advisor" : "admin", adminRole: admin.role, - mustChangePassword: admin.mustChangePassword + mustChangePassword: admin.mustChangePassword, }; }, }), @@ -103,83 +102,92 @@ export const authOptions = { maxAge: 30 * 60, // 30 minutes }, - callbacks: { - - // async jwt({ token, user }) { - // if (user) { - // token.id = user.id; - // token.userType = user.userType; - // token.name = user.name; - // token.adminRole = user.adminRole ?? null; - // token.mustChangePassword = user.mustChangePassword ?? false; - // } - // - // if (!token.userType) token.userType = "user"; - // - // return token; - // }, - // - // async session({ session, token }) { - // session.user.id = token.id; - // session.user.userType = token.userType; - // session.user.name = token.name; - // session.user.adminRole = token.adminRole; - // session.user.mustChangePassword = token.mustChangePassword; - // return session; - // }, - // - // async redirect({ url, baseUrl }) { - // return process.env.BASEURL; - // }, - - async jwt({ token, user,account }) { - - if (user) { - token.id = user.id; - token.name = user.name; - token.adminRole = user.adminRole ?? null; - - // 🔥 KEY FIX - if (account?.provider === "google" || account?.provider === "github") { - token.userType = "user"; // ✅ assign role for OAuth users - } else { - token.userType = user.userType ?? "user"; - } - } - - // 🔥 ALWAYS GET LATEST VALUE FROM DB - if (token.userType === "advisor" || token.userType === "admin") { - const admin = await prisma.admin.findUnique({ - where: { id: token.id }, - }); - - if (admin) { - token.mustChangePassword = admin.mustChangePassword; - token.name = admin.name; - token.email = admin.email; - } - } - - return token; - }, - - async session({ session, token }) { - session.user.id = token.id; - session.user.userType = token.userType ?? "user"; - session.user.name = token.name; - session.user.adminRole = token.adminRole; - session.user.mustChangePassword = token.mustChangePassword; - session.user.email = token.email; // ✅ IMPORTANT - return session; - }, - - async redirect({ url, baseUrl }) { - if (url.startsWith("/")) return baseUrl + url; - if (url.startsWith(baseUrl)) return url; - return baseUrl; + callbacks: { + // async jwt({ token, user }) { + // if (user) { + // token.id = user.id; + // token.userType = user.userType; + // token.name = user.name; + // token.adminRole = user.adminRole ?? null; + // token.mustChangePassword = user.mustChangePassword ?? false; + // } + // + // if (!token.userType) token.userType = "user"; + // + // return token; + // }, + // + // async session({ session, token }) { + // session.user.id = token.id; + // session.user.userType = token.userType; + // session.user.name = token.name; + // session.user.adminRole = token.adminRole; + // session.user.mustChangePassword = token.mustChangePassword; + // return session; + // }, + // + // async redirect({ url, baseUrl }) { + // return process.env.BASEURL; + // }, + + async jwt({ token, user, account, trigger, session }) { + if (user) { + token.id = user.id; + token.name = user.name; + token.email = user.email; + token.adminRole = user.adminRole ?? null; + + // 🔥 KEY FIX + if (account?.provider === "google" || account?.provider === "github") { + token.userType = "user"; // ✅ assign role for OAuth users + } else { + token.userType = user.userType ?? "user"; + } + } + + // Apply client-side session.update(...) payload immediately. + if (trigger === "update" && session) { + if (typeof session.name === "string") { + token.name = session.name; + } + if (typeof session.email === "string") { + token.email = session.email; } + } + + // 🔥 ALWAYS GET LATEST VALUE FROM DB + if (token.userType === "advisor" || token.userType === "admin") { + const admin = await prisma.admin.findUnique({ + where: { id: token.id }, + }); + + if (admin) { + token.mustChangePassword = admin.mustChangePassword; + token.name = admin.name; + token.email = admin.email; + } + } + + return token; + }, + + async session({ session, token }) { + session.user.id = token.id; + session.user.userType = token.userType ?? "user"; + session.user.name = token.name; + session.user.adminRole = token.adminRole; + session.user.mustChangePassword = token.mustChangePassword; + session.user.email = token.email; // ✅ IMPORTANT + return session; }, + async redirect({ url, baseUrl }) { + if (url.startsWith("/")) return baseUrl + url; + if (url.startsWith(baseUrl)) return url; + return baseUrl; + }, + }, + debug: true, secret: process.env.NEXTAUTH_SECRET, diff --git a/app/api/user/profile/route.ts b/app/api/user/profile/route.ts index 5862e7c..3efea84 100644 --- a/app/api/user/profile/route.ts +++ b/app/api/user/profile/route.ts @@ -53,16 +53,22 @@ export async function PATCH(request: Request) { return new Response("User not found", { status: 404 }); } - await prisma.user.update({ + const updatedUser = await prisma.user.update({ where: { email: session.user?.email || undefined }, data: { name: body.name, phone: body.phone, }, + select: { + name: true, + email: true, + phone: true, + createdAt: true, + }, }); return Response.json({ success: true, - data: user, + data: updatedUser, }); } catch (error) { return new Response("An error occurred while updating the profile", { @@ -70,4 +76,3 @@ export async function PATCH(request: Request) { }); } } - diff --git a/app/layout.tsx b/app/layout.tsx index 018ea9f..f899639 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -43,7 +43,7 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - + diff --git a/components/ChatBot.jsx b/components/ChatBot.jsx index a3d51b8..cb32dbb 100644 --- a/components/ChatBot.jsx +++ b/components/ChatBot.jsx @@ -1,11 +1,17 @@ "use client"; +import { Loader2, Send, X } from "lucide-react"; import { useState, useRef, useEffect } from "react"; -import { FaRobot, FaTimes, FaPaperPlane } from "react-icons/fa"; export default function ChatBot() { const [open, setOpen] = useState(false); - const [messages, setMessages] = useState([]); + const [messages, setMessages] = useState([ + { + role: "assistant", + content: + "Hello! I'm the Sameera Auto Advisor. How can I help you find your perfect vehicle today?", + }, + ]); const [input, setInput] = useState(""); const [loading, setLoading] = useState(false); @@ -16,51 +22,51 @@ export default function ChatBot() { messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); }, [messages, loading]); - const handleSend = async (e) => { - e.preventDefault(); - if (!input.trim() || loading) return; - - const userMessage = { - role: "user", - content: input, - }; - - setMessages((prev) => [...prev, userMessage]); - setInput(""); - setLoading(true); - - try { - const res = await fetch("/api/Chatbot", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - question: input, - }), - }); - - const data = await res.json(); - - const botMessage = { - role: "assistant", - content: data.answer || "No response from AI.", - }; - - setMessages((prev) => [...prev, botMessage]); - } catch (error) { - const errorMessage = { - role: "assistant", - content: "⚠️ AI server is currently unavailable.", - }; - - setMessages((prev) => [...prev, errorMessage]); - console.log(error); - } - - setLoading(false); + const handleSend = async (e) => { + e.preventDefault(); + if (!input.trim() || loading) return; + + const userMessage = { + role: "user", + content: input, }; + setMessages((prev) => [...prev, userMessage]); + setInput(""); + setLoading(true); + + try { + const res = await fetch("/api/Chatbot", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + question: input, + }), + }); + + const data = await res.json(); + + const botMessage = { + role: "assistant", + content: data.answer || "No response from AI.", + }; + + setMessages((prev) => [...prev, botMessage]); + } catch (error) { + const errorMessage = { + role: "assistant", + content: "⚠️ AI server is currently unavailable.", + }; + + setMessages((prev) => [...prev, errorMessage]); + console.log(error); + } + + setLoading(false); + }; + return ( <> {/* CHATBOT BUTTON */} @@ -130,35 +136,56 @@ export default function ChatBot() { {/* CHAT WINDOW */} {open && ( -
+
+
{/* HEADER */} -
-
- - Smart Auto Hub AI Assistant +
+
+
+ + + + +
+ +
+

+ Sameera Auto Advisor +

+

+ Always here to help +

+
{/* MESSAGES */} -
+
{messages.map((msg, index) => (
{msg.content} @@ -166,13 +193,14 @@ export default function ChatBot() {
))} - {/* LOADING (animated for 5s) */} + {/* LOADING INDICATOR */} {loading && (
-
- - - +
+ + + AI is thinking... +
)} @@ -180,28 +208,34 @@ export default function ChatBot() {
- {/* INPUT */} + {/* INPUT AREA */}
- - setInput(e.target.value)} - /> - - {/* SEND BUTTON */} - +
+ setInput(e.target.value)} + disabled={loading} + /> + + {/* SEND BUTTON */} + +
+

+ Powered by AI • Available 24/7 +

)} diff --git a/components/auth/login-form.tsx b/components/auth/login-form.tsx deleted file mode 100644 index 2148445..0000000 --- a/components/auth/login-form.tsx +++ /dev/null @@ -1,134 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { signIn } from "next-auth/react"; -import Link from "next/link"; -import { FcGoogle } from "react-icons/fc"; -import { FaEye, FaEyeSlash, FaGithub } from "react-icons/fa"; - -export default function LoginForm() { - const [email, setEmail] = useState(""); - const [password, setPassword] = useState(""); - const [loading, setLoading] = useState(false); - const [error, setError] = useState(""); - const [showPassword, setShowPassword] = useState(false); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - setLoading(true); - setError(""); - - try { - await signIn("user-credentials", { - email, - password, - redirect: true, - callbackUrl: "/dashboard", - }); - } catch (err) { - setError("Invalid email or password"); - } finally { - setLoading(false); - } - }; - - return ( - <> -

Welcome Back

-

- Enter your credentials to continue -

- -
-
- - setEmail(e.target.value)} - required - /> -
- -
-
- - e.preventDefault()} - > - Forgot password? - -
- -
- setPassword(e.target.value)} - required - /> - -
-
- - {error && ( -

{error}

- )} - - -
- -
-
- -
-
- - Or continue with - -
-
- -
- -
- -

- Don't have an account?{" "} - - Register - -

- -

- If you are an admin or an advisor - - Go to admin Portal Login - -

- - ); -} diff --git a/components/auth/register-form.tsx b/components/auth/register-form.tsx deleted file mode 100644 index f5408f6..0000000 --- a/components/auth/register-form.tsx +++ /dev/null @@ -1,147 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { useRouter } from "next/navigation"; -import { FcGoogle } from "react-icons/fc"; - -export default function RegisterForm() { - const router = useRouter(); - - const [username, setUsername] = useState(""); - const [email, setEmail] = useState(""); - const [countryCode, setCountryCode] = useState("+94"); - const [phone, setPhone] = useState(""); - const [password, setPassword] = useState(""); - const [loading, setLoading] = useState(false); - const [err, setErr] = useState(""); - - const handleRegister = async (e: any) => { - e.preventDefault(); - setLoading(true); - setErr(""); - - const res = await fetch("/api/auth/register", { - method: "POST", - body: JSON.stringify({ - email, - username, - password, - phone: `${countryCode}${phone}`, - }), - }); - - setLoading(false); - - if (!res.ok) { - setErr("Account already exists"); - return; - } - - router.push("/login"); - }; - - const loginWithGoogle = () => { - window.location.href = "/api/auth/google"; - }; - - return ( - <> -

Create Account

- - -
-
- OR -
-
- -
-
- - setUsername(e.target.value)} - required - /> -
- -
- - setEmail(e.target.value)} - required - /> -
- -
- -
- - - setPhone(e.target.value)} - required - /> -
-
- -
- - setPassword(e.target.value)} - required - /> -
- - {err && ( -

{err}

- )} - - -
- -

- Already have an account? - router.push("/login")} - className="text-blue-600 cursor-pointer font-medium pl-1 hover:underline" - > - Login - -

- - ); -} diff --git a/components/contact/FeedbackPopup.tsx b/components/contact/FeedbackPopup.tsx index 1788d48..5118adf 100644 --- a/components/contact/FeedbackPopup.tsx +++ b/components/contact/FeedbackPopup.tsx @@ -7,8 +7,8 @@ import { DialogContent, DialogDescription, DialogHeader, + DialogTitle, } from "../ui/dialog"; -import { DialogTitle } from "@radix-ui/react-dialog"; import { Button } from "../ui/button"; import { useRouter } from "next/navigation"; @@ -53,53 +53,59 @@ export default function FeedbackPopup() {
-

Contact Sameera Auto Traders Today !

+ Contact Sameera Auto Traders Today!
-

- Looking for your dream car or need more information about our - vehicles? -

-

- Our team is ready to help you with car inquiries, vehicle - availability, pricing, and consultation services. -

- -
    -
  • - - 📞 - {" "} - Friendly customer support -
  • -
  • - - 🚗 - {" "} - Expert advice on buying vehicles -
  • -
  • - - 🤝 - {" "} - Trusted car dealers -
  • -
  • - - 💬 - {" "} - Quick responses to your questions -
  • -
-

- Reach out to us anytime and let us help you drive away with - confidence. -

+ Looking for your dream car or need more information about our + vehicles?
+
+

+ Looking for your dream car or need more information about our + vehicles? +

+

+ Our team is ready to help you with car inquiries, vehicle + availability, pricing, and consultation services. +

+ +
    +
  • + + 📞 + {" "} + Friendly customer support +
  • +
  • + + 🚗 + {" "} + Expert advice on buying vehicles +
  • +
  • + + 🤝 + {" "} + Trusted car dealers +
  • +
  • + + 💬 + {" "} + Quick responses to your questions +
  • +
+

+ Reach out to us anytime and let us help you drive away with + confidence. +

+
- +
*/} - n[0]) - .join("") - .toUpperCase() || - "U" - } - /> + + + {displaySession?.user?.name + ?.split(" ") + .map((n) => n[0]) + .join("") + .toUpperCase() || "U"} +

- Welcome back, {session?.user?.name || "User"}! + Welcome back, {displaySession?.user?.name || "User"}!

@@ -510,9 +518,11 @@ export default function DashboardClient({ disabled={apt.status !== "PENDING"} onClick={() => { setNewDate( - new Date(apt.preferredDate) - .toISOString() - .split("T")[0] || "", + apt.preferredDate + ? new Date(apt.preferredDate) + .toISOString() + .split("T")[0] + : "", ); setNewTime(apt.preferredTime || ""); setRescheduleApt(apt); @@ -541,6 +551,7 @@ export default function DashboardClient({ /> - setUserProfile({ - ...userProfile, - name: e.target.value, - }) - } - defaultValue="John Doe" + onChange={(e) => { + setUserProfile((prev) => + prev ? { ...prev, name: e.target.value } : prev, + ); + }} disabled={!isEditingProfile} />

@@ -920,12 +926,11 @@ export default function DashboardClient({ - setUserProfile({ - ...userProfile, - email: e.target.value, - }) - } + onChange={(e) => { + setUserProfile((prev) => + prev ? { ...prev, email: e.target.value } : prev, + ); + }} disabled={true} />
@@ -937,13 +942,16 @@ export default function DashboardClient({ - setUserProfile({ - ...userProfile, - phone: e.target.value || undefined, - }) - } - defaultValue="+94 77 123 4567" + onChange={(e) => { + setUserProfile((prev) => + prev + ? { + ...prev, + phone: e.target.value || undefined, + } + : prev, + ); + }} disabled={!isEditingProfile} />
From 7900d0a5d3e8ff52a44274e54a6551237326930c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 06:10:40 +0000 Subject: [PATCH 03/17] Initial plan From bb116aeb76b39d55b319aff750dc5878436f60cd Mon Sep 17 00:00:00 2001 From: "P.P.K.S Dilhara" Date: Fri, 20 Mar 2026 11:41:55 +0530 Subject: [PATCH 04/17] Update components/dashboard/dashboard-client.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- components/dashboard/dashboard-client.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dashboard/dashboard-client.tsx b/components/dashboard/dashboard-client.tsx index 00fb1e2..7087450 100644 --- a/components/dashboard/dashboard-client.tsx +++ b/components/dashboard/dashboard-client.tsx @@ -301,7 +301,7 @@ export default function DashboardClient({ .toUpperCase() || "U"}
*/} - + {displaySession?.user?.name ?.split(" ") From 230590dc21135b4b748792a7e7ae15ef0f71aff3 Mon Sep 17 00:00:00 2001 From: "P.P.K.S Dilhara" Date: Fri, 20 Mar 2026 11:43:55 +0530 Subject: [PATCH 05/17] Update components/dashboard/dashboard-client.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- components/dashboard/dashboard-client.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dashboard/dashboard-client.tsx b/components/dashboard/dashboard-client.tsx index 7087450..b49fdf3 100644 --- a/components/dashboard/dashboard-client.tsx +++ b/components/dashboard/dashboard-client.tsx @@ -885,7 +885,7 @@ export default function DashboardClient({ .toUpperCase() || "U"}
*/} - + {displaySession?.user?.name ?.split(" ") From 466fb528a94108fa956158f013bf3f9738c598fb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 06:14:17 +0000 Subject: [PATCH 06/17] fix: prevent client-provided email spoofing in JWT callback - Remove token.email = session.email from session.update() handler; client-controlled email was being written directly to the JWT token, enabling session.user.email spoofing. - Add DB re-hydration of token.email for regular users (userType=user) using token.id, consistent with the existing pattern for admin/advisor. - Add a warning log when the user record is not found during re-hydration. Co-authored-by: shammy911 <180457932+shammy911@users.noreply.github.com> --- app/api/auth/[...nextauth]/route.ts | 15 +++- package-lock.json | 108 +++------------------------- 2 files changed, 20 insertions(+), 103 deletions(-) diff --git a/app/api/auth/[...nextauth]/route.ts b/app/api/auth/[...nextauth]/route.ts index 28c8439..1a9e2a7 100644 --- a/app/api/auth/[...nextauth]/route.ts +++ b/app/api/auth/[...nextauth]/route.ts @@ -146,13 +146,11 @@ export const authOptions = { } // Apply client-side session.update(...) payload immediately. + // Only allow updating display name — never trust client-provided email. if (trigger === "update" && session) { if (typeof session.name === "string") { token.name = session.name; } - if (typeof session.email === "string") { - token.email = session.email; - } } // 🔥 ALWAYS GET LATEST VALUE FROM DB @@ -166,6 +164,17 @@ export const authOptions = { token.name = admin.name; token.email = admin.email; } + } else if (token.userType === "user" && token.id) { + const user = await prisma.user.findUnique({ + where: { id: token.id }, + select: { email: true }, + }); + + if (user) { + token.email = user.email; + } else { + console.warn(`JWT: no user found for id=${token.id}; token may be stale`); + } } return token; diff --git a/package-lock.json b/package-lock.json index a25f105..38f031f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -157,7 +157,6 @@ "version": "7.29.0", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -666,7 +665,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -688,7 +686,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -2491,7 +2488,6 @@ "version": "6.19.2", "hasInstallScript": true, "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=18.18" }, @@ -4081,25 +4077,6 @@ "tailwindcss": "4.2.1" } }, - "node_modules/@testing-library/dom": { - "version": "10.4.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.3.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "picocolors": "1.1.1", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/@testing-library/jest-dom": { "version": "6.9.1", "dev": true, @@ -4190,11 +4167,6 @@ "tslib": "^2.4.0" } }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "dev": true, - "license": "MIT" - }, "node_modules/@types/babel__core": { "version": "7.20.5", "dev": true, @@ -4311,7 +4283,6 @@ "node_modules/@types/node": { "version": "22.19.15", "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -4338,18 +4309,16 @@ }, "node_modules/@types/react": { "version": "19.2.14", - "devOptional": true, + "dev": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } }, "node_modules/@types/react-dom": { "version": "19.2.3", - "devOptional": true, + "dev": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -5110,7 +5079,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -5740,11 +5708,6 @@ "node": ">=0.3.1" } }, - "node_modules/dom-accessibility-api": { - "version": "0.5.16", - "dev": true, - "license": "MIT" - }, "node_modules/dom-helpers": { "version": "5.2.1", "license": "MIT", @@ -5813,11 +5776,6 @@ "version": "1.5.313", "license": "ISC" }, - "node_modules/embla-carousel": { - "version": "8.6.0", - "license": "MIT", - "peer": true - }, "node_modules/embla-carousel-autoplay": { "version": "8.6.0", "license": "MIT", @@ -5838,8 +5796,7 @@ }, "node_modules/embla-carousel-react/node_modules/embla-carousel": { "version": "8.5.1", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/embla-carousel-react/node_modules/embla-carousel-reactive-utils": { "version": "8.5.1", @@ -6598,7 +6555,6 @@ "version": "30.3.0", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/core": "30.3.0", "@jest/types": "30.3.0", @@ -7529,7 +7485,6 @@ "version": "26.1.0", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "cssstyle": "^4.2.1", "data-urls": "^5.0.0", @@ -8047,14 +8002,6 @@ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" } }, - "node_modules/lz-string": { - "version": "1.5.0", - "dev": true, - "license": "MIT", - "bin": { - "lz-string": "bin/bin.js" - } - }, "node_modules/magic-string": { "version": "0.30.21", "dev": true, @@ -8214,7 +8161,6 @@ "resolved": "https://registry.npmjs.org/next/-/next-16.2.0.tgz", "integrity": "sha512-NLBVrJy1pbV1Yn00L5sU4vFyAHt5XuSjzrNyFnxo6Com0M0KrL6hHM5B99dbqXb2bE9pm4Ow3Zl1xp6HVY9edQ==", "license": "MIT", - "peer": true, "dependencies": { "@next/env": "16.2.0", "@swc/helpers": "0.5.15", @@ -8266,7 +8212,6 @@ "node_modules/next-auth": { "version": "4.24.13", "license": "ISC", - "peer": true, "dependencies": { "@babel/runtime": "^7.20.13", "@panva/hkdf": "^1.0.2", @@ -8387,7 +8332,6 @@ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.13.tgz", "integrity": "sha512-PNDFSJdP+KFgdsG3ZzMXCgquO7I6McjY2vlqILjtJd0hy8wEvtugS9xKRF2NWlPNGxvLCXlTNIae4serI7dinw==", "license": "MIT-0", - "peer": true, "engines": { "node": ">=6.0.0" } @@ -8660,7 +8604,6 @@ "node_modules/pg": { "version": "8.20.0", "license": "MIT", - "peer": true, "dependencies": { "pg-connection-string": "^2.12.0", "pg-pool": "^3.13.0", @@ -8794,6 +8737,7 @@ }, "node_modules/postcss": { "version": "8.5.8", + "dev": true, "funding": [ { "type": "opencollective", @@ -8809,7 +8753,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -8825,6 +8768,7 @@ }, "node_modules/postcss/node_modules/nanoid": { "version": "3.3.11", + "dev": true, "funding": [ { "type": "github", @@ -8877,7 +8821,6 @@ "node_modules/preact": { "version": "10.29.0", "license": "MIT", - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -8897,35 +8840,10 @@ "version": "3.8.0", "license": "MIT" }, - "node_modules/pretty-format": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/prisma": { "version": "6.19.2", "hasInstallScript": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "@prisma/config": "6.19.2", "@prisma/engines": "6.19.2" @@ -8996,7 +8914,6 @@ "node_modules/react": { "version": "19.2.0", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -9023,7 +8940,6 @@ "node_modules/react-dom": { "version": "19.2.0", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -9034,7 +8950,6 @@ "node_modules/react-hook-form": { "version": "7.71.2", "license": "MIT", - "peer": true, "engines": { "node": ">=18.0.0" }, @@ -9053,11 +8968,6 @@ "react": "*" } }, - "node_modules/react-is": { - "version": "17.0.2", - "dev": true, - "license": "MIT" - }, "node_modules/react-remove-scroll": { "version": "2.7.2", "license": "MIT", @@ -9701,8 +9611,8 @@ }, "node_modules/tailwindcss": { "version": "4.2.1", - "license": "MIT", - "peer": true + "dev": true, + "license": "MIT" }, "node_modules/tailwindcss-animate": { "version": "1.0.7", @@ -9892,7 +9802,6 @@ "version": "10.9.2", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -9982,9 +9891,8 @@ }, "node_modules/typescript": { "version": "5.9.3", - "devOptional": true, + "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" From b887cd02f6955291e48b18c35bb36d2714a68b0d Mon Sep 17 00:00:00 2001 From: "P.P.K.S Dilhara" Date: Fri, 20 Mar 2026 11:55:22 +0530 Subject: [PATCH 07/17] Update components/contact/FeedbackPopup.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- components/contact/FeedbackPopup.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/contact/FeedbackPopup.tsx b/components/contact/FeedbackPopup.tsx index 5118adf..df85cb1 100644 --- a/components/contact/FeedbackPopup.tsx +++ b/components/contact/FeedbackPopup.tsx @@ -62,8 +62,7 @@ export default function FeedbackPopup() {

- Looking for your dream car or need more information about our - vehicles? + How we can help you

Our team is ready to help you with car inquiries, vehicle From 9317173beb168a00e8a760773633a4563fbf92e4 Mon Sep 17 00:00:00 2001 From: "P.P.K.S Dilhara" Date: Fri, 20 Mar 2026 11:57:54 +0530 Subject: [PATCH 08/17] Update components/dashboard/dashboard-client.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- components/dashboard/dashboard-client.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/components/dashboard/dashboard-client.tsx b/components/dashboard/dashboard-client.tsx index b49fdf3..5741078 100644 --- a/components/dashboard/dashboard-client.tsx +++ b/components/dashboard/dashboard-client.tsx @@ -273,7 +273,6 @@ export default function DashboardClient({ await updateSession({ name: data.data?.name, - email: data.data?.email, }); toast.success("Profile updated successfully"); From 22329b83bad14384615353e21c20f02676216cf0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 06:29:57 +0000 Subject: [PATCH 09/17] Initial plan From bd679f4e4232e277b1d0d8e95ef375f7550ee700 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 06:30:27 +0000 Subject: [PATCH 10/17] Initial plan From e121ed0c9da06ab88b53c79c1cf7e65f2ffa12f5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 06:31:13 +0000 Subject: [PATCH 11/17] security: remove console.log that exposed plaintext credentials in admin authorize callback Co-authored-by: shammy911 <180457932+shammy911@users.noreply.github.com> --- app/api/auth/[...nextauth]/route.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/api/auth/[...nextauth]/route.ts b/app/api/auth/[...nextauth]/route.ts index 28c8439..cf3150e 100644 --- a/app/api/auth/[...nextauth]/route.ts +++ b/app/api/auth/[...nextauth]/route.ts @@ -70,8 +70,6 @@ export const authOptions = { if (!ok) return null; - console.log("LOGIN ATTEMPT:", credentials); - return { id: admin.id, email: admin.email, From 0e7bc76c50a1d628c114011ca328ea4c2a2747cf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 06:32:08 +0000 Subject: [PATCH 12/17] Initial plan From 84683bc0a4dc07597959c09588147817bf9ed3e6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 06:33:02 +0000 Subject: [PATCH 13/17] fix: enable NextAuth debug only in development environment Co-authored-by: shammy911 <180457932+shammy911@users.noreply.github.com> --- app/api/auth/[...nextauth]/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/api/auth/[...nextauth]/route.ts b/app/api/auth/[...nextauth]/route.ts index 28c8439..1d690a5 100644 --- a/app/api/auth/[...nextauth]/route.ts +++ b/app/api/auth/[...nextauth]/route.ts @@ -188,7 +188,7 @@ export const authOptions = { }, }, - debug: true, + debug: process.env.NODE_ENV === "development", secret: process.env.NEXTAUTH_SECRET, }; From b32b6bf53ed00f8a928fdbcb9c03562385af0a5d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 06:33:24 +0000 Subject: [PATCH 14/17] fix: use session.user.id instead of email for profile DB lookups Co-authored-by: shammy911 <180457932+shammy911@users.noreply.github.com> --- app/api/user/profile/route.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/api/user/profile/route.ts b/app/api/user/profile/route.ts index 3efea84..93cfba0 100644 --- a/app/api/user/profile/route.ts +++ b/app/api/user/profile/route.ts @@ -6,12 +6,12 @@ export async function GET(req: Request) { try { const session = await getServerSession(authOptions); - if (!session) { + if (!session || !session.user?.id) { return new Response("Unauthorized", { status: 401 }); } const user = await prisma.user.findUnique({ - where: { email: session.user?.email || undefined }, + where: { id: session.user.id }, select: { name: true, email: true, @@ -39,14 +39,14 @@ export async function PATCH(request: Request) { try { const session = await getServerSession(authOptions); - if (!session) { + if (!session || !session.user?.id) { return new Response("Unauthorized", { status: 401 }); } const body = await request.json(); const user = await prisma.user.findUnique({ - where: { email: session.user?.email || undefined }, + where: { id: session.user.id }, }); if (!user) { @@ -54,7 +54,7 @@ export async function PATCH(request: Request) { } const updatedUser = await prisma.user.update({ - where: { email: session.user?.email || undefined }, + where: { id: session.user.id }, data: { name: body.name, phone: body.phone, From 96f17914f7f0ae506087d811ffbddbe9f85dacbe Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 06:54:49 +0000 Subject: [PATCH 15/17] Initial plan From f6c3e5c87ea47380efded051cc84fbb7351915c7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 06:56:53 +0000 Subject: [PATCH 16/17] fix(accessibility): add aria-label to ChatBot chat input Co-authored-by: shammy911 <180457932+shammy911@users.noreply.github.com> --- components/ChatBot.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/components/ChatBot.jsx b/components/ChatBot.jsx index cb32dbb..b51407a 100644 --- a/components/ChatBot.jsx +++ b/components/ChatBot.jsx @@ -216,6 +216,7 @@ export default function ChatBot() {

Date: Fri, 20 Mar 2026 12:26:55 +0530 Subject: [PATCH 17/17] Update app/layout.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- app/layout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/layout.tsx b/app/layout.tsx index f899639..018ea9f 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -43,7 +43,7 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - +