feat(web client): content pages
This commit is contained in:
parent
58f5722551
commit
6fd3499d7b
15 changed files with 312 additions and 11 deletions
|
|
@ -64,6 +64,12 @@ pub struct GameDetail {
|
|||
pub participants: Vec<Participant>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub struct PageContent {
|
||||
pub title: String,
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
// ── Request bodies ────────────────────────────────────────────────────────────
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
|
@ -242,6 +248,18 @@ pub async fn post_reset_password(token: &str, new_password: &str) -> Result<(),
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn get_page(slug: &str, lang: &str) -> Result<PageContent, String> {
|
||||
let resp = gloo_net::http::Request::get(&url(&format!("/pages/{slug}?lang={lang}")))
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
if resp.status() == 200 {
|
||||
resp.json::<PageContent>().await.map_err(|e| e.to_string())
|
||||
} else {
|
||||
Err(format!("status {}", resp.status()))
|
||||
}
|
||||
}
|
||||
|
||||
// ── Utilities ─────────────────────────────────────────────────────────────────
|
||||
|
||||
/// Maps to the `Intl.DateTimeFormat` options object accepted by `Date.toLocaleString`.
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ use crate::game::trictrac::backend::TrictracBackend;
|
|||
use crate::game::trictrac::types::{GameDelta, PlayerAction, ScoredEvent, SerStage, ViewState};
|
||||
use crate::i18n::*;
|
||||
use crate::portal::{
|
||||
account::AccountPage, forgot_password::ForgotPasswordPage, game_detail::GameDetailPage,
|
||||
lobby::LobbyPage, profile::ProfilePage, reset_password::ResetPasswordPage,
|
||||
verify_email::VerifyEmailPage,
|
||||
account::AccountPage, content_page::ContentPage, forgot_password::ForgotPasswordPage,
|
||||
game_detail::GameDetailPage, lobby::LobbyPage, profile::ProfilePage,
|
||||
reset_password::ResetPasswordPage, verify_email::VerifyEmailPage,
|
||||
};
|
||||
use trictrac_store::CheckerMove;
|
||||
|
||||
|
|
@ -432,6 +432,7 @@ pub fn App() -> impl IntoView {
|
|||
<Route path=path!("/verify-email") view=VerifyEmailPage />
|
||||
<Route path=path!("/forgot-password") view=ForgotPasswordPage />
|
||||
<Route path=path!("/reset-password") view=ResetPasswordPage />
|
||||
<Route path=path!("/page/:slug") view=ContentPage />
|
||||
</Routes>
|
||||
</main>
|
||||
|
||||
|
|
|
|||
51
clients/web/src/portal/content_page.rs
Normal file
51
clients/web/src/portal/content_page.rs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
use leptos::prelude::*;
|
||||
use leptos_router::hooks::use_params_map;
|
||||
use pulldown_cmark::{Options, Parser, html};
|
||||
|
||||
use crate::api;
|
||||
use crate::i18n::*;
|
||||
|
||||
#[component]
|
||||
pub fn ContentPage() -> impl IntoView {
|
||||
let params = use_params_map();
|
||||
let slug = move || params.read().get("slug").unwrap_or_default();
|
||||
let i18n = use_i18n();
|
||||
|
||||
let page = LocalResource::new(move || {
|
||||
let s = slug();
|
||||
let lang = match i18n.get_locale() {
|
||||
Locale::en => "en",
|
||||
Locale::fr => "fr",
|
||||
};
|
||||
async move { api::get_page(&s, lang).await }
|
||||
});
|
||||
|
||||
view! {
|
||||
<div class="portal-main">
|
||||
{move || match page.get().map(|sw| sw.take()) {
|
||||
None => view! {
|
||||
<p class="portal-loading">{t!(i18n, loading)}</p>
|
||||
}.into_any(),
|
||||
Some(Err(_)) => view! {
|
||||
<p class="portal-empty">"Page not found."</p>
|
||||
}.into_any(),
|
||||
Some(Ok(p)) => {
|
||||
let html = md_to_html(&p.content);
|
||||
view! {
|
||||
<div class="portal-card content-page" inner_html=html />
|
||||
}.into_any()
|
||||
}
|
||||
}}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
fn md_to_html(md: &str) -> String {
|
||||
let mut opts = Options::empty();
|
||||
opts.insert(Options::ENABLE_TABLES);
|
||||
opts.insert(Options::ENABLE_STRIKETHROUGH);
|
||||
let parser = Parser::new_ext(md, opts);
|
||||
let mut output = String::new();
|
||||
html::push_html(&mut output, parser);
|
||||
output
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
pub mod account;
|
||||
pub mod content_page;
|
||||
pub mod forgot_password;
|
||||
pub mod game_detail;
|
||||
pub mod lobby;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue