File size: 5,779 Bytes
be02369 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
import React from 'react';
import type { View } from '../types';
import {
BonsaiIcon,
SparklesIcon,
BugIcon,
LeafIcon,
WrenchIcon,
BookUserIcon,
StethoscopeIcon,
PaletteIcon,
ScanIcon,
SnailIcon,
FilterIcon,
RootsIcon,
PotRulerIcon,
SunClockIcon,
BeakerIcon,
ShovelIcon,
UmbrellaIcon,
ScissorsIcon,
SettingsIcon,
ChevronsLeftIcon
} from './icons';
import { AuthContext } from '../context/AuthContext';
interface SidebarProps {
activeView: View;
setActiveView: (view: View) => void;
isCollapsed: boolean;
setIsCollapsed: (isCollapsed: boolean) => void;
}
const CATEGORIZED_NAV_ITEMS = [
{
category: 'Core',
items: [
{ id: 'garden', name: 'My Garden', icon: BookUserIcon },
{ id: 'steward', name: 'New Tree Analysis', icon: SparklesIcon },
]
},
{
category: 'AI Studios',
items: [
{ id: 'designStudio', name: 'AI Design Studio', icon: PaletteIcon },
{ id: 'wiringGuide', name: 'AI Wiring Guide', icon: SnailIcon },
{ id: 'nebariDeveloper', name: 'Nebari Developer', icon: RootsIcon },
// { id: 'virtualTrimmer', name: 'Virtual Trimmer', icon: ScissorsIcon },
]
},
{
category: 'Diagnostics',
items: [
{ id: 'healthCheck', name: 'Health Check-up', icon: StethoscopeIcon },
{ id: 'speciesIdentifier', name: 'Species Identifier', icon: ScanIcon },
{ id: 'soilAnalyzer', name: 'Soil Analyzer', icon: FilterIcon },
{ id: 'weatherShield', name: 'Weather Shield', icon: UmbrellaIcon },
]
},
{
category: 'Utilities',
items: [
{ id: 'sunTracker', name: 'Sun Tracker', icon: SunClockIcon },
{ id: 'potCalculator', name: 'Pot Calculator', icon: PotRulerIcon },
{ id: 'fertilizerMixer', name: 'Fertilizer Mixer', icon: BeakerIcon },
{ id: 'soilVolumeCalculator', name: 'Soil Mix Calculator', icon: ShovelIcon },
{ id: 'tools', name: 'Tool Guide', icon: WrenchIcon },
]
},
{
category: 'Reference',
items: [
{ id: 'pests', name: 'Pest Library', icon: BugIcon },
{ id: 'seasons', name: 'Seasonal Guides', icon: LeafIcon },
]
},
];
const Sidebar: React.FC<SidebarProps> = ({ activeView, setActiveView, isCollapsed, setIsCollapsed }) => {
const { logout } = React.useContext(AuthContext);
return (
<aside className={`flex-shrink-0 bg-white border-r border-stone-200 flex flex-col transition-all duration-300 ${isCollapsed ? 'w-20' : 'w-64'}`}>
<div className={`h-16 flex items-center border-b border-stone-200 transition-all duration-300 ${isCollapsed ? 'justify-center' : 'justify-center px-4'}`}>
<div className="flex items-center gap-2">
<BonsaiIcon className="h-8 w-8 text-green-700 flex-shrink-0" />
{!isCollapsed && <h1 className="text-xl font-bold text-stone-800">Yuki</h1>}
</div>
</div>
<nav className="flex-1 px-2 py-4 space-y-2 overflow-y-auto">
{CATEGORIZED_NAV_ITEMS.map((category) => (
<div key={category.category}>
{!isCollapsed && <h2 className="px-4 text-xs font-bold uppercase text-stone-500 tracking-wider">{category.category}</h2>}
{isCollapsed && category.category === 'Core' && <div className="h-px bg-stone-200 my-2 mx-4"></div>}
<div className="mt-2 space-y-1">
{category.items.map((item) => (
<button
key={item.id}
onClick={() => setActiveView(item.id as View)}
title={item.name}
className={`w-full flex items-center gap-3 px-4 py-2.5 rounded-lg text-sm font-medium transition-colors ${isCollapsed ? 'justify-center' : ''}
${
activeView === item.id
? 'bg-green-100 text-green-800'
: 'text-stone-600 hover:bg-stone-100 hover:text-stone-900'
}
`}
>
<item.icon className="h-5 w-5 flex-shrink-0" />
{!isCollapsed && <span>{item.name}</span>}
</button>
))}
</div>
</div>
))}
</nav>
<div className="flex-shrink-0 p-2 border-t border-stone-200">
<button
key="settings"
onClick={() => setActiveView('settings')}
title="Settings"
className={`w-full flex items-center gap-3 px-4 py-2.5 rounded-lg text-sm font-medium transition-colors ${isCollapsed ? 'justify-center' : ''}
${
activeView === 'settings'
? 'bg-green-100 text-green-800'
: 'text-stone-600 hover:bg-stone-100 hover:text-stone-900'
}
`}
>
<SettingsIcon className="h-5 w-5 flex-shrink-0" />
{!isCollapsed && <span>Settings</span>}
</button>
<div className="p-2 border-t border-stone-200 mt-2">
<button
onClick={() => setIsCollapsed(!isCollapsed)}
className={`w-full flex items-center gap-3 px-4 py-2 text-sm font-medium text-stone-600 hover:bg-stone-100 rounded-lg ${isCollapsed ? 'justify-center' : ''}`}
title={isCollapsed ? 'Expand Sidebar' : 'Collapse Sidebar'}
>
<ChevronsLeftIcon className={`h-5 w-5 flex-shrink-0 transition-transform duration-300 ${isCollapsed ? 'rotate-180' : ''}`} />
{!isCollapsed && <span>Collapse</span>}
</button>
</div>
</div>
</aside>
);
};
export default Sidebar; |