import { useState, useCallback, useEffect } from "react";
import { useParams, useNavigate } from "react-router";
import { Masthead } from "../components/Masthead";
import { DirectiveList } from "../components/directives/DirectiveList";
import { DirectiveDetail } from "../components/directives/DirectiveDetail";
import { useDirectives } from "../hooks/useDirectives";
import { useAuth } from "../contexts/AuthContext";
import type {
DirectiveWithChains,
CreateDirectiveRequest,
} from "../lib/api";
export default function DirectivesPage() {
const { isAuthenticated, isAuthConfigured, isLoading: authLoading } = useAuth();
const navigate = useNavigate();
// Redirect to login if not authenticated (when auth is configured)
useEffect(() => {
if (!authLoading && isAuthConfigured && !isAuthenticated) {
navigate("/login");
}
}, [authLoading, isAuthConfigured, isAuthenticated, navigate]);
if (authLoading) {
return (
<div className="relative z-10 min-h-screen flex flex-col bg-[#0a1628]">
<Masthead showNav />
<main className="flex-1 flex items-center justify-center">
<p className="text-[#7788aa] font-mono text-sm">Loading...</p>
</main>
</div>
);
}
return (
<div className="relative z-10 min-h-screen flex flex-col bg-[#0a1628]">
<Masthead showNav />
<DirectivesContent />
</div>
);
}
function DirectivesContent() {
const { id } = useParams<{ id?: string }>();
const navigate = useNavigate();
const {
directives,
loading,
error,
fetchDirective,
saveDirective,
removeDirective,
} = useDirectives();
const [selectedDirective, setSelectedDirective] =
useState<DirectiveWithChains | null>(null);
const [detailLoading, setDetailLoading] = useState(false);
const [showCreateForm, setShowCreateForm] = useState(false);
const [createTitle, setCreateTitle] = useState("");
const [createGoal, setCreateGoal] = useState("");
const [createRepoUrl, setCreateRepoUrl] = useState("");
// Load directive when ID changes
useEffect(() => {
if (id) {
setDetailLoading(true);
fetchDirective(id).then((d) => {
setSelectedDirective(d);
setDetailLoading(false);
});
} else {
setSelectedDirective(null);
}
}, [id, fetchDirective]);
const handleSelect = useCallback(
(directiveId: string) => {
navigate(`/directives/${directiveId}`);
},
[navigate]
);
const handleBack = useCallback(() => {
navigate("/directives");
}, [navigate]);
const handleCreate = useCallback(async () => {
if (!createTitle.trim() || !createGoal.trim()) return;
const data: CreateDirectiveRequest = {
title: createTitle.trim(),
goal: createGoal.trim(),
};
if (createRepoUrl.trim()) {
data.repositoryUrl = createRepoUrl.trim();
}
const result = await saveDirective(data);
if (result) {
setShowCreateForm(false);
setCreateTitle("");
setCreateGoal("");
setCreateRepoUrl("");
}
}, [createTitle, createGoal, createRepoUrl, saveDirective]);
const handleDelete = useCallback(
async (directiveId: string) => {
const ok = await removeDirective(directiveId);
if (ok && id === directiveId) {
navigate("/directives");
}
},
[removeDirective, id, navigate]
);
// Detail view
if (id) {
if (detailLoading) {
return (
<main className="flex-1 flex items-center justify-center">
<p className="text-[#7788aa] font-mono text-sm">Loading directive...</p>
</main>
);
}
if (!selectedDirective) {
return (
<main className="flex-1 flex items-center justify-center">
<p className="text-[#7788aa] font-mono text-sm">Directive not found</p>
</main>
);
}
return (
<main className="flex-1 p-4 max-w-4xl mx-auto w-full">
<DirectiveDetail
directive={selectedDirective}
onBack={handleBack}
onDelete={handleDelete}
/>
</main>
);
}
// List view
return (
<main className="flex-1 p-4 max-w-4xl mx-auto w-full">
{error && (
<div className="mb-4 p-2 border border-red-400/30 bg-red-400/5 font-mono text-xs text-red-400">
{error}
</div>
)}
{showCreateForm && (
<div className="mb-4 p-4 border border-dashed border-[rgba(117,170,252,0.35)] bg-[rgba(117,170,252,0.03)]">
<h3 className="font-mono text-xs text-[#75aafc] uppercase tracking-wider mb-3">
New Directive
</h3>
<div className="space-y-2">
<input
type="text"
placeholder="Title"
value={createTitle}
onChange={(e) => setCreateTitle(e.target.value)}
className="w-full px-2 py-1.5 font-mono text-xs text-[#dbe7ff] bg-[#0a1628] border border-[rgba(117,170,252,0.3)] focus:border-[#75aafc] outline-none"
/>
<textarea
placeholder="Goal - what should be accomplished?"
value={createGoal}
onChange={(e) => setCreateGoal(e.target.value)}
rows={3}
className="w-full px-2 py-1.5 font-mono text-xs text-[#dbe7ff] bg-[#0a1628] border border-[rgba(117,170,252,0.3)] focus:border-[#75aafc] outline-none resize-none"
/>
<input
type="text"
placeholder="Repository URL (optional)"
value={createRepoUrl}
onChange={(e) => setCreateRepoUrl(e.target.value)}
className="w-full px-2 py-1.5 font-mono text-xs text-[#dbe7ff] bg-[#0a1628] border border-[rgba(117,170,252,0.3)] focus:border-[#75aafc] outline-none"
/>
<div className="flex gap-2">
<button
onClick={handleCreate}
disabled={!createTitle.trim() || !createGoal.trim()}
className="px-3 py-1.5 font-mono text-xs text-[#dbe7ff] bg-[#0f3c78] border border-[#3f6fb3] hover:bg-[#153667] transition-colors uppercase disabled:opacity-50 disabled:cursor-not-allowed"
>
Create
</button>
<button
onClick={() => setShowCreateForm(false)}
className="px-3 py-1.5 font-mono text-xs text-[#7788aa] hover:text-[#dbe7ff] transition-colors uppercase"
>
Cancel
</button>
</div>
</div>
</div>
)}
<DirectiveList
directives={directives}
loading={loading}
onSelect={handleSelect}
onCreate={() => setShowCreateForm(true)}
onDelete={(d) => handleDelete(d.id)}
selectedId={id}
/>
</main>
);
}