import type { Course, CourseLevel, Lesson } from "@/types/course"; const STORAGE_KEY = "acve.teacher-courses.v1"; const TEACHER_UPDATED_EVENT = "acve:teacher-courses-updated"; export type TeacherCourseInput = { title: string; level: CourseLevel; summary: string; instructor: string; weeks: number; }; export type TeacherCoursePatch = Partial> & { summary?: string; title?: string; level?: CourseLevel; instructor?: string; weeks?: number; }; const isBrowser = () => typeof window !== "undefined"; const readStore = (): Course[] => { if (!isBrowser()) return []; const raw = window.localStorage.getItem(STORAGE_KEY); if (!raw) return []; try { return JSON.parse(raw) as Course[]; } catch { return []; } }; const writeStore = (courses: Course[]) => { if (!isBrowser()) return; window.localStorage.setItem(STORAGE_KEY, JSON.stringify(courses)); window.dispatchEvent(new Event(TEACHER_UPDATED_EVENT)); }; const slugify = (value: string) => value .toLowerCase() .trim() .replace(/[^a-z0-9\s-]/g, "") .replace(/\s+/g, "-") .replace(/-+/g, "-"); const lessonId = (index: number) => `lesson-${index}`; const normalizeCourse = (course: Course): Course => ({ ...course, lessonsCount: course.lessons.length, }); export const teacherCoursesUpdatedEventName = TEACHER_UPDATED_EVENT; export const getTeacherCourses = (): Course[] => readStore().map(normalizeCourse); export const getTeacherCourseBySlug = (slug: string): Course | undefined => getTeacherCourses().find((course) => course.slug === slug); export const ensureUniqueTeacherCourseSlug = (title: string, reservedSlugs: string[]) => { const baseSlug = slugify(title) || "untitled-course"; let slug = baseSlug; let index = 2; const pool = new Set(reservedSlugs.map((item) => item.toLowerCase())); while (pool.has(slug.toLowerCase())) { slug = `${baseSlug}-${index}`; index += 1; } return slug; }; export const createTeacherCourse = (input: TeacherCourseInput, reservedSlugs: string[]) => { const courses = getTeacherCourses(); const slug = ensureUniqueTeacherCourseSlug(input.title, reservedSlugs); const starterLesson: Lesson = { id: lessonId(1), title: "Course introduction", type: "video", minutes: 8, isPreview: true, videoUrl: "https://example.com/video-placeholder", }; const next: Course = { slug, title: input.title, level: input.level, summary: input.summary, rating: 5, weeks: Math.max(1, input.weeks), lessonsCount: 1, students: 0, instructor: input.instructor, lessons: [starterLesson], }; writeStore([...courses, next]); return next; }; export const updateTeacherCourse = (slug: string, patch: TeacherCoursePatch) => { const courses = getTeacherCourses(); const nextCourses = courses.map((course) => course.slug === slug ? normalizeCourse({ ...course, ...patch }) : course, ); writeStore(nextCourses); return nextCourses.find((course) => course.slug === slug); }; export const addLessonToTeacherCourse = (slug: string, lesson: Omit) => { const courses = getTeacherCourses(); const nextCourses = courses.map((course) => { if (course.slug !== slug) return course; const nextLesson: Lesson = { ...lesson, id: lessonId(course.lessons.length + 1), }; return normalizeCourse({ ...course, lessons: [...course.lessons, nextLesson], }); }); writeStore(nextCourses); return nextCourses.find((course) => course.slug === slug); };