CLASSROOMIO-T-80: Replace sapper with sveltekit
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
export async function handleAuthChange(event, session) {
|
||||
await fetch('/api/auth', {
|
||||
method: 'POST',
|
||||
headers: new Headers({ 'Content-Type': 'application/json' }),
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify({ event, session }),
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
export function toggleBodyByTheme(isDark) {
|
||||
if (!document) return;
|
||||
|
||||
if (isDark) {
|
||||
document.body.className = document.body.className.concat(' ', 'dark');
|
||||
} else {
|
||||
document.body.className = document.body.className.replace(' dark', '');
|
||||
}
|
||||
}
|
||||
|
||||
export function isCoursesPage(path) {
|
||||
return /courses\/[a-z 0-9 -]/.test(path);
|
||||
}
|
||||
|
||||
export function isCoursePage(path) {
|
||||
return /course\/[a-z 0-9 -]/.test(path);
|
||||
}
|
||||
|
||||
export function isOrgPage(path) {
|
||||
return /org\/[a-z 0-9 -]/.test(path);
|
||||
}
|
||||
|
||||
export function isQuizPage(path) {
|
||||
return /org\/[a-z 0-9 -]+\/quiz\/[a-z 0-9 -]/.test(path);
|
||||
}
|
||||
|
||||
export function isLMSPage(path) {
|
||||
return /lms[\/a-z 0-9 -]*/.test(path);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
export default (date) => {
|
||||
const d = new Date(date);
|
||||
|
||||
const ye = new Intl.DateTimeFormat('en', { year: 'numeric' }).format(d);
|
||||
const mo = new Intl.DateTimeFormat('en', { month: '2-digit' }).format(d);
|
||||
const da = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(d);
|
||||
|
||||
// return `${ye}-${mo}-${da} ${d.toLocaleTimeString('en-US')}`;
|
||||
return new Intl.DateTimeFormat('en-US', {
|
||||
dateStyle: 'full',
|
||||
timeStyle: 'medium',
|
||||
}).format(d);
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
export function formatYoutubeVideo(url: string, errors: { video: string }) {
|
||||
console.log(`url`, url);
|
||||
const prefix = 'https://www.youtube.com/embed';
|
||||
|
||||
// https://www.youtube.com/embed/qajK1J1neAM
|
||||
if (url.includes('embed')) {
|
||||
return url;
|
||||
}
|
||||
|
||||
// https://youtu.be/qajK1J1neAM
|
||||
if (url.includes('.be/')) {
|
||||
const splittedUrlWithBe = url.split('.be/');
|
||||
|
||||
return `${prefix}/${splittedUrlWithBe[1]}`;
|
||||
}
|
||||
|
||||
// https://www.youtube.com/watch?v=qajK1J1neAM
|
||||
const splitedUrl = url.split('watch');
|
||||
if (splitedUrl.length !== 2) {
|
||||
errors.video = 'Not a valid youtube link';
|
||||
return;
|
||||
}
|
||||
|
||||
const query = new URLSearchParams(splitedUrl[1]);
|
||||
|
||||
return `${prefix}/${query.get('v')}`;
|
||||
}
|
||||
|
||||
export function getEmbedId(url: string) {
|
||||
// https://www.youtube.com/embed/qajK1J1neAM
|
||||
if (url.includes('embed')) {
|
||||
return url.split('embed/')[1];
|
||||
}
|
||||
|
||||
// https://youtu.be/qajK1J1neAM
|
||||
if (url.includes('.be/')) {
|
||||
const splittedUrlWithBe = url.split('.be/');
|
||||
|
||||
return splittedUrlWithBe[1];
|
||||
}
|
||||
|
||||
// https://www.youtube.com/watch?v=qajK1J1neAM
|
||||
const splitedUrl = url.split('watch');
|
||||
if (splitedUrl.length !== 2) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const query = new URLSearchParams(splitedUrl[1]);
|
||||
|
||||
return query.get('v');
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
function generateSlug(title) {
|
||||
return title
|
||||
.match(/[^\W\s\d]*/g, '')
|
||||
.join('')
|
||||
.toLowerCase()
|
||||
.concat(`-${new Date().getTime()}`);
|
||||
}
|
||||
|
||||
export default generateSlug;
|
||||
@@ -0,0 +1,7 @@
|
||||
export default (currency: string | undefined) => {
|
||||
return new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
currency: currency,
|
||||
minimumFractionDigits: 2,
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
export default (created_at, due_date) => {
|
||||
return !!due_date
|
||||
? !!(new Date(created_at).getTime() <= new Date(due_date).getTime())
|
||||
: true;
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
export function isUUID(uuid: string) {
|
||||
let s = '' + uuid;
|
||||
|
||||
const m: RegExpMatchArray | null = s.match(
|
||||
'^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'
|
||||
);
|
||||
|
||||
if (m === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export function genQuizPin() {
|
||||
var minm = 100000;
|
||||
var maxm = 999999;
|
||||
return Math.floor(Math.random() * (maxm - minm + 1)) + minm;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export function removeDuplicate(arr) {
|
||||
let s = new Set(arr);
|
||||
let it = s.values();
|
||||
return Array.from(it);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import dayjs from 'dayjs';
|
||||
import isYesterday from 'dayjs/plugin/isYesterday';
|
||||
import isToday from 'dayjs/plugin/isToday';
|
||||
import isTomorrow from 'dayjs/plugin/isTomorrow';
|
||||
|
||||
import type {
|
||||
UserLessonDataType,
|
||||
LessonsByMonthIndexType,
|
||||
} from '$lib/utils/types';
|
||||
|
||||
dayjs.extend(isYesterday);
|
||||
dayjs.extend(isToday);
|
||||
dayjs.extend(isTomorrow);
|
||||
|
||||
export const formatUserUpcomingData = (
|
||||
data: UserLessonDataType[]
|
||||
): LessonsByMonthIndexType => {
|
||||
const result: LessonsByMonthIndexType = {};
|
||||
|
||||
for (const item of data) {
|
||||
const { lesson_at } = item;
|
||||
const lessonAtDate = new Date(lesson_at);
|
||||
const monthIndex = lessonAtDate.getMonth();
|
||||
const dateIndex = lessonAtDate.getDate();
|
||||
|
||||
if (result[monthIndex]) {
|
||||
const prevDateData = result[monthIndex][dateIndex];
|
||||
|
||||
if (Array.isArray(prevDateData)) {
|
||||
result[monthIndex] = {
|
||||
...result[monthIndex],
|
||||
[dateIndex]: [...prevDateData, item],
|
||||
};
|
||||
} else {
|
||||
result[monthIndex] = { ...result[monthIndex], [dateIndex]: [item] };
|
||||
}
|
||||
} else {
|
||||
result[monthIndex] = { [dateIndex]: [item] };
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export const formatDate = (_selectedDate: string | undefined): string => {
|
||||
if (!_selectedDate) return '';
|
||||
|
||||
const selectedDate = dayjs(_selectedDate);
|
||||
|
||||
if (selectedDate.isToday()) {
|
||||
return 'Today';
|
||||
} else if (selectedDate.isYesterday()) {
|
||||
return 'Yesterday';
|
||||
} else if (selectedDate.isTomorrow()) {
|
||||
return 'Tomorrow';
|
||||
}
|
||||
|
||||
return selectedDate.format('ddd, MMM D');
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import { PUBLIC_ROUTES } from '$lib/utils/constants/routes';
|
||||
|
||||
export default (route) => {
|
||||
return PUBLIC_ROUTES.some((publicRoute) => {
|
||||
const regex = new RegExp(publicRoute, 'g');
|
||||
return regex.test(route);
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
function showAppsSideBar(path) {
|
||||
return path.includes('/lessons/') && !path.includes('landingpage');
|
||||
}
|
||||
|
||||
export default showAppsSideBar;
|
||||
@@ -0,0 +1,28 @@
|
||||
import {
|
||||
PUBLIC_SUPABASE_ANON_KEY,
|
||||
PUBLIC_SUPABASE_URL,
|
||||
} from '$env/static/public';
|
||||
import { createClient, SupabaseClient } from '@supabase/supabase-js';
|
||||
import type { ConfigType } from '../types';
|
||||
|
||||
export let supabase: SupabaseClient;
|
||||
|
||||
export const getSupabase = (config?: ConfigType) => {
|
||||
if (supabase) return supabase;
|
||||
|
||||
config = {
|
||||
supabaseConfig: {
|
||||
bucketPath:
|
||||
'https://koxqonvbkeakwvmdegcf.supabase.in/storage/v1/object/sign/',
|
||||
url: PUBLIC_SUPABASE_URL || '',
|
||||
anonKey: PUBLIC_SUPABASE_ANON_KEY || '',
|
||||
},
|
||||
};
|
||||
|
||||
supabase = createClient(
|
||||
config.supabaseConfig.url,
|
||||
config.supabaseConfig.anonKey
|
||||
);
|
||||
|
||||
return supabase;
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
export function validateEmail(email) {
|
||||
const re =
|
||||
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
return re.test(String(email).toLowerCase());
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
import get from 'lodash/get';
|
||||
import isNumber from 'lodash/isNumber';
|
||||
import z from 'zod';
|
||||
import { validateEmail } from './validateEmail';
|
||||
|
||||
const createQuizValidationSchema = z.object({
|
||||
title: z.string().min(6, {
|
||||
message: 'Must be 6 or more characters long',
|
||||
invalid_type_error: 'Must not be empty',
|
||||
}),
|
||||
});
|
||||
|
||||
const askCommunityValidationSchema = z.object({
|
||||
title: z.string().min(6, {
|
||||
message: 'Must be 6 or more characters long',
|
||||
invalid_type_error: 'Must not be empty',
|
||||
}),
|
||||
body: z.string().min(20, {
|
||||
message: 'Must be 10 or more characters long',
|
||||
invalid_type_error: 'Must not be empty',
|
||||
}),
|
||||
});
|
||||
const commentInCommunityValidationSchema = z.object({
|
||||
comment: z.string().min(6, {
|
||||
message: 'Must be 6 or more characters long',
|
||||
invalid_type_error: 'Must not be empty',
|
||||
}),
|
||||
});
|
||||
|
||||
const forgotValidationSchema = z.object({
|
||||
email: z.string().email({
|
||||
message: 'Invalid email address',
|
||||
invalid_type_error: 'Must not be empty',
|
||||
}),
|
||||
});
|
||||
|
||||
const authValidationSchema = z.object({
|
||||
email: z.string().email({
|
||||
message: 'Invalid email address',
|
||||
invalid_type_error: 'Must not be empty',
|
||||
}),
|
||||
password: z.string().min(6, {
|
||||
message: 'Must be 6 or more characters long',
|
||||
invalid_type_error: 'Must not be empty',
|
||||
}),
|
||||
});
|
||||
|
||||
const resetValidationSchema = z.object({
|
||||
password: z.string().min(6, {
|
||||
message: 'Must be 6 or more characters long',
|
||||
invalid_type_error: 'Must not be empty',
|
||||
}),
|
||||
});
|
||||
|
||||
const onboardingValidationSchema = {
|
||||
stepOne: z.object({
|
||||
fullname: z.string().min(1, { message: 'Enter your fullname' }),
|
||||
orgName: z.string().min(1, { message: 'Enter your organisation name' }),
|
||||
siteName: z.string().min(1, { message: 'Enter your site name' }),
|
||||
}),
|
||||
stepTwo: z.object({
|
||||
goal: z
|
||||
.string({
|
||||
required_error: 'Select an option',
|
||||
invalid_type_error: 'Select an option',
|
||||
})
|
||||
.min(1),
|
||||
source: z
|
||||
.string({
|
||||
required_error: 'Select an option',
|
||||
invalid_type_error: 'Select an option',
|
||||
})
|
||||
.min(1),
|
||||
}),
|
||||
};
|
||||
|
||||
export const getConfirmPasswordError = ({ password, confirmPassword }) => {
|
||||
return password > 6 && confirmPassword > 6 && password !== confirmPassword
|
||||
? 'Does not match password'
|
||||
: null;
|
||||
};
|
||||
|
||||
export const processErrors = (error, mapToId) => {
|
||||
const errors = {};
|
||||
|
||||
if (Array.isArray(error?.issues)) {
|
||||
for (const issue of error.issues) {
|
||||
const { message, path } = issue;
|
||||
|
||||
if (!path.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mapToId) {
|
||||
let value = '';
|
||||
path.forEach((p, i) => {
|
||||
const isLast = !path[i + 1];
|
||||
const formatP = isNumber(p) ? `[${p}]` : p;
|
||||
|
||||
value += !value ? formatP : `.${formatP}`;
|
||||
});
|
||||
const key = value.replace('label', 'id');
|
||||
errors[key] = value;
|
||||
} else {
|
||||
errors[path[0]] = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
};
|
||||
|
||||
export const authValidation = (fields = {}) => {
|
||||
const { error } = authValidationSchema.safeParse(fields);
|
||||
|
||||
return processErrors(error);
|
||||
};
|
||||
|
||||
export const resetValidation = (fields = {}) => {
|
||||
const { error } = resetValidationSchema.safeParse(fields);
|
||||
|
||||
return processErrors(error);
|
||||
};
|
||||
|
||||
export const forgotValidation = (fields = {}) => {
|
||||
const { error } = forgotValidationSchema.safeParse(fields);
|
||||
|
||||
return processErrors(error);
|
||||
};
|
||||
|
||||
export const onboardingValidation = (fields = {}, step) => {
|
||||
const schema =
|
||||
step === 1
|
||||
? onboardingValidationSchema.stepOne
|
||||
: onboardingValidationSchema.stepTwo;
|
||||
const { error } = schema.safeParse(fields);
|
||||
|
||||
return processErrors(error);
|
||||
};
|
||||
|
||||
export const createQuizValidation = (fields = {}) => {
|
||||
const { error } = createQuizValidationSchema.safeParse(fields);
|
||||
|
||||
return processErrors(error);
|
||||
};
|
||||
|
||||
export const askCommunityValidation = (fields = {}) => {
|
||||
const { error } = askCommunityValidationSchema.safeParse(fields);
|
||||
|
||||
return processErrors(error);
|
||||
};
|
||||
|
||||
export const commentInCommunityValidation = (fields = {}) => {
|
||||
const { error } = commentInCommunityValidationSchema.safeParse(fields);
|
||||
|
||||
return processErrors(error);
|
||||
};
|
||||
|
||||
export const getDisableSubmit = ({ password, confirmPassword }) => {
|
||||
return !!(password && confirmPassword && password !== confirmPassword);
|
||||
};
|
||||
|
||||
export const validateEmailInString = (emailsStr) => {
|
||||
let error = '';
|
||||
let hasError = false;
|
||||
|
||||
if (!emailsStr) {
|
||||
return {
|
||||
hasError: true,
|
||||
error: 'Enter an email',
|
||||
emails: [],
|
||||
};
|
||||
}
|
||||
|
||||
const emails = emailsStr.split(',').map((_email) => {
|
||||
const email = _email.trim();
|
||||
|
||||
if (!validateEmail(email)) {
|
||||
hasError = true;
|
||||
error += !error.length ? `Not valid email: ${email}` : `, ${email}`;
|
||||
}
|
||||
|
||||
return email;
|
||||
});
|
||||
|
||||
return {
|
||||
hasError,
|
||||
error,
|
||||
emails,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user