mirror of
https://github.com/IgnatZakalinsky/home-works.git
synced 2025-12-16 20:39:24 +00:00
add hw 14-15 for design
This commit is contained in:
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
3
src/s2-homeworks/hw14/HW14.module.css
Normal file
3
src/s2-homeworks/hw14/HW14.module.css
Normal file
@@ -0,0 +1,3 @@
|
||||
.tech {
|
||||
|
||||
}
|
||||
84
src/s2-homeworks/hw14/HW14.tsx
Normal file
84
src/s2-homeworks/hw14/HW14.tsx
Normal 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
|
||||
@@ -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
|
||||
3
src/s2-homeworks/hw15/HW15.module.css
Normal file
3
src/s2-homeworks/hw15/HW15.module.css
Normal file
@@ -0,0 +1,3 @@
|
||||
.tech {
|
||||
|
||||
}
|
||||
141
src/s2-homeworks/hw15/HW15.tsx
Normal file
141
src/s2-homeworks/hw15/HW15.tsx
Normal 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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user