index.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. <?php
  2. /** @var list<\App\Domain\Worker> $workers */
  3. /** @var string $csrfToken */
  4. /** @var string $flash */
  5. /** @var string $error */
  6. use function App\Http\e;
  7. $errorMessages = [
  8. 'name_required' => 'Worker name is required.',
  9. 'name_taken' => 'That name is already in use.',
  10. 'rtb_out_of_range' => 'RTB must be between 0.0 and 1.0.',
  11. 'db_error' => 'Could not save. Try again.',
  12. ];
  13. $flashMessages = [
  14. 'created' => 'Worker created.',
  15. 'updated' => 'Saved.',
  16. 'noop' => 'Nothing changed.',
  17. ];
  18. ?>
  19. <section class="space-y-6">
  20. <div>
  21. <h1 class="text-2xl font-semibold tracking-tight">Workers</h1>
  22. <p class="text-slate-600 mt-1 text-sm max-w-prose">
  23. Master data for the people tasks get assigned to. Workers are not the
  24. same as users &mdash; a worker doesn't have to ever sign in. To remove
  25. someone, toggle them inactive rather than deleting.
  26. </p>
  27. </div>
  28. <?php if ($error !== '' && isset($errorMessages[$error])): ?>
  29. <div class="rounded-md border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-800">
  30. <?= e($errorMessages[$error]) ?>
  31. </div>
  32. <?php endif; ?>
  33. <?php if ($flash !== '' && isset($flashMessages[$flash])): ?>
  34. <div class="rounded-md border border-green-200 bg-green-50 px-4 py-3 text-sm text-green-800">
  35. <?= e($flashMessages[$flash]) ?>
  36. </div>
  37. <?php endif; ?>
  38. <!-- Add worker -->
  39. <div class="rounded-lg border bg-white p-4">
  40. <h2 class="text-sm font-semibold text-slate-700 uppercase tracking-wider">Add worker</h2>
  41. <form method="post" action="/workers" class="mt-3 flex flex-wrap items-end gap-3">
  42. <input type="hidden" name="_csrf" value="<?= e($csrfToken) ?>">
  43. <label class="flex-1 min-w-[12rem]">
  44. <span class="text-xs text-slate-600">Name</span>
  45. <input name="name" type="text" required
  46. class="mt-1 block w-full rounded-md border-slate-300 border shadow-sm px-3 py-2 focus:outline-none focus:ring-2 focus:ring-slate-400">
  47. </label>
  48. <label class="w-36">
  49. <span class="text-xs text-slate-600">Default RTB (0–1)</span>
  50. <input name="default_rtb" type="number" min="0" max="1" step="0.05" value="0.00"
  51. class="mt-1 block w-full rounded-md border-slate-300 border shadow-sm px-3 py-2 focus:outline-none focus:ring-2 focus:ring-slate-400">
  52. </label>
  53. <button type="submit"
  54. class="rounded-md bg-slate-900 text-white px-4 py-2 text-sm font-medium hover:bg-slate-800">
  55. Add
  56. </button>
  57. </form>
  58. </div>
  59. <!-- Workers table -->
  60. <div class="rounded-lg border bg-white overflow-hidden">
  61. <?php if ($workers === []): ?>
  62. <div class="p-8 text-center text-slate-500 text-sm">No workers yet.</div>
  63. <?php else: ?>
  64. <table class="min-w-full text-sm">
  65. <thead class="bg-slate-50 text-slate-600 text-xs uppercase tracking-wider">
  66. <tr>
  67. <th class="text-left px-4 py-2 font-semibold">Name</th>
  68. <th class="text-left px-4 py-2 font-semibold">Default RTB</th>
  69. <th class="text-left px-4 py-2 font-semibold">Active</th>
  70. <th class="text-right px-4 py-2 font-semibold">&nbsp;</th>
  71. </tr>
  72. </thead>
  73. <tbody class="divide-y divide-slate-100">
  74. <?php foreach ($workers as $w): ?>
  75. <tr class="<?= $w->isActive ? '' : 'opacity-60' ?>">
  76. <form method="post" action="/workers/<?= (int) $w->id ?>" class="contents">
  77. <input type="hidden" name="_csrf" value="<?= e($csrfToken) ?>">
  78. <td class="px-4 py-2">
  79. <input name="name" type="text" required
  80. value="<?= e($w->name) ?>"
  81. class="w-full rounded-md border-slate-300 border shadow-sm px-2 py-1 focus:outline-none focus:ring-2 focus:ring-slate-400">
  82. </td>
  83. <td class="px-4 py-2 w-32">
  84. <input name="default_rtb" type="number" min="0" max="1" step="0.05"
  85. value="<?= e(number_format($w->defaultRtb, 2, '.', '')) ?>"
  86. class="w-full rounded-md border-slate-300 border shadow-sm px-2 py-1 font-mono focus:outline-none focus:ring-2 focus:ring-slate-400">
  87. </td>
  88. <td class="px-4 py-2">
  89. <label class="inline-flex items-center gap-2">
  90. <input name="is_active" type="checkbox" value="1" <?= $w->isActive ? 'checked' : '' ?>
  91. class="rounded border-slate-300">
  92. <span class="text-slate-600">active</span>
  93. </label>
  94. </td>
  95. <td class="px-4 py-2 text-right">
  96. <button type="submit"
  97. class="rounded-md border border-slate-300 bg-white text-slate-700 px-3 py-1 text-sm hover:bg-slate-100">
  98. Save
  99. </button>
  100. </td>
  101. </form>
  102. </tr>
  103. <?php endforeach; ?>
  104. </tbody>
  105. </table>
  106. <?php endif; ?>
  107. </div>
  108. </section>