Fix more clippy issues, implement forgot password
All checks were successful
Build Crate / build (push) Successful in 1m48s
All checks were successful
Build Crate / build (push) Successful in 1m48s
This commit is contained in:
@@ -8,10 +8,16 @@ cfg_if::cfg_if! {
|
|||||||
if #[cfg(client)] {
|
if #[cfg(client)] {
|
||||||
use crate::{
|
use crate::{
|
||||||
state_enums::{ OpenState},
|
state_enums::{ OpenState},
|
||||||
templates::{get_api_path},
|
templates::get_api_path,
|
||||||
global_state::{self, AppStateRx},
|
global_state::{AppStateRx},
|
||||||
|
endpoints::FORGOT_PASSWORD,
|
||||||
|
models::{
|
||||||
|
auth::ForgotPasswordRequest,
|
||||||
|
generic::GenericResponse,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,6 +31,7 @@ lazy_static! {
|
|||||||
struct ForgotPasswordFormState {
|
struct ForgotPasswordFormState {
|
||||||
username: String,
|
username: String,
|
||||||
how_to_reach: String,
|
how_to_reach: String,
|
||||||
|
error: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ForgotPasswordFormStateRx {
|
impl ForgotPasswordFormStateRx {
|
||||||
@@ -32,6 +39,7 @@ impl ForgotPasswordFormStateRx {
|
|||||||
fn reset(&self) {
|
fn reset(&self) {
|
||||||
self.username.set(String::new());
|
self.username.set(String::new());
|
||||||
self.how_to_reach.set(String::new());
|
self.how_to_reach.set(String::new());
|
||||||
|
self.error.set(String::new());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +57,6 @@ fn forgot_password_form_capsule<G: Html>(
|
|||||||
{
|
{
|
||||||
spawn_local_scoped(cx, async move {
|
spawn_local_scoped(cx, async move {
|
||||||
let global_state = Reactor::<G>::from_cx(cx).get_global_state::<AppStateRx>(cx);
|
let global_state = Reactor::<G>::from_cx(cx).get_global_state::<AppStateRx>(cx);
|
||||||
|
|
||||||
// Close modal
|
// Close modal
|
||||||
state.reset();
|
state.reset();
|
||||||
global_state
|
global_state
|
||||||
@@ -63,6 +70,26 @@ fn forgot_password_form_capsule<G: Html>(
|
|||||||
#[cfg(client)]
|
#[cfg(client)]
|
||||||
{
|
{
|
||||||
spawn_local_scoped(cx, async move {
|
spawn_local_scoped(cx, async move {
|
||||||
|
let request = ForgotPasswordRequest {
|
||||||
|
username: state.username.get().as_ref().clone(),
|
||||||
|
contact_info: state.how_to_reach.get().as_ref().clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// // @todo clean up error handling
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let response = client
|
||||||
|
.post(get_api_path(FORGOT_PASSWORD).as_str())
|
||||||
|
.json(&request)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let status = response.status();
|
||||||
|
let response_data = response.json::<GenericResponse>().await.unwrap();
|
||||||
|
if status != StatusCode::OK {
|
||||||
|
state.error.set(response_data.status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let global_state = Reactor::<G>::from_cx(cx).get_global_state::<AppStateRx>(cx);
|
let global_state = Reactor::<G>::from_cx(cx).get_global_state::<AppStateRx>(cx);
|
||||||
|
|
||||||
// Close modal
|
// Close modal
|
||||||
@@ -81,11 +108,26 @@ fn forgot_password_form_capsule<G: Html>(
|
|||||||
div (class="bg-white rounded-lg shadow relative dark:bg-gray-700"){
|
div (class="bg-white rounded-lg shadow relative dark:bg-gray-700"){
|
||||||
div (class="flex justify-end p-2"){
|
div (class="flex justify-end p-2"){
|
||||||
button (on:click = close_modal, class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-800 dark:hover:text-white"){
|
button (on:click = close_modal, class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-800 dark:hover:text-white"){
|
||||||
"Back"
|
"Close"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
div (class="space-y-6 px-6 lg:px-8 pb-4 sm:pb-6 xl:pb-8") {
|
div (class="space-y-6 px-6 lg:px-8 pb-4 sm:pb-6 xl:pb-8") {
|
||||||
h3 (class="text-xl font-medium text-gray-900 dark:text-white"){"Forgot Password"}
|
h3 (class="text-xl font-medium text-gray-900 dark:text-white"){"Forgot Password"}
|
||||||
|
|
||||||
|
(match state.error.get().as_ref() != "" {
|
||||||
|
true => { view!{cx,
|
||||||
|
div (role="alert") {
|
||||||
|
div (class="bg-red-500 text-white font-bold rounded-t px-4 py-2") {
|
||||||
|
"Error"
|
||||||
|
}
|
||||||
|
div (class="border border-t-0 border-red-400 rounded-b bg-red-100 px-4 py-3 text-red-700"){
|
||||||
|
p {(state.error.get())}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
false => {view!{cx,}},
|
||||||
|
})
|
||||||
|
|
||||||
div {
|
div {
|
||||||
label (class="text-sm font-medium text-gray-900 block mb-2 dark:text-gray-300") {"Username"}
|
label (class="text-sm font-medium text-gray-900 block mb-2 dark:text-gray-300") {"Username"}
|
||||||
input (bind:value = state.username, class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white") {}
|
input (bind:value = state.username, class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white") {}
|
||||||
@@ -113,7 +155,8 @@ pub fn get_capsule<G: Html>() -> Capsule<G, ForgotPasswordFormProps> {
|
|||||||
#[engine_only_fn]
|
#[engine_only_fn]
|
||||||
async fn get_build_state(_info: StateGeneratorInfo<()>) -> ForgotPasswordFormState {
|
async fn get_build_state(_info: StateGeneratorInfo<()>) -> ForgotPasswordFormState {
|
||||||
ForgotPasswordFormState {
|
ForgotPasswordFormState {
|
||||||
username: "".to_owned(),
|
username: String::new(),
|
||||||
how_to_reach: "".to_owned(),
|
how_to_reach: String::new(),
|
||||||
|
error: String::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,11 @@ use web_sys::Event;
|
|||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(client)] {
|
if #[cfg(client)] {
|
||||||
use crate::{
|
use crate::{
|
||||||
models::auth::{LoginInfo, LoginResponse},
|
|
||||||
endpoints::LOGIN,
|
endpoints::LOGIN,
|
||||||
state_enums::{LoginState, OpenState},
|
global_state::{AppStateRx},
|
||||||
templates::{get_api_path},
|
models::auth::{LoginInfo, LoginResponse, WebAuthInfo},
|
||||||
global_state::{self, AppStateRx},
|
state_enums::{OpenState},
|
||||||
models::auth::WebAuthInfo,
|
templates::get_api_path,
|
||||||
};
|
};
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
}
|
}
|
||||||
@@ -141,7 +140,7 @@ fn login_form_capsule<G: Html>(
|
|||||||
div (class="bg-white rounded-lg shadow relative dark:bg-gray-700"){
|
div (class="bg-white rounded-lg shadow relative dark:bg-gray-700"){
|
||||||
div (class="flex justify-end p-2"){
|
div (class="flex justify-end p-2"){
|
||||||
button (on:click = close_modal, class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-800 dark:hover:text-white"){
|
button (on:click = close_modal, class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-800 dark:hover:text-white"){
|
||||||
"Back"
|
"Close"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
div (class="space-y-6 px-6 lg:px-8 pb-4 sm:pb-6 xl:pb-8") {
|
div (class="space-y-6 px-6 lg:px-8 pb-4 sm:pb-6 xl:pb-8") {
|
||||||
|
|||||||
@@ -9,11 +9,10 @@ cfg_if::cfg_if! {
|
|||||||
use crate::{
|
use crate::{
|
||||||
models::auth::{RegisterRequest},
|
models::auth::{RegisterRequest},
|
||||||
endpoints::REGISTER,
|
endpoints::REGISTER,
|
||||||
state_enums::{LoginState, OpenState},
|
state_enums::OpenState,
|
||||||
templates::{get_api_path},
|
templates::get_api_path,
|
||||||
global_state::{self, AppStateRx},
|
global_state::AppStateRx,
|
||||||
models::{
|
models::{
|
||||||
auth::WebAuthInfo,
|
|
||||||
generic::GenericResponse
|
generic::GenericResponse
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -120,7 +119,7 @@ fn register_form_capsule<G: Html>(
|
|||||||
div (class="bg-white rounded-lg shadow relative dark:bg-gray-700"){
|
div (class="bg-white rounded-lg shadow relative dark:bg-gray-700"){
|
||||||
div (class="flex justify-end p-2"){
|
div (class="flex justify-end p-2"){
|
||||||
button (on:click = close_modal, class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-800 dark:hover:text-white"){
|
button (on:click = close_modal, class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-800 dark:hover:text-white"){
|
||||||
"Back"
|
"Close"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
div (class="space-y-6 px-6 lg:px-8 pb-4 sm:pb-6 xl:pb-8") {
|
div (class="space-y-6 px-6 lg:px-8 pb-4 sm:pb-6 xl:pb-8") {
|
||||||
|
|||||||
@@ -16,13 +16,12 @@ cfg_if::cfg_if! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Prop)]
|
#[derive(Prop)]
|
||||||
pub struct HeaderProps<'a> {
|
pub struct HeaderProps {
|
||||||
pub game: GameState,
|
pub game: GameState,
|
||||||
pub title: &'a str,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Header<'a, G: Html>(cx: Scope<'a>, HeaderProps { game, title }: HeaderProps<'a>) -> View<G> {
|
pub fn Header<'a, G: Html>(cx: Scope<'a>, props: HeaderProps) -> View<G> {
|
||||||
// Get global state to get authentication info
|
// Get global state to get authentication info
|
||||||
let global_state = Reactor::<G>::from_cx(cx).get_global_state::<AppStateRx>(cx);
|
let global_state = Reactor::<G>::from_cx(cx).get_global_state::<AppStateRx>(cx);
|
||||||
|
|
||||||
@@ -63,7 +62,7 @@ pub fn Header<'a, G: Html>(cx: Scope<'a>, HeaderProps { game, title }: HeaderPro
|
|||||||
|
|
||||||
// Title
|
// Title
|
||||||
div(class = "text-gray-700 text-2xl font-semibold py-2") {
|
div(class = "text-gray-700 text-2xl font-semibold py-2") {
|
||||||
"Pool Elo - Season 1"
|
(props.game.to_string()) " - Season 1"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login / register or user buttons
|
// Login / register or user buttons
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ use sycamore::prelude::*;
|
|||||||
#[derive(Prop)]
|
#[derive(Prop)]
|
||||||
pub struct LayoutProps<'a, G: Html> {
|
pub struct LayoutProps<'a, G: Html> {
|
||||||
pub game: GameState,
|
pub game: GameState,
|
||||||
pub title: &'a str,
|
|
||||||
pub children: Children<'a, G>,
|
pub children: Children<'a, G>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,11 +22,7 @@ pub struct LayoutProps<'a, G: Html> {
|
|||||||
#[component]
|
#[component]
|
||||||
pub fn Layout<'a, G: Html>(
|
pub fn Layout<'a, G: Html>(
|
||||||
cx: Scope<'a>,
|
cx: Scope<'a>,
|
||||||
LayoutProps {
|
LayoutProps { game, children }: LayoutProps<'a, G>,
|
||||||
game,
|
|
||||||
title,
|
|
||||||
children,
|
|
||||||
}: LayoutProps<'a, G>,
|
|
||||||
) -> View<G> {
|
) -> View<G> {
|
||||||
let children = children.call(cx);
|
let children = children.call(cx);
|
||||||
|
|
||||||
@@ -39,7 +34,7 @@ pub fn Layout<'a, G: Html>(
|
|||||||
|
|
||||||
view! { cx,
|
view! { cx,
|
||||||
// Main page header, including login functionality
|
// Main page header, including login functionality
|
||||||
Header(game = game, title = title)
|
Header(game = game)
|
||||||
|
|
||||||
// Modals
|
// Modals
|
||||||
section(class = "flex-2") {
|
section(class = "flex-2") {
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
pub const REGISTER: &str = "/api/register";
|
pub const REGISTER: &str = "/api/register";
|
||||||
pub const LOGIN: &str = "/api/login";
|
pub const LOGIN: &str = "/api/login";
|
||||||
|
// TODO -> remove once it's used
|
||||||
|
#[cfg(engine)]
|
||||||
pub const LOGIN_TEST: &str = "/api/login-test";
|
pub const LOGIN_TEST: &str = "/api/login-test";
|
||||||
pub const FORGOT_PASSWORD: &str = "/api/forgot-password";
|
pub const FORGOT_PASSWORD: &str = "/api/forgot-password";
|
||||||
|
|||||||
@@ -1,12 +1,33 @@
|
|||||||
use crate::{models::auth::ForgotPasswordRequest, server::server_state::ServerState};
|
use crate::{
|
||||||
|
entity::{prelude::*, user},
|
||||||
|
models::{auth::ForgotPasswordRequest, generic::GenericResponse},
|
||||||
|
server::server_state::ServerState,
|
||||||
|
};
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::{Json, State},
|
extract::{Json, State},
|
||||||
http::StatusCode,
|
http::StatusCode,
|
||||||
};
|
};
|
||||||
|
use sea_orm::{ColumnTrait, EntityTrait, IntoActiveModel, QueryFilter, Set};
|
||||||
|
|
||||||
pub async fn post_forgot_password(
|
pub async fn post_forgot_password(
|
||||||
State(state): State<ServerState>,
|
State(state): State<ServerState>,
|
||||||
Json(password_request): Json<ForgotPasswordRequest>,
|
Json(password_request): Json<ForgotPasswordRequest>,
|
||||||
) -> StatusCode {
|
) -> (StatusCode, Json<GenericResponse>) {
|
||||||
StatusCode::OK
|
// Get user
|
||||||
|
let existing_user: Option<user::Model> = User::find()
|
||||||
|
.filter(user::Column::Username.eq(password_request.username))
|
||||||
|
.one(&state.db_conn)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
match existing_user {
|
||||||
|
Some(user) => {
|
||||||
|
let mut user = user.into_active_model();
|
||||||
|
user.forgot_password_request = Set(Some(password_request.contact_info));
|
||||||
|
(StatusCode::OK, Json(GenericResponse::ok()))
|
||||||
|
}
|
||||||
|
None => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(GenericResponse::err("Username doesn't exist")),
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ pub async fn post_login_user(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn post_test_login(
|
pub async fn post_test_login(
|
||||||
State(state): State<ServerState>,
|
State(_): State<ServerState>,
|
||||||
header_map: HeaderMap,
|
header_map: HeaderMap,
|
||||||
) -> Result<Json<String>, StatusCode> {
|
) -> Result<Json<String>, StatusCode> {
|
||||||
if let Some(auth_header) = header_map.get("Authorization") {
|
if let Some(auth_header) = header_map.get("Authorization") {
|
||||||
|
|||||||
@@ -71,11 +71,16 @@ pub async fn post_register_user(
|
|||||||
forgot_password_request: Set(None),
|
forgot_password_request: Set(None),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
// TODO -> error handling
|
let db_resp = user::Entity::insert(new_user).exec(&state.db_conn).await;
|
||||||
let db_resp = user::Entity::insert(new_user)
|
match db_resp {
|
||||||
.exec(&state.db_conn)
|
Ok(_) => {}
|
||||||
.await
|
Err(err) => {
|
||||||
.unwrap();
|
return (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(GenericResponse::err(err.to_string().as_str())),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (StatusCode::OK, Json(GenericResponse::ok()));
|
return (StatusCode::OK, Json(GenericResponse::ok()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,17 @@ pub enum GameState {
|
|||||||
TableTennis,
|
TableTennis,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToString for GameState {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
match self {
|
||||||
|
GameState::None => String::new(),
|
||||||
|
GameState::Pool => "Pool".to_owned(),
|
||||||
|
GameState::Pickleball => "Pool".to_owned(),
|
||||||
|
GameState::TableTennis => "Pool".to_owned(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub enum OpenState {
|
pub enum OpenState {
|
||||||
Open,
|
Open,
|
||||||
|
|||||||
@@ -4,14 +4,6 @@ use serde::{Deserialize, Serialize};
|
|||||||
use sycamore::prelude::*;
|
use sycamore::prelude::*;
|
||||||
use web_sys::Event;
|
use web_sys::Event;
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
|
||||||
if #[cfg(client)] {
|
|
||||||
use crate::global_state::AppStateRx;
|
|
||||||
use crate::templates::get_api_path;
|
|
||||||
use chrono::Utc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reactive page
|
// Reactive page
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, ReactiveState)]
|
#[derive(Serialize, Deserialize, Clone, ReactiveState)]
|
||||||
@@ -39,7 +31,7 @@ fn add_game_form_page<'a, G: Html>(cx: BoundedScope<'_, 'a>, state: &'a PageStat
|
|||||||
};
|
};
|
||||||
|
|
||||||
view! { cx,
|
view! { cx,
|
||||||
Layout(title = "Add Game Results", game = GameState::Pool) {
|
Layout(game = GameState::Pool) {
|
||||||
div (class = "flex flex-wrap") {
|
div (class = "flex flex-wrap") {
|
||||||
select {
|
select {
|
||||||
option (value="red")
|
option (value="red")
|
||||||
|
|||||||
66
src/templates/global_state.rs
Normal file
66
src/templates/global_state.rs
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
// Not a page, global state that is shared between all pages
|
||||||
|
|
||||||
|
use perseus::{prelude::*, state::GlobalStateCreator};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
models::auth::Claims,
|
||||||
|
state_enums::{LoginState, OpenState},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, ReactiveState, Clone)]
|
||||||
|
#[rx(alias = "AppStateRx")]
|
||||||
|
pub struct AppState {
|
||||||
|
#[rx(nested)]
|
||||||
|
pub auth: AuthData,
|
||||||
|
#[rx(nested)]
|
||||||
|
pub modals_open: ModalOpenData,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, ReactiveState, Clone)]
|
||||||
|
#[rx(alias = "AuthDataRx")]
|
||||||
|
pub struct AuthData {
|
||||||
|
pub state: LoginState,
|
||||||
|
pub username: Option<String>,
|
||||||
|
pub claims: Claims,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, ReactiveState, Clone)]
|
||||||
|
#[rx(alias = "ModalOpenDataRx")]
|
||||||
|
pub struct ModalOpenData {
|
||||||
|
pub login: OpenState,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_global_state_creator() -> GlobalStateCreator {
|
||||||
|
GlobalStateCreator::new().build_state_fn(get_build_state)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[engine_only_fn]
|
||||||
|
pub async fn get_build_state() -> AppState {
|
||||||
|
AppState {
|
||||||
|
auth: AuthData {
|
||||||
|
state: LoginState::Unknown,
|
||||||
|
username: None,
|
||||||
|
claims: Claims {
|
||||||
|
sub: "".to_owned(),
|
||||||
|
exp: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modals_open: ModalOpenData {
|
||||||
|
login: OpenState::Closed,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client only code to check if they're authenticated
|
||||||
|
#[cfg(client)]
|
||||||
|
impl AuthDataRx {
|
||||||
|
pub fn detect_state(&self) {
|
||||||
|
// If the user is in a known state, return
|
||||||
|
if let LoginState::Authenticated | LoginState::NotAuthenticated = *self.state.get() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO -> Get state from storage
|
||||||
|
self.state.set(LoginState::NotAuthenticated);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ use sycamore::prelude::*;
|
|||||||
|
|
||||||
fn index_page<G: Html>(cx: Scope) -> View<G> {
|
fn index_page<G: Html>(cx: Scope) -> View<G> {
|
||||||
view! { cx,
|
view! { cx,
|
||||||
Layout(title = "Index", game = GameState::Pool) {
|
Layout(game = GameState::Pool) {
|
||||||
// Anything we put in here will be rendered inside the `<main>` block of the layout
|
// Anything we put in here will be rendered inside the `<main>` block of the layout
|
||||||
p { "Hello World!" }
|
p { "Hello World!" }
|
||||||
br {}
|
br {}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ struct PageState {}
|
|||||||
|
|
||||||
fn one_v_one_board_page<'a, G: Html>(cx: BoundedScope<'_, 'a>, _state: &'a PageStateRx) -> View<G> {
|
fn one_v_one_board_page<'a, G: Html>(cx: BoundedScope<'_, 'a>, _state: &'a PageStateRx) -> View<G> {
|
||||||
view! { cx,
|
view! { cx,
|
||||||
Layout(title = "1v1 Leaderboard", game = GameState::Pool) {
|
Layout(game = GameState::Pool) {
|
||||||
p { "leaderboard" }
|
p { "leaderboard" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ fn overall_board_page<'a, G: Html>(cx: BoundedScope<'_, 'a>, _state: &'a PageSta
|
|||||||
let _global_state = Reactor::<G>::from_cx(cx).get_global_state::<AppStateRx>(cx);
|
let _global_state = Reactor::<G>::from_cx(cx).get_global_state::<AppStateRx>(cx);
|
||||||
|
|
||||||
view! { cx,
|
view! { cx,
|
||||||
Layout(title = "Overall Leaderboard", game = GameState::Pool) {
|
Layout(game = GameState::Pool) {
|
||||||
ul {
|
ul {
|
||||||
(View::new_fragment(
|
(View::new_fragment(
|
||||||
vec![],
|
vec![],
|
||||||
|
|||||||
Reference in New Issue
Block a user