Set up the landing page, which shows the user their profile

This commit is contained in:
Savanni D'Gerinel 2025-01-03 16:50:56 -05:00
parent 208083d39e
commit f59c3544b4
5 changed files with 64 additions and 20 deletions

View File

@ -1,6 +1,6 @@
use axum::{
extract::Path,
http::{header::CONTENT_TYPE, HeaderMap, Method, StatusCode},
http::{header::{AUTHORIZATION, CONTENT_TYPE}, HeaderMap, Method},
routing::{get, post, put},
Json, Router,
};
@ -8,7 +8,7 @@ use tower_http::cors::{Any, CorsLayer};
use crate::{
core::Core,
database::{SessionId, UserId},
database::UserId,
handlers::{
check_password, create_game, create_user, get_user, healthcheck, set_password,
wrap_handler, AuthRequest, CreateGameRequest, CreateUserRequest, SetPasswordRequest,
@ -34,9 +34,13 @@ pub fn routes(core: Core) -> Router {
post({
let core = core.clone();
move |req: Json<AuthRequest>| wrap_handler(|| check_password(core, req))
}).layer(
CorsLayer::new().allow_methods([Method::POST]).allow_headers([CONTENT_TYPE]).allow_origin(Any),
),
})
.layer(
CorsLayer::new()
.allow_methods([Method::POST])
.allow_headers([CONTENT_TYPE])
.allow_origin(Any),
),
)
.route(
// By default, just get the self user.
@ -45,6 +49,12 @@ pub fn routes(core: Core) -> Router {
let core = core.clone();
move |headers: HeaderMap| wrap_handler(|| get_user(core, headers, None))
})
.layer(
CorsLayer::new()
.allow_methods([Method::GET])
.allow_headers([AUTHORIZATION])
.allow_origin(Any),
)
.put({
let core = core.clone();
move |headers: HeaderMap, req: Json<CreateUserRequest>| {

View File

@ -1,4 +1,4 @@
import { SessionId } from "visions-types";
import { SessionId, UserId, UserProfile } from "visions-types";
export type PlayingField = {
backgroundImage: string;
@ -70,11 +70,29 @@ export class Client {
async auth(username: string, password: string): Promise<SessionId | undefined> {
const url = new URL(this.base);
url.pathname = `/api/v1/auth`
const response = await fetch(url, { method: 'POST', headers: [['Content-Type', 'application/json']], body: JSON.stringify({ 'username': username, 'password': password }) });
const response = await fetch(url, {
method: 'POST',
headers: [['Content-Type', 'application/json']],
body: JSON.stringify({ 'username': username, 'password': password })
});
const session_id: SessionId = await response.json();
return session_id;
}
async profile(sessionId: SessionId, userId: UserId | undefined): Promise<UserProfile | undefined> {
const url = new URL(this.base);
if (userId) {
url.pathname = `/api/v1/user${userId}`
} else {
url.pathname = `/api/v1/user`
}
const response = await fetch(url, {
method: 'GET',
headers: [['Authorization', `Bearer ${sessionId}`]],
});
return await response.json()
}
async health() {
const url = new URL(this.base);
url.pathname = `/api/v1/health`;

View File

@ -1,10 +1,12 @@
import React from 'react';
import { Client } from '../../client';
import { UserProfile } from 'visions-types';
interface ProfileProps {
client: Client
}
export const ProfileElement = ({ name, games, is_admin }: UserProfile) => {
const adminNote = is_admin ? <div> <i>Note: this user is an admin</i> </div> : <></>;
export const ProfileElement = ({ client }: ProfileProps) => {
return <div></div>
return (
<div className="card">
<h1>{name}</h1>
<div>Games: {games.map((game) => <>{game.game_name} ({game.game_type})</>).join(', ')}</div>
{adminNote}
</div>)
}

View File

@ -1,5 +1,6 @@
import { ProfileElement } from './Profile/Profile'
import { SimpleGuage } from './Guages/SimpleGuage'
import { ThumbnailElement } from './Thumbnail/Thumbnail'
import { TabletopElement } from './Tabletop/Tabletop'
import { SimpleGuage } from './Guages/SimpleGuage'
export default { ThumbnailElement, TabletopElement, SimpleGuage }
export { ProfileElement, ThumbnailElement, TabletopElement, SimpleGuage }

View File

@ -1,5 +1,7 @@
import React, { useContext } from 'react';
import { useContext, useEffect, useState } from 'react';
import { UserProfile } from 'visions-types';
import { Client } from '../../client';
import { ProfileElement } from '../../components';
import { getSessionId, StateContext, StateProvider } from '../../providers/StateProvider/StateProvider';
interface MainProps {
@ -7,10 +9,21 @@ interface MainProps {
}
export const MainView = ({ client }: MainProps) => {
const [state, manager] = useContext(StateContext)
const [state, _manager] = useContext(StateContext)
const [profile, setProfile] = useState<UserProfile | undefined>(undefined)
const sessionId = getSessionId(state);
const sessionId = getSessionId(state)
useEffect(() => {
if (sessionId) {
client.profile(sessionId, undefined).then((profile) => setProfile(profile))
}
}, [sessionId, client])
return <div>Profile: {sessionId}</div>
return (
<div>
<div>Session ID: {sessionId}</div>
{profile && <ProfileElement {...profile} />}
</div>
)
}