feat: redesign day picker with expandable calendar, status markers & Playwright E2E testing
- Replace modal calendar with inline expandable calendar widget integrated into the day picker. - Add status indicator dots (attended/absent/pending) to month calendar grid matching day picker. - Disable and gray out weekend days in calendar when weekend schedule is turned off. - Redesign extend bar with integrated handle that aligns with the palette. - Remove start-to-end timing on Today screen's class time rail, showing only start time. - Implement Playwright E2E and visual testing suite with multi-screen capture scripts. - Add cascade DELETE endpoints for subjects and versioned recurring timetable entries.
This commit is contained in:
36
lib/date.ts
36
lib/date.ts
@@ -1,3 +1,17 @@
|
||||
// Pre-instantiated Intl formatters hoisted to module scope (per js-hoist-intl best practice)
|
||||
const dayHeadingFormatter = new Intl.DateTimeFormat(undefined, { weekday: 'long', month: 'long', day: 'numeric' });
|
||||
const monthDayFormatter = new Intl.DateTimeFormat(undefined, { month: 'long', day: 'numeric' });
|
||||
const sessionDateFormatter = new Intl.DateTimeFormat(undefined, { weekday: 'short', month: 'short', day: 'numeric' });
|
||||
const weekdayNarrowFormatter = new Intl.DateTimeFormat(undefined, { weekday: 'narrow' });
|
||||
const weekdayLongFormatter = new Intl.DateTimeFormat(undefined, { weekday: 'long' });
|
||||
const monthYearFormatter = new Intl.DateTimeFormat(undefined, { month: 'long', year: 'numeric' });
|
||||
const monthShortDayFormatter = new Intl.DateTimeFormat(undefined, { month: 'short', day: 'numeric' });
|
||||
const yearFormatter = new Intl.DateTimeFormat(undefined, { year: 'numeric' });
|
||||
const timeShortFormatter = new Intl.DateTimeFormat(undefined, { hour: 'numeric', minute: '2-digit' });
|
||||
const headerDateFormatter = new Intl.DateTimeFormat(undefined, { weekday: 'long', month: 'short', day: 'numeric' });
|
||||
|
||||
const weekdayShortFormatter = new Intl.DateTimeFormat(undefined, { weekday: 'short' });
|
||||
|
||||
export const dateKey = (date: Date) => `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
|
||||
|
||||
export const addDays = (date: Date, amount: number) => {
|
||||
@@ -10,11 +24,27 @@ export const mondayOfWeek = (date: Date) => addDays(date, -((date.getDay() + 6)
|
||||
|
||||
export const dateFromKey = (value: string) => new Date(`${value}T12:00:00`);
|
||||
|
||||
export const formatDayHeading = (date: Date) => new Intl.DateTimeFormat(undefined, { weekday: 'long', month: 'long', day: 'numeric' }).format(date);
|
||||
export const formatDayHeading = (date: Date) => dayHeadingFormatter.format(date);
|
||||
|
||||
export const formatMonthDay = (date: Date) => new Intl.DateTimeFormat(undefined, { month: 'long', day: 'numeric' }).format(date);
|
||||
export const formatMonthDay = (date: Date) => monthDayFormatter.format(date);
|
||||
|
||||
export const formatSessionDate = (value: string) => new Intl.DateTimeFormat(undefined, { weekday: 'short', month: 'short', day: 'numeric' }).format(dateFromKey(value));
|
||||
export const formatSessionDate = (value: string) => sessionDateFormatter.format(dateFromKey(value));
|
||||
|
||||
export const formatWeekdayNarrow = (date: Date) => weekdayNarrowFormatter.format(date);
|
||||
|
||||
export const formatWeekdayShort = (date: Date) => weekdayShortFormatter.format(date);
|
||||
|
||||
export const formatWeekdayLong = (date: Date) => weekdayLongFormatter.format(date);
|
||||
|
||||
export const formatMonthYear = (date: Date) => monthYearFormatter.format(date);
|
||||
|
||||
export const formatMonthShortDay = (date: Date) => monthShortDayFormatter.format(date);
|
||||
|
||||
export const formatYear = (date: Date) => yearFormatter.format(date);
|
||||
|
||||
export const formatCurrentTime = (date = new Date()) => timeShortFormatter.format(date);
|
||||
|
||||
export const formatHeaderDate = (date: Date) => headerDateFormatter.format(date);
|
||||
|
||||
export const currentMinutes = () => {
|
||||
const now = new Date();
|
||||
|
||||
Reference in New Issue
Block a user