@@ -2,6 +2,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
22import { useForm } from "react-hook-form" ;
33import { z } from "zod" ;
44import { useTranslation } from "react-i18next" ;
5+ import { useEffect } from "react" ;
56import { Search } from "lucide-react" ;
67import { Button } from "@/components/ui/button" ;
78import {
@@ -22,13 +23,66 @@ import {
2223import { Input } from "@/components/ui/input" ;
2324import { Checkbox } from "@/components/ui/checkbox" ;
2425
25- const scanFormSchema = z . object ( {
26- start_ip : z . string ( ) . optional ( ) ,
27- end_ip : z . string ( ) . optional ( ) ,
28- use_predefined : z . boolean ( ) ,
29- timeout : z . number ( ) . min ( 1 ) . max ( 30 ) ,
30- max_workers : z . number ( ) . min ( 1 ) . max ( 100 ) ,
31- } ) ;
26+ // IP address validation regex
27+ const ipRegex =
28+ / ^ (?: (?: 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] [ 0 - 9 ] | [ 0 1 ] ? [ 0 - 9 ] [ 0 - 9 ] ? ) \. ) { 3 } (?: 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] [ 0 - 9 ] | [ 0 1 ] ? [ 0 - 9 ] [ 0 - 9 ] ? ) $ / ;
29+
30+ const scanFormSchema = z
31+ . object ( {
32+ start_ip : z . string ( ) . optional ( ) ,
33+ end_ip : z . string ( ) . optional ( ) ,
34+ use_predefined : z . boolean ( ) ,
35+ timeout : z . number ( ) . min ( 1 ) . max ( 30 ) ,
36+ max_workers : z . number ( ) . min ( 1 ) . max ( 100 ) ,
37+ } )
38+ . refine (
39+ ( data ) => {
40+ // If not using predefined, both IP fields are required
41+ if ( ! data . use_predefined ) {
42+ return (
43+ data . start_ip &&
44+ data . start_ip . trim ( ) !== "" &&
45+ data . end_ip &&
46+ data . end_ip . trim ( ) !== ""
47+ ) ;
48+ }
49+ return true ;
50+ } ,
51+ {
52+ message : "Start IP and End IP are required when not using predefined IPs" ,
53+ path : [ "start_ip" ] ,
54+ } ,
55+ )
56+ . refine (
57+ ( data ) => {
58+ // Validate start IP format if provided and not using predefined
59+ if (
60+ ! data . use_predefined &&
61+ data . start_ip &&
62+ data . start_ip . trim ( ) !== ""
63+ ) {
64+ return ipRegex . test ( data . start_ip . trim ( ) ) ;
65+ }
66+ return true ;
67+ } ,
68+ {
69+ message : "Please enter a valid IP address (e.g., 192.168.1.1)" ,
70+ path : [ "start_ip" ] ,
71+ } ,
72+ )
73+ . refine (
74+ ( data ) => {
75+ // Validate end IP format if provided and not using predefined
76+ if ( ! data . use_predefined && data . end_ip && data . end_ip . trim ( ) !== "" ) {
77+ return ipRegex . test ( data . end_ip . trim ( ) ) ;
78+ }
79+ return true ;
80+ } ,
81+ {
82+ message : "Please enter a valid IP address (e.g., 192.168.1.254)" ,
83+ path : [ "end_ip" ] ,
84+ } ,
85+ ) ;
3286
3387export type ScanFormData = z . infer < typeof scanFormSchema > ;
3488
@@ -53,11 +107,21 @@ export function ScanForm({ onSubmit, isLoading = false }: ScanFormProps) {
53107
54108 const usePredefined = form . watch ( "use_predefined" ) ;
55109
110+ // Clear IP fields when switching to predefined mode
111+ useEffect ( ( ) => {
112+ if ( usePredefined ) {
113+ form . setValue ( "start_ip" , "" ) ;
114+ form . setValue ( "end_ip" , "" ) ;
115+ // Clear any validation errors
116+ form . clearErrors ( [ "start_ip" , "end_ip" ] ) ;
117+ }
118+ } , [ usePredefined , form ] ) ;
119+
56120 const handleSubmit = ( data : ScanFormData ) => {
57121 const cleanData = {
58122 ...data ,
59- start_ip : data . start_ip || undefined ,
60- end_ip : data . end_ip || undefined ,
123+ start_ip : data . start_ip ?. trim ( ) || undefined ,
124+ end_ip : data . end_ip ?. trim ( ) || undefined ,
61125 } ;
62126 onSubmit ( cleanData ) ;
63127 } ;
@@ -106,9 +170,18 @@ export function ScanForm({ onSubmit, isLoading = false }: ScanFormProps) {
106170 name = "start_ip"
107171 render = { ( { field } ) => (
108172 < FormItem >
109- < FormLabel > { t ( "dashboard.scanForm.startIp" ) } </ FormLabel >
173+ < FormLabel >
174+ { t ( "dashboard.scanForm.startIp" ) }
175+ { ! usePredefined && (
176+ < span className = "text-red-500 ml-1" > *</ span >
177+ ) }
178+ </ FormLabel >
110179 < FormControl >
111- < Input placeholder = "192.168.1.1" { ...field } />
180+ < Input
181+ placeholder = "192.168.1.1"
182+ { ...field }
183+ value = { field . value || "" }
184+ />
112185 </ FormControl >
113186 < FormMessage />
114187 </ FormItem >
@@ -120,9 +193,18 @@ export function ScanForm({ onSubmit, isLoading = false }: ScanFormProps) {
120193 name = "end_ip"
121194 render = { ( { field } ) => (
122195 < FormItem >
123- < FormLabel > { t ( "dashboard.scanForm.endIp" ) } </ FormLabel >
196+ < FormLabel >
197+ { t ( "dashboard.scanForm.endIp" ) }
198+ { ! usePredefined && (
199+ < span className = "text-red-500 ml-1" > *</ span >
200+ ) }
201+ </ FormLabel >
124202 < FormControl >
125- < Input placeholder = "192.168.1.254" { ...field } />
203+ < Input
204+ placeholder = "192.168.1.254"
205+ { ...field }
206+ value = { field . value || "" }
207+ />
126208 </ FormControl >
127209 < FormMessage />
128210 </ FormItem >
0 commit comments