simple-web-app

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

user.rs (3619B)


      1 use askama::Template;
      2 use axum::{
      3     extract::{Path, Query, State},
      4     response::Html,
      5 };
      6 use axum_extra::extract::cookie::CookieJar;
      7 use serde::Deserialize;
      8 
      9 use crate::database::{CommentWithMeta, StoryWithMeta, UserProfile};
     10 use crate::database::{self, TARGET_TYPE_STORY};
     11 use crate::error::AppError;
     12 use crate::state::AppState;
     13 use crate::templates::{ApplicationTemplate, UserTemplate};
     14 
     15 #[derive(Debug, Deserialize)]
     16 pub struct UserQuery {
     17     #[serde(default = "default_tab")]
     18     pub tab: String,
     19 }
     20 
     21 fn default_tab() -> String {
     22     "submissions".to_string()
     23 }
     24 
     25 pub async fn show_user(
     26     State(state): State<AppState>,
     27     jar: CookieJar,
     28     Path(username): Path<String>,
     29     Query(query): Query<UserQuery>,
     30 ) -> Result<Html<String>, AppError> {
     31     let current_user_id = state.get_user_id(&jar).await;
     32     let tab = query.tab.clone();
     33     let username_clone = username.clone();
     34 
     35     let db = state.db();
     36     // Get user by username
     37     let user = db.get_user_by_username(&username_clone).await?
     38         .ok_or_else(|| AppError::NotFound(format!("User '{}' not found", username_clone)))?;
     39     let profile: UserProfile = user.into();
     40 
     41     let mut submissions: Vec<StoryWithMeta> = Vec::new();
     42     let mut comments: Vec<CommentWithMeta> = Vec::new();
     43 
     44     let user_id_num: i64 = profile.user_id.parse().unwrap_or(0);
     45 
     46     match tab.as_str() {
     47         "submissions" => {
     48             let stories = db.get_stories_by_user(user_id_num, 30, 0).await?;
     49 
     50             let story_ids: Vec<i64> = stories.iter().map(|s| s.id).collect();
     51             let voted_ids = if let Some(uid) = current_user_id {
     52                 if !story_ids.is_empty() {
     53                     db.get_user_votes(uid, TARGET_TYPE_STORY, &story_ids)
     54                         .await
     55                         .unwrap_or_default()
     56                 } else {
     57                     vec![]
     58                 }
     59             } else {
     60                 vec![]
     61             };
     62 
     63             // Batch fetch tags
     64             let meta = db.enrich_stories(&story_ids).await.unwrap_or_default();
     65 
     66             for (idx, story) in stories.into_iter().enumerate() {
     67                 let story_meta = meta.iter().find(|m| m.story_id == story.id);
     68                 let tags = story_meta
     69                     .map(|m| m.tags.iter().map(|name| database::Category { id: 0, name: Some(name.clone()) }).collect())
     70                     .unwrap_or_default();
     71                 let time_ago = database::time_ago(story.published);
     72                 let user_voted = voted_ids.contains(&story.id);
     73 
     74                 submissions.push(StoryWithMeta::from_story(
     75                     story,
     76                     tags,
     77                     Some(profile.username.clone()),
     78                     time_ago,
     79                     user_voted,
     80                     idx + 1,
     81                 ));
     82             }
     83         }
     84         "comments" => {
     85             let user_comments = db.get_comments_by_user(user_id_num, 30, 0).await?;
     86 
     87             for comment in user_comments {
     88                 let time_ago = database::time_ago(comment.created_at);
     89                 comments.push(CommentWithMeta::from_comment(
     90                     comment,
     91                     Some(profile.username.clone()),
     92                     time_ago,
     93                     false,
     94                 ));
     95             }
     96         }
     97         _ => {}
     98     }
     99 
    100     let is_logged_in = current_user_id.is_some();
    101 
    102     let user_template = UserTemplate {
    103         profile,
    104         submissions,
    105         comments,
    106         tab: query.tab,
    107         is_logged_in,
    108     };
    109 
    110     let app = ApplicationTemplate {
    111         content: user_template.render()?,
    112     };
    113     Ok(Html(app.render()?))
    114 }