feat: rework mobile UI for Tool Workshop and Profile pages

- Rework ToolWorkshopMobileView to support full desktop functionality:
  definition type selection (Compose/Dockerfile/Manifest), manifest editor,
  conditional port, startup command, readiness probe, required variables,
  and validation feedback.
- Add ProfileMobileView and wire ProfilePage to render it on mobile.
- Update useToolWorkshop hook to return boolean success from submit.
- Add responsive CSS for mobile forms, edit views, and manifest editor.
- Update project maps.

Quality gates: npm run typecheck, npm run lint, npm test -- --run (87 passed)

Refs: openspec/changes/mobile-tool-profile-ui
This commit is contained in:
Developer
2026-06-13 21:41:42 +00:00
parent 8f7f682a92
commit 350b393457
28 changed files with 797 additions and 187 deletions
+7 -5
View File
@@ -151,13 +151,13 @@ export const useToolWorkshop = () => {
resetToolTypeForm();
};
const handleToolTypeSubmit = async (e?: React.FormEvent) => {
const handleToolTypeSubmit = async (e?: React.FormEvent): Promise<boolean> => {
e?.preventDefault();
setToolTypeError(null);
if (!toolTypeForm.name.trim() || !toolTypeForm.display_name.trim()) {
setToolTypeError("Name and display name are required");
return;
return false;
}
if (
@@ -166,7 +166,7 @@ export const useToolWorkshop = () => {
isNaN(Number(toolTypeForm.default_port)))
) {
setToolTypeError("Default port is required and must be a number");
return;
return false;
}
if (toolTypeForm.definition_type !== "manifest") {
@@ -179,13 +179,13 @@ export const useToolWorkshop = () => {
setToolTypeError(
`${toolTypeForm.definition_type === "compose" ? "Compose" : "Dockerfile"} template is required`,
);
return;
return false;
}
} else if (!manifestData) {
setToolTypeError(
"Manifest data is required for manifest definition type",
);
return;
return false;
}
const variables = toolTypeForm.required_variables
@@ -307,8 +307,10 @@ export const useToolWorkshop = () => {
setToolTypeDirty(false);
}
await loadData();
return true;
} catch (err) {
setToolTypeError(extractErrorMessage(err));
return false;
}
};