add hw 14-15 for design

This commit is contained in:
neko
2022-11-08 14:01:28 +03:00
parent b25f4b4f5b
commit 7a91352d47
7 changed files with 362 additions and 0 deletions

View File

@@ -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() {
<HW11 />
<HW12 />
<HW13 />
<HW14 />
<HW15 />
</div>
)
}

View File

@@ -0,0 +1,3 @@
.tech {
}

View File

@@ -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<string[]>([])
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 => (
<div key={t} id={'hw14-tech-' + t} className={s.tech}>
{t}
</div>
))
return (
<div id={'hw14'}>
<div className={s2.hwTitle}>Homework #14</div>
<div className={s2.hw}>
<SuperDebouncedInput
id={'hw14-super-debounced-input'}
value={find}
onChangeText={onChangeText}
onDebouncedChange={sendQuery}
/>
{mappedTechs}
</div>
</div>
)
}
export default HW14

View File

@@ -0,0 +1,53 @@
import React, {DetailedHTMLProps, InputHTMLAttributes, ReactNode, useState} from 'react'
import SuperInputText from '../../../hw04/common/c1-SuperInputText/SuperInputText'
// тип пропсов обычного инпута
type DefaultInputPropsType = DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>,
HTMLInputElement>
// здесь мы говорим что у нашего инпута будут такие же пропсы как у обычного инпута, кроме type
// (чтоб не писать value: string, onChange: ...; они уже все описаны в DefaultInputPropsType)
export type SuperDebouncedInputPropsType = Omit<DefaultInputPropsType, 'type'> & {
// и + ещё пропсы которых нет в стандартном инпуте
onChangeText?: (value: string) => void
onEnter?: () => void
error?: ReactNode
spanClassName?: string
} // илм экспортировать тип SuperInputTextPropsType
& { // плюс специальный пропс SuperPagination
onDebouncedChange?: (value: string) => void
}
const SuperDebouncedInput: React.FC<SuperDebouncedInputPropsType> = (
{
onChangeText,
onDebouncedChange,
...restProps // все остальные пропсы попадут в объект restProps
}
) => {
const [timerId, setTimerId] = useState<number | undefined>(undefined)
const onChangeTextCallback = (value: string) => {
onChangeText?.(value)
if (onDebouncedChange) {
// делает студент
timerId && clearTimeout(timerId)
const id = +setTimeout(() => {
onDebouncedChange(value)
setTimerId(undefined)
}, 1500)
setTimerId(id)
//
}
}
return (
<SuperInputText onChangeText={onChangeTextCallback} {...restProps}/>
)
}
export default SuperDebouncedInput

View File

@@ -0,0 +1,3 @@
.tech {
}

View File

@@ -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<TechType[]>([])
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 => (
<div key={t.id} className={s.tech}>
<span id={'hw15-tech-' + t.id}>
{t.tech}
</span>
-----
<span id={'hw15-developer-' + t.id}>
{t.developer}
</span>
</div>
))
return (
<div id={'hw15'}>
<div className={s2.hwTitle}>Homework #15</div>
<div className={s2.hw}>
<SuperPagination
page={page}
count={count}
totalCount={totalCount}
onChange={onChange}
/>
таблица:
<div>
tech
<SuperButton // позже СуперСорт
onClick={() => setSort(sort === '1tech'
? '0tech'
: sort == '0tech'
? ''
: '1tech')}
>
{sort === '1tech'
? '\\/'
: sort === '0tech'
? '/\\'
: '-'}
</SuperButton>
developer
<SuperButton
onClick={() => setSort(sort === '1developer'
? '0developer'
: sort === '0developer'
? ''
: '1developer')}
>
{sort === '1developer'
? '\\/'
: sort === '0developer'
? '/\\'
: '-'}
</SuperButton>
</div>
{mappedTechs}
</div>
</div>
)
}
export default HW15

View File

@@ -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<SuperPaginationPropsType> = (
{
page, count, totalCount, onChange, id = 'hw15',
}
) => {
let pages = []
const lastPage = Math.ceil(totalCount / count)
for (let i = 1; i <= lastPage; i++) pages.push((
<SuperButton
key={id + '-page-' + i}
id={id + '-page-' + i}
onClick={() => onChange(i, count)}
xType={i === page ? undefined : 'secondary'}
>
{i}
</SuperButton>
))
// 1 ... 4 5 (6) 7 8 ... 11 // выбрана страница 6
// 1 2 3 4 (5) 6 7 ... 11 // выбрана страница 5
// делает студент
if ((page + 4) < lastPage) {
pages[page + 2] = (
<span key={id + '-span-' + (page + 3)} id={id + '-span-' + (page + 3)}>
{' ... '}
</span>
)
pages = pages.filter((p, i) => i < (page + 3) || i === (lastPage - 1))
}
if (page > 5) {
pages[1] = (
<span key={id + '-span-' + 2} id={id + '-span-' + 2}>
{' ... '}
</span>
)
pages = pages.filter((p, i) => i < 2 || i > page - 4)
}
//
return (
<div>
<SuperSelect
value={count}
options={[
{id: 4, value: 4},
{id: 7, value: 7},
{id: 10, value: 10},
]}
onChange={e => onChange(page, Number(e.currentTarget.value))}
/>
{pages}
</div>
)
}
export default SuperPagination