Files
lms-sb/src/lib/settings.ts
T
admins 7c8e72cd94 Add email notification on new lesson comment
Notify admins/curators (or configured notificationEmails) when a student
leaves a comment under a lesson. New setting notifyOnComment (default on) +
toggle in admin settings. Fires only for student comments, not admin/curator
replies; comment text is HTML-escaped in the email.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 10:02:07 +05:00

94 lines
2.9 KiB
TypeScript

import { cache } from "react";
import { prisma } from "./prisma";
// ── Defaults ──────────────────────────────────────────────────────────────────
export const SETTINGS_DEFAULTS = {
// Basic
schoolName: "Second Brain",
schoolDescription: "Образовательная платформа Second Brain",
schoolKeywords: "",
maintenanceMode: "false",
registrationEnabled: "true",
// Notifications
notificationEmails: "", // newline-separated list
notifyOnHomework: "true",
notifyOnComment: "true",
notifyOnRegistration: "true",
notifyStudentOnFeedback: "true",
// Student profile
requireEmailVerification: "true",
lastNameField: "optional", // required | optional | hidden
phoneField: "hidden", // required | optional | hidden
// Legal
privacyPolicyUrl: "",
termsUrl: "",
offerUrl: "",
showTermsCheckbox: "false",
orgRequisites: "",
// Curator permissions
curatorHomeworkScope: "all", // all | assigned
curatorCanAnswerQuestions: "true",
curatorCanSeeStudents: "true",
// Logo
logoUrl: "",
showLogo: "true",
// Social networks
socialYoutube: "",
socialVk: "",
socialTelegram: "",
// Code injection
headCode: "",
bodyCode: "",
} as const;
export type SettingsKey = keyof typeof SETTINGS_DEFAULTS;
export type Settings = Record<SettingsKey, string>;
// ── Getters ───────────────────────────────────────────────────────────────────
export const getSettings = cache(async (): Promise<Settings> => {
try {
const rows = await prisma.settings.findMany();
const stored: Record<string, string> = {};
for (const row of rows) stored[row.key] = row.value;
return Object.fromEntries(
Object.entries(SETTINGS_DEFAULTS).map(([k, v]) => [k, stored[k] ?? v])
) as Settings;
} catch {
// DB unavailable at build time — return defaults
return { ...SETTINGS_DEFAULTS } as Settings;
}
});
export async function getSetting(key: SettingsKey): Promise<string> {
try {
const row = await prisma.settings.findUnique({ where: { key } });
return row?.value ?? SETTINGS_DEFAULTS[key];
} catch {
return SETTINGS_DEFAULTS[key];
}
}
// ── Convenience helpers ───────────────────────────────────────────────────────
/** Parse a boolean setting ("true" / "false") */
export function asBool(value: string): boolean {
return value === "true";
}
/** Parse notification emails (newline-separated string → array) */
export function parseNotificationEmails(value: string): string[] {
return value
.split("\n")
.map((e) => e.trim())
.filter(Boolean);
}