You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
7.2KB

  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Controllers;
  4. use App\Models\BoardColumn;
  5. use App\Repositories\BoardColumnRepository;
  6. use App\Repositories\CardMovementRepository;
  7. use App\Repositories\CardRepository;
  8. use App\Services\AuthService;
  9. use Core\Controller;
  10. use Core\Request;
  11. class ColumnsController extends Controller
  12. {
  13. private function columns(): BoardColumnRepository
  14. {
  15. return new BoardColumnRepository(database());
  16. }
  17. private function cards(): CardRepository
  18. {
  19. return new CardRepository(database());
  20. }
  21. private function cardMovements(): CardMovementRepository
  22. {
  23. return new CardMovementRepository(database());
  24. }
  25. public function store(Request $request): mixed
  26. {
  27. if (!AuthService::isLoggedIn()) {
  28. return $this->json(['ok' => false, 'error' => 'Unauthorized'], 401);
  29. }
  30. $boardId = (int) $request->input('board_id', 0);
  31. $name = trim((string) $request->input('name', ''));
  32. if ($boardId === 0 || $name === '') {
  33. return $this->json(['ok' => false, 'error' => 'board_id and name are required']);
  34. }
  35. $now = date('Y-m-d H:i:s');
  36. $username = AuthService::getCurrentUsername();
  37. $col = new BoardColumn();
  38. $col->boardId = $boardId;
  39. $col->name = $name;
  40. $col->position = $this->columns()->maxPosition($boardId) + 1;
  41. $col->createdAt = $now;
  42. $col->createdBy = $username;
  43. $col->updatedAt = $now;
  44. $col->updatedBy = $username;
  45. $this->columns()->insert($col);
  46. return $this->json(['ok' => true, 'id' => $col->id, 'name' => $col->name, 'position' => $col->position]);
  47. }
  48. public function update(Request $request, int $id): mixed
  49. {
  50. if (!AuthService::isLoggedIn()) {
  51. return $this->json(['ok' => false, 'error' => 'Unauthorized'], 401);
  52. }
  53. $name = trim((string) $request->input('name', ''));
  54. if ($name === '') {
  55. return $this->json(['ok' => false, 'error' => 'name is required']);
  56. }
  57. $row = $this->columns()->find($id);
  58. if ($row === null) {
  59. return $this->json(['ok' => false, 'error' => 'Not found'], 404);
  60. }
  61. $col = \App\Models\BoardColumn::fromRow($row);
  62. $col->name = $name;
  63. $col->updatedAt = date('Y-m-d H:i:s');
  64. $col->updatedBy = AuthService::getCurrentUsername();
  65. $this->columns()->update($col);
  66. return $this->json(['ok' => true]);
  67. }
  68. public function toggleExport(Request $request, int $id): mixed
  69. {
  70. if (!AuthService::isLoggedIn()) {
  71. return $this->json(['ok' => false, 'error' => 'Unauthorized'], 401);
  72. }
  73. $row = $this->columns()->find($id);
  74. if ($row === null) {
  75. return $this->json(['ok' => false, 'error' => 'Not found'], 404);
  76. }
  77. $show = (string) $request->input('show_export_button', '0') === '1';
  78. $this->columns()->updateShowExportButton($id, $show, date('Y-m-d H:i:s'), AuthService::getCurrentUsername());
  79. return $this->json(['ok' => true, 'show_export_button' => $show]);
  80. }
  81. public function toggleCount(Request $request, int $id): mixed
  82. {
  83. if (!AuthService::isLoggedIn()) {
  84. return $this->json(['ok' => false, 'error' => 'Unauthorized'], 401);
  85. }
  86. $row = $this->columns()->find($id);
  87. if ($row === null) {
  88. return $this->json(['ok' => false, 'error' => 'Not found'], 404);
  89. }
  90. $show = (string) $request->input('show_card_count', '0') === '1';
  91. $this->columns()->updateShowCardCount($id, $show, date('Y-m-d H:i:s'), AuthService::getCurrentUsername());
  92. return $this->json(['ok' => true, 'show_card_count' => $show]);
  93. }
  94. public function updateCardAgeSettings(Request $request, int $id): mixed
  95. {
  96. if (!AuthService::isLoggedIn()) {
  97. return $this->json(['ok' => false, 'error' => 'Unauthorized'], 401);
  98. }
  99. $row = $this->columns()->find($id);
  100. if ($row === null) {
  101. return $this->json(['ok' => false, 'error' => 'Not found'], 404);
  102. }
  103. $showCardAge = (string) $request->input('show_card_age', '0') === '1';
  104. $cardAgeWarningDays = max(0, (int) $request->input('card_age_warning_days', 0));
  105. $this->columns()->updateCardAgeSettings(
  106. $id,
  107. $showCardAge,
  108. $cardAgeWarningDays,
  109. date('Y-m-d H:i:s'),
  110. AuthService::getCurrentUsername()
  111. );
  112. return $this->json([
  113. 'ok' => true,
  114. 'show_card_age' => $showCardAge,
  115. 'card_age_warning_days' => $cardAgeWarningDays,
  116. ]);
  117. }
  118. public function export(int $id): mixed
  119. {
  120. if (!AuthService::isLoggedIn()) {
  121. return $this->redirect('/auth/login');
  122. }
  123. $row = $this->columns()->find($id);
  124. if ($row === null) {
  125. return new \Core\Response('Not found', 404);
  126. }
  127. $col = \App\Models\BoardColumn::fromRow($row);
  128. $cards = $this->cards()->findByColumnId($id);
  129. $out = fopen('php://memory', 'wb');
  130. fputcsv($out, ['Job #', 'Job Name', 'Customer', 'Delivery Date', 'Quantity', 'Notes'], ',', '"', '\\');
  131. foreach ($cards as $card) {
  132. fputcsv($out, [
  133. $card->jobNumber,
  134. $card->jobName,
  135. $card->customerName,
  136. $card->deliveryDate ?? '',
  137. $card->quantity ?? '',
  138. $card->notes,
  139. ], ',', '"', '\\');
  140. }
  141. rewind($out);
  142. $csv = (string) stream_get_contents($out);
  143. fclose($out);
  144. $slug = trim((string) preg_replace('/[^a-z0-9]+/i', '-', $col->name), '-');
  145. $filename = ($slug ?: 'column') . '-' . date('Y-m-d') . '.csv';
  146. return new \Core\Response($csv, 200, [
  147. 'Content-Type' => 'text/csv; charset=utf-8',
  148. 'Content-Disposition' => 'attachment; filename="' . $filename . '"',
  149. ]);
  150. }
  151. public function destroy(int $id): mixed
  152. {
  153. if (!AuthService::isLoggedIn()) {
  154. return $this->json(['ok' => false, 'error' => 'Unauthorized'], 401);
  155. }
  156. $this->cardMovements()->deleteByColumnId($id);
  157. $this->cards()->deleteByColumnId($id);
  158. $this->columns()->delete($id);
  159. return $this->json(['ok' => true]);
  160. }
  161. public function reorder(): mixed
  162. {
  163. if (!AuthService::isLoggedIn()) {
  164. return $this->json(['ok' => false, 'error' => 'Unauthorized'], 401);
  165. }
  166. $raw = file_get_contents('php://input');
  167. $items = json_decode((string) $raw, true);
  168. if (!is_array($items)) {
  169. return $this->json(['ok' => false, 'error' => 'Invalid JSON payload']);
  170. }
  171. $now = date('Y-m-d H:i:s');
  172. $username = AuthService::getCurrentUsername();
  173. foreach ($items as $item) {
  174. $colId = (int) ($item['id'] ?? 0);
  175. $position = (int) ($item['position'] ?? 0);
  176. if ($colId > 0) {
  177. $this->columns()->updatePosition($colId, $position, $now, $username);
  178. }
  179. }
  180. return $this->json(['ok' => true]);
  181. }
  182. }

Powered by TurnKey Linux.