shell.rs
⎇
Raw
1use leptos::prelude::*;
2use wasm_bindgen_futures::spawn_local;
3
4use crate::api::{self, Me};
5use crate::app::AuthPhase;
6
7#[component]
8pub fn ShellView(
9 me: ReadSignal<Option<Me>>,
10 set_me: WriteSignal<Option<Me>>,
11 set_phase: WriteSignal<AuthPhase>,
12) -> impl IntoView {
13 let on_logout = move |_| {
14 spawn_local(async move {
15 let _ = api::logout().await;
16 set_me.set(None);
17 set_phase.set(AuthPhase::Login);
18 });
19 };
20
21 view! {
22 <div class="layout">
23 <header class="topbar">
24 <div class="brand">"📂 filebrowser-ng"</div>
25 <div class="topbar-right">
26 {move || {
27 let Some(m) = me.get() else {
28 return None;
29 };
30 let u = m.user?;
31 let is_admin = u.is_admin;
32 Some(
33 view! {
34 <span class="user-badge">
35 {u.name}
36 <Show when=move || is_admin>
37 <span class="badge">"admin"</span>
38 </Show>
39 </span>
40 }
41 .into_view()
42 .into_any(),
43 )
44 }}
45 <button class="btn" on:click=on_logout>"Log out"</button>
46 </div>
47 </header>
48 <main class="content">
49 <div class="card welcome-card">
50 {move || {
51 let Some(m) = me.get() else {
52 return None;
53 };
54 let u = m.user?;
55 Some(view! { "Welcome, " {u.name} "!" }.into_view().into_any())
56 }}
57 <p class="muted">
58 "You're signed in — auth, sessions and your configured
59 folders are working. The file browser itself arrives in
60 the next milestone."
61 </p>
62 <h2 class="section-title">"Your folders"</h2>
63 {move || {
64 let Some(m) = me.get() else {
65 return None;
66 };
67 Some(
68 view! {
69 <ul class="roots">
70 {m.roots.iter().map(|r| {
71 let name = r.name.clone();
72 let path = r.path.clone();
73 let mode = r.mode.clone();
74 view! {
75 <li>
76 <span class="root-name">{name}</span>
77 <span class="muted">{path}</span>
78 <span class="badge">
79 {if mode == "rw" {
80 "read-write"
81 } else {
82 "read-only"
83 }}
84 </span>
85 </li>
86 }
87 }).collect::<Vec<_>>()}
88 </ul>
89 }
90 .into_view()
91 .into_any(),
92 )
93 }}
94 </div>
95 </main>
96 </div>
97 }
98}
99