App.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import React, {useState, useEffect, useRef} from 'react'
  2. import logoDefault from './logo.svg';
  3. import './App.scss';
  4. import {Provider, connect} from 'react-redux';
  5. import {createStore, combineReducers, applyMiddleware} from 'redux';
  6. import thunk from 'redux-thunk';
  7. const Spoiler = ({header="+", open=true, children}) => {
  8. const [isOpen, setOpen] = useState(open)
  9. return (
  10. <div>
  11. <div onClick = {e => setOpen(!isOpen)}>{header}</div>
  12. {isOpen && children}
  13. </div>
  14. )
  15. }
  16. const RangeInput = ({min, max}) => {
  17. const [text, setText] = useState('')
  18. return (
  19. <input style={ {backgroundColor: (text.length >= min && text.length <= max) ? '#fff' : '#f00'} }
  20. value={text} onChange={(e) => setText(e.target.value)}/>
  21. )
  22. }
  23. const PasswordConfirm = ({min, char=false, bigChar=false, number=false}) => {
  24. const [pass, setPass] = useState('')
  25. const [pass2, setPass2] = useState('')
  26. const checkPass = (password) => {
  27. if ( password.length >= min &&
  28. (char ? password.match(/[a-zA-ZА-ЯЁа-яё]/) : true) &&
  29. (bigChar ? password.match(/[A-ZА-ЯЁ]/) : true) &&
  30. (number ? password.match(/[\d]/) : true) ) {
  31. return true
  32. } else {
  33. return false
  34. }
  35. }
  36. const printPassReq = (password) => {
  37. let str = ''
  38. if (!checkPass(password)) {
  39. str += 'Пароль должен содержать: '
  40. } else {
  41. str += 'Пароль подходит '
  42. }
  43. if (password.length < min) {
  44. str += ` минимум ${min} символ${((min === 1) ? '' : (min > 1 && min < 5) ? 'а' : 'ов')},`
  45. }
  46. if (!(char ? password.match(/[a-zA-ZА-ЯЁа-яё]/) : true)) {
  47. str += ' буквы,'
  48. }
  49. if (!(bigChar ? password.match(/[A-ZА-ЯЁ]/) : true)) {
  50. str += ' прописные буквы,'
  51. }
  52. if (!(number ? password.match(/[\d]/) : true)) {
  53. str += ' цифры,'
  54. }
  55. return str.slice(0, -1)
  56. }
  57. return (
  58. <div>
  59. <p>
  60. <input type='password' className="p1" value={pass} onChange={(e) => setPass(e.target.value)}
  61. style={ {backgroundColor: ( checkPass(pass) && pass === pass2) ? '#fff' : '#f00'} }/>
  62. <label>
  63. {printPassReq(pass)}
  64. </label>
  65. </p>
  66. <p>
  67. <input type='password' className="p2" value={pass2} onChange={(e) => setPass2(e.target.value)}
  68. style={ {backgroundColor: ( checkPass(pass2) && pass === pass2) ? '#fff' : '#f00'} }/>
  69. <label>
  70. {printPassReq(pass2)}
  71. </label>
  72. </p>
  73. <div>{(pass === pass2 ? '' : 'пароли не совпадают')}</div>
  74. </div>
  75. )
  76. }
  77. const Timer = ({seconds=100}) => {
  78. const [counter, setCounter] = useState(seconds)
  79. const [paused, setPause] = useState(false)
  80. useEffect(() => {
  81. setCounter(seconds)
  82. }, [seconds])
  83. useEffect(() => {
  84. let interval = null
  85. if (counter > 0 && !paused) {
  86. interval = setInterval(() => {
  87. setCounter(counter => counter - 1)
  88. }, 1000);
  89. }
  90. return () => {
  91. clearInterval(interval)
  92. }
  93. }, [paused, counter])
  94. let h = Math.floor(counter / 3600)
  95. let m = Math.floor(counter % 3600 / 60)
  96. let s = counter % 60
  97. return (
  98. <div>
  99. <h2>{h >= 10 ? h : '0'+h}:{m >= 10 ? m : '0'+m}:{s >= 10 ? s : '0'+s}</h2>
  100. <button onClick={() => setPause(!paused)}>{paused ? 'Го' : 'Пауза'}</button>
  101. </div>
  102. )
  103. }
  104. const TimerControl = ({setSeconds}) => {
  105. const [s, setS] = useState(0)
  106. const [m, setM] = useState(0)
  107. const [h, setH] = useState(0)
  108. return (
  109. <div>
  110. <input value={h} min="0" max="none" type="number" onChange={(e) => setH(e.target.value)}/>
  111. <input value={m} min="0" max="60" type="number" onChange={(e) => setM(e.target.value)}/>
  112. <input value={s} min="0" max="60" type="number" onChange={(e) => setS(e.target.value)}/>
  113. <button onClick={() => setSeconds(+h*3600 + +m*60 + +s) }>Start</button>
  114. </div>
  115. )
  116. }
  117. const SecondsTimer = ({seconds}) => (
  118. <h2>{seconds}</h2>
  119. )
  120. const TimerContainer = ({seconds=100, refresh=100, render}) => {
  121. const DisplayEl = render
  122. return (
  123. <>
  124. <DisplayEl seconds={200} />
  125. </>
  126. )
  127. }
  128. function App() {
  129. const [seconds, setSeconds] = useState(200)
  130. return (
  131. <>
  132. <Spoiler header={<h1>Заголовок</h1>} open={false}>
  133. Контент 1
  134. <p>
  135. лорем ипсум траливали и тп.
  136. </p>
  137. </Spoiler>
  138. <RangeInput min={2} max={10} />
  139. <PasswordConfirm min={3} char={true} bigChar={true} number={true}/>
  140. <Timer seconds={seconds} />
  141. <TimerControl setSeconds={setSeconds}/>
  142. <TimerContainer seconds={1800} refresh={100} render={SecondsTimer}/>
  143. </>
  144. );
  145. }
  146. export default App;