Remove decorative icons and update CORS configuration

This commit is contained in:
DaX
2025-06-20 13:05:36 +02:00
parent 18110ab159
commit 62a4891112
51 changed files with 4284 additions and 2385 deletions

View File

@@ -40,6 +40,9 @@ export const FilamentTableV2: React.FC<FilamentTableV2Props> = ({ filaments, loa
const storageCondition = legacy.vakum?.toLowerCase().includes('vakuum') ? 'vacuum' :
legacy.otvoreno?.toLowerCase().includes('otvorena') ? 'opened' : 'sealed';
const totalQuantity = parseInt(legacy.kolicina) || 1;
const availableQuantity = totalQuantity > 0 ? totalQuantity : 0;
return {
id: legacy.id || `legacy-${Math.random().toString(36).substr(2, 9)}`,
brand: legacy.brand,
@@ -49,12 +52,12 @@ export const FilamentTableV2: React.FC<FilamentTableV2Props> = ({ filaments, loa
weight: { value: 1000, unit: 'g' as const },
diameter: 1.75,
inventory: {
total: parseInt(legacy.kolicina) || 1,
available: storageCondition === 'opened' ? 0 : 1,
total: totalQuantity,
available: availableQuantity,
inUse: 0,
locations: {
vacuum: storageCondition === 'vacuum' ? 1 : 0,
opened: storageCondition === 'opened' ? 1 : 0,
vacuum: storageCondition === 'vacuum' ? totalQuantity : 0,
opened: storageCondition === 'opened' ? totalQuantity : 0,
printer: 0
}
},
@@ -83,6 +86,8 @@ export const FilamentTableV2: React.FC<FilamentTableV2Props> = ({ filaments, loa
// Filter and sort filaments
const filteredAndSortedFilaments = useMemo(() => {
let filtered = normalizedFilaments.filter(filament => {
// Only show available filaments
if (filament.inventory.available === 0) return false;
// Search filter
const searchLower = searchTerm.toLowerCase();
const matchesSearch =
@@ -90,7 +95,7 @@ export const FilamentTableV2: React.FC<FilamentTableV2Props> = ({ filaments, loa
filament.material.base.toLowerCase().includes(searchLower) ||
(filament.material.modifier?.toLowerCase().includes(searchLower)) ||
filament.color.name.toLowerCase().includes(searchLower) ||
(filament.sku?.toLowerCase().includes(searchLower));
false; // SKU removed
// Other filters
const matchesBrand = !filters.brand || filament.brand === filters.brand;
@@ -138,19 +143,19 @@ export const FilamentTableV2: React.FC<FilamentTableV2Props> = ({ filaments, loa
const summary = {
totalSpools: 0,
availableSpools: 0,
totalWeight: 0,
brandsCount: new Set<string>(),
lowStock: [] as FilamentV2[]
vacuumCount: 0,
openedCount: 0,
refillCount: 0
};
normalizedFilaments.forEach(f => {
summary.totalSpools += f.inventory.total;
summary.availableSpools += f.inventory.available;
summary.totalWeight += f.inventory.total * f.weight.value;
summary.brandsCount.add(f.brand);
summary.vacuumCount += f.inventory.locations.vacuum;
summary.openedCount += f.inventory.locations.opened;
if (f.inventory.available <= 1 && f.inventory.total > 0) {
summary.lowStock.push(f);
if (f.condition.isRefill) {
summary.refillCount += f.inventory.total;
}
});
@@ -168,9 +173,9 @@ export const FilamentTableV2: React.FC<FilamentTableV2Props> = ({ filaments, loa
return (
<div className="space-y-6">
{/* Inventory Summary */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<div className="grid grid-cols-2 md:grid-cols-5 gap-4">
<div className="bg-white dark:bg-gray-800 p-4 rounded-lg shadow">
<div className="text-sm text-gray-500 dark:text-gray-400">Ukupno kalema</div>
<div className="text-sm text-gray-500 dark:text-gray-400">Ukupno filamenta</div>
<div className="text-2xl font-bold text-gray-900 dark:text-white">{inventorySummary.totalSpools}</div>
</div>
<div className="bg-white dark:bg-gray-800 p-4 rounded-lg shadow">
@@ -178,12 +183,16 @@ export const FilamentTableV2: React.FC<FilamentTableV2Props> = ({ filaments, loa
<div className="text-2xl font-bold text-green-600 dark:text-green-400">{inventorySummary.availableSpools}</div>
</div>
<div className="bg-white dark:bg-gray-800 p-4 rounded-lg shadow">
<div className="text-sm text-gray-500 dark:text-gray-400">Ukupna težina</div>
<div className="text-2xl font-bold text-gray-900 dark:text-white">{(inventorySummary.totalWeight / 1000).toFixed(1)}kg</div>
<div className="text-sm text-gray-500 dark:text-gray-400">Vakum</div>
<div className="text-2xl font-bold text-blue-600 dark:text-blue-400">{inventorySummary.vacuumCount}</div>
</div>
<div className="bg-white dark:bg-gray-800 p-4 rounded-lg shadow">
<div className="text-sm text-gray-500 dark:text-gray-400">Malo na stanju</div>
<div className="text-2xl font-bold text-yellow-600 dark:text-yellow-400">{inventorySummary.lowStock.length}</div>
<div className="text-sm text-gray-500 dark:text-gray-400">Otvoreno</div>
<div className="text-2xl font-bold text-orange-600 dark:text-orange-400">{inventorySummary.openedCount}</div>
</div>
<div className="bg-white dark:bg-gray-800 p-4 rounded-lg shadow">
<div className="text-sm text-gray-500 dark:text-gray-400">Refill</div>
<div className="text-2xl font-bold text-purple-600 dark:text-purple-400">{inventorySummary.refillCount}</div>
</div>
</div>
@@ -191,7 +200,7 @@ export const FilamentTableV2: React.FC<FilamentTableV2Props> = ({ filaments, loa
<div className="relative">
<input
type="text"
placeholder="Pretraži po brendu, materijalu, boji ili SKU..."
placeholder="Pretraži po brendu, materijalu, boji..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="w-full px-4 py-2 pl-10 pr-4 text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:border-blue-500"
@@ -208,14 +217,30 @@ export const FilamentTableV2: React.FC<FilamentTableV2Props> = ({ filaments, loa
uniqueValues={uniqueValues}
/>
{/* Icon Legend */}
<div className="bg-white dark:bg-gray-800 rounded-lg shadow p-4">
<h3 className="text-base font-medium text-gray-700 dark:text-gray-300 mb-3 text-center">Legenda stanja:</h3>
<div className="flex justify-center gap-8">
<div className="flex items-center gap-3">
<div className="transform scale-125">
<InventoryBadge type="vacuum" count={1} />
</div>
<span className="text-gray-600 dark:text-gray-400 text-[15px]">Vakuum pakovanje</span>
</div>
<div className="flex items-center gap-3">
<div className="transform scale-125">
<InventoryBadge type="opened" count={1} />
</div>
<span className="text-gray-600 dark:text-gray-400 text-[15px]">Otvoreno</span>
</div>
</div>
</div>
{/* Table */}
<div className="overflow-x-auto bg-white dark:bg-gray-800 rounded-lg shadow">
<table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead className="bg-gray-50 dark:bg-gray-900">
<tr>
<th onClick={() => handleSort('sku')} className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800">
SKU
</th>
<th onClick={() => handleSort('brand')} className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800">
Brend
</th>
@@ -226,11 +251,14 @@ export const FilamentTableV2: React.FC<FilamentTableV2Props> = ({ filaments, loa
Boja
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
Skladište
Stanje
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
Težina
</th>
<th onClick={() => handleSort('pricing.purchasePrice')} className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800">
Cena
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
Status
</th>
@@ -239,9 +267,6 @@ export const FilamentTableV2: React.FC<FilamentTableV2Props> = ({ filaments, loa
<tbody className="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
{filteredAndSortedFilaments.map(filament => (
<tr key={filament.id} className="hover:bg-gray-50 dark:hover:bg-gray-700">
<td className="px-6 py-4 whitespace-nowrap text-sm font-mono text-gray-500 dark:text-gray-400">
{filament.sku || filament.id.substring(0, 8)}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-white">
{filament.brand}
</td>
@@ -267,16 +292,27 @@ export const FilamentTableV2: React.FC<FilamentTableV2Props> = ({ filaments, loa
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
{filament.weight.value}{filament.weight.unit}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-white">
{(() => {
// PLA Basic pricing logic
if (filament.material.base === 'PLA' && !filament.material.modifier) {
if (filament.condition.isRefill && filament.condition.storageCondition !== 'opened') {
return '3.499 RSD';
} else if (!filament.condition.isRefill && filament.condition.storageCondition === 'vacuum') {
return '3.999 RSD';
}
}
// Show original price if available
return filament.pricing.purchasePrice ?
`${filament.pricing.purchasePrice.toLocaleString('sr-RS')} ${filament.pricing.currency}` :
'-';
})()}
</td>
<td className="px-6 py-4 whitespace-nowrap">
<div className="flex flex-col gap-1">
{filament.condition.isRefill && (
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200">
Punjenje
</span>
)}
{filament.inventory.available === 0 && (
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200">
Nema na stanju
Refill
</span>
)}
{filament.inventory.available === 1 && (
@@ -293,7 +329,7 @@ export const FilamentTableV2: React.FC<FilamentTableV2Props> = ({ filaments, loa
</div>
<div className="text-sm text-gray-500 dark:text-gray-400 text-center">
Prikazano {filteredAndSortedFilaments.length} od {normalizedFilaments.length} filamenata
Prikazano {filteredAndSortedFilaments.length} dostupnih filamenata
</div>
</div>
);