simple-web-app

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

vote.rs (1928B)


      1 use askama::Template;
      2 use axum::{
      3     extract::{Path, State},
      4     response::Response,
      5 };
      6 use axum_extra::extract::cookie::CookieJar;
      7 
      8 use crate::database::{TARGET_TYPE_COMMENT, TARGET_TYPE_STORY};
      9 use crate::error::AppError;
     10 use crate::sse;
     11 use crate::state::AppState;
     12 use crate::templates::VoteButtonTemplate;
     13 
     14 fn render_vote_response(
     15     target_type: &str,
     16     target_id: i64,
     17     score: i64,
     18     voted: bool,
     19 ) -> Result<Response, AppError> {
     20     let template = VoteButtonTemplate {
     21         target_type,
     22         target_id,
     23         score,
     24         voted,
     25     };
     26     let button_html = template.render()?;
     27 
     28     let score_class = if target_type == "comment" { "comment-score" } else { "story-score" };
     29     let score_html = format!(
     30         "<span class=\"{score_class}\" id=\"score-{target_type}-{target_id}\">{score} point{}</span>",
     31         if score == 1 { "" } else { "s" }
     32     );
     33 
     34     Ok(sse::patch_multiple(&[&button_html, &score_html]))
     35 }
     36 
     37 /// Vote on a story (Datastar endpoint)
     38 pub async fn vote_story(
     39     State(state): State<AppState>,
     40     jar: CookieJar,
     41     Path(story_id): Path<i64>,
     42 ) -> Result<Response, AppError> {
     43     let user_id = state.get_user_id(&jar).await
     44         .ok_or_else(|| AppError::Unauthorized("Login required to vote".to_string()))?;
     45 
     46     let (voted, new_score) = state.db().toggle_vote(user_id, TARGET_TYPE_STORY, story_id).await?;
     47 
     48     render_vote_response("story", story_id, new_score, voted)
     49 }
     50 
     51 /// Vote on a comment (Datastar endpoint)
     52 pub async fn vote_comment(
     53     State(state): State<AppState>,
     54     jar: CookieJar,
     55     Path(comment_id): Path<i64>,
     56 ) -> Result<Response, AppError> {
     57     let user_id = state.get_user_id(&jar).await
     58         .ok_or_else(|| AppError::Unauthorized("Login required to vote".to_string()))?;
     59 
     60     let (voted, new_score) = state.db().toggle_vote(user_id, TARGET_TYPE_COMMENT, comment_id).await?;
     61 
     62     render_vote_response("comment", comment_id, new_score, voted)
     63 }