123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- import ClockFace from "./assets/images/ClockFace.png";
- import ClockFace_H from "./assets/images/ClockFace_H.png";
- import ClockFace_M from "./assets/images/ClockFace_M.png";
- import ClockFace_S from "./assets/images/ClockFace_S.png";
- import './assets/scss/_page-styles/rickandmortyapi.scss';
- import './assets/scss/_page-styles/common.scss';
- import './assets/scss/_page-styles/clock-face.scss';
- import React, {useState, useEffect, useRef} from 'react';
- // hw19 (22.10.2022)
- import dataEpisodes from './assets/json/dataEpisodes.json';
- import dataCharacters from './assets/json/dataCharacters.json';
- const CharactersItem = ({name, gender, image}) =>
- <li className="characters-list__item">
- <h3 className="characters-list__name">{name}</h3>
- <p>{gender}</p>
- <img className="characters-list__image"
- alt={name}
- src={image}
- />
- </li>
- const EpisodeItem = ({name, air_date, children}) =>
- <>
- <h1 className="episode__name">{name}</h1>
- <time className="episode__air-date">{air_date}</time>
- {children}
- </>
- const Episode = () =>
- dataEpisodes.map(item => (
- <div className="episode"
- key={Math.random()}
- >
- <EpisodeItem name={item.name}
- air_date={item.air_date}
- >
- <ul className="characters-list">
- {dataCharacters.map(character => (
- <CharactersItem key={Math.random()}
- name={character.name}
- gender={character.gender}
- image={character.image}
- />
- ))}
- </ul>
- </EpisodeItem>
- </div>
- ))
- // React JSX Homework - hw20 (22.10.2022)
- // Spoiler
- const Spoiler = ({header="+", open, children}) => {
- const [isOpen, setIsOpen] = useState(open)
- return (
- <section>
- <div onClick={() => setIsOpen(!isOpen)}>{header}</div>
- {isOpen && children}
- </section>
- )
- }
- // RangeInput
- const RangeInput = ({min, max}) => {
- const [text, setText] = useState('');
- return (
- <input type="text"
- value={text}
- style={{borderColor: (text.length > max || text.length < min) ? 'red' : 'rgb(118, 118, 118)'}}
- onChange={event => setText(event.target.value)}
- />
- )
- }
- // LoginForm
- const LoginForm = ({onLogin}) => {
- const [login, setLogin] = useState('');
- const [password, setPassword] = useState('');
- return(
- <fieldset>
- <input placeholder="login"
- type="text"
- name="login"
- value={login}
- onChange={e => setLogin(e.target.value)}
- /><br/>
- <input placeholder="password"
- type="password"
- name="password"
- value={password}
- onChange={e => setPassword(e.target.value)}
- /><br/>
- <button className="login-button"
- onClick={() => onLogin(login, password)}
- type="button"
- disabled={!(login.length > 0 && password.length > 0)}
- >Login</button>
- </fieldset>
- )
- }
- // PasswordConfirm
- const PasswordConfirm = ({min}) => {
- const [password, setPassword] = useState('');
- const [confirmPassword, setConfirmPassword] = useState('');
- return(
- <fieldset>
- <input placeholder="password"
- type="password"
- name="password"
- value={password}
- style={{borderColor: (password.length >= min && password === confirmPassword) ? 'gray' : 'red'}}
- onChange={e => setPassword(e.target.value)}
- /><br/>
- <input placeholder="confirm password"
- type="password"
- name="confirmPassword"
- value={confirmPassword}
- style={{borderColor: (confirmPassword.length >= min && confirmPassword === password) ? 'gray' : 'red'}}
- onChange={e => setConfirmPassword(e.target.value)}
- />
- </fieldset>
- )
- }
- // Timer
- const Timer = ({seconds}) => {
- const [count, setCount] = useState(seconds);
- const intervalRef = useRef(null)
- useEffect(() => {
- intervalRef.current = setInterval(() => {
- setCount(count => count - 1)
- }, 1000);
- return () => {
- clearInterval(intervalRef.current);
- }
- }, [seconds]);
- const pause = () => {
- clearInterval(intervalRef.current);
- }
- if(count === 0) pause();
- const ISODate = (start, end) => new Date(count * 1000).toISOString().slice(start, end);
- return(
- <div>
- <span>{ISODate(11, 13)}</span>:
- <span>{ISODate(14, 16)}</span>:
- <span>{ISODate(17, 19)}</span>
- <button className="default-button"
- type="button"
- onClick={pause}
- >Pause</button>
- </div>
- )
- }
- // TimerControl
- const TimerControl = () => {
- const [hoursVal, setHoursVal] = useState(10);
- const [minutesVal, setMinutesVal] = useState(0);
- const [secondsVal, setSecondsVal] = useState(0);
- const [isStart, setStart] = useState(false);
- const totalSeconds = (hoursVal * 3600) + (minutesVal * 60) + secondsVal;
- return(
- <fieldset>
- <label>
- часы
- <input type="text"
- name="hours"
- value={hoursVal}
- onChange={event => setHoursVal(+event.target.value)}
- />
- </label>
- <label>
- минуты
- <input type="text"
- name="minutes"
- value={minutesVal}
- onChange={event => setMinutesVal(+event.target.value)}
- />
- </label>
- <label>
- секунды
- <input type="text"
- name="seconds"
- value={secondsVal}
- onChange={event => setSecondsVal(+event.target.value)}
- />
- </label>
- <button type="button"
- className="default-button"
- onClick={() => setStart(!isStart)}
- >Start Timer</button>
- {isStart && <Timer seconds={totalSeconds}/>}
- </fieldset>
- )
- }
- // TimerContainer
- const SecondsTimer = ({seconds}) => <h2>{seconds}</h2>
- const TimerContainer = ({seconds, refresh, render}) => {
- const [count, setCount] = useState(seconds);
- useEffect(() => {
- const intervalID = setInterval(() => {
- setCount(count => count - 1)
- }, refresh);
- return () => {
- clearInterval(intervalID);
- }
- }, [seconds]);
- const RenderProps = render;
- return(
- <RenderProps seconds={count}/>
- );
- }
- // LCD
- const TimerPresentation = ({seconds}) => {
- const ISODate = (start, end) => new Date(seconds * 1000).toISOString().slice(start, end);
- return(
- <div>
- <span>{ISODate(11, 13)}</span>:
- <span>{ISODate(14, 16)}</span>:
- <span>{ISODate(17, 19)}</span>
- </div>
- )
- }
- // Watch
- const Watch = ({seconds}) => {
- const ISODate = (start, end) => new Date(seconds * 1000).toISOString().slice(start, end);
- return (
- <figure className="clock-face">
- <img className="clock-face__bg"
- src={ClockFace}
- width="400"
- height="400"
- alt="циферблат"
- />
- <img className="clock-face__element"
- src={ClockFace_H}
- width="400"
- height="400"
- alt="стрелка часовая"
- style={{rotate: `${ISODate(11, 13)*30}deg`}}
- />
- <img className="clock-face__element"
- src={ClockFace_M}
- width="400"
- height="400"
- alt="стрелка минутная"
- style={{rotate: `${ISODate(14, 16)*6}deg`}}
- />
- <img className="clock-face__element"
- src={ClockFace_S}
- width="400"
- height="400"
- alt="стрелка секундная"
- style={{rotate: `${ISODate(17, 19)*6}deg`}}
- />
- </figure>
- )
- }
- // TimerControl + TimerContainer
- const TimerControlContainer = ({render}) => {
- const [hoursVal, setHoursVal] = useState(0);
- const [minutesVal, setMinutesVal] = useState(0);
- const [secondsVal, setSecondsVal] = useState(0);
- const [isStart, setStart] = useState(false);
- const totalSeconds = (hoursVal * 3600) + (minutesVal * 60) + secondsVal;
- return(
- <fieldset>
- <label>
- часы
- <input type="text"
- name="hours"
- value={hoursVal}
- onChange={event => setHoursVal(+event.target.value)}
- />
- </label>
- <label>
- минуты
- <input type="text"
- name="minutes"
- value={minutesVal}
- onChange={event => setMinutesVal(+event.target.value)}
- />
- </label>
- <label>
- секунды
- <input type="text"
- name="seconds"
- value={secondsVal}
- onChange={event => setSecondsVal(+event.target.value)}
- />
- </label>
- <button type="button"
- className="default-button"
- onClick={() => setStart(!isStart)}
- >Start Timer</button>
- {isStart && <TimerContainer seconds={totalSeconds} render={render} refresh={150}/>}
- </fieldset>
- )
- }
- const App = () => {
- return (
- <div className="App">
- {/*<section className="episodes">
- <Episode />
- </section>*/}
- <Spoiler header={<h1>Заголовок</h1>} open>
- Контент 1
- <p>
- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Commodi, eaque?
- </p>
- </Spoiler>
- <br/>
- <Spoiler>
- <h2>Контент 2</h2>
- <p>
- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam consectetur consequatur corporis dolores, laborum minus repellat sequi! Aliquam, aspernatur, ipsam?
- </p>
- </Spoiler>
- <br/>
- <RangeInput min={5} max={20} />
- <br/><br/>
- <LoginForm onLogin={(login, password) => console.log({login, password})}/>
- <br/>
- <PasswordConfirm min={2} />
- <br/>
- <Timer seconds={50}/>
- <TimerControl />
- <TimerContainer seconds={1800}
- refresh={1000}
- render={SecondsTimer}
- />
- <TimerContainer seconds={500}
- refresh={500}
- render={TimerPresentation}
- />
- <TimerContainer seconds={30800}
- refresh={1000}
- render={Watch}
- />
- <TimerControlContainer render={Watch} />
- </div>
- )
- }
- export default App;
|