Skip to content

Commit 960d1f2

Browse files
authored
style/leaderboard (#173)
* feat(locales): add second and third place translations in multiple languages and improve leaderboard UI with new badges and animations * feat(locales): add new translation keys for last activity and registration date in multiple languages; enhance leaderboard UI with improved rank display and user information layout * feat(leaderboard-item): enhance leaderboard item UI with improved layout and added ClockIcon for last activity time display * feat(leaderboard): implement leaderboard period filtering and enhance date range handling for top workout users * feat(leaderboard): add user leaderboard position component and related actions for fetching user position in leaderboard * fix(Footer.tsx): remove period prop from UserLeaderboardPosition for consistency in usage * feat(leaderboard): add user authentication check and motivational message for users with no workouts * feat(leaderboard): enhance leaderboard page with new header and user info cards for better user engagement * feat(locales): add leaderboard titles and descriptions in multiple languages for improved user experience and localization support * refactor: clean up imports and simplify code structure across multiple files for better readability and maintainability * chore(use-user-position.ts): reorganize imports for better readability and maintainability * refactor(get-user-position.action.ts): remove unused code for counting users ahead to streamline the action logic * fix(locales): update period labels in English, Spanish, French, and Portuguese for consistency and clarity * refactor(leaderboard): extract date range logic into a new utility file for better code organization and reusability * refactor(get-top-workout-users.action.ts): extract date range logic into a separate utility function for better modularity and readability
1 parent a7f75ac commit 960d1f2

File tree

3 files changed

+42
-74
lines changed

3 files changed

+42
-74
lines changed

src/features/leaderboard/actions/get-top-workout-users.action.ts

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,21 @@
11
"use server";
22

33
import { z } from "zod";
4-
import utc from "dayjs/plugin/utc";
5-
import timezone from "dayjs/plugin/timezone";
64
import dayjs from "dayjs";
75

86
import { prisma } from "@/shared/lib/prisma";
97
import { actionClient } from "@/shared/api/safe-actions";
108
import { TopWorkoutUser } from "@/features/leaderboard/models/types";
11-
12-
// Initialize dayjs plugins
13-
dayjs.extend(utc);
14-
dayjs.extend(timezone);
9+
import { getDateRangeForPeriod } from "@/features/leaderboard/lib/utils";
1510

1611
const LIMIT_TOP_USERS = 20;
17-
const PARIS_TZ = "Europe/Paris";
1812

1913
export type LeaderboardPeriod = "all-time" | "weekly" | "monthly";
2014

2115
const inputSchema = z.object({
2216
period: z.enum(["all-time", "weekly", "monthly"]).default("all-time"),
2317
});
2418

25-
function getDateRangeForPeriod(period: LeaderboardPeriod): { startDate: Date | undefined; endDate: Date } {
26-
const now = dayjs().tz(PARIS_TZ);
27-
28-
switch (period) {
29-
case "weekly": {
30-
// Start of current week (Monday) in Paris timezone
31-
const startOfWeek = now.startOf("week").add(1, "day"); // dayjs week starts on Sunday, add 1 for Monday
32-
return {
33-
startDate: startOfWeek.toDate(),
34-
endDate: now.toDate(),
35-
};
36-
}
37-
case "monthly": {
38-
// Start of current month in Paris timezone
39-
const startOfMonth = now.startOf("month");
40-
return {
41-
startDate: startOfMonth.toDate(),
42-
endDate: now.toDate(),
43-
};
44-
}
45-
case "all-time":
46-
default:
47-
return {
48-
startDate: undefined,
49-
endDate: now.toDate(),
50-
};
51-
}
52-
}
53-
5419
export const getTopWorkoutUsersAction = actionClient.schema(inputSchema).action(async ({ parsedInput }) => {
5520
const { period } = parsedInput;
5621

src/features/leaderboard/actions/get-user-position.action.ts

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,16 @@
11
"use server";
22

33
import { z } from "zod";
4-
import utc from "dayjs/plugin/utc";
5-
import timezone from "dayjs/plugin/timezone";
6-
import dayjs from "dayjs";
74

85
import { prisma } from "@/shared/lib/prisma";
96
import { actionClient } from "@/shared/api/safe-actions";
10-
11-
import { LeaderboardPeriod } from "./get-top-workout-users.action";
12-
13-
// Initialize dayjs plugins
14-
dayjs.extend(utc);
15-
dayjs.extend(timezone);
16-
17-
const PARIS_TZ = "Europe/Paris";
7+
import { getDateRangeForPeriod } from "@/features/leaderboard/lib/utils";
188

199
const inputSchema = z.object({
2010
userId: z.string(),
2111
period: z.enum(["all-time", "weekly", "monthly"]).default("all-time"),
2212
});
2313

24-
function getDateRangeForPeriod(period: LeaderboardPeriod): { startDate: Date | undefined; endDate: Date } {
25-
const now = dayjs().tz(PARIS_TZ);
26-
27-
switch (period) {
28-
case "weekly": {
29-
const startOfWeek = now.startOf("week").add(1, "day");
30-
return {
31-
startDate: startOfWeek.toDate(),
32-
endDate: now.toDate(),
33-
};
34-
}
35-
case "monthly": {
36-
const startOfMonth = now.startOf("month");
37-
return {
38-
startDate: startOfMonth.toDate(),
39-
endDate: now.toDate(),
40-
};
41-
}
42-
case "all-time":
43-
default:
44-
return {
45-
startDate: undefined,
46-
endDate: now.toDate(),
47-
};
48-
}
49-
}
50-
5114
export const getUserPositionAction = actionClient.schema(inputSchema).action(async ({ parsedInput }) => {
5215
const { userId, period } = parsedInput;
5316

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import utc from "dayjs/plugin/utc";
2+
import timezone from "dayjs/plugin/timezone";
3+
import dayjs from "dayjs";
4+
5+
// Initialize dayjs plugins
6+
dayjs.extend(utc);
7+
dayjs.extend(timezone);
8+
9+
const PARIS_TZ = "Europe/Paris";
10+
11+
export type LeaderboardPeriod = "all-time" | "weekly" | "monthly";
12+
13+
export function getDateRangeForPeriod(period: LeaderboardPeriod): { startDate: Date | undefined; endDate: Date } {
14+
const now = dayjs().tz(PARIS_TZ);
15+
16+
switch (period) {
17+
case "weekly": {
18+
// Start of current week (Monday) in Paris timezone
19+
const startOfWeek = now.startOf("week").add(1, "day"); // dayjs week starts on Sunday, add 1 for Monday
20+
return {
21+
startDate: startOfWeek.toDate(),
22+
endDate: now.toDate(),
23+
};
24+
}
25+
case "monthly": {
26+
// Start of current month in Paris timezone
27+
const startOfMonth = now.startOf("month");
28+
return {
29+
startDate: startOfMonth.toDate(),
30+
endDate: now.toDate(),
31+
};
32+
}
33+
case "all-time":
34+
default:
35+
return {
36+
startDate: undefined,
37+
endDate: now.toDate(),
38+
};
39+
}
40+
}

0 commit comments

Comments
 (0)