Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions src/components/ui/filters.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import { cn } from "../../lib/utils";
import { Filter } from "../utilities/filter";

export default function Filters() {
export default function Filters({
categories,
selectedCategory,
setSelectedCategory,
}: {
categories: string[];
selectedCategory: string;
setSelectedCategory: (category: string) => void;
}) {
return (
<div className={cn("flex flex-col w-full gap-4")}>
<Filter name="Category" items={["Category 1", "Category 2", "Category 3"]} />
<Filter name="Category" items={["Category 1", "Category 2", "Category 3"]} />
<Filter name="Category" items={["Category 1", "Category 2", "Category 3"]} />
<Filter name="Category" items={["Category 1", "Category 2", "Category 3"]} />
<Filter name="Category" items={["Category 1", "Category 2", "Category 3"]} />
<Filter name="Category" items={["Category 1", "Category 2", "Category 3"]} />
<Filter
name="Category"
items={categories}
selectedItem={selectedCategory}
setSelectedItem={setSelectedCategory}
/>
</div>
);
}
}
10 changes: 8 additions & 2 deletions src/components/ui/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import SearchBar from "./searchbar";
import UserMenu from "./userMenu";
import { cn } from "../../lib/utils";

export function Header() {
export function Header({
search,
setSearch,
}: {
search: string;
setSearch: (search: string) => void;
}) {
const handleLogout = () => {
localStorage.removeItem("token");
localStorage.clear();
Expand All @@ -12,7 +18,7 @@ export function Header() {

return (
<div className={cn("flex flex-row justify-between items-center gap-4")}>
<SearchBar />
<SearchBar search={search} setSearch={setSearch} />
<UserMenu />
<div className="flex flex-col px-8">
<p className="text-sm">Witaj,{user}</p>
Expand Down
18 changes: 15 additions & 3 deletions src/components/ui/searchbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,25 @@ import Button from "../utilities/button";
import Icon from "../../lib/iconConfig";
import { CustomClasses } from "../utilities/customClasses";

export default function SearchBar() {
export default function SearchBar({
search,
setSearch,
}: {
search: string;
setSearch: (search: string) => void;
}) {
return (
<div className={cn("flex flex-row w-full border h-12", CustomClasses.shadowBox)}>
<Button className={cn(CustomClasses.yellowButton, CustomClasses.centerIcon, "p-1 border-r-2 border-black w-[40px]")}>
<Icon name="search" className={cn("size-5")}/>
</Button>
<input type="text" placeholder="Search inventory..." className={cn("border-none outline-none m-1 ml-2 w-full text-xs")}/>
<input
type="text"
placeholder="Search inventory..."
value={search}
onChange={(event) => setSearch(event.target.value)}
className={cn("border-none outline-none m-1 ml-2 w-full text-xs")}
/>
</div>
);
}
}
22 changes: 18 additions & 4 deletions src/components/ui/sideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@ import Filters from "./filters";
import Icon from "../../lib/iconConfig";
import Button from "../utilities/button";

export default function SideBar() {
export default function SideBar({
categories,
selectedCategory,
setSelectedCategory,
clearFilters,
}: {
categories: string[];
selectedCategory: string;
setSelectedCategory: (category: string) => void;
clearFilters: () => void;
}) {
return (
<div className={cn("flex flex-col w-1/6 h-full border", CustomClasses.shadowBox)}>
<div className={cn("flex flex-col m-3 mb-0")}>
Expand All @@ -17,12 +27,16 @@ export default function SideBar() {
</div>
<hr className={cn("border-2 border-black my-2 mx-3")}/>
<div className={cn("flex flex-col items-center gap-2 ml-3 overflow-y-auto pr-4 pl-1")}>
<Filters/>
<Filters
categories={categories}
selectedCategory={selectedCategory}
setSelectedCategory={setSelectedCategory}
/>
</div>
<div className={cn("flex flex-col gap-2 m-3 mt-auto")}>
<Button name="APPLY FILTERS" className={cn("w-full bg-black text-white", CustomClasses.filterButton)} />
<Button name="CLEAR ALL" className={cn("w-full bg-(--clearAllFilterBtn) text-black", CustomClasses.filterButton)} />
<Button name="CLEAR ALL" className={cn("w-full bg-(--clearAllFilterBtn) text-black", CustomClasses.filterButton)} onClick={clearFilters} />
</div>
</div>
);
}
}
21 changes: 18 additions & 3 deletions src/components/utilities/filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@ import { cn } from "../../lib/utils";
import Icon from "../../lib/iconConfig";
import { CustomClasses } from "./customClasses";

export function Filter({name, items}: {name: string, items: string[]}) {
export function Filter({
name,
items,
selectedItem,
setSelectedItem,
}: {
name: string;
items: string[];
selectedItem: string;
setSelectedItem: (item: string) => void;
}) {
return (
<div className={cn("flex flex-col border-2 border-black bg-(--filterSection)")}>
<h1 className={cn("flex flex-row items-center gap-2 m-2 ml-3 font-bold text-xl cursor-pointer")}>
Expand All @@ -16,12 +26,17 @@ export function Filter({name, items}: {name: string, items: string[]}) {
{items.map((item, index) => (
<li key={index} className={cn("flex flex-row items-center gap-2")}>
<label className={cn("flex flex-row items-center gap-2 cursor-pointer")}>
<input type="checkbox" className={cn("w-4 h-4 appearance-none border border-black checked:bg-black cursor-pointer")} />
<input
type="checkbox"
checked={selectedItem === item}
onChange={() => setSelectedItem(selectedItem === item ? "" : item)}
className={cn("w-4 h-4 appearance-none border border-black checked:bg-black cursor-pointer")}
/>
<span className={cn("text-black/60")}>{item}</span>
</label>
</li>
))}
</ul>
</div>
);
}
}
48 changes: 48 additions & 0 deletions src/hooks/useTableFilters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { useSearchParams } from "react-router-dom";

export function useTableFilters() {
const [params, setParams] = useSearchParams();

const page = Math.max(1, Math.floor(Number(params.get("page")) || 1));
const search = params.get("search") ?? "";
const category = params.get("category") ?? "";

const updateParam = (key: "search" | "page" | "category", value: string) => {
setParams((currentParams) => {
const nextParams = new URLSearchParams(currentParams);
const nextValue = value.trim();

if (!nextValue || (key === "page" && nextValue === "1")) {
nextParams.delete(key);
} else {
nextParams.set(key, nextValue);
}

if (key !== "page") {
nextParams.delete("page");
}

return nextParams;
});
};

return {
page,
search,
category,
setPage: (nextPage: number) => updateParam("page", String(nextPage)),
setSearch: (nextSearch: string) => updateParam("search", nextSearch),
setCategory: (nextCategory: string) => updateParam("category", nextCategory),
clearFilters: () => {
setParams((currentParams) => {
const nextParams = new URLSearchParams(currentParams);

nextParams.delete("search");
nextParams.delete("page");
nextParams.delete("category");

return nextParams;
});
},
};
}
77 changes: 45 additions & 32 deletions src/pages/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,59 @@ import { CustomClasses } from "../components/utilities/customClasses";
import EditForm from "../components/ui/editForm";
import { mockedProducts } from "../api/mockeddata";
import TableNavigation from "../components/ui/tableNavigation";
import { useState } from "react";
import { useEffect, useMemo, useState } from "react";
import { useTableFilters } from "../hooks/useTableFilters";

export default function Layout() {
const [isEditFormOpen, setIsEditFormOpen] = useState(false);
const [currentPage, setCurrentPage] = useState(1);
const tableFilters = useTableFilters();
function handleSetCurrentPage(page: number) {
if (page < 1) {
setCurrentPage(1);
tableFilters.setPage(1);
} else if (page > pages) {
setCurrentPage(pages);
tableFilters.setPage(pages);
} else {
setCurrentPage(page);
tableFilters.setPage(page);
}
}
const itemsPerPage = 7;
const pages = Math.ceil(mockedProducts.length / itemsPerPage);
const categories = useMemo(
() => Array.from(new Set(mockedProducts.map((product) => product.category))),
[],
);
const filteredProducts = useMemo(() => {
const search = tableFilters.search.toLowerCase();

return mockedProducts.filter((product) => {
const matchesCategory =
!tableFilters.category || product.category === tableFilters.category;
const matchesSearch =
!search ||
product.productName.toLowerCase().includes(search) ||
product.barcode.toLowerCase().includes(search) ||
product.producer.toLowerCase().includes(search);

return matchesCategory && matchesSearch;
});
}, [tableFilters.category, tableFilters.search]);
const pages = Math.max(1, Math.ceil(filteredProducts.length / itemsPerPage));

useEffect(() => {
if (tableFilters.page > pages) {
tableFilters.setPage(pages);
}
}, [pages, tableFilters]);

return (
<div className={cn("flex flex-col gap-4 h-screen w-full p-3")}>
<Header />
<Header search={tableFilters.search} setSearch={tableFilters.setSearch} />
<div className={cn("flex flex-row gap-4 flex-1 overflow-hidden")}>
<SideBar />
<SideBar
categories={categories}
selectedCategory={tableFilters.category}
setSelectedCategory={tableFilters.setCategory}
clearFilters={tableFilters.clearFilters}
/>
<div className={cn("flex flex-col gap-4 flex-1 min-w-0")}>
<div
className={cn(
Expand All @@ -40,27 +71,9 @@ export default function Layout() {
<div className={cn("flex-1 min-w-0 overflow-x-auto pb-4 pr-4")}>
<SelectedFilters
selectedFilters={[
"test",
"test2",
"test3",
"test4",
"test5",
"test6",
"test7",
"test8",
"test9",
"test10",
"test11",
"test12",
"test13",
"test14",
"test15",
"test16",
"test17",
"test18",
"test19",
"test20",
]}
tableFilters.search,
tableFilters.category,
].filter(Boolean)}
/>
</div>
<div className={cn("shrink-0")}>
Expand All @@ -78,14 +91,14 @@ export default function Layout() {
<div className={cn("flex flex-row gap-4 h-full justify-between")}>
<div className={cn("flex flex-col h-full gap-4 w-full")}>
<Table
data={mockedProducts}
data={filteredProducts}
number={itemsPerPage}
page={currentPage}
page={tableFilters.page}
setIsEditFormOpen={setIsEditFormOpen}
/>
<TableNavigation
pages={pages}
currentPage={currentPage}
currentPage={tableFilters.page}
setCurrentPage={handleSetCurrentPage}
/>
</div>
Expand Down
Loading