Last active
November 15, 2019 16:03
-
-
Save sotnikov-link/4e5049ef987ed591a3d7f2fc44769fe2 to your computer and use it in GitHub Desktop.
Система лифтов в ЖК Ленинградский 21к3п2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from "react"; | |
import { CSSProperties, HTMLProps, memo, useCallback, useState } from "react"; | |
const createElevator = (isFull = false) => ({ | |
/** | |
* Лифт активирован кнопкой | |
*/ | |
isActive: false, | |
/** | |
* Полноценный лифт, который умеет ездить везде включая паркинг | |
*/ | |
isFull | |
}); | |
export const Elevator = () => { | |
/** | |
* Список лифтов. Всего 5, но только 2 ездят везде включая паркинг. | |
*/ | |
const [elevatorList, setElevatorList] = useState([ | |
createElevator(true), | |
createElevator(true), | |
createElevator(), | |
createElevator(), | |
createElevator() | |
]); | |
/** | |
* Кнопка нажата для полноценного лифта | |
*/ | |
const [isActiveButtonForFull, setIsActiveButtonForFull] = useState(false); | |
/** | |
* Кнопка нажата для любого лифта | |
*/ | |
const [isActiveButtonForAny, setIsActiveButtonForAny] = useState(false); | |
/** | |
* Вызвать полноценный лифт | |
*/ | |
const callFull = useCallback(() => { | |
if (!isActiveButtonForFull) { | |
setIsActiveButtonForFull(true); | |
setElevatorList( | |
elevatorList.map(item => | |
item.isFull ? { ...item, isActive: true } : item | |
) | |
); | |
} | |
}, [ | |
setIsActiveButtonForFull, | |
isActiveButtonForFull, | |
setElevatorList, | |
elevatorList | |
]); | |
/** | |
* Вызвать любой лифт | |
*/ | |
const callAny = useCallback(() => { | |
if (!isActiveButtonForAny) { | |
setIsActiveButtonForAny(true); | |
setElevatorList(elevatorList.map(item => ({ ...item, isActive: true }))); | |
} | |
}, [ | |
isActiveButtonForAny, | |
setIsActiveButtonForAny, | |
setElevatorList, | |
elevatorList | |
]); | |
/** | |
* Открыть лифт, как будто он приехал | |
*/ | |
const openElevator = useCallback( | |
(openElevator: ReturnType<typeof createElevator>) => { | |
if (openElevator.isActive) { | |
/** | |
* Кнопка нажата на парковку | |
* Кнопка нажата любой | |
* Приехавший лифт полноценный | |
* ↓ | |
* Кнопка нажата на парковку | |
* Кнопка нажата любой | |
* | |
* Варианты событий | |
* 101 → 00 | |
* 110 → 10 ← выявляем этот вариант, чтобы человека отвезти на парковку | |
* 111 → 00 | |
* 010 → 00 | |
* 011 → 00 | |
*/ | |
const isNeedFull = !openElevator.isFull && isActiveButtonForFull; | |
setElevatorList( | |
elevatorList.map(item => ({ | |
...item, | |
isActive: isNeedFull ? (item.isFull ? true : false) : false | |
})) | |
); | |
setIsActiveButtonForAny(false); | |
openElevator.isFull && setIsActiveButtonForFull(false); | |
} | |
}, | |
[ | |
setElevatorList, | |
elevatorList, | |
setIsActiveButtonForAny, | |
setIsActiveButtonForFull, | |
isActiveButtonForFull | |
] | |
); | |
return ( | |
<div style={{ fontFamily: "sans-serif" }}> | |
<h1>Первая версия</h1> | |
<div style={{ display: "flex", flexWrap: "wrap" }}> | |
{elevatorList.map((item, index) => ( | |
<div | |
key={index} | |
style={{ | |
...styles.elevator, | |
backgroundColor: item.isActive ? "cyan" : "lightgray" | |
}} | |
onClick={() => { | |
openElevator(item); | |
}} | |
> | |
Лифт №{index + 1} | |
<div style={{ fontSize: "0.8em" }}> | |
<div>{item.isFull ? "с паркингом" : "без паркинга"}</div> | |
<div>{item.isActive ? "может приехать" : "не вызван"}</div> | |
</div> | |
</div> | |
))} | |
</div> | |
<div> | |
Вызвать лифт: | |
<Button isFull onClick={callFull} isActive={isActiveButtonForFull} /> | |
или | |
<Button onClick={callAny} isActive={isActiveButtonForAny} /> | |
</div> | |
{(isActiveButtonForFull || isActiveButtonForAny) && ( | |
<div style={{ color: "darkgreen", margin: "1em 0" }}> | |
Далее, чтобы продолжить эксперимент: выберите лифт, который | |
теоритически приедет или продолжите нажимать кнопки. | |
</div> | |
)} | |
</div> | |
); | |
}; | |
const defaultButtonProps = { isFull: false, isActive: false }; | |
type ButtonProps = HTMLProps<HTMLButtonElement> & | |
Partial<typeof defaultButtonProps>; | |
const Button = memo<ButtonProps>( | |
({ | |
isFull = defaultButtonProps.isFull, | |
isActive = defaultButtonProps.isActive, | |
type, | |
style, | |
...props | |
}) => ( | |
<button | |
style={{ | |
...styles.button, | |
...(isActive && { backgroundColor: "cyan" }), | |
...style | |
}} | |
{...props} | |
> | |
{isFull ? "В паркинг" : "Любой"} | |
</button> | |
) | |
); | |
const styles: { [name: string]: CSSProperties } = { | |
elevator: { | |
width: "6em", | |
height: "8em", | |
margin: "0.75em", | |
textAlign: "center", | |
padding: "0.25em", | |
border: "1em burlywood solid", | |
borderBottom: "none" | |
}, | |
button: { | |
border: "1px solid black", | |
margin: "0 0.5em", | |
outline: "none", | |
fontSize: "inherit" | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment