Skip to content
This repository has been archived by the owner on Mar 23, 2024. It is now read-only.

Fix/search bar #144

Merged
merged 8 commits into from
Mar 9, 2024
Merged
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
4 changes: 4 additions & 0 deletions client/src/app/(main)/layout.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
}
}

.content_zone {
margin-bottom: 48px;
}

.placeholder {
width: 93px;
flex-shrink: 0;
Expand Down
3 changes: 3 additions & 0 deletions client/src/app/(main)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export default function Home() {
type: 'checkbox',
placeholder: 'Search by countries',
optionsArr: countries,
oneItemName: 'country',
filterValue: [],
},
{
Expand All @@ -57,6 +58,7 @@ export default function Home() {
type: 'checkbox',
placeholder: 'Search by specialty',
optionsArr: specialities,
oneItemName: 'speciality',
filterValue: [],
},
{
Expand All @@ -65,6 +67,7 @@ export default function Home() {
type: 'checkbox',
placeholder: 'Search by focus',
optionsArr: focusesValues,
oneItemName: 'focus',
filterValue: [],
},
]}
Expand Down
4 changes: 4 additions & 0 deletions client/src/shared/ui/checkbox/checkbox.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
}

.label {
width: calc(100% - 26px);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--white-color);
font: var(--font-body-weight-m) var(--font-body-size-m) / var(--font-body-line-m)
var(--font-rubik);
Expand Down
29 changes: 16 additions & 13 deletions client/src/shared/ui/drawer/drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import React, { FC, PropsWithChildren } from 'react';
import DrawerComponent from 'react-modern-drawer';
import 'react-modern-drawer/dist/index.css';
import { Portal } from '../portal';

interface DrawerProps {
open: boolean;
Expand Down Expand Up @@ -65,18 +66,20 @@ export const Drawer: FC<PropsWithChildren<DrawerProps>> = props => {
} as React.CSSProperties;

return (
<DrawerComponent
zIndex={999}
open={open}
onClose={onClose}
direction={direction}
style={style}
className={className}
overlayClassName={overlayClassName}
customIdSuffix='t8s-drawer'
lockBackgroundScroll
>
{children}
</DrawerComponent>
<Portal>
<DrawerComponent
zIndex={999}
open={open}
onClose={onClose}
direction={direction}
style={style}
className={className}
overlayClassName={overlayClassName}
customIdSuffix='t8s-drawer'
lockBackgroundScroll
>
{children}
</DrawerComponent>
</Portal>
);
};
38 changes: 38 additions & 0 deletions client/src/shared/ui/search-bar/actions/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { MultiValue } from 'react-select';
import { Action, ActionTypesEnum } from './types';
import { IOptionItem } from '../types';

export const changeFilterValue = (
filterIndex: number,
newValue: string | MultiValue<IOptionItem> | [number, number] | null
): Action<ActionTypesEnum.CHANGE_FILTER_VALUE> => ({
type: ActionTypesEnum.CHANGE_FILTER_VALUE,
payload: {
filterIndex,
newValue,
},
});

export const clearOneMultipleOption = (
filterIndex: number,
optionIndex: number
): Action<ActionTypesEnum.CLEAR_ONE_MULTIPLE_OPTION> => ({
type: ActionTypesEnum.CLEAR_ONE_MULTIPLE_OPTION,
payload: { filterIndex, optionIndex },
});

export const clearAllExceptOneMultipleOptions = (
filterIndex: number
): Action<ActionTypesEnum.CLEAR_ALL_EXCEPT_ONE_MULTIPLE_OPTIONS> => ({
type: ActionTypesEnum.CLEAR_ALL_EXCEPT_ONE_MULTIPLE_OPTIONS,
payload: filterIndex,
});

export const clearFilter = (filterIndex: number): Action<ActionTypesEnum.CLEAR_FILTER> => ({
type: ActionTypesEnum.CLEAR_FILTER,
payload: filterIndex,
});

export const clearAllFilters = (): Action<ActionTypesEnum.CLEAR_ALL_FILTERS> => ({
type: ActionTypesEnum.CLEAR_ALL_FILTERS,
});
9 changes: 9 additions & 0 deletions client/src/shared/ui/search-bar/actions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export {
changeFilterValue,
clearOneMultipleOption,
clearAllExceptOneMultipleOptions,
clearFilter,
clearAllFilters,
} from './actions';
export type { Action } from './types';
export { ActionTypesEnum } from './types';
39 changes: 39 additions & 0 deletions client/src/shared/ui/search-bar/actions/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { MultiValue } from 'react-select';
import { IOptionItem } from '../types';

export enum ActionTypesEnum {
CHANGE_FILTER_VALUE = 'CHANGE_FILTER_VALUE',
CLEAR_ONE_MULTIPLE_OPTION = 'CLEAR_ONE_MULTIPLE_OPTION',
CLEAR_ALL_EXCEPT_ONE_MULTIPLE_OPTIONS = 'CLEAR_ALL_EXCEPT_ONE_MULTIPLE_OPTIONS',
CLEAR_FILTER = 'CLEAR_FILTER',
CLEAR_ALL_FILTERS = 'CLEAR_ALL_FILTERS',
}

type ActionsWithoutPayload = ActionTypesEnum.CLEAR_ALL_FILTERS;

interface ActionWithoutPayload {
type: ActionsWithoutPayload;
}

export interface ActionWithPayload<T extends ActionTypesEnum> {
type: T;
payload: ActionsPayloads[T];
}

interface ActionsPayloads {
[ActionTypesEnum.CHANGE_FILTER_VALUE]: {
filterIndex: number;
newValue: string | MultiValue<IOptionItem> | [number, number] | null;
};
[ActionTypesEnum.CLEAR_ONE_MULTIPLE_OPTION]: {
filterIndex: number;
optionIndex: number;
};
[ActionTypesEnum.CLEAR_ALL_EXCEPT_ONE_MULTIPLE_OPTIONS]: number;
[ActionTypesEnum.CLEAR_FILTER]: number;
[ActionTypesEnum.CLEAR_ALL_FILTERS]: never;
}

export type Action<T extends ActionTypesEnum> = T extends ActionsWithoutPayload
? ActionWithoutPayload
: ActionWithPayload<T>;
1 change: 1 addition & 0 deletions client/src/shared/ui/search-bar/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { useTrackFilterArr } from './useTrackFiltersArr';
export { useFilters } from './useFilters';
export { useFilterReducer } from './useFilterReducer';
132 changes: 132 additions & 0 deletions client/src/shared/ui/search-bar/hooks/useFilterReducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { useReducer } from 'react';
import { Filter, IFilterState } from '../types';
import { ActionTypesEnum, Action } from '../actions';

const reducer = (state: IFilterState, action: Action<ActionTypesEnum>) => {
switch (action.type) {
case ActionTypesEnum.CLEAR_ONE_MULTIPLE_OPTION: {
const { filterIndex, optionIndex } = action.payload;
const filter = state.filterArr[filterIndex];

if (filter.type === 'checkbox' || filter.type === 'multiple') {
const newFilterValue = filter.filterValue.filter((item, i) => i !== optionIndex);

return {
isTimerDisabled: false,
filterArr: state.filterArr.map((item, i) => {
if (filterIndex === i) {
item.filterValue = newFilterValue;
}

return item;
}),
};
}

return state;
}

case ActionTypesEnum.CLEAR_ALL_EXCEPT_ONE_MULTIPLE_OPTIONS: {
const filterIndex = action.payload;
const filter = state.filterArr[filterIndex];

if (filter.type === 'checkbox' || filter.type === 'multiple') {
const newFilterValue = [filter.filterValue[0]];

return {
isTimerDisabled: true,
filterArr: state.filterArr.map((item, i) => {
if (filterIndex === i) {
item.filterValue = newFilterValue;
}

return item;
}),
};
}

return state;
}

case ActionTypesEnum.CHANGE_FILTER_VALUE: {
const { filterIndex, newValue } = action.payload;

return {
isTimerDisabled: false,
filterArr: state.filterArr.map((item, i) => {
if (filterIndex === i) {
item.filterValue = newValue;
}

return item;
}),
};
}

case ActionTypesEnum.CLEAR_FILTER: {
const filterIndex = action.payload;

return {
isTimerDisabled: false,
filterArr: state.filterArr.map((item, index) => {
if (index === filterIndex) {
switch (item.type) {
case 'text':
item.filterValue = '';

return item;

case 'multiple':
case 'checkbox':
item.filterValue = [];

return item;

case 'range':
item.filterValue = null;

return item;
}
}

return item;
}),
};
}

case ActionTypesEnum.CLEAR_ALL_FILTERS: {
return {
isTimerDisabled: false,
filterArr: state.filterArr.map(item => {
switch (item.type) {
case 'text':
item.filterValue = '';

return item;

case 'multiple':
case 'checkbox':
item.filterValue = [];

return item;

case 'range':
item.filterValue = null;

return item;
}
}),
};
}

default:
return state;
}
};

export const useFilterReducer = (initialState: Filter[]) => {
return useReducer(reducer, {
isTimerDisabled: false,
filterArr: initialState,
});
};
Loading
Loading