feat: Enhance session handling in timetable and UI

- Introduced session types (exams, credits, consultations, coursework defenses) with distinct icons and colors for better visibility in the UI.
- Updated PlansScreen, ScheduleScreen, and WeekGrid to display session information appropriately.
- Modified CalendarView and PlansView to include session indicators in the calendar and plans.
- Enhanced LessonCard and CompactLesson to show session details and adjust styling based on session presence.
- Added new SessionMark component for consistent session representation across Android and iOS.
- Updated server logic to handle session entries from external documents, ensuring accurate timetable representation.
- Improved date parsing to accommodate session-related dates in various formats.
- Added tests to verify session handling and date parsing functionality.
This commit is contained in:
2026-10-19 20:49:13 +03:00
parent db9a3f8243
commit 15851b26cd
21 changed files with 421 additions and 42 deletions

View File

@@ -47,10 +47,24 @@ export function parseWeekRanges(condition) {
}
/** "10 сентября, 15 октября" → ISO dates inside the academic year that starts in `year`. */
/**
* A list of numeric dates, "10.09;15.10;19.11;17.12" or "03.10, 17.10": at least two, so a
* time such as "10.05" on its own is never taken for 10 May.
*/
export const DATE_LIST = /(?<![\d.:])\d{1,2}\.\d{1,2}(?:\.(?:\d{4}|\d{2}))?(?:\s*[;,]\s*\d{1,2}\.\d{1,2}(?:\.(?:\d{4}|\d{2}))?)+\.?(?![\d:])/gu;
export function parseTextDates(raw, year) {
if (!raw || !year) return [];
const pattern = new RegExp(`(\\d{1,2})\\s+(${MONTHS.join("|")})[а-я]*`, "giu");
const dates = [];
for (const list of raw.matchAll(DATE_LIST))
for (const m of list[0].matchAll(/(\d{1,2})\.(\d{1,2})(?:\.(\d{4}|\d{2}))?/g)) {
const day = Number(m[1]),
month = Number(m[2]);
if (day < 1 || day > 31 || month < 1 || month > 12) continue;
const y = m[3] ? Number(m[3].length === 2 ? `20${m[3]}` : m[3]) : month >= 8 ? Number(year) : Number(year) + 1;
dates.push(`${y}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`);
}
for (const m of raw.matchAll(pattern)) {
const month =
MONTHS.findIndex((stem) => new RegExp(`^${stem}`, "iu").test(m[2])) + 1;