feat: header with campaign image, name, session #, current date and (not yet functional nor properly styled) buttons
This commit is contained in:
parent
57f0b29d5c
commit
b8e9ddcdaf
@ -5,13 +5,14 @@ use leptos_router::{
|
|||||||
StaticSegment, WildcardSegment,
|
StaticSegment, WildcardSegment,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{ prelude::*, components::{ header::Header, Dash } };
|
use crate::{ prelude::*, components::{ sidebar::Sidebar, header::Header, Dash } };
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn App() -> impl IntoView {
|
pub fn App() -> impl IntoView {
|
||||||
// Provides context that manages stylesheets, titles, meta tags, etc.
|
// Provides context that manages stylesheets, titles, meta tags, etc.
|
||||||
provide_meta_context();
|
provide_meta_context();
|
||||||
provide_context(Store::new(Dashboard::mock()));
|
provide_context(Store::new(Dashboard::mock()));
|
||||||
|
console_error_panic_hook::set_once();
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
// injects a stylesheet into the document <head>
|
// injects a stylesheet into the document <head>
|
||||||
@ -23,14 +24,16 @@ pub fn App() -> impl IntoView {
|
|||||||
|
|
||||||
// content for this welcome page
|
// content for this welcome page
|
||||||
<Router>
|
<Router>
|
||||||
|
<div class="wrapper">
|
||||||
<Header />
|
<Header />
|
||||||
<aside></aside>
|
<Sidebar />
|
||||||
<main>
|
<main>
|
||||||
<Routes fallback=move || "Not found.">
|
<Routes fallback=move || "Not found.">
|
||||||
<Route path=StaticSegment("") view=Dash/>
|
<Route path=StaticSegment("") view=Dash/>
|
||||||
<Route path=WildcardSegment("any") view=NotFound/>
|
<Route path=WildcardSegment("any") view=NotFound/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</main>
|
</main>
|
||||||
|
</div>
|
||||||
</Router>
|
</Router>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,55 @@
|
|||||||
use crate::{ entities::DashboardStoreFields, prelude::* };
|
use crate::{ entities::DashboardStoreFields, prelude::* };
|
||||||
use leptos::prelude::*;
|
use chrono::TimeDelta;
|
||||||
|
use leptos::{ logging, prelude::* };
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Header () -> impl IntoView {
|
pub fn Header () -> impl IntoView {
|
||||||
let state = expect_context::<Context>();
|
let state = expect_context::<Context>();
|
||||||
let campaign = state.campaign();
|
let campaign = state.campaign();
|
||||||
let date = state.date();
|
let date = state.date();
|
||||||
|
let session = state.session();
|
||||||
|
let image = state.campaign_image();
|
||||||
|
|
||||||
|
let adjust_day = move |adjustment: i64| date.update(|d| {
|
||||||
|
*d = d.checked_add_signed(TimeDelta::days(adjustment)).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
let adjust_session = move |adjustment: isize| session.update(|s| {
|
||||||
|
if let Some(new) = s.checked_add_signed(adjustment) {
|
||||||
|
*s = new;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Effect::new(move |_| {
|
||||||
|
logging::warn!("{}", campaign.get());
|
||||||
|
});
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<header>
|
<header>
|
||||||
<h1>Aboba v{env!("CARGO_PKG_VERSION")} by mk</h1>
|
<Show when=move || !image.get().is_empty()>
|
||||||
<h2>{campaign.get_untracked()}</h2>
|
<div class="campaign-image">
|
||||||
<h3>{move || date.get().to_string()}</h3>
|
<img src=image.get()/>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
<section>
|
||||||
|
<h5 class="version">aex v{env!("CARGO_PKG_VERSION")} by mk</h5>
|
||||||
|
<input id="campaign-name" type="text" class="header-input header-input-1 campaign-name" bind:value=campaign></input>
|
||||||
|
<div class="game-date">
|
||||||
|
<h4>{move || format!("{}", date.get().format("%d/%m/%Y"))}</h4>
|
||||||
|
<button on:click=move |_| adjust_day(-1) title="Предыдущий день" class="adjust" id="date-back">"<"</button>
|
||||||
|
<button on:click=move |_| adjust_day( 1) title="Следующий день" class="adjust" id="date-forward">">"</button>
|
||||||
|
</div>
|
||||||
|
<div class="session-number">
|
||||||
|
<h4>Сессия #{move || format!("{}", session.get())}</h4>
|
||||||
|
<button on:click=move |_| adjust_session(-1) title="Предыдущая сессия" class="adjust" id="session-back">"<"</button>
|
||||||
|
<button on:click=move |_| adjust_session( 1) title="Следующая сессия" class="adjust" id="session-forward">">"</button>
|
||||||
|
</div>
|
||||||
|
<div class="controls">
|
||||||
|
<button>Save</button>
|
||||||
|
<button>Load</button>
|
||||||
|
<button>Clear</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</header>
|
</header>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,8 +10,7 @@ pub mod sidebar;
|
|||||||
pub fn Dash () -> impl IntoView {
|
pub fn Dash () -> impl IntoView {
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<div class="wrapper">
|
main
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +1,12 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use leptos::prelude::*;
|
use leptos::prelude::*;
|
||||||
|
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn Sidebar () -> impl IntoView {
|
||||||
|
view! {
|
||||||
|
<aside>
|
||||||
|
sidebar
|
||||||
|
</aside>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
#![allow(unused_imports)]
|
||||||
pub mod app;
|
pub mod app;
|
||||||
|
|
||||||
use leptos::prelude::*;
|
use leptos::prelude::*;
|
||||||
|
|||||||
@ -13,6 +13,8 @@ async fn main() -> std::io::Result<()> {
|
|||||||
let conf = get_configuration(None).unwrap();
|
let conf = get_configuration(None).unwrap();
|
||||||
let addr = conf.leptos_options.site_addr;
|
let addr = conf.leptos_options.site_addr;
|
||||||
|
|
||||||
|
console_error_panic_hook::set_once();
|
||||||
|
|
||||||
HttpServer::new(move || {
|
HttpServer::new(move || {
|
||||||
// Generate the list of routes in your Leptos App
|
// Generate the list of routes in your Leptos App
|
||||||
let routes = generate_route_list(App);
|
let routes = generate_route_list(App);
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
|
#![allow(dead_code)]
|
||||||
pub use std::collections::{ HashMap, HashSet };
|
pub use std::collections::{ HashMap, HashSet };
|
||||||
|
|
||||||
pub use serde_json::{ Value, Map };
|
pub use serde_json::{ Value, Map };
|
||||||
|
|||||||
7
style/_mixins.scss
Normal file
7
style/_mixins.scss
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
@mixin heading {
|
||||||
|
font-family: "Neusa Next Pro";
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin text {
|
||||||
|
font-family: "Noto Serif";
|
||||||
|
}
|
||||||
143
style/main.scss
143
style/main.scss
@ -1,11 +1,136 @@
|
|||||||
|
@use 'mixins';
|
||||||
@use 'reset';
|
@use 'reset';
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-size: 1.22em;
|
font-size: 1.22em;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
@include mixins.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
@include mixins.heading;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
width: 90vw;
|
||||||
|
height: 90vh;
|
||||||
display: grid;
|
display: grid;
|
||||||
|
grid-template-rows: 100px 1fr;
|
||||||
|
grid-template-columns: 3fr 6fr;
|
||||||
|
grid-gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header, aside, main {
|
||||||
|
background: rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
header {
|
||||||
|
grid-row: 1/2;
|
||||||
|
grid-column: 1/3;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.campaign-image {
|
||||||
|
width: 100px;
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover; /* or contain, or fill */
|
||||||
|
}
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
section {
|
||||||
|
width: 100%;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 3fr 1fr;
|
||||||
|
grid-template-rows: 2fr 1fr 1fr;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.campaign-name {
|
||||||
|
font-size: 2em;
|
||||||
|
grid-row: 1/2;
|
||||||
|
grid-column: 1/2;
|
||||||
|
align-self: last baseline;
|
||||||
|
padding-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version {
|
||||||
|
font-size: 0.6em;
|
||||||
|
text-transform: lowercase;
|
||||||
|
grid-row: 1/2;
|
||||||
|
grid-column: 2/3;
|
||||||
|
align-self: start;
|
||||||
|
justify-self: end;
|
||||||
|
padding: 3px;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
grid-row: 2/4;
|
||||||
|
grid-column: 2/3;
|
||||||
|
padding: 3px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: flex-end;
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: #ccc;
|
||||||
|
padding: 3px 5px;
|
||||||
|
text-transform: lowercase;
|
||||||
|
font-size: 0.66em;
|
||||||
|
line-height: 1em;
|
||||||
|
margin: 2px 5px;
|
||||||
|
@include mixins.heading;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-date, .session-number {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
:first-child {
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
.adjust {
|
||||||
|
margin: 0 1px;
|
||||||
|
width: 20px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.4);
|
||||||
|
transition: transform .2s;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.session-number {
|
||||||
|
grid-row: 2/3;
|
||||||
|
grid-column: 1/2;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-date {
|
||||||
|
grid-row: 3/4;
|
||||||
|
grid-column: 1/2;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aside {
|
||||||
|
grid-row: 2/3;
|
||||||
|
grid-column: 1/2;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
grid-row: 2/3;
|
||||||
|
grid-column: 2/3;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
@ -19,3 +144,19 @@ input {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input.header-input {
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&-1, &-2 {
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
&-3, &-4 {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
&-5, &-6 {
|
||||||
|
font-weight: 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include mixins.heading;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user