summaryrefslogtreecommitdiff
path: root/makima/frontend/src/routes
diff options
context:
space:
mode:
Diffstat (limited to 'makima/frontend/src/routes')
-rw-r--r--makima/frontend/src/routes/contracts.tsx72
1 files changed, 62 insertions, 10 deletions
diff --git a/makima/frontend/src/routes/contracts.tsx b/makima/frontend/src/routes/contracts.tsx
index 8c90804..f09ec5b 100644
--- a/makima/frontend/src/routes/contracts.tsx
+++ b/makima/frontend/src/routes/contracts.tsx
@@ -11,10 +11,12 @@ import type {
ContractWithRelations,
ContractPhase,
ContractStatus,
+ ContractType,
CreateContractRequest,
RepositorySourceType,
DaemonDirectory,
} from "../lib/api";
+import { getValidPhases, getDefaultPhase } from "../lib/api";
export default function ContractsPage() {
const { isAuthenticated, isAuthConfigured, isLoading: authLoading } = useAuth();
@@ -71,7 +73,8 @@ function ContractsPageContent() {
const [isCreating, setIsCreating] = useState(false);
const [newContractName, setNewContractName] = useState("");
const [newContractDescription, setNewContractDescription] = useState("");
- const [initialPhase, setInitialPhase] = useState<ContractPhase>("research");
+ const [contractType, setContractType] = useState<ContractType>("simple");
+ const [initialPhase, setInitialPhase] = useState<ContractPhase>("plan");
const [repoType, setRepoType] = useState<RepositorySourceType>("remote");
const [repoName, setRepoName] = useState("");
const [repoUrl, setRepoUrl] = useState("");
@@ -136,7 +139,8 @@ function ContractsPageContent() {
const data: CreateContractRequest = {
name: newContractName.trim(),
description: newContractDescription.trim() || undefined,
- initialPhase: initialPhase !== "research" ? initialPhase : undefined,
+ contractType: contractType,
+ initialPhase: initialPhase !== getDefaultPhase(contractType) ? initialPhase : undefined,
};
try {
@@ -171,7 +175,8 @@ function ContractsPageContent() {
setIsCreating(false);
setNewContractName("");
setNewContractDescription("");
- setInitialPhase("research");
+ setContractType("simple");
+ setInitialPhase("plan");
setRepoType("remote");
setRepoName("");
setRepoUrl("");
@@ -184,6 +189,8 @@ function ContractsPageContent() {
}, [
newContractName,
newContractDescription,
+ contractType,
+ initialPhase,
repoType,
repoName,
repoUrl,
@@ -200,7 +207,8 @@ function ContractsPageContent() {
setIsCreating(false);
setNewContractName("");
setNewContractDescription("");
- setInitialPhase("research");
+ setContractType("simple");
+ setInitialPhase("plan");
setRepoType("remote");
setRepoName("");
setRepoUrl("");
@@ -424,6 +432,48 @@ function ContractsPageContent() {
/>
</div>
+ {/* Contract Type */}
+ <div>
+ <label className="block font-mono text-xs text-[#8b949e] uppercase mb-1">
+ Contract Type
+ </label>
+ <div className="flex gap-2">
+ <button
+ type="button"
+ onClick={() => {
+ setContractType("simple");
+ setInitialPhase("plan");
+ }}
+ className={`flex-1 px-3 py-2 font-mono text-xs uppercase transition-colors ${
+ contractType === "simple"
+ ? "bg-[#0f3c78] text-[#dbe7ff] border border-[#75aafc]"
+ : "bg-[#0d1b2d] text-[#8b949e] border border-[#3f6fb3] hover:border-[#75aafc]"
+ }`}
+ >
+ Simple
+ </button>
+ <button
+ type="button"
+ onClick={() => {
+ setContractType("specification");
+ setInitialPhase("research");
+ }}
+ className={`flex-1 px-3 py-2 font-mono text-xs uppercase transition-colors ${
+ contractType === "specification"
+ ? "bg-[#0f3c78] text-[#dbe7ff] border border-[#75aafc]"
+ : "bg-[#0d1b2d] text-[#8b949e] border border-[#3f6fb3] hover:border-[#75aafc]"
+ }`}
+ >
+ Specification
+ </button>
+ </div>
+ <p className="mt-1 font-mono text-xs text-[#8b949e]">
+ {contractType === "simple"
+ ? "Plan → Execute: Simple workflow with a plan document"
+ : "Research → Specify → Plan → Execute → Review: Full specification-driven development with TDD"}
+ </p>
+ </div>
+
{/* Starting Phase */}
<div>
<label className="block font-mono text-xs text-[#8b949e] uppercase mb-1">
@@ -434,14 +484,16 @@ function ContractsPageContent() {
onChange={(e) => setInitialPhase(e.target.value as ContractPhase)}
className="w-full px-3 py-2 bg-[#0d1b2d] border border-[#3f6fb3] text-[#dbe7ff] font-mono text-sm focus:outline-none focus:border-[#75aafc]"
>
- <option value="research">Research</option>
- <option value="specify">Specify</option>
- <option value="plan">Plan</option>
- <option value="execute">Execute</option>
- <option value="review">Review</option>
+ {getValidPhases(contractType).map((phase) => (
+ <option key={phase} value={phase}>
+ {phase.charAt(0).toUpperCase() + phase.slice(1)}
+ </option>
+ ))}
</select>
<p className="mt-1 font-mono text-xs text-[#8b949e]">
- Skip earlier phases if you already have requirements defined
+ {contractType === "simple"
+ ? "Start in Plan to define what to build, or Execute if already planned"
+ : "Skip earlier phases if you already have requirements defined"}
</p>
</div>