refactor(add-service): Refactor ServiceForm.tsx to support internationalization

- Extract ServiceForm.tsx validation logic into the custom hook useServiceSchema
- Add internationalization support and move error messages to translation files
This commit is contained in:
YiZixuan
2025-08-17 23:13:25 +08:00
parent 6bf75b2bf7
commit fa3ad9b2e1
5 changed files with 57 additions and 20 deletions
@@ -3,7 +3,7 @@ import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { useToast } from "@/hooks/use-toast"; import { useToast } from "@/hooks/use-toast";
import { serviceSchema, ServiceFormData } from "./types"; import { useServiceSchema, ServiceFormData } from "./types";
import { ServiceBasicFields } from "./ServiceBasicFields"; import { ServiceBasicFields } from "./ServiceBasicFields";
import { ServiceTypeField } from "./ServiceTypeField"; import { ServiceTypeField } from "./ServiceTypeField";
import { ServiceConfigFields } from "./ServiceConfigFields"; import { ServiceConfigFields } from "./ServiceConfigFields";
@@ -36,6 +36,8 @@ export function ServiceForm({
const [isSubmitting, setIsSubmitting] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false);
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const serviceSchema = useServiceSchema();
// Initialize form with default values // Initialize form with default values
const form = useForm<ServiceFormData>({ const form = useForm<ServiceFormData>({
resolver: zodResolver(serviceSchema), resolver: zodResolver(serviceSchema),
@@ -1,13 +1,34 @@
import { z } from "zod"; import { z } from "zod";
import type { ZodSchema } from "zod";
import { useLanguage } from "@/contexts/LanguageContext";
export const serviceSchema = z.object({
name: z.string().min(1, "Service name is required"), export type ServiceFormData = {
name: string;
type: "http" | "ping" | "tcp" | "dns";
url: string;
port?: string;
interval: string;
retries: string;
notificationStatus?: "enabled" | "disabled";
notificationChannels?: string[];
alertTemplate?: string;
regionalMonitoringEnabled?: boolean;
regionalAgents?: string[];
};
// Hook to use the schema with translations
export const useServiceSchema = () => {
const { t } = useLanguage();
return z.object({
name: z.string().min(1, t("serviceNameRequired")),
type: z.enum(["http", "ping", "tcp", "dns"]), type: z.enum(["http", "ping", "tcp", "dns"]),
url: z.string().min(1, "URL/Domain/Host is required").refine((value) => { url: z.string()
// Basic validation - more specific validation can be added per type .min(1, t("urlDomainHostRequired"))
return value.trim().length > 0; .refine(
}, "Please enter a valid URL, hostname, or domain"), (value) => value.trim().length > 0,
t("enterValidUrlHostnameDomain")
),
port: z.string().optional(), port: z.string().optional(),
interval: z.string(), interval: z.string(),
retries: z.string(), retries: z.string(),
@@ -17,6 +38,5 @@ export const serviceSchema = z.object({
// Regional monitoring fields - now supports multiple agents // Regional monitoring fields - now supports multiple agents
regionalMonitoringEnabled: z.boolean().optional(), regionalMonitoringEnabled: z.boolean().optional(),
regionalAgents: z.array(z.string()).optional(), regionalAgents: z.array(z.string()).optional(),
}); });
};
export type ServiceFormData = z.infer<typeof serviceSchema>;
@@ -84,4 +84,9 @@ export const servicesTranslations: ServicesTranslations = {
targetDNSDesc: "Enter domain name for DNS record monitoring (A, AAAA, MX, etc.)", targetDNSDesc: "Enter domain name for DNS record monitoring (A, AAAA, MX, etc.)",
targetDefaultDesc: "Enter the target URL or hostname for monitoring", targetDefaultDesc: "Enter the target URL or hostname for monitoring",
targetDefaultPlaceholder: "Enter URL or hostname", targetDefaultPlaceholder: "Enter URL or hostname",
// types.ts
serviceNameRequired: "Service name is required",
urlDomainHostRequired: "URL/Domain/Host is required",
enterValidUrlHostnameDomain: "Please enter a valid URL, hostname, or domain",
}; };
@@ -82,4 +82,9 @@ export interface ServicesTranslations {
targetDNSDesc: string; targetDNSDesc: string;
targetDefaultDesc: string; targetDefaultDesc: string;
targetDefaultPlaceholder: string; targetDefaultPlaceholder: string;
// types.ts
serviceNameRequired: string;
urlDomainHostRequired: string;
enterValidUrlHostnameDomain: string;
} }
@@ -84,4 +84,9 @@ export const servicesTranslations: ServicesTranslations = {
targetDNSDesc: "输入要监控的 DNS 记录域名(A、AAAA、MX等)", targetDNSDesc: "输入要监控的 DNS 记录域名(A、AAAA、MX等)",
targetDefaultDesc: "输入要监控的目标 URL 或主机名", targetDefaultDesc: "输入要监控的目标 URL 或主机名",
targetDefaultPlaceholder: "输入 URL 或主机名", targetDefaultPlaceholder: "输入 URL 或主机名",
// types.ts
serviceNameRequired: "服务名称是必填项",
urlDomainHostRequired: "URL/域名/主机名是必填项",
enterValidUrlHostnameDomain: "请输入有效的URL、主机名或域名",
}; };