Skip to content

Commit

Permalink
Table sorting: added change icon when toggling ascending and descending
Browse files Browse the repository at this point in the history
Adjusted sort data type on IListCell to have parameter for asc and desc sorting
Adjusted useHover to be a proper hook
  • Loading branch information
JochemVH1 committed Jan 20, 2025
1 parent 33642ee commit a539bf6
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 19 deletions.
2 changes: 1 addition & 1 deletion frontend/src/components/controls/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,4 @@ export const EmailedIcon = ({...props}) => (
</Icon>
);

export const SortIcon = ({...props}) => <Icon className="tst-sort" fa="fa fa-sort" {...props} />;
export const SortIcon = ({...props}: IconProps) => <Icon className="tst-sort" {...props} />;
7 changes: 6 additions & 1 deletion frontend/src/components/controls/table/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,14 @@ export const List = ({feature}: ListProps) => {
data = data.slice().sort(feature.list.sorter);
}

const handleSort = (sort: any) => {
data = data.slice().sort(sort);
console.log("sorted", data.map((val) => val.consultantName));
}

return (
<Table size="sm" className={`table-${feature.key}`}>
<ListHeader feature={feature} />
<ListHeader feature={feature} onSort={handleSort} />
<tbody>
{data.slice(page * listSize, page * listSize + listSize).map(model => (
<ListRow config={config} model={model} key={model._id} />
Expand Down
11 changes: 4 additions & 7 deletions frontend/src/components/controls/table/ListHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import {t} from '../../utils';
import {IFeature} from '../feature/feature-models';
import { SortIcon } from '../Icon';
import { ListHeaderCell } from './ListHeaderCell';


type ListHeaderProps<TModel> = {
feature: IFeature<TModel>;
onSort?: (sort?: (a: TModel, b: TModel) => number) => void
}


// eslint-disable-next-line arrow-body-style
export const ListHeader = ({feature}: ListHeaderProps<any>) => {
export const ListHeader = ({feature, onSort}: ListHeaderProps<any>) => {
return (
<thead>
<tr>
Expand All @@ -31,10 +31,7 @@ export const ListHeader = ({feature}: ListHeaderProps<any>) => {
}

return (
<th key={col.key} style={{width}}>
{header ? t(header) : <>&nbsp;</>}
{addSort ? <><SortIcon/></> : <>&nbsp;</>}
</th>
<ListHeaderCell key={col.key} width={width} header={header} addSort={addSort} onSort={(asc) => { if(onSort && col.sort) onSort(col.sort(asc)) }}/>
);
})}
</tr>
Expand Down
20 changes: 17 additions & 3 deletions frontend/src/components/controls/table/ListHeaderCell.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
export const ListHeaderCell = () => {
import { useState } from "react";
import useHover from "../../hooks/useHover";
import { t } from "../../utils";
import { SortIcon } from "../Icon";

type ListHeaderCellProps = {
width: string | undefined | number
header:string
addSort: boolean,
onSort?: (asc: boolean) => void
}

export const ListHeaderCell = ({width, header, addSort, onSort}: ListHeaderCellProps) => {
const [hovered, eventHandlers] = useHover();
const [asc, setAsc] = useState<boolean | undefined>(undefined)

return (
<th key={col.key} style={{width}} {...eventHandlers}>

<th style={{width}} {...eventHandlers}>
{header ? t(header) : <>&nbsp;</>}
{addSort ? <><SortIcon/></> : <>&nbsp;</>}
{addSort && hovered ? <><SortIcon fa={asc ? "fa fa-arrow-up" : "fa fa-arrow-down"} onClick={() => {setAsc(!asc); if(onSort) onSort(!asc);}} size={1}/></> : <>&nbsp;</>}
</th>
)
}
2 changes: 1 addition & 1 deletion frontend/src/components/controls/table/table-models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export interface IListCell<TModel> {
/** Will span until next cell with a footer */
footer?: string | ((models: TModel[]) => string | React.ReactNode);

sort?: StringFn<TModel>
sort?: (asc: boolean) => (a: TModel, b: TModel) => number
}


Expand Down
10 changes: 6 additions & 4 deletions frontend/src/components/hooks/useHover.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
const { useState, useMemo } = React;
import { useState, useMemo } from 'react';

const useHover = () => {
const [hovered, setHovered] = useState<boolean>();
const useHover = () : [boolean, { onMouseOver(): void, onMouseOut(): void}] => {
const [hovered, setHovered] = useState<boolean>(false);

const eventHandlers = useMemo(() => ({
onMouseOver() { setHovered(true); },
onMouseOut() { setHovered(false); }
}), []);

return {hovered, eventHandlers};
return [hovered, eventHandlers];
}

export default useHover;
1 change: 0 additions & 1 deletion frontend/src/components/project/ProjectsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export const ProjectsList = () => {
</>
);


const feature = projectFeature(config);
return <ListPage feature={feature} topToolbar={TopToolbar} />;
};
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ const projectListConfig = (config: ProjectFeatureBuilderConfig): IList<FullProje
header: 'project.consultant',
value: p => <ConsultantLinkWithModal consultant={p.consultant} showType />,
footer: (models: FullProjectModel[]) => <ConsultantCountFooter consultants={models.map(x => x.consultant)} />,
sort: p => p.consultantName
sort: (asc) => (p, p2) => p.consultantName > p2.consultantName ? (asc ? 1 : -1) : (asc ? -1 : 1)
}, {
key: 'startDate',
header: 'project.startDate',
Expand Down

0 comments on commit a539bf6

Please sign in to comment.