diff --git a/.pnp.cjs b/.pnp.cjs index 8456376d..1fce15b8 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -49,6 +49,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@testing-library/jest-dom", "virtual:1c437dc0bcbbbbb8e13ce8545c57ffe2159f1e83486bc58aea069eb9730fc148eb58a88a9843f21c194c41eb6c191104836828c12c5751cdded24f62d33f0a43#npm:6.1.2"],\ ["@testing-library/react", "virtual:1c437dc0bcbbbbb8e13ce8545c57ffe2159f1e83486bc58aea069eb9730fc148eb58a88a9843f21c194c41eb6c191104836828c12c5751cdded24f62d33f0a43#npm:14.0.0"],\ ["@testing-library/user-event", "virtual:1c437dc0bcbbbbb8e13ce8545c57ffe2159f1e83486bc58aea069eb9730fc148eb58a88a9843f21c194c41eb6c191104836828c12c5751cdded24f62d33f0a43#npm:14.4.3"],\ + ["@types/debounce-promise", "npm:3.1.9"],\ ["@types/jest", "npm:29.5.4"],\ ["@types/lodash", "npm:4.14.200"],\ ["@types/node", "npm:20.5.7"],\ @@ -64,6 +65,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["commitlint", "npm:17.7.1"],\ ["concurrently", "npm:8.2.1"],\ ["date-fns", "npm:2.30.0"],\ + ["debounce-promise", "npm:3.1.2"],\ ["dotenv", "npm:16.3.1"],\ ["eslint", "npm:8.48.0"],\ ["eslint-config-prettier", "virtual:1c437dc0bcbbbbb8e13ce8545c57ffe2159f1e83486bc58aea069eb9730fc148eb58a88a9843f21c194c41eb6c191104836828c12c5751cdded24f62d33f0a43#npm:9.0.0"],\ @@ -95,6 +97,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["react-router-dom", "virtual:1c437dc0bcbbbbb8e13ce8545c57ffe2159f1e83486bc58aea069eb9730fc148eb58a88a9843f21c194c41eb6c191104836828c12c5751cdded24f62d33f0a43#npm:6.15.0"],\ ["release-it", "npm:16.1.5"],\ ["typescript", "patch:typescript@npm%3A5.1.6#~builtin::version=5.1.6&hash=5da071"],\ + ["use-debounce", "virtual:1c437dc0bcbbbbb8e13ce8545c57ffe2159f1e83486bc58aea069eb9730fc148eb58a88a9843f21c194c41eb6c191104836828c12c5751cdded24f62d33f0a43#npm:10.0.0"],\ ["uuid", "npm:9.0.1"],\ ["vite", "virtual:1c437dc0bcbbbbb8e13ce8545c57ffe2159f1e83486bc58aea069eb9730fc148eb58a88a9843f21c194c41eb6c191104836828c12c5751cdded24f62d33f0a43#npm:4.4.9"],\ ["vite-bundle-visualizer", "npm:0.10.0"],\ @@ -7139,6 +7142,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@types/debounce-promise", [\ + ["npm:3.1.9", {\ + "packageLocation": "./.yarn/cache/@types-debounce-promise-npm-3.1.9-9aea081a63-ea6c38c8d4.zip/node_modules/@types/debounce-promise/",\ + "packageDependencies": [\ + ["@types/debounce-promise", "npm:3.1.9"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/debug", [\ ["npm:4.1.8", {\ "packageLocation": "./.yarn/cache/@types-debug-npm-4.1.8-a04e2ca136-a9a9bb40a1.zip/node_modules/@types/debug/",\ @@ -9671,6 +9683,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["debounce-promise", [\ + ["npm:3.1.2", {\ + "packageLocation": "./.yarn/cache/debounce-promise-npm-3.1.2-3c185da0c7-29bac4524c.zip/node_modules/debounce-promise/",\ + "packageDependencies": [\ + ["debounce-promise", "npm:3.1.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["debug", [\ ["npm:3.2.7", {\ "packageLocation": "./.yarn/cache/debug-npm-3.2.7-754e818c7a-b3d8c59407.zip/node_modules/debug/",\ @@ -16088,6 +16109,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@testing-library/jest-dom", "virtual:1c437dc0bcbbbbb8e13ce8545c57ffe2159f1e83486bc58aea069eb9730fc148eb58a88a9843f21c194c41eb6c191104836828c12c5751cdded24f62d33f0a43#npm:6.1.2"],\ ["@testing-library/react", "virtual:1c437dc0bcbbbbb8e13ce8545c57ffe2159f1e83486bc58aea069eb9730fc148eb58a88a9843f21c194c41eb6c191104836828c12c5751cdded24f62d33f0a43#npm:14.0.0"],\ ["@testing-library/user-event", "virtual:1c437dc0bcbbbbb8e13ce8545c57ffe2159f1e83486bc58aea069eb9730fc148eb58a88a9843f21c194c41eb6c191104836828c12c5751cdded24f62d33f0a43#npm:14.4.3"],\ + ["@types/debounce-promise", "npm:3.1.9"],\ ["@types/jest", "npm:29.5.4"],\ ["@types/lodash", "npm:4.14.200"],\ ["@types/node", "npm:20.5.7"],\ @@ -16103,6 +16125,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["commitlint", "npm:17.7.1"],\ ["concurrently", "npm:8.2.1"],\ ["date-fns", "npm:2.30.0"],\ + ["debounce-promise", "npm:3.1.2"],\ ["dotenv", "npm:16.3.1"],\ ["eslint", "npm:8.48.0"],\ ["eslint-config-prettier", "virtual:1c437dc0bcbbbbb8e13ce8545c57ffe2159f1e83486bc58aea069eb9730fc148eb58a88a9843f21c194c41eb6c191104836828c12c5751cdded24f62d33f0a43#npm:9.0.0"],\ @@ -16134,6 +16157,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["react-router-dom", "virtual:1c437dc0bcbbbbb8e13ce8545c57ffe2159f1e83486bc58aea069eb9730fc148eb58a88a9843f21c194c41eb6c191104836828c12c5751cdded24f62d33f0a43#npm:6.15.0"],\ ["release-it", "npm:16.1.5"],\ ["typescript", "patch:typescript@npm%3A5.1.6#~builtin::version=5.1.6&hash=5da071"],\ + ["use-debounce", "virtual:1c437dc0bcbbbbb8e13ce8545c57ffe2159f1e83486bc58aea069eb9730fc148eb58a88a9843f21c194c41eb6c191104836828c12c5751cdded24f62d33f0a43#npm:10.0.0"],\ ["uuid", "npm:9.0.1"],\ ["vite", "virtual:1c437dc0bcbbbbb8e13ce8545c57ffe2159f1e83486bc58aea069eb9730fc148eb58a88a9843f21c194c41eb6c191104836828c12c5751cdded24f62d33f0a43#npm:4.4.9"],\ ["vite-bundle-visualizer", "npm:0.10.0"],\ @@ -17709,6 +17733,28 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["use-debounce", [\ + ["npm:10.0.0", {\ + "packageLocation": "./.yarn/cache/use-debounce-npm-10.0.0-04f7df41a1-b296fedba9.zip/node_modules/use-debounce/",\ + "packageDependencies": [\ + ["use-debounce", "npm:10.0.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:1c437dc0bcbbbbb8e13ce8545c57ffe2159f1e83486bc58aea069eb9730fc148eb58a88a9843f21c194c41eb6c191104836828c12c5751cdded24f62d33f0a43#npm:10.0.0", {\ + "packageLocation": "./.yarn/__virtual__/use-debounce-virtual-6ee902d8e7/0/cache/use-debounce-npm-10.0.0-04f7df41a1-b296fedba9.zip/node_modules/use-debounce/",\ + "packageDependencies": [\ + ["use-debounce", "virtual:1c437dc0bcbbbbb8e13ce8545c57ffe2159f1e83486bc58aea069eb9730fc148eb58a88a9843f21c194c41eb6c191104836828c12c5751cdded24f62d33f0a43#npm:10.0.0"],\ + ["@types/react", "npm:18.2.21"],\ + ["react", "npm:18.2.0"]\ + ],\ + "packagePeers": [\ + "@types/react",\ + "react"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["use-isomorphic-layout-effect", [\ ["npm:1.1.2", {\ "packageLocation": "./.yarn/cache/use-isomorphic-layout-effect-npm-1.1.2-65facd0a4b-a6532f7fc9.zip/node_modules/use-isomorphic-layout-effect/",\ diff --git a/.yarn/cache/@types-debounce-promise-npm-3.1.9-9aea081a63-ea6c38c8d4.zip b/.yarn/cache/@types-debounce-promise-npm-3.1.9-9aea081a63-ea6c38c8d4.zip new file mode 100644 index 00000000..cbca540a Binary files /dev/null and b/.yarn/cache/@types-debounce-promise-npm-3.1.9-9aea081a63-ea6c38c8d4.zip differ diff --git a/.yarn/cache/debounce-promise-npm-3.1.2-3c185da0c7-29bac4524c.zip b/.yarn/cache/debounce-promise-npm-3.1.2-3c185da0c7-29bac4524c.zip new file mode 100644 index 00000000..f19ab778 Binary files /dev/null and b/.yarn/cache/debounce-promise-npm-3.1.2-3c185da0c7-29bac4524c.zip differ diff --git a/.yarn/cache/use-debounce-npm-10.0.0-04f7df41a1-b296fedba9.zip b/.yarn/cache/use-debounce-npm-10.0.0-04f7df41a1-b296fedba9.zip new file mode 100644 index 00000000..99a2416d Binary files /dev/null and b/.yarn/cache/use-debounce-npm-10.0.0-04f7df41a1-b296fedba9.zip differ diff --git a/package.json b/package.json index 33ed9031..89b0428d 100644 --- a/package.json +++ b/package.json @@ -40,11 +40,13 @@ "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@tanstack/react-query": "^4.35.3", + "@types/debounce-promise": "^3.1.9", "@types/lodash": "^4.14.200", "@types/uuid": "^9.0.7", "axios": "^1.6.0", "chakra-react-select": "^4.7.6", "date-fns": "^2.30.0", + "debounce-promise": "^3.1.2", "form-data": "^4.0.0", "framer-motion": "^10.17.0", "lodash": "^4.17.21", @@ -55,6 +57,7 @@ "react-hook-form": "^7.45.4", "react-icons": "^4.11.0", "react-router-dom": "^6.15.0", + "use-debounce": "^10.0.0", "uuid": "^9.0.1", "zustand": "^4.4.1" }, diff --git a/src/features/filter/FilterSpecialization.tsx b/src/features/filter/FilterSpecialization.tsx index b061aa05..54989832 100644 --- a/src/features/filter/FilterSpecialization.tsx +++ b/src/features/filter/FilterSpecialization.tsx @@ -10,9 +10,12 @@ import { useDisclosure, } from '@chakra-ui/react'; import { useState } from 'react'; +import { useDebounce } from 'use-debounce'; import { useGetSpecs, useGetSpecsGroups } from '~/entities/storage'; +import { TIME } from '~/shared/lib/const'; + import { FilterSpecializationModal } from './FilterSpecializationModal'; export interface FilterSpecializationProps { @@ -30,10 +33,11 @@ export const FilterSpecialization = ({ }: FilterSpecializationProps) => { const { isOpen, onOpen, onClose } = useDisclosure(); const [searchText, setSearchText] = useState(''); + const [debounceText] = useDebounce(searchText, TIME.DEBOUNCE); const { data: specGroup } = useGetSpecsGroups(); const { data: specs } = useGetSpecs({ - query_text: searchText, + query: debounceText, }); const deleteSpecFilter = (id: string) => { diff --git a/src/pages/search/api/useGetAllPositions.tsx b/src/pages/search/api/useGetAllPositions.tsx index f265ae04..2a4e0c9c 100644 --- a/src/pages/search/api/useGetAllPositions.tsx +++ b/src/pages/search/api/useGetAllPositions.tsx @@ -23,7 +23,7 @@ export const useGetAllPositions = ({ specs, skills, date, searchText }: Search) specialization_ids: specs, skill_ids: skills?.map((skill) => skill.value), project_startline_ge: date, - project_query_text: searchText, + query: searchText, project_status: ['preparation', 'in_work'], }), getNextPageParam: (lastPage) => diff --git a/src/pages/search/ui/SearchPage.desktop.tsx b/src/pages/search/ui/SearchPage.desktop.tsx index c834fa9f..99eb5bcf 100644 --- a/src/pages/search/ui/SearchPage.desktop.tsx +++ b/src/pages/search/ui/SearchPage.desktop.tsx @@ -3,6 +3,7 @@ import { Flex, SimpleGrid, Skeleton, Box } from '@chakra-ui/react'; import { useQuery } from '@tanstack/react-query'; import React, { useRef, useState } from 'react'; import { Link, generatePath } from 'react-router-dom'; +import { useDebounce } from 'use-debounce'; import { ProjectCard } from '~/widgets/project-card'; @@ -14,6 +15,7 @@ import { useFilterStore } from '~/entities/project'; import { useGetSpecs } from '~/entities/storage'; import { useApi, useAuth, useInfinityScroll } from '~/shared/hooks'; +import { TIME } from '~/shared/lib/const'; import { PATHS } from '~/shared/lib/router'; import { STag } from '~/shared/ui/STag'; @@ -25,6 +27,7 @@ export const SearchPageDesktop = () => { const targetRef = useRef(null); const [searchText, setSearchText] = useState(''); + const [debounceText] = useDebounce(searchText, TIME.DEBOUNCE); const { filter } = useFilterStore(); @@ -38,7 +41,7 @@ export const SearchPageDesktop = () => { date: filter.date, skills: filter.skills, specs: filter.specs, - searchText, + searchText: debounceText, }); const { data: allSpecs } = useGetSpecs(); diff --git a/src/pages/search/ui/SearchPage.tsx b/src/pages/search/ui/SearchPage.tsx index 3f27f8f1..cd36f291 100644 --- a/src/pages/search/ui/SearchPage.tsx +++ b/src/pages/search/ui/SearchPage.tsx @@ -11,6 +11,7 @@ import { import { useQuery } from '@tanstack/react-query'; import React, { useRef, useState } from 'react'; import { Link, generatePath } from 'react-router-dom'; +import { useDebounce } from 'use-debounce'; import { ProjectCard } from '~/widgets/project-card'; @@ -23,6 +24,7 @@ import { useGetSpecs } from '~/entities/storage'; import { Avatar, NotAuthAvatar } from '~/entities/user'; import { useApi, useAuth, useInfinityScroll, useLayoutRefs } from '~/shared/hooks'; +import { TIME } from '~/shared/lib/const'; import { PATHS } from '~/shared/lib/router'; import { STag } from '~/shared/ui/STag'; @@ -35,6 +37,7 @@ export const SearchPage = () => { const layout = useLayoutRefs(); const [searchText, setSearchText] = useState(''); + const [debounceText] = useDebounce(searchText, TIME.DEBOUNCE); const { filter } = useFilterStore(); @@ -48,7 +51,7 @@ export const SearchPage = () => { date: filter.date, skills: filter.skills, specs: filter.specs, - searchText, + searchText: debounceText, }); const { data: allSpecs } = useGetSpecs(); diff --git a/src/shared/api/types/projects.ts b/src/shared/api/types/projects.ts index 99f9f2b3..b7eb036d 100644 --- a/src/shared/api/types/projects.ts +++ b/src/shared/api/types/projects.ts @@ -547,7 +547,7 @@ export interface operations { specialization_ids?: unknown; skill_ids?: unknown; joined_user_id?: unknown; - project_query_text?: unknown; + query?: unknown; project_startline_ge?: unknown; project_startline_le?: unknown; project_deadline_ge?: unknown; @@ -720,7 +720,7 @@ export interface operations { page?: number; /** @description Number of items per page */ per_page?: number; - query_text?: unknown; + query?: unknown; owner_id?: unknown; user_id?: unknown; startline_ge?: unknown; diff --git a/src/shared/api/types/storage.ts b/src/shared/api/types/storage.ts index 5c354744..69e92d2a 100644 --- a/src/shared/api/types/storage.ts +++ b/src/shared/api/types/storage.ts @@ -172,7 +172,7 @@ export interface operations { page?: number; /** @description Number of items per page */ per_page?: number; - query_text?: unknown; + query?: unknown; id?: unknown; exclude_id?: unknown; }; @@ -200,7 +200,7 @@ export interface operations { page?: number; /** @description Number of items per page */ per_page?: number; - query_text?: unknown; + query?: unknown; group_id?: unknown; id?: unknown; exclude_id?: unknown; @@ -229,7 +229,7 @@ export interface operations { page?: number; /** @description Number of items per page */ per_page?: number; - query_text?: unknown; + query?: unknown; }; }; requestBody?: { diff --git a/src/shared/lib/const.ts b/src/shared/lib/const.ts new file mode 100644 index 00000000..cacef341 --- /dev/null +++ b/src/shared/lib/const.ts @@ -0,0 +1,3 @@ +export const TIME = { + DEBOUNCE: 1000, +}; diff --git a/src/shared/ui/SearchSelect/SearchSelect.tsx b/src/shared/ui/SearchSelect/SearchSelect.tsx index 9e0b54f0..371b2dd5 100644 --- a/src/shared/ui/SearchSelect/SearchSelect.tsx +++ b/src/shared/ui/SearchSelect/SearchSelect.tsx @@ -2,15 +2,17 @@ import { SmallCloseIcon } from '@chakra-ui/icons'; import { Flex, IconButton, Tag, TagLabel, useToast } from '@chakra-ui/react'; import { useQuery } from '@tanstack/react-query'; import { - AsyncSelect, - chakraComponents, + type OptionsOrGroups, type GroupBase, type LoadingIndicatorProps, } from 'chakra-react-select'; -import { useEffect, useState } from 'react'; +import { AsyncSelect, chakraComponents } from 'chakra-react-select'; +import debounce from 'debounce-promise'; +import { useCallback, useEffect, useState } from 'react'; import type { GetSkillsParameters } from '~/shared/api/model'; import { useApi } from '~/shared/hooks'; +import { TIME } from '~/shared/lib/const'; import type { SelectOptions } from '~/shared/types'; const asyncComponents = { @@ -40,10 +42,9 @@ export const SearchSelect = ({ selectedItems, setSelectedItems }: SearchSelectPr const toast = useToast(); const { storageApi } = useApi(); const [unSelectedItems, setUnSelectedItems] = useState([]); - const [searchValue, setSearchValue] = useState(''); - const params: GetSkillsParameters = { - query_text: searchValue, + let params: GetSkillsParameters = { + // query: searchValue, exclude_id: selectedItems.map((item) => item.value), per_page: 10, }; @@ -86,6 +87,21 @@ export const SearchSelect = ({ selectedItems, setSelectedItems }: SearchSelectPr } }; + const getOptions = debounce( + async ( + value: string, + callback: ( + options: OptionsOrGroups>, + ) => void, + ) => { + params = { ...params, query: value }; + await refetch().then((response) => { + callback(response.data ?? []); + }); + }, + TIME.DEBOUNCE, + ); + return ( <> > @@ -97,14 +113,9 @@ export const SearchSelect = ({ selectedItems, setSelectedItems }: SearchSelectPr components={asyncComponents} defaultOptions={unSelectedItems} value={null} - loadOptions={(inputValue, callback) => { - setSearchValue(inputValue); - requestAnimationFrame(() => { - refetch().then((response) => { - callback(response.data ?? []); - }); - }); - }} + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + loadOptions={getOptions} onChange={(item) => { if (item) { setSelectedItems([...selectedItems, item]); diff --git a/yarn.lock b/yarn.lock index c7e91a0a..b06c703d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4205,6 +4205,13 @@ __metadata: languageName: node linkType: hard +"@types/debounce-promise@npm:^3.1.9": + version: 3.1.9 + resolution: "@types/debounce-promise@npm:3.1.9" + checksum: ea6c38c8d4b6006aea25fb9891281b0ea908aab7ae32755e85dfda1ae78331dab1884da7143aa4ca5166741884bc9f7665391072ddce800b5d2c1f44d4a11b9d + languageName: node + linkType: hard + "@types/debug@npm:^4.1.7": version: 4.1.8 resolution: "@types/debug@npm:4.1.8" @@ -6265,6 +6272,13 @@ __metadata: languageName: node linkType: hard +"debounce-promise@npm:^3.1.2": + version: 3.1.2 + resolution: "debounce-promise@npm:3.1.2" + checksum: 29bac4524c423cc852319d7455363909ea3d933a3b9e3eb1149d963cffc34c475fe37219d0bafc61af566500b5d663cba579bbad7ee4023bef06f8394ed900ad + languageName: node + linkType: hard + "debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" @@ -11781,6 +11795,7 @@ __metadata: "@testing-library/jest-dom": ^6.1.2 "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.4.3 + "@types/debounce-promise": ^3.1.9 "@types/jest": ^29.5.4 "@types/lodash": ^4.14.200 "@types/node": ^20.5.7 @@ -11796,6 +11811,7 @@ __metadata: commitlint: ^17.7.1 concurrently: ^8.2.1 date-fns: ^2.30.0 + debounce-promise: ^3.1.2 dotenv: ^16.3.1 eslint: ^8.48.0 eslint-config-prettier: ^9.0.0 @@ -11827,6 +11843,7 @@ __metadata: react-router-dom: ^6.15.0 release-it: ^16.1.5 typescript: ^5.1.6 + use-debounce: ^10.0.0 uuid: ^9.0.1 vite: ^4.4.9 vite-bundle-visualizer: ^0.10.0 @@ -13199,6 +13216,15 @@ __metadata: languageName: node linkType: hard +"use-debounce@npm:^10.0.0": + version: 10.0.0 + resolution: "use-debounce@npm:10.0.0" + peerDependencies: + react: ">=16.8.0" + checksum: b296fedba916ca721eeb7117f29a13c252966d03411abccc5e5894ed4de0f32b9cb6f6b150555b8b4cb9b0acf53b84022ad4cd43b89253389e9cd13779eebca7 + languageName: node + linkType: hard + "use-isomorphic-layout-effect@npm:^1.1.2": version: 1.1.2 resolution: "use-isomorphic-layout-effect@npm:1.1.2"