answer.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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;">Ihre Daten</h3>
  54. <div class="form-group">
  55. <label for="respondent_name">Ihr 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">Ihre 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. <label><?= htmlspecialchars($q['label']) ?> *</label>
  68. <?php
  69. $val = $existing_answers[$q['id']] ?? '';
  70. $is_array_val = is_array($val);
  71. $is_freetext_val = false;
  72. $freetext_content = '';
  73. if ($q['type'] === 'single_choice') {
  74. if (!empty($val) && !in_array($val, $q['options'])) {
  75. $is_freetext_val = true;
  76. $freetext_content = $val;
  77. }
  78. } elseif ($q['type'] === 'multiple_choice') {
  79. if ($is_array_val) {
  80. foreach ($val as $v) {
  81. if (!in_array($v, $q['options'])) {
  82. $is_freetext_val = true;
  83. $freetext_content = $v;
  84. }
  85. }
  86. }
  87. }
  88. if ($q['type'] === 'textarea'): ?>
  89. <textarea id="<?= htmlspecialchars($q['id']) ?>" name="answers[<?= htmlspecialchars($q['id']) ?>]" rows="4" required><?= htmlspecialchars(is_string($val) ? $val : '') ?></textarea>
  90. <?php elseif ($q['type'] === 'single_choice'): ?>
  91. <div class="options-container" style="display:flex; flex-direction:column; gap:0.5rem; margin-top:0.5rem;">
  92. <?php foreach ($q['options'] as $idx => $opt):
  93. $checked = (is_string($val) && $val === $opt) ? 'checked' : '';
  94. ?>
  95. <label style="font-weight:normal; display:flex; align-items:center; gap:0.5rem;">
  96. <input type="radio" name="answers[<?= htmlspecialchars($q['id']) ?>]" value="<?= htmlspecialchars($opt) ?>" required <?= $checked ?> style="width:auto; margin:0;">
  97. <?= htmlspecialchars($opt) ?>
  98. </label>
  99. <?php endforeach; ?>
  100. <?php if (!empty($q['allow_free_text'])): ?>
  101. <label style="font-weight:normal; display:flex; align-items:center; gap:0.5rem;">
  102. <input type="radio" name="answers[<?= htmlspecialchars($q['id']) ?>]" value="__freetext__" required <?= $is_freetext_val ? 'checked' : '' ?> style="width:auto; margin:0;">
  103. Sonstiges:
  104. <input type="text" name="answers_freetext[<?= htmlspecialchars($q['id']) ?>]" value="<?= htmlspecialchars($freetext_content) ?>" style="margin-left: 0.5rem; flex:1;">
  105. </label>
  106. <?php endif; ?>
  107. </div>
  108. <?php elseif ($q['type'] === 'multiple_choice'): ?>
  109. <div class="options-container" style="display:flex; flex-direction:column; gap:0.5rem; margin-top:0.5rem;">
  110. <?php foreach ($q['options'] as $idx => $opt):
  111. $checked = ($is_array_val && in_array($opt, $val)) ? 'checked' : '';
  112. ?>
  113. <label style="font-weight:normal; display:flex; align-items:center; gap:0.5rem;">
  114. <input type="checkbox" name="answers[<?= htmlspecialchars($q['id']) ?>][]" value="<?= htmlspecialchars($opt) ?>" <?= $checked ?> style="width:auto; margin:0;">
  115. <?= htmlspecialchars($opt) ?>
  116. </label>
  117. <?php endforeach; ?>
  118. <?php if (!empty($q['allow_free_text'])): ?>
  119. <label style="font-weight:normal; display:flex; align-items:center; gap:0.5rem;">
  120. <input type="checkbox" name="answers[<?= htmlspecialchars($q['id']) ?>][]" value="__freetext__" <?= $is_freetext_val ? 'checked' : '' ?> style="width:auto; margin:0;">
  121. Sonstiges:
  122. <input type="text" name="answers_freetext[<?= htmlspecialchars($q['id']) ?>]" value="<?= htmlspecialchars($freetext_content) ?>" style="margin-left: 0.5rem; flex:1;">
  123. </label>
  124. <?php endif; ?>
  125. </div>
  126. <?php elseif ($q['type'] === 'dropdown'): ?>
  127. <select id="<?= htmlspecialchars($q['id']) ?>" name="answers[<?= htmlspecialchars($q['id']) ?>]" required>
  128. <option value="">-- Bitte auswählen --</option>
  129. <?php foreach ($q['options'] as $opt):
  130. $selected = (is_string($val) && $val === $opt) ? 'selected' : '';
  131. ?>
  132. <option value="<?= htmlspecialchars($opt) ?>" <?= $selected ?>><?= htmlspecialchars($opt) ?></option>
  133. <?php endforeach; ?>
  134. </select>
  135. <?php else: ?>
  136. <input type="text" id="<?= htmlspecialchars($q['id']) ?>" name="answers[<?= htmlspecialchars($q['id']) ?>]" required value="<?= htmlspecialchars(is_string($val) ? $val : '') ?>">
  137. <?php endif; ?>
  138. </div>
  139. <?php endforeach; ?>
  140. </div>
  141. <div class="panel text-center" style="background:transparent; border:none; box-shadow:none;">
  142. <button type="submit" class="btn btn-block" style="font-size: 1.1rem; padding: 0.75rem;">Antworten senden</button>
  143. </div>
  144. </form>
  145. </main>
  146. <script>
  147. const formId = "<?= htmlspecialchars($form_id) ?>";
  148. const isEditMode = <?= $edit_id ? 'true' : 'false' ?>;
  149. // 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)
  150. // For radio groups, 'required' works as long as they have the same name.
  151. </script>
  152. <script src="assets/js/answer.js"></script>
  153. </body>
  154. </html>