Files
TEDI-DDP-FE/src/components/page/auth/MainLogin/MainLogin.tsx
T
2026-06-06 01:02:07 +07:00

206 lines
6.6 KiB
TypeScript

"use client";
import React, { useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import { useMutation } from "@tanstack/react-query";
import { ShieldPlus, User } from "lucide-react";
import { useSelector } from "react-redux";
import { RootState, store } from "@/redux/store";
import {
setDataLoginStorage,
setStateLogin,
setToken,
} from "@/redux/reducer/auth";
import { setRememberPassword } from "@/redux/reducer/site";
import { setInfoUser } from "@/redux/reducer/user";
import authServices, { LoginResponse } from "@/services/authServices";
import { httpRequest } from "@/services";
import { PATH } from "@/constant/config";
import FormCustom from "@/components/utils/FormCustom";
import InputForm from "@/components/utils/FormCustom/components/InputForm";
import CustomLoading from "@/components/customs/custom-loading";
import CustomButton from "@/components/customs/custom-button";
import { ContextFormCustom } from "@/components/utils/FormCustom/contexts";
export default function MainLogin() {
const router = useRouter();
const { dataLoginStorage } = useSelector((state: RootState) => state.auth);
const { isRememberPassword } = useSelector((state: RootState) => state.site);
// Khởi tạo state form từ data lưu trữ
const [form, setForm] = useState(() => ({
username: isRememberPassword ? dataLoginStorage?.usernameStorage || "" : "",
password: isRememberPassword ? dataLoginStorage?.passwordStorage || "" : "",
}));
const loginMutation = useMutation<LoginResponse>({
mutationFn: async () => {
return (await httpRequest({
http: authServices.login({
username: form.username,
password: form.password,
deviceId: "Browser-Chrome-Windowns",
}),
})) as LoginResponse;
},
onSuccess(data) {
if (data) {
store.dispatch(setToken(data?.token));
store.dispatch(
setInfoUser({
accessToken: data?.token || "",
refreshToken: data?.refreshToken || "",
userId: data?.userId || "",
}),
);
store.dispatch(setStateLogin(true));
if (isRememberPassword) {
store.dispatch(
setDataLoginStorage({
usernameStorage: form.username,
passwordStorage: form.password,
}),
);
} else {
store.dispatch(setDataLoginStorage(null));
}
router.replace(PATH.HOME, undefined);
}
},
});
const handleLogin = () => {
// Kiểm tra nhanh điều kiện dữ liệu trước khi trigger API
if (!form.username || !form.password) return;
if (isRememberPassword) {
store.dispatch(
setDataLoginStorage({
usernameStorage: form.username,
passwordStorage: form.password,
}),
);
} else {
store.dispatch(setDataLoginStorage(null));
}
loginMutation.mutate();
};
return (
<div className="w-full">
<CustomLoading loading={loginMutation.isPending} />
<FormCustom form={form} setForm={setForm} onSubmit={handleLogin}>
{/* TITLE */}
<h3 className="text-[34px] font-semibold text-[#1A1B2D]">Đăng nhập</h3>
<p className="mt-1 text-[14px] font-medium text-[#6F767E]">
Chào mừng bạn đến với hệ thống quản
</p>
{/* FORM */}
<div className="mt-6">
{/* USERNAME */}
<InputForm
label={
<span>
Tài khoản<span className="text-red-500"> *</span>
</span>
}
placeholder="Tài khoản"
type="text"
name="username"
onClean
isRequired
isBlur
showDone
icon={<User size={22} />}
/>
{/* PASSWORD */}
<div className="mt-5">
<InputForm
label={
<span>
Mật khẩu<span className="text-red-500"> *</span>
</span>
}
placeholder="Mật khẩu"
type="password"
name="password"
onClean
isRequired
isBlur
showDone
icon={<ShieldPlus size={22} />}
/>
</div>
{/* REMEMBER PASSWORD */}
<div className="mt-[14px] flex items-center gap-2 cursor-pointer">
<input
id="rememberPassword"
type="checkbox"
checked={isRememberPassword}
onChange={() =>
store.dispatch(setRememberPassword(!isRememberPassword))
}
className="h-5 w-5 cursor-pointer accent-[#0011AB]"
/>
<label
htmlFor="rememberPassword"
className="cursor-pointer select-none text-[14px] font-medium text-[#171717]"
>
Nhớ mật khẩu
</label>
</div>
{/* BUTTONS */}
<div className="mt-6">
<div className="flex gap-2">
{/* LOGIN BUTTON */}
<ContextFormCustom.Consumer>
{({ isDone }) => {
// Tự kiểm tra xem form hiện tại đã có sẵn dữ liệu hợp lệ chưa
const hasRememberedData = !!(form.username && form.password);
// Sáng nút nếu FormCustom báo Done HOẶC form đã có sẵn dữ liệu từ Redux
const canSubmit = isDone || hasRememberedData;
return (
<CustomButton
variant="midnightBlue"
disabled={!canSubmit}
rounded="full"
type="button" // Chuyển từ "submit" sang "button" để tránh bị FormCustom chặn
onClick={handleLogin} // Gọi trực tiếp hàm submit khi click
className="font-bold text-2xl disabled:cursor-not-allowed disabled:opacity-50 h-[52px]"
>
Đăng nhập
</CustomButton>
);
}}
</ContextFormCustom.Consumer>
{/* REGISTER BUTTON */}
<CustomButton
variant="default"
rounded="full"
className="font-bold text-2xl disabled:cursor-not-allowed disabled:opacity-50 h-[52px]"
onClick={() => router.push(PATH.REGISTER)}
>
Đăng
</CustomButton>
</div>
</div>
</div>
</FormCustom>
</div>
);
}