Overview
The TrackerService is a singleton service that manages all tracker operations in Minimal Tray Tasker. It provides methods for creating, updating, and managing task trackers, including support for daily recurring tasks.
Store
import { trackers } from '$lib/trackerService';
The trackers store is a Svelte writable store containing an array of SelectTracker objects. Subscribe to this store to reactively display tracker data in your UI.
Type: Writable<SelectTracker[]>
Methods
refresh()
Refreshes the tracker list from the database.
async refresh(): Promise<void>
Returns
Resolves when the tracker list has been refreshed from the database.
Example
import { TrackerService } from '$lib/trackerService';
// Refresh trackers from database
await TrackerService.refresh();
add()
Adds a new tracker to the database and updates the store.
async add(name: string, amount?: number, daily?: boolean): Promise<void>
Parameters
The name/description of the tracker.
The target amount to complete. Defaults to 1 if not specified.
Whether this tracker should reset daily. Defaults to false.
Returns
Resolves when the tracker has been added to the database and the store updated.
Example
import { TrackerService } from '$lib/trackerService';
// Add a simple one-time tracker
await TrackerService.add('Review pull requests');
// Add a tracker with custom amount
await TrackerService.add('Drink water', 8);
// Add a daily recurring tracker
await TrackerService.add('Exercise', 1, true);
Implementation Details
The method creates an InsertTracker object with the following defaults:
id: undefined (auto-generated by database)
progress: 0
completed: false
increment()
Increments the progress of a tracker by 1. Automatically marks the tracker as completed when progress reaches the target amount.
async increment(tracker: SelectTracker): Promise<void>
Parameters
The tracker object to increment. Must include the id, progress, and amount properties.
Returns
Resolves when the tracker progress has been updated in both the store and database.
Example
import { TrackerService, trackers } from '$lib/trackerService';
import { get } from 'svelte/store';
const currentTrackers = get(trackers);
const waterTracker = currentTrackers.find(t => t.name === 'Drink water');
if (waterTracker) {
await TrackerService.increment(waterTracker);
}
Behavior
- Progress is capped at the tracker’s
amount value
- When progress reaches
amount, the tracker is automatically marked as completed
- Updates both the Svelte store and the database
decrement()
Decrements the progress of a tracker by 1.
async decrement(tracker: SelectTracker): Promise<void>
Parameters
The tracker object to decrement. Must include the id and progress properties.
Returns
Resolves when the tracker progress has been updated in both the store and database.
Example
import { TrackerService, trackers } from '$lib/trackerService';
import { get } from 'svelte/store';
const currentTrackers = get(trackers);
const waterTracker = currentTrackers.find(t => t.name === 'Drink water');
if (waterTracker) {
await TrackerService.decrement(waterTracker);
}
Behavior
- Progress cannot go below 0
- Updates both the Svelte store and the database
remove()
Permanently deletes a tracker from the database and removes it from the store.
async remove(id: number): Promise<void>
Parameters
The unique identifier of the tracker to delete.
Returns
Resolves when the tracker has been deleted from both the store and database.
Example
import { TrackerService } from '$lib/trackerService';
// Remove tracker with ID 5
await TrackerService.remove(5);
Warning
This operation is permanent and cannot be undone. The tracker data will be completely removed from the database.
reopen()
Reopens a completed tracker by resetting its progress to 0 and marking it as incomplete.
async reopen(tracker: SelectTracker): Promise<void>
Parameters
The completed tracker to reopen. Must include the id property.
Returns
Resolves when the tracker has been reopened in both the store and database.
Example
import { TrackerService, trackers } from '$lib/trackerService';
import { get } from 'svelte/store';
const currentTrackers = get(trackers);
const completedTracker = currentTrackers.find(t => t.completed);
if (completedTracker) {
await TrackerService.reopen(completedTracker);
}
Behavior
- Sets
progress to 0
- Sets
completed to false
- Updates both the Svelte store and the database
refreshDailies()
Resets all daily trackers that haven’t been modified since the start of the current day. This method should be called on app startup or at midnight to reset daily tasks.
async refreshDailies(): Promise<void>
Returns
Resolves when all eligible daily trackers have been reset.
Example
import { TrackerService } from '$lib/trackerService';
// Called on app startup
await TrackerService.refreshDailies();
Behavior
- Only affects trackers where
isDaily is true
- Only resets trackers where
lastModifiedAt is before 00:00 of the current day
- Sets
progress to 0 and completed to false for eligible trackers
- Updates both the Svelte store and the database
Implementation Details
The method calculates the start of the current day (00:00) and compares each daily tracker’s lastModifiedAt timestamp:
let now = new Date();
let startOfDay = new Date(
now.getFullYear(),
now.getMonth(),
now.getDate(),
);
Types
SelectTracker
Represents a tracker retrieved from the database.
type SelectTracker = {
id: number;
name: string;
amount: number;
progress: number;
completed: boolean;
isDaily: boolean;
lastModifiedAt: Date;
}
InsertTracker
Represents a tracker object for insertion into the database.
type InsertTracker = {
id?: number;
name: string;
amount: number;
progress: number;
completed: boolean;
isDaily: boolean;
}
Usage in Components
<script lang="ts">
import { TrackerService, trackers } from '$lib/trackerService';
import { onMount } from 'svelte';
onMount(async () => {
// Load trackers on component mount
await TrackerService.refresh();
// Reset daily trackers
await TrackerService.refreshDailies();
});
async function handleAddTracker() {
await TrackerService.add('New Task', 5, false);
}
async function handleIncrement(tracker) {
await TrackerService.increment(tracker);
}
</script>
{#each $trackers as tracker}
<div>
<h3>{tracker.name}</h3>
<p>{tracker.progress} / {tracker.amount}</p>
<button on:click={() => handleIncrement(tracker)}>+</button>
</div>
{/each}