fix routes page

This commit is contained in:
Asger Juul Brunshøj 2025-02-20 22:28:55 +01:00
parent aebd30c1c2
commit a6942156e4
8 changed files with 120 additions and 74 deletions

View File

@ -2,9 +2,18 @@ use crate::models::HoldRole;
use crate::models::{self};
use leptos::prelude::*;
/// Displays a grid of the problem
#[component]
#[tracing::instrument(skip_all)]
pub fn Problem(#[prop(into)] dim: Signal<models::WallDimensions>, #[prop(into)] problem: Signal<models::Problem>) -> impl IntoView {
pub fn Problem(
/// Wall dimensions
#[prop(into)]
dim: Signal<models::WallDimensions>,
/// Problem (route)
#[prop(into)]
problem: Signal<models::Problem>,
) -> impl IntoView {
let holds = move || {
let mut holds = vec![];
for row in 0..dim.get().rows {

View File

@ -0,0 +1,29 @@
use crate::models;
use leptos::prelude::*;
#[component]
#[tracing::instrument(skip_all)]
pub fn ProblemInfo(problem: models::Problem) -> impl IntoView {
tracing::trace!("Enter problem info");
let name = problem.name;
let set_by = problem.set_by;
let method = problem.method;
view! {
<div class="grid grid-rows-none grid-cols-[auto,1fr]">
<NameValue name="Name:" value=name />
<NameValue name="Method:" value=method.to_string() />
<NameValue name="Set By:" value=set_by />
</div>
}
}
#[component]
#[tracing::instrument(skip_all)]
fn NameValue(#[prop(into)] name: String, #[prop(into)] value: String) -> impl IntoView {
view! {
<p class="text-orange-300 mr-4">{name}</p>
<p class="text-white font-semibold">{value}</p>
}
}

View File

@ -2,16 +2,19 @@ pub mod app;
pub mod pages {
pub mod edit_wall;
pub mod routes;
pub mod settings;
pub mod wall;
}
pub mod components {
pub use button::Button;
pub use header::StyledHeader;
pub use problem::Problem;
pub use problem_info::ProblemInfo;
pub mod button;
pub mod header;
pub mod problem;
pub mod problem_info;
}
pub mod resources {
use crate::codec::ron::Ron;

View File

@ -22,7 +22,6 @@ pub mod v2 {
use serde::Serialize;
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::fmt::Display;
#[derive(Serialize, Deserialize, Debug)]
pub struct Root {

View File

@ -37,7 +37,7 @@ pub fn Routes() -> impl IntoView {
link: Some("/".to_string()),
}],
middle: vec![HeaderItem {
text: "ROUTES".to_string(),
text: "Routes".to_string(),
link: None,
}],
right: vec![],
@ -64,7 +64,7 @@ pub fn Routes() -> impl IntoView {
each=problems_sample
key=|problem| problem.uid
children=move |problem: models::Problem| {
view! { <Problem dim=wall_dimensions problem /> }
view! { <Problem dim=wall_dimensions problem /> <hr class="h-px my-8 border-0 bg-gray-700" />}
}
/>
</div>
@ -76,11 +76,10 @@ pub fn Routes() -> impl IntoView {
};
view! {
<div class="min-w-screen min-h-screen bg-slate-900">
<div class="min-w-screen min-h-screen bg-neutral-950">
<StyledHeader items=header_items />
<div class="container mx-auto mt-2">
{move || view! { <Import wall_uid=wall_uid.get() /> }}
<div class="container mx-auto mt-6">
<Suspense fallback=|| view! { <p>"loading"</p> }>{suspend}</Suspense>
</div>
</div>
@ -90,44 +89,12 @@ pub fn Routes() -> impl IntoView {
#[component]
#[tracing::instrument(skip_all)]
fn Problem(#[prop(into)] dim: Signal<models::WallDimensions>, #[prop(into)] problem: Signal<models::Problem>) -> impl IntoView {
tracing::debug!("Enter");
view! {
<div class="flex items-start">
<div class="flex-none">
<components::Problem dim problem />
<p>{move || problem.get().name.clone()}</p>
</div>
<components::ProblemInfo problem=problem.get() />
</div>
}
}
#[component]
#[tracing::instrument(skip_all)]
fn Import(wall_uid: WallUid) -> impl IntoView {
tracing::debug!("ready");
let import_from_mini_moonboard = Action::from(ServerAction::<ImportFromMiniMoonboard>::new());
let onclick = move |_mouse_event| {
import_from_mini_moonboard.dispatch(ImportFromMiniMoonboard { wall_uid });
};
view! {
<p>"Import problems from"</p>
<button on:click=onclick>"Mini Moonboard"</button>
}
}
#[server(name = ImportFromMiniMoonboard)]
#[tracing::instrument]
async fn import_from_mini_moonboard(wall_uid: WallUid) -> Result<(), ServerFnError> {
use crate::server::config::Config;
use crate::server::db::Database;
tracing::info!("Importing mini moonboard problems");
let config = expect_context::<Config>();
let db = expect_context::<Database>();
crate::server::operations::import_mini_moonboard_problems(&config, db, wall_uid).await?;
// TODO: Return information about what was done
Ok(())
}

View File

@ -0,0 +1,63 @@
use crate::components::StyledHeader;
use crate::components::header::HeaderItem;
use crate::components::header::HeaderItems;
use crate::models::WallUid;
use leptos::prelude::*;
#[component]
#[tracing::instrument(skip_all)]
pub fn Settings() -> impl IntoView {
let header_items = HeaderItems {
left: vec![HeaderItem {
text: "← Ascend".to_string(),
link: Some("/".to_string()),
}],
middle: vec![HeaderItem {
text: "Settings".to_string(),
link: None,
}],
right: vec![],
};
view! {
<div class="min-w-screen min-h-screen bg-neutral-950">
<StyledHeader items=header_items />
<div class="container mx-auto mt-2">
// {move || view! { <Import wall_uid=wall_uid.get() /> }}
</div>
</div>
}
}
#[component]
#[tracing::instrument(skip_all)]
fn Import(wall_uid: WallUid) -> impl IntoView {
let import_from_mini_moonboard = Action::from(ServerAction::<ImportFromMiniMoonboard>::new());
let onclick = move |_mouse_event| {
import_from_mini_moonboard.dispatch(ImportFromMiniMoonboard { wall_uid });
};
view! {
<p>"Import problems from"</p>
<button on:click=onclick>"Mini Moonboard"</button>
}
}
#[server(name = ImportFromMiniMoonboard)]
#[tracing::instrument]
async fn import_from_mini_moonboard(wall_uid: WallUid) -> Result<(), ServerFnError> {
use crate::server::config::Config;
use crate::server::db::Database;
tracing::info!("Importing mini moonboard problems");
let config = expect_context::<Config>();
let db = expect_context::<Database>();
crate::server::operations::import_mini_moonboard_problems(&config, db, wall_uid).await?;
// TODO: Return information about what was done
Ok(())
}

View File

@ -1,6 +1,7 @@
// TODO: Put current problem UID in url
use crate::codec::ron::RonEncoded;
use crate::components::ProblemInfo;
use crate::components::button::Button;
use crate::components::header::HeaderItem;
use crate::components::header::HeaderItems;
@ -168,30 +169,3 @@ fn Hold(hold: models::Hold, role: Signal<Option<HoldRole>>) -> impl IntoView {
tracing::trace!("view");
view! { <div class=class>{img}</div> }
}
#[component]
#[tracing::instrument(skip_all)]
fn ProblemInfo(problem: models::Problem) -> impl IntoView {
tracing::trace!("Enter problem info");
let name = problem.name;
let set_by = problem.set_by;
let method = problem.method;
view! {
<div class="grid grid-cols-[auto,1fr] gap-2">
<NameValue name="Name:" value=name />
<NameValue name="Method:" value=method.to_string() />
<NameValue name="Set By:" value=set_by />
</div>
}
}
#[component]
#[tracing::instrument(skip_all)]
fn NameValue(#[prop(into)] name: String, #[prop(into)] value: String) -> impl IntoView {
view! {
<p class="text-orange-300">{name}</p>
<p class="text-white">{value}</p>
}
}

View File

@ -1,5 +1,3 @@
- save images with a uuid
- downscale images
- associate routes with wall
- group routes by pattern (pattern family has shift/mirror variations)
- generate pattern families of variations when importing problems
@ -10,3 +8,7 @@
- use wall id in URL.
- decide on routes vs problems terminology
- decide on holds vs wall-edit terminology
- clock
- hotkeys (enter =next problem, arrow = shift left/right up/down)
- remove brightness reduction when mousing over holds
- impl `sizes` hint next to `srcset`