use maud::{html, Markup};
use uuid::Uuid;
use crate::components::crud;
use crate::components::view::{self, *};
use async_trait::async_trait;
use crate::{models::Error, sqlite, Context};
use super::Trip;
#[derive(Debug, PartialEq, Eq)]
pub enum State {
Todo,
Done,
}
impl From for State {
fn from(done: bool) -> Self {
if done {
Self::Done
} else {
Self::Todo
}
}
}
impl From for bool {
fn from(value: State) -> Self {
match value {
State::Todo => false,
State::Done => true,
}
}
}
#[derive(Debug)]
pub struct Todo {
pub id: Uuid,
pub description: String,
pub state: State,
}
struct TodoRow {
id: String,
description: String,
done: bool,
}
impl TryFrom for Todo {
type Error = Error;
fn try_from(row: TodoRow) -> Result {
Ok(Todo {
id: Uuid::try_parse(&row.id)?,
description: row.description,
state: row.done.into(),
})
}
}
#[derive(Debug)]
pub struct TodoFilter {
pub trip_id: Uuid,
}
impl Todo {
pub fn is_done(&self) -> bool {
self.state == State::Done
}
}
#[async_trait]
impl crud::Read for Todo {
type Filter = TodoFilter;
type Id = Uuid;
async fn findall(
ctx: &Context,
pool: &sqlite::Pool,
filter: TodoFilter,
) -> Result, Error> {
let trip_id_param = filter.trip_id.to_string();
let user_id = ctx.user.id.to_string();
let todos: Vec = crate::query_all!(
&sqlite::QueryClassification {
query_type: sqlite::QueryType::Select,
component: sqlite::Component::Todo,
},
pool,
TodoRow,
Todo,
r#"
SELECT
todo.id AS id,
todo.description AS description,
todo.done AS done
FROM trip_todos AS todo
INNER JOIN trips
ON trips.id = todo.trip_id
WHERE
trips.id = $1
AND trips.user_id = $2
"#,
trip_id_param,
user_id,
)
.await?;
Ok(todos)
}
#[tracing::instrument]
async fn find(
ctx: &Context,
pool: &sqlite::Pool,
filter: TodoFilter,
todo_id: Uuid,
) -> Result