From 82abe4162c0c009ec5d3d9586894f92bba865715 Mon Sep 17 00:00:00 2001 From: Slipum Date: Mon, 26 Jan 2026 16:05:27 +0300 Subject: [PATCH 1/2] feat: add adaptive design for match list --- .github/workflows/ci.yml | 2 +- app/globals.css | 98 ++++++++++++++++++++++++++++++++++++++- components/ListMaps.tsx | 60 ++++++++++++++---------- hooks/useClickOutside.tsx | 28 +++++++++++ 4 files changed, 160 insertions(+), 28 deletions(-) create mode 100644 hooks/useClickOutside.tsx diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d383410..0da5a84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ on: - "**" pull_request: branches: - - "**" + - master workflow_dispatch: jobs: diff --git a/app/globals.css b/app/globals.css index ec8b64f..25b6c64 100644 --- a/app/globals.css +++ b/app/globals.css @@ -456,6 +456,13 @@ tbody tr td { color: #f6f4f4; } +.fa-clock-rotate-left { + position: absolute; + left: 0; + margin-left: 8%; + margin-top: 10px; +} + .td-tour { color: #eca23a; } @@ -762,8 +769,9 @@ tbody tr td { /* Выпадающее меню */ .dropdown-filter { - left: 25%; - margin-top: 3rem; + left: 50%; + transform: translate(-50%, -50%); + margin-top: 12rem; background: #1b1b1b; border: 1px solid #ccc; box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); @@ -1073,6 +1081,23 @@ tbody tr td { color: #ff9226; } +.adaptive-filter { + display: none; +} + +.matches-container { + margin-bottom: 400px; +} + +@media screen and (max-width: 1320px) { + .match-adr, + .match-hs, + .match-kr, + .match-kd { + display: none; + } +} + @media screen and (max-width: 1140px) { .text-logo, .h-logo img { @@ -1084,6 +1109,24 @@ tbody tr td { } } +@media screen and (max-width: 950px) { + #matches table thead { + display: none; + } + + .adaptive-filter { + display: block; + font-size: 1.5rem; + align-items: center; + text-align: center; + padding: 10px 0; + } + + .filter-button { + font-size: 1.25rem; + } +} + @media screen and (max-width: 850px) { #won-matches { margin-top: 10rem; @@ -1106,6 +1149,57 @@ tbody tr td { .user-info { display: inline; } + + .match-id .fa-clock-rotate-left { + display: none; + } + + .fa-id { + color: #ff9226; + } +} + +@media screen and (max-width: 760px) { + #matches table tbody tr { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + } + + #matches tbody td { + border: none; + font-size: 1.5rem; + } + + #matches .match-map img { + width: 130px; + height: 65px; + } + + .match-kills, + .match-deaths, + .match-assists { + display: none; + } + + .result-indicator { + font-size: 1.5rem; + margin: 8px 16px 8px; + padding: 10px; + width: 30px; + height: 30px; + } + + .match-date, + .match-id, + .match-map, + .match-score, + .match-elo { + margin: auto 0; + } + + .match-date p { + display: none; + } } @media screen and (max-width: 655px) { diff --git a/components/ListMaps.tsx b/components/ListMaps.tsx index 9ce6876..5ccbdb2 100644 --- a/components/ListMaps.tsx +++ b/components/ListMaps.tsx @@ -1,8 +1,9 @@ import { getIconMap, headers } from "@/constants"; import Image from "next/image"; import Link from "next/link"; -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import TitleMatches from "./TitleMatches"; +import { useClickOutside } from "@/hooks/useClickOutside"; type StatType = { title: string; @@ -80,6 +81,7 @@ export function ListMaps({ // Фильтрация const [selectedMaps, setSelectedMaps] = useState([]); const [isOpen, setIsOpen] = useState(false); + const dropdownRef = useRef(null); const handleMapFilterChange = (map: string) => { setSelectedMaps((prev) => prev.includes(map) ? prev.filter((m) => m !== map) : [...prev, map], @@ -94,6 +96,8 @@ export function ListMaps({ let wins: number = 0; let totalMatchesToday: number = 0; + useClickOutside(dropdownRef, isOpen, () => setIsOpen(false)); + useEffect(() => { const fetchMatches = async () => { try { @@ -329,9 +333,10 @@ export function ListMaps({ totalMatchesToday={totalMatchesToday} lastSessionElo={lastSessionElo} /> -
+
{isOpen && (
{[ @@ -355,30 +360,38 @@ export function ListMaps({ ))}
)} +
+ Map + setIsOpen(!isOpen)} className="filter-button"> + + +
+
+
- - - + + - - - - - - - - - + + + + + + + + + @@ -389,15 +402,7 @@ export function ListMaps({ {filteredMatches.map((match, index) => { const count = 100 - index; - return ( + const row = ( ); + return width < 760 ? ( + + {row} + + ) : ( + row + ); })}
MatchDate + MatchDate Map setIsOpen(!isOpen)} + onClick={() => setIsOpen((prev) => !prev)} className="filter-button" > ScoreKillsAssistsDeathsK/DK/RHS %ADRELOScoreKillsAssistsDeathsK/DK/RHS %ADRELO
{day == new Date(match.date).toDateString() ? ( <> - + ) : ( <> @@ -405,6 +410,7 @@ export function ListMaps({ {count} - {new Date(match.date).toLocaleDateString()} + {new Date(match.date).toLocaleDateString("en-EN", { + day: "numeric", + month: "short", + year: "numeric", + })}

( {new Date(match.date).toLocaleTimeString([], { diff --git a/hooks/useClickOutside.tsx b/hooks/useClickOutside.tsx new file mode 100644 index 0000000..4f7c1fd --- /dev/null +++ b/hooks/useClickOutside.tsx @@ -0,0 +1,28 @@ +import { RefObject, useEffect } from "react"; + +export function useClickOutside( + ref: RefObject, + isOpen: boolean, + onClose: () => void, +) { + useEffect(() => { + const handleClick = (event: MouseEvent) => { + const target = event.target as HTMLElement; + if ( + ref.current && + !ref.current.contains(event.target as Node) && + !target.closest(".filter-button") + ) { + onClose(); + } + }; + + if (isOpen) { + document.addEventListener("mousedown", handleClick); + } + + return () => { + document.removeEventListener("mousedown", handleClick); + }; + }, [ref, isOpen, onClose]); +} From bc7cfac77a3773215a2169599ba3cf7a9fa0a191 Mon Sep 17 00:00:00 2001 From: Slipum Date: Tue, 27 Jan 2026 19:30:13 +0300 Subject: [PATCH 2/2] feat: update adaptive design v2 --- app/[id]/PlayerAvatar.tsx | 10 ++- app/[id]/Team.tsx | 7 +- app/[id]/idPage.tsx | 2 +- app/globals.css | 162 +++++++++++++++++++++++++++++++++++-- components/AnotherStat.tsx | 2 +- components/ListMaps.tsx | 37 +++++++-- components/MapsWin.tsx | 28 ++++--- 7 files changed, 215 insertions(+), 33 deletions(-) diff --git a/app/[id]/PlayerAvatar.tsx b/app/[id]/PlayerAvatar.tsx index 00d983a..fb6dc64 100644 --- a/app/[id]/PlayerAvatar.tsx +++ b/app/[id]/PlayerAvatar.tsx @@ -8,11 +8,11 @@ type PlayerProps = { const PlayerAvatar = ({ avatar, nickname }: PlayerProps) => { const [imageError, setImageError] = useState(false); - return ( <> {avatar && !imageError ? ( {nickname} { /> ) : (

- avatar + avatar
)} diff --git a/app/[id]/Team.tsx b/app/[id]/Team.tsx index c5199e5..3c250ac 100644 --- a/app/[id]/Team.tsx +++ b/app/[id]/Team.tsx @@ -87,6 +87,7 @@ export default function Team({ rounds, team, players, pos }: TeamProps) { {rounds && (pos == "right" ? (

Number(rounds[0]) ? "#66bb6a" : "#ff4d4f" @@ -95,10 +96,12 @@ export default function Team({ rounds, team, players, pos }: TeamProps) { width: "fit-content", }} > +

{team.name}

{rounds[1]} ) : (

Number(rounds[1]) ? "#66bb6a" : "#ff4d4f" @@ -108,6 +111,7 @@ export default function Team({ rounds, team, players, pos }: TeamProps) { }} > {rounds[0]} +

{team.name}

))}
@@ -145,7 +149,7 @@ export default function Team({ rounds, team, players, pos }: TeamProps) { border: "none", }} /> -

{team.name}

+

{team.name}

{pos == "left" && ( <>
{day == new Date(match.date).toDateString() ? ( @@ -484,6 +486,16 @@ export function ListMaps({
@@ -537,13 +549,10 @@ function getEloChange(currentElo: number, previousElo: number, i?: number) { ); } return ( - - {currentElo} +
+
{currentElo}
{changeText} - +
); } } @@ -562,3 +571,17 @@ function getFire(value: number, fire: number) { if (value >= fire) return "fa-solid fa-fire"; return ""; } + +function useWindowWidth() { + const [width, setWidth] = useState( + typeof window !== "undefined" ? window.innerWidth : 0, + ); + + useEffect(() => { + const handleResize = () => setWidth(window.innerWidth); + window.addEventListener("resize", handleResize); + return () => window.removeEventListener("resize", handleResize); + }, []); + + return width; +} diff --git a/components/MapsWin.tsx b/components/MapsWin.tsx index 249418b..958974c 100644 --- a/components/MapsWin.tsx +++ b/components/MapsWin.tsx @@ -86,22 +86,24 @@ export function MapsWin({ arr, winrate, qualityMap }: mapsProps) {

{mapKey.replace("de_", "").toUpperCase()}
-
+
Recent results - {arr[mapKey] && - arr[mapKey].split("").map((char, index) => ( -
- {char == "1" ? "W" : "L"} -
- ))} +
+ {arr[mapKey] && + arr[mapKey].split("").map((char, index) => ( +
+ {char == "1" ? "W" : "L"} +
+ ))} +
);