summaryrefslogtreecommitdiff
path: root/makima/frontend/src/components/templates/TemplateEditor.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'makima/frontend/src/components/templates/TemplateEditor.tsx')
-rw-r--r--makima/frontend/src/components/templates/TemplateEditor.tsx257
1 files changed, 0 insertions, 257 deletions
diff --git a/makima/frontend/src/components/templates/TemplateEditor.tsx b/makima/frontend/src/components/templates/TemplateEditor.tsx
deleted file mode 100644
index c8e1f98..0000000
--- a/makima/frontend/src/components/templates/TemplateEditor.tsx
+++ /dev/null
@@ -1,257 +0,0 @@
-import { useState } from "react";
-import type { ContractTemplate, Phase, Deliverable } from "../../types/templates";
-
-interface Props {
- template: ContractTemplate;
- onSave: (template: ContractTemplate) => void;
- onCancel: () => void;
- readOnly?: boolean;
-}
-
-export function TemplateEditor({ template, onSave, onCancel, readOnly = false }: Props) {
- const [editedTemplate, setEditedTemplate] = useState<ContractTemplate>({
- ...template,
- phases: template.phases.map((p) => ({
- ...p,
- deliverables: [...p.deliverables],
- })),
- });
- const [newDeliverableName, setNewDeliverableName] = useState<{
- [phaseId: string]: string;
- }>({});
-
- const handlePhaseNameChange = (phaseId: string, newName: string) => {
- setEditedTemplate((prev) => ({
- ...prev,
- phases: prev.phases.map((p) =>
- p.id === phaseId ? { ...p, name: newName } : p
- ),
- }));
- };
-
- const handleDeliverableNameChange = (
- phaseId: string,
- deliverableId: string,
- newName: string
- ) => {
- setEditedTemplate((prev) => ({
- ...prev,
- phases: prev.phases.map((p) =>
- p.id === phaseId
- ? {
- ...p,
- deliverables: p.deliverables.map((d) =>
- d.id === deliverableId ? { ...d, name: newName } : d
- ),
- }
- : p
- ),
- }));
- };
-
- const handleAddDeliverable = (phaseId: string) => {
- const name = newDeliverableName[phaseId]?.trim();
- if (!name) return;
-
- const newDeliverable: Deliverable = {
- id: `deliverable-${Date.now()}`,
- name,
- };
-
- setEditedTemplate((prev) => ({
- ...prev,
- phases: prev.phases.map((p) =>
- p.id === phaseId
- ? { ...p, deliverables: [...p.deliverables, newDeliverable] }
- : p
- ),
- }));
- setNewDeliverableName((prev) => ({ ...prev, [phaseId]: "" }));
- };
-
- const handleRemoveDeliverable = (phaseId: string, deliverableId: string) => {
- setEditedTemplate((prev) => ({
- ...prev,
- phases: prev.phases.map((p) =>
- p.id === phaseId
- ? {
- ...p,
- deliverables: p.deliverables.filter((d) => d.id !== deliverableId),
- }
- : p
- ),
- }));
- };
-
- const handleAddPhase = () => {
- const newPhase: Phase = {
- id: `phase-${Date.now()}`,
- name: "New Phase",
- deliverables: [],
- };
- setEditedTemplate((prev) => ({
- ...prev,
- phases: [...prev.phases, newPhase],
- }));
- };
-
- const handleRemovePhase = (phaseId: string) => {
- setEditedTemplate((prev) => ({
- ...prev,
- phases: prev.phases.filter((p) => p.id !== phaseId),
- }));
- };
-
- return (
- <div className="bg-[#0d1b2d] border border-[rgba(117,170,252,0.35)] p-6">
- {/* Header */}
- <div className="mb-6 pb-4 border-b border-[rgba(117,170,252,0.15)]">
- <h2 className="text-sm font-mono uppercase tracking-wide text-[#9bc3ff] mb-1">
- {readOnly ? "View" : "Edit"} Template: {template.name}
- </h2>
- <p className="text-xs font-mono text-[#75aafc] opacity-70">
- {template.description}
- </p>
- {readOnly && (
- <p className="text-xs font-mono text-amber-400 mt-2">
- Built-in templates are read-only
- </p>
- )}
- </div>
-
- {/* Phases */}
- <div className="space-y-4 mb-6">
- {editedTemplate.phases.map((phase, phaseIndex) => (
- <div
- key={phase.id}
- className="bg-[rgba(0,0,0,0.3)] border border-[rgba(117,170,252,0.2)] p-4"
- >
- {/* Phase Header */}
- <div className="flex items-center gap-3 mb-3">
- <span className="w-6 h-6 flex items-center justify-center bg-[rgba(117,170,252,0.2)] text-[#9bc3ff] text-xs font-mono">
- {phaseIndex + 1}
- </span>
- <input
- type="text"
- className="flex-1 px-3 py-1.5 bg-transparent border border-[rgba(117,170,252,0.25)] text-white font-mono text-sm placeholder-[#556677] focus:outline-none focus:border-[#3f6fb3] disabled:opacity-60"
- value={phase.name}
- onChange={(e) => handlePhaseNameChange(phase.id, e.target.value)}
- placeholder="Phase name"
- disabled={readOnly}
- />
- {!template.isBuiltIn && (
- <button
- type="button"
- onClick={() => handleRemovePhase(phase.id)}
- className="w-7 h-7 flex items-center justify-center border border-[rgba(255,100,100,0.3)] text-[#ff6464] hover:bg-[rgba(255,100,100,0.1)] transition-colors text-sm"
- title="Remove phase"
- >
- x
- </button>
- )}
- </div>
-
- {/* Deliverables */}
- <div className="ml-9 space-y-2">
- {phase.deliverables.length === 0 ? (
- <div className="text-xs font-mono text-[#556677] italic">
- No deliverables
- </div>
- ) : (
- phase.deliverables.map((deliverable) => (
- <div
- key={deliverable.id}
- className="flex items-center gap-2"
- >
- <span className="text-[#75aafc] text-xs">-</span>
- <input
- type="text"
- className="flex-1 px-2 py-1 bg-transparent border border-[rgba(117,170,252,0.15)] text-[#dbe7ff] font-mono text-xs focus:outline-none focus:border-[#3f6fb3]"
- value={deliverable.name}
- onChange={(e) =>
- handleDeliverableNameChange(
- phase.id,
- deliverable.id,
- e.target.value
- )
- }
- />
- <button
- type="button"
- onClick={() =>
- handleRemoveDeliverable(phase.id, deliverable.id)
- }
- className="w-5 h-5 flex items-center justify-center text-[#ff6464] hover:bg-[rgba(255,100,100,0.1)] transition-colors text-xs"
- title="Remove deliverable"
- >
- x
- </button>
- </div>
- ))
- )}
-
- {/* Add Deliverable */}
- <div className="flex items-center gap-2 pt-2">
- <input
- type="text"
- className="flex-1 px-2 py-1 bg-transparent border border-[rgba(117,170,252,0.15)] text-[#dbe7ff] font-mono text-xs placeholder-[#445566] focus:outline-none focus:border-[#3f6fb3]"
- placeholder="New deliverable name..."
- value={newDeliverableName[phase.id] || ""}
- onChange={(e) =>
- setNewDeliverableName((prev) => ({
- ...prev,
- [phase.id]: e.target.value,
- }))
- }
- onKeyPress={(e) => {
- if (e.key === "Enter") {
- handleAddDeliverable(phase.id);
- }
- }}
- />
- <button
- type="button"
- onClick={() => handleAddDeliverable(phase.id)}
- className="px-2 py-1 border border-[rgba(117,170,252,0.3)] text-[#9bc3ff] font-mono text-xs hover:border-[#3f6fb3] hover:bg-[rgba(117,170,252,0.1)] transition-colors"
- >
- + Add
- </button>
- </div>
- </div>
- </div>
- ))}
- </div>
-
- {/* Add Phase (only for custom templates) */}
- {!template.isBuiltIn && (
- <button
- type="button"
- onClick={handleAddPhase}
- className="w-full mb-6 px-4 py-2 border border-dashed border-[rgba(117,170,252,0.3)] text-[#9bc3ff] font-mono text-xs uppercase tracking-wide hover:border-[#3f6fb3] hover:bg-[rgba(117,170,252,0.05)] transition-colors"
- >
- + Add Phase
- </button>
- )}
-
- {/* Footer Actions */}
- <div className="flex gap-3 justify-end pt-4 border-t border-[rgba(117,170,252,0.15)]">
- <button
- type="button"
- onClick={onCancel}
- 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"
- >
- {readOnly ? "Close" : "Cancel"}
- </button>
- {!readOnly && (
- <button
- type="button"
- onClick={() => onSave(editedTemplate)}
- 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"
- >
- Save Changes
- </button>
- )}
- </div>
- </div>
- );
-}