implement authentication system with login, signup, and user module components and layout structure

This commit is contained in:
Alaguraj0361 2026-04-17 14:47:49 +05:30
parent 350e632db6
commit 1e01ea3568
10 changed files with 33 additions and 57 deletions

View File

@ -86,16 +86,7 @@ const CoverLogin = () => {
<ComponentsAuthLoginForm />
{/* Sign-up link */}
<div className="text-center dark:text-white">
Don&apos;t have an account?&nbsp;
<Link
href="/signup"
className="uppercase text-primary underline transition hover:text-black dark:hover:text-white"
>
SIGN UP
</Link>
</div>
</div>
{/* Footer */}

View File

@ -1,6 +1,6 @@
import { NextResponse } from 'next/server';
const AUTH_API_BASE = process.env.AUTH_API_BASE ?? 'https://ebay.backend.vgproducts.com';
const AUTH_API_BASE = process.env.AUTH_API_BASE ?? 'http://localhost:3050';
const SESSION_MAX_AGE_S = 30 * 60; // 30 minutes in seconds
// Utility to extract userId from a nested object

View File

@ -1,6 +1,6 @@
import { NextResponse } from 'next/server';
const AUTH_API_BASE = process.env.AUTH_API_BASE ?? 'https://ebay.backend.vgproducts.com';
const AUTH_API_BASE = process.env.AUTH_API_BASE ?? 'http://localhost:3050';
export async function POST(req: Request) {
const body = await req.json();

View File

@ -13,7 +13,7 @@ export default function ForgotPasswordForm() {
setLoading(true);
setMessage("");
try {
const res = await axios.post("https://ebay.backend.vgproducts.com/api/auth/forgot-password", { email });
const res = await axios.post("http://localhost:3050/api/auth/forgot-password", { email });
setMessage("✅ Weve emailed you a reset code / link. Enter it below.");
} catch (err: any) {
console.error(err);

View File

@ -7,7 +7,7 @@ import IconMail from '@/components/icon/icon-mail';
const ComponentsAuthLoginForm = () => {
const router = useRouter();
const searchParams = useSearchParams();
const nextUrl = searchParams.get('next') || '/';
const nextUrl = searchParams.get('next') || '/user';
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
@ -29,7 +29,7 @@ const ComponentsAuthLoginForm = () => {
setLoading(true);
try {
// ✅ Call your Next.js API (same origin), which sets d4a_uid, d4a_session, d4a_exp cookies
const res = await fetch('https://ebay.backend.vgproducts.com/api/auth/login', {
const res = await fetch('http://localhost:3050/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
// credentials not required for same-origin, but harmless:

View File

@ -7,8 +7,8 @@ import IconUser from '@/components/icon/icon-user';
const API_BASE =
process.env.NEXT_PUBLIC_API_BASE_URL?.replace(/\/$/, '') ||
// 'https://ebay.backend.vgproducts.com';
'https://ebay.backend.vgproducts.com';
// 'http://localhost:3050';
'http://localhost:3050';
const ComponentsAuthRegisterForm = () => {

View File

@ -40,7 +40,7 @@ const ComponentsAuthChangePasswordForm = () => {
// ✅ Axios call with generic type
const res = await axios.post<ChangePasswordResponse>(
`https://ebay.backend.vgproducts.com/api/auth/change-password`,
`http://localhost:3050/api/auth/change-password`,
formData,
{
headers: {

View File

@ -54,7 +54,7 @@ const Header = () => {
setUser(email);
} else {
axios
.get("https://ebay.backend.vgproducts.com/api/auth/protected", { withCredentials: true })
.get("http://localhost:3050/api/auth/protected", { withCredentials: true })
.then((res: any) => {
const userData = res.data.user;
if (userData) {
@ -218,9 +218,7 @@ const Header = () => {
<IconMenu className="h-5 w-5" />
</button>
<Link href="/" className="main-logo flex shrink-0 items-center ml-3">
<img className="inline w-[164px] h-[40px] ltr:-ml-1 rtl:-mr-1 block dark:hidden" src="/assets/images/logo_dark.png" alt="logo" />
<img className="inline w-[164px] h-[40px] ltr:-ml-1 rtl:-mr-1 hidden dark:block" src="/assets/images/logo_light.png" alt="logo" />
{/* <span className="hidden align-middle text-2xl font-semibold transition-all duration-300 ltr:ml-1.5 rtl:mr-1.5 dark:text-white-light md:inline">VG Products</span> */}
<span className="align-middle text-2xl font-bold transition-all duration-300 ltr:ml-1.5 rtl:mr-1.5 dark:text-white-light md:inline text-[#e8572a]">VG Products</span>
</Link>
</div>

View File

@ -66,10 +66,8 @@ const Sidebar = () => {
>
<div className="h-full bg-white dark:bg-black">
<div className="flex items-center justify-between px-4 py-3">
<Link href="/" className="main-logo flex shrink-0 items-center">
<img className="ml-[5px] w-[164px] h-[40px] flex-none block dark:hidden" src="/assets/images/logo_dark.png" alt="logo" />
<img className="ml-[5px] w-[164px] h-[40px] flex-none hidden dark:block" src="/assets/images/logo_light.png" alt="logo" />
{/* <span className="align-middle text-2xl font-semibold ltr:ml-1.5 rtl:mr-1.5 dark:text-white-light lg:inline">VG Products</span> */}
<Link href="/user" className="main-logo flex shrink-0 items-center">
<span className="align-middle text-2xl font-bold ltr:ml-1.5 rtl:mr-1.5 dark:text-white-light lg:inline text-[#e8572a]">VG Products</span>
</Link>
<button
type="button"
@ -96,21 +94,9 @@ const Sidebar = () => {
</div>
</button>
<AnimateHeight duration={300} height={currentMenu === 'dashboard' ? 'auto' : 0}> */}
<li className="nav-item">
<Link href="/" className="group nav-link">
<div className="flex items-center">
<span className="shrink-0 group-hover:!text-primary">🏠</span>
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-[#506690] dark:group-hover:text-white-dark">{t('Dashboard')}</span>
</div>
</Link>
</li>
{/* </AnimateHeight>
</li> */}
{/* Dashboard removed */}
<h2 className="-mx-4 mb-1 flex items-center bg-[#0f2444] px-7 py-3 font-extrabold uppercase dark:bg-dark dark:bg-opacity-[0.08]">
<IconMinus className="hidden h-5 w-4 flex-none" />
<span>{t('settings')}</span>
</h2>
{/* Settings header removed */}
<li className="nav-item">
<Link href="/user" className="group nav-link">

View File

@ -14,11 +14,11 @@ const UserModule = () => {
const [addUserModal, setAddUserModal] = useState(false);
const defaultParams = {
userid: null,
_id: null,
name: '',
email: '',
password: '',
phonenumber: '',
mobileNumber: '',
role: 'customer',
};
const [params, setParams] = useState<any>({ ...defaultParams });
@ -26,9 +26,10 @@ const UserModule = () => {
// ✅ Fetch users
const fetchUsers = async () => {
try {
const res = await axios.get('https://ebay.backend.vgproducts.com/api/auth/users');
setUsers(res.data?.users || []);
setFilteredUsers(res.data?.users || []);
const res = await axios.get('http://localhost:3050/api/users');
const usersList = Array.isArray(res.data) ? res.data : (res.data?.users || []);
setUsers(usersList);
setFilteredUsers(usersList);
} catch (err) {
console.error(err);
showMessage('Failed to load users', 'error');
@ -72,19 +73,19 @@ const UserModule = () => {
// ✅ Add / Update User
const saveUser = async () => {
if (!params.name || !params.email || !params.phonenumber || !params.role) {
if (!params.name || !params.email || !params.role) {
showMessage('Please fill all required fields', 'error');
return;
}
try {
if (params.userid) {
if (params._id) {
// UPDATE
await axios.put(`https://ebay.backend.vgproducts.com/api/auth/users/${params.userid}`, params);
await axios.put(`http://localhost:3050/api/users/${params._id}`, params);
showMessage('User updated successfully');
} else {
// ADD
await axios.post('https://ebay.backend.vgproducts.com/api/auth/users/add', params);
await axios.post('http://localhost:3050/api/users/create', params);
showMessage('User added successfully');
}
setAddUserModal(false);
@ -113,7 +114,7 @@ const UserModule = () => {
}).then(async (result) => {
if (result.isConfirmed) {
try {
await axios.delete(`https://ebay.backend.vgproducts.com/api/auth/users/${user.userid}`);
await axios.delete(`http://localhost:3050/api/users/${user._id}`);
showMessage('User deleted successfully');
fetchUsers();
} catch (err) {
@ -174,10 +175,10 @@ const UserModule = () => {
</thead>
<tbody>
{filteredUsers.map((user: any) => (
<tr key={user.userid}>
<tr key={user._id}>
<td>{user.name}</td>
<td>{user.email}</td>
<td>{user.phonenumber}</td>
<td>{user.mobileNumber}</td>
<td>{user.role}</td>
<td className="text-center">
<div className="flex justify-center gap-2">
@ -241,7 +242,7 @@ const UserModule = () => {
<IconX />
</button>
<div className="bg-[#fbfbfb] py-3 text-lg font-medium ltr:pl-5 rtl:pr-5 dark:bg-[#121c2c]">
{params.userid ? 'Edit User' : 'Add User'}
{params._id ? 'Edit User' : 'Add User'}
</div>
<div className="p-5">
<form>
@ -267,7 +268,7 @@ const UserModule = () => {
placeholder="Enter email"
/>
</div>
{!params.userid && (
{!params._id && (
<div className="mb-4">
<label>Password</label>
<input
@ -283,10 +284,10 @@ const UserModule = () => {
<div className="mb-4">
<label>Phone Number</label>
<input
id="phonenumber"
id="mobileNumber"
type="text"
className="form-input"
value={params.phonenumber}
value={params.mobileNumber || ''}
onChange={changeValue}
placeholder="Enter phone number"
/>
@ -316,7 +317,7 @@ const UserModule = () => {
className="btn btn-primary ltr:ml-4 rtl:mr-4"
onClick={saveUser}
>
{params.userid ? 'Update' : 'Add'}
{params._id ? 'Update' : 'Add'}
</button>
</div>
</form>