Files
headquarter/apps/web/src/pages/ToolWorkshopPage.tsx
T
Developer 23fc0a6b82 feat: mobile edit-as-default with sticky save/delete actions
- Update MobileEditView to render Save and optional Delete in a
  sticky bottom action bar; header now shows Cancel + title only.
- Make ConfigProfilesMobileView open edit view on profile tap.
- Make ToolWorkshopMobileView open edit view on tool type tap.
- Wire delete into MobileEditView for existing profiles and tool
  types.
- Stay on edit view after saving an existing item; create flow
  returns to list as before.
- Update ToolWorkshopPage cancel to return to list.
- Add mobile-edit-actions and mobile-edit-delete CSS.

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

Refs: openspec/changes/mobile-edit-default-bottom-actions
2026-06-13 22:29:15 +00:00

119 lines
3.1 KiB
TypeScript

import { ErrorState, LoadingState } from "../components/data-states";
import { useMobileViewport } from "../hooks/use-mobile-viewport";
import { useToolWorkshop } from "../hooks/use-tool-workshop";
import { ToolTypeListSidebar } from "../components/features/tool-workshop/ToolTypeListSidebar";
import { ToolTypeEditorPanel } from "../components/features/tool-workshop/ToolTypeEditorPanel";
import { ToolWorkshopMobileView } from "../components/features/tool-workshop/ToolWorkshopMobileView";
import type { MobileView } from "../components/features/tool-workshop/ToolWorkshopMobileView";
import { useState } from "react";
export const ToolWorkshopPage = () => {
const isMobile = useMobileViewport();
const [mobileView, setMobileView] = useState<MobileView>("list");
const {
status,
toolTypes,
baseDefinitions,
selectedToolType,
selectedToolTypeId,
isCreating,
toolTypeForm,
manifestData,
manifestDefinitionId,
toolTypeError,
toolTypeDirty,
loadData,
handleSelectToolType,
handleCreateNew,
handleToolTypeSubmit,
handleDeleteToolType,
handleFormChange,
handleReset,
setManifestData,
setToolTypeDirty,
} = useToolWorkshop();
if (status === "loading") {
return (
<div className="container">
<LoadingState message="Loading Tool Workshop..." />
</div>
);
}
if (status === "error") {
return (
<div className="container">
<ErrorState message="Failed to load Tool Workshop." onRetry={loadData} />
</div>
);
}
if (isMobile) {
return (
<ToolWorkshopMobileView
toolTypes={toolTypes}
selectedToolType={selectedToolType}
mobileView={mobileView}
isCreating={isCreating}
toolTypeForm={toolTypeForm}
manifestData={manifestData}
manifestDefinitionId={manifestDefinitionId}
baseDefinitions={baseDefinitions}
toolTypeError={toolTypeError}
toolTypeDirty={toolTypeDirty}
onViewChange={setMobileView}
onSelect={handleSelectToolType}
onCreate={handleCreateNew}
onDelete={handleDeleteToolType}
onFormChange={handleFormChange}
onManifestChange={(m) => {
setManifestData(m);
setToolTypeDirty(true);
}}
onSubmit={handleToolTypeSubmit}
onCancel={() => {
if (toolTypeDirty) {
if (!window.confirm("You have unsaved changes. Discard them?")) {
return;
}
}
setMobileView("list");
}}
/>
);
}
return (
<div
className="container"
style={{ display: "flex", height: "calc(100vh - 4rem)", gap: 0, padding: 0 }}
>
<ToolTypeListSidebar
toolTypes={toolTypes}
selectedToolTypeId={selectedToolTypeId}
onSelect={handleSelectToolType}
onCreate={handleCreateNew}
onDelete={handleDeleteToolType}
/>
<ToolTypeEditorPanel
isCreating={isCreating}
selectedToolType={selectedToolType}
form={toolTypeForm}
manifestData={manifestData}
manifestDefinitionId={manifestDefinitionId}
baseDefinitions={baseDefinitions}
toolTypeError={toolTypeError}
toolTypeDirty={toolTypeDirty}
onFormChange={handleFormChange}
onManifestChange={(m) => {
setManifestData(m);
setToolTypeDirty(true);
}}
onSubmit={handleToolTypeSubmit}
onReset={handleReset}
/>
</div>
);
};