Upload files to "/"

This commit is contained in:
2026-09-14 23:35:23 +08:00
parent 1e893db246
commit aa5c739f16
5 changed files with 1662 additions and 0 deletions
+228
View File
@@ -0,0 +1,228 @@
import React from 'react';
import {
BookOpen,
Film,
Palette,
Users,
Sparkles,
Printer,
Volume2,
VolumeX,
Moon,
Sun,
Layers,
BookMarked
} from 'lucide-react';
import { soundManager } from '../utils/audio';
export type NavTab =
| 'reader'
| 'storyboard'
| 'art'
| 'characters'
| 'adaptability'
| 'publishing'
| 'activities';
export type AgeGroup = 'toddler' | 'pictureBook' | 'earlyReader';
interface NavbarProps {
activeTab: NavTab;
setActiveTab: (tab: NavTab) => void;
ageGroup: AgeGroup;
setAgeGroup: (age: AgeGroup) => void;
isBedtimeMode: boolean;
setIsBedtimeMode: (val: boolean) => void;
soundEnabled: boolean;
setSoundEnabled: (val: boolean) => void;
onOpenPitchDeck: () => void;
}
export const Navbar: React.FC<NavbarProps> = ({
activeTab,
setActiveTab,
ageGroup,
setAgeGroup,
isBedtimeMode,
setIsBedtimeMode,
soundEnabled,
setSoundEnabled,
onOpenPitchDeck,
}) => {
const tabs = [
{ id: 'reader' as NavTab, label: 'Story Reader', icon: BookOpen, badge: 'Live Book' },
{ id: 'storyboard' as NavTab, label: 'Storyboard', icon: Film, badge: '5 Scenes' },
{ id: 'art' as NavTab, label: 'Art Direction', icon: Palette, badge: 'Palette & Style' },
{ id: 'characters' as NavTab, label: 'Characters', icon: Users, badge: 'Cast' },
{ id: 'adaptability' as NavTab, label: 'Age Editions', icon: Layers, badge: '3 Ages' },
{ id: 'publishing' as NavTab, label: 'Format & Pitch', icon: BookMarked, badge: 'Specs' },
{ id: 'activities' as NavTab, label: 'Activity Corner', icon: Sparkles, badge: 'Creative' },
];
const handleTabClick = (tabId: NavTab) => {
soundManager.playPop();
setActiveTab(tabId);
};
const handleSoundToggle = () => {
const newState = !soundEnabled;
setSoundEnabled(newState);
soundManager.enabled = newState;
if (newState) soundManager.playChime();
};
const handleBedtimeToggle = () => {
soundManager.playHarp();
setIsBedtimeMode(!isBedtimeMode);
};
return (
<header className={`sticky top-0 z-50 border-b transition-colors duration-300 backdrop-blur-md ${
isBedtimeMode
? 'bg-indigo-950/90 border-indigo-800 text-indigo-100 shadow-lg shadow-indigo-950/40'
: 'bg-[#fffdfa]/95 border-amber-200/70 text-amber-950 shadow-sm'
}`}>
{/* Top Banner with Brand and Controls */}
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-2.5 flex flex-wrap items-center justify-between gap-3">
{/* Brand */}
<div
onClick={() => handleTabClick('reader')}
className="flex items-center gap-2.5 cursor-pointer group"
>
<div className="w-10 h-10 rounded-2xl bg-gradient-to-tr from-amber-400 via-rose-300 to-sky-300 flex items-center justify-center text-xl shadow-md group-hover:scale-105 transition-transform">
🦔
</div>
<div>
<div className="flex items-center gap-2">
<span className="font-heading font-bold text-lg sm:text-xl tracking-tight leading-none text-amber-900 dark:text-amber-100 group-hover:text-amber-600 transition-colors">
Pip & the Whispering Cloud
</span>
<span className="hidden md:inline-flex text-[11px] font-semibold px-2 py-0.5 rounded-full bg-amber-100 text-amber-800 border border-amber-300/60">
Storybook Studio
</span>
</div>
<p className="text-xs text-amber-800/70 dark:text-indigo-300">
Heartwarming Children's Story & Concept Architecture
</p>
</div>
</div>
{/* Global Toolbar Controls */}
<div className="flex items-center gap-2 flex-wrap">
{/* Age Adaptability Selector */}
<div className="flex items-center bg-amber-100/70 dark:bg-indigo-900/80 p-1 rounded-xl border border-amber-200/80 dark:border-indigo-700 text-xs font-semibold">
<span className="px-2 text-amber-800/80 dark:text-indigo-300 hidden sm:inline">Edition:</span>
<button
onClick={() => { soundManager.playPop(); setAgeGroup('toddler'); }}
className={`px-2.5 py-1 rounded-lg transition-all ${
ageGroup === 'toddler'
? 'bg-amber-500 text-white shadow-sm font-bold'
: 'text-amber-900 dark:text-indigo-200 hover:bg-amber-200/50 dark:hover:bg-indigo-800'
}`}
title="Ages 1-3: Sensory, Onomatopoeia & Touch"
>
Toddler (1–3)
</button>
<button
onClick={() => { soundManager.playPop(); setAgeGroup('pictureBook'); }}
className={`px-2.5 py-1 rounded-lg transition-all ${
ageGroup === 'pictureBook'
? 'bg-amber-500 text-white shadow-sm font-bold'
: 'text-amber-900 dark:text-indigo-200 hover:bg-amber-200/50 dark:hover:bg-indigo-800'
}`}
title="Ages 4-7: Lyrical Picture Book & Read-Aloud"
>
Picture Book (4–7)
</button>
<button
onClick={() => { soundManager.playPop(); setAgeGroup('earlyReader'); }}
className={`px-2.5 py-1 rounded-lg transition-all ${
ageGroup === 'earlyReader'
? 'bg-amber-500 text-white shadow-sm font-bold'
: 'text-amber-900 dark:text-indigo-200 hover:bg-amber-200/50 dark:hover:bg-indigo-800'
}`}
title="Ages 7-9: Illustrated Chapters & Vocabulary"
>
Early Reader (7–9)
</button>
</div>
{/* Bedtime / Day Toggle */}
<button
onClick={handleBedtimeToggle}
className={`p-2 rounded-xl border transition-all flex items-center gap-1.5 text-xs font-medium ${
isBedtimeMode
? 'bg-indigo-900 border-indigo-700 text-amber-300 shadow-inner'
: 'bg-amber-50 border-amber-200 text-amber-800 hover:bg-amber-100'
}`}
title={isBedtimeMode ? "Switch to Daytime Mode" : "Switch to Bedtime Lullaby Mode"}
>
{isBedtimeMode ? <Moon className="w-4 h-4 fill-amber-300" /> : <Sun className="w-4 h-4 text-amber-500" />}
<span className="hidden md:inline">{isBedtimeMode ? 'Bedtime Mode' : 'Day Mode'}</span>
</button>
{/* Sound FX Toggle */}
<button
onClick={handleSoundToggle}
className={`p-2 rounded-xl border transition-all ${
soundEnabled
? 'bg-emerald-50 border-emerald-200 text-emerald-700 dark:bg-emerald-950 dark:border-emerald-700 dark:text-emerald-300'
: 'bg-stone-100 border-stone-200 text-stone-400 dark:bg-stone-900 dark:border-stone-800'
}`}
title={soundEnabled ? "Mute Sound Effects" : "Enable Sound Effects"}
>
{soundEnabled ? <Volume2 className="w-4 h-4" /> : <VolumeX className="w-4 h-4" />}
</button>
{/* Pitch Deck / Presentation Button */}
<button
onClick={() => { soundManager.playHarp(); onOpenPitchDeck(); }}
className="flex items-center gap-1.5 px-3 py-1.5 rounded-xl bg-gradient-to-r from-amber-600 to-rose-600 hover:from-amber-700 hover:to-rose-700 text-white font-medium text-xs shadow-sm hover:shadow transition-all"
>
<Printer className="w-3.5 h-3.5" />
<span className="hidden sm:inline">Pitch Deck</span>
</button>
</div>
</div>
{/* Navigation Sub-Tabs */}
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 overflow-x-auto scrollbar-none">
<nav className="flex space-x-1 sm:space-x-2 py-1.5 min-w-max">
{tabs.map((tab) => {
const Icon = tab.icon;
const isActive = activeTab === tab.id;
return (
<button
key={tab.id}
onClick={() => handleTabClick(tab.id)}
className={`flex items-center gap-2 px-3.5 py-1.5 rounded-xl text-xs sm:text-sm font-semibold transition-all ${
isActive
? isBedtimeMode
? 'bg-indigo-800 text-amber-200 shadow-sm border border-indigo-600'
: 'bg-amber-500 text-white shadow-sm border border-amber-600/30'
: isBedtimeMode
? 'text-indigo-200 hover:bg-indigo-900/60 hover:text-white'
: 'text-amber-900/80 hover:bg-amber-100/70 hover:text-amber-950'
}`}
>
<Icon className={`w-4 h-4 ${isActive ? 'scale-110' : ''}`} />
<span>{tab.label}</span>
{tab.badge && (
<span className={`text-[10px] px-1.5 py-0.2 rounded-full font-bold ${
isActive
? 'bg-white/20 text-white'
: isBedtimeMode
? 'bg-indigo-900 text-indigo-300'
: 'bg-amber-200/60 text-amber-800'
}`}>
{tab.badge}
</span>
)}
</button>
);
})}
</nav>
</div>
</header>
);
};