diff options
| author | soryu <soryu@soryu.co> | 2026-02-16 17:59:38 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-02-16 17:59:38 +0000 |
| commit | b3de779d87450033f1e0361144c621a1d5f1dbf8 (patch) | |
| tree | 7cb84c2f953bf86f1dd3ec8ff305d70810ac55de /makima/frontend/src/routes | |
| parent | 7d2079d7c13804766405af8044574bfc93a86897 (diff) | |
| download | soryu-b3de779d87450033f1e0361144c621a1d5f1dbf8.tar.gz soryu-b3de779d87450033f1e0361144c621a1d5f1dbf8.zip | |
Fix contracts page overflow, remove contract link from orders, add directive name (#65)
* feat: soryu-co/soryu - makima: Add frontend pick-up-orders button and API integration
* WIP: heartbeat checkpoint
* feat: soryu-co/soryu - makima: Remove contract link from orders and add directive name to order metadata (frontend)
* fix: contracts page overflow - use contained scrolling layout
Changed the contracts page to use contained scrolling matching the
orders/directives pages, preventing the page from growing beyond
viewport height.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve completion_task_id FK violation and duplicate button
The completion_task_id column has an FK to tasks(id), but
claim_directive_for_completion was being called with a placeholder UUID
that did not exist in the tasks table, causing FK constraint violations.
Fix: Create the task FIRST via create_task_for_owner, then use the real
task.id when calling claim_directive_for_completion. Applied in all three
locations: phase_completion Part 1 (idle directives), Part 3 (verification
tasks), and trigger_completion_task (manual PR creation).
Also removes a duplicate "Pick Up Orders" button in DirectiveDetail.tsx.
* fix: restore Order type changes lost during rebase conflict resolution
Re-apply changes from the orders-refactor commit that were dropped when
resolving rebase conflicts with --ours:
- Replace contractId with directiveName in Order interface
- Make directiveId required in CreateOrderRequest
- Remove contractId from UpdateOrderRequest
- Change listOrders parameter from contractId to search
- Remove linkOrderToContract function
- Simplify convertOrderToStep to single argument
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'makima/frontend/src/routes')
| -rw-r--r-- | makima/frontend/src/routes/contracts.tsx | 23 | ||||
| -rw-r--r-- | makima/frontend/src/routes/orders.tsx | 34 |
2 files changed, 37 insertions, 20 deletions
diff --git a/makima/frontend/src/routes/contracts.tsx b/makima/frontend/src/routes/contracts.tsx index acb6789..6d838ab 100644 --- a/makima/frontend/src/routes/contracts.tsx +++ b/makima/frontend/src/routes/contracts.tsx @@ -524,15 +524,9 @@ function ContractsPageContent() { return ( <div className="relative z-10 min-h-screen flex flex-col bg-[#0a1628]"> <Masthead showNav /> - <main className="flex-1 flex flex-col p-4 pt-2 gap-4 overflow-hidden"> - {error && ( - <div className="p-3 bg-red-400/10 border border-red-400/30 text-red-400 font-mono text-sm"> - {error} - </div> - )} - - <div className="flex-1 grid grid-cols-[350px_1fr] gap-4 min-h-0"> - {/* Contract list */} + <main className="flex-1 flex overflow-hidden" style={{ height: "calc(100vh - 80px)" }}> + {/* Left: Contract list */} + <div className="w-[350px] shrink-0 border-r border-dashed border-[rgba(117,170,252,0.2)] overflow-hidden flex flex-col"> <ContractList contracts={contracts} loading={loading} @@ -545,8 +539,18 @@ function ContractsPageContent() { onDelete={handleContextDelete} onGoToSupervisor={handleContextGoToSupervisor} /> + </div> + + {/* Right: Detail or Create */} + <div className="flex-1 overflow-hidden flex flex-col"> + {error && ( + <div className="p-3 bg-red-400/10 border border-red-400/30 text-red-400 font-mono text-sm"> + {error} + </div> + )} {/* Contract detail, creation form, or empty state */} + <div className="flex-1 min-h-0 overflow-hidden"> {isCreating ? ( <div className="p-4 max-w-lg overflow-y-auto h-full bg-[#0a1628]"> <h3 className="font-mono text-[10px] text-[#9bc3ff] uppercase tracking-wide mb-4"> @@ -873,6 +877,7 @@ function ContractsPageContent() { </div> </div> )} + </div> </div> </main> </div> diff --git a/makima/frontend/src/routes/orders.tsx b/makima/frontend/src/routes/orders.tsx index 735c557..deca77f 100644 --- a/makima/frontend/src/routes/orders.tsx +++ b/makima/frontend/src/routes/orders.tsx @@ -16,7 +16,7 @@ export default function OrdersPage() { const [statusFilter, setStatusFilter] = useState<OrderStatus | undefined>(undefined); const [typeFilter, setTypeFilter] = useState<OrderType | undefined>(undefined); const { orders, loading: listLoading, create, refresh: refreshList } = useOrders(statusFilter, typeFilter); - const { order, refresh: refreshDetail, update, remove: removeOrder, linkDirective, linkContract, convertToStep } = useOrder(selectedId); + const { order, refresh: refreshDetail, update, remove: removeOrder, linkDirective, convertToStep } = useOrder(selectedId); const { directives } = useDirectives(); const [showCreate, setShowCreate] = useState(false); @@ -24,6 +24,7 @@ export default function OrdersPage() { const [newDesc, setNewDesc] = useState(""); const [newPriority, setNewPriority] = useState<OrderPriority>("medium"); const [newType, setNewType] = useState<OrderType>("feature"); + const [newDirectiveId, setNewDirectiveId] = useState<string>(""); useEffect(() => { if (!authLoading && isAuthConfigured && !isAuthenticated) { @@ -43,19 +44,21 @@ export default function OrdersPage() { } const handleCreate = async () => { - if (!newTitle.trim()) return; + if (!newTitle.trim() || !newDirectiveId) return; try { const o = await create({ title: newTitle.trim(), description: newDesc.trim() || undefined, priority: newPriority, orderType: newType, + directiveId: newDirectiveId, }); setShowCreate(false); setNewTitle(""); setNewDesc(""); setNewPriority("medium"); setNewType("feature"); + setNewDirectiveId(""); navigate(`/orders/${o.id}`); } catch (e) { console.error("Failed to create order:", e); @@ -84,13 +87,8 @@ export default function OrdersPage() { await refreshList(); }; - const handleLinkContract = async (contractId: string) => { - await linkContract(contractId); - await refreshList(); - }; - - const handleConvertToStep = async (directiveId: string) => { - await convertToStep(directiveId); + const handleConvertToStep = async () => { + await convertToStep(); await refreshList(); }; @@ -162,6 +160,21 @@ export default function OrdersPage() { className="w-full bg-[#0a1628] border border-[rgba(117,170,252,0.2)] rounded px-2 py-1.5 text-[12px] font-mono text-white resize-y" /> </div> + <div> + <label className="text-[10px] font-mono text-[#9bc3ff] uppercase tracking-wide block mb-1"> + Directive * + </label> + <select + value={newDirectiveId} + onChange={(e) => setNewDirectiveId(e.target.value)} + className="w-full bg-[#0a1628] border border-[rgba(117,170,252,0.2)] rounded px-2 py-1.5 text-[12px] font-mono text-white" + > + <option value="">Select directive...</option> + {directives.map((d) => ( + <option key={d.id} value={d.id}>{d.title}</option> + ))} + </select> + </div> <div className="flex gap-4"> <div className="flex-1"> <label className="text-[10px] font-mono text-[#9bc3ff] uppercase tracking-wide block mb-1"> @@ -196,7 +209,7 @@ export default function OrdersPage() { <button type="button" onClick={handleCreate} - disabled={!newTitle.trim()} + disabled={!newTitle.trim() || !newDirectiveId} className="text-[11px] font-mono text-emerald-400 hover:text-emerald-300 border border-emerald-800 rounded px-3 py-1 disabled:opacity-50" > Create @@ -218,7 +231,6 @@ export default function OrdersPage() { onUpdate={handleUpdate} onDelete={handleDelete} onLinkDirective={handleLinkDirective} - onLinkContract={handleLinkContract} onConvertToStep={handleConvertToStep} onRefresh={refreshDetail} /> |
