Nobody has started this yet — be first.
Business impact
Right now a user can see their current streak and longest streak, but not which days they actually checked in. Support cannot answer "why does my streak say 3, I thought I'd checked in more than that" without direct database access, because the API has no way to list the underlying dates. Any future UI feature that wants to render a calendar/heatmap view of a habit (a very standard habit-tracker UI pattern) is blocked on this -- it's the most-requested kind of "just let me see my own data" gap.
Problem
app/main.py already declares the route GET /habits/{habit_id}/checkins, wired to crud.list_checkins -- but crud.list_checkins is a stub that unconditionally raises NotImplementedError("crud.list_checkins is not implemented yet -- see practice_tickets/TICKET-02.md"). Calling the endpoint currently 500s.
Current behavior
Calling GET /habits/{id}/checkins currently returns a 500 Internal Server Error, with NotImplementedError: crud.list_checkins is not implemented yet logged, instead of the check-in history.
Expected behavior
GET /habits/{id}/checkins returns every check-in for that habit as a JSON array of {"id": ..., "date": "YYYY-MM-DD"} objects (matching schemas.CheckInOut, the same shape POST /habits/{id}/checkins already returns), ordered oldest to newest. A habit with no check-ins returns [], not an error. Ownership is already enforced for free by the get_current_habit dependency.
Steps to reproduce
uvicorn app.main:app --reload # or use the ticket test below, no server needed
curl -s http://127.0.0.1:8000/habits/<id>/checkins -H "Authorization: Bearer <token>"
Why this matters
This is the smallest possible instance of "the read side of a feature is missing" -- the data has existed since day one (CheckIn rows are created by create_checkin), only the query to list them back out was never written.
Suggested approach
Look at app/crud.py::get_checkin_dates, a few lines above the stub -- it already queries CheckIn rows for a habit, just returning dates as a set instead of ordered model instances. list_checkins needs the same WHERE habit_id = ... filter, but ordered, and returning the full rows (so response_model=list[schemas.CheckInOut] has an id to serialize, not just a date) rather than a deduplicated set.
Acceptance criteria
Verification
pytest practice_tickets/tests/test_ticket02_list_checkins.py -v
Hints (0/2)
Try it without hints first — the reading is the exercise.
Working on this ticket
Work on a branch named for the ticket — that's what you'll submit.
Branch off your fork
$git checkout -b feat/list-checkins-endpointFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin feat/list-checkins-endpointSubmit it below
Paste your fork URL and the branch name, with a short write-up of the root cause.
Questions
Ask about anything unclear in the ticket — the maintainer and anyone who has solved it can answer. Please don't post full solutions.
Sign in to ask a question or reply.
Sign indocker compose up --buildfastapi/habit_trackerRun the project's own suite with pytest -v (or pytest tests/ -q for a quick pass/fail count) from fastapi/habit_tracker -- a fresh clone should show a handful of failures until TICKET-03 and TICKET-06 are fixed.
Work the tickets in practice_tickets/ (TICKET-01 through TICKET-07); each names one pytest file under practice_tickets/tests/:
pytest practice_tickets/tests/test_ticket01_stats_window.py -v # a single ticket
./practice_tickets/run_tickets.sh # all 7, clean pass/fail summary
./practice_tickets/run_tickets.sh 03 07 # just a subset
practice_tickets/tests/ is intentionally outside pyproject.toml's testpaths = ["tests"], so a plain pytest run from the repo root never picks these up -- they're learning exercises, not part of the project's CI-gating regression suite.
Level 2
Implement a feature
Extend the system within its own patterns.