-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcourseValidation.ts
More file actions
75 lines (60 loc) · 2.19 KB
/
courseValidation.ts
File metadata and controls
75 lines (60 loc) · 2.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import { Course, CourseType } from './types';
const MIN_DAY = 0;
const MAX_DAY = 5;
const MIN_ROW = 0;
const MAX_ROW = 5;
const MIN_WEEK = 1;
const MAX_WEEK = 16;
const isRecord = (value: unknown): value is Record<string, unknown> => {
return typeof value === 'object' && value !== null;
};
const toInt = (value: unknown): number | null => {
const num = typeof value === 'number' ? value : Number(value);
if (!Number.isFinite(num)) return null;
return Math.trunc(num);
};
const normalizeWeeks = (value: unknown): number[] => {
if (!Array.isArray(value)) return [];
const weeks = value
.map(toInt)
.filter((week): week is number => week !== null && week >= MIN_WEEK && week <= MAX_WEEK);
return [...new Set(weeks)].sort((a, b) => a - b);
};
const normalizeType = (value: unknown): CourseType => {
return value === CourseType.SSR ? CourseType.SSR : CourseType.NORMAL;
};
export const normalizeCourse = (value: unknown, fallbackId: string): Course | null => {
if (!isRecord(value)) return null;
const name = typeof value.name === 'string' ? value.name.trim() : '';
const day = toInt(value.day);
const row = toInt(value.row);
const weeks = normalizeWeeks(value.weeks);
if (!name || day === null || row === null || weeks.length === 0) return null;
if (day < MIN_DAY || day > MAX_DAY) return null;
if (row < MIN_ROW || row > MAX_ROW) return null;
const id = typeof value.id === 'string' && value.id.trim() ? value.id : fallbackId;
const color = typeof value.color === 'string' && value.color.trim()
? value.color
: normalizeType(value.type) === CourseType.SSR
? 'bg-rose-100 text-rose-700 border-rose-200'
: 'bg-blue-100 text-blue-700 border-blue-200';
const location = typeof value.location === 'string' && value.location.trim()
? value.location.trim()
: undefined;
return {
id,
name,
day,
row,
weeks,
type: normalizeType(value.type),
color,
location,
};
};
export const normalizeCourses = (value: unknown): Course[] => {
if (!Array.isArray(value)) return [];
return value
.map((item, index) => normalizeCourse(item, `imported-${Date.now()}-${index}`))
.filter((course): course is Course => course !== null);
};