diff --git a/src/lib.rs b/src/lib.rs index a8a2157..c07ca09 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,8 @@ use templates::*; use users::User; use watches::{templates::*, ShowKind, Watch}; +use crate::watches::handlers::get_watch; + type AuthContext = axum_login::extractors::AuthContext>; @@ -47,6 +49,8 @@ pub async fn app(db_pool: sqlx::SqlitePool, session_secret: &[u8]) -> axum::Rout .route("/login", get(get_login).post(post_login)) .route("/logout", get(get_logout).post(post_logout)) .route("/watches", get(get_watches)) + .route("/watch", get(get_watch)) + .route("/watch/:id", get(get_watch)) .route("/search", get(get_search_watch).post(post_search_watch)) .route( "/add", diff --git a/src/watches/handlers.rs b/src/watches/handlers.rs index 245b761..d220ee5 100644 --- a/src/watches/handlers.rs +++ b/src/watches/handlers.rs @@ -1,5 +1,5 @@ use axum::{ - extract::{Form, Query, State}, + extract::{Form, Path, Query, State}, http::StatusCode, response::{IntoResponse, Response}, }; @@ -7,7 +7,7 @@ use serde::Deserialize; use sqlx::{query_as, SqlitePool}; use uuid::Uuid; -use super::templates::GetSearchWatches; +use super::templates::{GetSearchWatches, GetWatch}; use crate::{AuthContext, GetWatches, ShowKind, User, Watch}; //-************************************************************************ @@ -17,6 +17,8 @@ use crate::{AuthContext, GetWatches, ShowKind, User, Watch}; const GET_WATCHES_QUERY: &str = "select * from watches left join witch_watch on $1 = witch_watch.witch and watches.id = witch_watch.watch"; +const GET_WATCH_QUERY: &str = "select * from watches where id = $1"; + //-************************************************************************ // Error types for Watch creation //-************************************************************************ @@ -40,11 +42,34 @@ impl IntoResponse for WatchAddError { } } +//-************************************************************************ +// Types for receiving arguments from search queries +//-************************************************************************ + #[derive(Debug, Default, Clone, Deserialize)] pub struct SimpleSearchQuery { search: String, } +#[derive(Debug, Default, Clone, Deserialize)] +pub struct FullSearchQuery { + pub title: Option, + pub kind: Option, + pub year: Option, +} + +#[derive(Debug, Clone, Deserialize)] +pub enum SearchQuery { + Full(FullSearchQuery), + Simple(SimpleSearchQuery), +} + +impl Default for SearchQuery { + fn default() -> Self { + SearchQuery::Simple(SimpleSearchQuery::default()) + } +} + //-************************************************************************ // handlers //-************************************************************************ @@ -56,12 +81,34 @@ pub async fn put_add_watch() {} pub async fn post_add_watch() {} /// A single Watch -pub async fn get_watch() {} +pub async fn get_watch( + auth: AuthContext, + watch: Option>, + State(pool): State, +) -> impl IntoResponse { + let id = if let Some(Path(id)) = watch { + id + } else { + "".to_string() + }; + let id = id.trim(); + + let watch: Option = query_as(GET_WATCH_QUERY) + .bind(id) + .fetch_one(&pool) + .await + .ok(); + + GetWatch { + watch, + user: auth.current_user, + } +} /// everything the user has saved pub async fn get_watches(auth: AuthContext, State(pool): State) -> impl IntoResponse { - let user = &auth.current_user; - let watches: Vec = if user.is_some() { + let user = auth.current_user; + let watches: Vec = if (user).is_some() { query_as(GET_WATCHES_QUERY) .bind(user.as_ref().unwrap().id) .fetch_all(&pool) @@ -71,23 +118,27 @@ pub async fn get_watches(auth: AuthContext, State(pool): State) -> i vec![] }; - GetWatches { - watches, - user: user.clone(), - } + GetWatches { watches, user } } pub async fn get_search_watch( auth: AuthContext, State(_pool): State, - search: Option>, + search: Option>, ) -> impl IntoResponse { + use SearchQuery::*; let search = match search { - Some(Query(SimpleSearchQuery { search })) => search, + Some(Query(Simple(SimpleSearchQuery { search }))) => search, + Some(Query(Full(q))) => { + // obviously this is dumb + format!("{q:?}") + } None => "".to_owned(), }; let search = search.trim().to_string(); + let user = auth.current_user; + GetSearchWatches { watches: vec![], user, diff --git a/src/watches/templates.rs b/src/watches/templates.rs index b60e0d3..1f4525d 100644 --- a/src/watches/templates.rs +++ b/src/watches/templates.rs @@ -17,3 +17,10 @@ pub struct GetSearchWatches { pub user: Option, pub search: String, } + +#[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq, OptionalOptionalUser)] +#[template(path = "get_watch.html")] +pub struct GetWatch { + pub watch: Option, + pub user: Option, +} diff --git a/templates/get_watch.html b/templates/get_watch.html new file mode 100644 index 0000000..4af344f --- /dev/null +++ b/templates/get_watch.html @@ -0,0 +1,33 @@ +{% extends "base.html" %} +{% import "macros.html" as m %} + +{% block title %}Welcome to Witch Watch, Bish{% endblock %} + +{% block content %} + +

Whatcha Watchin?

+ +{% match watch %} + +{% when Some with (watch) %} + +
+ {{watch.title}} -- {% call m::get_or_default(watch.release_date, "when??") %} +
+ +{% else %} + +
Sorry, maybe you meant to search for something?
+ +{% endmatch %} + + +

+

+ +
+ +
+

+ +{% endblock %}