Restructure course routes + list of exercises

This commit is contained in:
Rotimi Best
2021-07-10 19:16:10 +00:00
parent d7968895b2
commit 4124a1fc02
32 changed files with 569 additions and 390 deletions
+16
View File
@@ -1702,6 +1702,16 @@
"integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==",
"dev": true
},
"carbon-components-svelte": {
"version": "0.39.0",
"resolved": "https://registry.npmjs.org/carbon-components-svelte/-/carbon-components-svelte-0.39.0.tgz",
"integrity": "sha512-pz6P8JwU959YyrjJ9TUxM4O9uVjj51htGFWHAXyH2ou2TcY2t2u8DgRQMAXImAqVpwOKgwTNJ5HhnEzNyFhiSw==",
"dev": true,
"requires": {
"carbon-icons-svelte": "^10.27.0",
"flatpickr": "4.6.9"
}
},
"carbon-icons-svelte": {
"version": "10.28.0",
"resolved": "https://registry.npmjs.org/carbon-icons-svelte/-/carbon-icons-svelte-10.28.0.tgz",
@@ -2214,6 +2224,12 @@
"pinkie-promise": "^2.0.0"
}
},
"flatpickr": {
"version": "4.6.9",
"resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.9.tgz",
"integrity": "sha512-F0azNNi8foVWKSF+8X+ZJzz8r9sE1G4hl06RyceIaLvyltKvDl6vqk9Lm/6AUUCi5HWaIjiUbk7UpeE/fOXOpw==",
"dev": true
},
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+1
View File
@@ -31,6 +31,7 @@
"@rollup/plugin-node-resolve": "^8.0.0",
"@rollup/plugin-replace": "^2.2.0",
"@tailwindcss/typography": "^0.3.1",
"carbon-components-svelte": "^0.39.0",
"carbon-icons-svelte": "^10.21.0",
"postcss": "^8.0.9",
"postcss-load-config": "^2.1.0",
+4 -3
View File
@@ -1,5 +1,6 @@
import * as sapper from '@sapper/app';
import "carbon-components-svelte/css/all.css";
import * as sapper from "@sapper/app";
sapper.start({
target: document.querySelector('#sapper')
});
target: document.querySelector("#sapper"),
});
@@ -1,8 +0,0 @@
<script>
import PageNav from "../../PageNav/index.svelte";
</script>
<style>
</style>
<PageNav title="Home tasks" />
@@ -1 +0,0 @@
<div>class work</div>
@@ -2,11 +2,13 @@
import { handleAddQuestion } from "./store/index";
import PrimaryButton from "../../../../PrimaryButton/index.svelte";
import PageBody from "../../../../PageBody/index.svelte";
import EditMode from "./EditMode.svelte";
import ViewMode from "./ViewMode.svelte";
import EditMode from "./EditMode.svelte";
import MODES from "../../../../../utils/constants/mode.js";
import { VARIANTS } from "../../../../PrimaryButton/constants";
export let exerciseId;
let mode = MODES.view;
let preview = false;
@@ -0,0 +1,66 @@
<script>
import { Modal } from "carbon-components-svelte";
import PrimaryButton from "../../../../PrimaryButton/index.svelte";
import PageBody from "../../../../PageBody/index.svelte";
import TextField from "../../../../Form/TextField.svelte";
export let path;
let exercises = [
{
id: 1,
title: "Practice Exercise",
link: `${path}&exerciseId=1`,
},
{
id: 2,
title: "Home task",
link: `${path}&exerciseId=2`,
},
];
let exerciseEditing;
let open = false;
let newExercise = {
id: 1,
title: "",
link: "",
};
function handleAddExercise() {
open = true;
}
</script>
<Modal
size="sm"
bind:open
modalHeading="Create database"
primaryButtonText="Confirm"
secondaryButtonText="Cancel"
on:click:button--secondary
on:open
on:close
on:submit
>
<p>Create a new Cloudant database in the US South region.</p>
</Modal>
<PageBody width="w-11/12 m-auto">
<slot:fragment slot="header">
<PrimaryButton className="mr-2" label="Add" onClick={handleAddExercise} />
</slot:fragment>
<div class="flex flex-wrap">
{#each exercises as exercise, index}
<a class="w-52 bg-gray-100 px-4 py-7 mr-4 mb-4" href={exercise.link}>
{#if exerciseEditing === index}
<TextField bind:value={exercise.title} autofocus={true} />
{:else}
<h3 class="text-xl">{exercise.title}</h3>
{/if}
<p class="mt-4 text-sm">Created Jul 3, 2021</p>
</a>
{/each}
</div>
</PageBody>
@@ -8,6 +8,7 @@
import Progress from "../../../../Progress/index.svelte";
import { removeDuplicate } from "../../../../../utils/functions/removeDuplicate";
import { QUESTION_TYPE } from "../../../../Question/constants";
import { STATUS } from "./constants";
export let preview;
@@ -113,10 +114,10 @@
};
}
function getTotalScores(scoresObject) {
function getTotalScores() {
let total = 0;
for (const score in scoresObject) {
total += score;
for (const score in $userQuestionniareAnswers.scores) {
total += parseInt($userQuestionniareAnswers.scores[score]);
}
return total;
@@ -206,19 +207,28 @@
<div class="flex items-center justify-between">
<div class="flex flex-col justify-between">
<h2 class="text-xl mb-2 mt-0">{title}</h2>
<span
class="bg-green-700 text-white rounded-full py-2 px-6 text-center"
title="Status: Pending Review"
>
Pending Review
</span>
{#if STATUS.IN_PROGRESS === $userQuestionniareAnswers.status}
<span
class="bg-yellow-600 text-white rounded-full py-2 px-6 text-center"
title="Status: Pending Review"
>
Pending
</span>
{:else if STATUS.REVIEWED === $userQuestionniareAnswers.status && getTotalScores() > 0}
<span
class="bg-green-700 text-white rounded-full py-2 px-6 text-center"
title="Status: Pending Review"
>
Reviewed
</span>
{/if}
</div>
<span
class="border-2 border-gray-700 rounded-full h-24 w-24 flex items-center justify-center text-2xl"
title="Status: Pending Review"
>
{getTotalScores($userQuestionniareAnswers.scores)}/100
{getTotalScores()}/100
</span>
</div>
{#each questions as currentQuestion, currentQuestionIndex}
@@ -0,0 +1,4 @@
export const STATUS = {
IN_PROGRESS: 0,
REVIEWED: 1,
};
@@ -0,0 +1,13 @@
<script>
import List from "./List.svelte";
import Exercise from "./Exercise.svelte";
export let exerciseId;
export let path;
</script>
{#if exerciseId}
<Exercise {exerciseId} />
{:else}
<List {path} />
{/if}
@@ -0,0 +1,21 @@
import { writable } from "svelte/store";
import { STATUS } from "../constants";
// export const userQuestionniareAnswers = writable({
// answers: {},
// scores: { gates: 60 },
// currentQuestionIndex: 5,
// isFinished: true,
// progressValue: 100,
// status: STATUS.REVIEWED,
// });
export const userQuestionniareAnswers = writable({
answers: {},
scores: {},
currentQuestionIndex: 0,
isFinished: false,
progressValue: 100,
status: STATUS.IN_PROGRESS,
});
@@ -1,149 +0,0 @@
<script>
import Time24 from "carbon-icons-svelte/lib/Time24";
import Edit24 from "carbon-icons-svelte/lib/Edit24";
import Save24 from "carbon-icons-svelte/lib/Save24";
import CheckmarkFilled24 from "carbon-icons-svelte/lib/CheckmarkFilled24";
import PageNav from "../../../../PageNav/index.svelte";
import PageBody from "../../../../PageBody/index.svelte";
import PrimaryButton from "../../../../PrimaryButton/index.svelte";
import TextField from "../../../../Form/TextField.svelte";
import IconButton from "../../../../IconButton/index.svelte";
import Select from "../../../../Form/Select.svelte";
import { lessons, lecturers, handleAddLesson } from "../store/lessons";
// export let path;
let lectureEditing;
let ref;
function formatDate(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}`;
}
function addLesson() {
handleAddLesson();
setTimeout(() => {
lectureEditing = $lessons.length - 1;
if (ref) {
ref.scrollIntoView({ block: "end", behavior: "smooth" });
}
}, 100);
}
</script>
<PageNav title="Lectures">
<div slot="widget">
<PrimaryButton label="Add" onClick={addLesson} />
</div>
</PageNav>
<PageBody width="w-11/12 m-auto">
<div class="w-4/5 m-auto">
{#each $lessons as lecture, index}
<div
bind:this={ref}
class="group relative m-auto rounded-md border-2 border-gray-100 py-3 px-5 mr-4 mb-4 flex items-center hover:shadow-2xl shadow-md transition delay-150 duration-300 ease-in-out"
>
<!-- Complete or Not complete icon -->
<div class="absolute -left-6 -top-6 success">
<IconButton
onClick={() => (lecture.isComplete = !lecture.isComplete)}
>
{#if lecture.isComplete}
<CheckmarkFilled24 class="carbon-icon" />
{:else}
<span class="text-2xl">🔒</span>
{/if}
</IconButton>
</div>
<!-- Edit/Save -->
<div class="absolute top-2 right-0">
{#if lectureEditing === index}
<IconButton onClick={() => (lectureEditing = null)}>
<Save24 class="carbon-icon" />
</IconButton>
{:else}
<IconButton onClick={() => (lectureEditing = index)}>
<Edit24 class="carbon-icon" />
</IconButton>
{/if}
</div>
<div class="">
<h3 class="text-4xl font-bold">{index + 1}</h3>
</div>
<div class="ml-8 w-4/5">
{#if lectureEditing === index}
<TextField bind:value={lecture.title} autofocus={true} />
{:else}
<h3 class="text-3xl font-semibold m-0 flex items-center">
<a href={lecture.to} class="hover:underline text-black">
{lecture.title}
</a>
</h3>
{/if}
<div class="flex items-center mb-2">
<div class="flex items-center mr-2">
{lecture.resources.map((r) => `${r.value} ${r.label}`).join(", ")}
</div>
</div>
<div class="flex items-center justify-between mt-3 w-full">
{#if lectureEditing === index}
<Select
bind:value={lecture.lecturer.name}
options={$lecturers}
valueKey="text"
/>
{:else}
<a
href="courses/1/people"
class="flex items-center hover:underline text-black"
>
<img
alt="Placeholder"
class="block rounded-full"
width="24"
height="20"
src={lecture.lecturer.avatar}
/>
<p class="ml-2 text-sm font-bold">{lecture.lecturer.name}</p>
</a>
{/if}
<div class="flex items-center">
{#if lectureEditing === index}
<input
type="date"
name="lecture-date-picker"
class="p-2 rounded-md w-40"
value={formatDate(lecture.date)}
on:input={(e) => (lecture.date = e.target.value)}
/>
{:else}
<Time24 class="carbon-icon" />
<p class="text-md font-semibold ml-2">
{new Date(lecture.date).toDateString()}
</p>
{/if}
</div>
</div>
</div>
</div>
{/each}
</div>
</PageBody>
<style>
.group {
min-height: 170px;
}
</style>
@@ -1,9 +0,0 @@
import { writable } from "svelte/store";
export const userQuestionniareAnswers = writable({
answers: {},
scores: {},
currentQuestionIndex: 5,
isFinished: true,
progressValue: 100,
});
@@ -1,51 +1,37 @@
<script>
import PageNav from "../../../PageNav/index.svelte";
import Classwork from "./Classwork.svelte";
import Homework from "./Homework/index.svelte";
import Exercises from "./Exercises/index.svelte";
import Readme from "./Readme/index.svelte";
import Home from "./Home/index.svelte";
export let path;
export let tab;
// export let lectureId;
export let showLectureHome;
export let exerciseId;
</script>
{#if showLectureHome}
<Home {path} />
{:else}
<div>
<PageNav
navItems={[
{
label: "README.md",
isActive: tab === "lectures",
href: `${path}?tab=lectures`,
},
{
label: "Class work",
isActive: tab === "classwork",
href: `${path}?tab=classwork`,
},
{
label: "Hometasks",
isActive: tab === "hometasks",
href: `${path}?tab=hometasks`,
},
]}
/>
<div>
<PageNav
navItems={[
{
label: "README.md",
isActive: tab === "lectures",
href: `${path}?tab=lectures`,
},
{
label: "Exercises",
isActive: tab === "exercises",
href: `${path}?tab=exercises`,
},
]}
/>
<div class="course relative">
{#if tab === "lectures"}
<Readme />
{:else if tab === "classwork"}
<Classwork />
{:else if tab === "hometasks"}
<Homework />
{/if}
</div>
<div class="course relative">
{#if tab === "lectures"}
<Readme />
{:else if tab === "exercises"}
<Exercises {exerciseId} path={`${path}?tab=exercises`} />
{/if}
</div>
{/if}
</div>
<style>
.course {
@@ -5,12 +5,16 @@
import ChevronLeft32 from "carbon-icons-svelte/lib/ChevronLeft32";
import ChevronRight32 from "carbon-icons-svelte/lib/ChevronRight32";
import { stores, goto } from "@sapper/app";
import Expandable from "../../Expandable/index.svelte";
import PageNav from "../../PageNav/index.svelte";
import IconButton from "../../IconButton/index.svelte";
import { getNavItemRoute, getLectureRoute, getLectureNo } from "../function";
import Expandable from "../../../Expandable/index.svelte";
import PageNav from "../../../PageNav/index.svelte";
import IconButton from "../../../IconButton/index.svelte";
import {
getNavItemRoute,
getLectureRoute,
getLectureNo,
} from "../../function";
import { lessons } from "./Lecture/store/lessons";
import { lessons } from "../Lecture/store/lessons";
// export let lectureId;
export let courseId;
@@ -38,13 +42,8 @@
isLecture: true,
},
{
label: "People",
to: getNavItemRoute(courseId, "people"),
hideSortIcon: true,
},
{
label: "Timetable",
to: getNavItemRoute(courseId, "timetable"),
label: "Exercises",
to: getNavItemRoute(courseId, "exercises"),
hideSortIcon: true,
},
{
@@ -53,8 +52,13 @@
hideSortIcon: true,
},
{
label: "Hometasks",
to: getNavItemRoute(courseId, "hometasks"),
label: "People",
to: getNavItemRoute(courseId, "people"),
hideSortIcon: true,
},
{
label: "Timetable",
to: getNavItemRoute(courseId, "timetable"),
hideSortIcon: true,
},
];
@@ -1,76 +0,0 @@
<script>
import { stores } from "@sapper/app";
import PageNav from "../../PageNav/index.svelte";
import UserCard from "../../UserCard/index.svelte";
const { page } = stores();
const teachers = [
{
name: "Alexander Pokidin",
title: "Senior Software Engineer",
avatar:
"https://media-exp1.licdn.com/dms/image/C5603AQFWia2m2J0syA/profile-displayphoto-shrink_100_100/0/1517423655318?e=1625702400&v=beta&t=SVGGkisvjOVcbz6Ejtb8pEDzRnqqFxMAMXGZgW-WE70",
telegramLink: "https://t.me/seed_of_abraham",
mailLink: "mailto:irb.ossystem@gmail.com",
},
{
name: "Andrey Filatov",
title: "Fullstack Software Engineer",
avatar:
"https://media-exp1.licdn.com/dms/image/C5103AQHuKuAX7RdoRw/profile-displayphoto-shrink_100_100/0/1517226025504?e=1625702400&v=beta&t=dReL72K1hYLVXBw_-v5LTDfjHLeDqfRC6IzBYOdqjqc",
telegramLink: "https://t.me/seed_of_abraham",
mailLink: "mailto:irb.ossystem@gmail.com",
},
{
name: "Sergey Semko",
title: "Senior Software Engineer",
avatar:
"https://media-exp1.licdn.com/dms/image/C5603AQFUEHk5pxnIyA/profile-displayphoto-shrink_100_100/0/1558013476527?e=1625702400&v=beta&t=Y3uBohyYlRvVf_U-1o4elfRGdcTFkKQMH9NqbD5lHlc",
telegramLink: "https://t.me/seed_of_abraham",
mailLink: "mailto:irb.ossystem@gmail.com",
},
{
name: "Natalia Fedii",
title: "Project Manager",
avatar:
"https://media-exp1.licdn.com/dms/image/C5603AQEi-IuSUG6kTQ/profile-displayphoto-shrink_100_100/0/1517884922407?e=1625702400&v=beta&t=rbj0wEM20msiDSQnTdwr68E4uv9N6xJTvObl3hLuRLc",
telegramLink: "https://t.me/seed_of_abraham",
mailLink: "mailto:irb.ossystem@gmail.com",
},
];
const students = [...teachers, ...teachers, ...teachers];
</script>
<PageNav title="People" disableSticky={true} />
<div class="m-3">
<h3>
<a id="teachers" name="teachers" href="{$page.path}#teachers">Teachers</a>
</h3>
<div class="flex flex-wrap">
{#each teachers as teacher}
<UserCard
name={teacher.name}
avatarUrl={teacher.avatar}
title={teacher.title}
telegramLink={teacher.telegramLink}
mailLink={teacher.mailLink}
/>
{/each}
</div>
</div>
<div class="m-3">
<h3>
<a id="students" name="students" href="{$page.path}#students">Students</a>
</h3>
<div class="flex flex-wrap">
{#each students as student}
<UserCard
name={student.name}
avatarUrl={student.avatar}
title={student.title}
/>
{/each}
</div>
</div>
@@ -1,8 +0,0 @@
<script>
import PageNav from "../../PageNav/index.svelte";
</script>
<style>
</style>
<PageNav title="Scoreboard" />
@@ -1,8 +0,0 @@
<script>
import PageNav from "../../PageNav/index.svelte";
</script>
<style>
</style>
<PageNav title="Time table" />
@@ -0,0 +1,28 @@
<script>
import Navigation from "../Course/components/Navigation/index.svelte";
export let courseTitle = "";
export let courseId = "";
</script>
<svelte:head>
<title>{courseTitle}</title>
</svelte:head>
<div class="root">
<Navigation {courseId} />
<div class="rightBar">
<slot />
</div>
</div>
<style>
.root {
display: flex;
border-right: 1px solid var(--border-color);
width: 100%;
}
.rightBar {
flex-grow: 1;
}
</style>
@@ -1,7 +1,7 @@
<script>
import { CodeSnippet } from "carbon-components-svelte";
import PrimaryButton from "../../PrimaryButton/index.svelte";
import { VARIANTS } from "../../PrimaryButton/constants";
import CodeSnippet from "../../CodeSnippet/index.svelte";
import Checkbox from "../../Form/Checkbox.svelte";
export let title = "";
@@ -59,7 +59,7 @@
<h2>{title}</h2>
{#if code}
<CodeSnippet {code} />
<CodeSnippet {code} type="multi" />
{/if}
<div class="ml-4">
@@ -1,8 +1,8 @@
<script>
import { CodeSnippet } from "carbon-components-svelte";
import PrimaryButton from "../../PrimaryButton/index.svelte";
import { VARIANTS } from "../../PrimaryButton/constants";
import RadioItem from "../../Form/RadioItem.svelte";
import CodeSnippet from "../../CodeSnippet/index.svelte";
export let title = "";
export let code;
@@ -59,7 +59,7 @@
<h2>{title}</h2>
{#if code}
<CodeSnippet {code} />
<CodeSnippet {code} type="multi" />
{/if}
<div class="ml-4">
@@ -1,7 +1,8 @@
<script>
import { CodeSnippet } from "carbon-components-svelte";
import marked from "marked";
import PrimaryButton from "../../PrimaryButton/index.svelte";
import { VARIANTS } from "../../PrimaryButton/constants";
import CodeSnippet from "../../CodeSnippet/index.svelte";
import TextArea from "../../Form/TextArea.svelte";
export let title = "";
@@ -32,12 +33,14 @@
<h2>{title}</h2>
{#if code}
<CodeSnippet {code} />
<CodeSnippet {code} type="multi" />
{/if}
<div class="ml-4">
{#if disabled}
<CodeSnippet code={defaultValue} />
<div class="bg-gray-200 p-5 rounded-md mb-3">
{@html marked(defaultValue)}
</div>
{:else}
<TextArea
bind:value={defaultValue}
+2 -1
View File
@@ -4,6 +4,7 @@
import LeftNav from "../components/LeftNav/index.svelte";
// import SideBar from "../components/SideBar/index.svelte";
import Footer from "../components/Footer/index.svelte";
import Apps from "../components/Apps/index.svelte";
export let segment;
</script>
@@ -15,7 +16,7 @@
<main class="flex">
<LeftNav {segment} />
<slot />
<!-- <SideBar /> -->
<Apps />
</main>
<Footer />
@@ -0,0 +1,18 @@
<script context="module">
export async function preload({ params }) {
let [courseId, courseNavItem, lectureId] = params.id;
return { courseId, courseNavItem, lectureId };
}
</script>
<script>
import PageNav from "../../../components/PageNav/index.svelte";
import CourseContainer from "../../../components/CourseContainer/index.svelte";
export let courseId;
</script>
<CourseContainer title="ReactJS" {courseId}>
<PageNav title="Exercises" />
</CourseContainer>
+4 -57
View File
@@ -7,65 +7,12 @@
</script>
<script>
import { stores } from "@sapper/app";
import Lecture from "../../../components/Course/components/Lecture/index.svelte";
import HomeTask from "../../../components/Course/components/HomeTask.svelte";
import Overview from "../../../components/Course/index.svelte";
import People from "../../../components/Course/components/People.svelte";
import Scoreboard from "../../../components/Course/components/Scoreboard.svelte";
import TimeTable from "../../../components/Course/components/TimeTable.svelte";
import CourseNav from "../../../components/Course/components/CourseNav.svelte";
import Apps from "../../../components/Apps/index.svelte";
import CourseContainer from "../../../components/CourseContainer/index.svelte";
export let courseId;
export let courseNavItem;
export let lectureId;
const { page } = stores();
let tab = "";
let mode = "";
$: tab = $page.query.tab || "lectures";
</script>
<svelte:head>
<title>ReactJS</title>
</svelte:head>
<div class="root">
<CourseNav {courseId} />
<div class="rightBar">
{#if !courseNavItem}
<Overview />
{:else if courseNavItem === "score"}
<Scoreboard />
{:else if courseNavItem === "timetable"}
<TimeTable />
{:else if courseNavItem === "hometasks"}
<HomeTask />
{:else if courseNavItem === "lecture"}
<Lecture
path={$page.path}
{tab}
{lectureId}
showLectureHome={!lectureId}
/>
{:else if courseNavItem === "people"}
<People />
{/if}
</div>
<Apps />
</div>
<style>
.root {
display: flex;
border-right: 1px solid var(--border-color);
width: 100%;
}
.rightBar {
flex-grow: 1;
}
</style>
<CourseContainer title="ReactJS" {courseId}>
<Overview />
</CourseContainer>
@@ -0,0 +1,27 @@
<script context="module">
export async function preload({ params }) {
let [courseId, courseNavItem, lectureId] = params.id;
return { courseId, courseNavItem, lectureId };
}
</script>
<script>
import { stores } from "@sapper/app";
import Lecture from "../../../../../components/Course/components/Lecture/index.svelte";
import CourseContainer from "../../../../../components/CourseContainer/index.svelte";
export let courseId;
export let lectureId;
const { page } = stores();
let tab = "";
let exerciseId = "";
$: tab = $page.query.tab || "lectures";
$: exerciseId = $page.query.exerciseId;
</script>
<CourseContainer title="ReactJS" {courseId}>
<Lecture path={$page.path} {tab} {exerciseId} {lectureId} />
</CourseContainer>
@@ -0,0 +1,166 @@
<script context="module">
export async function preload({ params }) {
let [courseId, courseNavItem, lectureId] = params.id;
return { courseId, courseNavItem, lectureId };
}
</script>
<script>
import { stores } from "@sapper/app";
import Time24 from "carbon-icons-svelte/lib/Time24";
import Edit24 from "carbon-icons-svelte/lib/Edit24";
import Save24 from "carbon-icons-svelte/lib/Save24";
import CheckmarkFilled24 from "carbon-icons-svelte/lib/CheckmarkFilled24";
import PageNav from "../../../../components/PageNav/index.svelte";
import PageBody from "../../../../components/PageBody/index.svelte";
import PrimaryButton from "../../../../components/PrimaryButton/index.svelte";
import TextField from "../../../../components/Form/TextField.svelte";
import IconButton from "../../../../components/IconButton/index.svelte";
import Select from "../../../../components/Form/Select.svelte";
import CourseContainer from "../../../../components/CourseContainer/index.svelte";
import {
lessons,
lecturers,
handleAddLesson,
} from "../../../../components/Course/components/Lecture/store/lessons";
export let courseId;
let lectureEditing;
let ref;
function formatDate(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}`;
}
function addLesson() {
handleAddLesson();
setTimeout(() => {
lectureEditing = $lessons.length - 1;
if (ref) {
ref.scrollIntoView({ block: "end", behavior: "smooth" });
}
}, 100);
}
</script>
<CourseContainer title="ReactJS" {courseId}>
<PageNav title="Lectures">
<div slot="widget">
<PrimaryButton label="Add" onClick={addLesson} />
</div>
</PageNav>
<PageBody width="w-11/12 m-auto">
<div class="w-4/5 m-auto">
{#each $lessons as lecture, index}
<div
bind:this={ref}
class="group relative m-auto rounded-md border-2 border-gray-100 py-3 px-5 mr-4 mb-4 flex items-center hover:shadow-2xl shadow-md transition delay-150 duration-300 ease-in-out"
>
<!-- Complete or Not complete icon -->
<div class="absolute -left-6 -top-6 success">
<IconButton
onClick={() => (lecture.isComplete = !lecture.isComplete)}
>
{#if lecture.isComplete}
<CheckmarkFilled24 class="carbon-icon" />
{:else}
<span class="text-2xl">🔒</span>
{/if}
</IconButton>
</div>
<!-- Edit/Save -->
<div class="absolute top-2 right-0">
{#if lectureEditing === index}
<IconButton onClick={() => (lectureEditing = null)}>
<Save24 class="carbon-icon" />
</IconButton>
{:else}
<IconButton onClick={() => (lectureEditing = index)}>
<Edit24 class="carbon-icon" />
</IconButton>
{/if}
</div>
<div class="">
<h3 class="text-3xl font-bold">{index + 1}.</h3>
</div>
<div class="ml-8 w-4/5">
{#if lectureEditing === index}
<TextField bind:value={lecture.title} autofocus={true} />
{:else}
<h3 class="text-3xl font-semibold m-0 flex items-center">
<a href={lecture.to} class="hover:underline text-black">
{lecture.title}
</a>
</h3>
{/if}
<div class="flex items-center mb-2">
<div class="flex items-center mr-2">
{lecture.resources
.map((r) => `${r.value} ${r.label}`)
.join(", ")}
</div>
</div>
<div class="flex items-center justify-between mt-3 w-full">
{#if lectureEditing === index}
<Select
bind:value={lecture.lecturer.name}
options={$lecturers}
valueKey="text"
/>
{:else}
<a
href="courses/1/people"
class="flex items-center hover:underline text-black"
>
<img
alt="Placeholder"
class="block rounded-full"
width="24"
height="20"
src={lecture.lecturer.avatar}
/>
<p class="ml-2 text-sm font-bold">{lecture.lecturer.name}</p>
</a>
{/if}
<div class="flex items-center">
{#if lectureEditing === index}
<input
type="date"
name="lecture-date-picker"
class="p-2 rounded-md w-40"
value={formatDate(lecture.date)}
on:input={(e) => (lecture.date = e.target.value)}
/>
{:else}
<Time24 class="carbon-icon" />
<p class="text-md font-semibold ml-2">
{new Date(lecture.date).toDateString()}
</p>
{/if}
</div>
</div>
</div>
</div>
{/each}
</div>
</PageBody>
</CourseContainer>
<style>
.group {
min-height: 170px;
}
</style>
+88
View File
@@ -0,0 +1,88 @@
<script context="module">
export async function preload({ params }) {
let [courseId, courseNavItem, lectureId] = params.id;
return { courseId, courseNavItem, lectureId };
}
</script>
<script>
import { stores } from "@sapper/app";
import CourseContainer from "../../../components/CourseContainer/index.svelte";
import PageNav from "../../../components/PageNav/index.svelte";
import UserCard from "../../../components/UserCard/index.svelte";
const { page } = stores();
const teachers = [
{
name: "Alexander Pokidin",
title: "Senior Software Engineer",
avatar: "https://i.pravatar.cc/150?img=1",
telegramLink: "https://t.me/seed_of_abraham",
mailLink: "mailto:irb.ossystem@gmail.com",
},
{
name: "Andrey Filatov",
title: "Fullstack Software Engineer",
avatar: "https://i.pravatar.cc/150?img=2",
telegramLink: "https://t.me/seed_of_abraham",
mailLink: "mailto:irb.ossystem@gmail.com",
},
{
name: "Sergey Semko",
title: "Senior Software Engineer",
avatar: "https://i.pravatar.cc/150?img=3",
telegramLink: "https://t.me/seed_of_abraham",
mailLink: "mailto:irb.ossystem@gmail.com",
},
{
name: "Natalia Fedii",
title: "Project Manager",
avatar: "https://i.pravatar.cc/150?img=4",
telegramLink: "https://t.me/seed_of_abraham",
mailLink: "mailto:irb.ossystem@gmail.com",
},
];
const students = [...teachers, ...teachers, ...teachers];
export let courseId;
</script>
<CourseContainer title="ReactJS" {courseId}>
<PageNav title="People" disableSticky={true} />
<div class="m-3">
<h3>
<a id="teachers" name="teachers" href="{$page.path}#teachers">Teachers</a>
</h3>
<div class="flex flex-wrap">
{#each teachers as teacher}
<UserCard
name={teacher.name}
avatarUrl={teacher.avatar}
title={teacher.title}
telegramLink={teacher.telegramLink}
mailLink={teacher.mailLink}
/>
{/each}
</div>
</div>
<div class="m-3">
<h3>
<a id="students" name="students" href="{$page.path}#students">Students</a>
</h3>
<div class="flex flex-wrap">
{#each students as student}
<UserCard
name={student.name}
avatarUrl={student.avatar}
title={student.title}
/>
{/each}
</div>
</div>
</CourseContainer>
@@ -0,0 +1,18 @@
<script context="module">
export async function preload({ params }) {
let [courseId, courseNavItem, lectureId] = params.id;
return { courseId, courseNavItem, lectureId };
}
</script>
<script>
import CourseContainer from "../../../components/CourseContainer/index.svelte";
import PageNav from "../../../components/PageNav/index.svelte";
export let courseId;
</script>
<CourseContainer title="ReactJS" {courseId}>
<PageNav title="Scoreboard" />
</CourseContainer>
@@ -0,0 +1,18 @@
<script context="module">
export async function preload({ params }) {
let [courseId, courseNavItem, lectureId] = params.id;
return { courseId, courseNavItem, lectureId };
}
</script>
<script>
import CourseContainer from "../../../components/CourseContainer/index.svelte";
import PageNav from "../../../components/PageNav/index.svelte";
export let courseId;
</script>
<CourseContainer title="ReactJS" {courseId}>
<PageNav title="Timetable" />
</CourseContainer>