@@ -85,8 +85,43 @@ export default function MainForm() {
8585 const searchParams = useSearchParams ( ) ;
8686 const router = useRouter ( ) ;
8787
88+ // Helper to normalize algorithm values from URL to internal values
89+ const normalizeAlgorithm = ( algo ?: string | null ) => {
90+ if ( ! algo ) return null ;
91+ const a = algo . toLowerCase ( ) ;
92+ if ( a === "fcfs" || a === "firstcomefirstserve" || a === "first_come_first_serve" ) return "FCFS" ;
93+ if ( a === "rr" || a === "roundrobin" || a === "round_robin" ) return "RR" ;
94+ if ( a === "sjf" || a === "shortestjobfirst" || a === "shortest_job_first" ) return "SJF" ;
95+ if (
96+ a === "srtf" ||
97+ a === "shortestremainingtimefirst" ||
98+ a === "shortest_remaining_time_first"
99+ )
100+ return "SRTF" ;
101+ return null ;
102+ } ;
103+
104+ // Get initial values from URL
105+ const getInitialAlgorithm = ( ) => {
106+ const algoRaw = searchParams ?. get ( "algo" ) ;
107+ return normalizeAlgorithm ( algoRaw ) || "" ;
108+ } ;
109+
110+ const getInitialQuantum = ( ) => {
111+ const quantum = searchParams ?. get ( "quantum" ) ;
112+ const algo = normalizeAlgorithm ( searchParams ?. get ( "algo" ) ) ;
113+ if ( quantum && algo === "RR" ) {
114+ return parseInt ( quantum ) ;
115+ }
116+ return undefined ;
117+ } ;
118+
88119 const form = useForm < z . infer < typeof FormSchema > > ( {
89120 resolver : zodResolver ( FormSchema ) ,
121+ defaultValues : {
122+ algorithm : getInitialAlgorithm ( ) ,
123+ quantum : getInitialQuantum ( ) ,
124+ } ,
90125 } ) ;
91126
92127 // Watch quantum so URL stays in sync when it changes
@@ -111,41 +146,22 @@ export default function MainForm() {
111146
112147 const summaryRef = useRef < HTMLDivElement > ( null ) ;
113148
114- // Helper to normalize algorithm values from URL to internal values
115- const normalizeAlgorithm = ( algo ?: string | null ) => {
116- if ( ! algo ) return null ;
117- const a = algo . toLowerCase ( ) ;
118- if ( a === "fcfs" || a === "firstcomefirstserve" || a === "first_come_first_serve" )
119- return "FCFS" ; // internal value used in Select
120- if ( a === "rr" || a === "roundrobin" || a === "round_robin" ) return "RR" ;
121- if ( a === "sjf" || a === "shortestjobfirst" || a === "shortest_job_first" )
122- return "SJF" ;
123- if (
124- a === "srtf" ||
125- a === "shortestremainingtimefirst" ||
126- a === "shortest_remaining_time_first"
127- )
128- return "SRTF" ;
129- return null ;
130- } ;
149+ // Sync selectedAlgorithm with form value on mount and changes
150+ useEffect ( ( ) => {
151+ const formAlgo = form . getValues ( "algorithm" ) ;
152+ if ( formAlgo && formAlgo !== selectedAlgorithm ) {
153+ setSelectedAlgorithm ( formAlgo ) ;
154+ }
155+ } , [ form . watch ( "algorithm" ) ] ) ;
131156
132- // Load data from URL on mount (only once)
157+ // Load processes from URL on mount (only once)
133158 useEffect ( ( ) => {
134- if ( hasLoadedFromUrl ) return ; // Prevent re-running
159+ if ( hasLoadedFromUrl ) return ;
160+ if ( ! searchParams ) return ;
135161
162+ const processesData = searchParams . get ( "processes" ) ;
136163 const algoRaw = searchParams . get ( "algo" ) ;
137164 const algo = normalizeAlgorithm ( algoRaw ) ;
138- const quantum = searchParams . get ( "quantum" ) ;
139- const processesData = searchParams . get ( "processes" ) ;
140-
141- if ( algo ) {
142- form . setValue ( "algorithm" , algo ) ;
143- setSelectedAlgorithm ( algo ) ;
144- }
145-
146- if ( quantum && algo === "RR" ) {
147- form . setValue ( "quantum" , parseInt ( quantum ) ) ;
148- }
149165
150166 if ( processesData ) {
151167 try {
@@ -159,21 +175,21 @@ export default function MainForm() {
159175 }
160176 if ( Array . isArray ( parsed ) ) {
161177 setProcesses ( parsed as Process [ ] ) ;
178+
179+ // If we have both algo and processes, trigger auto-submit
180+ if ( algo && parsed . length > 0 ) {
181+ setShouldAutoSubmit ( true ) ;
182+ }
162183 } else {
163184 console . error ( "Invalid processes data from URL" ) ;
164185 }
165-
166- // If we have both algo and processes, trigger auto-submit
167- if ( algo && Array . isArray ( parsed ) && parsed . length > 0 ) {
168- setShouldAutoSubmit ( true ) ;
169- }
170186 } catch ( error ) {
171187 console . error ( "Failed to parse processes from URL:" , error ) ;
172188 }
173189 }
174190
175191 setHasLoadedFromUrl ( true ) ;
176- } , [ ] ) ; // Run only once on mount
192+ } , [ searchParams , hasLoadedFromUrl ] ) ;
177193
178194 // Auto-submit when loaded from URL
179195 useEffect ( ( ) => {
@@ -194,22 +210,45 @@ export default function MainForm() {
194210 // Skip URL update if we haven't finished initial load
195211 if ( ! hasLoadedFromUrl ) return ;
196212
197- const params = new URLSearchParams ( ) ;
213+ // Start from current params so we don't accidentally drop existing ones
214+ const params = new URLSearchParams ( window . location . search ) ;
198215
216+ // algo handling
199217 if ( selectedAlgorithm ) {
200218 params . set ( "algo" , selectedAlgorithm ) ;
219+ } else {
220+ // If no algorithm is selected in state, do not drop an existing algo from the URL
221+ // Only remove it when state explicitly says there is none AND there wasn't one before
222+ // i.e., when it's already missing.
223+ if ( ! params . get ( "algo" ) ) {
224+ params . delete ( "algo" ) ;
225+ }
201226 }
202227
203- if ( selectedAlgorithm === "RR" && quantumValue != null && ! Number . isNaN ( quantumValue ) ) {
228+ // quantum handling (only valid for RR)
229+ if (
230+ selectedAlgorithm === "RR" &&
231+ quantumValue != null &&
232+ ! Number . isNaN ( quantumValue )
233+ ) {
204234 params . set ( "quantum" , String ( quantumValue ) ) ;
235+ } else {
236+ params . delete ( "quantum" ) ;
205237 }
206238
239+ // processes handling
207240 if ( processes . length > 0 ) {
208241 params . set ( "processes" , encodeURIComponent ( JSON . stringify ( processes ) ) ) ;
242+ } else {
243+ params . delete ( "processes" ) ;
209244 }
210245
211- const newUrl = params . toString ( ) ? `?${ params . toString ( ) } ` : window . location . pathname ;
212- router . replace ( newUrl , { scroll : false } ) ;
246+ const newQuery = params . toString ( ) ;
247+ const currentQuery = window . location . search . replace ( / ^ \? / , "" ) ;
248+ if ( newQuery !== currentQuery ) {
249+ const newUrl = newQuery ? `?${ newQuery } ` : window . location . pathname ;
250+ router . replace ( newUrl , { scroll : false } ) ;
251+ }
213252 } , [ processes , selectedAlgorithm , quantumValue , router , hasLoadedFromUrl ] ) ;
214253
215254 const addProcess = ( newProcess : Omit < Process , "process_id" > ) => {
0 commit comments