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 &&
}