Browse Source

the task finally is done.(Thank you Ivan)

miskson 2 years ago
parent
commit
d7ccf2a99f
1 changed files with 110 additions and 135 deletions
  1. 110 135
      hw19-react-jsx-homework/src/App.js

+ 110 - 135
hw19-react-jsx-homework/src/App.js

@@ -6,55 +6,55 @@ import ClockHour from './assets/ClockFace_H.png'
 import './App.css';
 import { useEffect, useRef, useState } from 'react';
 
-const Spoiler = ({header="+", open=true, children}) => {
-  let [isOpen=open, setOpen] = useState()
+const Spoiler = ({ header = "+", open = true, children }) => {
+  let [isOpen = open, setOpen] = useState()
   return (
     <>
       <header onClick={() => setOpen(!isOpen)}>{header}</header>
-      <div style={{visibility: isOpen? 'visible' : 'hidden'}}>
+      <div style={{ visibility: isOpen ? 'visible' : 'hidden' }}>
         {children}
       </div>
     </>
   )
 }
 
-const RangeInput = ({min=1, max=10, type='text'}) => {
+const RangeInput = ({ min = 1, max = 10, type = 'text' }) => {
   let [valueLen, setValue] = useState()
   return (
     <div>
-      <input 
-        type={type} 
-        style={{outlineColor: valueLen < min || valueLen > max ? 'red' : 'black'}} 
+      <input
+        type={type}
+        style={{ outlineColor: valueLen < min || valueLen > max ? 'red' : 'black' }}
         onChange={(e) => setValue(e.target.value.length)}
       />
     </div>
   )
 }
 
-const PasswordConfirm = ({min=8}) => {
-  let [pass='', setPass] = useState()
+const PasswordConfirm = ({ min = 8 }) => {
+  let [pass = '', setPass] = useState()
   let [passRepeat, setPassReapeat] = useState()
 
   return (
-    <div style={{border: '1px solid black', backgroundColor: 'whitesmoke', width: 'fit-content'}}>
-      <input 
+    <div style={{ border: '1px solid black', backgroundColor: 'whitesmoke', width: 'fit-content' }}>
+      <input
         type='password'
         style={{
           display: 'block',
-          borderColor: pass === passRepeat && 
-          pass.length >= min && /[0-9]/.test(pass) && !/[\s]/.test(pass)? 'mediumseagreen': 'red'
+          borderColor: pass === passRepeat &&
+            pass.length >= min && /[0-9]/.test(pass) && !/[\s]/.test(pass) ? 'mediumseagreen' : 'red'
         }}
-        placeholder='password' 
+        placeholder='password'
         onChange={(e) => setPass(e.target.value)}
       />
-      <br/>
-      <input 
+      <br />
+      <input
         type='password'
         style={{
           display: 'block',
-          borderColor: pass === passRepeat? 'mediumseagreen' : 'red',
-          visibility: pass.length >= min && 
-          /[0-9]/.test(pass) && !/[\s]/.test(pass)? 'visible' : 'hidden' 
+          borderColor: pass === passRepeat ? 'mediumseagreen' : 'red',
+          visibility: pass.length >= min &&
+            /[0-9]/.test(pass) && !/[\s]/.test(pass) ? 'visible' : 'hidden'
         }}
         placeholder='repeat password'
         onChange={(e) => setPassReapeat(e.target.value)}
@@ -63,19 +63,19 @@ const PasswordConfirm = ({min=8}) => {
   )
 }
 
-const Timer = ({seconds=10}) => {
-  let [isPause ,setIsPause] = useState(false);
-  let [time=seconds, setTime] = useState(seconds)
+const Timer = ({ seconds = 10 }) => {
+  let [isPause, setIsPause] = useState(false);
+  let [time = seconds, setTime] = useState(seconds)
   useEffect(() => {
-    const interval = setInterval(()=> {
-      if(!isPause) {
-        time > 0? setTime(time - 1) : clearInterval(interval)
+    const interval = setInterval(() => {
+      if (!isPause) {
+        time > 0 ? setTime(time - 1) : clearInterval(interval)
       } else {
         clearInterval(interval)
       }
     }, 1000)
-    return() => {clearInterval(interval)}
-  },[time, isPause])
+    return () => { clearInterval(interval) }
+  }, [time, isPause])
 
   return (
     <>
@@ -85,168 +85,144 @@ const Timer = ({seconds=10}) => {
         {Math.floor(time % 60)}
       </strong>
       &nbsp;
-      <button onClick={() => setIsPause(!isPause)}>{isPause? 'Start' : 'Pause'}</button>
+      <button onClick={() => setIsPause(!isPause)}>{isPause ? 'Start' : 'Pause'}</button>
     </>
   )
 }
 
-const LCD = ({seconds=10}) =>
+const LCD = ({ seconds = 10 }) =>
   <strong>
     {Math.floor(((seconds / (60 * 60)) % 24))} :
     {Math.floor(((seconds / 60)) % 60)} :
     {Math.floor(seconds % 60)}
   </strong>
 
-const Watch = ({seconds=1000}) =>
-  <div style={{width:'fit-content'}}>
-    <img src={ClockFace} style={{width: 'inherit', position:'absolute'}}  alt='img'/>
-    <img src={ClockSec}  style={{width: 'inherit', position:'absolute',
-                                transform: `rotate(${seconds % 60 * 6}deg)`}} alt='img'/>
-    <img src={ClockMin}  style={{width: 'inherit', position:'absolute',
-                                transform: `rotate(${(seconds / 60) % 60 * 6}deg)`}} alt='img'/>
-    <img src={ClockHour} style={{width: 'inherit', position:'absolute',
-                                transform: `rotate(${((seconds) / (60*60)) % 24 * 30}deg)`}}  alt='img'/>
+const Watch = ({ seconds = 1000 }) =>
+  <div style={{ width: 'fit-content' }}>
+    <img src={ClockFace} style={{ width: 'inherit', position: 'absolute' }} alt='img' />
+    <img src={ClockSec} style={{
+      width: 'inherit', position: 'absolute',
+      transform: `rotate(${seconds % 60 * 6}deg)`
+    }} alt='img' />
+    <img src={ClockMin} style={{
+      width: 'inherit', position: 'absolute',
+      transform: `rotate(${(seconds / 60) % 60 * 6}deg)`
+    }} alt='img' />
+    <img src={ClockHour} style={{
+      width: 'inherit', position: 'absolute',
+      transform: `rotate(${((seconds) / (60 * 60)) % 24 * 30}deg)`
+    }} alt='img' />
   </div>
 
 
-const SecondsTimer = ({seconds}) => <h2>{seconds.toFixed(2)}</h2>
+const SecondsTimer = ({ seconds }) => <h2>{seconds.toFixed(2)}</h2>
 
-const TimerControl = ({hour=0, minute=0, second=0}) => {
+const TimerControl = ({ hour = 0, minute = 0, second = 0 }) => {
   let [hr, setHr] = useState(hour)
   let [min, setMin] = useState(minute)
   let [sec, setSec] = useState(second)
-  let [active=false, setActive] = useState()
+  let [active = false, setActive] = useState()
 
   return (
     <span>
       <input
         type="number"
-        min="0" 
+        min="0"
         max="30"
-        placeholder='hr' 
-        value={hr} 
-        onChange={(e)=> setHr(+e.target.value < 0 || +e.target.value > +e.target.max ? 0 : +e.target.value)}
+        placeholder='hr'
+        value={hr}
+        onChange={(e) => setHr(+e.target.value < 0 || +e.target.value > +e.target.max ? 0 : +e.target.value)}
       />:
       <input
         type="number"
-        min="0" 
-        max="59"  
-        placeholder='min' 
+        min="0"
+        max="59"
+        placeholder='min'
         value={min}
-        onChange={(e)=> setMin(+e.target.value > 59 || e.target.value < 0? 0 : +e.target.value)}
+        onChange={(e) => setMin(+e.target.value > 59 || e.target.value < 0 ? 0 : +e.target.value)}
       />:
-      <input 
+      <input
         type="number"
-        min="0" 
+        min="0"
         max="59"
-        placeholder='sec' 
-        value={sec} 
-        onChange={(e)=> setSec(+e.target.value > 59 || e.target.value < 0? 0 : +e.target.value)}
+        placeholder='sec'
+        value={sec}
+        onChange={(e) => setSec(+e.target.value > 59 || e.target.value < 0 ? 0 : +e.target.value)}
       />
 
-      { active ? <button onClick={() => setActive(false)}>Stop</button> :
-                 <button onClick={() => setActive(true)}>Start</button>}
+      {active ? <button onClick={() => setActive(false)}>Stop</button> :
+        <button onClick={() => setActive(true)}>Start</button>}
       <br />
-      { active ? <Timer seconds={hr*60*60 + min*60 + sec}/> : ''}
+      {active ? <Timer seconds={hr * 60 * 60 + min * 60 + sec} /> : ''}
     </span>
   )
 }
 
-const TimerContainer = ({seconds=3800, refresh=10, render:Component}) => {
-  let [time, setTime] = useState()
-  let set = useRef(false)
-  let ended = useRef(false)
-  let idle = useRef(0)
-  let interval = useRef(setInterval)
-  let start = performance.now()
+const TimerContainer = ({ seconds = 0, refresh = 10, render: Component }) => {
+  let [time, setTime] = useState(seconds * 1000)
 
   useEffect(() => {
-    console.log('isSet', set.current)
-    console.log('idle', idle)
-
-    if(seconds > 0 && !set.current && !ended.current) {
-      setTime(seconds*1000)
-      console.log('TIMESET', time)
-      set.current = true
-      idle.current = 0
-    } else {
-      if (time > 0) {
-        setTime(time)
-      } else {
-        //ended.current = true
-        setTime(0)
-        set.current = false
-        idle.current = seconds*1000  - performance.now()
-      }
-    }
-  })
+    setTime(seconds * 1000)
+  }, [seconds])
 
   useEffect(() => {
+    let interval = null
     let now = performance.now()
-    const interval = setInterval(()=> {
-      if(set.current) {
-        setTime(seconds*1000 -performance.now())
-      } else {
-        set.current = false
-        setTime(0);
-        //clearInterval(interval); 
-      }
-    },refresh)
-    
+    if (time > 0) {
+      interval = setInterval(() => {
+        setTime(time => time - (performance.now() - now))
+      }, refresh)
+    }
+    return () => { clearInterval(interval) }
+  })
 
-    return() => clearInterval(interval)
-  }, [refresh, time, seconds])
-  
-  return(
-    <Component seconds={time/1000}/>
+  return (
+    <Component seconds={time > 0 ? time / 1000 : 0} />
   )
 }
 
-const TimerControlContainer = ({hour=0, minute=0, second=0, render:Component, refresh=10}) => {
+const TimerControlContainer = ({ hour = 0, minute = 0, second = 0, render: Component, refresh = 10 }) => {
   let [hr, setHr] = useState(hour)
   let [min, setMin] = useState(minute)
   let [sec, setSec] = useState(second)
-  let [active, setActive] = useState(false)
-  let [returned, setReturned] = useState(hr*60*60 + min*60 + sec)
 
-  useEffect(() => {
-    active ? setReturned(hr*60*60 + min*60 + sec) :setReturned(0) 
-  }, [Component, active, hr, min, sec, refresh])
+  let [active, setActive] = useState(false)
+  let [returned, setReturned] = useState(null)
 
   return (
     <div>
       <span>
         <input
           type="number"
-          min="0" 
+          min="0"
           max="30"
-          placeholder='hr' 
-          value={hr} 
-          onChange={(e)=> setHr(+e.target.value < 0 || +e.target.value > +e.target.max ? 0 : +e.target.value)}
+          placeholder='hr'
+          value={hr}
+          onChange={(e) => setHr(+e.target.value < 0 || +e.target.value > +e.target.max ? 0 : +e.target.value)}
         />:
         <input
           type="number"
-          min="0" 
-          max="59"  
-          placeholder='min' 
+          min="0"
+          max="59"
+          placeholder='min'
           value={min}
-          onChange={(e)=> setMin(+e.target.value > 59 || e.target.value < 0? 0 : +e.target.value)}
+          onChange={(e) => setMin(+e.target.value > 59 || e.target.value < 0 ? 0 : +e.target.value)}
         />:
-        <input 
+        <input
           type="number"
-          min="0" 
+          min="0"
           max="59"
-          placeholder='sec' 
-          value={sec} 
-          onChange={(e)=> setSec(+e.target.value > 59 || e.target.value < 0? 0 : +e.target.value)}
+          placeholder='sec'
+          value={sec}
+          onChange={(e) => setSec(+e.target.value > 59 || e.target.value < 0 ? 0 : +e.target.value)}
         />
 
-        { active ? <button onClick={() => setActive(false)}>Stop</button> :
-                  <button onClick={() => setActive(true)}>Start</button>}
+        {!active ? <button disabled={!hr && !min && !sec} onClick={() => { setReturned(hr * 60 * 60 + min * 60 + sec); setActive(true) }}>Start</button> :
+          <button onClick={() => { setReturned(null); setActive(false) }}>Stop</button>}
         <br />
       </span>
-      <TimerContainer seconds={returned} render={Component} refresh={refresh}/>
-      {/* {returned > 0? <TimerContainer seconds={returned} render={Component} refresh={refresh}/> : ''} */}
+      {returned ? <TimerContainer seconds={returned} render={Component} refresh={refresh} /> :
+        <TimerContainer seconds={0} render={Component} refresh={refresh} />}
     </div>
   )
 }
@@ -257,11 +233,11 @@ function App() {
       <Spoiler header={<h1>Заголовок(клацать сюда)</h1>} open>
         Контент 1
         <p>
-            лорем ипсум траливали и тп.
+          лорем ипсум траливали и тп.
         </p>
-        <img alt="img" src={logo} width="200" heigt="200"/>
+        <img alt="img" src={logo} width="200" heigt="200" />
         <h3>Range Input</h3>
-        <RangeInput min={2}/>
+        <RangeInput min={2} />
       </Spoiler>
       <br />
 
@@ -269,22 +245,21 @@ function App() {
       <PasswordConfirm />
 
       <h3>Timer</h3>
-      <Timer seconds={10}/>
+      <Timer seconds={10} />
 
       <h3>Timer Control</h3>
-      <TimerControl second={10}/>
-      
-      {/* <h3>Timer Container</h3>
-      <TimerContainer render={SecondsTimer}/>
-      <TimerContainer render={SecondsTimer} seconds={10} refresh={10}/>
-      <TimerContainer render={LCD}/> */}
+      <TimerControl second={10} />
+
+      <h3>Timer Container</h3>
+      <TimerContainer render={SecondsTimer} seconds={200} />
+      <TimerContainer render={SecondsTimer} seconds={10} refresh={10} />
+      <TimerContainer render={LCD} seconds={1800} />
 
-      {/* <h3>Watch</h3>
-      <TimerContainer render={Watch} seconds={7200}/>
-      <TimerContainer render={LCD} seconds={7200}/> */}
+      <h3>Watch</h3>
+      <TimerContainer render={LCD} seconds={7200} />
 
       <h3>Timer Control Container</h3>
-      <TimerControlContainer render={SecondsTimer} />
+      <TimerControlContainer render={Watch} />
     </div>
   );
 }