CRUD* Lecture

This commit is contained in:
Ibitoye Rotimi Best
2021-07-08 09:44:16 +03:00
parent 44d612488b
commit 7941b0b51f
13 changed files with 391 additions and 66 deletions
@@ -1,5 +1,6 @@
<script>
import { onMount } from "svelte";
import CheckmarkFilled20 from "carbon-icons-svelte/lib/CheckmarkFilled20";
import hotkeys from "hotkeys-js";
import ChevronLeft32 from "carbon-icons-svelte/lib/ChevronLeft32";
import ChevronRight32 from "carbon-icons-svelte/lib/ChevronRight32";
@@ -9,6 +10,8 @@
import IconButton from "../../IconButton/index.svelte";
import { getNavItemRoute, getLectureRoute, getLectureNo } from "../function";
import { lessons } from "./Lecture/store/lessons";
// export let lectureId;
export let courseId;
@@ -32,33 +35,7 @@
label: "Lectures",
to: getLectureRoute(courseId),
hideSortIcon: false,
items: [
{
id: 1,
title: "Вводный урок. Soft skills",
to: getLectureRoute(courseId, 1),
},
{
id: 2,
title: "Введение в ReactJS",
to: getLectureRoute(courseId, 2),
},
{
id: 3,
title: "Компоненты",
to: getLectureRoute(courseId, 3),
},
{
id: 4,
title: "Состояние компонентов и пропсы",
to: getLectureRoute(courseId, 4),
},
{
id: 5,
title: "Жизненный цикл",
to: getLectureRoute(courseId, 5),
},
],
isLecture: true,
},
{
label: "People",
@@ -92,6 +69,8 @@
}
});
});
$: console.log("lessons", $lessons);
</script>
<div class="root z-10 {!show && 'hide'}">
@@ -105,16 +84,24 @@
isGroupActive={$page.path === navItem.to}
hideSortIcon={navItem.hideSortIcon}
>
{#if Array.isArray(navItem.items)}
{#each navItem.items as item, index}
{#if navItem.isLecture}
{#each $lessons as item, index}
<a
class="item flex items-center {(item.to === $page.path ||
!$page.path.length > 3) &&
'active'} pl-7 py-2"
href={item.to}
'active'} pl-7 py-2 {!item.isComplete &&
'cursor-not-allowed'}"
href={item.isComplete ? item.to : $page.path}
>
<span class="course-counter"> {getLectureNo(index + 1)} </span>
<span>{item.title}</span>
{#if item.isComplete}
<span class="ml-2 success">
<CheckmarkFilled20 class="carbon-icon" />
</span>
{:else}
<span class="text-md ml-2">🔒</span>
{/if}
</a>
{/each}
{/if}
@@ -146,13 +133,15 @@
height: 90vh;
display: flex;
flex-direction: column;
width: 360px;
min-width: 360px;
max-width: 360px;
position: sticky;
top: 0;
border-right: 1px solid var(--border-color);
&.hide {
width: 0px;
min-width: 0px;
max-width: 0px;
}
}
@@ -1,8 +1,149 @@
<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" />
<PageNav title="Lectures">
<div slot="widget">
<PrimaryButton label="Add" onClick={addLesson} />
</div>
</PageNav>
<PageBody>All lecture will be here</PageBody>
<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-5 -top-5 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>
@@ -7,11 +7,12 @@
export let path;
export let tab;
// export let lectureId;
export let showLectureHome;
</script>
{#if showLectureHome}
<Home />
<Home {path} />
{:else}
<div>
<PageNav
@@ -0,0 +1,187 @@
import { writable } from "svelte/store";
export const lessons = writable([
{
title: "Вступительное слово. Софт скилы",
to: "/courses/1/lecture/1",
lecturer: {
userId: 1,
avatar: "https://picsum.photos/32/32/?random",
name: "Sergey Semko",
},
resources: [
{
label: "lesson",
value: 1,
},
{
label: "quiz",
value: 1,
},
{
label: "home task",
value: 2,
},
],
date: new Date(),
isComplete: true,
},
{
title: "Введение в ReactJS",
to: "/courses/1/lecture/2",
lecturer: {
userId: 1,
avatar: "https://picsum.photos/32/32/?random",
name: "Sergey Semko",
},
resources: [
{
label: "lesson",
value: 1,
},
{
label: "quiz",
value: 1,
},
{
label: "home task",
value: 2,
},
],
date: new Date(),
isComplete: false,
},
{
title: "Компоненты",
to: "/courses/1/lecture/3",
lecturer: {
userId: 1,
avatar: "https://picsum.photos/32/32/?random",
name: "Sergey Semko",
},
resources: [
{
label: "lesson",
value: 1,
},
{
label: "quiz",
value: 1,
},
{
label: "home task",
value: 2,
},
],
date: new Date(),
isComplete: false,
},
{
title: "Состояние компонентов и пропсы",
to: "/courses/1/lecture/4",
lecturer: {
userId: 1,
avatar: "https://picsum.photos/32/32/?random",
name: "Sergey Semko",
},
resources: [
{
label: "lesson",
value: 1,
},
{
label: "quiz",
value: 1,
},
{
label: "home task",
value: 2,
},
],
date: new Date(),
isComplete: false,
},
{
title: "Жизненный цикл",
to: "/courses/1/lecture/5",
lecturer: {
userId: 1,
avatar: "https://picsum.photos/32/32/?random",
name: "Sergey Semko",
},
resources: [
{
label: "lesson",
value: 1,
},
{
label: "quiz",
value: 1,
},
{
label: "home task",
value: 2,
},
],
date: new Date(),
isComplete: false,
},
]);
export const lecturers = writable([
{
id: 1,
text: "Sergey Semko",
},
{
id: 3,
text: "Jonathan Nelson",
},
{
id: 4,
text: "Sasha Pokidin",
},
{
id: 5,
text: "Natasha Rudenko",
},
{
id: 6,
text: "Yulia Marushko",
},
]);
export function handleAddLesson() {
const resources = [
{
label: "lesson",
value: 0,
},
{
label: "quiz",
value: 0,
},
{
label: "home task",
value: 0,
},
];
lessons.update(_lessons => {
return [
..._lessons,
{
title: 'Untitled lesson',
to: "/courses/1/lecture/" + (_lessons.length + 1),
resources,
lecturer: {
userId: 1,
avatar: "https://picsum.photos/32/32/?random",
name: "",
},
date: new Date()
}
]
})
}
@@ -54,7 +54,8 @@
avatarUrl={teacher.avatar}
title={teacher.title}
telegramLink={teacher.telegramLink}
mailLink={teacher.mailLink} />
mailLink={teacher.mailLink}
/>
{/each}
</div>
</div>
@@ -68,7 +69,8 @@
<UserCard
name={student.name}
avatarUrl={student.avatar}
title={student.title} />
title={student.title}
/>
{/each}
</div>
</div>
+1 -1
View File
@@ -9,7 +9,7 @@
// export let subMenuItems = [];
function onClick() {
isExpanded = !isExpanded;
// isExpanded = !isExpanded;
handleClick();
}
</script>
+2 -1
View File
@@ -2,13 +2,14 @@
export let label;
export let value;
export let options = [];
export let valueKey = "id";
</script>
<label class="block">
{#if label} <span class="text-gray-700">{label}</span> {/if}
<select bind:value class="form-select block w-full mt-1">
{#each options as option}
<option value={option.id}>
<option value={option[valueKey]}>
{option.text}
</option>
{/each}
+2
View File
@@ -4,6 +4,7 @@
export let value;
export let onKeyDown;
export let className = "";
export let autofocus = false;
</script>
<label class="block {className}">
@@ -14,5 +15,6 @@
on:keydown={onKeyDown}
{placeholder}
bind:value
autofocus
/>
</label>
+2 -5
View File
@@ -1,9 +1,10 @@
<script>
// import
// border border-gray-300 rounded-md p-3 bg-blue-200 bg-opacity-25
export let width = "max-w-3xl";
</script>
<div class="root mt-4 mx-auto max-w-3xl relative pb-5">
<div class="mt-4 mx-auto {width} relative pb-5">
{#if $$slots.header}
<div
class="head flex bg-white items-center justify-between sticky right-0 w-full py-3"
@@ -16,10 +17,6 @@
</div>
<style>
/* .root {
max-width: 700px;
} */
.head {
top: 61px;
z-index: 1;
+1
View File
@@ -6,6 +6,7 @@
export let addButtonHref;
export let addButtonLabel;
export let disableSticky = false;
let dynamicRootClass = "";
$: dynamicRootClass =
+2 -2
View File
@@ -57,11 +57,11 @@
}
[aria-current] :global(svg.carbon-icon),
button.active :global(svg.carbon-icon) {
.active :global(svg.carbon-icon) {
fill: var(--main-primary-color);
}
button.success :global(svg.carbon-icon) {
.success :global(svg.carbon-icon) {
fill: green;
}
</style>
+17 -18
View File
@@ -11,27 +11,14 @@
export let telegramLink;
</script>
<style>
.profile {
width: 200px;
}
.profile img {
width: 104px;
height: 104px;
}
.description {
min-height: 70px;
}
</style>
<figure class="profile bg-gray-100 rounded-xl px-4 py-7 mr-4 mb-4">
<figure class="w-52 bg-gray-100 px-4 py-7 mr-4 mb-4">
<img
class="w-32 h-32 rounded-full mx-auto"
src={avatarUrl}
alt=""
width="384"
height="512" />
height="512"
/>
<div class="pt-6 text-center space-y-4">
<div class="description font-medium flex flex-col justify-around">
<div class="text-cyan-600">{name}</div>
@@ -45,15 +32,27 @@
data={faTelegram}
scale="1"
class="social-icon"
style="color:#4dabf7;margin:0 5px;" />
style="color:#4dabf7;margin:0 5px;"
/>
</a>
<a href={mailLink} target="_blank">
<Icon
data={faEnvelope}
scale="1"
class="social-icon"
style="color:#d44c3d;margin:0 5px;" />
style="color:#d44c3d;margin:0 5px;"
/>
</a>
</div>
{/if}
</figure>
<style>
img {
width: 104px;
height: 104px;
}
.description {
min-height: 70px;
}
</style>
+6 -1
View File
@@ -44,7 +44,12 @@
{:else if courseNavItem === "hometasks"}
<HomeTask />
{:else if courseNavItem === "lecture"}
<Lecture path={$page.path} {tab} showLectureHome={!lectureId} />
<Lecture
path={$page.path}
{tab}
{lectureId}
showLectureHome={!lectureId}
/>
{:else if courseNavItem === "people"}
<People />
{/if}