App.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. import {useEffect, useState, useRef} from "react";
  2. import React from 'react';
  3. import './App.css';
  4. import ClockFace from './pics/ClockFace.png'
  5. import ClockSec from './pics/ClockFace_S.png'
  6. import ClockMin from './pics/ClockFace_M.png'
  7. import ClockHour from './pics/ClockFace_H.png'
  8. const Spoiler = ({header="+", open=true, children}) => {
  9. const [open2, setOpen] = useState(open);
  10. return(
  11. <>
  12. <div onClick={()=> setOpen(open2===true?false:true)}>
  13. {header}
  14. {open2 && children}
  15. </div>
  16. </>
  17. )
  18. }
  19. const RangeInput = ({min=0, max=0}) => {
  20. //const [min2, setMin] = useState(min);
  21. //const [max2, setMax] = useState(max);
  22. const [length, setLength] = useState(0);
  23. return(
  24. <>
  25. <input type='text' style={{backgroundColor: (length<min || length>max)?'red':'green'}}
  26. onChange={e=>setLength(+e.target.value.length)} />
  27. </>
  28. )
  29. }
  30. const PasswordConfirm = ({min=0}) => {
  31. const [val, setVal] = useState('');
  32. const [secVal, setSecVal] = useState('');
  33. const [length, setLength] = useState(0);
  34. return(
  35. <>
  36. <div className='BTF'>
  37. <input type='password' onChange={e=>{setVal(e.target.value); setLength(e.target.value.length)}}
  38. style={{backgroundColor: length<min?'red':'green'}} className='btf1'/>
  39. <h3>{val}</h3>
  40. </div>
  41. <div className='BTF'>
  42. <input type='password' style={{backgroundColor: (length<min||secVal.toLowerCase()!==val.toLowerCase())?'red':'green'}}
  43. onChange={e=>setSecVal(e.target.value)} className='btf1'/>
  44. <p>{secVal}</p>
  45. </div>
  46. </>
  47. )
  48. }
  49. const Timer = ({startSec, onDelete, c}) => {
  50. const [sec, setSec] = useState(startSec);
  51. const [stop, setStop] = useState(false);
  52. const [add, setAdd] =useState(0);
  53. const [min,setMin] = useState(0);
  54. const [hour, setHour] = useState(0);
  55. const [err, setErr] = useState('');
  56. const [count, setCount] = useState(c);
  57. useEffect(() => {
  58. if(!stop) {
  59. if(sec === 0) return;
  60. const interval = setInterval(() => {
  61. setSec(sec => sec - 1)
  62. }, 1000)
  63. return () => {
  64. clearInterval(interval)
  65. }
  66. }
  67. }, [stop, sec, add])
  68. return (
  69. <div className='t'>
  70. <hr className='h' />
  71. <p>{count}</p>
  72. <p>{new Date(new Date().setHours(hour, min, sec)).toLocaleString().split (", ")[1]}</p>
  73. <input onChange={e=>setAdd(+e.target.value)} placeholder='add' />
  74. <button onClick={()=>setSec(sec+add)}>Add</button>
  75. <button onClick={() => setStop(!stop)}>Stop</button>
  76. <button onClick={onDelete}>x</button>
  77. {err}
  78. </div>
  79. )
  80. }
  81. //доделать: как сделать чтобы count совподал с текущей позицией
  82. const TimerControl = ({hours, minutes, seconds}) => {
  83. const [timers, setTimers] = useState([]);
  84. const [count, setCount] = useState(0);
  85. let [h, setH] = useState(hours);
  86. let [m, setM] = useState(minutes);
  87. let [s, setS] = useState(seconds);
  88. let item=0;
  89. let res = (h * 3600) + (m * 60) + +s;
  90. console.log(timers);
  91. return (
  92. <>
  93. <input value={h.toString()} type='number' min='0' max='23' placeholder='hours' onChange={e => setH(+e.target.value)}/>
  94. <input value={m.toString()} type='number' min='0' max='59' placeholder='minutes' onChange={e => setM(+e.target.value)}/>
  95. <input value={s.toString()} type='number' min='0' max='59' placeholder='seconds' onChange={e => setS(+e.target.value)}/>
  96. <button onClick={() =>{setCount(count+1); setTimers([Math.random(), ...timers]);}}>Start</button>
  97. <p>{timers.map(i => <Timer startSec={res} c={count} key={i} onDelete={()=>{setCount(count-1); setTimers(timers.filter(t=>t!==i));}}/>)}</p>
  98. </>
  99. )
  100. }
  101. const SecondsTimer = ({seconds}) => <h2>{seconds || 0}</h2>
  102. const TimerContainer = ({seconds, refresh, render:Tag}) => {
  103. const [count, setCount] = useState(seconds);
  104. useEffect(()=>{
  105. if(count<=0) return;
  106. let interval = setInterval(()=>{
  107. setCount(count=>count-1);
  108. }, refresh)
  109. return ()=> clearInterval(interval);
  110. }, [count, refresh])
  111. return(
  112. <>
  113. <Tag seconds={count}/>
  114. </>
  115. )
  116. }
  117. const Timer2 = ({startSec}) => {
  118. return (
  119. <div className='t'>
  120. <p>00:00:{startSec}</p>
  121. <input placeholder='not used' />
  122. <button>Add</button>
  123. <button>Stop</button>
  124. </div>
  125. )
  126. }
  127. const TimerContainer2 = ({startSec, refresh, render:Tag}) => {
  128. const [count, setCount] = useState(startSec);
  129. useEffect(()=>{
  130. if(count<=0) return;
  131. let interval = setInterval(()=>{
  132. setCount(count=>count-1);
  133. }, refresh)
  134. return ()=> clearInterval(interval);
  135. }, [count, refresh])
  136. return(
  137. <>
  138. <Tag startSec={count>0?(count<10?'0'+count:count):'00'}/>
  139. </>
  140. )
  141. }
  142. const Watch = ({ seconds = 1000 }) =>
  143. <div style={{ width: 'fit-content' }}>
  144. <img src={ClockFace} style={{ width: 'inherit', position: 'absolute' }} alt='img' />
  145. <img src={ClockSec} style={{
  146. width: 'inherit', position: 'absolute',
  147. transform: `rotate(${seconds % 60 * 6}deg)`
  148. }} alt='img' />
  149. <img src={ClockMin} style={{
  150. width: 'inherit', position: 'absolute',
  151. transform: `rotate(${(seconds / 60) % 60 * 6}deg)`
  152. }} alt='img' />
  153. <img src={ClockHour} style={{
  154. width: 'inherit', position: 'absolute',
  155. transform: `rotate(${((seconds) / (60 * 60)) % 24 * 30}deg)`
  156. }} alt='img' />
  157. </div>
  158. const TimerContainer3 = ({ seconds = 0, refresh = 10, render: Tag}) => {
  159. const [time, setTime] = useState(seconds * 1000)
  160. let [isPause, setIsPause] = useState(false)
  161. useEffect(() => {
  162. setTime(seconds * 1000)
  163. }, [seconds])
  164. useEffect(() => {
  165. let interval = null
  166. let now = performance.now()
  167. if (time > 0) {
  168. interval = setInterval(() => {
  169. if(!isPause){
  170. console.log('1:'+`${isPause}`)
  171. time > 0 ? setTime(time => time - (performance.now() - now)) : clearInterval(interval)
  172. }else{
  173. console.log('2:'+`${isPause}`)
  174. }
  175. }, refresh)
  176. }
  177. return () => clearInterval(interval)
  178. })
  179. return (
  180. <div>
  181. <button onClick={()=>setIsPause(!isPause)}>Pause / Continue</button>
  182. <Tag className="clock" seconds={time > 0 ? time / 1000 : 0} />
  183. </div>
  184. )
  185. }
  186. const Timer_Control_Container = ({h=0, m=0, s=0, render:Tag, refresh=10}) => {
  187. const [sec, setSec] = useState(s)
  188. const [min, setMin] = useState(m)
  189. const [hour, setHour] = useState(h)
  190. const [work, setWork] = useState(null)
  191. const [active, setActive] = useState(false)
  192. return (
  193. <div>
  194. <span>
  195. <input type="number" min="0" max="30" placeholder='hour'
  196. onChange={(e) => setHour(+e.target.value)}
  197. />
  198. <input type="number" min="0" max="59" placeholder='minutes'
  199. onChange={(e) => setMin(+e.target.value)}
  200. />
  201. <input type="number" min="0" max="59" placeholder='seconds'
  202. onChange={(e) => setSec(+e.target.value)}
  203. />
  204. {active===false ? <button disabled={!hour && !min && !sec} onClick={() => { setWork(hour * 60 * 60 + min * 60 + sec); setActive(true) }}>Start</button> :
  205. <button className='bckgr' onClick={() => { setWork(null); setActive(false) }}>Stop</button>}
  206. <br />
  207. </span>
  208. {work ? <TimerContainer3 seconds={work} render={Tag} refresh={refresh} /> :
  209. <TimerContainer3 seconds={0} render={Tag} refresh={refresh} />}
  210. </div>
  211. )
  212. }
  213. function App() {
  214. return (
  215. <div className="App">
  216. <h2><hr/>Spoiler</h2>
  217. <Spoiler header={<h1>Заголовок</h1>} open>
  218. Контент 1
  219. <p>
  220. лорем ипсум траливали и тп.
  221. </p>
  222. </Spoiler>
  223. <Spoiler>
  224. <h2>Контент 2</h2>
  225. <p>
  226. лорем ипсум траливали и тп.
  227. </p>
  228. </Spoiler>
  229. <h2><hr/>RangeInput</h2>
  230. <RangeInput min={5} max={10} />
  231. <h2><hr/>PasswordConfirm</h2>
  232. <PasswordConfirm min={2} />
  233. <h2><hr/>Timer</h2>
  234. <Timer startSec={5}/>
  235. <h2><hr/>TimerControl</h2>
  236. <TimerControl hours={1} minutes={10} seconds={10}/>
  237. <h2><hr/>TimerContainer</h2>
  238. <TimerContainer seconds={200} refresh={100} render={SecondsTimer}/>
  239. <h2><hr/>LCD</h2>
  240. <TimerContainer2 startSec={20} refresh={1000} render={Timer2}/>
  241. <h2><hr/>Watch</h2>
  242. <Timer_Control_Container render={Watch} />
  243. </div>
  244. );
  245. }
  246. export default App;