diff --git a/src/lib.rs b/src/lib.rs index 6107bb5..69953cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,8 +52,8 @@ pub async fn app(db_pool: sqlx::SqlitePool) -> IntoMakeService { use signup::handlers::{get_create_user, get_signup_success, post_create_user}; use tower_http::services::ServeDir; use watches::handlers::{ - get_add_new_watch, get_watch, get_watch_status, get_watches, post_add_new_watch, - post_add_watch_quest, + edit_watch_quest, get_add_new_watch, get_watch, get_watch_status, get_watches, + post_add_new_watch, post_add_watch_quest, }; let conf = crate::conf::Config::get(); @@ -80,6 +80,7 @@ pub async fn app(db_pool: sqlx::SqlitePool) -> IntoMakeService { .route("/watch", get(get_watch)) .route("/watch/:watch", get(get_watch)) .route("/watch/status/:watch", get(get_watch_status)) + .route("/quest/edit", post(edit_watch_quest)) .route("/title-search", get(get_search_watch)) .route("/add", get(get_add_new_watch).post(post_add_new_watch)) .route( diff --git a/src/watches/handlers.rs b/src/watches/handlers.rs index 619597e..d7b13cf 100644 --- a/src/watches/handlers.rs +++ b/src/watches/handlers.rs @@ -57,6 +57,33 @@ impl IntoResponse for AddError { } } +#[Error] +pub struct EditError(#[from] EditErrorKind); + +#[Error] +#[non_exhaustive] +pub enum EditErrorKind { + UnknownDBError, + NotSignedIn, + NotFound, +} + +impl IntoResponse for EditError { + fn into_response(self) -> Response { + match &self.0 { + EditErrorKind::UnknownDBError => { + (StatusCode::INTERNAL_SERVER_ERROR, format!("{self}")).into_response() + } + EditErrorKind::NotSignedIn => ( + StatusCode::OK, + "Ope, you need to sign in first!".to_string(), + ) + .into_response(), + EditErrorKind::NotFound => (StatusCode::OK, "Could not find watch").into_response(), + } + } +} + //-************************************************************************ // Types for receiving arguments from forms //-************************************************************************ @@ -82,6 +109,12 @@ pub struct PostAddExistingWatch { pub public: bool, } +#[derive(Debug, Default, Deserialize, PartialEq, Eq)] +pub struct PostEditQuest { + pub watch: String, + pub act: String, +} + //-************************************************************************ // handlers //-************************************************************************ @@ -184,6 +217,110 @@ pub async fn add_watch_quest_impl(pool: &SqlitePool, quest: &WatchQuest) -> Resu Ok(()) } +#[axum::debug_handler] +pub async fn edit_watch_quest( + auth: AuthSession, + State(pool): State, + Form(form): Form, +) -> Result { + if let Some(user) = auth.user { + let watch = Julid::from_str(form.watch.trim()).map_err(|_| EditErrorKind::NotFound)?; + Ok( + edit_watch_quest_impl(&pool, form.act.trim(), user.id, watch) + .await? + .into_response(), + ) + } else { + // todo: return editerror that prompts a login + let resp = Redirect::to("/login"); + let mut resp = resp.into_response(); + resp.headers_mut() + .insert("HX-Redirect", HeaderValue::from_str("/login").unwrap()); + Ok(resp.into_response()) + } +} + +async fn edit_watch_quest_impl( + pool: &SqlitePool, + action: &str, + user: Julid, + watch: Julid, +) -> Result { + let quest: Option = query_as(GET_QUEST_QUERY) + .bind(user) + .bind(watch) + .fetch_optional(pool) + .await + .map_err(|e| { + tracing::error!("Got error from checking watch status: {e:?}"); + EditErrorKind::UnknownDBError + })?; + if let Some(quest) = quest { + match action { + "remove" => { + sqlx::query!( + "delete from watch_quests where user = ? and watch = ?", + user, + watch + ) + .execute(pool) + .await + .map_err(|e| { + tracing::error!("Error removing quest: {e}"); + EditErrorKind::UnknownDBError + })?; + Ok(WatchStatusMenus { watch, quest: None }) + } + "watched" => { + let watched = !quest.watched; + sqlx::query!( + "update watch_quests set watched = ? where user = ? and watch = ?", + watched, + user, + watch + ) + .execute(pool) + .await + .map_err(|e| { + tracing::error!("Error updating quest: {e}"); + EditErrorKind::UnknownDBError + })?; + let quest = WatchQuest { watched, ..quest }; + Ok(WatchStatusMenus { + watch, + quest: Some(quest), + }) + } + "viz" => { + let public = !quest.public; + sqlx::query!( + "update watch_quests set public = ? where user = ? and watch = ?", + public, + user, + watch + ) + .execute(pool) + .await + .map_err(|e| { + tracing::error!("Error updating quest: {e}"); + EditErrorKind::UnknownDBError + })?; + let quest = WatchQuest { public, ..quest }; + Ok(WatchStatusMenus { + watch, + quest: Some(quest), + }) + } + _ => Ok(WatchStatusMenus { + watch, + quest: Some(quest), + }), + } + } else { + Err(EditErrorKind::NotFound) + } +} + /// A single Watch pub async fn get_watch( auth: AuthSession, diff --git a/templates/elements/add_watch_button.html b/templates/elements/add_watch_button.html index f9edb07..5c86c62 100644 --- a/templates/elements/add_watch_button.html +++ b/templates/elements/add_watch_button.html @@ -1,43 +1,51 @@ {% match quest %} {% when Some with (q) %} -{% let public %} +{% let viz %} {% let np %} {% if q.public -%} -{% let public = "public" %} +{% let viz = "public" %} {% let np = "private" %} {% else %} -{% let public = "private" %} +{% let viz = "private" %} {% let np = "public" %} {%- endif %} {% let status %} {% if q.watched -%} -{% let status = "want to watch" %} -{% else %} {% let status = "watched" %} +{% else %} +{% let status = "want to watch" %} {% endif %} - - + +
Added{{- public -}}{{- status -}}{{- viz -}}
- + {% else %} + + + + {% endif %}
- +