fix
This commit is contained in:
+17
@@ -1533,6 +1533,23 @@ function allowedApiTarget(req) {
|
||||
return url
|
||||
}
|
||||
|
||||
if (pathname === '/api/tss/teams/search') {
|
||||
const keys = [...params.keys()]
|
||||
const query = params.get('q') || params.get('name') || ''
|
||||
const limit = Number(params.get('limit') || 10)
|
||||
if (
|
||||
keys.some((key) => !['q', 'name', 'limit'].includes(key)) ||
|
||||
query.length < 2 ||
|
||||
query.length > MAX_TEAM_NAME_LENGTH ||
|
||||
!Number.isInteger(limit) ||
|
||||
limit < 1 ||
|
||||
limit > 20
|
||||
) {
|
||||
return null
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
const teamMatch = pathname.match(/^\/api\/tss\/teams\/([^/]+)(?:\/(history|games))?$/)
|
||||
if (!teamMatch || [...params.keys()].length) return null
|
||||
|
||||
|
||||
+27
-4
@@ -19,6 +19,7 @@ const apiEndpoints = {
|
||||
teams: '/api/tss/leaderboard/teams?limit=100',
|
||||
teamsHealth: '/api/tss/leaderboard/teams?limit=1',
|
||||
resolve: (name) => `/api/tss/teams/resolve?name=${encodeURIComponent(name)}`,
|
||||
searchTeams: (name) => `/api/tss/teams/search?q=${encodeURIComponent(name)}&limit=10`,
|
||||
detail: (name) => `/api/tss/teams/${encodeURIComponent(name)}`,
|
||||
history: (name) => `/api/tss/teams/${encodeURIComponent(name)}/history`,
|
||||
games: (name) => `/api/tss/teams/${encodeURIComponent(name)}/games`,
|
||||
@@ -547,6 +548,7 @@ function AppContent() {
|
||||
const [showFloatingNav, setShowFloatingNav] = useState(() => window.scrollY > 40)
|
||||
const [teamQuery, setTeamQuery] = useState('')
|
||||
const [searchHint, setSearchHint] = useState({ status: 'idle', name: '' })
|
||||
const [teamSearchResults, setTeamSearchResults] = useState([])
|
||||
const [profile, setProfile] = useState({
|
||||
teamName: '',
|
||||
detail: { status: 'idle', data: null, error: null },
|
||||
@@ -733,22 +735,42 @@ function AppContent() {
|
||||
const query = teamQuery.trim()
|
||||
if (query.length < 2) {
|
||||
setSearchHint({ status: 'idle', name: '' })
|
||||
setTeamSearchResults([])
|
||||
return
|
||||
}
|
||||
|
||||
const controller = new AbortController()
|
||||
const timer = window.setTimeout(() => {
|
||||
setSearchHint({ status: 'loading', name: '' })
|
||||
fetchJson(apiEndpoints.resolve(query), controller.signal)
|
||||
fetchJson(apiEndpoints.searchTeams(query), controller.signal)
|
||||
.then((data) => {
|
||||
const name = data.tag_name || data.short_name || data.long_name || query
|
||||
setSearchHint({ status: 'ready', name })
|
||||
const results = (data.teams || data.results || [])
|
||||
.map((team) => ({
|
||||
name: bestTeamName(team),
|
||||
detail: team.long_name || team.short_name || '',
|
||||
aliases: [team.tag_name, team.short_name, team.long_name].filter(Boolean),
|
||||
}))
|
||||
.filter((team) => team.name)
|
||||
.slice(0, 10)
|
||||
setTeamSearchResults(results)
|
||||
setSearchHint(results.length ? { status: 'ready', name: results[0].name } : { status: 'error', name: '' })
|
||||
})
|
||||
.catch(() => {
|
||||
if (!controller.signal.aborted) {
|
||||
fetchJson(apiEndpoints.resolve(query), controller.signal)
|
||||
.then((data) => {
|
||||
const name = data.tag_name || data.short_name || data.long_name || ''
|
||||
setTeamSearchResults(name ? [{ name, detail: data.long_name || data.short_name || '', aliases: [name] }] : [])
|
||||
setSearchHint(name ? { status: 'ready', name } : { status: 'error', name: '' })
|
||||
})
|
||||
.catch(() => {
|
||||
if (!controller.signal.aborted) {
|
||||
setTeamSearchResults([])
|
||||
setSearchHint({ status: 'error', name: '' })
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}, 350)
|
||||
|
||||
return () => {
|
||||
@@ -1060,7 +1082,7 @@ function AppContent() {
|
||||
}, [route.page, route.teamName])
|
||||
|
||||
const topTeamName = bestTeamName(teams[0])
|
||||
const teamSuggestions = useMemo(() => {
|
||||
const localTeamSuggestions = useMemo(() => {
|
||||
const query = teamQuery.trim().toLowerCase()
|
||||
const seen = new Set()
|
||||
|
||||
@@ -1078,6 +1100,7 @@ function AppContent() {
|
||||
})
|
||||
.slice(0, 10)
|
||||
}, [teamQuery, teams])
|
||||
const teamSuggestions = teamSearchResults.length ? teamSearchResults : localTeamSuggestions
|
||||
const searchPlaceholder =
|
||||
searchHint.status === 'ready'
|
||||
? `Found ${searchHint.name}`
|
||||
|
||||
@@ -92,6 +92,20 @@ function isAllowedApiUrl(req) {
|
||||
return keys.every((key) => key === 'name') && name.length >= 2 && name.length <= MAX_TEAM_NAME_LENGTH
|
||||
}
|
||||
|
||||
if (url.pathname === '/api/tss/teams/search') {
|
||||
const keys = [...params.keys()]
|
||||
const query = params.get('q') || params.get('name') || ''
|
||||
const limit = Number(params.get('limit') || 10)
|
||||
return (
|
||||
keys.every((key) => ['q', 'name', 'limit'].includes(key)) &&
|
||||
query.length >= 2 &&
|
||||
query.length <= MAX_TEAM_NAME_LENGTH &&
|
||||
Number.isInteger(limit) &&
|
||||
limit >= 1 &&
|
||||
limit <= 20
|
||||
)
|
||||
}
|
||||
|
||||
if ([...params.keys()].length) return false
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user