boards()->getAll(); return $this->view('boards.index', [ 'pageTitle' => 'Boards', 'boards' => $boards, ]); } public function create(): mixed { if ($guard = AuthService::requireLogin()) { return $guard; } return $this->view('boards.create', ['pageTitle' => 'New Board']); } public function store(Request $request): mixed { if ($guard = AuthService::requireLogin()) { return $guard; } $name = trim((string) $request->input('name', '')); if ($name === '') { return $this->view('boards.create', [ 'pageTitle' => 'New Board', 'error' => 'Board name is required.', 'old' => $request->all(), ]); } $username = AuthService::getCurrentUsername(); $now = date('Y-m-d H:i:s'); $board = new Board(); $board->name = $name; $board->slug = $this->boards()->uniqueSlug($this->generateSlug($name)); $board->importFromPrintstream = $request->input('import_from_printstream') === 'on'; $board->printstreamJobName = trim((string) $request->input('printstream_job_name', '')); $board->createdAt = $now; $board->createdBy = $username; $board->updatedAt = $now; $board->updatedBy = $username; $this->boards()->insert($board); return $this->redirect('/board/' . $board->slug); } public function show(string $slug): mixed { if ($guard = AuthService::requireLogin()) { return $guard; } $board = $this->boards()->findBySlug($slug); if ($board === null) { return \Core\Response::notFound('Board not found.'); } $columns = $this->columns()->findByBoardId($board->id); $lanes = $this->lanes()->findByBoardId($board->id); $allCards = $this->cards()->findByBoardId($board->id); $cardsJson = json_encode( array_map(fn($c) => $c->toJsonArray(), $allCards), JSON_THROW_ON_ERROR ); return $this->fragment('boards.show', [ 'board' => $board, 'columns' => $columns, 'lanes' => $lanes, 'cardsJson' => $cardsJson, ]); } public function edit(string $slug): mixed { if ($guard = AuthService::requireLogin()) { return $guard; } $board = $this->boards()->findBySlug($slug); if ($board === null) { return \Core\Response::notFound('Board not found.'); } return $this->view('boards.edit', [ 'pageTitle' => 'Edit Board', 'board' => $board, ]); } public function update(Request $request, string $slug): mixed { if ($guard = AuthService::requireLogin()) { return $guard; } $board = $this->boards()->findBySlug($slug); if ($board === null) { return \Core\Response::notFound('Board not found.'); } $newName = trim((string) $request->input('name', '')); if ($newName === '') { return $this->view('boards.edit', [ 'pageTitle' => 'Edit Board', 'board' => $board, 'error' => 'Board name is required.', ]); } $board->name = $newName; $board->slug = $this->boards()->uniqueSlug($this->generateSlug($newName), $board->id); $board->importFromPrintstream = $request->input('import_from_printstream') === 'on'; $board->printstreamJobName = trim((string) $request->input('printstream_job_name', '')); $board->updatedAt = date('Y-m-d H:i:s'); $board->updatedBy = AuthService::getCurrentUsername(); $this->boards()->update($board); return $this->redirect('/board/' . $board->slug); } public function updateCardAgeSettings(Request $request, int $id): mixed { if (!AuthService::isLoggedIn()) { return $this->json(['ok' => false, 'error' => 'Unauthorized'], 401); } $row = $this->boards()->find($id); if ($row === null) { return $this->json(['ok' => false, 'error' => 'Not found'], 404); } $showCardAge = (string) $request->input('show_card_age', '0') === '1'; $cardAgeWarningDays = max(0, (int) $request->input('card_age_warning_days', 0)); $this->boards()->updateCardAgeSettings( $id, $showCardAge, $cardAgeWarningDays, date('Y-m-d H:i:s'), AuthService::getCurrentUsername() ); return $this->json([ 'ok' => true, 'show_card_age' => $showCardAge, 'card_age_warning_days' => $cardAgeWarningDays, ]); } public function destroy(string $slug): mixed { if ($guard = AuthService::requireLogin()) { return $guard; } $board = $this->boards()->findBySlug($slug); if ($board === null) { return $this->redirect('/boards'); } $this->cards()->deleteByBoardId($board->id); $this->columns()->deleteByBoardId($board->id); $this->lanes()->deleteByBoardId($board->id); $this->boards()->delete($board->id); return $this->redirect('/boards'); } private function generateSlug(string $text): string { $slug = strtolower($text); $slug = preg_replace('/[^a-z0-9\s-]/', '', $slug) ?? $slug; $slug = preg_replace('/[\s-]+/', '-', trim($slug)) ?? $slug; return trim($slug, '-'); } }