|
@@ -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>
|
|
|
|
|
|
- <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 {
|
|
|
-
|
|
|
- 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);
|
|
|
-
|
|
|
- }
|
|
|
- },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 ? <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}/>
|
|
|
-
|
|
|
- {
|
|
|
- <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} />
|
|
|
|
|
|
- {
|
|
|
- <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>
|
|
|
);
|
|
|
}
|