2025-06-14 18:25:56 -04:00
|
|
|
//! TUI state
|
|
|
|
|
|
2025-06-22 20:02:39 -04:00
|
|
|
use ratatui::crossterm::event::KeyEvent;
|
2025-06-14 18:25:56 -04:00
|
|
|
use ratatui::widgets::TableState;
|
|
|
|
|
|
2025-06-22 01:25:11 -04:00
|
|
|
use crate::places::db_repository::DbPlacesRepository;
|
|
|
|
|
use crate::places::models::Place;
|
|
|
|
|
use crate::places::repository::PlacesRepository;
|
|
|
|
|
|
|
|
|
|
use super::ui::Message;
|
2025-06-14 18:25:56 -04:00
|
|
|
|
|
|
|
|
pub struct State {
|
|
|
|
|
pub height: u16,
|
|
|
|
|
pub page: u32,
|
|
|
|
|
pub mode: Mode,
|
|
|
|
|
places_repository: DbPlacesRepository,
|
|
|
|
|
pub places: Vec<Place>,
|
|
|
|
|
places_status: DataStatus,
|
|
|
|
|
pub confirmation: Option<ConfirmationStatus>,
|
|
|
|
|
pub selected_place: TableState,
|
2025-06-22 01:25:11 -04:00
|
|
|
pub ui_messages: Vec<Message>,
|
2025-06-14 18:25:56 -04:00
|
|
|
pub quit: bool,
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-22 01:25:11 -04:00
|
|
|
#[derive(Copy, Clone)]
|
2025-06-14 18:25:56 -04:00
|
|
|
pub enum Mode {
|
|
|
|
|
List,
|
|
|
|
|
Edit,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum DataStatus {
|
|
|
|
|
Fresh,
|
|
|
|
|
Old,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub enum ConfirmationStatus {
|
|
|
|
|
Deletion(i64),
|
2025-06-22 01:25:11 -04:00
|
|
|
Save(Place),
|
2025-06-14 18:25:56 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl State {
|
|
|
|
|
pub fn new(places_repository: DbPlacesRepository, height: u16) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
height,
|
|
|
|
|
page: 0,
|
|
|
|
|
mode: Mode::List,
|
|
|
|
|
places_repository,
|
|
|
|
|
places_status: DataStatus::Old,
|
|
|
|
|
places: vec![],
|
|
|
|
|
selected_place: TableState::default(),
|
|
|
|
|
confirmation: None,
|
2025-06-22 01:25:11 -04:00
|
|
|
ui_messages: Vec::new(),
|
2025-06-14 18:25:56 -04:00
|
|
|
quit: false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-22 01:25:11 -04:00
|
|
|
pub fn set_list_mode(&mut self) {
|
|
|
|
|
self.mode = Mode::List;
|
|
|
|
|
self.push_mode_change();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_edit_mode(&mut self) {
|
|
|
|
|
self.mode = Mode::Edit;
|
|
|
|
|
self.push_mode_change();
|
|
|
|
|
|
|
|
|
|
let Some(selection) = self.selected_place.selected() else {
|
|
|
|
|
return;
|
|
|
|
|
};
|
|
|
|
|
let Some(place) = self.places.get(selection) else {
|
|
|
|
|
return;
|
|
|
|
|
};
|
|
|
|
|
self.ui_messages.push(Message::EditPlace(place.clone()))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn push_mode_change(&mut self) {
|
|
|
|
|
self.ui_messages.push(Message::UpdateAppMode(self.mode));
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-14 18:25:56 -04:00
|
|
|
pub fn next_page(&mut self) {
|
|
|
|
|
self.page += 1;
|
|
|
|
|
self.places_status = DataStatus::Old;
|
2025-06-22 01:25:11 -04:00
|
|
|
self.push_page_change();
|
2025-06-14 18:25:56 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn prev_page(&mut self) {
|
|
|
|
|
self.page = self.page.saturating_sub(1);
|
|
|
|
|
self.places_status = DataStatus::Old;
|
2025-06-22 01:25:11 -04:00
|
|
|
self.push_page_change();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn push_page_change(&mut self) {
|
|
|
|
|
self.ui_messages.push(Message::UpdatePage(self.page));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn edit_next(&mut self) {
|
|
|
|
|
self.ui_messages.push(Message::EditNext);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn edit_prev(&mut self) {
|
|
|
|
|
self.ui_messages.push(Message::EditPrev);
|
2025-06-14 18:25:56 -04:00
|
|
|
}
|
|
|
|
|
|
2025-06-22 20:02:39 -04:00
|
|
|
pub fn edit_input(&mut self, key_event: KeyEvent) {
|
|
|
|
|
self.ui_messages.push(Message::Input(key_event));
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-14 18:25:56 -04:00
|
|
|
pub async fn fetch_places(&mut self) {
|
|
|
|
|
if let DataStatus::Fresh = self.places_status {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
let limit = (self.height as u8).saturating_sub(3);
|
|
|
|
|
let offset = (limit as u32) * self.page;
|
|
|
|
|
match self
|
|
|
|
|
.places_repository
|
|
|
|
|
.get_places_paginated(offset, limit)
|
|
|
|
|
.await
|
|
|
|
|
{
|
|
|
|
|
Ok(places) => {
|
|
|
|
|
self.places = places;
|
|
|
|
|
if !self.places.is_empty() {
|
|
|
|
|
self.selected_place.select(Some(0));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Err(err) => {
|
|
|
|
|
tracing::error!("{err}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
self.places_status = DataStatus::Fresh;
|
2025-06-22 01:25:11 -04:00
|
|
|
self.ui_messages
|
|
|
|
|
.push(Message::UpdatePlaces(self.places.clone()))
|
2025-06-14 18:25:56 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn confirm_deletion(&mut self) {
|
|
|
|
|
if let Some(Some(id)) = self
|
|
|
|
|
.selected_place
|
|
|
|
|
.selected()
|
|
|
|
|
.map(|index| self.places.get(index).map(|p| p.id))
|
|
|
|
|
{
|
|
|
|
|
self.confirmation = Some(ConfirmationStatus::Deletion(id))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-22 20:02:39 -04:00
|
|
|
pub fn start_save(&mut self) {
|
|
|
|
|
if let Some(Some(id)) = self
|
|
|
|
|
.selected_place
|
|
|
|
|
.selected()
|
|
|
|
|
.map(|index| self.places.get(index).map(|p| p.id))
|
|
|
|
|
{
|
|
|
|
|
self.ui_messages.push(Message::SavePlace(id));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-22 01:25:11 -04:00
|
|
|
pub fn confirm_save(&mut self, place: Place) {
|
|
|
|
|
self.confirmation = Some(ConfirmationStatus::Save(place));
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-14 18:25:56 -04:00
|
|
|
pub fn cancel_confirmation(&mut self) {
|
|
|
|
|
self.confirmation = None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn proceed_confirmation(&mut self) {
|
|
|
|
|
let Some(confirmation) = &self.confirmation else {
|
|
|
|
|
return;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
match confirmation {
|
|
|
|
|
ConfirmationStatus::Deletion(id) => {
|
|
|
|
|
if let Err(err) = self.places_repository.delete_place(*id).await {
|
|
|
|
|
tracing::error!("{err}");
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-06-22 01:25:11 -04:00
|
|
|
ConfirmationStatus::Save(place) => {
|
|
|
|
|
if let Err(err) = self.places_repository.update_place(place.clone()).await {
|
|
|
|
|
tracing::error!("{err}");
|
|
|
|
|
}
|
2025-06-22 20:02:39 -04:00
|
|
|
self.mode = Mode::List;
|
|
|
|
|
self.push_mode_change();
|
2025-06-22 01:25:11 -04:00
|
|
|
}
|
2025-06-14 18:25:56 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.confirmation = None;
|
|
|
|
|
self.places_status = DataStatus::Old;
|
|
|
|
|
}
|
|
|
|
|
}
|