|
@@ -2,63 +2,131 @@ import {useState} from 'react';
|
|
|
import logo from './logo.svg';
|
|
|
import './App.scss';
|
|
|
|
|
|
-const Spoiler = ({children, header, defaultState=false}) => { //придумайте, куда засунуть defaultState, что бы изначально спойлер мог быть открыт или закрыт
|
|
|
-
|
|
|
- const [isOpen, setIsOpen] = useState(false)
|
|
|
+const capitalize = (name) =>
|
|
|
+ name.length > 0 ?
|
|
|
+name[0].toUpperCase() + name.slice(1).toLowerCase() : ''
|
|
|
+
|
|
|
|
|
|
- const onChange = () => setIsOpen(!isOpen)
|
|
|
+const CapitalizedInput = ({...props}) => {
|
|
|
+ const [value, setValue] = useState('')
|
|
|
+
|
|
|
+ return (
|
|
|
+ <input type='text' onChange={e => setValue(capitalize(e.target.value))}
|
|
|
+ value={value} {...props}/>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+const Sum = () => {
|
|
|
+ const [a, setA] = useState(0)
|
|
|
+ const [b, setB] = useState(0)
|
|
|
|
|
|
return (
|
|
|
<>
|
|
|
- <div onClick={onChange}>{header}</div>
|
|
|
- {isOpen ? children : ''}
|
|
|
+ <input type='number' onChange={e => setA(+e.target.value)}
|
|
|
+ value={a} />
|
|
|
+ <input type='number' onChange={e => setB(+e.target.value)}
|
|
|
+ value={b} />
|
|
|
+ <h2>{a+b}</h2>
|
|
|
+ <h2>{a-b}</h2>
|
|
|
+ <h2>{a*b}</h2>
|
|
|
+ <h2>{a/b}</h2>
|
|
|
</>
|
|
|
)
|
|
|
}
|
|
|
|
|
|
-const PasswordInput = ({minlength=8}) => {
|
|
|
- const [password, setPassword] = useState('')
|
|
|
|
|
|
- const onChange = e => setPassword(e.target.value)
|
|
|
+let channelToHex = channel =>
|
|
|
+ channel > 15 ?
|
|
|
+channel.toString(16).toUpperCase() : '0' + channel.toString(16).toUpperCase()
|
|
|
+
|
|
|
+const ColorPicker = () => {
|
|
|
+ const [r, setR] = useState(0)
|
|
|
+ const [g, setG] = useState(0)
|
|
|
+ const [b, setB] = useState(0)
|
|
|
+
|
|
|
+
|
|
|
+ const style = {
|
|
|
+ backgroundColor: `rgb(${r}, ${g}, ${b})`,
|
|
|
+ color: `rgb(${255 - r}, ${255 - g}, ${255 - b})`,
|
|
|
+ color: `rgb(${(r + 128) % 256}, ${(g + 128) % 256}, ${(b + 128) % 256})`
|
|
|
+ }
|
|
|
+
|
|
|
+ const hexColor = `#${channelToHex(r)}${channelToHex(g)}${channelToHex(b)}`
|
|
|
+ console.log(r, g, b, hexColor)
|
|
|
|
|
|
- console.log('Текущий пароль:', password)
|
|
|
- const isPasswordLong = 'ТУТ УСЛОВИЕ. НЕ ЗАБУДЬТЕ использовать переменную minlength'
|
|
|
- const className = 'ТУТ ТЕРНАРКА, которая дает тот или иной класс'
|
|
|
|
|
|
return (
|
|
|
<>
|
|
|
+ <div style={style}>
|
|
|
+ <input type='number' onChange={e => setR(+e.target.value)}
|
|
|
+ value={r} min={0} max={255}/>
|
|
|
+ <input type='number' onChange={e => setG(+e.target.value)}
|
|
|
+ value={g} min={0} max={255}/>
|
|
|
+ <input type='number' onChange={e => setB(+e.target.value)}
|
|
|
+ value={b} min={0} max={255}/>
|
|
|
+ <span>{style.backgroundColor}</span>
|
|
|
+ <span>{hexColor}</span>
|
|
|
+ <span>{style.color}</span>
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+const ViewablePassword = ({}) => {
|
|
|
+ //добавьте нужные состояния, для того что бы прикрутить к паролю чекбокс,
|
|
|
+ //который дает "глаз" просмотра пароля. Что бы пароль был закрытый, поменяйте его
|
|
|
+ //тип с "text" на "password" и наоборот для открытия.
|
|
|
+ return (
|
|
|
+ <>
|
|
|
+ <input type="?????"/>
|
|
|
+ <input type="checkbox"/>
|
|
|
+ </>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+const PasswordConfirm = ({minLength=8}) => {
|
|
|
+ //пара инпутов для подтверждения пароля при регистрации/смене пароля.
|
|
|
+ //Для успеха они должны совпадать;
|
|
|
+ const [password, setPassword] = useState('')
|
|
|
+ const [passwordConfirm, setPasswordConfirm] = useState('')
|
|
|
+
|
|
|
+ const passwordOk = 'УСЛОВИЕ' //результатом должен быть false или true
|
|
|
+ //На месте условия напишите (поэтапно, насколько сможете):
|
|
|
+ // - для начала условие равенства или неравенства паролей
|
|
|
+ // - проверка что пароли не короче minLength
|
|
|
+ // - проверка на наличие цифр в пароле для большей безопасности
|
|
|
+ // - проверка на наличие букв разных размеров
|
|
|
+ // условия объединяются через `&&` (логическое И)
|
|
|
+ const className = passwordOk ? 'passwordOk' : 'passwordWrong'
|
|
|
+ //Предусмотрите разные классы в scss для визуализации.
|
|
|
+
|
|
|
+ return ( //прикрутите сюда кнопку 'сменить пароль', которая становится disabled если passwordOk "не ОК"
|
|
|
+ <>
|
|
|
+ <input type='password'
|
|
|
+ value={password}
|
|
|
+ onChange={e => setPassword(e.target.value)}
|
|
|
+ className={className}
|
|
|
+ />
|
|
|
<input type='password'
|
|
|
- value={password}
|
|
|
- className={className}
|
|
|
- onChange={onChange} />
|
|
|
+ value={passwordConfirm}
|
|
|
+ onChange={e => setPasswordConfirm(e.target.value)}
|
|
|
+ className={className}
|
|
|
+ />
|
|
|
</>
|
|
|
)
|
|
|
}
|
|
|
|
|
|
|
|
|
+//<CapitalizedInput className="input_class"
|
|
|
+ //id="super_id"/><br/>
|
|
|
+//<Sum />
|
|
|
+//<input type='color' />
|
|
|
+
|
|
|
const App = () =>
|
|
|
<>
|
|
|
- <Spoiler header={<b>Спойлер1</b>} defaultState>
|
|
|
- ЭТОТ СПОЙЛЕР ИЗНАЧАЛЬНО ОТКРЫТ, потому шо выше написано defaultState
|
|
|
- <p>
|
|
|
- Hello World
|
|
|
- </p>
|
|
|
- </Spoiler>
|
|
|
-
|
|
|
- <Spoiler header={<i>ОТКРОЙ МЕНЯ</i>}>
|
|
|
- <h3>второй спойлер</h3>
|
|
|
- <p>
|
|
|
- Hello World 2
|
|
|
- </p>
|
|
|
-
|
|
|
- <Spoiler header={<b>Спойлер внутри второго</b>}>
|
|
|
- <p>
|
|
|
- Hello World inside of Hello World
|
|
|
- </p>
|
|
|
- </Spoiler>
|
|
|
- </Spoiler>
|
|
|
- <PasswordInput />
|
|
|
- <PasswordInput minlength={10}/>
|
|
|
+ <PasswordConfirm />
|
|
|
+ <ViewablePassword />
|
|
|
</>
|
|
|
|
|
|
export default App;
|