diff --git a/src/s2-homeworks/hw05/pages/JuniorPlus.tsx b/src/s2-homeworks/hw05/pages/JuniorPlus.tsx index 3a8979d..6e7fb9d 100644 --- a/src/s2-homeworks/hw05/pages/JuniorPlus.tsx +++ b/src/s2-homeworks/hw05/pages/JuniorPlus.tsx @@ -3,6 +3,8 @@ import HW10 from '../../hw10/HW10' import HW11 from '../../hw11/HW11' import HW12 from '../../hw12/HW12' import HW13 from '../../hw13/HW13' +import HW14 from '../../hw14/HW14' +import HW15 from '../../hw15/HW15' function JuniorPlus() { return ( @@ -11,6 +13,8 @@ function JuniorPlus() { + + ) } diff --git a/src/s2-homeworks/hw14/HW14.module.css b/src/s2-homeworks/hw14/HW14.module.css new file mode 100644 index 0000000..164d37b --- /dev/null +++ b/src/s2-homeworks/hw14/HW14.module.css @@ -0,0 +1,3 @@ +.tech { + +} \ No newline at end of file diff --git a/src/s2-homeworks/hw14/HW14.tsx b/src/s2-homeworks/hw14/HW14.tsx new file mode 100644 index 0000000..9387a19 --- /dev/null +++ b/src/s2-homeworks/hw14/HW14.tsx @@ -0,0 +1,84 @@ +import React, {useEffect, useState} from 'react' +import s2 from '../../s1-main/App.module.css' +import s from './HW14.module.css' +import axios from 'axios' +import SuperDebouncedInput from './common/c8-SuperDebouncedInput/SuperDebouncedInput' +import {useSearchParams} from 'react-router-dom' + +/* +* 1 - дописать функцию onChangeTextCallback в SuperPagination +* 2 - дописать функцию sendQuery в HW14 +* 3 - дописать функцию onChangeText в HW14 +* 4 - сделать стили в соответствии с дизайном +* 5 - добавить HW14 в HW5/pages/JuniorPlus +* */ + +const getTechs = (find: string) => { + return axios + .get<{techs: string[]}>( + 'https://incubator-personal-page-back.herokuapp.com/api/3.0/homework/test2', + {params: {find}} + ) + .catch((e) => { + alert(e.response?.data?.errorText || e.message) + }) +} + +const HW14 = () => { + const [find, setFind] = useState('') + const [searchParams, setSearchParams] = useSearchParams() + const [techs, setTechs] = useState([]) + + const sendQuery = (value: string) => { + getTechs(value) + .then((res) => { + // делает студент + + if (res) setTechs(res.data.techs) + + // + }) + } + + const onChangeText = (value: string) => { + setFind(value) + // делает студент + + const findQuery: {find?: string} = value ? {find: value} : {} // если нет - то не записывать в урл + const {find, ...lastQueries} = Object.fromEntries(searchParams) + + setSearchParams({...lastQueries, ...findQuery}) + + // + } + + useEffect(() => { + const params = Object.fromEntries(searchParams) + sendQuery(params.find || '') + setFind(params.find || '') + }, []) + + const mappedTechs = techs.map(t => ( +
+ {t} +
+ )) + + return ( +
+
Homework #14
+ +
+ + {mappedTechs} +
+
+ ) +} + +export default HW14 diff --git a/src/s2-homeworks/hw14/common/c8-SuperDebouncedInput/SuperDebouncedInput.tsx b/src/s2-homeworks/hw14/common/c8-SuperDebouncedInput/SuperDebouncedInput.tsx new file mode 100644 index 0000000..b214a88 --- /dev/null +++ b/src/s2-homeworks/hw14/common/c8-SuperDebouncedInput/SuperDebouncedInput.tsx @@ -0,0 +1,53 @@ +import React, {DetailedHTMLProps, InputHTMLAttributes, ReactNode, useState} from 'react' +import SuperInputText from '../../../hw04/common/c1-SuperInputText/SuperInputText' + +// тип пропсов обычного инпута +type DefaultInputPropsType = DetailedHTMLProps, + HTMLInputElement> + +// здесь мы говорим что у нашего инпута будут такие же пропсы как у обычного инпута, кроме type +// (чтоб не писать value: string, onChange: ...; они уже все описаны в DefaultInputPropsType) +export type SuperDebouncedInputPropsType = Omit & { + // и + ещё пропсы которых нет в стандартном инпуте + onChangeText?: (value: string) => void + onEnter?: () => void + error?: ReactNode + spanClassName?: string +} // илм экспортировать тип SuperInputTextPropsType + & { // плюс специальный пропс SuperPagination + onDebouncedChange?: (value: string) => void +} + +const SuperDebouncedInput: React.FC = ( + { + onChangeText, + onDebouncedChange, + + ...restProps // все остальные пропсы попадут в объект restProps + } +) => { + const [timerId, setTimerId] = useState(undefined) + + const onChangeTextCallback = (value: string) => { + onChangeText?.(value) + + if (onDebouncedChange) { + // делает студент + + timerId && clearTimeout(timerId) + const id = +setTimeout(() => { + onDebouncedChange(value) + setTimerId(undefined) + }, 1500) + setTimerId(id) + + // + } + } + + return ( + + ) +} + +export default SuperDebouncedInput diff --git a/src/s2-homeworks/hw15/HW15.module.css b/src/s2-homeworks/hw15/HW15.module.css new file mode 100644 index 0000000..164d37b --- /dev/null +++ b/src/s2-homeworks/hw15/HW15.module.css @@ -0,0 +1,3 @@ +.tech { + +} \ No newline at end of file diff --git a/src/s2-homeworks/hw15/HW15.tsx b/src/s2-homeworks/hw15/HW15.tsx new file mode 100644 index 0000000..7a1b66e --- /dev/null +++ b/src/s2-homeworks/hw15/HW15.tsx @@ -0,0 +1,141 @@ +import React, {useEffect, useState} from 'react' +import s2 from '../../s1-main/App.module.css' +import s from './HW15.module.css' +import axios from 'axios' +import SuperPagination from './common/c9-SuperPagination/SuperPagination' +import {useSearchParams} from 'react-router-dom' +import SuperButton from "../hw04/common/c2-SuperButton/SuperButton"; + +/* +* 1 - дописать SuperPagination +* 2 - дописать функцию send в HW15 +* 3 - дописать функцию onChangeText в HW15 +* 4 - сделать стили в соответствии с дизайном +* 5 - добавить HW15 в HW5/pages/JuniorPlus +* */ + +type TechType = { + id: number + tech: string + developer: string +} + +const getTechs = (params: any) => { + return axios + .get<{ techs: TechType[], totalCount: number }>( + 'https://incubator-personal-page-back.herokuapp.com/api/3.0/homework/test3', + {params} + ) + .catch((e) => { + alert(e.response?.data?.errorText || e.message) + }) +} + +const HW15 = () => { + const [sort, setSort] = useState('') + const [page, setPage] = useState(1) + const [count, setCount] = useState(4) + const [totalCount, setTotalCount] = useState(100) + const [searchParams, setSearchParams] = useSearchParams() + const [techs, setTechs] = useState([]) + + const sendQuery = (params: any) => { + getTechs(params) + .then((res) => { + // делает студент + + if (res) { + setTechs(res.data.techs) + setTotalCount(res.data.totalCount) + } + + // + }) + } + + const onChange = (newPage: number, newCount: number) => { + // делает студент + + setPage(newPage) + setCount(newCount) + const pageQuery: { page?: string } = newPage !== 1 ? {page: newPage + ''} : {} // если стандарт - то не записывать в урл + const countQuery: { count?: string } = newCount !== 4 ? {count: newCount + ''} : {} // если стандарт - то не записывать в урл + const {count, page, ...lastQueries} = Object.fromEntries(searchParams) + + sendQuery({page: newPage || '', count: newCount || ''}) + setSearchParams({...lastQueries, ...pageQuery, ...countQuery}) + + // + } + + useEffect(() => { + const params = Object.fromEntries(searchParams) + sendQuery({page: params.page, count: params.count}) + setPage(+params.page || 1) + setCount(+params.count || 4) + }, []) + + const mappedTechs = techs.map(t => ( +
+ + {t.tech} + + ----- + + {t.developer} + +
+ )) + + return ( +
+
Homework #15
+ +
+ + + таблица: + +
+ tech + setSort(sort === '1tech' + ? '0tech' + : sort == '0tech' + ? '' + : '1tech')} + > + {sort === '1tech' + ? '\\/' + : sort === '0tech' + ? '/\\' + : '-'} + + developer + setSort(sort === '1developer' + ? '0developer' + : sort === '0developer' + ? '' + : '1developer')} + > + {sort === '1developer' + ? '\\/' + : sort === '0developer' + ? '/\\' + : '-'} + +
+ + {mappedTechs} +
+
+ ) +} + +export default HW15 diff --git a/src/s2-homeworks/hw15/common/c9-SuperPagination/SuperPagination.tsx b/src/s2-homeworks/hw15/common/c9-SuperPagination/SuperPagination.tsx new file mode 100644 index 0000000..2c7da6a --- /dev/null +++ b/src/s2-homeworks/hw15/common/c9-SuperPagination/SuperPagination.tsx @@ -0,0 +1,74 @@ +import React from 'react' +import SuperButton from '../../../hw04/common/c2-SuperButton/SuperButton' +import SuperSelect from '../../../hw07/common/c5-SuperSelect/SuperSelect' + +export type SuperPaginationPropsType = { + id?: string + page: number + count: number + totalCount: number + onChange: (page: number, count: number) => void +} + +const SuperPagination: React.FC = ( + { + page, count, totalCount, onChange, id = 'hw15', + } +) => { + let pages = [] + const lastPage = Math.ceil(totalCount / count) + + for (let i = 1; i <= lastPage; i++) pages.push(( + onChange(i, count)} + xType={i === page ? undefined : 'secondary'} + + > + {i} + + )) + + // 1 ... 4 5 (6) 7 8 ... 11 // выбрана страница 6 + // 1 2 3 4 (5) 6 7 ... 11 // выбрана страница 5 + // делает студент + + if ((page + 4) < lastPage) { + pages[page + 2] = ( + + {' ... '} + + ) + pages = pages.filter((p, i) => i < (page + 3) || i === (lastPage - 1)) + } + if (page > 5) { + pages[1] = ( + + {' ... '} + + ) + pages = pages.filter((p, i) => i < 2 || i > page - 4) + } + + // + + return ( +
+ onChange(page, Number(e.currentTarget.value))} + + /> + + {pages} +
+ ) +} + +export default SuperPagination