This commit is contained in:
Asger Juul Brunshøj 2025-01-19 23:55:09 +01:00
parent 5fd2b1206a
commit 8beaa5b0d4
4 changed files with 125 additions and 22 deletions

View File

@ -40,11 +40,6 @@ pub fn App() -> impl leptos::IntoView {
<Title text="Ascend" />
<Router>
// <nav class="shadow-md mb-2 bg-white border-gray-200 px-4 lg:px-6 py-2.5">
// <div class="flex flex-wrap justify-start items-center gap-4 max-w-screen-xl">
// <HeaderItem text="Home" link="/"/>
// </div>
// </nav>
<main>
<Routes fallback=|| "Not found">
<Route path=path!("/wall") view=Wall />

View File

@ -1,6 +1,54 @@
use leptos::prelude::*;
#[component]
pub fn Header() -> impl leptos::IntoView {
leptos::view! { <div class="border-b py-2 mb-4">"Ascend"</div> }
pub struct HeaderItems {
pub left: Vec<HeaderItem>,
pub middle: Vec<HeaderItem>,
pub right: Vec<HeaderItem>,
}
pub struct HeaderItem {
pub text: String,
pub link: Option<String>,
}
#[component]
pub fn Header(items: HeaderItems) -> impl IntoView {
let HeaderItems { left, middle, right } = items;
view! {
<div class="text-xl font-semibold p-4 flex gap-4">
// Left side of header
<Items items=left />
// Expanding space in the middle
<div class="flex-auto mx-auto">
<Items items=middle />
</div>
// Right side of header
<Items items=right />
</div>
}
}
#[component]
fn Items(items: Vec<HeaderItem>) -> impl IntoView {
items.into_iter().map(|item| view! { <Item item /> }).collect_view()
}
#[component]
fn Item(item: HeaderItem) -> impl IntoView {
let text = item.text;
let link = item.link;
if let Some(link) = link {
view! {
<a href=link>
<span class="whitespace-nowrap">{text}</span>
</a>
}
.into_any()
} else {
view! { <span class="whitespace-nowrap">{text}</span> }.into_any()
}
}

View File

@ -1,5 +1,7 @@
use crate::codec::ron::RonCodec;
use crate::components::header::Header;
use crate::components::header::HeaderItem;
use crate::components::header::HeaderItems;
use crate::models;
use crate::models::HoldPosition;
use crate::models::Wall;
@ -21,10 +23,54 @@ pub fn EditWall() -> impl leptos::IntoView {
load_initial_data().await.unwrap()
};
let header_items = HeaderItems {
left: vec![HeaderItem {
text: "".to_string(),
link: Some("/wall".to_string()),
}],
middle: vec![HeaderItem {
text: "Edit wall".to_string(),
link: None,
}],
right: vec![],
};
leptos::view! {
<div class="min-w-screen min-h-screen bg-slate-900">
<div class="container mx-auto">
<Header />
<div class="flex">
// Left gradient chunk
<div class="flex-grow">
<div class="h-2/5" style="background: #eaac53" />
<div class="h-3/5" style="background: linear-gradient(to bottom left, #eaac53 49.5%, rgb(15 23 42) 50.5%)" />
</div>
<div class="flex-none container mx-auto text-black" style="background: #eaac53">
<Header items=header_items />
</div>
// Right gradient chunk
<div class="flex-grow" style="background: #eaac53" />
</div>
<div class="flex">
// Left gradient chunk
<div class="flex-grow" />
<div class="flex-none container mx-auto">
// Background color gradient
<div
class="h-6"
style="background: linear-gradient(to bottom left, #eaac53 49.5%, rgb(15 23 42) 50.5%)"
/>
</div>
// Right gradient chunk
<div class="flex-grow">
<div class="h-4/5" style="background: #eaac53" />
<div class="h-1/5" style="background: linear-gradient(to bottom right, #eaac53 49.5%, rgb(15 23 42) 50.5%)" />
</div>
</div>
<div class="container mx-auto mt-2">
<Await future=load let:data>
<Ready data=data.deref().to_owned() />
</Await>
@ -44,7 +90,10 @@ fn Ready(data: InitialData) -> impl leptos::IntoView {
let grid_classes = format!("grid grid-rows-{} grid-cols-{} gap-2", data.wall.rows, data.wall.cols);
view! { <div class=move || { grid_classes.clone() }>{holds}</div> }
view! {
<div>
<p class="my-4 font-semibold">"Click hold to replace image"</p>
<div class=move || { grid_classes.clone() }>{holds}</div> </div>}
}
#[component]
@ -98,15 +147,13 @@ fn Hold(hold: models::Hold) -> impl leptos::IntoView {
let img = move || {
hold.read().image.as_ref().map(|img| {
let src = format!("/files/holds/{}", img.filename);
view! {
<img class="object-cover w-full h-full" src=src />
}
view! { <img class="object-cover w-full h-full" src=src /> }
})
};
view! {
<button on:click=open_camera>
<div class="bg-indigo-100 aspect-square rounded">{ img }</div>
<div class="bg-indigo-100 aspect-square rounded">{img}</div>
</button>
<input

View File

@ -1,5 +1,7 @@
use crate::codec::ron::RonCodec;
use crate::components::header::Header;
use crate::components::header::HeaderItem;
use crate::components::header::HeaderItems;
use crate::models;
use crate::models::HoldRole;
use leptos::prelude::*;
@ -15,10 +17,22 @@ pub fn Wall() -> impl leptos::IntoView {
load_initial_data().await.unwrap()
};
let header_items = HeaderItems {
left: vec![],
middle: vec![HeaderItem {
text: "Ascend".to_string(),
link: None,
}],
right: vec![HeaderItem {
text: "Edit wall".to_string(),
link: Some("/wall/edit".to_string()),
}],
};
leptos::view! {
<div class="min-w-screen min-h-screen bg-slate-900">
<div class="container mx-auto">
<Header />
<Header items=header_items />
<Await future=load let:data>
<Ready data=data.deref().to_owned() />
</Await>
@ -43,7 +57,7 @@ fn Ready(data: InitialData) -> impl leptos::IntoView {
let role = move || current_problem.get().and_then(|problem| problem.holds.get(&hold_position).copied());
let role = Signal::derive(role);
let cell = view! { <Hold role hold=hold.clone()/> };
let cell = view! { <Hold role hold=hold.clone() /> };
cells.push(cell);
}
@ -63,7 +77,8 @@ fn Hold(hold: models::Hold, #[prop(into)] role: Signal<Option<HoldRole>>) -> imp
Some(HoldRole::Normal) => Some("outline outline-offset-2 outline-blue-500"),
Some(HoldRole::Zone) => Some("outline outline-offset-2 outline-amber-500"),
Some(HoldRole::End) => Some("outline outline-offset-2 outline-red-500"),
None => Some("brightness-50"),
// None => Some("brightness-50"),
None => None,
};
let mut s = "bg-indigo-100 aspect-square rounded".to_string();
if let Some(c) = role_classes {
@ -75,12 +90,10 @@ fn Hold(hold: models::Hold, #[prop(into)] role: Signal<Option<HoldRole>>) -> imp
let img = hold.image.map(|img| {
let src = format!("/files/holds/{}", img.filename);
view! {
<img class="hover:object-scale-down object-cover w-full h-full" src=src />
}
view! { <img class="hover:object-scale-down object-cover w-full h-full" src=src /> }
});
view! { <div class=class>{ img }</div> }
view! { <div class=class>{img}</div> }
}
#[derive(Serialize, Deserialize, Clone)]