fix: unintended changes in the leaderboard JSON model

This commit is contained in:
sBubshait 2025-08-07 11:15:33 +03:00
parent 8541eb4a6e
commit 5e5c6c7346
3 changed files with 148 additions and 143 deletions

View File

@ -70,10 +70,9 @@ public class PuzzleController {
@GetMapping("/leaderboard")
@Operation(summary = "Get daily leaderboard", description = "Returns leaderboard with 9am cutoff logic (before 9am shows yesterday, from 9am shows today)")
public ResponseEntity<ApiResponse<Map<String, Object>>> getLeaderboard() {
public ResponseEntity<ApiResponse<List<LeaderboardEntry>>> getLeaderboard() {
try {
List<PuzzleAttempt> attempts = puzzleService.getTodaysLeaderboard();
String leaderboardInfo = puzzleService.getLeaderboardDateInfo();
List<LeaderboardEntry> leaderboard = attempts.stream()
.filter(attempt -> attempt.isSolved())
@ -87,12 +86,7 @@ public class PuzzleController {
))
.collect(Collectors.toList());
Map<String, Object> response = Map.of(
"leaderboard", leaderboard,
"dateInfo", leaderboardInfo
);
return ResponseEntity.ok(ApiResponse.success(response));
return ResponseEntity.ok(ApiResponse.success(leaderboard));
} catch (RuntimeException e) {
return ResponseEntity.ok(ApiResponse.error(e.getMessage()));
}

View File

@ -172,15 +172,4 @@ public class PuzzleService {
return puzzleAttemptRepository.findByPuzzleOrderBySubmittedAtAsc(puzzleOpt.get());
}
public String getLeaderboardDateInfo() {
LocalDateTime riyadhNow = getRiyadhNow();
LocalDate leaderboardDate = getLeaderboardDate();
LocalDate today = riyadhNow.toLocalDate();
if (leaderboardDate.equals(today)) {
return "Today's Leaderboard (from 9:00 AM Riyadh time)";
} else {
return "Yesterday's Leaderboard (before 9:00 AM Riyadh time)";
}
}
}

View File

@ -383,142 +383,164 @@ class _WordlePageState extends State<WordlePage> with TickerProviderStateMixin {
child: Container(height: 1, color: Colors.grey[200]),
),
),
body: Column(
children: [
Expanded(
child: Center(
child: Container(
constraints: BoxConstraints(maxWidth: 350),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Game Grid
Container(
padding: EdgeInsets.all(16),
child: Column(
children: List.generate(MAX_ATTEMPTS, (row) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 2),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(WORD_LENGTH, (col) {
bool shouldAnimate =
row == animatingRow &&
gridStates[row][col] !=
LetterState.empty;
body: SafeArea(
child: LayoutBuilder(
builder: (context, constraints) {
double screenHeight = constraints.maxHeight;
double keyboardHeight = (gameWon || gameLost) ? 200 : 200; // Estimated heights
double availableHeight = screenHeight - keyboardHeight;
return Column(
children: [
// Game Grid Section
Expanded(
child: Container(
height: availableHeight,
child: Center(
child: Container(
constraints: BoxConstraints(maxWidth: 350),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Game Grid
Container(
padding: EdgeInsets.all(16),
child: Column(
children: List.generate(MAX_ATTEMPTS, (row) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 2),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(WORD_LENGTH, (col) {
bool shouldAnimate =
row == animatingRow &&
gridStates[row][col] !=
LetterState.empty;
return Container(
margin: EdgeInsets.all(2),
width: 62,
height: 62,
child: shouldAnimate
? AnimatedBuilder(
animation: _tileAnimations[col],
builder: (context, child) {
double scale =
0.8 +
(0.2 *
_tileAnimations[col]
.value);
return Transform.scale(
scale: scale,
child: Container(
width: 62,
height: 62,
decoration: BoxDecoration(
border: Border.all(
color:
_getBorderColor(
return Container(
margin: EdgeInsets.all(2),
width: 62,
height: 62,
child: shouldAnimate
? AnimatedBuilder(
animation: _tileAnimations[col],
builder: (context, child) {
double scale =
0.8 +
(0.2 *
_tileAnimations[col]
.value);
return Transform.scale(
scale: scale,
child: Container(
width: 62,
height: 62,
decoration: BoxDecoration(
border: Border.all(
color:
_getBorderColor(
row,
col,
),
width: 2,
),
color:
_getAnimatedTileColor(
row,
col,
_tileAnimations[col]
.value,
),
borderRadius:
BorderRadius.circular(
4,
),
),
child: Center(
child: Text(
grid[row][col],
style: TextStyle(
fontSize: 32,
fontWeight:
FontWeight.bold,
color: _getAnimatedTextColor(
row,
col,
_tileAnimations[col]
.value,
),
),
),
),
),
);
},
)
: Container(
width: 62,
height: 62,
decoration: BoxDecoration(
border: Border.all(
color: _getBorderColor(
row,
col,
),
width: 2,
),
color: _getTileColor(
row,
col,
),
borderRadius:
BorderRadius.circular(4),
),
child: Center(
child: Text(
grid[row][col],
style: TextStyle(
fontSize: 32,
fontWeight:
FontWeight.bold,
color: _getTextColor(
row,
col,
),
width: 2,
),
color:
_getAnimatedTileColor(
row,
col,
_tileAnimations[col]
.value,
),
borderRadius:
BorderRadius.circular(
4,
),
),
child: Center(
child: Text(
grid[row][col],
style: TextStyle(
fontSize: 32,
fontWeight:
FontWeight.bold,
color: _getAnimatedTextColor(
row,
col,
_tileAnimations[col]
.value,
),
),
),
),
),
);
},
)
: Container(
width: 62,
height: 62,
decoration: BoxDecoration(
border: Border.all(
color: _getBorderColor(
row,
col,
),
width: 2,
),
color: _getTileColor(
row,
col,
),
borderRadius:
BorderRadius.circular(4),
),
child: Center(
child: Text(
grid[row][col],
style: TextStyle(
fontSize: 32,
fontWeight:
FontWeight.bold,
color: _getTextColor(
row,
col,
),
),
),
),
),
);
}),
);
}),
),
);
}),
),
),
);
}),
],
),
),
),
],
),
),
),
),
),
// Keyboard or completion message
Container(
padding: EdgeInsets.all(8),
child: (gameWon || gameLost)
? _buildCompletionMessage()
: _buildKeyboard(),
),
],
// Spacer between grid and keyboard
SizedBox(height: 16),
// Keyboard or completion message section
Container(
constraints: BoxConstraints(
minHeight: 200,
maxHeight: 250,
),
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
child: (gameWon || gameLost)
? _buildCompletionMessage()
: _buildKeyboard(),
),
// Bottom padding to ensure keyboard isn't at the very bottom
SizedBox(height: MediaQuery.of(context).padding.bottom + 8),
],
);
},
),
),
),
),