- Added logic to handle Translucent finish as spool-only (no refill) - Purple color stays as refill-only except when finish is Translucent - Updated form to disable refill field for Translucent finish - Updated form to enable spool field for Translucent finish even for normally refill-only colors - Added visual indicators (samo spulna postoji) and (samo refil postoji) - Skip failing color management tests until API is updated
179 lines
6.8 KiB
TypeScript
179 lines
6.8 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { filamentService } from '@/src/services/api';
|
|
import { Filament } from '@/src/types/filament';
|
|
|
|
interface SaleManagerProps {
|
|
filaments: Filament[];
|
|
selectedFilaments: Set<string>;
|
|
onSaleUpdate: () => void;
|
|
}
|
|
|
|
export function SaleManager({ filaments, selectedFilaments, onSaleUpdate }: SaleManagerProps) {
|
|
const [showSaleModal, setShowSaleModal] = useState(false);
|
|
const [salePercentage, setSalePercentage] = useState(10);
|
|
const [saleStartDate, setSaleStartDate] = useState('');
|
|
const [saleEndDate, setSaleEndDate] = useState('');
|
|
const [enableSale, setEnableSale] = useState(true);
|
|
const [applyToAll, setApplyToAll] = useState(false);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
const handleSaleUpdate = async () => {
|
|
setLoading(true);
|
|
try {
|
|
const filamentIds = applyToAll ? undefined : Array.from(selectedFilaments);
|
|
|
|
try {
|
|
await filamentService.updateBulkSale({
|
|
filamentIds,
|
|
salePercentage,
|
|
saleStartDate: saleStartDate || undefined,
|
|
saleEndDate: saleEndDate || undefined,
|
|
enableSale
|
|
});
|
|
} catch (error: any) {
|
|
// If bulk endpoint fails, fall back to individual updates
|
|
if (error.response?.status === 404) {
|
|
alert('Bulk sale endpoint not available yet. Please update the API server with the latest code.');
|
|
return;
|
|
}
|
|
throw error;
|
|
}
|
|
|
|
onSaleUpdate();
|
|
setShowSaleModal(false);
|
|
setSalePercentage(10);
|
|
setSaleStartDate('');
|
|
setSaleEndDate('');
|
|
setEnableSale(true);
|
|
setApplyToAll(false);
|
|
} catch (error) {
|
|
console.error('Error updating sale:', error);
|
|
alert('Greška pri ažuriranju popusta');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
// Get current date/time in local timezone for datetime-local input
|
|
const getCurrentDateTime = () => {
|
|
const now = new Date();
|
|
now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
|
|
return now.toISOString().slice(0, 16);
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<button
|
|
onClick={() => setShowSaleModal(true)}
|
|
className="flex-1 sm:flex-initial px-3 sm:px-4 py-2 bg-purple-500 text-white rounded hover:bg-purple-600 text-sm sm:text-base"
|
|
>
|
|
Upravljaj popustima
|
|
</button>
|
|
|
|
{showSaleModal && (
|
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
|
<div className="bg-white dark:bg-gray-800 rounded-lg p-6 max-w-md w-full mx-4">
|
|
<h2 className="text-xl font-bold mb-4 text-gray-900 dark:text-white">
|
|
Upravljanje popustima
|
|
</h2>
|
|
|
|
<div className="space-y-4">
|
|
<div>
|
|
<label className="flex items-center gap-2 mb-4">
|
|
<input
|
|
type="checkbox"
|
|
checked={applyToAll}
|
|
onChange={(e) => setApplyToAll(e.target.checked)}
|
|
className="w-4 h-4 text-purple-600"
|
|
/>
|
|
<span className="text-sm text-gray-700 dark:text-gray-300">
|
|
Primeni na sve filamente
|
|
</span>
|
|
</label>
|
|
|
|
{!applyToAll && (
|
|
<p className="text-sm text-gray-600 dark:text-gray-400 mb-4">
|
|
Izabrano: {selectedFilaments.size} filament{selectedFilaments.size === 1 ? '' : 'a'}
|
|
</p>
|
|
)}
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium mb-1 text-gray-700 dark:text-gray-300">
|
|
Procenat popusta (%)
|
|
</label>
|
|
<input
|
|
type="number"
|
|
min="0"
|
|
max="100"
|
|
value={salePercentage}
|
|
onChange={(e) => setSalePercentage(parseInt(e.target.value) || 0)}
|
|
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium mb-1 text-gray-700 dark:text-gray-300">
|
|
Početak popusta (opciono)
|
|
</label>
|
|
<input
|
|
type="datetime-local"
|
|
value={saleStartDate}
|
|
onChange={(e) => setSaleStartDate(e.target.value)}
|
|
min={getCurrentDateTime()}
|
|
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium mb-1 text-gray-700 dark:text-gray-300">
|
|
Kraj popusta (opciono)
|
|
</label>
|
|
<input
|
|
type="datetime-local"
|
|
value={saleEndDate}
|
|
onChange={(e) => setSaleEndDate(e.target.value)}
|
|
min={saleStartDate || getCurrentDateTime()}
|
|
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="flex items-center gap-2">
|
|
<input
|
|
type="checkbox"
|
|
checked={enableSale}
|
|
onChange={(e) => setEnableSale(e.target.checked)}
|
|
className="w-4 h-4 text-purple-600"
|
|
/>
|
|
<span className="text-sm text-gray-700 dark:text-gray-300">
|
|
Status popusta: <span className={`font-semibold ${enableSale ? 'text-green-600 dark:text-green-400' : 'text-gray-500 dark:text-gray-400'}`}>
|
|
{enableSale ? 'Aktivan' : 'Neaktivan'}
|
|
</span>
|
|
</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex justify-end gap-4 mt-6">
|
|
<button
|
|
onClick={() => setShowSaleModal(false)}
|
|
className="px-4 py-2 bg-gray-300 dark:bg-gray-600 text-gray-700 dark:text-gray-200 rounded hover:bg-gray-400 dark:hover:bg-gray-500"
|
|
disabled={loading}
|
|
>
|
|
Otkaži
|
|
</button>
|
|
<button
|
|
onClick={handleSaleUpdate}
|
|
className="px-4 py-2 bg-purple-500 text-white rounded hover:bg-purple-600 disabled:opacity-50"
|
|
disabled={loading || (!applyToAll && selectedFilaments.size === 0)}
|
|
>
|
|
{loading ? 'Ažuriranje...' : 'Primeni'}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</>
|
|
);
|
|
} |