new.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. <?php
  2. /** @var string $csrfToken */
  3. /** @var string $error */
  4. /** @var array{name:string,start_date:string,end_date:string,reserve_fraction:string,n_weeks:string} $form */
  5. use function App\Http\e;
  6. $errorMessages = [
  7. 'name_required' => 'Sprint name is required.',
  8. 'dates_invalid' => 'Start and end dates must both be valid dates (YYYY-MM-DD).',
  9. 'dates_order' => 'End date must not be before start date.',
  10. 'reserve_invalid' => 'Reserve must be a number (0–100).',
  11. 'reserve_out_of_range' => 'Reserve must be between 0 and 100 percent.',
  12. 'n_weeks_invalid' => 'Weeks must be an integer.',
  13. 'n_weeks_range' => 'Weeks must be between 1 and 26.',
  14. 'db_error' => 'Could not save. Try again.',
  15. ];
  16. ?>
  17. <section class="max-w-xl">
  18. <h1 class="text-2xl font-semibold tracking-tight">New sprint</h1>
  19. <p class="text-slate-600 mt-1 text-sm dark:text-slate-400">
  20. Worker membership, weekly availability and tasks are configured on the
  21. sprint page after creation.
  22. </p>
  23. <?php if ($error !== '' && isset($errorMessages[$error])): ?>
  24. <div class="mt-4 rounded-md border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-800 dark:bg-red-900 dark:border-red-800 dark:text-red-200">
  25. <?= e($errorMessages[$error]) ?>
  26. </div>
  27. <?php endif; ?>
  28. <form method="post" action="/sprints" class="mt-6 space-y-4 rounded-lg border bg-white p-5 dark:bg-slate-800 dark:border-slate-700">
  29. <input type="hidden" name="_csrf" value="<?= e($csrfToken) ?>">
  30. <label class="block">
  31. <span class="text-sm text-slate-700 dark:text-slate-300">Name</span>
  32. <input name="name" type="text" required
  33. value="<?= e($form['name']) ?>"
  34. placeholder="e.g. Sprint 12"
  35. 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 dark:bg-slate-800 dark:border-slate-600 dark:text-slate-100 dark:focus:ring-slate-500">
  36. </label>
  37. <div class="grid grid-cols-2 gap-3">
  38. <label class="block">
  39. <span class="text-sm text-slate-700 dark:text-slate-300">Start date</span>
  40. <input name="start_date" type="date" required
  41. value="<?= e($form['start_date']) ?>"
  42. 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 dark:bg-slate-800 dark:border-slate-600 dark:text-slate-100 dark:focus:ring-slate-500">
  43. </label>
  44. <label class="block">
  45. <span class="text-sm text-slate-700 dark:text-slate-300">End date</span>
  46. <input name="end_date" type="date" required
  47. value="<?= e($form['end_date']) ?>"
  48. 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 dark:bg-slate-800 dark:border-slate-600 dark:text-slate-100 dark:focus:ring-slate-500">
  49. </label>
  50. </div>
  51. <div class="grid grid-cols-2 gap-3">
  52. <label class="block">
  53. <span class="text-sm text-slate-700 dark:text-slate-300">Reserve (%)</span>
  54. <input name="reserve_fraction" type="number" min="0" max="100" step="1" required
  55. value="<?= e($form['reserve_fraction']) ?>"
  56. class="mt-1 block w-full rounded-md border-slate-300 border shadow-sm px-3 py-2 font-mono focus:outline-none focus:ring-2 focus:ring-slate-400 dark:bg-slate-800 dark:border-slate-600 dark:text-slate-100 dark:focus:ring-slate-500">
  57. <span class="text-xs text-slate-500 dark:text-slate-400">Reduction from raw capacity. The Excel uses 20%.</span>
  58. </label>
  59. <label class="block">
  60. <span class="text-sm text-slate-700 dark:text-slate-300">Weeks</span>
  61. <input name="n_weeks" type="number" min="1" max="26" step="1" required
  62. value="<?= e($form['n_weeks']) ?>"
  63. class="mt-1 block w-full rounded-md border-slate-300 border shadow-sm px-3 py-2 font-mono focus:outline-none focus:ring-2 focus:ring-slate-400 dark:bg-slate-800 dark:border-slate-600 dark:text-slate-100 dark:focus:ring-slate-500">
  64. <span class="text-xs text-slate-500 dark:text-slate-400">Week rows get 5 days/week by default; edit on the sprint page.</span>
  65. </label>
  66. </div>
  67. <div class="flex gap-3 pt-2">
  68. <button type="submit"
  69. class="rounded-md bg-slate-900 text-white px-4 py-2 text-sm font-medium hover:bg-slate-800 dark:bg-slate-700 dark:hover:bg-slate-600">
  70. Create sprint
  71. </button>
  72. <a href="/" class="inline-flex items-center rounded-md border border-slate-300 bg-white text-slate-700 px-4 py-2 text-sm hover:bg-slate-100 dark:bg-slate-800 dark:border-slate-600 dark:text-slate-200 dark:hover:bg-slate-700">
  73. Cancel
  74. </a>
  75. </div>
  76. </form>
  77. </section>