feat(home): implement home summary feature with routes and use case
- Added home routes and corresponding route handler for fetching home summary. - Created GetHomeSummary use case to aggregate user data including groups, attendees, and upcoming payments. - Introduced HomeSummaryDto and related schemas for data validation. - Implemented nextClassOccurrence function to determine the next class based on user timezone. - Added tests for home summary functionality and next class occurrence logic.
This commit is contained in:
62
packages/shared/src/schemas/home.ts
Normal file
62
packages/shared/src/schemas/home.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { z } from 'zod';
|
||||
import { weekdaySchema } from './enums.js';
|
||||
import { paymentStatusSchema } from './payments.js';
|
||||
|
||||
const isoDateTimeSchema = z.string().datetime();
|
||||
|
||||
const timeZoneSchema = z
|
||||
.string()
|
||||
.refine((tz) => {
|
||||
try {
|
||||
new Intl.DateTimeFormat('en-US', { timeZone: tz });
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}, 'Zona horaria IANA inválida');
|
||||
|
||||
export const HomeStatsSchema = z.object({
|
||||
groups: z.number().int().nonnegative(),
|
||||
attendees: z.number().int().nonnegative(),
|
||||
pendingPayments: z.number().int().nonnegative(),
|
||||
pendingAmount: z.number().nonnegative(),
|
||||
});
|
||||
export type HomeStats = z.output<typeof HomeStatsSchema>;
|
||||
|
||||
export const NextClassSchema = z.object({
|
||||
groupId: z.string(),
|
||||
name: z.string(),
|
||||
days: z.array(weekdaySchema).nullable(),
|
||||
time: z.string().nullable(),
|
||||
occurrenceAt: isoDateTimeSchema,
|
||||
isNow: z.boolean(),
|
||||
});
|
||||
export type NextClass = z.output<typeof NextClassSchema>;
|
||||
|
||||
export const UpcomingPaymentSchema = z.object({
|
||||
id: z.string(),
|
||||
amount: z.coerce.number().positive(),
|
||||
currency: z.string(),
|
||||
dueDate: isoDateTimeSchema,
|
||||
status: paymentStatusSchema,
|
||||
groupName: z.string(),
|
||||
attendeeName: z.string(),
|
||||
});
|
||||
export type UpcomingPayment = z.output<typeof UpcomingPaymentSchema>;
|
||||
|
||||
export const HomeSummarySchema = z.object({
|
||||
stats: HomeStatsSchema,
|
||||
nextClass: NextClassSchema.nullable(),
|
||||
upcomingPayments: z.array(UpcomingPaymentSchema),
|
||||
});
|
||||
export type HomeSummary = z.output<typeof HomeSummarySchema>;
|
||||
|
||||
export type HomeSummaryDto = HomeSummary;
|
||||
export type HomeStatsDto = HomeStats;
|
||||
export type NextClassDto = NextClass;
|
||||
export type UpcomingPaymentDto = UpcomingPayment;
|
||||
|
||||
export const HomeQuerySchema = z.object({
|
||||
timeZone: timeZoneSchema.optional(),
|
||||
});
|
||||
export type HomeQuery = z.output<typeof HomeQuerySchema>;
|
||||
Reference in New Issue
Block a user