Fix navbar

This commit is contained in:
Adrian Woźniak 2023-08-15 10:26:22 +02:00
parent c9fd7128f3
commit 29e6e75e95
17 changed files with 99 additions and 2481 deletions

View File

@ -969,6 +969,11 @@ select {
padding: 1.5rem;
}
.px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.px-4 {
padding-left: 1rem;
padding-right: 1rem;
@ -1039,6 +1044,11 @@ select {
color: rgb(17 24 39 / var(--tw-text-opacity));
}
.text-neutral-500 {
--tw-text-opacity: 1;
color: rgb(115 115 115 / var(--tw-text-opacity));
}
.text-red-700 {
--tw-text-opacity: 1;
color: rgb(185 28 28 / var(--tw-text-opacity));
@ -1061,16 +1071,42 @@ select {
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.transition {
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.duration-200 {
transition-duration: 200ms;
}
.hover\:bg-gray-100:hover {
--tw-bg-opacity: 1;
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
}
.hover\:text-neutral-700:hover {
--tw-text-opacity: 1;
color: rgb(64 64 64 / var(--tw-text-opacity));
}
.hover\:ease-in-out:hover {
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
.focus\:border-blue-500:focus {
--tw-border-opacity: 1;
border-color: rgb(59 130 246 / var(--tw-border-opacity));
}
.focus\:text-neutral-700:focus {
--tw-text-opacity: 1;
color: rgb(64 64 64 / var(--tw-text-opacity));
}
.focus\:outline-none:focus {
outline: 2px solid transparent;
outline-offset: 2px;
@ -1112,6 +1148,16 @@ select {
--tw-ring-offset-width: 2px;
}
.disabled\:text-black\/30:disabled {
color: rgb(0 0 0 / 0.3);
}
@media (prefers-reduced-motion: reduce) {
.motion-reduce\:transition-none {
transition-property: none;
}
}
@media (prefers-color-scheme: dark) {
.dark\:divide-gray-600 > :not([hidden]) ~ :not([hidden]) {
--tw-divide-opacity: 1;
@ -1153,6 +1199,11 @@ select {
color: rgb(156 163 175 / var(--tw-text-opacity));
}
.dark\:text-neutral-200 {
--tw-text-opacity: 1;
color: rgb(229 229 229 / var(--tw-text-opacity));
}
.dark\:text-white {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
@ -1178,6 +1229,11 @@ select {
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
}
.dark\:hover\:text-neutral-400:hover {
--tw-text-opacity: 1;
color: rgb(163 163 163 / var(--tw-text-opacity));
}
.dark\:hover\:text-white:hover {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
@ -1188,6 +1244,11 @@ select {
border-color: rgb(59 130 246 / var(--tw-border-opacity));
}
.dark\:focus\:text-neutral-400:focus {
--tw-text-opacity: 1;
color: rgb(163 163 163 / var(--tw-text-opacity));
}
.dark\:focus\:ring-blue-500:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity));
@ -1290,3 +1351,14 @@ select {
}
}
}
.\[\&\.active\]\:text-black\/90.active {
color: rgb(0 0 0 / 0.9);
}
@media (prefers-color-scheme: dark) {
.dark\:\[\&\.active\]\:text-neutral-400.active {
--tw-text-opacity: 1;
color: rgb(163 163 163 / var(--tw-text-opacity));
}
}

View File

@ -1,6 +1,6 @@
<div class="flex items-center md:order-2">
{% match opts.session %}
{% when Some with (session) %}
<div class="flex items-center md:order-2">
<button
type="button"
class="flex mr-3 text-sm bg-gray-800 rounded-full md:mr-0 focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600"
@ -39,6 +39,30 @@
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h15M1 7h15M1 13h15"/>
</svg>
</button>
{% when None %}
<a
class="flex items-center px-2 text-neutral-500 transition duration-200 hover:text-neutral-700 hover:ease-in-out focus:text-neutral-700 disabled:text-black/30 motion-reduce:transition-none dark:text-neutral-200 dark:hover:text-neutral-400 dark:focus:text-neutral-400 [&.active]:text-black/90 dark:[&.active]:text-neutral-400"
href="/login"
hx-get='/login'
hx-target='main'
hx-headers='{"Accept":"text/html-partial"}'
data-te-dropdown-toggle-ref
aria-expanded="false"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
stroke-width="1.5"
stroke="currentColor"
class="h-5 w-5"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z"
/>
</svg>
</a>
{% endmatch %}
</div>
{% when None %}
{% endmatch %}

View File

@ -1,19 +0,0 @@
[package]
name = "web"
version = "0.1.0"
edition = "2021"
[dependencies]
bincode = { version = "1.3.3", features = [] }
console_error_panic_hook = "0.1.7"
contract = { path = "../contract" }
serde = { version = "*", features = ['derive'] }
serde-wasm-bindgen = "*"
serde_json = { version = "*" }
sycamore = { version = "0.8.2", features = ['suspense'] }
sycamore-router = { version = "0.8" }
tracing = { version = "*" }
tracing-subscriber = { version = "*" }
tracing-subscriber-wasm = { version = "0.1.0" }
wasm_request = { version = "0.1.1" }
web-sys = { version = "0.3.61", features = ['Headers'] }

View File

@ -1,7 +0,0 @@
{
"dependencies": {
"@tailwindcss/line-clamp": "^0.4.4",
"tailwind": "^4.0.0",
"update-browserslist-db": "^1.0.11"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +0,0 @@
use sycamore::prelude::*;
#[component]
pub fn Footer<G: Html>(cx: Scope) -> View<G> {
view! {
cx,
div(class="w-full h-64 xl:h-16 relative") {
footer(class="w-full absolute bottom-0") {
div(class="container mx-auto px-4") {
div(class="items-center xl:justify-between flex flex-wrap -mx-4") {
div(class="px-4 relative w-full xl:w-6/12 w-full sm:w-full") {
div(class="text-sm text-gray-200 text-center xl:text-left py-6") {
"Copyright © 2021"
a(href="https://ita-prog.pl", target="_blank", class="text-blueGray-100 font-semibold ml-1") {
"ITA Prog"
}
". All rights reserved."
}
}
div(class="px-4 relative w-full xl:w-6/12 w-full sm:w-full") {
ul(class="justify-center xl:justify-end mx-auto flex flex-wrap list-none pl-0 mb-0") {
li() {a(target = "__blank") {}}
li() {a(target = "__blank") {}}
li() {a(target = "__blank") {}}
}
}
}
}
}
}
}
}

View File

@ -1,64 +0,0 @@
use sycamore::prelude::*;
#[component]
pub fn Header<G: Html>(cx: Scope) -> View<G> {
view!(cx, div(class = "px-4 py-5 flex-auto ct-docs-frame") {
div(class = "relative flex flex-wrap justify-center bg-blueGray-100") {
div(class = "w-full h-16 relative") {
nav(class = "absolute w-full z-50 flex flex-wrap items-center justify-between px-2 py-3 mb-3 lg:bg-transparent bg-white") {
div(class = "flex container mx-auto flex flex-wrap items-center justify-between px-0 lg:px-4") {
a(
class = "text-sm font-bold leading-relaxed inline-flex items-center mr-4 py-2 whitespace-nowrap uppercase text-blueGray-500",
href = "/"
) {
img(class = "rounded-full mr-2", style = "width: 30px") {}
span() { "OS Wilno" }
button(class="ml-auto cursor-pointer text-xl leading-none px-3 py-1 border border-solid border-blueGray-400 rounded bg-transparent block outline-none focus:outline-none text-blueGray-300 lg:hidden", type="button") {
i(class="fas fa-bars")
}
div(class="items-center w-full lg:flex lg:w-auto flex-grow duration-300 transition-all ease-in-out hidden") {
ul(class="lg:items-center lg:ml-auto flex flex-wrap list-none pl-0 mb-0 flex flex-col list-none pl-0 mb-0 lg:flex-row") {
li {
a(class="hover:opacity-75 px-3 py-4 lg:py-2 flex items-center text-xs uppercase font-bold transition-all duration-150 ease-in-out") {
"Usługi"
}
}
li {
a(class="hover:opacity-75 px-3 py-4 lg:py-2 flex items-center text-xs uppercase font-bold transition-all duration-150 ease-in-out") {
"Garaż"
}
}
li(class = "relative") {
a(class="hover:opacity-75 px-3 py-4 lg:py-2 flex items-center text-xs uppercase font-bold transition-all duration-150 ease-in-out text-blueGray-800", href="") {
"Demo Pages"
i(class="ml-1 fas fa-caret-down transition-all duration-200 ease-in-out transform")
}
div(class="hidden z-50") {
div(class="origin-top-right bg-white text-base float-left p-2 border list-none text-left rounded-lg shadow-lg min-w-48 transition-all duration-100 ease-in-out transform scale-95 opacity-0 absolute") {
span(class="uppercase font-bold text-xs px-3 pt-4 block w-full whitespace-nowrap bg-transparent text-blueGray-400") {
"Group 1"
}
a(class="text-sm px-3 py-2 block w-full whitespace-nowrap bg-transparent hover:bg-blueGray-100 rounded transition-all duration-100") {
"Demo page 1"
}
a(class="text-sm px-3 py-2 block w-full whitespace-nowrap bg-transparent hover:bg-blueGray-100 rounded transition-all duration-100") {
"Demo page 2"
}
span(class="uppercase font-bold text-xs px-3 pt-4 block w-full whitespace-nowrap bg-transparent text-blueGray-400") { "Group 2" }
}
}
}
li(class = "relative") {
a(class="hover:opacity-75 px-3 py-4 lg:py-2 flex items-center text-xs uppercase font-bold transition-all duration-150 ease-in-out", href = "/account") {
"Account"
}
}
}
}
}
}
}
}
}
})
}

View File

@ -1,7 +0,0 @@
mod card;
mod footer;
mod header;
pub use card::*;
pub use footer::*;
pub use header::*;

View File

@ -1,23 +0,0 @@
mod components;
mod pages;
use pages::AppRoutes;
use sycamore::prelude::*;
use tracing_subscriber_wasm::MakeConsoleWriter;
fn main() {
console_error_panic_hook::set_once();
tracing_subscriber::fmt::fmt()
.with_ansi(false)
.with_writer(MakeConsoleWriter::default().map_trace_level_to(tracing::Level::DEBUG))
.without_time()
.init();
sycamore::render(|cx| {
view! { cx,
main() {
AppRoutes()
}
}
});
}

View File

@ -1,7 +0,0 @@
pub mod details;
pub mod register;
pub mod sign_in;
use details::*;
use register::*;
use sign_in::*;

View File

@ -1,105 +0,0 @@
use sycamore::prelude::*;
#[component]
pub fn SignIn<G: Html>(cx: Scope) -> View<G> {
let name = create_signal(cx, "".to_string());
let pass = create_signal(cx, "".to_string());
let agree = create_signal(cx, false);
view!(
cx,
div(class="flex content-center items-center justify-center h-full") {
div(class="w-full lg:w-5/12 px-4") {
div(class="relative flex flex-col w-full mb-6 shadow-lg rounded-lg bg-white") {
div(class="mb-0 px-6 py-6") {
div(class="text-center mb-3") {
h6(class="text-blueGray-500 text-sm font-bold") { "Sign up with" }
}
div(class="text-center") {
a(
class="inline-block outline-none focus:outline-none align-middle transition-all duration-150 ease-in-out uppercase border border-solid font-bold last:mr-0 mr-2 text-white bg-github-regular border-github-regular active:bg-github-active active:border-github-active text-xs px-3 py-2 shadow hover:shadow-md rounded-md",
style="background-color: rgba(34, 34, 34, var(--tw-bg-opacity))"
) {
i( class="mr-1 fab fa-solid fa-github")
" github"
}
a(
class="inline-block outline-none focus:outline-none align-middle transition-all duration-150 ease-in-out uppercase border border-solid font-bold last:mr-0 mr-2 text-white bg-facebook-regular border-facebook-regular active:bg-facebook-active active:border-facebook-active text-xs px-3 py-2 shadow hover:shadow-md rounded-md",
style="background-color: rgba(59, 89, 153, var(--tw-bg-opacity))"
) {
i(class="mr-1 fab fa-solid fa-facebook")
" facebook"
}
}
hr(class="mt-6 border-b-1 border-blueGray-200")
}
div(class="flex-auto px-4 lg:px-10 py-10 pt-0") {
div(class="text-blueGray-500 text-center mb-3 font-bold") {
small { "Or sign up with credentials" }
}
form(data-bitwarden-watching="1") {
div(class="relative w-full") {
label(
class="block uppercase text-blueGray-500 text-xs font-bold mb-2 ml-1"
) {
"Name"
}
div(class="mb-3 pt-0") {
input(
placeholder="Name",
type="text",
bind:value=name,
class="border-blueGray-300 px-3 py-2 text-sm w-full placeholder-blueGray-200 text-blueGray-700 relative bg-white rounded-md outline-none focus:ring focus:ring-lightBlue-500 focus:ring-1 focus:border-lightBlue-500 border border-solid transition duration-200"
)
}
}
div(
class="relative w-full"
) {
label(
class="block uppercase text-blueGray-500 text-xs font-bold mb-2 ml-1"
) {
"Password"
}
div(class="mb-3 pt-0") {
input(
placeholder="Password",
type="password",
bind:value=pass,
class="border-blueGray-300 px-3 py-2 text-sm w-full placeholder-blueGray-200 text-blueGray-700 relative bg-white rounded-md outline-none focus:ring focus:ring-lightBlue-500 focus:ring-1 focus:border-lightBlue-500 border border-solid transition duration-200 "
)
}
}
div(
class="mt-2 inline-block"
) {
label(
class="inline-flex items-center cursor-pointer"
) {
input(
type="checkbox",
bind:checked=agree,
class="form-checkbox appearance-none ml-1 w-5 h-5 ease-linear transition-all duration-150 border border-blueGray-300 rounded checked:bg-blueGray-700 checked:border-blueGray-700 focus:border-blueGray-300"
)
span(class="ml-2 text-sm font-semibold text-blueGray-500") {
"I agree with the Privacy Policy"
}
}
}
div(class="text-center mt-5") {
a(
href="/register",
class="inline-block outline-none focus:outline-none align-middle transition-all duration-150 ease-in-out uppercase border border-solid font-bold last:mr-0 mr-2 text-white bg-blueGray-800 border-blueGray-800 active:bg-blueGray-900 active:border-blueGray-900 text-sm px-6 py-2 shadow hover:shadow-lg rounded-md w-full text-center",
style="background-color: rgba(30, 41, 59, var(--tw-bg-opacity))"
) {
"Create account"
}
}
}
}
}
}
}
)
}

View File

@ -1,103 +0,0 @@
use contract::LocalBusinessItem;
use sycamore::prelude::*;
#[derive(Prop)]
pub struct LocalBusinessCardProps {
name: String,
desc: String,
items: Vec<LocalBusinessItem>,
}
#[component]
pub fn LocalBusinessCard<G: Html>(cx: Scope<'_>, props: LocalBusinessCardProps) -> View<G> {
let items = create_signal(cx, props.items);
view! {
cx,
div(class = "px-4 relative w-full md:w-4/12") {
div(class = "mb-6 text-center shadow-lg rounded-lg relative flex flex-col bg-white p-6 w-full mb-6") {
div(class = "py-6 flex-auto") {
div(class = "shadow-lg mt-6 rounded-full my-6 mx-auto w-100-px p-6 bg-white") {
img(class = "mx-auto", src = "data:image/png;base64,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") {}
}
h4(class = "text-2xl font-bold leading-tight mt-0 mb-2") { (props.name) }
p(class="text-blueGray-500 px-8 line-clamp-2") { (props.desc) }
div(class = "flex justify-center mt-8 mb-2 text-blueGray-400") {
div(class = "flex items-center") {
Indexed(
iterable=items,
view=|cx, item| view! { cx,
BusinessItem(
url = item.picture_url,
name = item.name
)
}
)
}
}
Rating(rating = 37)
}
}
}
}
}
#[derive(Prop)]
pub struct BusinessItemProps {
name: String,
url: String,
}
#[component]
pub fn BusinessItem<G: Html>(cx: Scope<'_>, props: BusinessItemProps) -> View<G> {
view!(
cx,
a(
class="text-white bg-blueGray-500 inline-flex items-center justify-center shadow-lg rounded rounded-full relative border-2 border-white -ml-4 hover:z-1 w-10 h-10",
title = props.name
) {
img(class="rounded-full w-full", src=(props.url)) {}
div(class = "hidden") {
div(class = "border-0 mb-3 block z-50 font-normal leading-normal text-sm text-left no-underline break-words rounded") {
div(class = "py-1 px-2 text-center rounded text-white bg-black") { "Photo" }
}
}
}
)
}
#[derive(Prop)]
struct RatingProps {
rating: u8,
}
#[component]
fn Rating<G: Html>(cx: Scope, props: RatingProps) -> View<G> {
let rating = props.rating;
let has_half = rating % 10 != 0;
let full = rating / 10;
let empty = if has_half { 4 - full } else { 5 - full };
let full_it = create_signal(cx, (0..full).collect::<Vec<_>>());
let empty_it = create_signal(cx, (0..empty).collect::<Vec<_>>());
view! {
cx,
div(class="w-full") {
div(class="text-orange-500") {
Indexed(
iterable = full_it,
view = |cx, _| view!(cx, i(class="mr-1 fas fa-star"))
)
(if has_half {
view!(cx, i(class="mr-1 fas fa-star-half-alt"))
} else {
view!(cx, )
})
Indexed(
iterable = empty_it,
view = |cx, _| view!(cx, i(class="mr-1 fa fa-regular fa-star"))
)
a(href="https://www.creative-tim.com", class="inline text-sm ml-1 text-blueGray-700 hover:text-blueGray-500") { "76 customer reviews" }
}
}
}
}

View File

@ -1,89 +0,0 @@
use contract::businesses::BusinessList;
use contract::*;
use sycamore::prelude::*;
use sycamore::suspense::Suspense;
use tracing::info;
use super::local_business::LocalBusinessCard;
#[component]
async fn LocalBusinessesList<G: Html>(cx: Scope<'_>) -> View<G> {
let req = wasm_request::get_options::<Vec<LocalBusiness>>(
"/api/local-businesses",
wasm_request::Method::Get,
Some({
let h = web_sys::Headers::new().unwrap();
h.append("Accept", "application/json").unwrap();
h
}),
None,
);
let payload = wasm_request::request(req).await.unwrap_or_default();
let page = serde_wasm_bindgen::from_value::<BusinessList>(payload).unwrap_or_default();
info!("{page:#?}");
let businesses = {
let businesses = page.businesses.clone();
create_signal(cx, businesses)
};
let search = create_signal(cx, "".to_string());
let visible = create_memo(cx, || {
let s = &*search.get();
let s = s.trim();
if s.is_empty() {
let b = businesses.get();
b.as_slice().to_vec()
} else {
businesses
.get()
.iter()
.filter(|b| b.name.contains(s) || b.description.contains(s))
.cloned()
.collect::<Vec<_>>()
}
});
view! {
cx,
div(class = "container mx-auto px-4") {
div(class = "items-center w-full lg:flex lg:w-auto flex-grow duration-300 transition-all ease-in-out lg:h-auto-important hidden") {
form(class = "flex flex-row flex-wrap items-center ml-auto mr-3 mt-4") {
div(class = "hover:opacity-75 px-3 py-4 lg:py-2 flex items-center text-xs uppercase font-bold transition-all duration-150 ease-in-out text-blueGray-500 pr-4") {
i(class = "lg:text-blueGray-300 text-blueGray-500 far text-lg leading-lg mr-2 fa-solid fa-magnifying-glass")
}
div(class = "mb-3 pt-0") {
input(
id = "search-local-business",
bind:value = search,
type = "search",
placeholder = "Znajdź",
class = "border-transparent shadow px-3 py-2 text-sm w-full placeholder-blueGray-200 text-blueGray-700 relative bg-white rounded-md outline-none focus:ring focus:ring-lightBlue-500 focus:ring-1 focus:border-lightBlue-500 border border-solid transition duration-200"
)
}
}
}
div(class = "mb-12 flex flex-wrap -mx-4") {
Indexed(
iterable = visible,
view = |cx, business| view! { cx,
LocalBusinessCard(
name = business.name,
desc = business.description,
items = business.items
)
}
)
}
}
}
}
#[component]
pub fn LocalBusinesses<G: Html>(cx: Scope) -> View<G> {
view!(
cx,
Suspense(fallback = view! { cx, "Loading..." }) {
LocalBusinessesList()
}
)
}

View File

@ -1,5 +0,0 @@
mod local_business;
mod local_businesses;
use local_business::*;
pub use local_businesses::*;

View File

@ -1,48 +0,0 @@
use account::sign_in::SignIn;
use local_businesses::LocalBusinesses;
use sycamore::prelude::*;
use sycamore_router::*;
use crate::components::{Footer, Header};
mod account;
mod local_businesses;
#[derive(Route)]
enum Routes {
#[to("/")]
Home,
#[to("/account")]
Account,
#[not_found]
NotFound,
}
#[component]
pub fn AppRoutes<G: Html>(cx: Scope) -> View<G> {
view! {
cx,
Header()
Router(
integration=HistoryIntegration::new(),
view=|cx, route: &ReadSignal<Routes>| {
view! {
cx,
article(class="w-full") {
(match route.get().as_ref() {
Routes::Home => view! { cx,
LocalBusinesses()
},
Routes::Account => view! { cx,
SignIn()
},
Routes::NotFound => view! { cx,
"404 Not Found"
},
})
}
}
}
)
Footer()
}
}