Now set up a landing page of sorts

This commit is contained in:
Savanni D'Gerinel 2025-03-26 23:30:18 -04:00
parent 11e33eca2f
commit 6969bc659b
5 changed files with 80 additions and 12 deletions
visions

View File

@ -54,6 +54,7 @@ impl result_extended::FatalError for FatalError {}
fn parse_session_header(headers: HeaderMap) -> ResultExt<Option<SessionId>, AppError, FatalError> {
match headers.get("Authorization") {
Some(token) => {
println!("session token: {:?}", token);
match token
.to_str()
.unwrap()
@ -116,6 +117,7 @@ async fn main() {
"/api/test/list-users",
get(|headers: HeaderMap| {
auth_required(headers, || async {
println!("list_users is about to return a bunch of stuff");
(
StatusCode::OK,
Some(vec![

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Deserialize, Serialize)]
#[derive(Clone, Deserialize, PartialEq, Serialize)]
#[serde(tag = "type", content = "content", rename_all = "kebab-case")]
pub enum AccountStatus {
Ok,
@ -65,7 +65,7 @@ impl From<String> for UserId {
}
}
#[derive(Deserialize, Serialize)]
#[derive(Clone, Deserialize, PartialEq, Serialize)]
pub struct UserOverview {
pub id: UserId,
pub name: String,

6
visions/ui/Taskfile.yml Normal file
View File

@ -0,0 +1,6 @@
version: '3'
tasks:
dev:
cmds:
- trunk serve --open

View File

@ -11,7 +11,7 @@ pub enum ClientError {
pub trait Client {
fn auth(&self, username: String, password: String) -> impl Future<Output = Result<AuthResponse, ClientError>>;
fn list_users(&self, session_id: SessionId) -> impl Future<Output = Result<Vec<UserOverview>, ClientError>>;
fn list_users(&self, session_id: &SessionId) -> impl Future<Output = Result<Vec<UserOverview>, ClientError>>;
}
pub struct Connection;
@ -38,7 +38,18 @@ impl Client for Connection {
}
}
async fn list_users(&self, session_id: SessionId) -> Result<Vec<UserOverview>, ClientError> {
todo!()
async fn list_users(&self, session_id: &SessionId) -> Result<Vec<UserOverview>, ClientError> {
let response: Response = Request::get("/api/test/list-users")
.header("Content-Type", "application/json")
.header("Authorization", &format!("Bearer {}", session_id.as_str()))
.send()
.await
.unwrap();
if response.ok() {
Ok(serde_json::from_slice(&response.binary().await.unwrap()).unwrap())
} else {
Err(ClientError::Err(response.status()))
}
}
}

View File

@ -1,7 +1,7 @@
use std::rc::Rc;
use gloo_console::log;
use visions_types::AuthResponse;
use visions_types::{AuthResponse, SessionId, UserOverview};
use wasm_bindgen::JsCast;
use web_sys::HtmlInputElement;
use yew::prelude::*;
@ -10,7 +10,7 @@ mod client;
use client::*;
struct AuthInfo {
session_id: Option<String>,
session_id: Option<SessionId>,
}
impl Default for AuthInfo {
@ -31,7 +31,7 @@ impl Reducible for AuthInfo {
// log!("reduce", action);
match action {
AuthAction::Auth(session_id) => Self {
session_id: Some(session_id),
session_id: Some(session_id.into()),
}
.into(),
AuthAction::Unauth => Self { session_id: None }.into(),
@ -92,6 +92,56 @@ fn Login(LoginProps { on_login }: &LoginProps) -> Html {
}
}
#[derive(Properties, PartialEq)]
struct LandingProps {
session_id: SessionId,
}
#[function_component]
fn Landing(LandingProps { session_id }: &LandingProps) -> Html {
let user_ref = use_state(|| vec![]);
{
let user_ref = user_ref.clone();
let session_id = session_id.clone();
use_effect(move || {
wasm_bindgen_futures::spawn_local(async move {
let client = Connection::new();
match client.list_users(&session_id).await {
Ok(users) => user_ref.set(users),
Err(ClientError::Unauthorized) => todo!(),
Err(ClientError::Err(status)) => {
log!("error: {:?}", status);
todo!()
}
}
})
});
}
html! {
<div>
{"Landing Page"}
{user_ref.iter().map(|overview| {
let overview = overview.clone();
html! { <UserOverviewComponent overview={overview} /> }}).collect::<Vec<Html>>()
}
</div>
}
}
#[derive(Properties, PartialEq)]
struct UserOverviewProps {
overview: UserOverview,
}
#[function_component]
fn UserOverviewComponent(UserOverviewProps { overview }: &UserOverviewProps) -> Html {
html! {
<div> { overview.name.clone() } </div>
}
}
#[function_component]
fn App() -> Html {
let auth_info = use_reducer(AuthInfo::default);
@ -116,10 +166,9 @@ fn App() -> Html {
})
};
if auth_info.session_id.is_some() {
html! { <p>{ "this is just a thing" }</p> }
} else {
html! { <Login on_login={on_login.clone()} /> }
match auth_info.session_id {
Some(ref session_id) => html! { <Landing session_id={session_id.clone()} /> },
None => html! { <Login on_login={on_login.clone()} /> },
}
}