feature: Add projects homepage and support for adding new projects

This commit is contained in:
Keith Solomon
2026-04-05 16:58:51 -05:00
parent 239a7eff64
commit 6d923b98b9
10 changed files with 492 additions and 38 deletions
+96 -8
View File
@@ -15,15 +15,19 @@ use IronKanban\Service\BoardService;
$projectRepository = new ProjectRepository();
$projects = $projectRepository->getAll();
$requestedProject = isset($_GET['project']) ? trim((string) $_GET['project']) : '';
$activeProjectId = $requestedProject !== '' ? $requestedProject : ($projects[0]->id ?? '');
$activeProjectId = $requestedProject;
$boardService = new BoardService();
$initialState = null;
$loadError = null;
$showDashboard = $requestedProject === '';
if ($activeProjectId !== '') {
try {
$initialState = $boardService->getBoardState($activeProjectId);
$showDashboard = false;
} catch (Throwable $exception) {
$initialState = null;
$showDashboard = true;
$loadError = 'The requested project could not be loaded. Pick another project or create a new one.';
}
}
?>
@@ -44,6 +48,16 @@ if ($activeProjectId !== '') {
<h1>IronKanban</h1>
<p class="sidebar-copy">Projects stay as flat files, while the UI gives you drag-and-drop columns, quick edits, notes, and polling-based refreshes.</p>
</div>
<div class="sidebar-actions">
<a class="button ghost" href="/">All Projects</a>
<?php if ($showDashboard) : ?>
<a class="button primary" href="#project-create-form">New Project</a>
<?php elseif ($initialState !== null) : ?>
<a class="button primary" href="/?project=<?php echo rawurlencode((string) $initialState['project']['id']); ?>">Open Current Board</a>
<?php endif; ?>
</div>
<section class="project-list">
<div class="section-heading">
<h2>Projects</h2>
@@ -55,13 +69,14 @@ if ($activeProjectId !== '') {
</div>
<?php else : ?>
<?php foreach ($projects as $project) : ?>
<a class="project-link<?php echo $project->id === $activeProjectId ? ' active' : ''; ?>" href="/?project=<?php echo rawurlencode($project->id); ?>">
<a class="project-link<?php echo $project->id === $activeProjectId && !$showDashboard ? ' active' : ''; ?>" href="/?project=<?php echo rawurlencode($project->id); ?>">
<strong><?php echo e($project->title); ?></strong>
<span><?php echo e($project->id); ?></span>
</a>
<?php endforeach; ?>
<?php endif; ?>
</section>
<section class="project-root">
<div class="section-heading">
<h2>Storage</h2>
@@ -70,11 +85,83 @@ if ($activeProjectId !== '') {
</section>
</aside>
<main class="workspace" id="app" data-project-id="<?php echo e($activeProjectId); ?>">
<?php if ($initialState === null) : ?>
<section class="hero empty-state">
<h2>No project selected</h2>
<p>Create or copy a project folder into <code><?php echo e(project_root()); ?></code> using the markdown layout from the notes.</p>
<main class="workspace" id="app" data-project-id="<?php echo e($showDashboard ? '' : $activeProjectId); ?>" data-view="<?php echo e($showDashboard ? 'dashboard' : 'board'); ?>">
<?php if ($showDashboard) : ?>
<section class="dashboard-intro hero">
<div>
<p class="eyebrow">Project Dashboard</p>
<h2>Choose a project or start a fresh one</h2>
<p class="project-description">Each project stays as markdown on disk, with its own notes, tasks, board definition, and revision tracking.</p>
</div>
<div class="dashboard-intro-meta">
<span><?php echo count($projects); ?> project<?php echo count($projects) === 1 ? '' : 's'; ?></span>
<span>Stored in <code><?php echo e(project_root()); ?></code></span>
</div>
</section>
<?php if ($loadError !== null) : ?>
<section class="hero error-state">
<h2>Project unavailable</h2>
<p><?php echo e($loadError); ?></p>
</section>
<?php endif; ?>
<section class="dashboard-grid">
<section class="project-create-panel">
<div class="section-heading">
<h2>Create Project</h2>
</div>
<form class="project-create-form" id="project-create-form" data-project-form>
<label>
<span>Title</span>
<input type="text" name="title" maxlength="200" required placeholder="Release Planning">
</label>
<label>
<span>Slug</span>
<input type="text" name="slug" maxlength="200" placeholder="release-planning">
</label>
<label>
<span>Description</span>
<textarea name="body" rows="7" placeholder="Describe the project, goals, and context."></textarea>
</label>
<div class="project-create-actions">
<p class="form-hint">Leave the slug blank to generate it automatically.</p>
<button type="submit" class="button primary">Create Project</button>
</div>
</form>
</section>
<section class="projects-panel">
<div class="section-heading">
<h2>Projects</h2>
<span><?php echo count($projects); ?></span>
</div>
<?php if ($projects === []) : ?>
<div class="empty-state">
<h3>No projects yet</h3>
<p>Create your first project to generate a board with default kanban columns.</p>
</div>
<?php else : ?>
<div class="project-card-grid">
<?php foreach ($projects as $project) : ?>
<?php
$preview = trim(preg_replace('/\s+/', ' ', $project->body) ?? '');
$preview = $preview !== '' ? $preview : 'No project description yet.';
$preview = strlen($preview) > 180 ? substr($preview, 0, 177) . '...' : $preview;
?>
<a class="project-card" href="/?project=<?php echo rawurlencode($project->id); ?>">
<p class="eyebrow">Project</p>
<h3><?php echo e($project->title); ?></h3>
<p class="project-card-body"><?php echo e($preview); ?></p>
<div class="project-card-footer">
<span class="project-card-slug"><?php echo e($project->id); ?></span>
<span class="project-card-cta">Open Board</span>
</div>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
</section>
</section>
<?php else : ?>
<header class="workspace-header">
@@ -84,6 +171,7 @@ if ($activeProjectId !== '') {
<p class="project-description"><?php echo nl2br(e((string) $initialState['project']['body'])); ?></p>
</div>
<div class="header-actions">
<a class="button ghost" href="/">All Projects</a>
<button type="button" class="button ghost" data-action="new-column">New Column</button>
<button type="button" class="button primary" data-action="new-task">New Task</button>
</div>