use askama_axum::{IntoResponse, Response, Template}; use axum::{extract::{Path, State}, response::Redirect, Extension, Form}; use axum_extra::response::Html; use chrono::Utc; use http::StatusCode; use serde::Deserialize; use sqlx::{SqlitePool, Row}; use crate::{middlewares::is_authorized, user::{get_user_roles_display, get_user_wishlist_items, UserData, UserWishlistItem}}; struct HtmlTemplate(T); impl IntoResponse for HtmlTemplate where T: Template, { fn into_response(self) -> Response { match self.0.render() { Ok(html) => Html(html).into_response(), Err(err) => ( StatusCode::INTERNAL_SERVER_ERROR, format!("Failed to render template. Error: {}", err), ) .into_response(), } } } #[derive(Template)] #[template(path = "userwishlists.html")] struct WishListsTemplate { logged_in: bool, name: String, user_roles: Vec, users: Vec, } pub async fn wishlists( Extension(user_data): Extension>, State(db_pool): State, ) -> impl IntoResponse { let user_name = user_data.as_ref().map(|s| s.name.clone()); let logged_in = user_name.is_some(); let name = user_name.unwrap_or_default(); let users = sqlx::query_as::<_, UserData>("SELECT * FROM users") .fetch_all(&db_pool) .await .unwrap(); let userid = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default(); if is_authorized("/userwishlists", user_data, db_pool.clone()).await { // Get user roles let user_roles = get_user_roles_display(userid, &db_pool.clone()).await; let template = WishListsTemplate { logged_in, name, users, user_roles, }; HtmlTemplate(template).into_response() } else { Redirect::to("/").into_response() } } #[derive(Template)] #[template(path = "userwishlist.html")] struct UserWishListTemplate { logged_in: bool, name: String, my_wishlist: bool, user: UserData, user_roles: Vec, user_wishlist_items: Vec, } pub async fn user_wishlist( Path(user_id): Path, State(db_pool): State, Extension(user_data): Extension>, ) -> impl IntoResponse { // Extract the user's name from the user data. let user_name = user_data.as_ref().map(|s| s.name.clone()); let logged_in = user_data.is_some(); let name = user_name.unwrap_or_default(); // Extract the user's id from the user data let user_userid = user_data.as_ref().map(|s| s.id.clone()); let userid = user_userid.unwrap_or_default(); // Extract the user data. let user = sqlx::query_as!(UserData, "SELECT * FROM users WHERE id = ?", user_id) .fetch_one(&db_pool) .await .unwrap(); if is_authorized("/wishlist", user_data, db_pool.clone()).await { // Get user roles let user_roles = get_user_roles_display(userid, &db_pool.clone()).await; // Get user wishlist let user_wishlist_items = get_user_wishlist_items(user_id, &db_pool.clone()).await; // Is viewed and viewing user the same (my wishlist)? let my_wishlist = user_id == userid; // Create the wishlist template. let template = UserWishListTemplate { logged_in, name, my_wishlist, user: user, user_roles, user_wishlist_items, }; return HtmlTemplate(template).into_response(); } else { Redirect::to("/").into_response() } } #[derive(Template)] #[template(path = "userwishlistadd.html")] struct UserWishListAddTemplate { logged_in: bool, name: String, user: UserData, user_roles: Vec, user_wishlist_items: Vec, } pub async fn user_wishlist_add( Path(user_id): Path, State(db_pool): State, Extension(user_data): Extension>, ) -> impl IntoResponse { // Extract the user's name from the user data. let user_name = user_data.as_ref().map(|s| s.name.clone()); let logged_in = user_data.is_some(); let name = user_name.unwrap_or_default(); // Extract the user data. let user = sqlx::query_as!(UserData, "SELECT * FROM users WHERE id = ?", user_id) .fetch_one(&db_pool) .await .unwrap(); let userid = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default(); if is_authorized("/wishlist", user_data, db_pool.clone()).await { // Get user roles let user_roles = get_user_roles_display(userid, &db_pool.clone()).await; // Get user wishlist items let user_wishlist_items = get_user_wishlist_items(user_id, &db_pool.clone()).await; // Create the wishlist template. let template = UserWishListAddTemplate { logged_in, name, user: user, user_roles, user_wishlist_items, }; return HtmlTemplate(template).into_response(); } else { Redirect::to("/").into_response() } } #[derive(Deserialize, Debug)] pub struct ItemForm { item: String, item_url: String, } pub async fn user_wishlist_add_item( Path(user_id): Path, State(db_pool): State, Extension(user_data): Extension>, Form(item_form): Form ) -> impl IntoResponse { if is_authorized("/wishlist", user_data.clone(), db_pool.clone()).await { // Insert new item to database let now = Utc::now().timestamp(); sqlx::query("insert into wishlist_items (created_at, created_by, updated_at, updated_by, user_id, item, item_url) values (?, ?, ?, ?, ?, ?, ?)") .bind(now)// Created now .bind(user_data.as_ref().unwrap().id)// Created by current user .bind(now) // Updated now .bind(user_data.as_ref().unwrap().id) // Updated by current user .bind(user_id) .bind(item_form.item) .bind(item_form.item_url) .execute(&db_pool) .await .unwrap(); let redirect_string = format!("/userwishlist/{user_id}"); Redirect::to(&redirect_string).into_response() } else { Redirect::to("/").into_response() } } pub async fn user_wishlist_bought_item( Path(user_id): Path, State(db_pool): State, Extension(user_data): Extension> ) -> impl IntoResponse { if is_authorized("/wishlist", user_data.clone(), db_pool.clone()).await { // Update item to purchased sqlx::query("update wishlist_items set purchased_by = ? where id = ?") .bind(user_data.as_ref().unwrap().id)// Created by current user .bind(user_id) .execute(&db_pool) .await .unwrap(); // Redirect to user wishlist // Extract the user data. let row = sqlx::query( "SELECT user_id FROM wishlist_items WHERE id = ?") .bind(user_id) .fetch_one(&db_pool) .await .unwrap(); let userid = row.get::("user_id"); let redirect_string = format!("/userwishlist/{userid}"); Redirect::to(&redirect_string).into_response() } else { Redirect::to("/").into_response() } } pub async fn user_wishlist_received_item( Path(user_id): Path, State(db_pool): State, Extension(user_data): Extension> ) -> impl IntoResponse { if is_authorized("/wishlist", user_data.clone(), db_pool.clone()).await { // Update item received time let now = Utc::now().timestamp(); sqlx::query("update wishlist_items set received_at = ? where id = ?") .bind(now)// Received now .bind(user_id) .execute(&db_pool) .await .unwrap(); // Redirect to user wishlist let userid = user_data.as_ref().unwrap().id; let redirect_string = format!("/userwishlist/{userid}"); Redirect::to(&redirect_string).into_response() } else { Redirect::to("/").into_response() } }