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 7 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
1 change: 1 addition & 0 deletions client/src/app/(main)/layout.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
}

.content_zone {
margin-bottom: 48px;
padding-left: 88px;

@media screen and (max-width: 768px) {
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