mod error;
mod login;
mod orthography;
mod phonemes;
mod phonotactics;
use leptos::*;
use leptos_mview::*;
use leptos_router::{Route, Router, Routes, A};
use leptos_use::{use_color_mode_with_options, ColorMode, UseColorModeOptions, UseColorModeReturn};
use phosphor_leptos::{Cube, Heart, Horse, IconWeight, List as Menu, Moon, Sun};
#[component]
fn DarkModeToggle() -> impl IntoView {
let UseColorModeReturn { mode, set_mode, .. } = use_color_mode_with_options(
UseColorModeOptions::default()
.custom_modes(vec!["fantasy".to_string()])
.attribute("data-theme"),
);
let light_mode = ColorMode::Custom("fantasy".to_string());
view! {
<label class="flex cursor-pointer items-center gap-2">
<Sun class="size-8"/>
<input
class="toggle theme-controller"
type="checkbox"
prop:checked=move || mode.get() == ColorMode::Dark
on:input=move |_| {
set_mode
.update(|mode| {
*mode = match mode {
ColorMode::Auto => ColorMode::Dark,
ref mode if mode == &&light_mode => ColorMode::Dark,
ColorMode::Dark => light_mode.clone(),
_ => ColorMode::Dark,
};
})
}
/>
<Moon class="size-8"/>
</label>
}
}
#[component]
fn AppNavbar() -> impl IntoView {
use crate::app::login::LoginAvatar;
let nav_contents = move || {
mview! {
li {
A href="demo" active_class="active" {
"Demo"
}
}
li {
details {
summary { "Phonology" }
ul class="bg-base-200 rounded-t-none" {
li {
details class="min-w-40" {
summary { "Phonetics" }
ul {
li {
A href="phonemes" active_class="active" {
"Phonemes"
}
}
li {
A href="phonotactics" active_class="active" {
"Phonotactics"
}
}
}
}
}
li {
A href="orthography" active_class="active" {
"Orthography"
}
}
}
}
}
}
};
mview! {
nav class="navbar bg-base-200" {
div class="navbar-start" {
div class="dropdown dropdown-hover" {
div role="button" tabindex=0 class="btn btn-ghost lg:hidden" {
Menu class="size-8";
}
ul tabindex=0 class="menu menu-sm dropdown-content z-[1] p-2 shadow bg-base-200 rounded-box w-52" {
{nav_contents()}
}
}
A href="" class="btn btn-ghost text-xl" { "Noteboek" }
}
div class="navbar-center hidden lg:flex" {
ul class="menu menu-horizontal px-1 space-x-2" {
{nav_contents()}
}
}
div class="navbar-end space-x-4" {
LoginAvatar;
DarkModeToggle;
}
}
}
}
#[component]
fn DemoView() -> impl IntoView {
tracing::info!("woop");
tracing::warn!("woop");
tracing::error!("woop");
let (count, set_count) = create_signal(0);
mview! {
div.prose.prose-zinc {
h1 { "Hello, world! 🐢" }
p { "Hello, world! 🐢" }
}
div {
h1 { "Hello, world! 🐢" }
p { "Hello, world! 🐢" }
}
button.btn.btn-primary on:click={move |_| set_count.update(|n| *n += 1)} {"Click me: " {move || count.get()}}
Horse;
Heart color="#AE2983" weight={IconWeight::Fill} size="32px";
Cube color="teal" weight={IconWeight::Bold};
Cube.text-slate-200 mirrored={true} weight={IconWeight::Duotone};
Cube color="teal" weight={IconWeight::Fill};
Cube color="teal" weight={IconWeight::Light};
Cube color="teal" weight={IconWeight::Regular};
Cube color="teal" weight={IconWeight::Thin};
}
}
#[derive(Clone, Copy, Debug)]
struct UserStatusResource(pub(crate) Resource<(), Result<login::UserStatus, gloo_net::Error>>);
#[component]
pub fn App() -> impl IntoView {
let user_status = UserStatusResource(create_local_resource(
|| (),
|_| async move { login::fetch_user_status().await },
));
provide_context(user_status);
mview! {
Router {
AppNavbar;
main {
Routes {
Route path="demo" view=[DemoView];
Route path="login" view=[login::LoginView];
Route path="phonotactics" view=[phonotactics::PhonotacticsView];
Route path="phonemes" view=[phonemes::PhonemesView];
Route path="orthography" view=[orthography::OrthographyView];
}
}
}
}
}