mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 10:42:57 +00:00
262 lines
8.9 KiB
Markdown
262 lines
8.9 KiB
Markdown
# Matches Page Enhancements
|
|
|
|
## Overview
|
|
Enhanced the Matches page (`MatchesPage.tsx`) with sorting functionality, improved date handling, countdown display, enhanced status badges, Czech date formatting, and "Všechny kategorie" tab showing all matches.
|
|
|
|
## Changes Made
|
|
|
|
### 1. **Sort Functionality**
|
|
- ✅ Added date sorting: **oldest to newest by default**
|
|
- ✅ Added toggle button at the top to switch between:
|
|
- **"Nejstarší první"** (Oldest first) - ascending order
|
|
- **"Nejnovější první"** (Newest first) - descending order
|
|
- ✅ Visual indicator (icon) shows current sort direction
|
|
- ✅ Smooth transitions and hover effects on the sort button
|
|
|
|
### 2. **Enhanced Date Handling**
|
|
- ✅ Improved date comparison logic using `Date.now()` consistently
|
|
- ✅ Added explicit `currentTime` variable for accurate comparisons
|
|
- ✅ Fixed future/past match detection
|
|
- ✅ Better handling of match states: future, past, and finished
|
|
|
|
### 3. **Countdown Display**
|
|
- ✅ Countdown automatically shows for upcoming matches
|
|
- ✅ Updates every 30 seconds (configurable)
|
|
- ✅ Format: "Začátek za" + countdown time
|
|
- ✅ Shows days/hours, hours/minutes, or minutes based on time remaining
|
|
- ✅ Orange color (#f97316) for visual emphasis
|
|
|
|
### 4. **Enhanced Status Badges**
|
|
All status badges now feature:
|
|
- Gradient backgrounds
|
|
- Better visual hierarchy
|
|
- Consistent padding and styling
|
|
- Box shadows for depth
|
|
|
|
**Status Types:**
|
|
1. **✓ Skončeno** (Finished) - Green gradient
|
|
- Shown when match has a score
|
|
- `linear-gradient(135deg, #10b981 0%, #059669 100%)`
|
|
|
|
2. **Odehráno** (Played) - Gray gradient
|
|
- NEW: Shows for past matches without scores
|
|
- `linear-gradient(135deg, #6b7280 0%, #4b5563 100%)`
|
|
|
|
3. **Nadcházející** (Upcoming) - Blue gradient
|
|
- Shown for future matches without countdown
|
|
- `linear-gradient(135deg, #3b82f6 0%, #2563eb 100%)`
|
|
|
|
### 5. **Czech Date Formatting**
|
|
- ✅ Dates now display in Czech format: **DD.MM.YYYY**
|
|
- ✅ Uses `toLocaleDateString('cs-CZ')` for proper localization
|
|
- ✅ Consistent date formatting across all match cards
|
|
|
|
### 6. **"Všechny kategorie" Tab**
|
|
- ✅ NEW: Added as the first tab
|
|
- ✅ Shows all matches from all competitions combined
|
|
- ✅ Matches sorted by date (respects sort order setting)
|
|
- ✅ Each match shows its competition name below the venue
|
|
- ✅ Automatically updates when competitions load
|
|
|
|
### 7. **Smart Match Score Handling**
|
|
- ✅ CRITICAL FIX: Future matches no longer show score even if API data exists
|
|
- ✅ Checks match timestamp against current time during data loading
|
|
- ✅ Sets score to `null` **ONLY for future matches**
|
|
- ✅ **Past matches keep their scores** from the API
|
|
- ✅ Ensures countdown always displays for upcoming matches instead of bogus scores
|
|
|
|
### 8. **Code Improvements**
|
|
- Added `sortAscending` state to track sort order
|
|
- Created `sortedCompetitions` memoized value for efficient sorting
|
|
- Added `formatCzechDate()` helper function
|
|
- Removed inline sort logic from data fetching
|
|
- Better separation of concerns
|
|
- Improved performance with useMemo
|
|
- Added location emoji (📍) to venue display
|
|
|
|
## Technical Details
|
|
|
|
### Key State Changes
|
|
```typescript
|
|
const [sortAscending, setSortAscending] = useState<boolean>(true); // true = oldest first
|
|
```
|
|
|
|
### Sorting Logic
|
|
```typescript
|
|
const sortedCompetitions = useMemo(() => {
|
|
return facrCompetitions.map(comp => ({
|
|
...comp,
|
|
matches: [...comp.matches].sort((a: any, b: any) => {
|
|
const aTime = new Date(`${a.date}T${(a.time || '00:00')}:00`).getTime();
|
|
const bTime = new Date(`${b.date}T${(b.time || '00:00')}:00`).getTime();
|
|
return sortAscending ? aTime - bTime : bTime - aTime;
|
|
})
|
|
}));
|
|
}, [facrCompetitions, sortAscending]);
|
|
```
|
|
|
|
### Match State Detection
|
|
```typescript
|
|
const matchTime = new Date(`${m.date}T${(m.time || '00:00')}:00`).getTime();
|
|
const currentTime = Date.now();
|
|
const isFuture = matchTime > currentTime;
|
|
const isPast = matchTime < currentTime;
|
|
const hasScore = m.score && m.score.trim() !== '';
|
|
```
|
|
|
|
### Smart Score Handling (Future vs Past)
|
|
```typescript
|
|
// In data loading - prevent ONLY future matches from showing scores
|
|
const matchTime = new Date(`${isoDate}T${time}:00`).getTime();
|
|
const isFutureMatch = matchTime > Date.now();
|
|
const actualScore = isFutureMatch ? null : m.score;
|
|
|
|
// Logic breakdown:
|
|
// - If match is in FUTURE → set score to null (show countdown instead)
|
|
// - If match is in PAST → keep score from API (show actual result)
|
|
```
|
|
|
|
### Czech Date Formatting
|
|
```typescript
|
|
const formatCzechDate = (dateStr: string, timeStr: string) => {
|
|
try {
|
|
const date = new Date(`${dateStr}T${timeStr}:00`);
|
|
return date.toLocaleDateString('cs-CZ', {
|
|
day: 'numeric',
|
|
month: 'numeric',
|
|
year: 'numeric'
|
|
});
|
|
} catch {
|
|
return dateStr;
|
|
}
|
|
};
|
|
```
|
|
|
|
### All Categories Tab
|
|
```typescript
|
|
// Add "Všechny kategorie" as first tab with all matches combined
|
|
if (sorted.length > 0) {
|
|
const allMatches = sorted.flatMap(comp =>
|
|
comp.matches.map(m => ({ ...m, competitionName: comp.name }))
|
|
);
|
|
allMatches.sort((a: any, b: any) => {
|
|
const aTime = new Date(`${a.date}T${(a.time || '00:00')}:00`).getTime();
|
|
const bTime = new Date(`${b.date}T${(b.time || '00:00')}:00`).getTime();
|
|
return sortAscending ? aTime - bTime : bTime - aTime;
|
|
});
|
|
|
|
return [
|
|
{
|
|
name: 'Všechny kategorie',
|
|
matches: allMatches,
|
|
matches_link: undefined
|
|
},
|
|
...sorted
|
|
];
|
|
}
|
|
```
|
|
|
|
## User Interface
|
|
|
|
### Sort Button
|
|
- Located at the top right, next to the page title
|
|
- Shows icon indicating current sort direction
|
|
- Smooth hover animation
|
|
- Uses primary brand color
|
|
- Responsive design
|
|
|
|
### Match Cards
|
|
Each match card now displays:
|
|
1. **Date and time** at the top (Czech format: DD.MM.YYYY)
|
|
2. **Home team** logo and name
|
|
3. **Score OR countdown** (for upcoming matches - prioritizes countdown)
|
|
4. **Away team** logo and name
|
|
5. **Venue** with location emoji 📍 (if available)
|
|
6. **Competition name** (only on "Všechny kategorie" tab)
|
|
7. **Status badge** at the bottom
|
|
|
|
## Testing Recommendations
|
|
|
|
1. **"Všechny kategorie" Tab**
|
|
- Verify it appears as the first tab
|
|
- Check all matches from all competitions are shown
|
|
- Confirm competition names appear below venue
|
|
- Test sorting works on this tab
|
|
|
|
2. **Sort Functionality**
|
|
- Click the sort button and verify order changes
|
|
- Check that all tabs maintain their individual sort order
|
|
- Verify icon changes with sort direction
|
|
|
|
3. **Future Match Handling** ⚠️ CRITICAL
|
|
- **Test with future matches that have score data**
|
|
- Verify countdown displays instead of score
|
|
- Confirm "Nadcházející" status shows
|
|
- Example: Match on 10/12/2025 should show countdown, NOT 0:0 score
|
|
|
|
4. **Countdown Display**
|
|
- Check upcoming matches show countdown
|
|
- Verify countdown updates (wait 30 seconds)
|
|
- Test with matches at different time ranges (days, hours, minutes)
|
|
|
|
5. **Czech Date Format**
|
|
- Verify dates display as DD.MM.YYYY (e.g., 12.10.2025)
|
|
- Check consistency across all match cards
|
|
|
|
6. **Status Badges**
|
|
- Verify finished matches show "✓ Skončeno"
|
|
- Check past matches without scores show "Odehráno"
|
|
- Confirm future matches show "Nadcházející"
|
|
|
|
7. **Date Accuracy**
|
|
- Verify matches transition from future to past correctly
|
|
- Check timezone handling
|
|
- Test with matches around midnight
|
|
|
|
## Browser Compatibility
|
|
|
|
- Modern browsers (Chrome, Firefox, Safari, Edge)
|
|
- Uses standard JavaScript Date API
|
|
- CSS gradients supported in all modern browsers
|
|
- SVG icons for sort button
|
|
|
|
## Performance
|
|
|
|
- Sorting is memoized to prevent unnecessary recalculations
|
|
- Countdown updates optimized to 30-second intervals
|
|
- No performance impact on large match lists
|
|
|
|
## Bug Fixes
|
|
|
|
### Critical Bug Fixed: Future Matches Showing Score
|
|
**Problem:** Matches scheduled in the future (e.g., 10/12/2025 at 15:00) were displaying scores (e.g., 0:0) and "Skončeno" status even though they hadn't been played yet.
|
|
|
|
**Root Cause:** Score data from API was being displayed without checking if the match had actually occurred.
|
|
|
|
**Solution:**
|
|
1. Added time check during data loading: `matchTime > Date.now()`
|
|
2. Set score to `null` **ONLY for matches in the future**
|
|
3. **Past matches keep their actual scores** from the API
|
|
4. Changed display logic to prioritize countdown for future matches
|
|
5. Now correctly shows countdown and "Nadcházející" status for future matches
|
|
6. Past matches correctly show their scores and "✓ Skončeno" status
|
|
|
|
**Important:** This fix does NOT remove scores from past matches - it only prevents future matches from showing scores they shouldn't have yet.
|
|
|
|
## Future Enhancements
|
|
|
|
Potential improvements:
|
|
- Add filter by date range
|
|
- Add search functionality
|
|
- Add competition-specific sorting preferences
|
|
- Export matches to calendar
|
|
- Share individual match cards
|
|
- Add match notifications/reminders
|
|
|
|
---
|
|
|
|
**Date:** 2025-10-11 (Updated: 15:54)
|
|
**File Modified:** `frontend/src/pages/MatchesPage.tsx`
|
|
**Status:** ✅ Complete
|
|
**Critical Fix:** ✅ Future match countdown issue resolved
|