From 7e488e22a2ef907085f149d36d1bf605a659686d Mon Sep 17 00:00:00 2001 From: Luc Date: Tue, 26 Nov 2024 20:13:14 +0100 Subject: [PATCH] Introduce user profile entry by id --- engine/src/routes/mod.rs | 4 +++- engine/src/routes/users/mod.rs | 20 ++++++++++++++++++ web/src/api/user.ts | 33 ++++++++++++++++++++++++++++++ web/src/components/UserProfile.tsx | 11 ++++++---- 4 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 engine/src/routes/users/mod.rs create mode 100644 web/src/api/user.ts diff --git a/engine/src/routes/mod.rs b/engine/src/routes/mod.rs index ca4a65b..b2e9b4b 100644 --- a/engine/src/routes/mod.rs +++ b/engine/src/routes/mod.rs @@ -7,6 +7,7 @@ use poem::{ use poem_openapi::{OpenApi, OpenApiService}; use root::RootApi; use sessions::ApiSessions; +use users::ApiUserById; use crate::state::AppState; @@ -15,9 +16,10 @@ pub mod oauth; pub mod properties; pub mod root; pub mod sessions; +pub mod users; fn get_api() -> impl OpenApi { - (RootApi, ApiMe, ApiSessions) + (RootApi, ApiMe, ApiSessions, ApiUserById) } #[handler] diff --git a/engine/src/routes/users/mod.rs b/engine/src/routes/users/mod.rs new file mode 100644 index 0000000..f0671e3 --- /dev/null +++ b/engine/src/routes/users/mod.rs @@ -0,0 +1,20 @@ +use std::sync::Arc; + +use poem::web::{Data, Path}; +use poem_openapi::{payload::Json, OpenApi}; + +use crate::{models::user_data::{User, UserEntry}, state::AppState}; + +pub struct ApiUserById; + +#[OpenApi] +impl ApiUserById { + #[oai(path = "/user/:id", method = "get")] + pub async fn user(&self, state: Data<&Arc>, id: Path) -> Json { + let user = UserEntry::get_by_id(id.0, &state.database) + .await + .unwrap(); + + Json(user.into()) + } +} diff --git a/web/src/api/user.ts b/web/src/api/user.ts new file mode 100644 index 0000000..b21da62 --- /dev/null +++ b/web/src/api/user.ts @@ -0,0 +1,33 @@ +import { useHttp } from './core'; + +export type ApiUserByIdResponse = { + id: number; + oauth_sub: string; + name: string; + picture: string; + // oauth_data: { + // sub: string; + // name: string; + // given_name: string; + // family_name: string; + // middle_name: null; + // nickname: null; + // preferred_username: null; + // profile: null; + // picture: string; + // website: null; + // email: string; + // email_verified: boolean; + // gender: null; + // birthdate: null; + // zoneinfo: null; + // locale: null; + // phone_number: null; + // phone_number_verified: boolean; + // address: null; + // updated_at: null; + // }; +}; + +export const useApiUserById = (user_id: string) => + useHttp(`/api/user/${user_id}`); diff --git a/web/src/components/UserProfile.tsx b/web/src/components/UserProfile.tsx index 8155d82..f85b30c 100644 --- a/web/src/components/UserProfile.tsx +++ b/web/src/components/UserProfile.tsx @@ -6,6 +6,7 @@ import { FC } from 'react'; import { match } from 'ts-pattern'; import { ApiMeResponse, useApiMe } from '../api/me'; +import { useApiUserById } from '../api/user'; type Properties = { user_id: string; @@ -42,7 +43,7 @@ export const AvatarHolder: FC<{ )} delayMs={600} > - {initials || 'JD'} + {initials || 'X'} ); @@ -96,8 +97,10 @@ export const getInitials = (name?: string) => { .join(''); }; +const UNKNOWN_USER = 'Unknown User'; + export const UserProfile: FC = ({ user_id, variant }) => { - const { data: user } = useApiMe(); // temporarily use current user instead of target user_id + const { data: user } = useApiUserById(user_id); return (
@@ -131,7 +134,7 @@ export const UserProfile: FC = ({ user_id, variant }) => { size="compact" /> - {user?.name} + {user?.name || UNKNOWN_USER} @@ -151,7 +154,7 @@ export const UserProfile: FC = ({ user_id, variant }) => { />
- {user?.name} + {user?.name || UNKNOWN_USER}
#{user?.id}