feat(ui): add AppHeader support to 404 not-found page
All checks were successful
Deploy Waveform to VPS / deploy (push) Successful in 1m17s

This commit is contained in:
Chneemann 2026-10-15 04:09:09 +02:00
parent 3a0a4041c2
commit 38d1a8ab70
No known key found for this signature in database
2 changed files with 37 additions and 19 deletions

View file

@ -3,27 +3,30 @@
* @description Server component rendering a custom 404 page for missing or invalid routes within the app layout. * @description Server component rendering a custom 404 page for missing or invalid routes within the app layout.
*/ */
import { AppHeader } from "@/components/layout/AppHeader";
import { AlertCircle } from "lucide-react"; import { AlertCircle } from "lucide-react";
/** Renders the 404 Not Found fallback view containing an alert icon, message, and navigation link back to the summary page. */ /** Renders the 404 Not Found fallback view containing an alert icon, message, and navigation link back to the summary page. */
export default function NotFound() { export default function NotFound() {
return ( return (
<div className="flex flex-col items-center justify-center h-full w-full text-center my-auto"> <div className="flex flex-col h-full w-full bg-background p-4 min-h-0 overflow-hidden">
<div className="max-w-md w-full space-y-6"> <AppHeader isNotFound />
{/* Icon Badge */} <div className="flex flex-col items-center justify-center h-full w-full text-center my-auto">
<div className="mx-auto w-16 h-16 rounded-2xl bg-destructive-bg border border-destructive-border flex items-center justify-center text-destructive shadow-sm"> <div className="max-w-md w-full space-y-6">
<AlertCircle size={36} /> {/* Icon Badge */}
</div> <div className="mx-auto w-16 h-16 rounded-2xl bg-destructive-bg border border-destructive-border flex items-center justify-center text-destructive shadow-sm">
<AlertCircle size={36} />
</div>
{/* Text Content */} {/* Text Content */}
<div className="space-y-2"> <div className="space-y-2">
<h1 className="text-2xl font-bold tracking-tight text-foreground"> <h1 className="text-2xl font-bold tracking-tight text-foreground">
Page not found Page not found
</h1> </h1>
<p className="text-sm text-foreground-muted leading-relaxed"> <p className="text-sm text-foreground-muted leading-relaxed">
The page you are looking for doesn't exist or has been moved. Please The page you are looking for doesn't exist or has been moved.
check the URL or head back to your summary. </p>
</p> </div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,6 +1,6 @@
/** /**
* @file components/layout/AppHeader.tsx * @file components/layout/AppHeader.tsx
* @description Application top header component providing navigation controls, dynamic channel or friend tab titles, optional server settings, member list toggles, and legal views support. * @description Application top header component providing navigation controls, dynamic channel or friend tab titles, optional server settings, member list toggles, legal views, and 404 support.
*/ */
"use client"; "use client";
@ -14,6 +14,7 @@ import {
Settings, Settings,
FileText, FileText,
ShieldCheck, ShieldCheck,
AlertCircle,
} from "lucide-react"; } from "lucide-react";
import { ServerSettingsMenu } from "./ServerSettingsMenu"; import { ServerSettingsMenu } from "./ServerSettingsMenu";
import { FriendsHeader, TabType } from "@/components/friends/FriendsHeader"; import { FriendsHeader, TabType } from "@/components/friends/FriendsHeader";
@ -35,9 +36,10 @@ interface AppHeaderProps {
isSettings?: boolean; isSettings?: boolean;
isLegalImprint?: boolean; isLegalImprint?: boolean;
isLegalPrivacy?: boolean; isLegalPrivacy?: boolean;
isNotFound?: boolean;
} }
/** Renders the application header with navigation controls, dynamic titles, tabs, and action buttons. */ /** Renders the application header with navigation controls, dynamic titles, tabs, action buttons, and 404 support. */
export function AppHeader({ export function AppHeader({
title, title,
showMembersButton = false, showMembersButton = false,
@ -50,6 +52,7 @@ export function AppHeader({
isSettings = false, isSettings = false,
isLegalImprint = false, isLegalImprint = false,
isLegalPrivacy = false, isLegalPrivacy = false,
isNotFound = false,
}: AppHeaderProps) { }: AppHeaderProps) {
const { isNavOpen, toggleNav, toggleMembers } = useSidebarStore(); const { isNavOpen, toggleNav, toggleMembers } = useSidebarStore();
@ -62,7 +65,8 @@ export function AppHeader({
!!server || !!server ||
showFriendsTabs || showFriendsTabs ||
isSettings || isSettings ||
isLegalView; isLegalView ||
isNotFound;
return ( return (
<div <div
@ -87,6 +91,16 @@ export function AppHeader({
)} )}
</button> </button>
{/* 404 Not Found Header Title */}
{isNotFound && (
<div className="flex items-center gap-1.5 ml-1 min-w-0">
<AlertCircle className="w-4 h-4 text-destructive shrink-0" />
<h1 className="font-bold text-white text-base truncate">
Not Found
</h1>
</div>
)}
{/* Settings View Header Title */} {/* Settings View Header Title */}
{isSettings && ( {isSettings && (
<div className="flex items-center gap-1.5 ml-1 min-w-0"> <div className="flex items-center gap-1.5 ml-1 min-w-0">
@ -116,7 +130,7 @@ export function AppHeader({
)} )}
{/* Dynamic Channel Title */} {/* Dynamic Channel Title */}
{!isSettings && !isLegalView && title && ( {!isSettings && !isLegalView && !isNotFound && title && (
<div className="flex items-center gap-1.5 ml-1 min-w-0"> <div className="flex items-center gap-1.5 ml-1 min-w-0">
<Hash className="w-4 h-4 text-muted shrink-0" /> <Hash className="w-4 h-4 text-muted shrink-0" />
<h1 className="font-bold text-white text-base truncate">{title}</h1> <h1 className="font-bold text-white text-base truncate">{title}</h1>
@ -126,6 +140,7 @@ export function AppHeader({
{/* Friends Header Component */} {/* Friends Header Component */}
{!isSettings && {!isSettings &&
!isLegalView && !isLegalView &&
!isNotFound &&
showFriendsTabs && showFriendsTabs &&
setActiveTab && setActiveTab &&
activeTab && ( activeTab && (