Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ import { ProductList } from './components/ProductList';
import { ProductForm } from './components/ProductForm';
import { Loader2 } from 'lucide-react';

const BarcodeScanner = lazy(() =>
import('./components/BarcodeScanner').then((m) => ({ default: m.BarcodeScanner }))
);

const Settings = lazy(() =>
import('./components/Settings').then((m) => ({ default: m.Settings }))
);
Expand All @@ -41,12 +37,6 @@ function PageContent() {
return <ProductList />;
case 'add':
return <ProductForm />;
case 'scanner':
return (
<Suspense fallback={<LazyFallback />}>
<BarcodeScanner />
</Suspense>
);
case 'settings':
return (
<Suspense fallback={<LazyFallback />}>
Expand Down
16 changes: 6 additions & 10 deletions src/components/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import type { ProductCategory } from '../types';
import { StatRing } from './StatRing';
import {
Package,
ScanBarcode,
PlusCircle,
TrendingDown,
ChevronRight,
Expand All @@ -32,6 +31,7 @@ const URGENT_TEXT_COLORS: Record<string, string> = {

export function Dashboard() {
const setPage = useAppStore((s) => s.setPage);
const setEditingProductId = useAppStore((s) => s.setEditingProductId);
const products = useLiveQuery(() => db.products.toArray()) ?? [];
const { t } = useTranslation();

Expand Down Expand Up @@ -73,13 +73,9 @@ export function Dashboard() {
<p className="mt-5 text-xl font-semibold text-gray-200">{t('dashboard.noProducts')}</p>
<p className="mt-2 max-w-xs text-sm text-gray-400">{t('dashboard.noProductsDesc')}</p>
<div className="mt-6 flex gap-3">
<button onClick={() => setPage('scanner')} className="flex items-center gap-2 rounded-xl bg-green-600 px-5 py-3 font-medium text-white hover:bg-green-500 active:scale-[0.98] transition-transform">
<ScanBarcode size={18} />
{t('dashboard.scan')}
</button>
<button onClick={() => setPage('add')} className="flex items-center gap-2 rounded-xl border border-primary-600 px-5 py-3 font-medium text-gray-300 hover:bg-primary-700">
<button onClick={() => { setEditingProductId(null); setPage('add'); }} className="flex items-center gap-2 rounded-xl bg-green-600 px-5 py-3 font-medium text-white hover:bg-green-500 active:scale-[0.98] transition-transform">
<PlusCircle size={18} />
{t('dashboard.manual')}
{t('nav.add')}
</button>
</div>
</div>
Expand All @@ -98,12 +94,12 @@ export function Dashboard() {
</div>

<div className="grid grid-cols-2 gap-3">
<button onClick={() => setPage('scanner')} className="flex items-center gap-3 rounded-xl border border-primary-700 bg-primary-800/60 p-4 text-start hover:bg-primary-700/50 active:scale-[0.98] transition-transform">
<button onClick={() => { setEditingProductId(null); setPage('add'); }} className="flex items-center gap-3 rounded-xl border border-primary-700 bg-primary-800/60 p-4 text-start hover:bg-primary-700/50 active:scale-[0.98] transition-transform">
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-green-600/20">
<ScanBarcode size={20} className="text-green-400" />
<PlusCircle size={20} className="text-green-400" />
</div>
<div>
<p className="text-sm font-medium text-gray-200">{t('dashboard.scan')}</p>
<p className="text-sm font-medium text-gray-200">{t('nav.add')}</p>
<p className="text-[0.65rem] text-gray-400">{t('dashboard.scanBarcode')}</p>
</div>
</button>
Expand Down
54 changes: 47 additions & 7 deletions src/components/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,75 @@ import { useAppStore } from '../store/useAppStore';
import {
LayoutDashboard,
Package,
PlusCircle,
ScanBarcode,
Plus,
Settings,
BarChart3,
} from 'lucide-react';

const NAV_ITEMS = [
const LEFT_ITEMS = [
{ id: 'dashboard' as const, labelKey: 'nav.dashboard', icon: LayoutDashboard },
{ id: 'products' as const, labelKey: 'nav.products', icon: Package },
{ id: 'add' as const, labelKey: 'nav.add', icon: PlusCircle },
{ id: 'scanner' as const, labelKey: 'nav.scanner', icon: ScanBarcode },
];

const RIGHT_ITEMS = [
{ id: 'stats' as const, labelKey: 'nav.stats', icon: BarChart3 },
{ id: 'settings' as const, labelKey: 'nav.settings', icon: Settings },
];

export function Navigation() {
const { currentPage, setPage, setEditingProductId } = useAppStore();
const { t } = useTranslation();
const isAddActive = currentPage === 'add';

return (
<nav className="fixed bottom-0 left-0 right-0 z-40 border-t border-primary-700 bg-primary-800/95 backdrop-blur-sm safe-bottom">
<div className="mx-auto flex max-w-lg items-center justify-around">
{NAV_ITEMS.map(({ id, labelKey, icon: Icon }) => {
{/* Left nav items */}
{LEFT_ITEMS.map(({ id, labelKey, icon: Icon }) => {
const isActive = currentPage === id;
const label = t(labelKey);
return (
<button
key={id}
onClick={() => setPage(id)}
className={`flex min-w-[3rem] flex-col items-center gap-0.5 px-2 py-2 text-xs transition-colors ${
isActive
? 'text-green-400'
: 'text-gray-300 hover:text-gray-200'
}`}
aria-label={label}
aria-current={isActive ? 'page' : undefined}
>
<Icon size={22} strokeWidth={isActive ? 2.5 : 2} />
<span className="leading-none">{label}</span>
</button>
);
})}

{/* Center FAB button */}
<div className="relative flex items-center justify-center">
<button
onClick={() => { setEditingProductId(null); setPage('add'); }}
className={`-mt-7 flex h-14 w-14 items-center justify-center rounded-full shadow-lg transition-all active:scale-95 ${
isAddActive
? 'bg-green-500 shadow-green-500/30'
: 'bg-green-600 shadow-green-600/20 hover:bg-green-500 hover:shadow-green-500/30'
}`}
aria-label={t('nav.add')}
aria-current={isAddActive ? 'page' : undefined}
>
<Plus size={28} strokeWidth={2.5} className="text-white" />
</button>
</div>

{/* Right nav items */}
{RIGHT_ITEMS.map(({ id, labelKey, icon: Icon }) => {
const isActive = currentPage === id;
const label = t(labelKey);
return (
<button
key={id}
onClick={() => { if (id === 'add') setEditingProductId(null); setPage(id); }}
onClick={() => setPage(id)}
className={`flex min-w-[3rem] flex-col items-center gap-0.5 px-2 py-2 text-xs transition-colors ${
isActive
? 'text-green-400'
Expand Down
Loading