2025-12-26 13:12:37 +00:00

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>
);
}