'use client'; import { useState, useEffect } from 'react'; import { analyticsService, filamentService, productService } from '@/src/services/api'; import { InventoryStats, SalesStats, Product } from '@/src/types/product'; import { Filament } from '@/src/types/filament'; type Tab = 'inventar' | 'prodaja' | 'posetioci' | 'nabavka'; const CATEGORY_LABELS: Record = { printer: 'Stampaci', build_plate: 'Ploce', nozzle: 'Mlaznice', spare_part: 'Delovi', accessory: 'Oprema', }; export default function AnalitikaPage() { const [activeTab, setActiveTab] = useState('inventar'); const [inventoryStats, setInventoryStats] = useState(null); const [salesStats, setSalesStats] = useState(null); const [filaments, setFilaments] = useState<(Filament & { id: string })[]>([]); const [products, setProducts] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { const fetchData = async () => { try { const [inv, sales, fils, prods] = await Promise.all([ analyticsService.getInventory().catch(() => null), analyticsService.getSales().catch(() => null), filamentService.getAll().catch(() => []), productService.getAll().catch(() => []), ]); setInventoryStats(inv); setSalesStats(sales); setFilaments(fils); setProducts(prods); } catch (error) { console.error('Error loading analytics:', error); } finally { setLoading(false); } }; fetchData(); }, []); const tabs: { key: Tab; label: string }[] = [ { key: 'inventar', label: 'Inventar' }, { key: 'prodaja', label: 'Prodaja' }, { key: 'posetioci', label: 'Posetioci' }, { key: 'nabavka', label: 'Nabavka' }, ]; if (loading) { return (
Ucitavanje analitike...
); } return (
{/* Page Header */}

Analitika

Pregled stanja inventara i prodaje

{/* Tabs */}
{tabs.map(tab => ( ))}
{/* Inventar Tab */} {activeTab === 'inventar' && (
{inventoryStats ? ( <> {/* Filament stats */}

Filamenti

SKU-ovi

{inventoryStats.filaments.total_skus}

Ukupno jedinica

{inventoryStats.filaments.total_units}

Refili

{inventoryStats.filaments.total_refills}

Spulne

{inventoryStats.filaments.total_spools}

Nema na stanju

{inventoryStats.filaments.out_of_stock}

Vrednost inventara

{inventoryStats.filaments.inventory_value.toLocaleString('sr-RS')} RSD

{/* Product stats */}

Proizvodi

SKU-ovi

{inventoryStats.products.total_skus}

Ukupno jedinica

{inventoryStats.products.total_units}

Nema na stanju

{inventoryStats.products.out_of_stock}

Vrednost inventara

{inventoryStats.products.inventory_value.toLocaleString('sr-RS')} RSD

{/* Category breakdown */} {inventoryStats.products.by_category && Object.keys(inventoryStats.products.by_category).length > 0 && (

Po kategoriji

{Object.entries(inventoryStats.products.by_category).map(([cat, count]) => (

{CATEGORY_LABELS[cat] || cat}

{count}

))}
)}
{/* Combined */}

Ukupno

Ukupno SKU-ova

{inventoryStats.combined.total_skus}

Ukupno jedinica

{inventoryStats.combined.total_units}

Nema na stanju

{inventoryStats.combined.out_of_stock}

) : (

Podaci o inventaru nisu dostupni. Proverite API konekciju.

{/* Fallback from direct data */}

Filamenata

{filaments.length}

Proizvoda

{products.length}

Nisko stanje (fil.)

{filaments.filter(f => f.kolicina <= 2 && f.kolicina > 0).length}

Nema na stanju (fil.)

{filaments.filter(f => f.kolicina === 0).length}

)}
)} {/* Prodaja Tab */} {activeTab === 'prodaja' && (
{salesStats ? ( <>

Aktivni popusti

{salesStats.total_active_sales}

{salesStats.filament_sales.length > 0 && (

Filamenti na popustu ({salesStats.filament_sales.length})

{salesStats.filament_sales.map(sale => ( ))}
Naziv Popust Originalna cena Cena sa popustom Istice
{sale.name} -{sale.sale_percentage}% {sale.original_price.toLocaleString('sr-RS')} RSD {sale.sale_price.toLocaleString('sr-RS')} RSD {sale.sale_end_date ? new Date(sale.sale_end_date).toLocaleDateString('sr-RS') : '-'}
)} {salesStats.product_sales.length > 0 && (

Proizvodi na popustu ({salesStats.product_sales.length})

{salesStats.product_sales.map(sale => ( ))}
Naziv Kategorija Popust Originalna cena Cena sa popustom Istice
{sale.name} {CATEGORY_LABELS[sale.category] || sale.category} -{sale.sale_percentage}% {sale.original_price.toLocaleString('sr-RS')} RSD {sale.sale_price.toLocaleString('sr-RS')} RSD {sale.sale_end_date ? new Date(sale.sale_end_date).toLocaleDateString('sr-RS') : '-'}
)} {salesStats.filament_sales.length === 0 && salesStats.product_sales.length === 0 && (

Nema aktivnih popusta

)} ) : (

Podaci o prodaji nisu dostupni. Proverite API konekciju.

Filamenti sa popustom: {filaments.filter(f => f.sale_active).length}

Proizvodi sa popustom: {products.filter(p => p.sale_active).length}

)}
)} {/* Posetioci Tab */} {activeTab === 'posetioci' && (

Analitika posetilaca

Matomo analitika je dostupna na eksternom dashboardu.

Otvori Matomo analitiku

analytics.demirix.dev - Site ID: 7

)} {/* Nabavka Tab */} {activeTab === 'nabavka' && (

Preporuke za nabavku

Na osnovu trenutnog stanja inventara

{/* Critical (out of stock) */} {(() => { const critical = filaments.filter(f => f.kolicina === 0); return critical.length > 0 ? (

Kriticno - nema na stanju ({critical.length})

{critical.map(f => ( ))}
Tip Finis Boja Stanje
{f.tip} {f.finish} {f.boja_hex &&
} {f.boja}
0
) : null; })()} {/* Warning (low stock) */} {(() => { const warning = filaments.filter(f => f.kolicina > 0 && f.kolicina <= 2); return warning.length > 0 ? (

Upozorenje - nisko stanje ({warning.length})

{warning.map(f => ( ))}
Tip Finis Boja Stanje
{f.tip} {f.finish} {f.boja_hex &&
} {f.boja}
{f.kolicina}
) : null; })()} {/* OK */} {(() => { const ok = filaments.filter(f => f.kolicina > 2); return (

Dobro stanje ({ok.length})

{ok.length} filamenata ima dovoljno na stanju (3+)

); })()} {/* Product restock */} {(() => { const lowProducts = products.filter(p => p.stock <= 2); return lowProducts.length > 0 ? (

Proizvodi za nabavku ({lowProducts.length})

{lowProducts.map(p => (
{p.name} {p.stock}
))}
) : null; })()}
)}
); }