1
0
Code Issues Pull Requests Actions Packages Projects Releases Wiki Activity Security Code Quality

Add logon page

This commit is contained in:
2025-07-06 10:18:19 +07:00
parent 99607fb75b
commit e8f76f395a
6 changed files with 241 additions and 14 deletions

16
src/app/api/auth/route.ts Normal file
View File

@@ -0,0 +1,16 @@
import { NextRequest, NextResponse } from 'next/server';
import { db, initDB } from '@/database/database';
export async function POST(req: NextRequest) {
await initDB();
const { username, password } = await req.json();
const user = db.data?.users.find(
(u) => u.username === username && u.password === password && !u.isDeleted
);
if (user) {
// In a real app, return a JWT or session token
return NextResponse.json({ success: true, user: { id: user.id, username: user.username, email: user.email, firstName: user.firstName, lastName: user.lastName } });
} else {
return NextResponse.json({ success: false, message: 'Invalid credentials' }, { status: 401 });
}
}

View File

@@ -0,0 +1,90 @@
"use client";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import axios from "axios";
import { useState } from "react";
import { loginSchema } from "@/schemas/auth.schema";
import { Form } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
type LoginForm = z.infer<typeof loginSchema>;
export default function LoginPage() {
const form = useForm<LoginForm>({
resolver: zodResolver(loginSchema),
defaultValues: { username: "", password: "" },
});
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const onSubmit = async (data: LoginForm) => {
setError("");
setLoading(true);
try {
const res = await axios.post("/api/auth", data);
if (res.data.success) {
// You can redirect or set session here
window.location.href = "/";
} else {
setError(res.data.message || "Login failed");
}
} catch (e: any) {
setError(e.response?.data?.message || "Login failed");
} finally {
setLoading(false);
}
};
return (
<div className="flex min-h-screen items-center justify-center bg-gray-50">
<div className="w-full max-w-md rounded-lg bg-white p-8 shadow">
<h2 className="mb-6 text-center text-2xl font-bold">Login</h2>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<div>
<Label htmlFor="username">Username</Label>
<Input
id="username"
type="text"
{...form.register("username")}
aria-invalid={!!form.formState.errors.username}
disabled={loading}
/>
{form.formState.errors.username && (
<p className="mt-1 text-xs text-red-500">
{form.formState.errors.username.message as string}
</p>
)}
</div>
<div>
<Label htmlFor="password">Password</Label>
<Input
id="password"
type="password"
{...form.register("password")}
aria-invalid={!!form.formState.errors.password}
disabled={loading}
/>
{form.formState.errors.password && (
<p className="mt-1 text-xs text-red-500">
{form.formState.errors.password.message as string}
</p>
)}
</div>
{error && <div className="text-red-500 text-sm">{error}</div>}
<button
type="submit"
className="w-full rounded bg-blue-600 py-2 px-4 font-semibold text-white hover:bg-blue-700 disabled:opacity-50"
disabled={loading}
>
{loading ? "Logging in..." : "Login"}
</button>
</form>
</Form>
</div>
</div>
);
}

View File

@@ -0,0 +1,8 @@
import { z } from "zod";
export const loginSchema = z.object({
username: z.string().min(1, "Username is required"),
password: z.string().min(1, "Password is required"),
});
export type LoginSchema = typeof loginSchema;

View File

@@ -0,0 +1,24 @@
import { z } from "zod";
export const customerSchema = z.object({
id: z.number(),
firstNameEn: z.string(),
lastNameEn: z.string(),
email: z.string().email(),
mobile: z.string(),
// If you want to add optional or commented fields from the database schema, add them here as needed
});
export type Customer = z.infer<typeof customerSchema>;
export const customerDependantSchema = z.object({
id: z.number(),
custId: z.string(),
firstNameEn: z.string(),
lastNameEn: z.string(),
email: z.string().email(),
email2: z.string().email().optional(),
// Add more fields as needed from the database schema
});
export type CustomerDependant = z.infer<typeof customerDependantSchema>;