1+ from typing import Optional
12from uuid import UUID
23
3- from fastapi import APIRouter , Depends , HTTPException , status
4+ from fastapi import APIRouter , Depends , HTTPException , Query , status
45
5- from src .core .schemas .response import PaginatedResponse , SuccessResponse
6- from src .modules .todo .presentation .schemas .response import TodoResponse
76from src .core .authorization .dependencies import require_permission
87from src .core .authorization .permissions import (
98 CREATE_ACTION ,
1211 TODO_RESOURCE ,
1312 UPDATE_ACTION ,
1413)
14+ from src .core .schemas .response import (
15+ CursorMeta ,
16+ CursorPaginatedResponse ,
17+ SuccessResponse ,
18+ )
19+ from src .core .utils .cursor import CursorDirection , decode_cursor , encode_cursor
1520from src .modules .todo .application .create_todo .command import CreateTodoCommand
1621from src .modules .todo .application .create_todo .handler import CreateTodoHandler
1722from src .modules .todo .application .delete_todo .handler import DeleteTodoHandler
18- from src .modules .todo .application .list_todo .handler import GetTodosQueryHandler
23+ from src .modules .todo .application .list_todo .handler import (
24+ GetTodosCursorQuery ,
25+ )
1926from src .modules .todo .application .list_todo .query import GetTodosQuery
2027from src .modules .todo .application .update_todo .command import UpdateTodoCommand
2128from src .modules .todo .application .update_todo .handler import UpdateTodoHandler
2633from src .modules .todo .presentation .dependency import (
2734 get_create_todo_handler ,
2835 get_delete_todo_handler ,
29- get_get_todos_query_handler ,
36+ get_todos_query_handler ,
3037 get_update_todo_handler ,
3138)
39+ from src .modules .todo .presentation .schemas .response import TodoResponse
3240
3341router = APIRouter (prefix = "/todos" , tags = ["Todos" ])
3442
@@ -55,24 +63,68 @@ async def create_todo(
5563 )
5664
5765
58- @router .get ("/" , response_model = PaginatedResponse [TodoResponse ])
66+ @router .get ("/" , response_model = CursorPaginatedResponse [TodoResponse ])
5967async def get_todos (
68+ cursor : Optional [str ] = Query (
69+ None , description = "Cursor for pagination (from previous response)"
70+ ),
71+ limit : int = Query (10 , ge = 1 , le = 100 , description = "Number of items per page" ),
6072 current_user : dict = Depends (require_permission (TODO_RESOURCE , READ_ACTION )),
61- query : GetTodosQueryHandler = Depends (get_get_todos_query_handler ),
73+ query : GetTodosCursorQuery = Depends (get_todos_query_handler ),
6274):
75+ cursor_created_at = None
76+ cursor_id = None
77+ if cursor :
78+ cursor_created_at , cursor_id , direction = decode_cursor (cursor )
79+
6380 command = GetTodosQuery (user_id = current_user .get ("id" ))
64- todos = await query .execute (command = command )
65- return PaginatedResponse (
66- message = "fetch todo success" ,
67- success = True ,
68- data = [
69- TodoResponse (
70- id = str (todo .id ),
71- title = todo .title ,
72- is_completed = todo .is_completed ,
73- )
74- for todo in todos
75- ],
81+ todos , has_more = await query .execute (
82+ user_id = command .user_id ,
83+ cursor_created_at = cursor_created_at ,
84+ cursor_id = cursor_id ,
85+ limit = limit ,
86+ direction = direction ,
87+ )
88+ response_todos = [
89+ TodoResponse (
90+ id = str (t .id ),
91+ title = t .title ,
92+ description = t .description ,
93+ is_completed = t .is_completed ,
94+ created_at = t .created_at .isoformat (),
95+ )
96+ for t in todos
97+ ]
98+
99+ next_cursor = None
100+ prev_cursor = None
101+
102+ if has_more and len (todos ) > 0 :
103+ last_item = todos [- 1 ]
104+ next_cursor = encode_cursor (
105+ last_item .created_at ,
106+ last_item .id ,
107+ CursorDirection .DIRECTION_NEXT ,
108+ )
109+
110+ if cursor and len (todos ) > 0 :
111+ first_item = todos [0 ]
112+ prev_cursor = encode_cursor (
113+ first_item .created_at ,
114+ first_item .id ,
115+ CursorDirection .DIRECTION_PREV ,
116+ )
117+
118+ return CursorPaginatedResponse (
119+ message = "Todos retrieved successfully" ,
120+ meta = CursorMeta (
121+ next_cursor = next_cursor ,
122+ prev_cursor = prev_cursor ,
123+ has_next = has_more ,
124+ has_prev = cursor is not None ,
125+ limit = limit ,
126+ ),
127+ data = response_todos ,
76128 )
77129
78130
0 commit comments