getTasksUseCase = $getTasksUseCase; $this->createTaskUseCase = $createTaskUseCase; $this->deleteTaskUseCase = $deleteTaskUseCase; $this->assignTaskUseCase = $assignTaskUseCase; $this->updateStatusUseCase = $updateStatusUseCase; $this->saveResultUseCase = $saveResultUseCase; $this->executeAIUseCase = $executeAIUseCase; $this->taskRepository = $taskRepository; $this->resultRepository = $resultRepository; } public function index(): void { try { $filters = []; $status = $this->getString('status'); if ($status !== '') { $filters['status'] = $status; } $type = $this->getString('type'); if ($type !== '') { $filters['type'] = $type; } $search = $this->getString('search'); if ($search !== '') { $filters['search'] = $search; } $limit = $this->getInt('limit', 50); $offset = $this->getInt('offset'); $tasks = $this->getTasksUseCase->execute($filters, $limit, $offset); $total = $this->getTasksUseCase->count($filters); $this->json([ 'success' => true, 'data' => array_map(fn ($t) => $t->toArray(), $tasks), 'meta' => [ 'total' => $total, 'limit' => $limit, 'offset' => $offset, ], ]); } catch (\Exception $e) { $this->jsonError($e->getMessage()); } } public function show(string $id): void { try { $details = $this->getTasksUseCase->getTaskWithDetails((int) $id); if ($details === null) { $this->json(['success' => false, 'error' => 'Task not found'], 404); return; } $this->json([ 'success' => true, 'data' => $details, ]); } catch (\Exception $e) { $this->jsonError($e->getMessage()); } } public function store(): void { try { $input = $this->getJsonInput(); $task = $this->createTaskUseCase->execute($input); $this->json([ 'success' => true, 'data' => $task->toArray(), ], 201); } catch (\InvalidArgumentException $e) { $this->json(['success' => false, 'error' => $e->getMessage()], 400); } catch (\Exception $e) { $this->jsonError($e->getMessage()); } } public function update(string $id): void { try { $input = $this->getJsonInput(); $task = $this->getTasksUseCase->findById((int) $id); if ($task === null) { $this->json(['success' => false, 'error' => 'Task not found'], 404); return; } if (isset($input['title']) || isset($input['description'])) { $task->updateDetails( $input['title'] ?? $task->getTitle(), $input['description'] ?? $task->getDescription() ); } if (isset($input['type'])) { $task->changeType(\Domain\ValueObject\TaskType::from($input['type'])); } if (isset($input['due_date'])) { $task->setDueDateTo(new \DateTimeImmutable($input['due_date'])); } $this->taskRepository->update($task); $this->json([ 'success' => true, 'data' => $task->toArray(), ]); } catch (\InvalidArgumentException $e) { $this->json(['success' => false, 'error' => $e->getMessage()], 400); } catch (\Exception $e) { $this->jsonError($e->getMessage()); } } public function destroy(string $id): void { try { $this->deleteTaskUseCase->execute((int) $id); $this->json([ 'success' => true, 'message' => 'Task deleted', ]); } catch (\InvalidArgumentException $e) { $this->json(['success' => false, 'error' => $e->getMessage()], 404); } catch (\Exception $e) { $this->jsonError($e->getMessage()); } } public function assign(string $id): void { try { $input = $this->getJsonInput(); $assignment = $this->assignTaskUseCase->execute((int) $id, $input); $this->json([ 'success' => true, 'data' => $assignment->toArray(), ], 201); } catch (\InvalidArgumentException $e) { $this->json(['success' => false, 'error' => $e->getMessage()], 400); } catch (\Exception $e) { $this->jsonError($e->getMessage()); } } public function updateStatus(string $id): void { $this->requireCsrf(); try { // Accept both JSON and form data $input = $this->getJsonInput(); $status = $input['status'] ?? $_POST['status'] ?? null; if ($status === null || $status === '') { if ($this->isHtmxRequest()) { $this->htmxError('Status ist erforderlich'); return; } $this->json(['success' => false, 'error' => 'Status is required'], 400); return; } $updatedBy = $input['updated_by'] ?? 'api'; $updatedByType = $input['updated_by_type'] ?? 'human'; $task = $this->updateStatusUseCase->execute((int) $id, $status, $updatedBy, $updatedByType); // HTMX: Return updated status select if ($this->isHtmxRequest()) { $this->partial('tasks.partials.status-select', [ 'task' => $task->toArray(), ]); return; } $this->json([ 'success' => true, 'data' => $task->toArray(), ]); } catch (\InvalidArgumentException $e) { if ($this->isHtmxRequest()) { $this->htmxError($e->getMessage()); return; } $this->json(['success' => false, 'error' => $e->getMessage()], 400); } catch (\Exception $e) { if ($this->isHtmxRequest()) { $this->htmxError($e->getMessage()); return; } $this->jsonError($e->getMessage()); } } public function storeResult(string $id): void { try { $input = $this->getJsonInput(); $result = $this->saveResultUseCase->execute((int) $id, $input); $this->json([ 'success' => true, 'data' => $result->toArray(), ], 201); } catch (\InvalidArgumentException $e) { $this->json(['success' => false, 'error' => $e->getMessage()], 400); } catch (\Exception $e) { $this->jsonError($e->getMessage()); } } public function getResults(string $id): void { try { $results = $this->resultRepository->findByTaskId((int) $id); $this->json([ 'success' => true, 'data' => array_map(fn ($r) => $r->toArray(), $results), ]); } catch (\Exception $e) { $this->jsonError($e->getMessage()); } } public function executeAI(string $id): void { $this->requireCsrf(); try { $input = $this->getJsonInput(); $result = $this->executeAIUseCase->execute((int) $id, $input); // HTMX: Redirect to task page on success if ($this->isHtmxRequest()) { $this->htmxRedirect('/tasks/' . $id); return; } $this->json([ 'success' => true, 'data' => $result->toArray(), ]); } catch (\InvalidArgumentException $e) { if ($this->isHtmxRequest()) { $this->htmxError($e->getMessage()); return; } $this->json(['success' => false, 'error' => $e->getMessage()], 400); } catch (\RuntimeException $e) { if ($this->isHtmxRequest()) { $this->htmxError($e->getMessage()); return; } $this->json(['success' => false, 'error' => $e->getMessage()], 503); } catch (\Exception $e) { if ($this->isHtmxRequest()) { $this->htmxError($e->getMessage()); return; } $this->jsonError($e->getMessage()); } } public function statistics(): void { try { $taskStats = $this->getTasksUseCase->getStatistics(); $tokenStats = $this->resultRepository->getTokenStatistics(); $modelUsage = $this->resultRepository->getModelUsage(); $this->json([ 'success' => true, 'data' => [ 'tasks' => $taskStats, 'tokens' => $tokenStats, 'models' => $modelUsage, ], ]); } catch (\Exception $e) { $this->jsonError($e->getMessage()); } } }