mirror of
https://github.com/IgnatZakalinsky/home-works.git
synced 2025-12-24 12:31:27 +00:00
final ref hw3
This commit is contained in:
@@ -2,6 +2,7 @@ import React from 'react'
|
|||||||
import s from './App.module.css'
|
import s from './App.module.css'
|
||||||
import HW1 from '../s2-homeworks/hw01/HW1'
|
import HW1 from '../s2-homeworks/hw01/HW1'
|
||||||
import HW2 from '../s2-homeworks/hw02/HW2'
|
import HW2 from '../s2-homeworks/hw02/HW2'
|
||||||
|
import HW3 from '../s2-homeworks/hw03/HW3'
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
// для дз 12
|
// для дз 12
|
||||||
@@ -17,7 +18,7 @@ function App() {
|
|||||||
>
|
>
|
||||||
<HW1/>
|
<HW1/>
|
||||||
<HW2/>
|
<HW2/>
|
||||||
{/*<HW3/>*/}
|
<HW3/>
|
||||||
{/*<HW4/>*/}
|
{/*<HW4/>*/}
|
||||||
|
|
||||||
{/*<HW5/>*/}
|
{/*<HW5/>*/}
|
||||||
|
|||||||
@@ -10,7 +10,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
|
position: absolute;
|
||||||
margin-top: 7px;
|
margin-top: 7px;
|
||||||
|
|
||||||
color: #cc0000;
|
color: #cc0000;
|
||||||
font-family: 'Montserrat', sans-serif;
|
font-family: 'Montserrat', sans-serif;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
@@ -19,21 +21,23 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.input {
|
.input {
|
||||||
|
width: 370px;
|
||||||
|
padding: 8px 0 8px 12px;
|
||||||
|
|
||||||
border: 1px solid #d1d1d1;
|
border: 1px solid #d1d1d1;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
width: 370px;
|
|
||||||
|
color: #000;
|
||||||
font-family: 'Montserrat', sans-serif;
|
font-family: 'Montserrat', sans-serif;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
padding: 8px 0 8px 12px;
|
|
||||||
color: #000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.input:focus {
|
.input:focus {
|
||||||
outline: none;
|
|
||||||
border: 1px solid #06c;
|
border: 1px solid #06c;
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.errorInput {
|
.errorInput {
|
||||||
@@ -41,19 +45,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
|
height: 36px;
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
|
padding: 8px 24px;
|
||||||
|
|
||||||
background: #06c;
|
background: #06c;
|
||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
outline: none;
|
outline: none;
|
||||||
padding: 8px 24px;
|
|
||||||
font-family: 'Montserrat', sans-serif;
|
font-family: 'Montserrat', sans-serif;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
height: 36px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.button:focus {
|
.button:focus {
|
||||||
@@ -67,12 +73,14 @@
|
|||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
.count {
|
.text {
|
||||||
|
margin-bottom: 9px;
|
||||||
|
|
||||||
|
opacity: .5;
|
||||||
font-family: 'Montserrat', sans-serif;
|
font-family: 'Montserrat', sans-serif;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 17px;
|
line-height: 17px;
|
||||||
margin-bottom: 9px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.greeting {
|
.greeting {
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import React, { ChangeEvent, KeyboardEvent } from 'react'
|
import React, {ChangeEvent, KeyboardEvent} from 'react'
|
||||||
import s from './Greeting.module.css'
|
import s from './Greeting.module.css'
|
||||||
|
|
||||||
type GreetingPropsType = {
|
type GreetingPropsType = {
|
||||||
name: string // need to fix any
|
name: any // need to fix any
|
||||||
setNameCallback: (e: ChangeEvent<HTMLInputElement>) => void // need to fix any
|
setNameCallback: any // need to fix any
|
||||||
addUser: () => void // need to fix any
|
addUser: any // need to fix any
|
||||||
onBlur: () => void // need to fix any
|
onBlur: any // need to fix any
|
||||||
onEnter: (e: KeyboardEvent<HTMLInputElement>) => void
|
onEnter: any // need to fix any
|
||||||
error: string // need to fix any
|
error: any // need to fix any
|
||||||
totalUsers: number // need to fix any
|
totalUsers: any // need to fix any
|
||||||
lastUser?: string // need to fix any
|
lastUserName?: any // need to fix any
|
||||||
}
|
}
|
||||||
|
|
||||||
// презентационная компонента (для верстальщика)
|
// презентационная компонента (для верстальщика)
|
||||||
@@ -19,19 +19,23 @@ const Greeting: React.FC<GreetingPropsType> = (
|
|||||||
setNameCallback,
|
setNameCallback,
|
||||||
addUser,
|
addUser,
|
||||||
onEnter,
|
onEnter,
|
||||||
|
onBlur,
|
||||||
error,
|
error,
|
||||||
totalUsers,
|
totalUsers,
|
||||||
lastUser,
|
lastUserName,
|
||||||
onBlur,
|
|
||||||
} // деструктуризация пропсов
|
} // деструктуризация пропсов
|
||||||
) => {
|
) => {
|
||||||
const inputClass = error ? `${s.input} ${s.errorInput}` : s.input // need to fix with (?:)
|
const inputClass = error ? `${s.input} ${s.errorInput}` : s.input // need to fix with (?:)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id={'hw3-form'} className={s.greetingForm}>
|
<div id={'hw3-form'} className={s.greetingForm}>
|
||||||
<div id={'hw3-users-total'} className={s.count}>
|
<div className={s.text}>
|
||||||
|
{'Людей добавили: '}
|
||||||
|
<span id={'hw3-users-total'}>
|
||||||
{totalUsers}
|
{totalUsers}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={s.inputAndButtonContainer}>
|
<div className={s.inputAndButtonContainer}>
|
||||||
<div>
|
<div>
|
||||||
<input
|
<input
|
||||||
@@ -51,15 +55,15 @@ const Greeting: React.FC<GreetingPropsType> = (
|
|||||||
id={'hw3-button'}
|
id={'hw3-button'}
|
||||||
onClick={addUser}
|
onClick={addUser}
|
||||||
className={s.button}
|
className={s.button}
|
||||||
disabled={!name}
|
disabled={!name.trim()}
|
||||||
>
|
>
|
||||||
add
|
add
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{lastUser && (
|
{lastUserName && (
|
||||||
<div className={s.greeting}>
|
<div className={s.greeting}>
|
||||||
hello <span id={'hw3-last-user'}>{lastUser}</span>!
|
hello <span id={'hw3-last-user'}>{lastUserName}</span>!
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,8 +3,30 @@ import Greeting from './Greeting'
|
|||||||
import { UserType } from './HW3'
|
import { UserType } from './HW3'
|
||||||
|
|
||||||
type GreetingContainerPropsType = {
|
type GreetingContainerPropsType = {
|
||||||
users: UserType[] // need to fix any
|
users: any // need to fix any
|
||||||
addUserCallback: (name: string) => void // need to fix any
|
addUserCallback: any // need to fix any
|
||||||
|
}
|
||||||
|
|
||||||
|
export const pureAddUser = (name: any, setError: any, setName: any, addUserCallback: any) => {
|
||||||
|
// если имя пустое - показать ошибку, иначе - добавить юзера и очистить инпут
|
||||||
|
if (!name.trim()) {
|
||||||
|
setError('name is required!')
|
||||||
|
} else {
|
||||||
|
addUserCallback(name)
|
||||||
|
setName('')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const pureOnBlur = (name: any, setError: any) => { // если имя пустое - показать ошибку
|
||||||
|
if (!name.trim()) {
|
||||||
|
setError('name is required!')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const pureOnEnter = (e: any, addUser: any) => { // если нажата кнопка Enter - добавить
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
addUser()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// более простой и понятный для новичков
|
// более простой и понятный для новичков
|
||||||
@@ -16,54 +38,39 @@ const GreetingContainer: React.FC<GreetingContainerPropsType> = ({
|
|||||||
addUserCallback,
|
addUserCallback,
|
||||||
}) => {
|
}) => {
|
||||||
// деструктуризация пропсов
|
// деструктуризация пропсов
|
||||||
const [name, setName] = useState<string>('') // need to fix any
|
const [name, setName] = useState<any>('') // need to fix any
|
||||||
const [error, setError] = useState<string>('') // need to fix any
|
const [error, setError] = useState<any>('') // need to fix any
|
||||||
|
|
||||||
const setNameCallback = (e: ChangeEvent<HTMLInputElement>) => {
|
const setNameCallback = (e: any) => { // need to fix any
|
||||||
// need to fix any // нельзя пробелы перед и после имени, можно в середине
|
|
||||||
setName(e.currentTarget.value) // need to fix
|
setName(e.currentTarget.value) // need to fix
|
||||||
|
|
||||||
error && setError('')
|
error && setError('')
|
||||||
}
|
}
|
||||||
const addUser = () => {
|
const addUser = () => {
|
||||||
addUserCallback(name)
|
pureAddUser(name, setError, setName, addUserCallback)
|
||||||
setName('')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const onBlur = () => {
|
const onBlur = () => {
|
||||||
const trimmedName = name.trim()
|
pureOnBlur(name, setError)
|
||||||
|
|
||||||
if (!trimmedName) {
|
|
||||||
setError('name is required!')
|
|
||||||
}
|
|
||||||
setName(trimmedName) // need to fix
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const onEnter = (e: KeyboardEvent<HTMLInputElement>) => {
|
const onEnter = (e: any) => {
|
||||||
if (e.key === 'Enter') {
|
pureOnEnter(e, addUser)
|
||||||
const trimmedName = name.trim()
|
|
||||||
|
|
||||||
if (!trimmedName) {
|
|
||||||
setName('')
|
|
||||||
setError('name is required!')
|
|
||||||
} else {
|
|
||||||
addUserCallback(trimmedName)
|
|
||||||
setName('')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const totalUsers = users.length // need to fix
|
const totalUsers = users.length // need to fix
|
||||||
|
const lastUserName = users[users.length - 1]?.name // need to fix
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Greeting
|
<Greeting
|
||||||
onBlur={onBlur}
|
|
||||||
name={name}
|
name={name}
|
||||||
setNameCallback={setNameCallback}
|
setNameCallback={setNameCallback}
|
||||||
addUser={addUser}
|
addUser={addUser}
|
||||||
|
onBlur={onBlur}
|
||||||
onEnter={onEnter}
|
onEnter={onEnter}
|
||||||
error={error}
|
error={error}
|
||||||
totalUsers={totalUsers}
|
totalUsers={totalUsers}
|
||||||
lastUser={users[users.length - 1]?.name}
|
lastUserName={lastUserName}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,41 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { v1 } from 'uuid'
|
import { v1 } from 'uuid'
|
||||||
import s from './Greeting.module.css'
|
|
||||||
import s2 from '../../s1-main/App.module.css'
|
import s2 from '../../s1-main/App.module.css'
|
||||||
import GreetingContainer from './GreetingContainer'
|
import GreetingContainer from './GreetingContainer'
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 1 - описать тип UserType
|
||||||
|
* 2 - указать нужный тип в useState с users
|
||||||
|
* 3 - дописать типы и логику функции pureAddUserCallback и проверить её тестами
|
||||||
|
* 4 - в файле GreetingContainer.tsx дописать типизацию пропсов
|
||||||
|
* 5 - в файле GreetingContainer.tsx указать нужные типы в useState с name и error
|
||||||
|
* 6 - в файле GreetingContainer.tsx дописать тип и логику функции setNameCallback
|
||||||
|
* 7 - в файле GreetingContainer.tsx дописать логику функций pureAddUser, pureOnBlur, pureOnEnter и проверить их тестами
|
||||||
|
* 8 - в файле GreetingContainer.tsx вычислить количество добавленных и имя последнего (totalUsers, lastUserName)
|
||||||
|
* 9 - в файле Greeting.tsx дописать типизацию пропсов
|
||||||
|
* 10 - в файле Greeting.tsx вычислить inputClass в зависимости от наличия ошибки
|
||||||
|
* 11 - сделать стили в соответствии с дизайном
|
||||||
|
* */
|
||||||
|
|
||||||
// types
|
// types
|
||||||
export type UserType = {
|
export type UserType = {
|
||||||
_id: string // need to fix any
|
_id: any // need to fix any
|
||||||
name: string // need to fix any
|
name: any // need to fix any
|
||||||
}
|
}
|
||||||
|
|
||||||
const HW3 = () => {
|
export const pureAddUserCallback = (name: any, setUsers: any, users: any) => { // need to fix any
|
||||||
const [users, setUsers] = useState<UserType[]>([]) // need to fix any
|
const user = { // need to fix
|
||||||
|
|
||||||
const addUserCallback = (name: string) => {
|
|
||||||
// need to fix any
|
|
||||||
const user = {
|
|
||||||
_id: v1(),
|
_id: v1(),
|
||||||
name,
|
name,
|
||||||
}
|
}
|
||||||
setUsers([...users, user]) // need to fix
|
setUsers([...users, user])
|
||||||
|
}
|
||||||
|
|
||||||
|
const HW3 = () => {
|
||||||
|
const [users, setUsers] = useState<any>([]) // need to fix any
|
||||||
|
|
||||||
|
const addUserCallback = (name: any) => { // need to fix any
|
||||||
|
pureAddUserCallback(name, setUsers, users)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
43
src/s2-homeworks/hw03/tests/pureAddUser.test.tsx
Normal file
43
src/s2-homeworks/hw03/tests/pureAddUser.test.tsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {pureAddUser} from '../GreetingContainer'
|
||||||
|
|
||||||
|
let name: any
|
||||||
|
const setName = (a: any) => {
|
||||||
|
name = a
|
||||||
|
}
|
||||||
|
let error: any
|
||||||
|
const setError = (a: any) => {
|
||||||
|
error = a
|
||||||
|
}
|
||||||
|
let added: any
|
||||||
|
const addUserCallback = () => {
|
||||||
|
added = true
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
name = ''
|
||||||
|
error = ''
|
||||||
|
added = false
|
||||||
|
})
|
||||||
|
|
||||||
|
test('name 1', () => {
|
||||||
|
name = '1'
|
||||||
|
pureAddUser(name, setError, setName, addUserCallback)
|
||||||
|
expect(name).toBe('')
|
||||||
|
expect(error).toBe('')
|
||||||
|
expect(added).toBe(true)
|
||||||
|
})
|
||||||
|
test('name 2', () => {
|
||||||
|
name = ''
|
||||||
|
pureAddUser(name, setError, setName, addUserCallback)
|
||||||
|
expect(name).toBe('')
|
||||||
|
expect(error).toBe('name is required!')
|
||||||
|
expect(added).toBe(false)
|
||||||
|
})
|
||||||
|
test('name 3', () => {
|
||||||
|
name = ' '
|
||||||
|
pureAddUser(name, setError, setName, addUserCallback)
|
||||||
|
expect(name).toBe(' ')
|
||||||
|
expect(error).toBe('name is required!')
|
||||||
|
expect(added).toBe(false)
|
||||||
|
})
|
||||||
18
src/s2-homeworks/hw03/tests/pureAddUserCallback.test.tsx
Normal file
18
src/s2-homeworks/hw03/tests/pureAddUserCallback.test.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {pureAddUserCallback} from '../HW3'
|
||||||
|
|
||||||
|
let initialState: any[]
|
||||||
|
const setName = (a: any[]) => {
|
||||||
|
initialState = a
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
initialState = []
|
||||||
|
})
|
||||||
|
|
||||||
|
test('name 1', () => {
|
||||||
|
pureAddUserCallback('name', setName, initialState)
|
||||||
|
expect(initialState.length).toBe(1)
|
||||||
|
expect(initialState[0].name).toBe('name')
|
||||||
|
expect(!!initialState[0]._id).toBe(true)
|
||||||
|
})
|
||||||
29
src/s2-homeworks/hw03/tests/pureOnBlur.test.tsx
Normal file
29
src/s2-homeworks/hw03/tests/pureOnBlur.test.tsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {pureOnBlur} from '../GreetingContainer'
|
||||||
|
|
||||||
|
let name: any
|
||||||
|
let error: any
|
||||||
|
const setError = (a: any) => {
|
||||||
|
error = a
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
name = ''
|
||||||
|
error = ''
|
||||||
|
})
|
||||||
|
|
||||||
|
test('name 1', () => {
|
||||||
|
name = '1'
|
||||||
|
pureOnBlur(name, setError)
|
||||||
|
expect(error).toBe('')
|
||||||
|
})
|
||||||
|
test('name 2', () => {
|
||||||
|
name = ''
|
||||||
|
pureOnBlur(name, setError)
|
||||||
|
expect(error).toBe('name is required!')
|
||||||
|
})
|
||||||
|
test('name 3', () => {
|
||||||
|
name = ' '
|
||||||
|
pureOnBlur(name, setError)
|
||||||
|
expect(error).toBe('name is required!')
|
||||||
|
})
|
||||||
20
src/s2-homeworks/hw03/tests/pureOnEnter.test.tsx
Normal file
20
src/s2-homeworks/hw03/tests/pureOnEnter.test.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {pureOnEnter} from '../GreetingContainer'
|
||||||
|
|
||||||
|
let added: any
|
||||||
|
const addUser = () => {
|
||||||
|
added = true
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
added = false
|
||||||
|
})
|
||||||
|
|
||||||
|
test('name 1', () => {
|
||||||
|
pureOnEnter({key: 'Enter'} as any, addUser)
|
||||||
|
expect(added).toBe(true)
|
||||||
|
})
|
||||||
|
test('name 2', () => {
|
||||||
|
pureOnEnter({key: ''} as any, addUser)
|
||||||
|
expect(added).toBe(false)
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user