Skip to content

Commit

Permalink
Merge pull request #240 from bruin-tennis-consulting/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
Fredenck authored Nov 14, 2024
2 parents 71420f9 + d9c3903 commit fa25496
Show file tree
Hide file tree
Showing 25 changed files with 456 additions and 345 deletions.
4 changes: 2 additions & 2 deletions app/(interactive)/match-list/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import React from 'react'
import Link from 'next/link'
import { useMatchData } from '../../components/MatchDataProvider' // Assuming the hook is located in the context folder
import { useData } from '../../components/DataProvider' // Assuming the hook is located in the context folder

const formatMatches = (matches) => {
return matches
Expand All @@ -11,7 +11,7 @@ const formatMatches = (matches) => {
}

export default function MatchList() {
const { matches, updateMatch, refresh } = useMatchData()
const { matches, updateMatch, refresh } = useData()
// const [newName, setNewName] = useState('')

const formattedMatches = formatMatches(matches)
Expand Down
108 changes: 90 additions & 18 deletions app/(interactive)/matches/[slug]/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,10 @@ import FilterList from '../../../components/FilterList'
import PointsList from '../../../components/PointsList'
import ScoreBoard from '../../../components/ScoreBoard'
import MatchTiles from '@/app/components/MatchTiles'
import { useMatchData } from '@/app/components/MatchDataProvider'
import extractSetScores from '@/app/services/extractSetScores'
import { useData } from '@/app/components/DataProvider'
import ExtendedList from '../../../components/ExtendedList'
import nameMap from '@/app/services/nameMap'

console.log(match)

const MatchPage = () => {
const [matchData, setMatchData] = useState()
const [filterList, setFilterList] = useState([])
Expand All @@ -31,7 +28,7 @@ const MatchPage = () => {
const tableRef = useRef(null)
const iframeRef = useRef(null)

const { matches, updateMatch } = useMatchData()
const { matches, updateMatch } = useData()
const pathname = usePathname()
const docId = pathname.substring(pathname.lastIndexOf('/') + 1)

Expand Down Expand Up @@ -153,18 +150,70 @@ const MatchPage = () => {
}
}

const matchSetScores = matchData ? extractSetScores(matchData.pointsJson) : {}
const getMatchScores = (pointsJson) => {
if (!pointsJson || !pointsJson.length) return []

// Group points by set and get the last point of each set
return (
Object.values(
pointsJson.reduce((acc, point) => {
if (
!acc[point.setNum] ||
point.Position > acc[point.setNum].Position
) {
acc[point.setNum] = point
}
return acc
}, {})
)
// Sort by set number
.sort((a, b) => a.setNum - b.setNum)
// Map to score arrays, filtering out 0-0 scores
.map((point) => {
if (!point.gameScore || point.gameScore === '0-0') return null
return point.gameScore.split('-').map(Number)
})
.filter(Boolean)
)
}

// Usage in your component:
const matchScores = matchData ? getMatchScores(matchData.pointsJson) : []

return (
<div className={styles.container}>
{matchData && (
<>
<MatchTiles
matchName={matchData.name}
clientTeam={matchData.clientTeam}
opponentTeam={matchData.opponentTeam}
matchDetails={matchData.matchDetails}
{...matchSetScores}
matchName={matchData.matchDetails.event}
clientTeam={matchData.teams.clientTeam}
opponentTeam={matchData.teams.opponentTeam}
matchDetails={matchData.matchDetails.event} // This needs to be updated in MatchTiles.js
date={matchData.matchDetails.date}
player1Name={
matchData.players.client.firstName +
' ' +
matchData.players.client.lastName
}
player2Name={
matchData.players.opponent.firstName +
' ' +
matchData.players.opponent.lastName
}
player1FinalScores={matchScores.map((scores) => ({
score: scores[0]
}))}
player2FinalScores={matchScores.map((scores) => ({
score: scores[1]
}))}
player1TieScores={matchData.pointsJson.map(
(point) => point.player1TiebreakScore
)}
player2TieScores={matchData.pointsJson.map(
(point) => point.player2TiebreakScore
)}
isUnfinished={matchData.matchDetails.status === 'unfinished'}
displaySections={{ score: true, info: true, matchup: true }}
/>
<div className={styles.headerRow}>
<div className={styles.titleContainer}>
Expand Down Expand Up @@ -286,8 +335,8 @@ const MatchPage = () => {
pointsData={returnFilteredPoints()}
onPointSelect={handleJumpToTime}
onBookmark={handleBookmark}
clientTeam={matchData.clientTeam}
opponentTeam={matchData.opponentTeam}
clientTeam={matchData.teams.clientTeam}
opponentTeam={matchData.teams.opponentTeam}
/>
</div>
<div style={{ padding: '0.5vw', paddingLeft: '5vw' }}>
Expand All @@ -307,8 +356,8 @@ const MatchPage = () => {
pointsData={bookmarks}
onPointSelect={handleJumpToTime}
onBookmark={handleBookmark}
clientTeam={matchData.clientTeam}
opponentTeam={matchData.opponentTeam}
clientTeam={matchData.teams.clientTeam}
opponentTeam={matchData.teams.opponentTeam}
/>
</div>
<div style={{ padding: '0.5vw', paddingLeft: '5vw' }}>
Expand All @@ -325,7 +374,30 @@ const MatchPage = () => {
<ScoreBoard
names={matchData.name}
playData={playingPoint}
{...matchSetScores}
player1Name={
matchData.players.client.firstName +
' ' +
matchData.players.client.lastName
}
player2Name={
matchData.players.opponent.firstName +
' ' +
matchData.players.opponent.lastName
}
player1FinalScores={matchScores.map((scores) => ({
score: scores[0]
}))}
player2FinalScores={matchScores.map((scores) => ({
score: scores[1]
}))}
player1TieScores={matchData.pointsJson.map(
(point) => point.player1TiebreakScore
)}
player2TieScores={matchData.pointsJson.map(
(point) => point.player2TiebreakScore
)}
isUnfinished={matchData.matchDetails.status === 'unfinished'}
displaySections={{ score: true, info: true, matchup: true }}
/>
</div>
</div>
Expand Down Expand Up @@ -362,8 +434,8 @@ const MatchPage = () => {
<div ref={tableRef} className={styles.ExtendedList}>
<ExtendedList
pointsData={returnFilteredPoints()}
clientTeam={matchData.clientTeam}
opponentTeam={matchData.opponentTeam}
clientTeam={matchData.teams.clientTeam}
opponentTeam={matchData.teams.opponentTeam}
onPointSelect={handleJumpToTime}
iframe={iframeRef}
/>
Expand Down
4 changes: 2 additions & 2 deletions app/(interactive)/tag-match/[slug]/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import {
} from '../../../services/taggerButtonData.js'
import styles from '../../../styles/TagMatch.module.css'
import { usePathname } from 'next/navigation'
import { useMatchData } from '@/app/components/MatchDataProvider'
import { useData } from '@/app/components/DataProvider'
import TennisCourtSVG from '@/app/components/TennisCourtSVG'

export default function TagMatch() {
const pathname = usePathname()
const matchId = pathname.substring(pathname.lastIndexOf('/') + 1)
const { matches, updateMatch, refresh } = useMatchData()
const { matches, updateMatch, refresh } = useData()
const match = matches.find((m) => m.id === matchId)

const [videoObject, setVideoObject] = useState(null)
Expand Down
4 changes: 2 additions & 2 deletions app/(interactive)/upload-match/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
import React, { useState, useEffect, useCallback } from 'react'
import Form from '@rjsf/core'
import validator from '@rjsf/validator-ajv8'
import { useMatchData } from '../../components/MatchDataProvider.js'
import { useData } from '../../components/DataProvider.js'
import { useAuth } from '../../components/AuthWrapper.js'
import getTeams from '@/app/services/getTeams.js'
import styles from '../../styles/Upload.module.css'
import { initialSchema, uiSchema } from '@/app/services/matchSchemas.js'
import { searchableProperties } from '@/app/services/searchableProperties.js'

export default function UploadMatchForm() {
const { createMatch } = useMatchData() // Use the createMatch hook
const { createMatch } = useData() // Use the createMatch hook
const [schema, setSchema] = useState(initialSchema)
const [teams, setTeams] = useState([])
const [collections, setCollections] = useState([])
Expand Down
4 changes: 2 additions & 2 deletions app/components/AuthWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import React, {
import { onAuthStateChanged, signOut } from 'firebase/auth'
import { auth } from '../services/initializeFirebase'
import { getUserProfile } from '../services/userInfo'
import SignIn from './SignIn'
import LandingPage from './LandingPage'

const AuthContext = createContext()

Expand Down Expand Up @@ -55,7 +55,7 @@ export const AuthProvider = ({ children }) => {
<AuthContext.Provider
value={{ authUser, userProfile: memoizedUserProfile, handleSignOut }}
>
{authUser ? children : <SignIn />}
{authUser ? children : <LandingPage />}
</AuthContext.Provider>
</div>
)
Expand Down
10 changes: 2 additions & 8 deletions app/components/Dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

import React, { useState, useMemo } from 'react'
import { useRouter } from 'next/navigation'
import { useMatchData } from './MatchDataProvider'
import { useDatabase } from './DatabaseProvider'
import { useData } from './DataProvider'
import styles from '../styles/Dashboard.module.css'
import DashTileContainer from './DashTileContainer'
// import getTeams from '@/app/services/getTeams.js'
Expand All @@ -23,12 +22,7 @@ const formatMatches = (matches) => {

const Dashboard = () => {
const router = useRouter()
const { matches, error } = useMatchData() // Using the custom hook to access match data
const { logos } = useDatabase()

// TODO: remove this line used for linting
console.log(error)

const { matches, logos } = useData()
const [searchTerm, setSearchTerm] = useState('')
const [selectedMatchSets, setSelectedMatchSets] = useState([])

Expand Down
4 changes: 2 additions & 2 deletions app/components/DashboardTile.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react'
import styles from '../styles/DashboardTile.module.css'
import { useDatabase } from './DatabaseProvider'
import { useData } from './DataProvider'

// Calculate winner of match
const calculateWinner = (player1, player2) => {
Expand All @@ -27,7 +27,7 @@ const DashboardTile = ({
isUnfinished,
isTagged
}) => {
const { logos, loading } = useDatabase()
const { logos, loading } = useData()
const [clientLogo, setClientLogo] = useState(null)
const [opponentLogo, setOpponentLogo] = useState(null)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,24 @@ import React, {
import { collection, getDocs, doc, updateDoc, addDoc } from 'firebase/firestore'
import { db } from '../services/initializeFirebase.js'
import { useAuth } from './AuthWrapper.js'
import getTeams from '../services/getTeams.js'

const MatchDataContext = createContext()
const DataContext = createContext()

export const MatchDataProvider = ({ children }) => {
export const DataProvider = ({ children }) => {
// For Match Data
const [matches, setMatches] = useState([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)

// For Logos
const [logos, setLogos] = useState(() => {
const storedLogos = localStorage.getItem('teamLogos')
return storedLogos ? JSON.parse(storedLogos) : {}
})
const [logosLoading, setLogosLoading] = useState(!Object.keys(logos).length)
const [logosError, setLogosError] = useState(null)

const { userProfile } = useAuth()

const fetchMatches = useCallback(async () => {
Expand Down Expand Up @@ -101,38 +112,69 @@ export const MatchDataProvider = ({ children }) => {
[fetchMatches]
)

const fetchLogos = useCallback(async () => {
const storedLogos = localStorage.getItem('teamLogos')
if (storedLogos) {
setLogos(JSON.parse(storedLogos))
setLogosLoading(false)
return
}

setLogosLoading(true)
setLogosError(null)

try {
const teams = await getTeams()
const logosMap = teams.reduce((acc, team) => {
acc[team.name] = team.logoUrl
return acc
}, {})

setLogos(logosMap)
localStorage.setItem('teamLogos', JSON.stringify(logosMap))
} catch (err) {
setLogosError(err)
console.error('Error fetching team logos:', err)
} finally {
setLogosLoading(false)
}
}, [])

useEffect(() => {
fetchMatches()
}, [fetchMatches])
fetchLogos()
}, [fetchMatches, fetchLogos])

return (
<MatchDataContext.Provider
<DataContext.Provider
value={{
matches,
loading,
error,
logos,
loading: loading || logosLoading,
error: error || logosError,
refresh: fetchMatches,
updateMatch,
createMatch
}}
>
{children}
</MatchDataContext.Provider>
</DataContext.Provider>
)
}

export const useMatchData = () => {
const context = useContext(MatchDataContext)
export const useData = () => {
const context = useContext(DataContext)

if (!context) {
throw new Error('useMatchData must be used within a MatchDataProvider')
throw new Error('useData must be used within a MatchDataProvider')
}

const { matches, loading, error, refresh, updateMatch, createMatch } = context
const { matches, logos, loading, error, refresh, updateMatch, createMatch } =
context

useEffect(() => {
refresh()
}, [refresh])

return { matches, loading, error, refresh, updateMatch, createMatch }
return { matches, logos, loading, error, refresh, updateMatch, createMatch }
}
Loading

0 comments on commit fa25496

Please sign in to comment.