simplify form

This commit is contained in:
Alex Holliday
2026-02-18 20:14:35 +00:00
parent bbb2da3935
commit cdbf5fd0c0
2 changed files with 61 additions and 56 deletions
+24 -1
View File
@@ -1,9 +1,15 @@
import { BasePage, ConfigBox } from "@/Components/v2/design-elements";
import { Autocomplete, Select } from "@/Components/v2/inputs";
import { Stack, useTheme, MenuItem, type SelectChangeEvent } from "@mui/material";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useTranslation } from "react-i18next";
import { useSelector, useDispatch } from "react-redux";
import DummyChart from "@/Pages/Settings/DummyChart";
import { useGet } from "@/Hooks/UseApi";
import { useSettingsForm } from "@/Hooks/useSettingsForm";
import type { SettingsFormData } from "@/Validation/settings";
import {
setTimezone,
@@ -25,6 +31,23 @@ export const SettingsPage = () => {
const theme = useTheme();
const { t, i18n } = useTranslation();
const dispatch = useDispatch();
// Fetch settings data from API
const { data: fetchedSettings } = useGet<any>("/settings");
// Initialize form with schema and defaults
const { schema, defaults } = useSettingsForm({ data: fetchedSettings?.settings });
const form = useForm<SettingsFormData>({
resolver: zodResolver(schema),
defaultValues: defaults,
});
// Reset form when defaults change
useEffect(() => {
form.reset(defaults);
}, [defaults, form]);
const {
timezone: selectedTimezoneId,
mode,
@@ -61,7 +84,7 @@ export const SettingsPage = () => {
const languages = Object.keys(i18n.options.resources || {});
return (
<BasePage>
<BasePage component="form">
<Stack gap={theme.spacing(8)}>
<ConfigBox
title={t("pages.settings.form.timezone.title")}
+37 -55
View File
@@ -1,69 +1,51 @@
import { z } from "zod";
// Helper to normalize empty strings to undefined
const optionalString = () =>
z.preprocess(
(val) =>
val === "" || val === null || val === undefined ? undefined : String(val).trim(),
z.string().optional()
);
// Helper for threshold fields
const thresholdField = (min: number, max: number, unit: string) =>
z.preprocess(
(val) => (val === "" || val === null || val === undefined ? undefined : val),
z.coerce
.number()
.int()
.min(min, `Min ${min}${unit}`)
.max(max, `Max ${max}${unit}`)
.optional()
);
export const settingsSchema = z.object({
systemEmailIgnoreTLS: z.boolean(),
systemEmailRequireTLS: z.boolean(),
systemEmailRejectUnauthorized: z.boolean(),
systemEmailConnectionHost: optionalString(),
systemEmailConnectionHost: z
.string()
.transform((val) => (val.trim() === "" ? undefined : val.trim()))
.optional(),
systemEmailSecure: z.boolean().optional(),
systemEmailPool: z.boolean().optional(),
showURL: z.boolean().optional(),
checkTTL: z.coerce
.number()
.int()
.min(1, "Please enter a value")
.max(365, "Maximum 365 days"),
pagespeedApiKey: optionalString(),
systemEmailHost: z.preprocess(
(val) =>
val === "" || val === null || val === undefined ? undefined : String(val).trim(),
z
.string()
.regex(/^[a-zA-Z0-9.-]+$/, "Invalid hostname or IP address")
.optional()
),
systemEmailPort: z.preprocess(
(val) => (val === "" || val === null || val === undefined ? undefined : val),
z.coerce
.number()
.int()
.min(1, "Port must be at least 1")
.max(65535, "Port must be at most 65535")
.optional()
),
systemEmailAddress: z.preprocess((val) => {
if (val === "" || val === null || val === undefined) return undefined;
return String(val).toLowerCase().trim();
}, z.string().email("Please enter a valid email address").optional()),
systemEmailUser: optionalString(),
systemEmailPassword: optionalString(),
systemEmailTLSServername: optionalString(),
checkTTL: z.number().int().min(1, "Please enter a value").max(365, "Maximum 365 days"),
pagespeedApiKey: z
.string()
.transform((val) => (val.trim() === "" ? undefined : val.trim()))
.optional(),
systemEmailHost: z
.string()
.regex(/^[a-zA-Z0-9.-]*$/, "Invalid hostname or IP address")
.transform((val) => (val.trim() === "" ? undefined : val.trim()))
.optional(),
systemEmailPort: z.number().int().min(1).max(65535).optional(),
systemEmailAddress: z
.string()
.email("Please enter a valid email address")
.or(z.literal(""))
.transform((val) => (val === "" ? undefined : val.toLowerCase().trim()))
.optional(),
systemEmailUser: z
.string()
.transform((val) => (val.trim() === "" ? undefined : val.trim()))
.optional(),
systemEmailPassword: z
.string()
.transform((val) => (val.trim() === "" ? undefined : val.trim()))
.optional(),
systemEmailTLSServername: z
.string()
.transform((val) => (val.trim() === "" ? undefined : val.trim()))
.optional(),
globalThresholds: z
.object({
cpu: thresholdField(0, 100, "%"),
memory: thresholdField(0, 100, "%"),
disk: thresholdField(0, 100, "%"),
temperature: thresholdField(0, 150, "°C"),
cpu: z.number().int().min(0).max(100).optional(),
memory: z.number().int().min(0).max(100).optional(),
disk: z.number().int().min(0).max(100).optional(),
temperature: z.number().int().min(0).max(150).optional(),
})
.optional(),
});