Skip to content

Commit f2a872e

Browse files
authored
fix: create screens now allow enter to trigger the create (#57)
1 parent 0352649 commit f2a872e

3 files changed

Lines changed: 147 additions & 149 deletions

File tree

src/components/DevboxCreatePage.tsx

Lines changed: 80 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -205,39 +205,87 @@ export const DevboxCreatePage = ({
205205
currentField === "resource_size",
206206
);
207207

208-
useInput((input, key) => {
209-
// Handle result screen
210-
if (result) {
211-
if (input === "q" || key.escape || key.return) {
212-
if (onCreate) {
213-
onCreate(result);
208+
// Main form input handler - active when not in metadata section
209+
useInput(
210+
(input, key) => {
211+
// Handle result screen
212+
if (result) {
213+
if (input === "q" || key.escape || key.return) {
214+
if (onCreate) {
215+
onCreate(result);
216+
}
217+
onBack();
214218
}
215-
onBack();
219+
return;
220+
}
221+
222+
// Handle error screen
223+
if (error) {
224+
if (input === "r" || key.return) {
225+
// Retry - clear error and return to form
226+
setError(null);
227+
} else if (input === "q" || key.escape) {
228+
// Quit - go back to list
229+
onBack();
230+
}
231+
return;
216232
}
217-
return;
218-
}
219233

220-
// Handle error screen
221-
if (error) {
222-
if (input === "r" || key.return) {
223-
// Retry - clear error and return to form
224-
setError(null);
225-
} else if (input === "q" || key.escape) {
226-
// Quit - go back to list
234+
// Handle creating state
235+
if (creating) {
236+
return;
237+
}
238+
239+
// Back to list
240+
if (input === "q" || key.escape) {
227241
onBack();
242+
return;
228243
}
229-
return;
230-
}
231244

232-
// Handle creating state
233-
if (creating) {
234-
return;
235-
}
245+
// Submit form with Ctrl+S
246+
if (input === "s" && key.ctrl) {
247+
handleCreate();
248+
return;
249+
}
236250

237-
// Handle metadata section FIRST (before general escape handler)
238-
if (inMetadataSection) {
251+
// Enter key on metadata field to enter metadata section
252+
if (currentField === "metadata" && key.return) {
253+
setInMetadataSection(true);
254+
setSelectedMetadataIndex(0);
255+
return;
256+
}
257+
258+
// Handle Enter on any field to submit
259+
if (key.return) {
260+
handleCreate();
261+
return;
262+
}
263+
264+
// Handle select field navigation using shared hooks
265+
if (handleArchitectureNav(input, key)) return;
266+
if (handleResourceSizeNav(input, key)) return;
267+
268+
// Navigation (up/down arrows and tab/shift+tab)
269+
if ((key.upArrow || (key.tab && key.shift)) && currentFieldIndex > 0) {
270+
setCurrentField(fields[currentFieldIndex - 1].key);
271+
return;
272+
}
273+
274+
if (
275+
(key.downArrow || (key.tab && !key.shift)) &&
276+
currentFieldIndex < fields.length - 1
277+
) {
278+
setCurrentField(fields[currentFieldIndex + 1].key);
279+
return;
280+
}
281+
},
282+
{ isActive: !inMetadataSection },
283+
);
284+
285+
// Metadata section input handler - active when in metadata section
286+
useInput(
287+
(input, key) => {
239288
const metadataKeys = Object.keys(formData.metadata);
240-
// Selection model: 0 = "Add new", 1..n = Existing items, n+1 = "Done"
241289
const maxIndex = metadataKeys.length + 1;
242290

243291
// Handle input mode (typing key or value)
@@ -258,35 +306,31 @@ export const DevboxCreatePage = ({
258306
setMetadataKey("");
259307
setMetadataValue("");
260308
setMetadataInputMode(null);
261-
setSelectedMetadataIndex(0); // Back to "add new" row
309+
setSelectedMetadataIndex(0);
262310
return;
263311
} else if (key.escape) {
264-
// Cancel input
265312
setMetadataKey("");
266313
setMetadataValue("");
267314
setMetadataInputMode(null);
268315
return;
269316
} else if (key.tab) {
270-
// Tab between key and value
271317
setMetadataInputMode(metadataInputMode === "key" ? "value" : "key");
272318
return;
273319
}
274-
return; // Don't process other keys while in input mode
320+
return;
275321
}
276322

277-
// Navigation mode
323+
// Navigation mode in metadata section
278324
if (key.upArrow && selectedMetadataIndex > 0) {
279325
setSelectedMetadataIndex(selectedMetadataIndex - 1);
280326
} else if (key.downArrow && selectedMetadataIndex < maxIndex) {
281327
setSelectedMetadataIndex(selectedMetadataIndex + 1);
282328
} else if (key.return) {
283329
if (selectedMetadataIndex === 0) {
284-
// Add new
285330
setMetadataKey("");
286331
setMetadataValue("");
287332
setMetadataInputMode("key");
288333
} else if (selectedMetadataIndex === maxIndex) {
289-
// Done - exit metadata section
290334
setInMetadataSection(false);
291335
setSelectedMetadataIndex(0);
292336
setMetadataKey("");
@@ -296,87 +340,37 @@ export const DevboxCreatePage = ({
296340
selectedMetadataIndex >= 1 &&
297341
selectedMetadataIndex <= metadataKeys.length
298342
) {
299-
// Edit existing (selectedMetadataIndex - 1 gives array index)
300343
const keyToEdit = metadataKeys[selectedMetadataIndex - 1];
301344
setMetadataKey(keyToEdit || "");
302345
setMetadataValue(formData.metadata[keyToEdit] || "");
303-
304-
// Remove old entry
305346
const newMetadata = { ...formData.metadata };
306347
delete newMetadata[keyToEdit];
307348
setFormData({ ...formData, metadata: newMetadata });
308-
309349
setMetadataInputMode("key");
310350
}
311351
} else if (
312352
(input === "d" || key.delete) &&
313353
selectedMetadataIndex >= 1 &&
314354
selectedMetadataIndex <= metadataKeys.length
315355
) {
316-
// Delete selected item (selectedMetadataIndex - 1 gives array index)
317356
const keyToDelete = metadataKeys[selectedMetadataIndex - 1];
318357
const newMetadata = { ...formData.metadata };
319358
delete newMetadata[keyToDelete];
320359
setFormData({ ...formData, metadata: newMetadata });
321-
// Stay at same position or move to add new if we deleted the last item
322360
const newLength = Object.keys(newMetadata).length;
323361
if (selectedMetadataIndex > newLength) {
324362
setSelectedMetadataIndex(Math.max(0, newLength));
325363
}
326364
} else if (key.escape || input === "q") {
327-
// Exit metadata section
328365
setInMetadataSection(false);
329366
setSelectedMetadataIndex(0);
330367
setMetadataKey("");
331368
setMetadataValue("");
332369
setMetadataInputMode(null);
333370
}
334-
return;
335-
}
336-
337-
// Back to list (only when not in metadata section)
338-
if (input === "q" || key.escape) {
339-
onBack();
340-
return;
341-
}
342-
343-
// Submit form
344-
if (input === "s" && key.ctrl) {
345-
handleCreate();
346-
return;
347-
}
348-
349-
// Handle Enter on create field
350-
if (currentField === "create" && key.return) {
351-
handleCreate();
352-
return;
353-
}
354-
355-
// Handle select field navigation using shared hooks
356-
if (handleArchitectureNav(input, key)) return;
357-
if (handleResourceSizeNav(input, key)) return;
358-
359-
// Navigation (up/down arrows and tab/shift+tab)
360-
if ((key.upArrow || (key.tab && key.shift)) && currentFieldIndex > 0) {
361-
setCurrentField(fields[currentFieldIndex - 1].key);
362-
return;
363-
}
364-
365-
if (
366-
(key.downArrow || (key.tab && !key.shift)) &&
367-
currentFieldIndex < fields.length - 1
368-
) {
369-
setCurrentField(fields[currentFieldIndex + 1].key);
370-
return;
371-
}
372-
373-
// Enter key on metadata field to enter metadata section
374-
if (currentField === "metadata" && key.return) {
375-
setInMetadataSection(true);
376-
setSelectedMetadataIndex(0); // Start at "add new" row
377-
return;
378-
}
379-
});
371+
},
372+
{ isActive: inMetadataSection },
373+
);
380374

381375
// Validate custom resource configuration
382376
const validateCustomResources = (): string | null => {
@@ -589,6 +583,7 @@ export const DevboxCreatePage = ({
589583
onChange={(value) =>
590584
setFormData({ ...formData, [field.key]: value })
591585
}
586+
onSubmit={handleCreate}
592587
isActive={isActive}
593588
placeholder={field.placeholder}
594589
/>

0 commit comments

Comments
 (0)