From b7c28f3c4ccd4111a586ecb1006b44b1854c121d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20Schr=C3=B6der?= Date: Thu, 18 Dec 2025 15:38:37 +0100 Subject: [PATCH] rss bug fixes --- src/pages/home.rs | 42 ++++++++++++--------- style/home.scss | 95 +++++++++++++++++++++-------------------------- 2 files changed, 67 insertions(+), 70 deletions(-) diff --git a/src/pages/home.rs b/src/pages/home.rs index 143a973..e0cb3f5 100644 --- a/src/pages/home.rs +++ b/src/pages/home.rs @@ -13,7 +13,6 @@ pub struct Project { pub code_url: String, } -// Deine vordefinierte Liste fn get_all_projects() -> Vec { vec![ Project { @@ -27,12 +26,20 @@ fn get_all_projects() -> Vec { Project { id: 2, title: "Anderes Projekt".into(), - description: "Beschreibung deines zweiten Projekts hier.".into(), + description: "Ein weiteres Beispielprojekt mit einer etwas längeren Beschreibung, um das Grid zu testen.".into(), image_url: "/assets/bytemalte_de.png".into(), download_url: "#".into(), code_url: "#".into(), }, - // Füge hier weitere hinzu... + Project { + id: 3, + title: "Projekt Drei".into(), + description: "Hier ist ein drittes Projekt, das ebenfalls in der Liste erscheint.".into(), + image_url: "/assets/Logo.jpg".into(), + download_url: "#".into(), + code_url: "#".into(), + }, + // Füge hier weitere Projekte hinzu... ] } @@ -41,14 +48,13 @@ pub fn HomePage() -> impl IntoView { let items_per_page = 3; let all_data = get_all_projects(); - // WICHTIG: Wir laden die erste Seite direkt hier für das SSR! + // Initialer Zustand für SSR & Client let initial_projects = all_data.iter().take(items_per_page).cloned().collect::>(); - let has_more_initially = all_data.len() > items_per_page; - + let (projects, set_projects) = signal(initial_projects); let (page, set_page) = signal(1); let (loading, set_loading) = signal(false); - let (all_loaded, set_all_loaded) = signal(!has_more_initially); + let (all_loaded, set_all_loaded) = signal(all_data.len() <= items_per_page); let sentinel = NodeRef::
::new(); @@ -66,7 +72,7 @@ pub fn HomePage() -> impl IntoView { return; } - // Simuliere Netzwerk-Delay für den Spinner + // Kurze Verzögerung für den Lade-Effekt set_timeout(move || { let slice = all_my_projects[start..end].to_vec(); set_projects.update(|projs| projs.extend(slice)); @@ -75,10 +81,9 @@ pub fn HomePage() -> impl IntoView { set_all_loaded.set(true); } set_loading.set(false); - }, std::time::Duration::from_millis(300)); + }, std::time::Duration::from_millis(200)); }; - // Scroll-Event-Listener (Nur im Browser aktiv) Effect::new(move |_| { let w = window(); let w_clone = w.clone(); @@ -92,10 +97,10 @@ pub fn HomePage() -> impl IntoView { let inner_height = w_clone.inner_height().unwrap().as_f64().unwrap_or(0.0); let total_height = el.offset_height() as f64; - if scroll_y + inner_height >= total_height - 250.0 { - let next_page = page.get_untracked(); - set_page.set(next_page + 1); - fetch_projects(next_page); + if scroll_y + inner_height >= total_height - 300.0 { + let current_page = page.get_untracked(); + set_page.set(current_page + 1); + fetch_projects(current_page); } } } @@ -110,7 +115,8 @@ pub fn HomePage() -> impl IntoView {

"Entdecke meine neuesten Projekte."

-
+ // Der Container MUSS die Klasse projects-grid haben +
impl IntoView {

{p.title}

{p.description}

} } /> - +
{move || match (loading.get(), all_loaded.get()) { diff --git a/style/home.scss b/style/home.scss index 6f0fec9..f7d4b30 100644 --- a/style/home.scss +++ b/style/home.scss @@ -1,66 +1,63 @@ .home-container { - max-width: 1200px; + max-width: 1100px; margin: 0 auto; - padding: 0 1.5rem; + padding: 0 1rem; } .projects-grid { display: grid; - grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); + // Sorgt dafür, dass die Karten immer gleich breit sind + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 2rem; - margin-top: 2rem; + margin: 2rem 0; + // Verhindert Layout-Shifts + align-items: stretch; } .project-card { background: var(--white); - border-radius: 1.25rem; - overflow: hidden; + border-radius: 1rem; border: 1px solid var(--border); - transition: transform 0.3s ease, box-shadow 0.3s ease; + overflow: hidden; display: flex; flex-direction: column; + transition: transform 0.2s ease, box-shadow 0.2s ease; + height: 100%; // Wichtig für einheitliche Höhe im Grid &:hover { - transform: translateY(-8px); - box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1); + transform: translateY(-5px); + box-shadow: 0 10px 20px rgba(0,0,0,0.05); } .project-image { - width: 100%; - height: 200px; - background: #eef2ff; - overflow: hidden; - + height: 180px; + background: #f1f5f9; img { width: 100%; height: 100%; object-fit: cover; - transition: transform 0.5s ease; + display: block; } } - &:hover .project-image img { - transform: scale(1.05); - } - .project-content { - padding: 1.5rem; + padding: 1.25rem; display: flex; flex-direction: column; - flex: 1; + flex-grow: 1; h3 { - margin: 0 0 0.75rem 0; + margin: 0 0 0.5rem 0; font-size: 1.25rem; color: var(--text-main); } p { - margin: 0 0 1.5rem 0; - color: var(--text-light); font-size: 0.95rem; - line-height: 1.6; - flex: 1; + color: var(--text-light); + line-height: 1.5; + margin-bottom: 1.5rem; + flex-grow: 1; // Drückt die Buttons nach unten } } @@ -70,13 +67,14 @@ gap: 0.75rem; a { + display: inline-block; text-decoration: none; padding: 0.6rem; - border-radius: 0.75rem; + border-radius: 0.5rem; font-size: 0.85rem; font-weight: 600; text-align: center; - transition: all 0.2s; + transition: background 0.2s; } .btn-download { @@ -86,42 +84,35 @@ } .btn-code { - background: #f1f5f9; + background: var(--bg); color: var(--text-main); - &:hover { background: #e2e8f0; } + border: 1px solid var(--border); + &:hover { background: var(--border); } } } } .loading-trigger { - display: flex; - justify-content: center; - align-items: center; - min-height: 150px; - padding-bottom: 50px; - color: var(--text-light); + text-align: center; + padding: 3rem 0; + min-height: 100px; +} - p { font-size: 0.9rem; opacity: 0.7; } +.end-msg { + color: var(--text-light); + font-size: 0.9rem; + border-top: 1px solid var(--border); + padding-top: 2rem; } .spinner { - width: 40px; - height: 40px; - border: 3px solid rgba(99, 102, 241, 0.1); + width: 30px; + height: 30px; + border: 3px solid var(--border); border-top-color: var(--primary); border-radius: 50%; + margin: 0 auto; animation: spin 0.8s linear infinite; } -@keyframes spin { - to { transform: rotate(360deg); } -} - -@media (max-width: 640px) { - .projects-grid { - grid-template-columns: 1fr; - } - .home-hero h1 { - font-size: 2.5rem; - } -} \ No newline at end of file +@keyframes spin { to { transform: rotate(360deg); } } \ No newline at end of file