clickable htmx button for adding search results to your list
This commit is contained in:
parent
1c304e1184
commit
c4976a3efc
4 changed files with 55 additions and 56 deletions
|
@ -8,7 +8,7 @@ table {
|
|||
}
|
||||
|
||||
th {
|
||||
background-color: darkgray;
|
||||
background-color: ghostwhite;
|
||||
}
|
||||
|
||||
th, td {
|
||||
|
@ -16,7 +16,7 @@ th, td {
|
|||
padding: 8px;
|
||||
}
|
||||
|
||||
tr:nth-child(odd) {background-color: ghostwhite;}
|
||||
tr:nth-child(even) {background-color: ghostwhite;}
|
||||
|
||||
#header {
|
||||
text-align: end;
|
||||
|
|
|
@ -3,6 +3,7 @@ use axum::{
|
|||
http::StatusCode,
|
||||
response::{IntoResponse, Redirect, Response},
|
||||
};
|
||||
use http::HeaderValue;
|
||||
use julid::Julid;
|
||||
use serde::Deserialize;
|
||||
use sqlx::{query, query_as, query_scalar, SqlitePool};
|
||||
|
@ -37,22 +38,22 @@ const EMPTY_SEARCH_QUERY_STRUCT: SearchQuery = SearchQuery {
|
|||
//-************************************************************************
|
||||
|
||||
#[Error]
|
||||
pub struct WatchAddError(#[from] WatchAddErrorKind);
|
||||
pub struct AddError(#[from] AddErrorKind);
|
||||
|
||||
#[Error]
|
||||
#[non_exhaustive]
|
||||
pub enum WatchAddErrorKind {
|
||||
pub enum AddErrorKind {
|
||||
UnknownDBError,
|
||||
NotSignedIn,
|
||||
}
|
||||
|
||||
impl IntoResponse for WatchAddError {
|
||||
impl IntoResponse for AddError {
|
||||
fn into_response(self) -> Response {
|
||||
match &self.0 {
|
||||
WatchAddErrorKind::UnknownDBError => {
|
||||
AddErrorKind::UnknownDBError => {
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, format!("{self}")).into_response()
|
||||
}
|
||||
WatchAddErrorKind::NotSignedIn => (
|
||||
AddErrorKind::NotSignedIn => (
|
||||
StatusCode::OK,
|
||||
"Ope, you need to sign in first!".to_string(),
|
||||
)
|
||||
|
@ -94,7 +95,7 @@ pub struct PostAddNewWatch {
|
|||
|
||||
#[derive(Debug, Default, Deserialize, PartialEq, Eq)]
|
||||
pub struct PostAddExistingWatch {
|
||||
pub id: String,
|
||||
pub watch: String,
|
||||
pub public: bool,
|
||||
pub watched_already: bool,
|
||||
}
|
||||
|
@ -107,18 +108,12 @@ pub async fn get_add_new_watch(auth: AuthSession) -> impl IntoResponse {
|
|||
AddNewWatchPage { user: auth.user }
|
||||
}
|
||||
|
||||
struct QuestQuest {
|
||||
pub user: Julid,
|
||||
pub is_public: bool,
|
||||
pub already_watched: bool,
|
||||
}
|
||||
|
||||
/// Add a Watch to your watchlist (side effects system-add)
|
||||
pub async fn post_add_new_watch(
|
||||
auth: AuthSession,
|
||||
State(pool): State<SqlitePool>,
|
||||
Form(form): Form<PostAddNewWatch>,
|
||||
) -> Result<impl IntoResponse, WatchAddError> {
|
||||
) -> Result<impl IntoResponse, AddError> {
|
||||
if let Some(user) = auth.user {
|
||||
{
|
||||
let release_date = year_to_epoch(form.year.as_deref());
|
||||
|
@ -130,31 +125,27 @@ pub async fn post_add_new_watch(
|
|||
added_by: user.id,
|
||||
..Default::default()
|
||||
};
|
||||
let quest = QuestQuest {
|
||||
|
||||
let watch_id = add_new_watch_impl(&pool, &watch).await?;
|
||||
let quest = WatchQuest {
|
||||
user: user.id,
|
||||
is_public: !form.private,
|
||||
already_watched: form.watched_already,
|
||||
watch: watch_id,
|
||||
};
|
||||
|
||||
let watch_id = add_new_watch_impl(&pool, &watch, Some(quest)).await?;
|
||||
add_watch_quest_impl(&pool, &quest)
|
||||
.await
|
||||
.map_err(|_| AddErrorKind::UnknownDBError)?;
|
||||
|
||||
let location = format!("/watch/{watch_id}");
|
||||
Ok(Redirect::to(&location))
|
||||
}
|
||||
} else {
|
||||
Err(WatchAddErrorKind::NotSignedIn.into())
|
||||
Err(AddErrorKind::NotSignedIn.into())
|
||||
}
|
||||
}
|
||||
|
||||
async fn add_new_watch_impl(
|
||||
db_pool: &SqlitePool,
|
||||
watch: &Watch,
|
||||
quest: Option<QuestQuest>,
|
||||
) -> Result<Julid, WatchAddError> {
|
||||
let mut tx = db_pool
|
||||
.begin()
|
||||
.await
|
||||
.map_err(|_| WatchAddErrorKind::UnknownDBError)?;
|
||||
async fn add_new_watch_impl(db_pool: &SqlitePool, watch: &Watch) -> Result<Julid, AddError> {
|
||||
let watch_id: Julid = query_scalar(ADD_WATCH_QUERY)
|
||||
.bind(&watch.title)
|
||||
.bind(watch.kind)
|
||||
|
@ -162,44 +153,43 @@ async fn add_new_watch_impl(
|
|||
.bind(&watch.metadata_url)
|
||||
.bind(watch.added_by)
|
||||
.bind(watch.length)
|
||||
.fetch_one(&mut *tx)
|
||||
.fetch_one(db_pool)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
tracing::error!("Got error: {err}");
|
||||
WatchAddErrorKind::UnknownDBError
|
||||
AddErrorKind::UnknownDBError
|
||||
})?;
|
||||
|
||||
if let Some(quest) = quest {
|
||||
query(ADD_WATCH_QUEST_QUERY)
|
||||
.bind(quest.user)
|
||||
.bind(watch_id)
|
||||
.bind(quest.is_public)
|
||||
.bind(quest.already_watched)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
tracing::error!("Got error: {err}");
|
||||
WatchAddErrorKind::UnknownDBError
|
||||
})?;
|
||||
}
|
||||
tx.commit().await.map_err(|err| {
|
||||
tracing::error!("Got error: {err}");
|
||||
WatchAddErrorKind::UnknownDBError
|
||||
})?;
|
||||
|
||||
Ok(watch_id)
|
||||
}
|
||||
|
||||
/// Add a Watch to your watchlist by selecting it with a checkbox
|
||||
pub async fn post_add_watch_quest(
|
||||
_auth: AuthSession,
|
||||
State(_pool): State<SqlitePool>,
|
||||
Form(_form): Form<PostAddExistingWatch>,
|
||||
) -> impl IntoResponse {
|
||||
todo!()
|
||||
auth: AuthSession,
|
||||
State(pool): State<SqlitePool>,
|
||||
Form(form): Form<PostAddExistingWatch>,
|
||||
) -> Result<impl IntoResponse, AddError> {
|
||||
if let Some(user) = auth.user {
|
||||
let quest = WatchQuest {
|
||||
user: user.id,
|
||||
watch: Julid::from_string(&form.watch).unwrap(),
|
||||
is_public: form.public,
|
||||
already_watched: form.watched_already,
|
||||
};
|
||||
add_watch_quest_impl(&pool, &quest)
|
||||
.await
|
||||
.map_err(|_| AddErrorKind::UnknownDBError)?;
|
||||
let resp = "<style=\"background-color:green\">✓</style>";
|
||||
Ok(resp.into_response())
|
||||
} else {
|
||||
let resp = Redirect::to("/login");
|
||||
let mut resp = resp.into_response();
|
||||
resp.headers_mut()
|
||||
.insert("HX-Redirect", HeaderValue::from_str("/login").unwrap());
|
||||
Ok(resp)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn _add_watch_quest_impl(pool: &SqlitePool, quest: &WatchQuest) -> Result<(), ()> {
|
||||
pub async fn add_watch_quest_impl(pool: &SqlitePool, quest: &WatchQuest) -> Result<(), ()> {
|
||||
query(ADD_WATCH_QUEST_QUERY)
|
||||
.bind(quest.user)
|
||||
.bind(quest.watch)
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{% when None %} <!-- this is for the `when` statement -->
|
||||
{% when None %}
|
||||
<div class="header_logged_out">
|
||||
<a href="/login">log in</a> or <a href="/signup">sign up</a>?
|
||||
</div>
|
||||
|
|
|
@ -2,4 +2,13 @@
|
|||
<td><span class="watchtitle">{{watch.title}}</span></td>
|
||||
<td>{{watch.kind}}</td>
|
||||
<td> {% call m::get_or_default(watch.year(), "when??") -%}</td>
|
||||
<td>
|
||||
<form id="add-watch-{{watch.id}}">
|
||||
<input type="hidden" name="watch" value="{{watch.id}}">
|
||||
<input type="hidden" name="public" value="true">
|
||||
<input type="hidden" name="watched_already" value="false">
|
||||
<button hx-post="/add/watch" hx-target="#add-watch-{{watch.id}}" hx-trigger="click"
|
||||
hx-swap="OuterHTML">wanna watch?</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
Loading…
Reference in a new issue