Jelajahi Sumber

adding is_adult check

Medowar 1 bulan lalu
induk
melakukan
9d8e21dd00
3 mengubah file dengan 110 tambahan dan 2 penghapusan
  1. 56 1
      assets/js/form.js
  2. 1 0
      config/form_schema.php
  3. 53 1
      src/Form/Validator.php

+ 56 - 1
assets/js/form.js

@@ -304,6 +304,61 @@
     return ['1', 'on', 'true', true, 1].includes(value);
   }
 
+  function parseBirthdateParts(value) {
+    const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(String(value || '').trim());
+    if (!match) {
+      return null;
+    }
+
+    const year = Number(match[1]);
+    const month = Number(match[2]);
+    const day = Number(match[3]);
+    const candidate = new Date(Date.UTC(year, month - 1, day));
+    if (
+      Number.isNaN(candidate.getTime()) ||
+      candidate.getUTCFullYear() !== year ||
+      candidate.getUTCMonth() !== month - 1 ||
+      candidate.getUTCDate() !== day
+    ) {
+      return null;
+    }
+
+    return { year, month, day };
+  }
+
+  function deriveAdultFlagFromBirthdate(birthdateValue) {
+    const parts = parseBirthdateParts(birthdateValue);
+    if (!parts) {
+      return '';
+    }
+
+    const now = new Date();
+    const yearNow = now.getFullYear();
+    const monthNow = now.getMonth() + 1;
+    const dayNow = now.getDate();
+    const isFutureBirthdate =
+      parts.year > yearNow ||
+      (parts.year === yearNow && (parts.month > monthNow || (parts.month === monthNow && parts.day > dayNow)));
+    if (isFutureBirthdate) {
+      return '';
+    }
+
+    let age = yearNow - parts.year;
+    const hadBirthdayThisYear = monthNow > parts.month || (monthNow === parts.month && dayNow >= parts.day);
+    if (!hadBirthdayThisYear) {
+      age -= 1;
+    }
+
+    return age >= 18 ? '1' : '0';
+  }
+
+  function addComputedAgeFlags(data) {
+    const adultFlag = deriveAdultFlagFromBirthdate(data.geburtsdatum || '');
+    data.is_adult = adultFlag;
+    data.is_minor = adultFlag === '' ? '' : adultFlag === '1' ? '0' : '1';
+    return data;
+  }
+
   function collectCurrentFormData() {
     const data = {};
 
@@ -324,7 +379,7 @@
       }
     });
 
-    return data;
+    return addComputedAgeFlags(data);
   }
 
   function evaluateFieldRule(rule, formData) {

+ 1 - 0
config/form_schema.php

@@ -11,6 +11,7 @@ return [
                 ['key' => 'vorname', 'label' => 'Vorname', 'type' => 'text', 'required' => true, 'max_length' => 100],
                 ['key' => 'nachname', 'label' => 'Nachname', 'type' => 'text', 'required' => true, 'max_length' => 100],
                 ['key' => 'geburtsdatum', 'label' => 'Geburtsdatum', 'type' => 'date', 'required' => true],
+                ['key' => 'beispiel_erziehungsberechtigte', 'label' => 'Beispiel: Name eines Erziehungsberechtigten (nur < 18)', 'type' => 'text', 'required' => false, 'visible_if' => ['field' => 'is_minor', 'equals' => '1'], 'max_length' => 100],
                 ['key' => 'strasse', 'label' => 'Straße und Hausnummer', 'type' => 'text', 'required' => true, 'max_length' => 200],
                 ['key' => 'plz', 'label' => 'PLZ', 'type' => 'number', 'required' => true, 'max_length' => 5],
                 ['key' => 'ort', 'label' => 'Ort', 'type' => 'text', 'required' => true, 'max_length' => 100],

+ 53 - 1
src/Form/Validator.php

@@ -109,7 +109,59 @@ final class Validator
             return false;
         }
 
-        return (string) ($data[$sourceField] ?? '') === $equals;
+        return $this->resolveRuleValue($sourceField, $data) === $equals;
+    }
+
+    /** @param array<string, mixed> $data */
+    private function resolveRuleValue(string $sourceField, array $data): string
+    {
+        if (array_key_exists($sourceField, $data)) {
+            return (string) ($data[$sourceField] ?? '');
+        }
+
+        $derived = $this->derivedRuleValues($data);
+        return (string) ($derived[$sourceField] ?? '');
+    }
+
+    /**
+     * @param array<string, mixed> $data
+     * @return array<string, string>
+     */
+    private function derivedRuleValues(array $data): array
+    {
+        $adultFlag = $this->deriveAdultFlag((string) ($data['geburtsdatum'] ?? ''));
+        if ($adultFlag === null) {
+            return [
+                'is_adult' => '',
+                'is_minor' => '',
+            ];
+        }
+
+        return [
+            'is_adult' => $adultFlag ? '1' : '0',
+            'is_minor' => $adultFlag ? '0' : '1',
+        ];
+    }
+
+    private function deriveAdultFlag(string $birthdate): ?bool
+    {
+        $birthdate = trim($birthdate);
+        if ($birthdate === '') {
+            return null;
+        }
+
+        $date = \DateTimeImmutable::createFromFormat('!Y-m-d', $birthdate);
+        if (!$date || $date->format('Y-m-d') !== $birthdate) {
+            return null;
+        }
+
+        $today = new \DateTimeImmutable('today');
+        if ($date > $today) {
+            return null;
+        }
+
+        $age = $date->diff($today)->y;
+        return $age >= 18;
     }
 
     private function isEmptyValue(mixed $value, string $type): bool