diff --git a/frontend/src/pages/History.jsx b/frontend/src/pages/History.jsx
index de2b58c..5db64bf 100644
--- a/frontend/src/pages/History.jsx
+++ b/frontend/src/pages/History.jsx
@@ -1,9 +1,9 @@
-import React, { useState, useEffect, useCallback, useRef } from 'react';
+import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
import { useToast } from '../components/Toast';
import api from '../api/axios';
-import { formatLocalDate, isSunday } from '../utils/dateUtils';
+import { formatDayHeader, formatTimeOnly, getLocalDateKey, isSunday } from '../utils/dateUtils';
import { prefixKey } from '../utils/adminPrefs';
function History() {
@@ -150,6 +150,23 @@ function History() {
}
};
+ const groupedSessions = useMemo(() => {
+ const groups = [];
+ let currentKey = null;
+
+ sessions.forEach(session => {
+ const dateKey = getLocalDateKey(session.created_at);
+ if (dateKey !== currentKey) {
+ currentKey = dateKey;
+ groups.push({ dateKey, sessions: [session] });
+ } else {
+ groups[groups.length - 1].sessions.push(session);
+ }
+ });
+
+ return groups;
+ }, [sessions]);
+
if (loading) {
return (
@@ -220,109 +237,134 @@ function History() {
No sessions found
) : (
- {sessions.map(session => {
- const isActive = session.is_active === 1;
- const isSelected = selectedIds.has(session.id);
- const isSundaySession = isSunday(session.created_at);
- const isArchived = session.archived === 1;
- const canSelect = selectMode && !isActive;
+ {groupedSessions.map((group, groupIdx) => {
+ const isSundayGroup = isSunday(group.sessions[0].created_at);
+ const isContinued = groupIdx === 0 && page > 1 && prevLastDate &&
+ getLocalDateKey(prevLastDate) === group.dateKey;
return (
-
{
- if (longPressFired.current) {
- longPressFired.current = false;
- return;
- }
- if (selectMode) {
- if (!isActive) toggleSelection(session.id);
- } else {
- navigate(`/history/${session.id}`);
- }
- }}
- onPointerDown={() => {
- if (!isActive) handlePointerDown(session.id);
- }}
- onPointerUp={handlePointerUp}
- onPointerLeave={handlePointerUp}
- >
-
-
- {selectMode && (
-
- {isSelected && (
- โ
- )}
-
+
+ {/* Day header bar */}
+
+
+
+ {formatDayHeader(group.sessions[0].created_at)}
+
+ {isContinued && (
+
(continued)
)}
-
-
-
-
- Session #{session.id}
-
- {isActive && (
-
- Active
-
- )}
- {isSundaySession && (
-
- ๐ฒ Game Night
-
- )}
- {isArchived && (filter === 'all' || filter === 'archived') && (
-
- Archived
-
- )}
-
-
- {session.games_played} game{session.games_played !== 1 ? 's' : ''}
-
-
-
- {formatLocalDate(session.created_at)}
- {isSundaySession && (
- ยท Sunday
- )}
-
- {session.has_notes && session.notes_preview && (
-
- {session.notes_preview}
-
+
+ {!isContinued && (
+
+
+ {group.sessions.length} session{group.sessions.length !== 1 ? 's' : ''}
+
+ {isSundayGroup && (
+ ๐ฒ Game Night
)}
-
+ )}
- {!selectMode && isAuthenticated && isActive && (
-
-
-
- )}
+ {/* Session cards under this day */}
+
+ {group.sessions.map(session => {
+ const isActive = session.is_active === 1;
+ const isSelected = selectedIds.has(session.id);
+ const isArchived = session.archived === 1;
+
+ return (
+
{
+ if (longPressFired.current) {
+ longPressFired.current = false;
+ return;
+ }
+ if (selectMode) {
+ if (!isActive) toggleSelection(session.id);
+ } else {
+ navigate(`/history/${session.id}`);
+ }
+ }}
+ onPointerDown={() => {
+ if (!isActive) handlePointerDown(session.id);
+ }}
+ onPointerUp={handlePointerUp}
+ onPointerLeave={handlePointerUp}
+ >
+
+
+ {selectMode && (
+
+ {isSelected && (
+ โ
+ )}
+
+ )}
+
+
+
+
+ Session #{session.id}
+
+ {isActive && (
+
+ Active
+
+ )}
+ {isArchived && (filter === 'all' || filter === 'archived') && (
+
+ Archived
+
+ )}
+
+
+ {session.games_played} game{session.games_played !== 1 ? 's' : ''}
+
+
+
+ {formatTimeOnly(session.created_at)}
+
+ {session.has_notes && session.notes_preview && (
+
+ {session.notes_preview}
+
+ )}
+
+
+
+
+ {!selectMode && isAuthenticated && isActive && (
+
+
+
+ )}
+
+ );
+ })}
+
);
})}