Add per-route top-10 leaderboard to activity detail
New /activities/{id}/route-leaderboard endpoint ranks the user's timed
efforts on the same route; frontend RouteLeaderboard card sits beside
Laps, showing this activity's time/rank/gap and the top 10 (current
effort highlighted green, also surfaced if outside the top 10).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@ import MetricTimeline from '../components/activity/MetricTimeline'
|
||||
import HRZoneBar from '../components/activity/HRZoneBar'
|
||||
import LapTable from '../components/activity/LapTable'
|
||||
import SegmentsPanel from '../components/activity/SegmentsPanel'
|
||||
import RouteLeaderboard from '../components/activity/RouteLeaderboard'
|
||||
import StatCard from '../components/ui/StatCard'
|
||||
import {
|
||||
formatDuration, formatDistance, formatPace, formatElevation,
|
||||
@@ -74,6 +75,12 @@ export default function ActivityDetailPage() {
|
||||
enabled: !!activity?.named_route_id,
|
||||
})
|
||||
|
||||
const { data: routeBoard } = useQuery({
|
||||
queryKey: ['route-leaderboard', id],
|
||||
queryFn: () => api.get(`/activities/${id}/route-leaderboard`).then(r => r.data),
|
||||
enabled: !!activity?.named_route_id,
|
||||
})
|
||||
|
||||
const handleMapClick = ({ lat, lng }) => {
|
||||
if (!segCreate || !dataPoints) return
|
||||
const dist = nearestDistance(dataPoints, lat, lng)
|
||||
@@ -293,8 +300,8 @@ export default function ActivityDetailPage() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Laps + Segments side by side */}
|
||||
{((laps && laps.length > 0) || (actSegments && actSegments.length > 0)) && (
|
||||
{/* Laps + Route leaderboard + Segments side by side */}
|
||||
{((laps && laps.length > 0) || (actSegments && actSegments.length > 0) || (routeBoard && routeBoard.top?.length > 0)) && (
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||
{laps && laps.length > 0 && (
|
||||
<div className="bg-gray-900 rounded-xl border border-gray-800 p-4">
|
||||
@@ -302,6 +309,12 @@ export default function ActivityDetailPage() {
|
||||
<LapTable laps={laps} sportType={activity.sport_type} lapBests={lapBests} />
|
||||
</div>
|
||||
)}
|
||||
{routeBoard && routeBoard.top?.length > 0 && (
|
||||
<div className="bg-gray-900 rounded-xl border border-gray-800 p-4">
|
||||
<h3 className="text-sm font-medium text-gray-300 mb-3">Route — Top 10 Times</h3>
|
||||
<RouteLeaderboard data={routeBoard} />
|
||||
</div>
|
||||
)}
|
||||
{actSegments && actSegments.length > 0 && (
|
||||
<div className="bg-gray-900 rounded-xl border border-gray-800 p-4">
|
||||
<h3 className="text-sm font-medium text-gray-300 mb-3">Segments</h3>
|
||||
|
||||
Reference in New Issue
Block a user