setFocused(true)}
+ onFocus={() => dispatch(updateSearchOpen(true))}
className={`${
- focused
+ searchBarState.search.open
? "h-48 sm:h-64 translate-y-0 opacity-100"
: "h-0 translate-y--2 opacity-0"
} overflow-hidden transition-all duration-500 bg-slate-100 rounded-b-sm absolute w-full top-full flex flex-col lg:flex-row border-[1px] border-gray-200`}
diff --git a/components/Sidebar/Sidebar.jsx b/components/Sidebar/Sidebar.jsx
index bab7a71..3a22bd2 100644
--- a/components/Sidebar/Sidebar.jsx
+++ b/components/Sidebar/Sidebar.jsx
@@ -1,58 +1,71 @@
"use client";
-
+import { createElement } from "react";
import { BsGearFill } from "react-icons/bs";
import TftLogo from "../../public/images/tft-logo.svg";
import ValorantLogo from "../../public/images/valorant-logo.svg";
import LolLogo from "../../public/images/lol-logo.svg";
-import Logo from "../../public/images/icon.svg";
import Link from "next/link";
import { useTranslation } from "next-i18next";
+import BrandLogo from "@/public/images/brand-logo.svg";
+import { useRouter } from "next/router";
+
+const SIDEBAR_ICONS = [
+ {
+ logo: LolLogo,
+ size: 28,
+ text: "League of Legends",
+ href: "/",
+ },
+ {
+ logo: ValorantLogo,
+ size: 28,
+ text: "Valorant",
+ href: "/valorant",
+ },
+ {
+ logo: TftLogo,
+ size: 28,
+ text: "Teamfight Tactics",
+ href: "/tft",
+ },
+ {
+ logo: BsGearFill,
+ size: 22,
+ textKey: "settings", // Using translation key here
+ href: "/settings",
+ },
+];
const SideBar = () => {
+ const router = useRouter();
const { t } = useTranslation("sidebar");
return (
);
};
-const SideBarIcon = ({ href, icon, text = "tooltip 💡" }) => (
-
-
-);
-
-const SideBarMainIcon = ({ href, icon, text = "tooltip 💡" }) => (
+const SideBarIcon = ({ href, icon, text = "tooltip 💡", isActive }) => (
+
{icon}
{text}
diff --git a/hooks/useOutsideClick.js b/hooks/useOutsideClick.js
new file mode 100644
index 0000000..acfd19f
--- /dev/null
+++ b/hooks/useOutsideClick.js
@@ -0,0 +1,22 @@
+import { useEffect } from "react";
+
+function useOutsideClick(ref1, ref2, callback) {
+ useEffect(() => {
+ function handleClickOutside(event) {
+ if (
+ ref1.current &&
+ !ref1.current.contains(event.target) &&
+ (!ref2 ||
+ (ref2 && ref2.current && !ref2.current.contains(event.target)))
+ ) {
+ callback();
+ }
+ }
+
+ document.addEventListener("mousedown", handleClickOutside);
+ return () => {
+ document.removeEventListener("mousedown", handleClickOutside);
+ };
+ }, [ref1, ref2, callback]);
+}
+export default useOutsideClick;
diff --git a/package-lock.json b/package-lock.json
index e7a156d..0253f84 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -40,6 +40,7 @@
"react-icons": "^4.10.1",
"react-redux": "^8.1.2",
"react-responsive": "^9.0.2",
+ "redux-thunk": "^2.4.2",
"tailwind-merge": "^1.14.0",
"tailwindcss": "3.3.3",
"tailwindcss-animate": "^1.0.6"
diff --git a/package.json b/package.json
index 9a884ba..03b17a8 100644
--- a/package.json
+++ b/package.json
@@ -41,6 +41,7 @@
"react-icons": "^4.10.1",
"react-redux": "^8.1.2",
"react-responsive": "^9.0.2",
+ "redux-thunk": "^2.4.2",
"tailwind-merge": "^1.14.0",
"tailwindcss": "3.3.3",
"tailwindcss-animate": "^1.0.6"
diff --git a/pages/_app.js b/pages/_app.js
index da3b268..61d1465 100644
--- a/pages/_app.js
+++ b/pages/_app.js
@@ -3,8 +3,10 @@ import { appWithTranslation } from "next-i18next";
import "@/styles/globals.css";
import { Noto_Sans } from "next/font/google";
-import { Provider } from "react-redux";
+import { Provider, useDispatch } from "react-redux";
import store from "@/store/store";
+import { useRouter } from "next/router";
+import { useEffect } from "react";
const natoSans = Noto_Sans({
subsets: ["latin"],
@@ -12,20 +14,33 @@ const natoSans = Noto_Sans({
display: "swap",
});
-const App = ({ Component, pageProps }) => {
- return (
-
-
-
+function InnerApp({ Component, pageProps }) {
+ const dispatch = useDispatch();
+ const router = useRouter();
+
+ useEffect(() => {
+ dispatch({
+ type: "ROUTE_CHANGED",
+ payload: router.pathname,
+ });
+ }, [router.pathname]);
-
-
-
+ return (
+
+
+
+
);
-};
+}
+
+const App = ({ Component, pageProps }) => (
+
+
+
+);
export default appWithTranslation(App);
diff --git a/pages/valorant.js b/pages/valorant.js
new file mode 100644
index 0000000..e4a563d
--- /dev/null
+++ b/pages/valorant.js
@@ -0,0 +1,25 @@
+import axios from "axios";
+import SearchBar from "@/components/SearchBar/SearchBar";
+import GenericLayout from "@/layout/generic-layout";
+import { serverSideTranslations } from "next-i18next/serverSideTranslations";
+import { useTranslation } from "next-i18next";
+
+export default function Home() {
+ return (
+
+
+
+
+
+ );
+}
+
+export async function getServerSideProps({ locale }) {
+ return {
+ props: {
+ ...(await serverSideTranslations(locale, ["home", "sidebar"])),
+ },
+ };
+}
diff --git a/public/images/brand-logo.svg b/public/images/brand-logo.svg
new file mode 100644
index 0000000..c4abd01
--- /dev/null
+++ b/public/images/brand-logo.svg
@@ -0,0 +1,16 @@
+
+
diff --git a/public/json/platform-api-routes.js b/public/json/platform-api-routes.js
index 09449ee..3e1e743 100644
--- a/public/json/platform-api-routes.js
+++ b/public/json/platform-api-routes.js
@@ -1,4 +1,4 @@
-const PLATFORM_LIST = [
+export const PLATFORM_LIST_LOL = [
{ code: "NA1", label: "NA", url: "na1.api.riotgames.com" },
{ code: "EUW1", label: "EUW", url: "euw1.api.riotgames.com" },
{ code: "EUN1", label: "EUN", url: "eun1.api.riotgames.com" },
@@ -16,4 +16,12 @@ const PLATFORM_LIST = [
{ code: "VN2", label: "VN", url: "vn2.api.riotgames.com" },
];
-export default PLATFORM_LIST;
+export const PLATFORM_LIST_VAL = [
+ { code: "NA", label: "NA", url: "na.api.riotgames.com" },
+ { code: "EU", label: "EU", url: "eu.api.riotgames.com" },
+ { code: "LATAM", label: "LATAM", url: "latam.api.riotgames.com" },
+ { code: "BR", label: "BR", url: "br.api.riotgames.com" },
+ { code: "KR", label: "KR", url: "kr.api.riotgames.com" },
+ { code: "AP", label: "AP", url: "ap.api.riotgames.com" },
+ { code: "ESPORTS", label: "ESPORTS", url: "esports.api.riotgames.com" },
+];
diff --git a/store/middleware/routeChangeMiddleware .js b/store/middleware/routeChangeMiddleware .js
new file mode 100644
index 0000000..5eaf5d2
--- /dev/null
+++ b/store/middleware/routeChangeMiddleware .js
@@ -0,0 +1,27 @@
+import {
+ updateGameValue,
+ updateRegionValue,
+} from "@/store/slices/searchBarSlice";
+import {
+ PLATFORM_LIST_LOL,
+ PLATFORM_LIST_VAL,
+} from "@/public/json/platform-api-routes.js";
+import GAME_LIST from "@/public/json/game-platforms";
+
+const routeChangeMiddleware = (store) => (next) => (action) => {
+ if (action.type === "ROUTE_CHANGED") {
+ const pathname = action.payload;
+
+ if (pathname.includes("/valorant")) {
+ store.dispatch(updateRegionValue(PLATFORM_LIST_VAL[0]));
+ store.dispatch(updateGameValue(GAME_LIST[1]));
+ } else {
+ store.dispatch(updateRegionValue(PLATFORM_LIST_LOL[0]));
+ store.dispatch(updateGameValue(GAME_LIST[0]));
+ }
+ }
+
+ return next(action);
+};
+
+export default routeChangeMiddleware;
diff --git a/store/slices/searchBarSlice.js b/store/slices/searchBarSlice.js
new file mode 100644
index 0000000..38c06a1
--- /dev/null
+++ b/store/slices/searchBarSlice.js
@@ -0,0 +1,62 @@
+import { createSlice } from "@reduxjs/toolkit";
+
+const searchbarSlice = createSlice({
+ name: "searchBar",
+ initialState: {
+ region: {
+ open: false,
+ value: null,
+ },
+ game: {
+ open: false,
+ value: null,
+ },
+ search: {
+ open: false,
+ value: null,
+ },
+ },
+ reducers: {
+ updateRegionValue(state, action) {
+ state.region.value = action.payload;
+ },
+ updateRegionOpen(state, action) {
+ state.region.open = action.payload;
+ if (action.payload === true) {
+ state.game.open = false;
+ state.search.open = false;
+ }
+ },
+ updateGameValue(state, action) {
+ state.game.value = action.payload;
+ },
+ updateGameOpen(state, action) {
+ state.game.open = action.payload;
+ if (action.payload === true) {
+ state.region.open = false;
+ state.search.open = false;
+ }
+ },
+ updateSearchValue(state, action) {
+ state.search.value = action.payload;
+ },
+ updateSearchOpen(state, action) {
+ state.search.open = action.payload;
+ if (action.payload === true) {
+ state.region.open = false;
+ state.game.open = false;
+ }
+ },
+ },
+});
+
+export const {
+ updateRegionValue,
+ updateRegionOpen,
+ updateGameValue,
+ updateGameOpen,
+ updateSearchValue,
+ updateSearchOpen,
+} = searchbarSlice.actions;
+
+export default searchbarSlice;
diff --git a/store/store.js b/store/store.js
index f6846ce..e0c9d86 100644
--- a/store/store.js
+++ b/store/store.js
@@ -1,12 +1,17 @@
import { combineReducers, configureStore } from "@reduxjs/toolkit";
import userSlice from "./slices/userSlice";
+import searchbarSlice from "./slices/searchBarSlice";
+import routeChangeMiddleware from "./middleware/routeChangeMiddleware ";
const reducer = combineReducers({
user: userSlice.reducer,
+ searchBar: searchbarSlice.reducer,
});
const store = configureStore({
reducer: reducer,
+ middleware: (getDefaultMiddleware) =>
+ getDefaultMiddleware().concat(routeChangeMiddleware),
});
export default store;
diff --git a/styles/_scrollbar.css b/styles/_scrollbar.css
new file mode 100644
index 0000000..5a53d7b
--- /dev/null
+++ b/styles/_scrollbar.css
@@ -0,0 +1,42 @@
+/* Total scrollbar */
+scrollbar,
+scrollbar * {
+ width: 10px !important;
+ height: 10px !important;
+}
+
+/* Track */
+scrollbar-track {
+ background: #f1f1f1 !important;
+}
+
+/* Handle */
+scrollbar-thumb {
+ background-color: #888 !important;
+}
+
+/* Handle on hover */
+scrollbar-thumb:hover {
+ background-color: #555 !important;
+}
+
+/* Total scrollbar */
+::-webkit-scrollbar {
+ width: 10px; /* width of the entire scrollbar */
+ height: 10px; /* height of the horizontal scrollbar */
+}
+
+/* Track */
+::-webkit-scrollbar-track {
+ background: #f1f1f1; /* color of the tracking area */
+}
+
+/* Handle */
+::-webkit-scrollbar-thumb {
+ background: #888; /* scrollbar handle color */
+}
+
+/* Handle on hover */
+::-webkit-scrollbar-thumb:hover {
+ background: #555; /* scrollbar handle hover color */
+}
diff --git a/styles/_sidebar.css b/styles/_sidebar.css
index 1a61f38..5e55609 100644
--- a/styles/_sidebar.css
+++ b/styles/_sidebar.css
@@ -4,19 +4,9 @@
.sidebar-icon {
@apply relative flex items-center justify-center
h-12 w-10 sm:w-12 mt-2 mb-2 mx-auto
- hover:bg-accent
- text-accent hover:text-white
- hover:rounded-xl rounded-3xl
- transition-all duration-100 ease-linear
- cursor-pointer;
- }
-
- .sidebar-icon-main {
- @apply relative flex items-center justify-center
- h-12 w-10 sm:w-12 mt-2 mb-2 mx-auto
- hover:bg-red-500
- text-red-500 hover:text-black
- hover:rounded-xl rounded-3xl
+ hover:bg-secondary
+ text-white
+ hover:rounded-xl rounded-xl
transition-all duration-100 ease-linear
cursor-pointer;
}
diff --git a/styles/globals.css b/styles/globals.css
index 09596c3..62d2260 100644
--- a/styles/globals.css
+++ b/styles/globals.css
@@ -3,6 +3,7 @@
@tailwind utilities;
@import "_sidebar.css";
+@import "_scrollbar.css";
@layer base {
:root {