answer.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. <?php
  2. // answer.php - Renders an existing form for answering
  3. $form_id = $_GET['id'] ?? '';
  4. $form_file = __DIR__ . '/data/forms/' . preg_replace('/[^a-zA-Z0-9_-]/', '', $form_id) . '.json';
  5. if (empty($form_id) || !file_exists($form_file)) {
  6. die('<div style="font-family:sans-serif; text-align:center; padding:50px;"><h2>Formular nicht gefunden</h2><p>Der Link ist möglicherweise ungültig oder abgelaufen.</p></div>');
  7. }
  8. $form_data = json_decode(file_get_contents($form_file), true);
  9. // If editing a response
  10. $edit_id = $_GET['edit'] ?? null;
  11. $existing_answers = [];
  12. if ($edit_id) {
  13. // Sanitize edit\_id
  14. $safe_edit_id = preg_replace('/[^a-zA-Z0-9_-]/', '', $edit_id);
  15. $answer_file = __DIR__ . "/data/answers/{$form_id}_{$safe_edit_id}.json";
  16. if (file_exists($answer_file)) {
  17. $answer_data = json_decode(file_get_contents($answer_file), true);
  18. $existing_answers = $answer_data['answers'] ?? [];
  19. }
  20. }
  21. ?>
  22. <!DOCTYPE html>
  23. <html lang="de">
  24. <head>
  25. <meta charset="UTF-8">
  26. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  27. <title><?= htmlspecialchars($form_data['title']) ?> - Intranet Formulare</title>
  28. <link rel="stylesheet" href="assets/css/style.css">
  29. </head>
  30. <body>
  31. <header class="site-header">
  32. <div class="container header-inner">
  33. <div class="brand">
  34. <span class="brand-title"><?= htmlspecialchars($form_data['title']) ?></span>
  35. </div>
  36. </div>
  37. </header>
  38. <main class="container">
  39. <!-- Error tracking container (JS managed) -->
  40. <div id="already-submitted-alert" class="alert alert-warning" style="display:none;">
  41. Sie haben dieses Formular bereits ausgefüllt. <a href="submit.php?id=<?= htmlspecialchars($form_id) ?>" style="font-weight:bold;">Ihre Antworten ansehen</a>
  42. </div>
  43. <form action="submit.php" method="POST" id="answer-form">
  44. <input type="hidden" name="form_id" value="<?= htmlspecialchars($form_id) ?>">
  45. <?php if ($edit_id): ?>
  46. <input type="hidden" name="edit_id" value="<?= htmlspecialchars($edit_id) ?>">
  47. <?php endif; ?>
  48. <div class="panel">
  49. <h1 class="card-title"><?= htmlspecialchars($form_data['title']) ?></h1>
  50. <?php if (!empty($form_data['description'])): ?>
  51. <p style="margin-bottom:1rem; color:var(--brand-muted);"><?= nl2br(htmlspecialchars($form_data['description'])) ?></p>
  52. <?php endif; ?>
  53. <h3 style="border-bottom: 1px solid var(--brand-border); padding-bottom: 0.5rem; margin-bottom: 1rem;">Deine Daten</h3>
  54. <div class="form-group">
  55. <label for="respondent_name">Dein Name *</label>
  56. <input type="text" id="respondent_name" name="respondent_name" required>
  57. </div>
  58. <div class="form-group">
  59. <label for="respondent_email">Deine E-Mail (Optional, um eine Kopie zu erhalten)</label>
  60. <input type="email" id="respondent_email" name="respondent_email">
  61. </div>
  62. </div>
  63. <div class="panel">
  64. <h3 style="border-bottom: 1px solid var(--brand-border); padding-bottom: 0.5rem; margin-bottom: 1rem;">Fragen</h3>
  65. <?php foreach ($form_data['questions'] as $q): ?>
  66. <div class="form-group">
  67. <?php
  68. $is_required = !isset($q['required']) || $q['required'] === true;
  69. $req_attr = $is_required ? 'required' : '';
  70. ?>
  71. <label><?= htmlspecialchars($q['label']) ?><?= $is_required ? ' *' : '' ?></label>
  72. <?php
  73. $val = $existing_answers[$q['id']] ?? '';
  74. $is_array_val = is_array($val);
  75. $is_freetext_val = false;
  76. $freetext_content = '';
  77. if ($q['type'] === 'single_choice') {
  78. if (!empty($val) && !in_array($val, $q['options'])) {
  79. $is_freetext_val = true;
  80. $freetext_content = $val;
  81. }
  82. } elseif ($q['type'] === 'multiple_choice') {
  83. if ($is_array_val) {
  84. foreach ($val as $v) {
  85. if (!in_array($v, $q['options'])) {
  86. $is_freetext_val = true;
  87. $freetext_content = $v;
  88. }
  89. }
  90. }
  91. }
  92. if ($q['type'] === 'textarea'): ?>
  93. <textarea id="<?= htmlspecialchars($q['id']) ?>" name="answers[<?= htmlspecialchars($q['id']) ?>]" rows="4" <?= $req_attr ?>><?= htmlspecialchars(is_string($val) ? $val : '') ?></textarea>
  94. <?php elseif ($q['type'] === 'single_choice'): ?>
  95. <div class="options-container" style="display:flex; flex-direction:column; gap:0.5rem; margin-top:0.5rem;">
  96. <?php foreach ($q['options'] as $idx => $opt):
  97. $checked = (is_string($val) && $val === $opt) ? 'checked' : '';
  98. ?>
  99. <label style="font-weight:normal; display:flex; align-items:center; gap:0.5rem;">
  100. <input type="radio" name="answers[<?= htmlspecialchars($q['id']) ?>]" value="<?= htmlspecialchars($opt) ?>" <?= $req_attr ?> <?= $checked ?> style="width:auto; margin:0;">
  101. <?= htmlspecialchars($opt) ?>
  102. </label>
  103. <?php endforeach; ?>
  104. <?php if (!empty($q['allow_free_text'])): ?>
  105. <label style="font-weight:normal; display:flex; align-items:center; gap:0.5rem;">
  106. <input type="radio" name="answers[<?= htmlspecialchars($q['id']) ?>]" value="__freetext__" <?= $req_attr ?> <?= $is_freetext_val ? 'checked' : '' ?> style="width:auto; margin:0;">
  107. Sonstiges:
  108. <input type="text" name="answers_freetext[<?= htmlspecialchars($q['id']) ?>]" value="<?= htmlspecialchars($freetext_content) ?>" style="margin-left: 0.5rem; flex:1;">
  109. </label>
  110. <?php endif; ?>
  111. </div>
  112. <?php elseif ($q['type'] === 'multiple_choice'): ?>
  113. <div class="options-container" style="display:flex; flex-direction:column; gap:0.5rem; margin-top:0.5rem;">
  114. <?php foreach ($q['options'] as $idx => $opt):
  115. $checked = ($is_array_val && in_array($opt, $val)) ? 'checked' : '';
  116. ?>
  117. <label style="font-weight:normal; display:flex; align-items:center; gap:0.5rem;">
  118. <input type="checkbox" name="answers[<?= htmlspecialchars($q['id']) ?>][]" value="<?= htmlspecialchars($opt) ?>" <?= $checked ?> style="width:auto; margin:0;">
  119. <?= htmlspecialchars($opt) ?>
  120. </label>
  121. <?php endforeach; ?>
  122. <?php if (!empty($q['allow_free_text'])): ?>
  123. <label style="font-weight:normal; display:flex; align-items:center; gap:0.5rem;">
  124. <input type="checkbox" name="answers[<?= htmlspecialchars($q['id']) ?>][]" value="__freetext__" <?= $is_freetext_val ? 'checked' : '' ?> style="width:auto; margin:0;">
  125. Sonstiges:
  126. <input type="text" name="answers_freetext[<?= htmlspecialchars($q['id']) ?>]" value="<?= htmlspecialchars($freetext_content) ?>" style="margin-left: 0.5rem; flex:1;">
  127. </label>
  128. <?php endif; ?>
  129. </div>
  130. <?php elseif ($q['type'] === 'dropdown'): ?>
  131. <select id="<?= htmlspecialchars($q['id']) ?>" name="answers[<?= htmlspecialchars($q['id']) ?>]" <?= $req_attr ?>>
  132. <option value="">-- Bitte auswählen --</option>
  133. <?php foreach ($q['options'] as $opt):
  134. $selected = (is_string($val) && $val === $opt) ? 'selected' : '';
  135. ?>
  136. <option value="<?= htmlspecialchars($opt) ?>" <?= $selected ?>><?= htmlspecialchars($opt) ?></option>
  137. <?php endforeach; ?>
  138. </select>
  139. <?php else: ?>
  140. <input type="text" id="<?= htmlspecialchars($q['id']) ?>" name="answers[<?= htmlspecialchars($q['id']) ?>]" <?= $req_attr ?> value="<?= htmlspecialchars(is_string($val) ? $val : '') ?>">
  141. <?php endif; ?>
  142. </div>
  143. <?php endforeach; ?>
  144. </div>
  145. <div class="panel text-center" style="background:transparent; border:none; box-shadow:none;">
  146. <button type="submit" class="btn btn-block" style="font-size: 1.1rem; padding: 0.75rem;">Antworten senden</button>
  147. </div>
  148. </form>
  149. </main>
  150. <script>
  151. const formId = "<?= htmlspecialchars($form_id) ?>";
  152. const isEditMode = <?= $edit_id ? 'true' : 'false' ?>;
  153. // Remove 'required' from radios if checkbox group is used (not natively supported without JS, so let's ensure single choice allows form submission if freetext is present)
  154. // For radio groups, 'required' works as long as they have the same name.
  155. </script>
  156. <script src="assets/js/answer.js"></script>
  157. </body>
  158. </html>