Add logon page
This commit is contained in:
16
src/app/api/auth/route.ts
Normal file
16
src/app/api/auth/route.ts
Normal 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 });
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
8
src/schemas/auth.schema.ts
Normal file
8
src/schemas/auth.schema.ts
Normal 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;
|
||||
24
src/schemas/customer.schema.ts
Normal file
24
src/schemas/customer.schema.ts
Normal 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>;
|
||||
Reference in New Issue
Block a user