93 lines
4.1 KiB
TypeScript
93 lines
4.1 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { Task } from '../data/schema';
|
|
import { priorities, statuses } from '../data/data';
|
|
|
|
interface DataTableToolbarProps {
|
|
onFilter: (filteredData: Task[]) => void;
|
|
data: Task[];
|
|
}
|
|
|
|
export const DataTableToolbar: React.FC<DataTableToolbarProps> = ({ onFilter, data }) => {
|
|
const [searchText, setSearchText] = useState('');
|
|
const [statusFilter, setStatusFilter] = useState<string[]>([]);
|
|
const [priorityFilter, setPriorityFilter] = useState<string[]>([]);
|
|
|
|
const applyFilters = () => {
|
|
const filteredData = data.filter(task => {
|
|
const matchesSearch = task.title.toLowerCase().includes(searchText.toLowerCase());
|
|
const matchesStatus = statusFilter.length === 0 || statusFilter.includes(task.status);
|
|
const matchesPriority = priorityFilter.length === 0 || priorityFilter.includes(task.priority);
|
|
return matchesSearch && matchesStatus && matchesPriority;
|
|
});
|
|
onFilter(filteredData);
|
|
};
|
|
|
|
const toggleFilter = (filter: string[], value: string, setFilter: (filter: string[]) => void) => {
|
|
const newFilter = filter.includes(value)
|
|
? filter.filter(f => f !== value)
|
|
: [...filter, value];
|
|
setFilter(newFilter);
|
|
applyFilters();
|
|
};
|
|
|
|
return (
|
|
<div className="px-6 py-4 bg-white border-b border-gray-200">
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex-1 max-w-lg">
|
|
<input
|
|
type="text"
|
|
placeholder="Filter tasks..."
|
|
className="block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500"
|
|
value={searchText}
|
|
onChange={(e) => {
|
|
setSearchText(e.target.value);
|
|
applyFilters();
|
|
}}
|
|
/>
|
|
</div>
|
|
<div className="ml-4 flex space-x-4">
|
|
<div className="relative">
|
|
<button className="inline-flex justify-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
|
|
Status
|
|
</button>
|
|
<div className="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 z-10">
|
|
<div className="py-1">
|
|
{statuses.map((status) => (
|
|
<label key={status.value} className="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
|
|
<input
|
|
type="checkbox"
|
|
checked={statusFilter.includes(status.value)}
|
|
onChange={() => toggleFilter(statusFilter, status.value, setStatusFilter)}
|
|
className="mr-2"
|
|
/>
|
|
{status.label}
|
|
</label>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="relative">
|
|
<button className="inline-flex justify-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
|
|
Priority
|
|
</button>
|
|
<div className="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 z-10">
|
|
<div className="py-1">
|
|
{priorities.map((priority) => (
|
|
<label key={priority.value} className="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
|
|
<input
|
|
type="checkbox"
|
|
checked={priorityFilter.includes(priority.value)}
|
|
onChange={() => toggleFilter(priorityFilter, priority.value, setPriorityFilter)}
|
|
className="mr-2"
|
|
/>
|
|
{priority.label}
|
|
</label>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|