Generated by Spark: header and footer can be 1 component esch

This commit is contained in:
2025-12-24 19:12:35 +00:00
parent 8fe11dd13c
commit 38b28c0dab
7 changed files with 147 additions and 64 deletions
+2 -5
View File
@@ -6,6 +6,7 @@ import { RenderComponent } from '@/components/RenderComponent'
import { SignOut, House, List, X } from '@phosphor-icons/react'
import { toast } from 'sonner'
import { getPageRenderer, type PageDefinition, type PageContext } from '@/lib/page-renderer'
import { AppFooter } from './shared/AppFooter'
import type { User } from '@/lib/level-types'
interface GenericPageProps {
@@ -262,11 +263,7 @@ export function GenericPage({
{renderContent()}
</main>
{page.metadata?.showFooter !== false && (
<footer className="border-t border-border mt-12 py-6">
<div className="max-w-7xl mx-auto px-4 text-center text-sm text-muted-foreground">
<p>Powered by MetaBuilder</p>
</div>
</footer>
<AppFooter text="Powered by MetaBuilder" />
)}
</div>
)
+2 -5
View File
@@ -6,6 +6,7 @@ import { GodCredentialsBanner } from './level1/GodCredentialsBanner'
import { HeroSection } from './level1/HeroSection'
import { FeaturesSection } from './level1/FeaturesSection'
import { ContactSection } from './level1/ContactSection'
import { AppFooter } from './shared/AppFooter'
interface Level1Props {
onNavigate: (level: number) => void
@@ -121,11 +122,7 @@ export function Level1({ onNavigate }: Level1Props) {
<ContactSection />
<footer className="border-t border-border bg-muted/30 py-8 mt-20">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center text-sm text-muted-foreground">
<p>© 2024 MetaBuilder. Built with the power of visual workflows and declarative schemas.</p>
</div>
</footer>
<AppFooter />
</div>
)
}
+9 -30
View File
@@ -3,14 +3,14 @@ import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Textarea } from '@/components/ui/textarea'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { Avatar, AvatarFallback } from '@/components/ui/avatar'
import { User, ChatCircle, SignOut, House } from '@phosphor-icons/react'
import { User, ChatCircle } from '@phosphor-icons/react'
import { toast } from 'sonner'
import { Database, hashPassword } from '@/lib/database'
import { generateScrambledPassword, simulateEmailSend } from '@/lib/password-utils'
import { IRCWebchatDeclarative } from './IRCWebchatDeclarative'
import { ProfileCard } from './level2/ProfileCard'
import { CommentsList } from './level2/CommentsList'
import { AppHeader } from './shared/AppHeader'
import type { User as UserType, Comment } from '@/lib/level-types'
interface Level2Props {
@@ -104,34 +104,13 @@ export function Level2({ user, onLogout, onNavigate }: Level2Props) {
return (
<div className="min-h-screen bg-background">
<nav className="border-b border-border bg-card sticky top-0 z-50">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
<div className="flex items-center gap-6">
<div className="flex items-center gap-2">
<div className="w-8 h-8 rounded-lg bg-gradient-to-br from-primary to-accent" />
<span className="font-bold text-xl">MetaBuilder</span>
</div>
<Button variant="ghost" size="sm" onClick={() => onNavigate(1)}>
<House className="mr-2" size={16} />
Home
</Button>
</div>
<div className="flex items-center gap-2">
<span className="text-sm text-muted-foreground hidden sm:inline">
{currentUser.username}
</span>
<Avatar className="w-8 h-8">
<AvatarFallback>{currentUser.username[0].toUpperCase()}</AvatarFallback>
</Avatar>
<Button variant="ghost" size="sm" onClick={onLogout}>
<SignOut size={16} />
</Button>
</div>
</div>
</div>
</nav>
<AppHeader
username={currentUser.username}
showAvatar={true}
onNavigateHome={() => onNavigate(1)}
onLogout={onLogout}
variant="user"
/>
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<h1 className="text-3xl font-bold mb-8">User Dashboard</h1>
+10 -24
View File
@@ -19,9 +19,10 @@ import {
DialogTitle,
} from '@/components/ui/dialog'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { SignOut, MagnifyingGlass, Plus, PencilSimple, Trash, Users, ChatCircle, House } from '@phosphor-icons/react'
import { MagnifyingGlass, Plus, PencilSimple, Trash, Users, ChatCircle } from '@phosphor-icons/react'
import { toast } from 'sonner'
import { Database } from '@/lib/database'
import { AppHeader } from './shared/AppHeader'
import type { User as UserType, Comment } from '@/lib/level-types'
import type { ModelSchema } from '@/lib/schema-types'
@@ -96,29 +97,14 @@ export function Level3({ user, onLogout, onNavigate }: Level3Props) {
return (
<div className="min-h-screen bg-background">
<nav className="border-b border-border bg-sidebar sticky top-0 z-50">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
<div className="flex items-center gap-6">
<div className="flex items-center gap-2">
<div className="w-8 h-8 rounded-lg bg-gradient-to-br from-orange-500 to-orange-600" />
<span className="font-bold text-xl text-sidebar-foreground">Admin Panel</span>
</div>
<Button variant="ghost" size="sm" onClick={() => onNavigate(1)} className="text-sidebar-foreground">
<House className="mr-2" size={16} />
Home
</Button>
</div>
<div className="flex items-center gap-2">
<Badge variant="secondary">{user.username}</Badge>
<Button variant="ghost" size="sm" onClick={onLogout} className="text-sidebar-foreground">
<SignOut size={16} />
</Button>
</div>
</div>
</div>
</nav>
<AppHeader
title="Admin Panel"
username={user.username}
showBadge={true}
onNavigateHome={() => onNavigate(1)}
onLogout={onLogout}
variant="admin"
/>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="mb-8">
+17
View File
@@ -0,0 +1,17 @@
interface AppFooterProps {
text?: string
className?: string
}
export function AppFooter({
text = '© 2024 MetaBuilder. Built with the power of visual workflows and declarative schemas.',
className = '',
}: AppFooterProps) {
return (
<footer className={`border-t border-border bg-muted/30 py-8 mt-20 ${className}`}>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center text-sm text-muted-foreground">
<p>{text}</p>
</div>
</footer>
)
}
+105
View File
@@ -0,0 +1,105 @@
import { Button } from '@/components/ui/button'
import { Avatar, AvatarFallback } from '@/components/ui/avatar'
import { Badge } from '@/components/ui/badge'
import { SignOut, House } from '@phosphor-icons/react'
interface AppHeaderProps {
title?: string
username?: string
showAvatar?: boolean
showBadge?: boolean
onNavigateHome?: () => void
onLogout?: () => void
variant?: 'default' | 'admin' | 'user'
children?: React.ReactNode
}
export function AppHeader({
title = 'MetaBuilder',
username,
showAvatar = false,
showBadge = false,
onNavigateHome,
onLogout,
variant = 'default',
children,
}: AppHeaderProps) {
const getLogoGradient = () => {
switch (variant) {
case 'admin':
return 'bg-gradient-to-br from-orange-500 to-orange-600'
case 'user':
return 'bg-gradient-to-br from-primary to-accent'
default:
return 'bg-gradient-to-br from-primary to-accent'
}
}
const getBgClass = () => {
switch (variant) {
case 'admin':
return 'bg-sidebar'
case 'user':
return 'bg-card'
default:
return 'bg-card'
}
}
const getTextClass = () => {
return variant === 'admin' ? 'text-sidebar-foreground' : ''
}
return (
<nav className={`border-b border-border ${getBgClass()} sticky top-0 z-50`}>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
<div className="flex items-center gap-6">
<div className="flex items-center gap-2">
<div className={`w-8 h-8 rounded-lg ${getLogoGradient()}`} />
<span className={`font-bold text-xl ${getTextClass()}`}>{title}</span>
</div>
{onNavigateHome && (
<Button
variant="ghost"
size="sm"
onClick={onNavigateHome}
className={getTextClass()}
>
<House className="mr-2" size={16} />
Home
</Button>
)}
{children}
</div>
<div className="flex items-center gap-2">
{username && showBadge && (
<Badge variant="secondary">{username}</Badge>
)}
{username && showAvatar && (
<>
<span className="text-sm text-muted-foreground hidden sm:inline">
{username}
</span>
<Avatar className="w-8 h-8">
<AvatarFallback>{username[0].toUpperCase()}</AvatarFallback>
</Avatar>
</>
)}
{onLogout && (
<Button
variant="ghost"
size="sm"
onClick={onLogout}
className={getTextClass()}
>
<SignOut size={16} />
</Button>
)}
</div>
</div>
</div>
</nav>
)
}
+2
View File
@@ -0,0 +1,2 @@
export { AppHeader } from './AppHeader'
export { AppFooter } from './AppFooter'