mosh-helpdesk/client/src/pages/LoginPage.tsx

90 lines
2.5 KiB
TypeScript
Raw Normal View History

import { useState } from "react";
2026-02-11 18:36:05 +01:00
import { Navigate, useNavigate } from "react-router";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
2026-02-11 18:36:05 +01:00
import { signIn, useSession } from "../lib/auth-client";
const loginSchema = z.object({
email: z.email("Please enter a valid email"),
password: z.string().min(1, "Password is required"),
});
type LoginFormData = z.infer<typeof loginSchema>;
2026-02-11 18:36:05 +01:00
export default function LoginPage() {
const { data: session, isPending } = useSession();
const navigate = useNavigate();
const [serverError, setServerError] = useState("");
const {
register,
handleSubmit,
formState: { errors, isSubmitting },
} = useForm<LoginFormData>({
resolver: zodResolver(loginSchema),
});
2026-02-11 18:36:05 +01:00
if (isPending) {
return <div className="loading">Loading...</div>;
}
if (session) {
return <Navigate to="/" replace />;
}
const onSubmit = async (data: LoginFormData) => {
setServerError("");
2026-02-11 18:36:05 +01:00
const { error } = await signIn.email(data);
2026-02-11 18:36:05 +01:00
if (error) {
setServerError(error.message ?? "Login failed");
2026-02-11 18:36:05 +01:00
return;
}
navigate("/", { replace: true });
};
return (
<div className="login-container">
<div className="login-card">
<h1>Helpdesk</h1>
<p className="login-subtitle">Sign in to your account</p>
<form onSubmit={handleSubmit(onSubmit)} noValidate>
{serverError && <div className="error-message">{serverError}</div>}
2026-02-11 18:36:05 +01:00
<label htmlFor="email">Email</label>
<input
id="email"
type="email"
className={errors.email ? "input-error" : ""}
2026-02-11 18:36:05 +01:00
placeholder="admin@example.com"
{...register("email")}
2026-02-11 18:36:05 +01:00
/>
{errors.email && (
<div className="field-error">{errors.email.message}</div>
)}
2026-02-11 18:36:05 +01:00
<label htmlFor="password">Password</label>
<input
id="password"
type="password"
className={errors.password ? "input-error" : ""}
2026-02-11 18:36:05 +01:00
placeholder="Enter your password"
{...register("password")}
2026-02-11 18:36:05 +01:00
/>
{errors.password && (
<div className="field-error">{errors.password.message}</div>
)}
<button
className="btn btn-primary"
type="submit"
disabled={isSubmitting}
>
{isSubmitting ? "Signing in..." : "Sign in"}
2026-02-11 18:36:05 +01:00
</button>
</form>
</div>
</div>
);
}