diff --git a/frontend/src/pages/xray/balancers/BalancerFormModal.tsx b/frontend/src/pages/xray/balancers/BalancerFormModal.tsx index 446364c93..93d6ff250 100644 --- a/frontend/src/pages/xray/balancers/BalancerFormModal.tsx +++ b/frontend/src/pages/xray/balancers/BalancerFormModal.tsx @@ -68,10 +68,14 @@ export default function BalancerFormModal({ }: BalancerFormModalProps) { const { t } = useTranslation(); const [state, setState] = useState(() => initialState(balancer)); + const [touched, setTouched] = useState>>({}); + const [submitAttempted, setSubmitAttempted] = useState(false); const isEdit = balancer != null; - const update = (key: K, value: FormState[K]) => + const update = (key: K, value: FormState[K]) => { + setTouched((prev) => (prev[key] ? prev : { ...prev, [key]: true })); setState((prev) => ({ ...prev, [key]: value })); + }; const parsed = useMemo( () => BalancerFormSchema.safeParse(state), @@ -89,8 +93,17 @@ export default function BalancerFormModal({ return map; }, [parsed, t]); + const showTagIssue = submitAttempted || !!touched.tag; + const showSelectorIssue = submitAttempted || !!touched.selector; + const tagError = showTagIssue ? issues.tag : ''; + const selectorError = showSelectorIssue ? issues.selector : ''; + const showDuplicate = showTagIssue && duplicateTag; + function submit() { - if (!parsed.success || duplicateTag) return; + if (!parsed.success || duplicateTag) { + setSubmitAttempted(true); + return; + } const values = { ...parsed.data }; if (values.strategy !== 'leastLoad') delete values.settings; onConfirm(values); @@ -128,7 +141,6 @@ export default function BalancerFormModal({ title={title} okText={okText} cancelText={t('close')} - okButtonProps={{ disabled: !parsed.success || duplicateTag }} mask={{ closable: false }} onOk={submit} onCancel={onClose} @@ -137,8 +149,8 @@ export default function BalancerFormModal({