login UI
This commit is contained in:
1 parent
527543d79f
commit
ea68e660fc
7 files changed
+166
-6
No files matched your search
@@ -205,12 +205,17 @@ export const MonitorBasePageWithStates = ({
|
||||
);
|
||||
};
|
||||
|
||||
interface BaseAuthPageProps extends React.PropsWithChildren {
|
||||
interface BaseAuthPageProps extends React.PropsWithChildren, StackProps {
|
||||
title: string;
|
||||
subtitle: string;
|
||||
}
|
||||
|
||||
export const BaseAuthPage = ({ title, subtitle, children }: BaseAuthPageProps) => {
|
||||
export const BaseAuthPage = ({
|
||||
title,
|
||||
subtitle,
|
||||
children,
|
||||
...props
|
||||
}: BaseAuthPageProps) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<BasePage
|
||||
@@ -220,6 +225,7 @@ export const BaseAuthPage = ({ title, subtitle, children }: BaseAuthPageProps) =
|
||||
justifyContent={"center"}
|
||||
minHeight="100vh"
|
||||
position={"relative"}
|
||||
{...props}
|
||||
>
|
||||
<HeaderAuthControls
|
||||
hideLogo
|
||||
@@ -243,7 +249,16 @@ export const BaseAuthPage = ({ title, subtitle, children }: BaseAuthPageProps) =
|
||||
</Typography>
|
||||
<Typography variant="h1">{subtitle}</Typography>
|
||||
</Stack>
|
||||
{children}
|
||||
<Stack
|
||||
gap={theme.spacing(8)}
|
||||
width={{
|
||||
xs: "80%",
|
||||
md: "25%",
|
||||
lg: "15%",
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Stack>
|
||||
</BasePage>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import type { StackProps } from "@mui/material/Stack";
|
||||
import Link from "@mui/material/Link";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
|
||||
interface TextLinkProps extends StackProps {
|
||||
text: string;
|
||||
linkText: string;
|
||||
href: string;
|
||||
target?: string;
|
||||
}
|
||||
|
||||
export const TextLink = ({
|
||||
text,
|
||||
linkText,
|
||||
href,
|
||||
target = "_self",
|
||||
...props
|
||||
}: TextLinkProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
gap={theme.spacing(4)}
|
||||
{...props}
|
||||
>
|
||||
<Typography>{text}</Typography>
|
||||
<Link
|
||||
color="primary"
|
||||
to={href}
|
||||
component={RouterLink}
|
||||
target={target}
|
||||
>
|
||||
{linkText}
|
||||
</Link>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
@@ -18,3 +18,4 @@ export * from "./BaseChart";
|
||||
export * from "./Gauge";
|
||||
export * from "./Tabs";
|
||||
export * from "./SplitBox";
|
||||
export * from "./TextLink";
|
||||
@@ -0,0 +1,13 @@
|
||||
import { useMemo } from "react";
|
||||
import { loginSchema, type LoginFormData } from "@/Validation/login";
|
||||
|
||||
export const useLoginForm = () => {
|
||||
return useMemo(() => {
|
||||
const defaults: LoginFormData = {
|
||||
email: "",
|
||||
password: "",
|
||||
};
|
||||
|
||||
return { schema: loginSchema, defaults };
|
||||
}, []);
|
||||
};
|
||||
@@ -1,13 +1,79 @@
|
||||
import { BaseAuthPage } from "@/Components/v2/design-elements";
|
||||
import { BaseAuthPage, TextLink } from "@/Components/v2/design-elements";
|
||||
import { Button, TextField } from "@/Components/v2/inputs";
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod/dist/zod.js";
|
||||
import { useLoginForm } from "@/Hooks/useLoginForm";
|
||||
import type { LoginFormData } from "@/Validation/login";
|
||||
|
||||
const LoginPage = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { schema, defaults } = useLoginForm();
|
||||
|
||||
const { control, handleSubmit } = useForm<LoginFormData>({
|
||||
resolver: zodResolver(schema),
|
||||
defaultValues: defaults,
|
||||
});
|
||||
|
||||
const onSubmit = (data: LoginFormData) => {
|
||||
console.log("Login submitted:", data);
|
||||
};
|
||||
|
||||
return (
|
||||
<BaseAuthPage
|
||||
component="form"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
title={t("pages.auth.login.title")}
|
||||
subtitle={t("pages.auth.login.subtitle")}
|
||||
></BaseAuthPage>
|
||||
>
|
||||
<Controller
|
||||
name="email"
|
||||
control={control}
|
||||
render={({ field, fieldState }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fieldLabel={t("pages.auth.common.form.option.email.label")}
|
||||
placeholder={t("pages.auth.common.form.option.email.placeholder")}
|
||||
error={!!fieldState.error}
|
||||
helperText={fieldState.error ? t(fieldState.error.message ?? "") : ""}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
name="password"
|
||||
control={control}
|
||||
render={({ field, fieldState }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
type="password"
|
||||
fieldLabel={t("pages.auth.common.form.option.password.label")}
|
||||
placeholder={t("pages.auth.common.form.option.password.placeholder")}
|
||||
error={!!fieldState.error}
|
||||
helperText={fieldState.error ? t(fieldState.error.message ?? "") : ""}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Button
|
||||
variant="contained"
|
||||
type="submit"
|
||||
>
|
||||
{t("pages.auth.login.submit")}
|
||||
</Button>
|
||||
<TextLink
|
||||
alignSelf={"center"}
|
||||
text={t("pages.auth.login.links.forgotPassword.text")}
|
||||
linkText={t("pages.auth.login.links.forgotPassword.linkText")}
|
||||
href="/forgot-password"
|
||||
/>
|
||||
<TextLink
|
||||
alignSelf={"center"}
|
||||
text={t("pages.auth.login.links.register.text")}
|
||||
linkText={t("pages.auth.login.links.register.linkText")}
|
||||
href="/register"
|
||||
/>
|
||||
</BaseAuthPage>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const loginSchema = z.object({
|
||||
email: z
|
||||
.string()
|
||||
.min(1, "auth.common.inputs.email.errors.empty")
|
||||
.email("auth.common.inputs.email.errors.invalid")
|
||||
.transform((val) => val.toLowerCase().trim()),
|
||||
password: z.string().min(1, "auth.common.inputs.password.errors.empty"),
|
||||
});
|
||||
|
||||
export type LoginFormData = z.infer<typeof loginSchema>;
|
||||
@@ -515,7 +515,18 @@
|
||||
},
|
||||
"login": {
|
||||
"title": "Welcome back to Checkmate!",
|
||||
"subtitle": "Log in to continue"
|
||||
"subtitle": "Log in to continue",
|
||||
"submit": "Login",
|
||||
"links": {
|
||||
"forgotPassword": {
|
||||
"text": "Forgot password?",
|
||||
"linkText": "Reset password"
|
||||
},
|
||||
"register": {
|
||||
"text": "Don't have an account?",
|
||||
"linkText": "Register here"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"checks": {
|
||||
|
||||
Reference in new issue
Block a user