history
This commit is contained in:
@@ -66,6 +66,20 @@ const History = () => {
|
||||
fetchHistoryData();
|
||||
}, []);
|
||||
|
||||
// Close dropdown when clicking outside
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event) => {
|
||||
if (showProductDropdown && !event.target.closest('.relative')) {
|
||||
setShowProductDropdown(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, [showProductDropdown]);
|
||||
|
||||
const fetchHistoryData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
@@ -248,7 +262,7 @@ const History = () => {
|
||||
|
||||
{showFilters && (
|
||||
<div className="p-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Time Period
|
||||
@@ -262,7 +276,32 @@ const History = () => {
|
||||
<option value="today">Today</option>
|
||||
<option value="week">Last Week</option>
|
||||
<option value="month">Last Month</option>
|
||||
<option value="custom">Custom Range</option>
|
||||
</select>
|
||||
|
||||
{/* Date Range Inputs */}
|
||||
{dateFilter === 'custom' && (
|
||||
<div className="mt-2 grid grid-cols-2 gap-2">
|
||||
<div>
|
||||
<label className="block text-xs text-gray-600 mb-1">From</label>
|
||||
<input
|
||||
type="date"
|
||||
value={dateRangeStart}
|
||||
onChange={(e) => setDateRangeStart(e.target.value)}
|
||||
className="w-full border border-gray-300 rounded px-2 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs text-gray-600 mb-1">To</label>
|
||||
<input
|
||||
type="date"
|
||||
value={dateRangeEnd}
|
||||
onChange={(e) => setDateRangeEnd(e.target.value)}
|
||||
className="w-full border border-gray-300 rounded px-2 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -298,17 +337,80 @@ const History = () => {
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Product
|
||||
Products
|
||||
</label>
|
||||
<div className="relative">
|
||||
<button
|
||||
onClick={() => setShowProductDropdown(!showProductDropdown)}
|
||||
className="w-full border border-gray-300 rounded px-3 py-2 text-sm text-left focus:outline-none focus:ring-2 focus:ring-blue-500 flex items-center justify-between"
|
||||
>
|
||||
<span>
|
||||
{selectedProducts.length === 0
|
||||
? 'All Products'
|
||||
: `${selectedProducts.length} selected`
|
||||
}
|
||||
</span>
|
||||
<svg className={`h-4 w-4 transform transition-transform ${showProductDropdown ? 'rotate-180' : ''}`} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
{showProductDropdown && (
|
||||
<div className="absolute z-10 w-full mt-1 bg-white border border-gray-300 rounded-md shadow-lg max-h-60 overflow-auto">
|
||||
{uniqueProducts.length === 0 ? (
|
||||
<div className="px-3 py-2 text-sm text-gray-500">No products available</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="px-3 py-2 border-b">
|
||||
<button
|
||||
onClick={() => {
|
||||
if (selectedProducts.length === uniqueProducts.length) {
|
||||
setSelectedProducts([]);
|
||||
} else {
|
||||
setSelectedProducts([...uniqueProducts]);
|
||||
}
|
||||
}}
|
||||
className="text-xs text-blue-600 hover:text-blue-800"
|
||||
>
|
||||
{selectedProducts.length === uniqueProducts.length ? 'Deselect All' : 'Select All'}
|
||||
</button>
|
||||
</div>
|
||||
{uniqueProducts.map(product => (
|
||||
<label key={product} className="flex items-center px-3 py-2 hover:bg-gray-50 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={selectedProducts.includes(product)}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
setSelectedProducts([...selectedProducts, product]);
|
||||
} else {
|
||||
setSelectedProducts(selectedProducts.filter(p => p !== product));
|
||||
}
|
||||
}}
|
||||
className="mr-2"
|
||||
/>
|
||||
<span className="text-sm">{product}</span>
|
||||
</label>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Application Type
|
||||
</label>
|
||||
<select
|
||||
value={productFilter}
|
||||
onChange={(e) => setProductFilter(e.target.value)}
|
||||
value={applicationTypeFilter}
|
||||
onChange={(e) => setApplicationTypeFilter(e.target.value)}
|
||||
className="w-full border border-gray-300 rounded px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
>
|
||||
<option value="all">All Products</option>
|
||||
{uniqueProducts.map(product => (
|
||||
<option key={product} value={product}>{product}</option>
|
||||
))}
|
||||
<option value="all">All Types</option>
|
||||
<option value="granular">Granular</option>
|
||||
<option value="liquid">Liquid</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -332,10 +434,14 @@ const History = () => {
|
||||
<button
|
||||
onClick={() => {
|
||||
setDateFilter('all');
|
||||
setDateRangeStart('');
|
||||
setDateRangeEnd('');
|
||||
setStatusFilter('all');
|
||||
setPropertyFilter('all');
|
||||
setProductFilter('all');
|
||||
setSelectedProducts([]);
|
||||
setApplicationTypeFilter('all');
|
||||
setSortBy('date');
|
||||
setShowProductDropdown(false);
|
||||
}}
|
||||
className="px-4 py-2 text-sm text-gray-600 hover:text-gray-800 border border-gray-300 rounded hover:bg-gray-50"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user