mirror of
https://github.com/IgnatZakalinsky/home-works.git
synced 2025-12-16 20:39:24 +00:00
add hw3
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,7 @@
|
|||||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
|
/.idea
|
||||||
/node_modules
|
/node_modules
|
||||||
/.pnp
|
/.pnp
|
||||||
.pnp.js
|
.pnp.js
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
.env.development.local
|
.env.development.local
|
||||||
.env.test.local
|
.env.test.local
|
||||||
.env.production.local
|
.env.production.local
|
||||||
|
.env
|
||||||
|
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
|
|||||||
@@ -11,11 +11,13 @@
|
|||||||
"@types/node": "^16.7.13",
|
"@types/node": "^16.7.13",
|
||||||
"@types/react": "^18.0.0",
|
"@types/react": "^18.0.0",
|
||||||
"@types/react-dom": "^18.0.0",
|
"@types/react-dom": "^18.0.0",
|
||||||
|
"@types/uuid": "^8.3.4",
|
||||||
"gh-pages": "^4.0.0",
|
"gh-pages": "^4.0.0",
|
||||||
"react": "^18.1.0",
|
"react": "^18.1.0",
|
||||||
"react-dom": "^18.1.0",
|
"react-dom": "^18.1.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"typescript": "^4.4.2",
|
"typescript": "^4.4.2",
|
||||||
|
"uuid": "^8.3.2",
|
||||||
"web-vitals": "^2.1.0"
|
"web-vitals": "^2.1.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return (
|
return (
|
||||||
@@ -9,7 +10,7 @@ const App = () => {
|
|||||||
<div>react homeworks:</div>
|
<div>react homeworks:</div>
|
||||||
<HW1/>
|
<HW1/>
|
||||||
<HW2/>
|
<HW2/>
|
||||||
{/*<HW3/>*/}
|
<HW3/>
|
||||||
{/*<HW4/>*/}
|
{/*<HW4/>*/}
|
||||||
{/*<HW5/>*/}
|
{/*<HW5/>*/}
|
||||||
|
|
||||||
|
|||||||
61
src/s2-homeworks/hw03/Greeting.module.css
Normal file
61
src/s2-homeworks/hw03/Greeting.module.css
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
.greetingForm {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
position: absolute;
|
||||||
|
color: red;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-top: -14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
margin: 10px;
|
||||||
|
|
||||||
|
background: #003300;
|
||||||
|
color: #99ff99;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input:focus {
|
||||||
|
outline: none;
|
||||||
|
border: #99ff99 solid 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.errorInput {
|
||||||
|
margin: 10px;
|
||||||
|
|
||||||
|
background: #003300;
|
||||||
|
color: #99ff99;
|
||||||
|
|
||||||
|
border: 2px solid red;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
margin: 10px;
|
||||||
|
width: 60px;
|
||||||
|
|
||||||
|
background: #003300;
|
||||||
|
color: #99ff99;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.button:focus {
|
||||||
|
outline: #99ff99 solid 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:active {
|
||||||
|
background: #99ff99;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:disabled {
|
||||||
|
color: #005500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.count {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.greeting {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
47
src/s2-homeworks/hw03/Greeting.tsx
Normal file
47
src/s2-homeworks/hw03/Greeting.tsx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import React, {ChangeEvent, KeyboardEvent} from 'react'
|
||||||
|
import s from './Greeting.module.css'
|
||||||
|
|
||||||
|
type GreetingPropsType = {
|
||||||
|
name: string // need to fix any
|
||||||
|
setNameCallback: (e: ChangeEvent<HTMLInputElement>) => void // need to fix any
|
||||||
|
addUser: () => void // need to fix any
|
||||||
|
onEnter: (e: KeyboardEvent<HTMLInputElement>) => void
|
||||||
|
error: string // need to fix any
|
||||||
|
totalUsers: number // need to fix any
|
||||||
|
lastUser?: string // need to fix any
|
||||||
|
}
|
||||||
|
|
||||||
|
// презентационная компонента (для верстальщика)
|
||||||
|
const Greeting: React.FC<GreetingPropsType> = (
|
||||||
|
{name, setNameCallback, addUser, onEnter, error, totalUsers, lastUser} // деструктуризация пропсов
|
||||||
|
) => {
|
||||||
|
const inputClass = error ? s.errorInput : s.input // need to fix with (?:)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div id={'hw3-form'} className={s.greetingForm}>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
id={'hw3-input'}
|
||||||
|
value={name}
|
||||||
|
onChange={setNameCallback}
|
||||||
|
className={inputClass}
|
||||||
|
onKeyDown={onEnter}
|
||||||
|
onBlur={setNameCallback}
|
||||||
|
/>
|
||||||
|
<div id={'hw3-error'} className={s.error}>{error}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button id={'hw3-button'} onClick={addUser} className={s.button} disabled={!name}>add</button>
|
||||||
|
<div id={'hw3-users-total'} className={s.count}>{totalUsers}</div>
|
||||||
|
{lastUser && (
|
||||||
|
<div className={s.greeting}>
|
||||||
|
hello{' '}
|
||||||
|
<span id={'hw3-last-user'}>{lastUser}</span>
|
||||||
|
!
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Greeting
|
||||||
59
src/s2-homeworks/hw03/GreetingContainer.tsx
Normal file
59
src/s2-homeworks/hw03/GreetingContainer.tsx
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import React, {ChangeEvent, KeyboardEvent, useState} from 'react'
|
||||||
|
import Greeting from './Greeting'
|
||||||
|
import {UserType} from './HW3'
|
||||||
|
|
||||||
|
type GreetingContainerPropsType = {
|
||||||
|
users: UserType[] // need to fix any
|
||||||
|
addUserCallback: (name: string) => void // need to fix any
|
||||||
|
}
|
||||||
|
|
||||||
|
// более простой и понятный для новичков
|
||||||
|
// function GreetingContainer(props: GreetingPropsType) {
|
||||||
|
|
||||||
|
// более современный и удобный для про :)
|
||||||
|
const GreetingContainer: React.FC<GreetingContainerPropsType> = ({users, addUserCallback}) => { // деструктуризация пропсов
|
||||||
|
const [name, setName] = useState<string>('') // need to fix any
|
||||||
|
const [error, setError] = useState<string>('') // need to fix any
|
||||||
|
|
||||||
|
const setNameCallback = (e: ChangeEvent<HTMLInputElement>) => { // need to fix any // нельзя пробелы перед и после имени, можно в середине
|
||||||
|
const trimmedName = e.currentTarget.value.trim()
|
||||||
|
|
||||||
|
if (trimmedName) {
|
||||||
|
setName(trimmedName) // need to fix
|
||||||
|
setError('')
|
||||||
|
} else {
|
||||||
|
setName('')
|
||||||
|
setError('name is require!')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const addUser = () => {
|
||||||
|
addUserCallback(name)
|
||||||
|
setName('')
|
||||||
|
}
|
||||||
|
|
||||||
|
const onEnter = (e: KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
if (name) {
|
||||||
|
addUser()
|
||||||
|
} else {
|
||||||
|
setError('name is require!')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalUsers = users.length // need to fix
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Greeting
|
||||||
|
name={name}
|
||||||
|
setNameCallback={setNameCallback}
|
||||||
|
addUser={addUser}
|
||||||
|
onEnter={onEnter}
|
||||||
|
error={error}
|
||||||
|
totalUsers={totalUsers}
|
||||||
|
lastUser={users[users.length - 1]?.name}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GreetingContainer
|
||||||
39
src/s2-homeworks/hw03/HW3.tsx
Normal file
39
src/s2-homeworks/hw03/HW3.tsx
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import React, {useState} from 'react'
|
||||||
|
import {v1} from 'uuid'
|
||||||
|
import s from './Greeting.module.css'
|
||||||
|
import GreetingContainer from './GreetingContainer'
|
||||||
|
|
||||||
|
// types
|
||||||
|
export type UserType = {
|
||||||
|
_id: string// need to fix any
|
||||||
|
name: string // need to fix any
|
||||||
|
}
|
||||||
|
|
||||||
|
const HW1 = () => {
|
||||||
|
const [users, setUsers] = useState<UserType[]>([]) // need to fix any
|
||||||
|
|
||||||
|
const addUserCallback = (name: string) => { // need to fix any
|
||||||
|
const user = {
|
||||||
|
_id: v1(),
|
||||||
|
name,
|
||||||
|
}
|
||||||
|
setUsers([...users, user]) // need to fix
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div id={'hw3'} className={s.hw3}>
|
||||||
|
<hr/>
|
||||||
|
{/*можно убрать этот тег*/}
|
||||||
|
|
||||||
|
{/*для автоматической проверки дз (не менять)*/}
|
||||||
|
<GreetingContainer users={users} addUserCallback={addUserCallback}/>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
{/*можно убрать этот тег*/}
|
||||||
|
<hr/>
|
||||||
|
{/*можно убрать этот тег*/}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HW1
|
||||||
@@ -2022,6 +2022,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756"
|
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756"
|
||||||
integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==
|
integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==
|
||||||
|
|
||||||
|
"@types/uuid@^8.3.4":
|
||||||
|
version "8.3.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc"
|
||||||
|
integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==
|
||||||
|
|
||||||
"@types/ws@^8.5.1":
|
"@types/ws@^8.5.1":
|
||||||
version "8.5.3"
|
version "8.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d"
|
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d"
|
||||||
|
|||||||
Reference in New Issue
Block a user