Add new pages and improve blog content display functionality
Implement new routes for articles, categories, and individual articles. Update the UI to display articles with improved content rendering, including safe HTML and media embeds. Refactor storage to use a database and add image upload capabilities. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 413891e8-d784-4bea-b9f5-91a5a68316b4 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: b96b221e-0ed6-418f-80df-e4670bf5ba4b Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/413891e8-d784-4bea-b9f5-91a5a68316b4/cftwqyT Replit-Helium-Checkpoint-Created: true
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { Link } from "wouter";
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="border-t border-border bg-card mt-16" data-testid="footer">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-10">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
<div>
|
||||
<h3 className="font-bold text-card-foreground text-lg mb-3">news.folx.tv</h3>
|
||||
<p className="text-muted-foreground text-sm leading-relaxed">
|
||||
Das Newsportal von Folx Music Television. Aktuelle Nachrichten, Interviews und
|
||||
Hintergrundberichte aus der Welt der Volksmusik und des Schlagers.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold text-card-foreground mb-3">Kategorien</h4>
|
||||
<ul className="space-y-2 text-sm">
|
||||
<li>
|
||||
<Link href="/category/News">
|
||||
<span className="text-muted-foreground cursor-pointer hover:text-primary transition-colors" data-testid="link-footer-news">
|
||||
News
|
||||
</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/category/Star-News">
|
||||
<span className="text-muted-foreground cursor-pointer hover:text-primary transition-colors" data-testid="link-footer-star-news">
|
||||
Star-News
|
||||
</span>
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold text-card-foreground mb-3">Links</h4>
|
||||
<ul className="space-y-2 text-sm">
|
||||
<li>
|
||||
<a
|
||||
href="https://folx.tv"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-muted-foreground hover:text-primary transition-colors"
|
||||
data-testid="link-footer-folxtv"
|
||||
>
|
||||
folx.tv
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="border-t border-border mt-8 pt-6 text-center">
|
||||
<p className="text-xs text-muted-foreground">
|
||||
© {new Date().getFullYear()} Folx Music Television. Alle Rechte vorbehalten.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import { Link, useLocation } from "wouter";
|
||||
import { Menu, X, Search } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useState } from "react";
|
||||
import folxLogo from "@assets/webf_1772296176957.jpg";
|
||||
|
||||
const navItems = [
|
||||
{ label: "Start", href: "/" },
|
||||
{ label: "News", href: "/category/News" },
|
||||
{ label: "Star-News", href: "/category/Star-News" },
|
||||
];
|
||||
|
||||
export default function Header() {
|
||||
const [mobileOpen, setMobileOpen] = useState(false);
|
||||
const [location] = useLocation();
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-50 bg-card/95 backdrop-blur-md border-b border-card-border" data-testid="header">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex items-center justify-between gap-4 h-16">
|
||||
<Link href="/">
|
||||
<div className="flex items-center gap-2 cursor-pointer" data-testid="link-logo">
|
||||
<div className="h-10 w-auto flex items-center">
|
||||
<img src={folxLogo} alt="Folx TV" className="h-10 w-auto object-contain rounded-sm" />
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
<nav className="hidden md:flex items-center gap-1" data-testid="nav-desktop">
|
||||
{navItems.map((item) => (
|
||||
<Link key={item.href} href={item.href}>
|
||||
<Button
|
||||
variant={location === item.href ? "default" : "ghost"}
|
||||
size="sm"
|
||||
data-testid={`link-nav-${item.label.toLowerCase().replace(/\s/g, "-")}`}
|
||||
>
|
||||
{item.label}
|
||||
</Button>
|
||||
</Link>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="md:hidden"
|
||||
onClick={() => setMobileOpen(!mobileOpen)}
|
||||
data-testid="button-mobile-menu"
|
||||
>
|
||||
{mobileOpen ? <X className="w-5 h-5" /> : <Menu className="w-5 h-5" />}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{mobileOpen && (
|
||||
<div className="md:hidden border-t border-card-border bg-card" data-testid="nav-mobile">
|
||||
<nav className="flex flex-col p-4 gap-1">
|
||||
{navItems.map((item) => (
|
||||
<Link key={item.href} href={item.href}>
|
||||
<Button
|
||||
variant={location === item.href ? "default" : "ghost"}
|
||||
className="w-full justify-start"
|
||||
onClick={() => setMobileOpen(false)}
|
||||
data-testid={`link-mobile-${item.label.toLowerCase().replace(/\s/g, "-")}`}
|
||||
>
|
||||
{item.label}
|
||||
</Button>
|
||||
</Link>
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
)}
|
||||
</header>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user