aboutsummaryrefslogtreecommitdiff
path: root/src/components/AssignLabs.svelte
diff options
context:
space:
mode:
authorFurkan Sahin <furkan-dev@proton.me>2022-07-23 23:38:33 -0500
committerFurkan Sahin <furkan-dev@proton.me>2022-07-23 23:38:33 -0500
commite4915154c6bb71b3d0fb8da6e971783156548b8e (patch)
tree0894a1c35280389e2c7d1067cfcb734712d93c17 /src/components/AssignLabs.svelte
parent31530fcb5b881d3ac83f202f0b2c913aba935b8b (diff)
Restructure file organization
Diffstat (limited to 'src/components/AssignLabs.svelte')
-rw-r--r--src/components/AssignLabs.svelte151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/components/AssignLabs.svelte b/src/components/AssignLabs.svelte
new file mode 100644
index 0000000..6ff006f
--- /dev/null
+++ b/src/components/AssignLabs.svelte
@@ -0,0 +1,151 @@
+<script lang="ts">
+ import type PeerTeacher from "../models/PeerTeacher";
+ import type Lab from "../models/Lab";
+ import { labStore, ptStore } from "../stores";
+ import LabBox from "./helpers/LabBox.svelte";
+ import PT from "./helpers/PTBox.svelte";
+
+ let selectedPeerTeacher: PeerTeacher | undefined;
+ let selectedLab: Lab | undefined;
+
+ $: peerTeachers = [...$ptStore.values()].sort((a, b) =>
+ a.lastname.toUpperCase() === b.lastname.toUpperCase()
+ ? a.firstname.toUpperCase().localeCompare(b.firstname.toUpperCase())
+ : a.lastname.toUpperCase().localeCompare(b.lastname.toUpperCase())
+ );
+
+ $: labs = [...$labStore.values()].sort((a, b) => a.id - b.id);
+
+ $: selectedPtAssignedLabs = [...(selectedPeerTeacher?.labs.values() ?? [])]
+ .flatMap((labId) => {
+ const lab = $labStore.get(labId);
+ return lab === undefined ? [] : [lab];
+ })
+ .sort((a, b) => a.id - b.id);
+
+ $: unassignedLabs = labs.filter((lab) => !lab.assigned);
+
+ $: compatibleLabs = labs.filter((lab) =>
+ isPTandLabCompatible(lab, selectedPeerTeacher)
+ );
+
+ $: compatiblePTs = peerTeachers.filter((pt) =>
+ isPTandLabCompatible(selectedLab, pt)
+ );
+
+ function isPTandLabCompatible(
+ lab: Lab | undefined,
+ pt: PeerTeacher | undefined
+ ): boolean {
+ return (
+ pt != undefined &&
+ lab != undefined &&
+ !lab?.assigned &&
+ !pt?.conflictsWith(lab.event)
+ );
+ }
+
+ function updateReactiveDeclarations() {
+ selectedPeerTeacher = selectedPeerTeacher;
+ selectedLab = selectedLab;
+ peerTeachers = peerTeachers;
+ labs = labs;
+ }
+
+ function assignLab(id: number) {
+ const lab = $labStore.get(id);
+ if (lab === undefined) return;
+ lab.assigned = true;
+ selectedPeerTeacher?.labs.add(id);
+ updateReactiveDeclarations();
+ }
+
+ function unassignLab(id: number) {
+ const lab = $labStore.get(id);
+ if (lab === undefined) return;
+ lab.assigned = false;
+ selectedPeerTeacher?.labs.delete(id);
+ updateReactiveDeclarations();
+ }
+</script>
+
+<div
+ class="flex-none overflow-hidden flex-col h-[100vh] w-[80vw] px-[2vw] pt-[1vh]"
+>
+ <!-- Top half: 3 Columns -->
+ <div class="flex flex-row h-[80vh]">
+ <!-- PT Box -->
+ <div class="assign-box rounded-l-xl">
+ <!-- PT Header -->
+ <div class="assign-box-header">Peer Teacher</div>
+ <!-- PT Body -->
+ <div class="assign-box-body">
+ {#each peerTeachers as pt}
+ <div
+ class={compatiblePTs.includes(pt) //selectedPeerTeacher == pt
+ ? "bg-info text-info-content" // "border-l-8 border-blue-500"
+ : "bg-base-100 text-base-100-content"}
+ on:click={() => {
+ selectedPeerTeacher = pt;
+ }}
+ >
+ <svelte:component this={PT} {pt} />
+ </div>
+ {/each}
+ </div>
+ </div>
+
+ <!-- Available Labs -->
+ <div class="assign-box">
+ <div class="assign-box-header">Labs: {labs.length}</div>
+ <div class="assign-box-body">
+ {#each compatibleLabs as lab}
+ <svelte:component
+ this={LabBox}
+ {lab}
+ iconName="plus-circle"
+ iconClick={() => {
+ assignLab(lab.id);
+ }}
+ />
+ {/each}
+ </div>
+ </div>
+
+ <!-- Selected PT's Labs -->
+ <div class="assign-box rounded-r-xl">
+ <div class="assign-box-header">
+ {selectedPeerTeacher?.name ?? "PT's Labs"}
+ </div>
+ <div class="assign-box-body">
+ {#each selectedPtAssignedLabs as lab}
+ <svelte:component
+ this={LabBox}
+ {lab}
+ iconName="minus-circle"
+ iconClick={() => {
+ unassignLab(lab.id);
+ }}
+ />
+ {/each}
+ </div>
+ </div>
+ </div>
+
+ <!-- Bottom half: Universal unassigned labs -->
+ <div class="flex flex-col mt-2 text-center">
+ <h1>Unassigned Labs: {unassignedLabs.length}</h1>
+ <ul class="menu menu-horizontal bg-base-100 rounded-box overflow-auto">
+ {#each unassignedLabs as lab}
+ <li
+ on:click={() => {
+ selectedLab = lab;
+ }}
+ class={selectedLab == lab ? "bg-info text-info-content" : ""}
+ >
+ <span>{lab.course} {lab.section}</span>
+ </li>
+ {/each}
+ </ul>
+ </div>
+</div>