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
12 changes: 12 additions & 0 deletions frontend/src/components/FormElements/FormElements.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ type InputType = React.DetailedHTMLProps<
HTMLInputElement
>;

/**
* Styled input component
*
* Auto applies type-specific styles (like textInput or emailInput)
*/
export const Input = React.forwardRef<HTMLInputElement, InputType>(
({ type, className, ...props }, ref) => (
<input
Expand All @@ -56,6 +61,13 @@ type ButtonProps = {
disabled?: boolean;
};

/**
* Reusable button component with size + style variants
*
* - 'outline' switches between primary and secondary styles
* - 'small' turns on compact sizing
* - click handler is disabled automatically when 'disabled is true
*/
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
(props, ref) => {
const {
Expand Down
23 changes: 23 additions & 0 deletions frontend/src/components/FormElements/SearchAndFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ export default function SearchAndFilter<T extends Record<string, any>>({
const [isFilterOpen, setIsFilterOpen] = useState(false);
const [activeSection, setActiveSection] = useState<string | null>(null);

/**
* Handles changes to the search input.
* Applies search and currently active filters in real time.
*/

const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newSearchTerm = e.target.value;
setSearchTerm(newSearchTerm);
Expand Down Expand Up @@ -75,6 +80,10 @@ export default function SearchAndFilter<T extends Record<string, any>>({
onFilterApply(searchFilteredItems);
};

/**
* Toggles a filter value on or off for a given field.
* Updates pending filters only.
*/
const toggleFilter = (field: string, value: string) => {
setPendingFilters((prevFilters) => {
const updatedFilters = { ...prevFilters };
Expand All @@ -94,10 +103,17 @@ export default function SearchAndFilter<T extends Record<string, any>>({
});
};

/**
* Returns the total number of active filter values.
*/
const getActiveFilterCount = () => {
return Object.values(filters).reduce((acc, curr) => acc + curr.length, 0);
};

/**
* Clears all applied and pending filters.
* Keeps the current search term active.
*/
const clearFilters = () => {
setPendingFilters({});
setFilters({});
Expand All @@ -115,6 +131,9 @@ export default function SearchAndFilter<T extends Record<string, any>>({
onFilterApply(searchFilteredItems);
};

/**
* Applies pending filters and updates the result set.
*/
const applyFilters = () => {
setFilters(pendingFilters);

Expand Down Expand Up @@ -159,6 +178,10 @@ export default function SearchAndFilter<T extends Record<string, any>>({
setIsFilterOpen(false);
};

/**
* Resets search input and all filters.
* Restores the full item list.
*/
const clearAll = () => {
setSearchTerm('');
setFilters({});
Expand Down
Loading