From ac60529d4cf45f4ede8792d9a2a82a03c95d7dbb Mon Sep 17 00:00:00 2001 From: EduardZaydler <117674342+EduardZaydler@users.noreply.github.com> Date: Wed, 4 Dec 2024 16:17:25 +0700 Subject: [PATCH 1/7] new year mood --- .../ChristmasLights/ChristmasLights.less | 139 ++++++++++++++++++ .../ChristmasLights/ChristmasLights.tsx | 52 +++++++ .../ChristmasMoodToggle.tsx | 20 +++ .../Header/Components/ChristmasHat.tsx | 36 +++++ src/Components/Header/Header.less | 9 +- src/Components/Header/Header.tsx | 10 +- src/Domain/Config.ts | 5 + src/desktop.bundle.tsx | 6 + src/hooks/useChristmasMood.ts | 32 ++++ src/hooks/useFeatureFlag.ts | 36 +++++ src/store/Reducers/ConfigReducer.slice.ts | 7 +- src/store/Reducers/UIReducer.slice.ts | 9 ++ 12 files changed, 358 insertions(+), 3 deletions(-) create mode 100644 src/Components/ChristmasLights/ChristmasLights.less create mode 100644 src/Components/ChristmasLights/ChristmasLights.tsx create mode 100644 src/Components/ChristmasMoodToggle/ChristmasMoodToggle.tsx create mode 100644 src/Components/Header/Components/ChristmasHat.tsx create mode 100644 src/hooks/useChristmasMood.ts create mode 100644 src/hooks/useFeatureFlag.ts diff --git a/src/Components/ChristmasLights/ChristmasLights.less b/src/Components/ChristmasLights/ChristmasLights.less new file mode 100644 index 00000000..131d862a --- /dev/null +++ b/src/Components/ChristmasLights/ChristmasLights.less @@ -0,0 +1,139 @@ +@bulb-size: 8px; +@lines-color: #000000; + +.ChristmasLightsWrapper { + height: 0; + width: 100%; + max-width: 100%; + display: flex; + justify-content: start; + align-items: start; + position: sticky; + z-index: 16; + overflow-x: clip; + pointer-events: none; +} + +.Bulb { + display: flex; + margin-left: 8px; + margin-right: 24px; + border-radius: 50%; + height: @bulb-size; + width: @bulb-size; + position: relative; + transition: 1s all ease; + + &:before { + position: absolute; + content: ""; + height: 2px; + width: 3px; + left: 2.5px; + top: -3px; + background: @lines-color; + border-radius: 2px; + border-bottom: 2px solid @lines-color; + } + + &:after { + position: absolute; + content: ""; + top: -11px; + left: 4px; + width: 40px; + height: 12px; + border-bottom: solid @lines-color 1.5px; + border-radius: 50%; + } + + &:last-child::after { + content: ""; + position: absolute; + border: none; + } +} + +@keyframes glow-red { + 0%, + 100% { + box-shadow: none; + background-color: rgba(192, 57, 43, 0.25); + border: 0.5px solid rgba(192, 57, 43, 0.33); + } + 33% { + background-color: rgb(192, 57, 43); + } + 50% { + box-shadow: 0 0 15px 2px rgb(192, 57, 43); + background-color: rgb(192, 57, 43); + } +} + +@keyframes glow-green { + 0%, + 100% { + box-shadow: none; + background-color: rgba(46, 204, 113, 0.25); + border: 0.5px solid rgba(46, 204, 113, 0.33); + } + 33% { + background-color: rgb(46, 204, 113); + } + 50% { + box-shadow: 0 0 15px 2px rgb(46, 204, 113); + background-color: rgb(46, 204, 113); + } +} + +@keyframes glow-blue { + 0%, + 100% { + box-shadow: none; + background-color: rgba(116, 247, 225, 0.25); + border: 0.5px solid rgba(116, 247, 225, 0.33); + } + 33% { + background-color: rgb(116, 247, 225); + } + 50% { + box-shadow: 0 0 15px 2px rgb(116, 247, 225); + background-color: rgb(116, 247, 225); + } +} + +@keyframes glow-yellow { + 0%, + 100% { + box-shadow: none; + background-color: rgba(241, 196, 15, 0.25); + border: 0.5px solid rgba(241, 196, 15, 0.33); + } + 33% { + background-color: rgb(241, 196, 15); + } + 50% { + box-shadow: 0 0 15px 2px rgb(241, 196, 15); + background-color: rgb(241, 196, 15); + } +} + +.RedBulb { + border-color: rgb(192, 57, 43); + animation: glow-red infinite; +} + +.GreenBulb { + background-color: rgb(46, 204, 113); + animation: glow-green infinite; +} + +.BlueBulb { + background-color: rgb(116, 247, 225); + animation: glow-blue infinite; +} + +.YellowBulb { + background-color: rgb(241, 196, 15); + animation: glow-yellow infinite; +} diff --git a/src/Components/ChristmasLights/ChristmasLights.tsx b/src/Components/ChristmasLights/ChristmasLights.tsx new file mode 100644 index 00000000..8e07b819 --- /dev/null +++ b/src/Components/ChristmasLights/ChristmasLights.tsx @@ -0,0 +1,52 @@ +import React, { useEffect, useState } from "react"; +import classNames from "classnames/bind"; +import styles from "./ChristmasLights.less"; + +const cn = classNames.bind(styles); + +export function ChristmasLights() { + const [width, setWidth] = useState(window.innerWidth); + + useEffect(() => { + const handleResize = () => setWidth(window.innerWidth); + + window.addEventListener("resize", handleResize); + return () => window.removeEventListener("resize", handleResize); + }, []); + + const count = Math.floor(width / 40); + const ids = [...Array(count).keys()]; + + return ( +
+ {ids.map((id) => ( + + ))} +
+ ); +} + +const randomNumberBetween = (min: number, max: number): number => { + if (min > max) { + throw new Error("Minimum value should be smaller than maximum value."); + } + const range = max - min; + return parseFloat((min + range * Math.random()).toFixed(2)); +}; + +const ChristmasBulb: React.FC<{ index: number }> = ({ index }) => { + const [duration] = useState(randomNumberBetween(3, 6)); + + let bulbClassName; + if (index % 4 === 0) { + bulbClassName = cn("Bulb", "RedBulb"); + } else if (index % 4 === 1) { + bulbClassName = cn("Bulb", "GreenBulb"); + } else if (index % 4 === 2) { + bulbClassName = cn("Bulb", "BlueBulb"); + } else { + bulbClassName = cn("Bulb", "YellowBulb"); + } + + return
; +}; diff --git a/src/Components/ChristmasMoodToggle/ChristmasMoodToggle.tsx b/src/Components/ChristmasMoodToggle/ChristmasMoodToggle.tsx new file mode 100644 index 00000000..75ed2569 --- /dev/null +++ b/src/Components/ChristmasMoodToggle/ChristmasMoodToggle.tsx @@ -0,0 +1,20 @@ +import React, { FC } from "react"; +import { Toggle } from "@skbkontur/react-ui/components/Toggle"; +import { useChristmasMood } from "../../hooks/useChristmasMood"; +import { useAppDispatch } from "../../store/hooks"; +import { toggleChristmasMood } from "../../store/Reducers/UIReducer.slice"; + +export const ChristmasMoodToggle: FC = () => { + const dispatch = useAppDispatch(); + const [isChristmasMood, setChristmasMood] = useChristmasMood(); + + const handleToggleChristmasMood = (selected: boolean) => { + setChristmasMood(selected); + dispatch(toggleChristmasMood(selected)); + }; + return ( + + New Year mood + + ); +}; diff --git a/src/Components/Header/Components/ChristmasHat.tsx b/src/Components/Header/Components/ChristmasHat.tsx new file mode 100644 index 00000000..2e90ea94 --- /dev/null +++ b/src/Components/Header/Components/ChristmasHat.tsx @@ -0,0 +1,36 @@ +import React, { SVGProps } from "react"; + +export const ChristmasHatSVG = (props: SVGProps) => { + return ( + + + + + + ); +}; diff --git a/src/Components/Header/Header.less b/src/Components/Header/Header.less index 8ac9b39a..40db9af8 100644 --- a/src/Components/Header/Header.less +++ b/src/Components/Header/Header.less @@ -30,6 +30,13 @@ .logo-link { text-decoration: none; + position: relative; +} + +.christmas-hat { + position: absolute; + left: 38px; + top: -4px; } .logo-img { @@ -41,7 +48,7 @@ .menu { margin-left: auto; - a { + > * { margin-left: 15px; color: #fff !important; } diff --git a/src/Components/Header/Header.tsx b/src/Components/Header/Header.tsx index 70e0fb79..9795ff09 100644 --- a/src/Components/Header/Header.tsx +++ b/src/Components/Header/Header.tsx @@ -9,9 +9,13 @@ import RouterLink from "../RouterLink/RouterLink"; import svgLogo from "./moira-logo.svg"; import { AdminMenu } from "./Components/AdminMenu"; import { useSelector } from "react-redux"; -import { selectPlatform } from "../../store/Reducers/ConfigReducer.slice"; +import { selectIsChristmasMood, selectPlatform } from "../../store/Reducers/ConfigReducer.slice"; import { useGetConfigQuery } from "../../services/BaseApi"; import { Platform } from "../../Domain/Config"; +import { ChristmasHatSVG } from "./Components/ChristmasHat"; +import { ChristmasMoodToggle } from "../ChristmasMoodToggle/ChristmasMoodToggle"; +import { useAppSelector } from "../../store/hooks"; +import { UIState } from "../../store/selectors"; import classNames from "classnames/bind"; import styles from "./Header.less"; @@ -21,6 +25,8 @@ const cn = classNames.bind(styles); export default function Header(): React.ReactElement { const platform = useSelector(selectPlatform); const { isLoading } = useGetConfigQuery(); + const { isChristmasMood } = useAppSelector(UIState); + const isChristmasMoodEnabled = useSelector(selectIsChristmasMood); return (
+ {isChristmasMood && } Moira