diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3d19a63..5af8d13 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,3 +9,9 @@ variables: include: - project: 'turniere/turniere-infra' file: '/ci/pipeline.yaml' + +eslint: + stage: test + script: + - yarn install + - yarn eslint . diff --git a/README.md b/README.md index f4d7260..e730bc3 100644 --- a/README.md +++ b/README.md @@ -41,3 +41,8 @@ $ docker build -t turniere-frontend . ``` The built container exposes port 80. + +# Todo + +Timer in topnav +showMatches={playoffStages !== null} showmatches in GroupStage mittlerweile vmtl useless weil immer eingeklappt \ No newline at end of file diff --git a/js/components/BigImage.js b/js/components/BigImage.js index b89f6ff..aba9d5a 100644 --- a/js/components/BigImage.js +++ b/js/components/BigImage.js @@ -1,9 +1,27 @@ -import React from 'react'; +import React, {useEffect} from 'react'; export function BigImage(props) { + useEffect(() => { + const handleResize = () => { + const element = document.querySelector('.dynamically-resizing-h1'); + if (element) { + const parentWidth = element.parentElement.offsetWidth; + const fontSize = parentWidth / 16; // Adjust the divisor as needed + element.style.fontSize = `${fontSize}px`; + } + }; + + window.addEventListener('resize', handleResize); + handleResize(); // Initial call to set the font size + + return () => { + window.removeEventListener('resize', handleResize); + }; + }, []); + return (
-

{props.text}

+

{props.text}

); } diff --git a/js/components/FavoriteBar.js b/js/components/FavoriteBar.js new file mode 100644 index 0000000..86fd731 --- /dev/null +++ b/js/components/FavoriteBar.js @@ -0,0 +1,192 @@ +import React, {useState, useEffect, useRef} from 'react'; +import {Button, ButtonGroup, Input} from 'reactstrap'; +import {FaHeartCirclePlus, FaRegHeart, FaHeart, FaArrowTurnDown} from 'react-icons/fa6'; + +export function FavoriteBar({teams}) { + const [favorite, setFavorite] = useState(null); + const [isVisible, setIsVisible] = useState(false); + const [isLoading, setIsLoading] = useState(true); + const [isPulsing, setIsPulsing] = useState(false); + const [searchQuery, setSearchQuery] = useState(''); + const headingRef = useRef(null); + const favoriteBarRef = useRef(null); + const scrollButtonRef = useRef(null); + + useEffect(() => { + const savedFavorite = localStorage.getItem('favoriteTeam'); + if (savedFavorite) { + const team = teams.find(team => team.id === parseInt(savedFavorite, 10)); + if (team) { + setFavorite(team); + } + } + setIsLoading(false); + }, [teams]); + + useEffect(() => { + if (isVisible && favoriteBarRef.current) { + favoriteBarRef.current.style.maxHeight = `${favoriteBarRef.current.scrollHeight}px`; + } else if (favoriteBarRef.current) { + favoriteBarRef.current.style.maxHeight = '0'; + } + }, [isVisible]); + + useEffect(() => { + if (favoriteBarRef.current) { + favoriteBarRef.current.style.maxHeight = `${favoriteBarRef.current.scrollHeight}px`; + } + }, [searchQuery]); + + const toggleFavorite = team => { + if (favorite && favorite.id === team.id) { + setFavorite(null); + localStorage.removeItem('favoriteTeam'); + } else { + setFavorite(team); + localStorage.setItem('favoriteTeam', team.id); + setIsPulsing(true); + headingRef.current.scrollIntoView({behavior: 'smooth', block: 'center'}); + if (scrollButtonRef.current) { + scrollButtonRef.current.focus(); + } + } + setIsVisible(false); // Close the favorite menu + }; + + function findLowestPlayoffParticipation(favoriteId) { + const matchesWithFavoriteParticipation = document.querySelectorAll(`[data-team-level-ids*='-${favoriteId}']`); + let lowestMatch = null; // lowest means lowest stage number > latest game of the favorite + let lowestStageNum = Infinity; + + // Iterate over each element to find the match with the lowest stage number + matchesWithFavoriteParticipation.forEach(el => { + const dataTeamLevelIds = el.getAttribute('data-team-level-ids').split(','); + dataTeamLevelIds.forEach(pair => { + const [stage, teamId] = pair.split('-').map(Number); + if (teamId === favorite.id && stage < lowestStageNum) { + lowestStageNum = stage; + lowestMatch = el; + } + }); + }); + return lowestMatch; + } + + function findScrollToGroup(favoriteId) { + // Look for group elements that contain the favorite team's ID + const groupElements = document.querySelectorAll('[data-teams]'); + const scrollToNotFound = null; + + groupElements.forEach(groupEl => { + const teamIds = groupEl.getAttribute('data-teams').split(',').map(id => parseInt(id, 10)); + if (teamIds.includes(favoriteId)) { + return groupEl; + } + }); + + return scrollToNotFound; + } + + const scrollToFavorite = () => { + if (!favorite) { + return; // Exit if there is no favorite team selected + } + + const lowestMatch = findLowestPlayoffParticipation(favorite.id); + + let scrollTo; + if (lowestMatch) { + scrollTo = lowestMatch; + } else { + scrollTo = findScrollToGroup(favorite.id); + } + + if (!scrollTo) { + console.error('No match or group found for the favorite team'); + return; + } + + let scrollTimeout; + const handleScroll = () => { + clearTimeout(scrollTimeout); + scrollTimeout = setTimeout(() => { + setIsPulsing(false); + scrollTo.classList.add('scroll-to-highlight'); + setTimeout(() => { + scrollTo.classList.remove('scroll-to-highlight'); + }, 2000); + window.removeEventListener('scroll', handleScroll); + }, 100); + }; + + scrollTo.scrollIntoView({behavior: 'smooth', block: 'center'}); // Smoothly scroll to the target element + + // Add a scroll event listener to start the highlighting after scrolling only + window.addEventListener('scroll', handleScroll); + }; + + if (isLoading) { + return
Loading...
; + } + + const sortedTeams = [...teams].sort((a, b) => a.name.localeCompare(b.name)); + const filteredTeams = sortedTeams.filter(team => team.name.toLowerCase().includes(searchQuery.toLowerCase())); + + return ( +
+
+

Favorit:

+

{favorite ? favorite.name : ''}

+ + + {favorite && ( + + )} + +
+
+ {sortedTeams.length > 5 && ( + setSearchQuery(e.target.value)} + className="mb-2" + /> + )} +
+ {filteredTeams.map(team => ( +
toggleFavorite(team)} + style={{display: 'flex', alignItems: 'center', cursor: 'pointer'}} + > + + {team.name} +
+ ))} +
+
+
+ ); +} diff --git a/js/components/Footer.js b/js/components/Footer.js index d29ea06..70687cf 100644 --- a/js/components/Footer.js +++ b/js/components/Footer.js @@ -1,20 +1,13 @@ export function Footer() { return ( -