$userId]; if (!empty($filters['category_id'])) { $where[] = 'h.category_id = :category_id'; $params['category_id'] = (int) $filters['category_id']; } if (($filters['status'] ?? '') === 'done') { $where[] = 'hl.id IS NOT NULL'; } elseif (($filters['status'] ?? '') === 'open') { $where[] = 'hl.id IS NULL'; } $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 FROM habits h LEFT JOIN categories c ON c.id = h.category_id LEFT JOIN habit_logs hl ON hl.habit_id = h.id AND hl.completed_on = CURRENT_DATE WHERE ' . implode(' AND ', $where) . ' ORDER BY h.created_at DESC'; $statement = Database::connection()->prepare($sql); $statement->execute($params); return $statement->fetchAll(); } public static function findForUser(int $id, int $userId): ?array { $statement = Database::connection()->prepare( 'SELECT * FROM habits WHERE id = :id AND user_id = :user_id LIMIT 1' ); $statement->execute(['id' => $id, 'user_id' => $userId]); $habit = $statement->fetch(); return $habit ?: null; } public static function create(int $userId, array $data): bool { $sql = 'INSERT INTO habits (user_id, category_id, title, description, target_per_week) VALUES (:user_id, :category_id, :title, :description, :target_per_week)'; return Database::connection()->prepare($sql)->execute([ 'user_id' => $userId, 'category_id' => $data['category_id'] ?: null, 'title' => $data['title'], 'description' => $data['description'], 'target_per_week' => (int) $data['target_per_week'], ]); } public static function update(int $id, int $userId, array $data): bool { $sql = 'UPDATE habits SET category_id = :category_id, title = :title, description = :description, target_per_week = :target_per_week WHERE id = :id AND user_id = :user_id'; return Database::connection()->prepare($sql)->execute([ 'id' => $id, 'user_id' => $userId, 'category_id' => $data['category_id'] ?: null, 'title' => $data['title'], 'description' => $data['description'], 'target_per_week' => (int) $data['target_per_week'], ]); } public static function delete(int $id, int $userId): bool { $statement = Database::connection()->prepare('DELETE FROM habits WHERE id = :id AND user_id = :user_id'); return $statement->execute(['id' => $id, 'user_id' => $userId]); } public static function toggleToday(int $id, int $userId): bool { $habit = self::findForUser($id, $userId); if (!$habit) { return false; } $db = Database::connection(); $check = $db->prepare( 'SELECT id FROM habit_logs WHERE habit_id = :habit_id AND completed_on = CURRENT_DATE LIMIT 1' ); $check->execute(['habit_id' => $id]); $log = $check->fetch(); if ($log) { return $db->prepare('DELETE FROM habit_logs WHERE id = :id')->execute(['id' => $log['id']]); } $insert = $db->prepare('INSERT INTO habit_logs (habit_id, completed_on) VALUES (:habit_id, CURRENT_DATE)'); return $insert->execute(['habit_id' => $id]); } }