Basic functions, Home and Community Tab

This commit is contained in:
Malte Schröder
2025-12-17 20:41:51 +01:00
commit 506f12adc2
28 changed files with 1086 additions and 0 deletions

144
src/pages/community.rs Normal file
View File

@@ -0,0 +1,144 @@
use leptos::prelude::*;
use leptos::html::Div;
use crate::backend::logic::*;
#[component]
pub fn CommunityPage() -> impl IntoView {
// --- STATE & SIGNALS ---
// Wer ist eingeloggt? (ID und Benutzername)
let (user_id, set_user_id) = signal(None::<i64>);
let (username, set_username) = signal(String::new());
// Referenz auf das Chat-Fenster für automatisches Scrollen
let scroll_ref = NodeRef::<Div>::new();
// --- DATEN-ABFRAGE (RESOURCE) ---
// Holt die Nachrichten vom Server
let messages = Resource::new(|| (), |_| async move {
get_all_messages().await.unwrap_or_default()
});
// --- ECHTZEIT-POLLING ---
// Fragt alle 2 Sekunden den Server nach neuen Nachrichten (nur im Browser)
#[cfg(not(feature = "ssr"))]
{
use std::time::Duration;
Effect::new(move |_| {
let _ = set_interval_with_handle(move || {
messages.refetch();
}, Duration::from_secs(2));
});
}
// --- AUTO-SCROLL EFFEKT ---
// Immer wenn neue Nachrichten geladen werden, scrollen wir nach ganz unten
Effect::new(move |_| {
messages.get(); // Reagiere auf Änderungen der Nachrichten
if let Some(div) = scroll_ref.get() {
request_animation_frame(move || {
div.set_scroll_top(div.scroll_height());
});
}
});
// --- SERVER ACTIONS ---
let login_action = ServerAction::<LoginOrRegister>::new();
let send_action = ServerAction::<SendMessage>::new();
// --- LOGIK-EFFEKTE ---
// 1. Login-Erfolg verarbeiten
Effect::new(move |_| {
if let Some(Ok(id)) = login_action.value().get() {
set_user_id.set(Some(id));
}
});
// 2. Nach dem Senden sofort Nachrichten aktualisieren
Effect::new(move |_| {
if send_action.value().get().is_some() {
messages.refetch();
}
});
// --- VIEW / UI ---
view! {
<div class="community-container">
{move || match user_id.get() {
// FALL A: Nutzer ist nicht eingeloggt (Anmelde-Karte)
None => view! {
<div class="auth-card">
<h2>"Community Login"</h2>
<p>"Tritt der Diskussion bei und schreibe mit Malxte."</p>
<ActionForm action=login_action>
<input
type="text"
name="user"
placeholder="Dein Name"
on:input:target=move |ev| set_username.set(ev.target().value())
required
/>
<input
type="password"
name="pass"
placeholder="Passwort"
required
/>
<button type="submit">"Beitreten"</button>
</ActionForm>
// Fehlermeldung anzeigen, falls Login fehlschlägt
{move || login_action.value().get().map(|v| match v {
Err(e) => view! { <p style="color: red; margin-top: 10px;">{e.to_string()}</p> }.into_any(),
_ => view! {}.into_any()
})}
</div>
}.into_any(),
// FALL B: Nutzer ist eingeloggt (Chat-Fenster)
Some(id) => view! {
<div class="chat-main">
<header class="chat-top-bar">
<h3>"Globaler Chat"</h3>
<span class="badge">{move || username.get()}</span>
</header>
<div class="message-area" node_ref=scroll_ref>
<Suspense fallback=|| view! { <div class="loading">"Lade Nachrichten..."</div> }>
{move || messages.get().map(|list| {
list.into_iter().map(|msg| {
let is_me = msg.username == username.get();
view! {
<div class=if is_me { "msg-row me" } else { "msg-row other" }>
<div class="msg-bubble">
<strong>{msg.username}</strong>
<p>{msg.content}</p>
</div>
</div>
}
}).collect_view()
})}
</Suspense>
</div>
<div class="chat-input-wrapper">
<ActionForm action=send_action>
// Die ID wird versteckt mitgesendet
<input type="hidden" name="user_id" value=id.to_string() />
<div class="input-group">
<input
type="text"
name="content"
placeholder="Deine Nachricht..."
required
autocomplete="off"
/>
<button type="submit">"Senden"</button>
</div>
</ActionForm>
</div>
</div>
}.into_any()
}}
</div>
}
}

9
src/pages/dashboard.rs Normal file
View File

@@ -0,0 +1,9 @@
use leptos::prelude::*;
#[component]
pub fn DashboardPage() -> impl IntoView {
view! {
<h1>"Dashboard"</h1>
<p>"Hier werden später Community-Statistiken stehen."</p>
}
}

11
src/pages/home.rs Normal file
View File

@@ -0,0 +1,11 @@
use leptos::prelude::*;
#[component]
pub fn HomePage() -> impl IntoView {
view! {
<div class="home-hero">
<h1>"Malxte."</h1>
<p>"Willkommen in der Rust-Community."</p>
</div>
}
}

2
src/pages/mod.rs Normal file
View File

@@ -0,0 +1,2 @@
pub mod home;
pub mod community; // Das hat gefehlt!