338 lines
12 KiB
TypeScript
338 lines
12 KiB
TypeScript
"use client";
|
|
import { formatCreatedAtWithEnd, showMessage } from "@/utils/commonFunction.utils";
|
|
import axios from "axios";
|
|
import { useRouter } from "next/navigation";
|
|
import React, { useEffect, useState } from "react";
|
|
import EditProfileModal from "@/components/account/EditProfileModal";
|
|
|
|
export default function AccountPage() {
|
|
const router = useRouter();
|
|
const [userId, setUserId] = useState<string | null>(null);
|
|
const [user, setUser] = useState<any>(null);
|
|
const [payment, setPayment] = useState<any>(null);
|
|
const [loading, setLoading] = useState(false);
|
|
const [editModalOpen, setEditModalOpen] = useState(false);
|
|
const [role, setRole] = useState()
|
|
const [userDetails, setUserDetails] = useState<any>({});
|
|
|
|
const defaultParams = {
|
|
userid: user?.userid || userId,
|
|
name: user?.name || "",
|
|
email: user?.email || "",
|
|
phonenumber: user?.phonenumber || "",
|
|
// ✅ Role is taken from login payload (localStorage), not editable
|
|
// role: storedRole || user?.role || "",
|
|
// companyname: user?.companyname || "",
|
|
};
|
|
|
|
const [params, setParams] = useState<any>({ ...defaultParams });
|
|
|
|
const fetchUsers = async () => {
|
|
try {
|
|
const uid = localStorage.getItem("data4auto_uid");
|
|
const res: any = await axios.get(`https://ebay.backend.data4autos.com/api/motorstate/auth/users/${uid}`);
|
|
setUserDetails(res.data?.user || []);
|
|
console.log("user", res.data?.user)
|
|
} catch (err) {
|
|
console.error(err);
|
|
showMessage('Failed to load users', 'error');
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
fetchUsers();
|
|
}, []);
|
|
|
|
// ✅ Update params when userDetails are loaded
|
|
useEffect(() => {
|
|
if (userDetails && Object.keys(userDetails).length > 0) {
|
|
setParams({
|
|
userid: userDetails.userid || "",
|
|
name: userDetails.name || "",
|
|
email: userDetails.email || "",
|
|
phonenumber: userDetails.phonenumber || "",
|
|
});
|
|
}
|
|
}, [userDetails]);
|
|
|
|
|
|
// ✅ Fetch payment details
|
|
useEffect(() => {
|
|
const Role: any = localStorage.getItem("user_role");
|
|
setRole(Role)
|
|
const sessionId = localStorage.getItem("payment_session");
|
|
|
|
if (Role === "admin" || Role === "partner") return;
|
|
|
|
if (!sessionId) {
|
|
router.push("/pricing");
|
|
return;
|
|
}
|
|
|
|
const fetchPaymentDetails = async () => {
|
|
try {
|
|
const res: any = await axios.get(
|
|
"https://ebay.backend.data4autos.com/api/payment/details",
|
|
{ params: { session_id: sessionId } }
|
|
);
|
|
setPayment(res.data.payment);
|
|
} catch (err) {
|
|
console.error("Error fetching payment details:", err);
|
|
}
|
|
};
|
|
|
|
fetchPaymentDetails();
|
|
}, [router]);
|
|
|
|
// ✅ Check authentication
|
|
useEffect(() => {
|
|
const uid = localStorage.getItem("data4auto_uid");
|
|
const email = localStorage.getItem("d4a_email");
|
|
|
|
if (uid && email) {
|
|
setUserId(uid);
|
|
setUser(email);
|
|
} else {
|
|
axios
|
|
.get("https://ebay.backend.data4autos.com/api/auth/protected", {
|
|
withCredentials: true,
|
|
})
|
|
.then((res: any) => {
|
|
const userData = res.data.user;
|
|
if (userData) {
|
|
setUser(userData.email);
|
|
setUserId(userData.userid);
|
|
localStorage.setItem("data4auto_uid", userData.userid);
|
|
localStorage.setItem("d4a_email", userData.email);
|
|
}
|
|
})
|
|
.catch(() => {
|
|
router.push("/login");
|
|
});
|
|
}
|
|
}, [router]);
|
|
|
|
|
|
const handleInputChange = (e: any) => {
|
|
const { id, value } = e.target;
|
|
// ✅ Skip updating "role" manually
|
|
// if (id === "role") return;
|
|
setParams({ ...params, [id]: value });
|
|
};
|
|
|
|
|
|
|
|
const saveProfile = async () => {
|
|
console.log("Saving profile...", params); // debug log
|
|
|
|
if (!params.name || !params.email || !params.phonenumber) {
|
|
showMessage("Please fill all required fields", "error");
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// ✅ Always use the role from localStorage (payload), not user-edited
|
|
const finalParams = {
|
|
...params,
|
|
role: role || "customer",
|
|
};
|
|
|
|
if (finalParams.userid) {
|
|
console.log("PUT request →", `http://localhost:3003/api/auth/users/${finalParams.userid}`);
|
|
await axios.put(`http://localhost:3003/api/auth/users/${finalParams.userid}`, finalParams);
|
|
fetchUsers();
|
|
showMessage("User updated successfully");
|
|
setTimeout(() => setEditModalOpen(false), 800);
|
|
} else {
|
|
console.warn("Missing userid — skipping PUT");
|
|
}
|
|
setEditModalOpen(false);
|
|
} catch (err: any) {
|
|
console.error("Error saving user:", err);
|
|
showMessage("Error saving user", "error");
|
|
}
|
|
};
|
|
|
|
|
|
const handleViewInvoice = () => router.push("/invoice/preview");
|
|
|
|
const handleCancel = async () => {
|
|
if (!confirm("Are you sure you want to cancel your subscription?")) return;
|
|
const subscriptionId = 1;
|
|
setLoading(true);
|
|
try {
|
|
const res = await axios.post("https://ebay.backend.data4autos.com/api/payment/cancel", {
|
|
subscriptionId,
|
|
});
|
|
alert("Subscription cancelled successfully!");
|
|
console.log(res.data);
|
|
} catch (err) {
|
|
alert("Failed to cancel subscription.");
|
|
console.error(err);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="min-h-[83vh] bg-gradient-to-br from-[#00d1ff]/10 via-white to-[#00d1ff]/20 py-10 px-4">
|
|
<div className="max-w-6xl mx-auto space-y-8">
|
|
{/* Subscription / Billing / Profile cards */}
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
{/* Subscription Card */}
|
|
<div className="bg-white border border-gray-200 rounded-xl shadow-sm p-6">
|
|
<h2 className="text-lg font-semibold text-gray-900 mb-4">Subscription</h2>
|
|
<div className="space-y-3 text-sm">
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-600">Subscription</span>
|
|
<span className="font-medium text-gray-900">{payment?.plan || "N/A"}</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-600">Period</span>
|
|
<span className="font-medium text-gray-900">
|
|
{formatCreatedAtWithEnd(payment?.createdAt, payment?.plan)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div className="flex gap-3 mt-6">
|
|
<button
|
|
onClick={handleCancel}
|
|
disabled={loading}
|
|
className="flex-1 border border-red-400 text-red-500 font-medium py-2 rounded-lg hover:bg-red-50 transition disabled:opacity-50"
|
|
>
|
|
{loading ? "Cancelling..." : "Cancel Subscription"}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Billing Card */}
|
|
<div className="bg-white border border-gray-200 rounded-xl shadow-sm p-6">
|
|
<h2 className="text-lg font-semibold text-gray-900 mb-4">Billing</h2>
|
|
<div className="space-y-3 text-sm">
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-600">Card</span>
|
|
<span className="font-medium text-gray-900">
|
|
•••• •••• •••• 1325{" "}
|
|
<span className="text-blue-600 font-semibold">VISA</span>
|
|
</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-600">Expires</span>
|
|
<span className="font-medium text-gray-900">3 / 2028</span>
|
|
</div>
|
|
</div>
|
|
<div className="flex gap-3 mt-6">
|
|
<button className="flex-1 bg-[#00d1ff] text-white font-medium py-2 rounded-lg hover:bg-[#00b8e6] transition">
|
|
Update Billing Details
|
|
</button>
|
|
<button className="flex-1 border border-gray-300 text-gray-700 font-medium py-2 rounded-lg hover:bg-gray-100 transition">
|
|
Add Coupon
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Profile Card */}
|
|
<div className="bg-white border border-gray-200 rounded-xl shadow-sm p-6">
|
|
<h2 className="text-lg font-semibold text-gray-900 mb-4">Profile</h2>
|
|
<div className="space-y-3 text-sm">
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-600">Full Name</span>
|
|
<span className="font-medium text-gray-900">{userDetails?.name}</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-600">Email</span>
|
|
<span className="font-medium text-gray-900">{userDetails?.email || "N/A"}</span>
|
|
</div>
|
|
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-600">Phone</span>
|
|
<span className="font-medium text-gray-900">{userDetails?.phonenumber}</span>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className="flex gap-3 mt-6">
|
|
<button
|
|
className="flex-1 bg-[#00d1ff] text-white font-medium py-2 rounded-lg hover:bg-[#00b8e6] transition"
|
|
onClick={() => {
|
|
setParams((prev: any) => ({
|
|
...prev,
|
|
userid: userId || localStorage.getItem("data4auto_uid"),
|
|
email: user || localStorage.getItem("d4a_email"),
|
|
|
|
}));
|
|
setEditModalOpen(true);
|
|
}}
|
|
>
|
|
Update Details
|
|
</button>
|
|
|
|
<button
|
|
className="flex-1 border border-gray-300 text-gray-700 font-medium py-2 rounded-lg hover:bg-gray-100 transition"
|
|
onClick={() => router.push("/change-password")}
|
|
>
|
|
Change Password
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Billing History Table */}
|
|
<div className="bg-white border border-gray-200 rounded-xl shadow-sm p-6">
|
|
<h2 className="text-lg font-semibold text-gray-900 mb-4">Billing History</h2>
|
|
<div className="overflow-x-auto">
|
|
<table className="w-full text-sm text-left border-t border-gray-100">
|
|
<thead>
|
|
<tr className="text-gray-600 bg-gray-50">
|
|
<th className="py-3 px-4 font-medium">INVOICE NUMBER</th>
|
|
<th className="py-3 px-4 font-medium">DATE</th>
|
|
<th className="py-3 px-4 font-medium">STATUS</th>
|
|
<th className="py-3 px-4 font-medium">AMOUNT</th>
|
|
<th className="py-3 px-4 font-medium">PDF INVOICE</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{payment && (
|
|
<tr className="border-t">
|
|
<td className="py-3 px-4">{payment.invoice_number || "INV-0001"}</td>
|
|
<td className="py-3 px-4">
|
|
{formatCreatedAtWithEnd(payment?.createdAt).split(" - ")[0]}
|
|
</td>
|
|
<td className="py-3 px-4">
|
|
<span className="px-2 py-1 text-xs rounded-full bg-green-100 text-green-600 font-medium">
|
|
Paid
|
|
</span>
|
|
</td>
|
|
<td className="py-3 px-4 text-gray-800 font-medium">
|
|
${payment.amount || "59.00"}
|
|
</td>
|
|
<td className="py-3 px-4">
|
|
<button
|
|
onClick={handleViewInvoice}
|
|
className="bg-gray-100 hover:bg-[#00d1ff] hover:text-white text-gray-700 text-sm font-medium py-1.5 px-4 rounded-md transition"
|
|
>
|
|
View
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div className="text-gray-500 text-sm mt-4">
|
|
Showing {payment ? 1 : 0} of {payment ? 1 : 0} entries
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<EditProfileModal
|
|
isOpen={editModalOpen}
|
|
onClose={() => setEditModalOpen(false)}
|
|
params={params}
|
|
onChange={handleInputChange}
|
|
onSave={saveProfile}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|