Skip to content

Instantly share code, notes, and snippets.

@sotnikov-link
Last active November 15, 2019 16:03
Show Gist options
  • Save sotnikov-link/4e5049ef987ed591a3d7f2fc44769fe2 to your computer and use it in GitHub Desktop.
Save sotnikov-link/4e5049ef987ed591a3d7f2fc44769fe2 to your computer and use it in GitHub Desktop.
Система лифтов в ЖК Ленинградский 21к3п2
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