App.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. import {useState, useEffect, useRef} from 'react';
  2. import './App.scss';
  3. /////////////Spoiler
  4. const Spoiler = ({ header = "+", open, children }) => {
  5. const [opening, setOpening] = useState('');
  6. if (opening !== '') {
  7. open = opening;
  8. }
  9. return <>
  10. <div onClick={() => setOpening(!open)}>{header}</div>
  11. <div>{open && children}</div>
  12. </>
  13. }
  14. /////////////RangeInput
  15. const RangeInput = ({min,max}) => {
  16. const [text, setText] = useState('')
  17. return <div><input
  18. style={{backgroundColor: text.length<min || text.length>max ?'red':'white'}}
  19. value={text}
  20. onChange={e => setText(e.target.value)}
  21. type="text"/></div>
  22. }
  23. ////////////LoginForm
  24. const LoginForm = ({onLogin}) => {
  25. const [login, setTextLogin] = useState('')
  26. const [password, setTextPass] = useState('')
  27. let buttonDisabled= login.length<6 || password.length<6 ? true : false
  28. return (
  29. <div>
  30. <input placeholder='Login'
  31. value={login}
  32. onChange={e => setTextLogin(e.target.value)}
  33. type="text"
  34. /><br/>
  35. <input placeholder='Password'
  36. value={password}
  37. onChange={e => setTextPass(e.target.value)}
  38. type="password"
  39. /><br/>
  40. <button
  41. disabled= {buttonDisabled}
  42. onClick={() => onLogin({login,password})}
  43. >Login...</button>
  44. </div>
  45. )
  46. }
  47. ///////////PasswordConfirm
  48. const PasswordConfirm = ({min}) => {
  49. const [pass1, setPass1] = useState('')
  50. const [pass2, setPass2] = useState('')
  51. let inpunStyle
  52. let errorText
  53. let errorText2
  54. if(pass1===pass2 && pass1.length>=min && pass2.length>=min){
  55. inpunStyle = 'green'
  56. errorText =''
  57. errorText2 =''
  58. }else{
  59. pass1!==pass2? errorText = 'Пароли не совпадают':errorText =''
  60. pass1.length<min && pass2.length<min? errorText2 = `Пароль должени состоять минимум из ${min} символов`:errorText2 =''
  61. inpunStyle = 'white'
  62. }
  63. return <div>Введите пароль<br/>
  64. <input
  65. style={{backgroundColor: inpunStyle}}
  66. value={pass1}
  67. onChange={e => setPass1(e.target.value)}
  68. placeholder='Password'
  69. type="password"
  70. /><br/>Повторите пароль<br/>
  71. <input
  72. style={{backgroundColor: inpunStyle}}
  73. value={pass2}
  74. onChange={e => setPass2(e.target.value)}
  75. placeholder='Password'
  76. type="password"
  77. /><div style={{color:'red'}}>{errorText}<br/>{errorText2}</div>
  78. </div>
  79. }
  80. const oneCat = {
  81. "_id": "62c9472cb74e1f5f2ec1a0d4",
  82. "name": "iPhone",
  83. "goods": [
  84. {
  85. "_id": "62c9472cb74e1f5f2ec1a0d1",
  86. "name": "iPhone 4",
  87. "images": [
  88. {
  89. "url": "images/e48e7ee1bcc4ab5432d1e7a3a89b8466"
  90. },
  91. {
  92. "url": "images/58c6157d51d8c2430c4dd41b6d0132f4"
  93. }
  94. ]
  95. },
  96. {
  97. "_id": "62c9472cb74e1f5f2ec1a0d2",
  98. "name": "iPhone X",
  99. "images": [
  100. {
  101. "url": "images/c67956dff69d1160a6e70b71838d7282"
  102. },
  103. {
  104. "url": "images/0153956fc7bf99567e620ee446319b00"
  105. }
  106. ]
  107. },
  108. {
  109. "_id": "62c9472cb74e1f5f2ec1a0d3",
  110. "name": "iPhone 13",
  111. "images": [
  112. {
  113. "url": "images/56c5d476685355221b1a3ba2c554ad91"
  114. },
  115. {
  116. "url": "images/29393a087c933d7caea010c98f4d2876"
  117. }
  118. ]
  119. },
  120. {
  121. "_id": "634190ccb74e1f5f2ec1a37b",
  122. "name": "Iphone14",
  123. "images": [
  124. {
  125. "url": "images/2b2b08dfca28972c19f3f901c68966af"
  126. }
  127. ]
  128. }
  129. ]
  130. }
  131. const origUrl = 'http://shop-roles.node.ed.asmer.org.ua/'
  132. const GoodCard = ({good}) => {
  133. const [indexArr, setindexArr] = useState(0)
  134. return <div>
  135. {good.name}<br/>
  136. <img
  137. onClick={()=>indexArr=== good.images.length-1?setindexArr(0) :setindexArr(indexArr+1)}/////////////
  138. src={origUrl+good.images[indexArr].url}/>
  139. </div>
  140. }
  141. const OneCat = ({cat=oneCat}) =>
  142. <div>
  143. <h1>{cat.name}</h1>
  144. <div>{cat.goods.map(el=><GoodCard good={el}/>)}</div>
  145. </div>
  146. ///////////////Timer
  147. const Timer = ({countSeconds}) => {
  148. const [time, setTime] = useState(countSeconds)
  149. const [startTimer, setStartTimer] = useState(false)
  150. const [timerId, setTimerId] = useState(0)
  151. useEffect(() => {
  152. let intervalId = null
  153. if(startTimer){
  154. intervalId = setInterval(() => setTime(count => count -1), 1000)
  155. setTimerId(intervalId)
  156. }else{
  157. clearInterval(timerId)
  158. }
  159. },[startTimer])
  160. useEffect(() => {
  161. if(time===0){
  162. clearInterval(timerId)
  163. }
  164. },[time===0])
  165. let hours = Math.floor(time/60/60)
  166. let minutes = Math.floor(time/60)-(hours*60)
  167. let sec = time % 60
  168. return (
  169. <>
  170. <div>{hours}:{minutes}:{sec}</div>
  171. <button onClick={()=>setStartTimer(true) }>Start</button>
  172. <button onClick={()=>setStartTimer(false) }>Stop</button>
  173. </>
  174. )
  175. }
  176. const TimerControl = ()=>{
  177. const [hours, setHours] = useState('')
  178. const [minutes, setMinutes] = useState('')
  179. const [seconds, setSeconds] = useState('')
  180. const [start, setStart] = useState(false)
  181. return (
  182. <>
  183. <input
  184. className="inputTime"
  185. value={hours}
  186. onChange={e => setHours(e.target.value)}
  187. type="number"
  188. placeholder='hours'></input>
  189. <input
  190. className="inputTime"
  191. value={minutes}
  192. onChange={e => setMinutes(e.target.value)}
  193. type="number"
  194. placeholder='minutes'></input>
  195. <input
  196. className="inputTime"
  197. value={seconds}
  198. onChange={e => setSeconds(e.target.value)}
  199. type="number"
  200. placeholder='seconds'></input><br/>
  201. <button onClick={() => setStart(!start)}>Set time</button>
  202. {start && <Timer countSeconds={hours*60*6 + minutes*6 + seconds}/>}
  203. </>
  204. )
  205. }
  206. const TimerContainer = ({seconds, refresh, render}) => {
  207. const [sec, setSec] = useState(seconds);
  208. useEffect(() => {
  209. if(sec > 0){
  210. const intervalId = setInterval(()=>{setSec(sec=> sec-1)},refresh)
  211. return () => {
  212. clearInterval(intervalId);
  213. }
  214. }
  215. },[sec]);
  216. const Render = render;
  217. return (<Render seconds={sec} />)
  218. }
  219. const SecondsTimer = ({seconds}) => <h2>{seconds}</h2>
  220. function App() {
  221. return (
  222. <div className="App">
  223. <TimerContainer seconds={1800} refresh={1000} render={Watch}/>
  224. <TimerContainer seconds={1800} refresh={100} render={SecondsTimer}/>
  225. <TimerControl/>
  226. <Spoiler header={<h1>Заголовок</h1>} open>
  227. Контент 1
  228. <p>
  229. лорем ипсум траливали и тп.
  230. </p>
  231. </Spoiler>
  232. <Spoiler>
  233. <h2>Контент 2</h2>
  234. <p>
  235. лорем ипсум траливали и тп.
  236. </p>
  237. </Spoiler>
  238. <div>Задание RangeInput</div>
  239. <RangeInput min={2} max={10} />
  240. <div>Задание LoginForm</div>
  241. <LoginForm onLogin={({login, password}) => console.log('ЛОГИН И ПАРОЛЬ', login, password)}/>
  242. <div>Задание PasswordConfirm </div>
  243. <PasswordConfirm min={6} />
  244. <OneCat/>
  245. </div>
  246. );
  247. }
  248. export default App;