refactor: sider bar
This commit is contained in:
@@ -178,7 +178,7 @@ function DraggableAttribute({ id, label }: { id: string; label: string }) {
|
||||
|
||||
export function Sidebar() {
|
||||
const [search, setSearch] = useState("");
|
||||
const [selectedGroupId, setSelectedGroupId] = useState(ATTRIBUTE_GROUPS[0].id);
|
||||
const [selectedGroupIds, setSelectedGroupIds] = useState<string[]>([ATTRIBUTE_GROUPS[0].id]);
|
||||
|
||||
const filteredGroups = useMemo(() => {
|
||||
if (search.trim()) {
|
||||
@@ -191,37 +191,14 @@ export function Sidebar() {
|
||||
}
|
||||
|
||||
// Khi không search, chỉ hiển thị nhóm được chọn
|
||||
return ATTRIBUTE_GROUPS.filter(g => g.id === selectedGroupId);
|
||||
}, [search, selectedGroupId]);
|
||||
return ATTRIBUTE_GROUPS.filter(g => selectedGroupIds.includes(g.id));
|
||||
}, [search, selectedGroupIds]);
|
||||
|
||||
return (
|
||||
<div className="w-72 border-r bg-gray-50/50 flex flex-col h-full">
|
||||
<div className="p-4 border-b bg-white flex flex-col gap-3">
|
||||
<h3 className="font-semibold">Trường dữ liệu</h3>
|
||||
|
||||
{/* Dropdown chọn nhóm */}
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<label className="text-xs font-medium text-muted-foreground">Nhóm dữ liệu</label>
|
||||
<select
|
||||
className="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary"
|
||||
value={selectedGroupId}
|
||||
onChange={(e) => {
|
||||
setSelectedGroupId(e.target.value);
|
||||
setSearch(""); // Reset search khi chuyển nhóm
|
||||
}}
|
||||
>
|
||||
{Array.from(new Set(ATTRIBUTE_GROUPS.map(g => g.category))).map(category => (
|
||||
<optgroup key={category} label={category}>
|
||||
{ATTRIBUTE_GROUPS.filter(g => g.category === category).map(g => (
|
||||
<option key={g.id} value={g.id}>{g.name}</option>
|
||||
))}
|
||||
</optgroup>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* Ô tìm kiếm */}
|
||||
<div className="relative mt-1">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
type="search"
|
||||
@@ -231,6 +208,52 @@ export function Sidebar() {
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Chips chọn nhóm */}
|
||||
<div className="flex flex-col gap-1.5">
|
||||
{selectedGroupIds.length > 0 && (
|
||||
<div className="flex justify-end">
|
||||
<button
|
||||
onClick={() => setSelectedGroupIds([])}
|
||||
className="text-[10px] text-muted-foreground hover:text-primary transition-colors"
|
||||
>
|
||||
Bỏ chọn tất cả
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col gap-3 max-h-[35vh] overflow-y-auto pb-1 pr-1 scrollbar-thin scrollbar-thumb-gray-200">
|
||||
{Array.from(new Set(ATTRIBUTE_GROUPS.map(g => g.category))).map(category => (
|
||||
<div key={category} className="flex flex-col gap-1.5">
|
||||
<div className="text-[10px] font-semibold text-muted-foreground uppercase tracking-wider">{category}</div>
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{ATTRIBUTE_GROUPS.filter(g => g.category === category).map(g => {
|
||||
const isSelected = selectedGroupIds.includes(g.id);
|
||||
return (
|
||||
<button
|
||||
key={g.id}
|
||||
onClick={() => {
|
||||
if (isSelected) {
|
||||
setSelectedGroupIds(prev => prev.filter(id => id !== g.id));
|
||||
} else {
|
||||
setSelectedGroupIds(prev => [...prev, g.id]);
|
||||
}
|
||||
setSearch(""); // Reset search khi chuyển nhóm
|
||||
}}
|
||||
className={`inline-flex items-center px-2.5 py-0.5 text-[11px] font-medium rounded-md border transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 ${
|
||||
isSelected
|
||||
? "border-transparent bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm"
|
||||
: "border-input bg-background hover:bg-accent hover:text-accent-foreground"
|
||||
}`}
|
||||
>
|
||||
{g.name}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 overflow-y-auto p-4 flex flex-col gap-6">
|
||||
|
||||
Reference in New Issue
Block a user