Add weekly progress and validation

This commit is contained in:
2026-07-10 16:23:50 +02:00
parent 23416ee382
commit 1cdef43a87
6 changed files with 39 additions and 11 deletions
+4 -2
View File
@@ -9,6 +9,7 @@ Habit Tracker ist eine PHP-Webanwendung, mit der Benutzer eigene Gewohnheiten an
- Habits erstellen, bearbeiten, loeschen und fuer heute abhaken
- Kategorien und Statusfilter im Dashboard
- Tagesprotokoll ueber `habit_logs`
- Wochenfortschritt im Dashboard gegen das persoenliche Wochenziel
- Responsive Oberflaeche fuer Desktop und Smartphone
- Serverseitige Validierung und klare Fehlermeldungen
- Schutz gegen SQL-Injection durch PDO Prepared Statements
@@ -67,8 +68,9 @@ Die Datenbank besteht aus 5 Tabellen:
3. Habit mit Kategorie und Wochenziel erstellen.
4. Habit im Dashboard filtern.
5. Habit fuer heute abhaken.
6. Habit bearbeiten und loeschen.
7. Seite auf Smartphone-Breite pruefen.
6. Wochenfortschritt im Dashboard kontrollieren.
7. Habit bearbeiten und loeschen.
8. Seite auf Smartphone-Breite pruefen.
## Bewertungsbezug
+10 -1
View File
@@ -119,6 +119,16 @@ class HabitController
if ($title === '') {
$errors['title'] = 'Bitte gib einen Namen fuer den Habit ein.';
} elseif (mb_strlen($title) > 120) {
$errors['title'] = 'Der Name darf maximal 120 Zeichen lang sein.';
}
if (mb_strlen($description) > 1000) {
$errors['description'] = 'Die Beschreibung darf maximal 1000 Zeichen lang sein.';
}
if ($categoryId !== '' && !Category::exists((int) $categoryId)) {
$errors['category_id'] = 'Bitte waehle eine gueltige Kategorie aus.';
}
if ($targetPerWeek < 1 || $targetPerWeek > 7) {
@@ -134,4 +144,3 @@ class HabitController
];
}
}
+9 -1
View File
@@ -1,4 +1,4 @@
<?php
<?php
class Category
{
@@ -8,4 +8,12 @@ class Category
->query('SELECT id, name, color FROM categories ORDER BY name')
->fetchAll();
}
public static function exists(int $id): bool
{
$statement = Database::connection()->prepare('SELECT id FROM categories WHERE id = :id LIMIT 1');
$statement->execute(['id' => $id]);
return (bool) $statement->fetch();
}
}
+6 -2
View File
@@ -1,4 +1,4 @@
<?php
<?php
class Habit
{
@@ -19,7 +19,11 @@ class Habit
}
$sql = 'SELECT h.*, c.name AS category_name, c.color AS category_color,
CASE WHEN hl.id IS NULL THEN 0 ELSE 1 END AS done_today
CASE WHEN hl.id IS NULL THEN 0 ELSE 1 END AS done_today,
(SELECT COUNT(*)
FROM habit_logs hwl
WHERE hwl.habit_id = h.id
AND YEARWEEK(hwl.completed_on, 1) = YEARWEEK(CURRENT_DATE, 1)) AS completed_this_week
FROM habits h
LEFT JOIN categories c ON c.id = h.category_id
LEFT JOIN habit_logs hl
+1 -2
View File
@@ -43,7 +43,7 @@
<p><?= e($habit['description']) ?></p>
<small>
<?= e($habit['category_name'] ?? 'Ohne Kategorie') ?> |
Ziel: <?= (int) $habit['target_per_week'] ?>x pro Woche
Woche: <?= (int) $habit['completed_this_week'] ?> / <?= (int) $habit['target_per_week'] ?> erledigt
</small>
</div>
</div>
@@ -64,4 +64,3 @@
</article>
<?php endforeach; ?>
</section>
+9 -3
View File
@@ -14,6 +14,7 @@
id="title"
name="title"
type="text"
maxlength="120"
class="<?= !empty($errors['title']) ? 'input-error' : '' ?>"
value="<?= e($habit['title'] ?? '') ?>"
required
@@ -24,10 +25,13 @@
<?php endif; ?>
<label for="description">Beschreibung <span>optional</span></label>
<textarea id="description" name="description" rows="4"><?= e($habit['description'] ?? '') ?></textarea>
<textarea id="description" name="description" rows="4" maxlength="1000"><?= e($habit['description'] ?? '') ?></textarea>
<?php if (!empty($errors['description'])): ?>
<small class="field-error"><?= e($errors['description']) ?></small>
<?php endif; ?>
<label for="category_id">Kategorie</label>
<select id="category_id" name="category_id">
<select id="category_id" name="category_id" class="<?= !empty($errors['category_id']) ? 'input-error' : '' ?>">
<option value="">Keine Kategorie</option>
<?php foreach ($categories as $category): ?>
<option value="<?= (int) $category['id'] ?>" <?= (string) ($habit['category_id'] ?? '') === (string) $category['id'] ? 'selected' : '' ?>>
@@ -35,6 +39,9 @@
</option>
<?php endforeach; ?>
</select>
<?php if (!empty($errors['category_id'])): ?>
<small class="field-error"><?= e($errors['category_id']) ?></small>
<?php endif; ?>
<label for="target_per_week">Ziel pro Woche</label>
<input
@@ -55,4 +62,3 @@
<button type="submit"><?= $isEdit ? 'Speichern' : 'Erstellen' ?></button>
</form>
</section>