finish form extraction

This commit is contained in:
Alex Holliday committed 2025-12-29 18:28:30 +00:00
1 parent 6dcfb67246
commit 18408a6bf6
15 files changed
+65 -64

No files matched your search

@@ -1,4 +1,4 @@
import { profileSchema } from "@/validation/zod";
import { profileSchema } from "@/validation";
import { useMemo } from "react";
import { z } from "zod";
@@ -1,14 +1,13 @@
import { recoverySchema } from "@/validation/zod";
import { useMemo } from "react";
import type { FormValues } from "@/pages/recovery/RecoveryForm";
import { z } from "zod";
export const useInitForm = ({
initialData,
}: {
initialData: Partial<z.infer<typeof recoverySchema>> | undefined;
initialData: FormValues | undefined;
}) => {
return useMemo(() => {
const defaults: z.infer<typeof recoverySchema> = {
const defaults: FormValues = {
email: initialData?.email || "",
};
return { defaults };
+1 -1
View File
@@ -1,4 +1,4 @@
import { resetSchema } from "@/validation/zod";
import { resetSchema } from "@/validation";
import { useMemo } from "react";
import { z } from "zod";
+1 -1
View File
@@ -8,7 +8,7 @@ import { BasePage, ConfigBox } from "@/components/design-elements";
import { useEffect, useState, useMemo } from "react";
import { useTheme } from "@mui/material/styles";
import { useTranslation } from "react-i18next";
import { inviteSchema } from "@/validation/zod";
import { inviteSchema } from "@/validation";
import { z } from "zod";
import { useForm, Controller } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
+1 -3
View File
@@ -5,12 +5,10 @@ import { useState, useEffect } from "react";
import type { IUser } from "@/types/user";
import type { ApiResponse } from "@/types/api";
import { useGet, usePatch, useGetOnDemand } from "@/hooks/UseApi";
import { z } from "zod";
import { profileSchema } from "@/validation/zod";
import { useTranslation } from "react-i18next";
import { useAppDispatch } from "@/hooks/AppHooks";
import { setUser as setUserGlobal } from "@/features/authSlice";
type FormValues = z.infer<typeof profileSchema>;
import type { FormValues } from "@/pages/profile/ProfileForm";
const Profile = () => {
const { t } = useTranslation();
+6 -6
View File
@@ -12,8 +12,8 @@ import { useTheme } from "@mui/material/styles";
import { useInitForm } from "@/hooks/forms/UseInitProfileForm";
import type { IUser } from "@/types/user";
import { profileSchema } from "@/validation/zod";
type FormData = z.infer<typeof profileSchema>;
import { profileSchema } from "@/validation";
export type FormValues = z.infer<typeof profileSchema>;
export const ProfileForm = ({
user,
@@ -23,21 +23,21 @@ export const ProfileForm = ({
}: {
user: Partial<IUser> | null;
hasUser?: boolean;
initialData?: Partial<FormData>;
onSubmit: SubmitHandler<FormData>;
initialData?: Partial<FormValues>;
onSubmit: SubmitHandler<FormValues>;
loading: boolean;
}) => {
const { t } = useTranslation();
const theme = useTheme();
const { defaults } = useInitForm({ initialData: initialData });
const resolver = zodResolver(profileSchema) as unknown as Resolver<FormData>;
const resolver = zodResolver(profileSchema) as Resolver<FormValues>;
const {
handleSubmit,
control,
reset,
formState: { errors },
} = useForm<FormData>({
} = useForm<FormValues>({
resolver,
defaultValues: {
firstName: "",
+3 -6
View File
@@ -2,19 +2,16 @@ import { AuthBasePage } from "@/components/auth";
import { useTranslation } from "react-i18next";
import { RecoveryForm } from "./RecoveryForm";
import { recoverySchema } from "@/validation/zod";
import { z } from "zod";
import { usePost } from "@/hooks/UseApi";
import { useToast } from "@/hooks/UseToast";
type FormData = z.infer<typeof recoverySchema>;
import type { FormValues } from "@/pages/recovery/RecoveryForm";
const Recovery = () => {
const { t } = useTranslation();
const { post, loading } = usePost<FormData>();
const { post, loading } = usePost<FormValues>();
const { showToast } = useToast();
const onSubmit = async (data: FormData) => {
const onSubmit = async (data: FormValues) => {
await post("/recovery", data);
showToast(t("common.toasts.recoveryEmailSent"));
};
+6 -6
View File
@@ -9,18 +9,18 @@ import { useEffect } from "react";
import { z } from "zod";
import { useTranslation } from "react-i18next";
import { useTheme } from "@mui/material/styles";
import { useInitForm } from "@/hooks/forms/UseInitRegisterForm";
import { useInitForm } from "@/hooks/forms/UseInitRecoveryForm";
import { recoverySchema } from "@/validation/zod";
type FormData = z.infer<typeof recoverySchema>;
import { recoverySchema } from "@/validation";
export type FormValues = z.infer<typeof recoverySchema>;
export const RecoveryForm = ({
initialData,
onSubmit,
loading,
}: {
initialData?: Partial<FormData>;
onSubmit: SubmitHandler<FormData>;
initialData?: FormValues;
onSubmit: SubmitHandler<FormValues>;
loading: boolean;
}) => {
const { t } = useTranslation();
@@ -32,7 +32,7 @@ export const RecoveryForm = ({
control,
reset,
formState: { errors },
} = useForm<FormData>({
} = useForm<FormValues>({
resolver: zodResolver(recoverySchema),
defaultValues: {
email: "",
+2 -5
View File
@@ -3,8 +3,6 @@ import { AuthBasePage } from "@/components/auth";
import { useTranslation } from "react-i18next";
import { useParams } from "react-router";
import { ResetForm } from "@/pages/recovery/ResetForm";
import { resetSchema } from "@/validation/zod";
import { z } from "zod";
import { usePost } from "@/hooks/UseApi";
import { useToast } from "@/hooks/UseToast";
import { useNavigate } from "react-router";
@@ -15,8 +13,7 @@ import {
setSelectedTeamId,
logout,
} from "@/features/authSlice";
type FormData = z.infer<typeof resetSchema>;
import type { FormValues } from "@/pages/recovery/ResetForm";
const Reset = () => {
const { t } = useTranslation();
@@ -26,7 +23,7 @@ const Reset = () => {
const { toastSuccess } = useToast();
const { id: token } = useParams<{ id: string }>();
const onSubmit = async (data: FormData) => {
const onSubmit = async (data: FormValues) => {
const result = await post(`/recovery/reset`, {
password: data.password,
token: token || "",
+5 -5
View File
@@ -11,8 +11,8 @@ import { useTranslation } from "react-i18next";
import { useTheme } from "@mui/material/styles";
import { useInitForm } from "@/hooks/forms/UseInitResetForm";
import { resetSchema } from "@/validation/zod";
type FormData = z.infer<typeof resetSchema>;
import { resetSchema } from "@/validation";
export type FormValues = z.infer<typeof resetSchema>;
export const ResetForm = ({
initialData,
@@ -20,8 +20,8 @@ export const ResetForm = ({
loading,
}: {
hasUser?: boolean;
initialData?: Partial<FormData>;
onSubmit: SubmitHandler<FormData>;
initialData?: Partial<FormValues>;
onSubmit: SubmitHandler<FormValues>;
loading: boolean;
}) => {
const { t } = useTranslation();
@@ -33,7 +33,7 @@ export const ResetForm = ({
control,
reset,
formState: { errors },
} = useForm<FormData>({
} = useForm<FormValues>({
resolver: zodResolver(resetSchema),
defaultValues: {
password: "",
+4 -1
View File
@@ -1,4 +1,3 @@
export * from "./zod";
export * from "./login";
export * from "./register";
export * from "./monitor";
@@ -10,3 +9,7 @@ export * from "./maintenance";
export * from "./team";
export * from "./system-settings";
export * from "./status-page";
export * from "./invite";
export * from "./recovery";
export * from "./reset";
export * from "./profile";
+9
View File
@@ -0,0 +1,9 @@
import { z } from "zod";
export const inviteSchema = z.object({
email: z.email("Invalid email address"),
teamId: z.string().min(1, "Team is required"),
teamRoleId: z.string().min(1, "Role is required"),
orgRoleId: z.string().optional(),
});
@@ -1,30 +1,5 @@
import { z } from "zod";
export const inviteSchema = z.object({
email: z.email("Invalid email address"),
teamId: z.string().min(1, "Team is required"),
teamRoleId: z.string().min(1, "Role is required"),
orgRoleId: z.string().optional(),
});
export const recoverySchema = z.object({
email: z.email({ message: "Invalid email address" }).trim().toLowerCase(),
});
export const resetSchema = z
.object({
password: z
.string()
.min(6, { message: "Password must be at least 6 characters" }),
confirmPassword: z
.string()
.min(6, { message: "Confirm Password must be at least 6 characters" }),
})
.refine((data) => data.password === data.confirmPassword, {
path: ["confirmPassword"],
message: "Passwords must match",
});
export const profileSchema = z
.object({
firstName: z
@@ -63,3 +38,4 @@ export const profileSchema = z
path: ["confirmPassword"],
}
);
+6
View File
@@ -0,0 +1,6 @@
import { z } from "zod";
export const recoverySchema = z.object({
email: z.email({ message: "Invalid email address" }).trim().toLowerCase(),
});
+16
View File
@@ -0,0 +1,16 @@
import { z } from "zod";
export const resetSchema = z
.object({
password: z
.string()
.min(6, { message: "Password must be at least 6 characters" }),
confirmPassword: z
.string()
.min(6, { message: "Confirm Password must be at least 6 characters" }),
})
.refine((data) => data.password === data.confirmPassword, {
path: ["confirmPassword"],
message: "Passwords must match",
});