From a1e74d73b719ee11debf4b39a0787017109c9f37 Mon Sep 17 00:00:00 2001 From: Mark Pitblado Date: Fri, 25 Oct 2024 18:09:08 -0700 Subject: [PATCH] feat: add pagination A future commit with make filtering by != done in the api request, rather than handling it client side --- src/api.rs | 11 ++++++----- src/app.rs | 32 +++++++++++++++++++++++++++++++- src/main.rs | 2 +- src/ui.rs | 4 ++++ 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/api.rs b/src/api.rs index d19f24a..42b9795 100644 --- a/src/api.rs +++ b/src/api.rs @@ -2,12 +2,13 @@ use crate::models::{Label, Task, TaskDetail}; use reqwest::Client; use std::collections::HashMap; -pub async fn fetch_tasks(instance_url: &str, api_key: &str) -> Result, reqwest::Error> { +pub async fn fetch_tasks( + instance_url: &str, + api_key: &str, + page: usize, +) -> Result, reqwest::Error> { let client = Client::new(); - let url = format!( - "{}/api/v1/tasks/all?project=Inbox&sort_by=created", - instance_url - ); + let url = format!("{}/api/v1/tasks/all?page={}", instance_url, page); let res = client .get(&url) diff --git a/src/app.rs b/src/app.rs index eeabc52..c470bdb 100644 --- a/src/app.rs +++ b/src/app.rs @@ -10,6 +10,7 @@ pub struct App { pub task_detail: Option, pub input_mode: InputMode, pub new_task_title: String, + pub page: usize, } pub enum InputMode { @@ -31,6 +32,17 @@ impl App { task_detail: None, input_mode: InputMode::Normal, new_task_title: String::new(), + page: 1, + } + } + + pub fn next_page(&mut self) { + self.page += 1; + } + + pub fn previous_page(&mut self) { + if self.page > 1 { + self.page -= 1; } } @@ -86,6 +98,22 @@ impl App { KeyCode::Char('q') => return Ok(true), KeyCode::Char('j') => self.next(), KeyCode::Char('k') => self.previous(), + KeyCode::Char('n') => { + // Next page + self.next_page(); + if let Ok(new_tasks) = fetch_tasks(instance_url, api_key, self.page).await { + self.tasks = new_tasks.into_iter().filter(|task| !task.done).collect(); + self.state.select(Some(0)); + } + } + KeyCode::Char('p') => { + // Previous page + self.previous_page(); + if let Ok(new_tasks) = fetch_tasks(instance_url, api_key, self.page).await { + self.tasks = new_tasks.into_iter().filter(|task| !task.done).collect(); + self.state.select(Some(0)); + } + } KeyCode::Char('a') => { self.input_mode = InputMode::Editing; self.new_task_title.clear(); @@ -108,7 +136,9 @@ impl App { eprintln!("Error creating task: {}", err); } else { // Refresh the task list - if let Ok(all_tasks) = fetch_tasks(instance_url, api_key).await { + if let Ok(all_tasks) = + fetch_tasks(instance_url, api_key, self.page).await + { self.tasks = all_tasks.into_iter().filter(|task| !task.done).collect(); self.state.select(Some(0)); diff --git a/src/main.rs b/src/main.rs index e2acfbd..f3e8eba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,7 +47,7 @@ async fn main() -> Result<(), Box> { let instance_url = config.vikunja.instance_url; let api_key = config.vikunja.api_key; - let all_tasks = api::fetch_tasks(&instance_url, &api_key).await?; + let all_tasks = api::fetch_tasks(&instance_url, &api_key, 1).await?; let incomplete_tasks: Vec = all_tasks.into_iter().filter(|task| !task.done).collect(); diff --git a/src/ui.rs b/src/ui.rs index 4f3f8e5..046d516 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -66,6 +66,10 @@ fn get_legend(input_mode: &InputMode) -> Text<'static> { Span::raw(": Down "), Span::styled(" k ", Style::default().fg(Color::Red)), Span::raw(": Up "), + Span::styled(" n ", Style::default().fg(Color::Red)), + Span::raw(": Next Page "), + Span::styled(" p ", Style::default().fg(Color::Red)), + Span::raw(": Previous Page "), Span::styled(" Enter ", Style::default().fg(Color::Red)), Span::raw(": View Details "), Span::styled(" a ", Style::default().fg(Color::Red)),