[DONE] clone a course
This commit is contained in:
@@ -164,7 +164,7 @@
|
||||
<main>
|
||||
{#if $preloading && $delayedPreloading}
|
||||
<Backdrop>
|
||||
<Firework size="60" color="#fff" unit="px" duration="1s" />
|
||||
<Firework size="60" color="#1d4ed8" unit="px" duration="1s" />
|
||||
</Backdrop>
|
||||
{/if}
|
||||
{#if !['login', 'signup'].includes(path) && !isCoursePage(path)}
|
||||
|
||||
+11
-129
@@ -19,93 +19,25 @@
|
||||
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
// import { stores } from '@sapper/app';
|
||||
import PageNav from '../components/PageNav/index.svelte';
|
||||
import Courses from '../components/Courses/index.svelte';
|
||||
import NewCourseModal from '../components/Courses/components/NewCourseModal/index.svelte';
|
||||
import PrimaryButton from '../components/PrimaryButton/index.svelte';
|
||||
import Modal from '../components/Modal/index.svelte';
|
||||
import TextField from '../components/Form/TextField.svelte';
|
||||
import TextArea from '../components/Form/TextArea.svelte';
|
||||
import { courses, createCourseModal } from '../components/Courses/store';
|
||||
import { validateForm } from '../components/Courses/functions';
|
||||
import { ROLE } from '../utils/constants/roles';
|
||||
import { addGroupMember } from '../utils/services/courses';
|
||||
import { supabase } from '../utils/functions/supabase';
|
||||
import {
|
||||
courses,
|
||||
createCourseModal,
|
||||
courseMetaDeta,
|
||||
} from '../components/Courses/store';
|
||||
import { setProfileIdOfGroupMember } from '../utils/services/courses';
|
||||
|
||||
// const { page } = stores();
|
||||
|
||||
export let allCourses = [];
|
||||
export let cantFetch;
|
||||
|
||||
let errors = {
|
||||
emails: '',
|
||||
};
|
||||
|
||||
// let tab = '';
|
||||
|
||||
async function createCourse(e) {
|
||||
const { hasError, fieldErrors, students, tutors } =
|
||||
validateForm($createCourseModal);
|
||||
|
||||
errors = fieldErrors;
|
||||
if (hasError) return;
|
||||
|
||||
const { title, description } = $createCourseModal;
|
||||
// Create group from course_id
|
||||
const { data: newGroup } = await supabase
|
||||
.from('group')
|
||||
.insert({ name: title, description });
|
||||
|
||||
console.log(`newGroup`, newGroup);
|
||||
const { id: group_id } = newGroup[0];
|
||||
|
||||
// Create course with group_id
|
||||
const { data: newCourse } = await supabase.from('course').insert({
|
||||
title,
|
||||
description,
|
||||
group_id,
|
||||
});
|
||||
console.log(`newCourse`, newCourse);
|
||||
|
||||
courses.update((_courses) => [..._courses, newCourse[0]]);
|
||||
|
||||
// Get profile of author and add as member
|
||||
await addGroupMember({
|
||||
profile_id: $profile.id,
|
||||
email: $profile.email,
|
||||
group_id,
|
||||
role_id: ROLE.TUTOR,
|
||||
});
|
||||
|
||||
let membersStack = [];
|
||||
|
||||
// Create groupmemebers from group_id and add teachers and students
|
||||
for (const student of students) {
|
||||
membersStack.push({
|
||||
email: student,
|
||||
group_id,
|
||||
role_id: ROLE.STUDENT,
|
||||
});
|
||||
}
|
||||
|
||||
for (const tutor of tutors) {
|
||||
membersStack.push({
|
||||
email: tutor,
|
||||
group_id,
|
||||
role_id: ROLE.TUTOR,
|
||||
});
|
||||
}
|
||||
|
||||
addGroupMember(membersStack).then((membersAdded) => {
|
||||
console.log(`membersAdded`, membersAdded);
|
||||
$createCourseModal.open = false;
|
||||
});
|
||||
}
|
||||
|
||||
async function getCourses(userId) {
|
||||
if (process.browser) {
|
||||
if (cantFetch && typeof cantFetch === 'boolean' && !allCourses.length) {
|
||||
$courseMetaDeta.isLoading = true;
|
||||
|
||||
const updatedProfile = await setProfileIdOfGroupMember(
|
||||
$profile.email,
|
||||
userId
|
||||
@@ -114,6 +46,7 @@
|
||||
const coursesResult = await fetchCourses(userId);
|
||||
console.log(`coursesResult`, coursesResult);
|
||||
|
||||
$courseMetaDeta.isLoading = false;
|
||||
if (!coursesResult) return;
|
||||
|
||||
// organizationId = coursesResult.organizationId;
|
||||
@@ -122,7 +55,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
onMount(() => {
|
||||
courses.set(allCourses);
|
||||
});
|
||||
|
||||
@@ -145,58 +78,7 @@
|
||||
</div>
|
||||
</PageNav>
|
||||
|
||||
<Modal
|
||||
onClose={() => ($createCourseModal.open = false)}
|
||||
bind:open={$createCourseModal.open}
|
||||
width="w-2/5"
|
||||
modalHeading="Create a Course"
|
||||
>
|
||||
<form on:submit|preventDefault={createCourse}>
|
||||
<TextField
|
||||
label="Course name"
|
||||
bind:value={$createCourseModal.title}
|
||||
autofocus={true}
|
||||
placeholder="Your course name"
|
||||
className="mb-4"
|
||||
isRequired={true}
|
||||
errorMessage={errors.title}
|
||||
autoComplete={false}
|
||||
/>
|
||||
<TextArea
|
||||
label="Invite Tutors"
|
||||
bind:value={$createCourseModal.tutors}
|
||||
rows="2"
|
||||
maxRows="3"
|
||||
placeholder="tutor@company.com, john@gmail.com"
|
||||
helperMessage="To invite people, add their emails separated by a comma"
|
||||
errorMessage={errors.tutors}
|
||||
className="mb-4"
|
||||
/>
|
||||
<TextArea
|
||||
label="Invite Students"
|
||||
bind:value={$createCourseModal.students}
|
||||
rows="2"
|
||||
maxRows="3"
|
||||
placeholder="student@gmail.com, john@gmail.com"
|
||||
helperMessage="To invite people, add their emails separated by a comma"
|
||||
errorMessage={errors.students}
|
||||
className="mb-4"
|
||||
/>
|
||||
<TextArea
|
||||
label="Short description"
|
||||
bind:value={$createCourseModal.description}
|
||||
rows="4"
|
||||
maxRows="4"
|
||||
placeholder="A little description about this course"
|
||||
className="mb-4"
|
||||
isRequired={true}
|
||||
/>
|
||||
|
||||
<div class="mt-5 flex items-center">
|
||||
<PrimaryButton className="px-6 py-2" label="Finish" type="submit" />
|
||||
</div>
|
||||
</form>
|
||||
</Modal>
|
||||
<NewCourseModal />
|
||||
|
||||
<Courses />
|
||||
</section>
|
||||
|
||||
@@ -44,12 +44,14 @@
|
||||
let mode = MODES.view;
|
||||
let prevMode;
|
||||
let prevLessonId;
|
||||
let isFetching = false;
|
||||
|
||||
const { page } = stores();
|
||||
|
||||
async function fetchReqData(lessonId) {
|
||||
let lessonData;
|
||||
isFetching = true;
|
||||
|
||||
let lessonData;
|
||||
if (!$course.id) {
|
||||
const [_course, lesson] = await Promise.all([
|
||||
fetchCourse(courseId),
|
||||
@@ -69,6 +71,7 @@
|
||||
const totalExercises =
|
||||
lessonData.totalExercises[0] && lessonData.totalExercises[0].count;
|
||||
setLesson(lessonData, totalExercises);
|
||||
isFetching = false;
|
||||
}
|
||||
|
||||
function setLesson(lessonData, totalExercises) {
|
||||
@@ -92,7 +95,11 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<CourseContainer {path} isExercisePage={!isMaterialsTabActive && exerciseId}>
|
||||
<CourseContainer
|
||||
{isFetching}
|
||||
{path}
|
||||
isExercisePage={!isMaterialsTabActive && exerciseId}
|
||||
>
|
||||
<PageNav
|
||||
navItems={[
|
||||
{
|
||||
|
||||
@@ -18,7 +18,10 @@
|
||||
group,
|
||||
} from '../../../components/Course/store';
|
||||
import { lessons } from '../../../components/Course/components/Lesson/store/lessons';
|
||||
import { fetchCourse, fetchExercises } from '../../../utils/services/courses';
|
||||
import {
|
||||
fetchCourse,
|
||||
fetchExercisesByMarks,
|
||||
} from '../../../utils/services/courses';
|
||||
import { getLectureNo } from '../../../components/Course/function';
|
||||
import { fetchMarks } from '../../../utils/services/marks';
|
||||
import { profile } from '../../../utils/store/user';
|
||||
@@ -67,7 +70,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
const { data: exercises } = await fetchExercises(courseId);
|
||||
const { data: exercises } = await fetchExercisesByMarks(courseId);
|
||||
|
||||
// Map exercises to { lessonId: { exerciseId: exerciseTitle, ... }, ... }
|
||||
exercises.forEach((exercise) => {
|
||||
|
||||
+3
-13
@@ -64,7 +64,7 @@
|
||||
data-atf="1"
|
||||
/>
|
||||
-->
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="text-4xl text-center">
|
||||
Classroom<span class="text-blue-700">IO</span>
|
||||
</h3>
|
||||
@@ -87,18 +87,8 @@
|
||||
isRequired={true}
|
||||
isDisabled={isAdding}
|
||||
/>
|
||||
<PrimaryButton
|
||||
type="submit"
|
||||
variant={isAdding ? VARIANTS.OUTLINED : VARIANTS.CONTAINED}
|
||||
className="py-2 w-full justify-center sm:w-auto {isAdding &&
|
||||
'py-4 border-blue-700'}"
|
||||
isDisabled={isAdding}
|
||||
>
|
||||
{#if isAdding}
|
||||
<BarLoader size="30" color="#1d4ed8" unit="px" duration="1s" />
|
||||
{:else}
|
||||
Join waiting list
|
||||
{/if}
|
||||
<PrimaryButton type="submit" isLoading={isAdding}>
|
||||
Join waiting list
|
||||
</PrimaryButton>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
<script context="module">
|
||||
export function preload({ params }) {
|
||||
console.log(`params`, params);
|
||||
return { profileId: params.id };
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// import { goto } from '$app/navigation';
|
||||
import { onMount } from 'svelte';
|
||||
import { Chasing } from 'svelte-loading-spinners';
|
||||
import Search32 from 'carbon-icons-svelte/lib/Search32';
|
||||
import UserAvatar16 from 'carbon-icons-svelte/lib/UserAvatar16';
|
||||
import Book16 from 'carbon-icons-svelte/lib/Book16';
|
||||
import TextField from '../../components/Form/TextField.svelte';
|
||||
|
||||
Reference in New Issue
Block a user