<html data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{.Name}} - AI Project Manager</title>
<!-- HTMX -->
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.8/dist/htmx.min.js"
integrity="sha384-/TgkGk7p307TH7EXJDuUlgG3Ce1UVolAOFopFekQkkXihi5u/6OCvVKyz1W+idaz"
crossorigin="anonymous"></script>
<!-- Tailwind CSS & Daisy UI -->
<link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet" type="text/css" />
<link href="https://cdn.jsdelivr.net/npm/daisyui@5/themes.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<!-- Sortable.js for drag-and-drop -->
<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>
</head>
{{with projects.CurrentProject}}
<body class="bg-base-200">
<div class="min-h-screen">
<!-- Navbar -->
<div class="navbar bg-base-100 shadow-lg">
<div class="flex-1">
<a href="{{hostPrefix}}/" class="btn btn-ghost text-xl">🤖 AI Project Manager</a>
<div class="divider divider-horizontal mx-2"></div>
<span class="text-lg font-semibold">{{.Name}}</span>
</div>
<div class="flex-none">
<div class="flex gap-2">
{{if not projects.HasAPIKey}}
<button class="btn btn-warning btn-sm" onclick="api_key_modal.showModal()">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
</svg>
Configure API Key
</button>
{{end}}
<button class="btn btn-ghost btn-sm" onclick="ai_summary_modal.showModal()">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
</svg>
AI Summary
</button>
<button class="btn btn-secondary btn-sm" onclick="ai_generate_modal.showModal()">
✨ Generate Tasks
</button>
<button class="btn btn-primary btn-sm" onclick="create_task_modal.showModal()">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
</svg>
New Task
</button>
</div>
</div>
</div>
<!-- Main Content -->
<div class="container mx-auto p-6 max-w-7xl">
<!-- Project Header -->
<div class="card bg-base-100 shadow-xl mb-6">
<div class="card-body">
<h2 class="card-title text-2xl">{{.Name}}</h2>
<p class="text-base-content/70">{{.Description}}</p>
<!-- Stats -->
<div class="stats shadow mt-4">
<div class="stat place-items-center">
<div class="stat-title">To Do</div>
<div class="stat-value text-info">{{index projects.TaskStats "todo"}}</div>
</div>
<div class="stat place-items-center">
<div class="stat-title">In Progress</div>
<div class="stat-value text-warning">{{index projects.TaskStats "in_progress"}}</div>
</div>
<div class="stat place-items-center">
<div class="stat-title">Done</div>
<div class="stat-value text-success">{{index projects.TaskStats "done"}}</div>
</div>
</div>
</div>
</div>
<!-- Kanban Board -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- To Do Column -->
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h3 class="card-title">
<div class="badge badge-info badge-lg">{{index projects.TaskStats "todo"}}</div>
To Do
</h3>
<form class="sortable space-y-3 mt-4" hx-post="{{hostPrefix}}/tasks/reorder" hx-trigger="end">
{{range projects.TodoTasks}}
<div class="card bg-base-200 shadow-sm cursor-move hover:shadow-md transition-shadow">
<input type="hidden" name="task" value="{{.ID}}" />
<div class="card-body p-4">
<h4 class="font-semibold">{{.Title}}</h4>
{{if .Description}}
<p class="text-sm opacity-70 mt-1">{{.Description}}</p>
{{end}}
<div class="card-actions justify-between items-center mt-3">
<div class="badge badge-sm {{if eq .Priority " high"}}badge-error{{else if eq .Priority "medium"
}}badge-warning{{else}}badge-info{{end}}">
{{.Priority}}
</div>
<button type="button" onclick="event.stopPropagation();"
hx-post="{{hostPrefix}}/task/{{.ID}}/move/in_progress" hx-swap="none"
class="btn btn-xs btn-ghost">
→
</button>
</div>
</div>
</div>
{{else}}
<div class="text-center text-sm opacity-50 py-8">
No tasks yet
</div>
{{end}}
</form>
</div>
</div>
<!-- In Progress Column -->
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h3 class="card-title">
<div class="badge badge-warning badge-lg">{{index projects.TaskStats "in_progress"}}</div>
In Progress
</h3>
<form class="sortable space-y-3 mt-4" hx-post="{{hostPrefix}}/tasks/reorder" hx-trigger="end">
{{range projects.InProgressTasks}}
<div class="card bg-base-200 shadow-sm cursor-move hover:shadow-md transition-shadow">
<input type="hidden" name="task" value="{{.ID}}" />
<div class="card-body p-4">
<h4 class="font-semibold">{{.Title}}</h4>
{{if .Description}}
<p class="text-sm opacity-70 mt-1">{{.Description}}</p>
{{end}}
<div class="card-actions justify-between items-center mt-3">
<div class="badge badge-sm {{if eq .Priority " high"}}badge-error{{else if eq .Priority "medium"
}}badge-warning{{else}}badge-info{{end}}">
{{.Priority}}
</div>
<div class="btn-group btn-group-horizontal">
<button type="button" onclick="event.stopPropagation();"
hx-post="{{hostPrefix}}/task/{{.ID}}/move/todo" hx-swap="none" class="btn btn-xs btn-ghost">
←
</button>
<button type="button" onclick="event.stopPropagation();"
hx-post="{{hostPrefix}}/task/{{.ID}}/move/done" hx-swap="none" class="btn btn-xs btn-ghost">
→
</button>
</div>
</div>
</div>
</div>
{{else}}
<div class="text-center text-sm opacity-50 py-8">
No tasks yet
</div>
{{end}}
</form>
</div>
</div>
<!-- Done Column -->
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h3 class="card-title">
<div class="badge badge-success badge-lg">{{index projects.TaskStats "done"}}</div>
Done
</h3>
<form class="sortable space-y-3 mt-4" hx-post="{{hostPrefix}}/tasks/reorder" hx-trigger="end">
{{range projects.DoneTasks}}
<div class="card bg-base-200 shadow-sm opacity-75 cursor-move hover:opacity-100 transition-opacity">
<input type="hidden" name="task" value="{{.ID}}" />
<div class="card-body p-4">
<h4 class="font-semibold line-through">{{.Title}}</h4>
{{if .Description}}
<p class="text-sm opacity-70 mt-1 line-through">{{.Description}}</p>
{{end}}
<div class="card-actions justify-between items-center mt-3">
<div class="badge badge-sm {{if eq .Priority " high"}}badge-error{{else if eq .Priority "medium"
}}badge-warning{{else}}badge-info{{end}}">
{{.Priority}}
</div>
<button type="button" onclick="event.stopPropagation();"
hx-post="{{hostPrefix}}/task/{{.ID}}/move/in_progress" hx-swap="none"
class="btn btn-xs btn-ghost">
←
</button>
</div>
</div>
</div>
{{else}}
<div class="text-center text-sm opacity-50 py-8">
No completed tasks
</div>
{{end}}
</form>
</div>
</div>
</div>
</div>
</div>
<!-- Create Task Modal -->
<dialog id="create_task_modal" class="modal">
<div class="modal-box">
<h3 class="font-bold text-lg mb-4">Create New Task</h3>
<form hx-post="{{hostPrefix}}/task/create" hx-swap="none">
<input type="hidden" name="project_id" value="{{.ID}}" />
<div class="form-control mb-4">
<label class="label">
<span class="label-text">Task Title</span>
</label>
<input type="text" name="title" placeholder="Fix the login bug" class="input input-bordered" required />
</div>
<div class="form-control mb-4">
<label class="label">
<span class="label-text">Description</span>
</label>
<textarea name="description" placeholder="What needs to be done?" class="textarea textarea-bordered h-24"
rows="3"></textarea>
</div>
<div class="form-control mb-4">
<label class="label">
<span class="label-text">Priority</span>
</label>
<select name="priority" class="select select-bordered">
<option value="low">Low</option>
<option value="medium" selected>Medium</option>
<option value="high">High</option>
</select>
</div>
<div class="modal-action">
<button type="button" class="btn" onclick="create_task_modal.close()">Cancel</button>
<button type="submit" class="btn btn-primary">Create Task</button>
</div>
</form>
</div>
<form method="dialog" class="modal-backdrop">
<button>close</button>
</form>
</dialog>
<!-- AI Generate Tasks Modal -->
<dialog id="ai_generate_modal" class="modal">
<div class="modal-box max-w-4xl">
<h3 class="font-bold text-lg mb-2">✨ AI Task Generator</h3>
<p class="text-sm opacity-70 mb-4">Let AI analyze your project and generate suggested tasks</p>
<div id="ai-generate-output" class="bg-base-200 rounded-box p-4 min-h-[200px] max-h-[500px] overflow-y-auto">
<div class="flex flex-col items-center justify-center h-full text-base-content/50 py-12">
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 mb-4 opacity-30" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
</svg>
<p>Click "Generate" to start AI task generation</p>
</div>
</div>
<div class="modal-action">
<button type="button" class="btn" onclick="ai_generate_modal.close()">Close</button>
<button type="button" class="btn btn-primary" hx-post="{{hostPrefix}}/ai/generate-tasks"
hx-vals='{"project_id": "{{.ID}}"}' hx-target="#ai-generate-output" hx-swap="innerHTML"
hx-indicator="#ai-generate-spinner">
<span id="ai-generate-spinner" class="loading loading-spinner loading-sm htmx-indicator"></span>
Generate Tasks
</button>
</div>
</div>
<form method="dialog" class="modal-backdrop">
<button>close</button>
</form>
</dialog>
<!-- API Key Configuration Modal -->
<dialog id="api_key_modal" class="modal">
<div class="modal-box">
<h3 class="font-bold text-lg mb-2">🔑 Configure Friendli API Key</h3>
<p class="text-sm opacity-70 mb-4">Enter your Friendli.ai API key to enable AI features</p>
<form hx-post="{{hostPrefix}}/api/settings/api-key" hx-swap="none">
<div class="form-control mb-4">
<label class="label">
<span class="label-text">API Key</span>
</label>
<input type="password" name="api_key" placeholder="flp_..." class="input input-bordered" required />
<label class="label">
<span class="label-text-alt">Get your API key from <a href="https://friendli.ai" target="_blank"
class="link">friendli.ai</a></span>
</label>
</div>
<div class="modal-action">
<button type="button" class="btn" onclick="api_key_modal.close()">Cancel</button>
<button type="submit" class="btn btn-primary">Save API Key</button>
</div>
</form>
</div>
<form method="dialog" class="modal-backdrop">
<button>close</button>
</form>
</dialog>
<!-- AI Project Summary Modal -->
<dialog id="ai_summary_modal" class="modal">
<div class="modal-box max-w-4xl">
<h3 class="font-bold text-lg mb-2">🤖 AI Project Summary</h3>
<p class="text-sm opacity-70 mb-4">AI analysis of your project's current status</p>
<div id="ai-summary-output"
class="prose max-w-none bg-base-200 rounded-box p-4 min-h-[300px] max-h-[600px] overflow-y-auto">
<div class="flex flex-col items-center justify-center h-full text-base-content/50 py-12 not-prose">
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 mb-4 opacity-30" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" />
</svg>
<p>Click "Analyze" to get AI insights</p>
</div>
</div>
<div class="modal-action">
<button type="button" class="btn" onclick="ai_summary_modal.close()">Close</button>
<button type="button" class="btn btn-primary" hx-post="{{hostPrefix}}/ai/project-summary"
hx-vals='{"project_id": "{{.ID}}"}' hx-target="#ai-summary-output" hx-swap="innerHTML"
hx-indicator="#ai-summary-spinner">
<span id="ai-summary-spinner" class="loading loading-spinner loading-sm htmx-indicator"></span>
Analyze Project
</button>
</div>
</div>
<form method="dialog" class="modal-backdrop">
<button>close</button>
</form>
</dialog>
<!-- Initialize Sortable.js -->
<script>
htmx.onLoad(function (content) {
var sortables = content.querySelectorAll(".sortable");
for (var i = 0; i < sortables.length; i++) {
var sortable = sortables[i];
new Sortable(sortable, {
animation: 150,
ghostClass: 'opacity-50',
dragClass: 'rotate-1 scale-105',
handle: '.card',
onEnd: function (evt) {
htmx.trigger(evt.from, 'end');
}
});
}
});
</script>
</body>
{{else}}
<body class="bg-base-200">
<div class="hero min-h-screen">
<div class="hero-content text-center">
<div class="max-w-md">
<h1 class="text-5xl font-bold mb-4">404</h1>
<p class="text-xl mb-6">Project not found</p>
<a href="{{hostPrefix}}/" class="btn btn-primary">Go Home</a>
</div>
</div>
</div>
</body>
{{end}}
</html>