Initial habit tracker project
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
class Habit
|
||||
{
|
||||
public static function allForUser(int $userId, array $filters = []): array
|
||||
{
|
||||
$where = ['h.user_id = :user_id'];
|
||||
$params = ['user_id' => $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]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user