import { useState, useEffect } from "react";
import { useNavigate } from "react-router";
import { Masthead } from "../components/Masthead";
import { TemplateEditor } from "../components/templates/TemplateEditor";
import { useAuth } from "../contexts/AuthContext";
import type { ContractTemplate } from "../types/templates";
import { DEFAULT_TEMPLATES } from "../types/templates";
const STORAGE_KEY = "makima_contract_templates";
export default function TemplatesPage() {
const navigate = useNavigate();
const { isAuthenticated, isAuthConfigured, isLoading: authLoading } = useAuth();
const [templates, setTemplates] = useState<ContractTemplate[]>(() => {
const saved = localStorage.getItem(STORAGE_KEY);
if (saved) {
try {
return JSON.parse(saved);
} catch {
return DEFAULT_TEMPLATES;
}
}
return DEFAULT_TEMPLATES;
});
const [editingTemplate, setEditingTemplate] = useState<ContractTemplate | null>(
null
);
const [showNewTemplateForm, setShowNewTemplateForm] = useState(false);
const [newTemplateName, setNewTemplateName] = useState("");
const [newTemplateDescription, setNewTemplateDescription] = useState("");
// Redirect to login if not authenticated
useEffect(() => {
if (!authLoading && isAuthConfigured && !isAuthenticated) {
navigate("/login");
}
}, [authLoading, isAuthConfigured, isAuthenticated, navigate]);
const saveTemplates = (newTemplates: ContractTemplate[]) => {
setTemplates(newTemplates);
localStorage.setItem(STORAGE_KEY, JSON.stringify(newTemplates));
};
const handleSaveTemplate = (updatedTemplate: ContractTemplate) => {
const newTemplates = templates.map((t) =>
t.id === updatedTemplate.id ? updatedTemplate : t
);
saveTemplates(newTemplates);
setEditingTemplate(null);
};
const handleCreateTemplate = () => {
if (!newTemplateName.trim()) return;
const newTemplate: ContractTemplate = {
id: `custom-${Date.now()}`,
name: newTemplateName.trim(),
description: newTemplateDescription.trim() || "Custom contract template",
isBuiltIn: false,
phases: [
{
id: `phase-${Date.now()}`,
name: "Execute",
deliverables: [],
},
],
};
saveTemplates([...templates, newTemplate]);
setNewTemplateName("");
setNewTemplateDescription("");
setShowNewTemplateForm(false);
};
const handleDeleteTemplate = (templateId: string) => {
const template = templates.find((t) => t.id === templateId);
if (template?.isBuiltIn) return;
if (window.confirm(`Are you sure you want to delete "${template?.name}"?`)) {
saveTemplates(templates.filter((t) => t.id !== templateId));
}
};
const handleResetToDefaults = () => {
if (
window.confirm(
"Reset all templates to defaults? This will remove any custom templates."
)
) {
saveTemplates(DEFAULT_TEMPLATES);
}
};
// Show loading state
if (authLoading) {
return (
<div className="relative z-10 min-h-screen flex items-center justify-center bg-[#0a1628]">
<div className="text-[#75aafc] font-mono text-sm animate-pulse">
Loading...
</div>
</div>
);
}
// Editor view
if (editingTemplate) {
return (
<div className="relative z-10 min-h-screen bg-[#0a1628]">
<Masthead />
<main className="max-w-4xl mx-auto px-4 py-6">
<TemplateEditor
template={editingTemplate}
onSave={handleSaveTemplate}
onCancel={() => setEditingTemplate(null)}
/>
</main>
</div>
);
}
return (
<div className="relative z-10 min-h-screen bg-[#0a1628]">
<Masthead />
<main className="max-w-6xl mx-auto px-4 py-6">
{/* Header */}
<div className="flex justify-between items-start mb-6 pb-4 border-b border-[rgba(117,170,252,0.15)]">
<div>
<h1 className="text-lg font-mono uppercase tracking-wide text-[#9bc3ff] mb-1">
Contract Templates
</h1>
<p className="text-xs font-mono text-[#75aafc] opacity-70">
Manage contract types and their phase deliverables
</p>
</div>
<div className="flex gap-3">
<button
type="button"
onClick={handleResetToDefaults}
className="px-3 py-2 border border-[rgba(117,170,252,0.25)] text-[#9bc3ff] font-mono text-xs uppercase tracking-wide hover:border-[#3f6fb3] transition-colors"
>
Reset to Defaults
</button>
<button
type="button"
onClick={() => setShowNewTemplateForm(true)}
className="px-3 py-2 border border-[#3f6fb3] bg-[rgba(117,170,252,0.15)] text-[#9bc3ff] font-mono text-xs uppercase tracking-wide hover:bg-[rgba(117,170,252,0.25)] transition-colors"
>
+ New Template
</button>
</div>
</div>
{/* New Template Form */}
{showNewTemplateForm && (
<div className="bg-[#0d1b2d] border border-[rgba(117,170,252,0.35)] p-4 mb-6">
<div className="flex gap-3 items-center">
<input
type="text"
className="flex-1 px-3 py-2 bg-transparent border border-[rgba(117,170,252,0.25)] text-white font-mono text-sm placeholder-[#556677] focus:outline-none focus:border-[#3f6fb3]"
placeholder="Template name..."
value={newTemplateName}
onChange={(e) => setNewTemplateName(e.target.value)}
/>
<input
type="text"
className="flex-1 px-3 py-2 bg-transparent border border-[rgba(117,170,252,0.25)] text-white font-mono text-sm placeholder-[#556677] focus:outline-none focus:border-[#3f6fb3]"
placeholder="Description (optional)..."
value={newTemplateDescription}
onChange={(e) => setNewTemplateDescription(e.target.value)}
/>
<button
type="button"
onClick={handleCreateTemplate}
className="px-4 py-2 border border-[#3f6fb3] bg-[rgba(117,170,252,0.15)] text-[#9bc3ff] font-mono text-xs uppercase tracking-wide hover:bg-[rgba(117,170,252,0.25)] transition-colors"
>
Create
</button>
<button
type="button"
onClick={() => setShowNewTemplateForm(false)}
className="px-4 py-2 border border-[rgba(117,170,252,0.25)] text-[#9bc3ff] font-mono text-xs uppercase tracking-wide hover:border-[#3f6fb3] transition-colors"
>
Cancel
</button>
</div>
</div>
)}
{/* Templates Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{templates.map((template) => (
<div
key={template.id}
className="bg-[#0d1b2d] border border-[rgba(117,170,252,0.25)] hover:border-[rgba(117,170,252,0.45)] transition-colors"
>
{/* Card Header */}
<div className="px-4 py-3 border-b border-[rgba(117,170,252,0.15)] flex items-center justify-between">
<h3 className="font-mono text-sm text-white">{template.name}</h3>
{template.isBuiltIn ? (
<span className="px-2 py-0.5 bg-[rgba(117,170,252,0.15)] text-[#75aafc] font-mono text-[10px] uppercase tracking-wide">
Built-in
</span>
) : (
<span className="px-2 py-0.5 bg-[rgba(100,200,100,0.15)] text-[#7bc97b] font-mono text-[10px] uppercase tracking-wide">
Custom
</span>
)}
</div>
{/* Card Body */}
<div className="px-4 py-3">
<p className="text-xs font-mono text-[#75aafc] opacity-70 mb-4 min-h-[2.5rem]">
{template.description}
</p>
{/* Phases */}
<div className="space-y-2 mb-4">
{template.phases.map((phase, index) => (
<div key={phase.id} className="flex items-start gap-2">
<div className="flex flex-col items-center">
<span className="w-2 h-2 rounded-full bg-[#3f6fb3]" />
{index < template.phases.length - 1 && (
<span className="w-px h-4 bg-[rgba(117,170,252,0.25)]" />
)}
</div>
<div className="flex-1 min-w-0">
<span className="text-xs font-mono text-[#9bc3ff]">
{phase.name}
</span>
<span className="text-[10px] font-mono text-[#556677] ml-2">
{phase.deliverables.length === 0
? "(no deliverables)"
: phase.deliverables.map((d) => d.name).join(", ")}
</span>
</div>
</div>
))}
</div>
</div>
{/* Card Footer */}
<div className="px-4 py-3 border-t border-[rgba(117,170,252,0.15)] flex gap-2">
<button
type="button"
onClick={() => setEditingTemplate(template)}
className="flex-1 px-3 py-1.5 border border-[rgba(117,170,252,0.25)] text-[#9bc3ff] font-mono text-xs uppercase tracking-wide hover:border-[#3f6fb3] hover:bg-[rgba(117,170,252,0.05)] transition-colors"
>
Edit
</button>
{!template.isBuiltIn && (
<button
type="button"
onClick={() => handleDeleteTemplate(template.id)}
className="px-3 py-1.5 border border-[rgba(255,100,100,0.25)] text-[#ff6464] font-mono text-xs uppercase tracking-wide hover:border-[rgba(255,100,100,0.5)] hover:bg-[rgba(255,100,100,0.05)] transition-colors"
>
Delete
</button>
)}
</div>
</div>
))}
</div>
</main>
</div>
);
}