aboutsummaryrefslogtreecommitdiff
path: root/src/components/AssignLabs
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/AssignLabs')
-rw-r--r--src/components/AssignLabs/AssignLabs.svelte151
-rw-r--r--src/components/AssignLabs/LabBox.svelte32
-rw-r--r--src/components/AssignLabs/PTBox.svelte44
3 files changed, 227 insertions, 0 deletions
diff --git a/src/components/AssignLabs/AssignLabs.svelte b/src/components/AssignLabs/AssignLabs.svelte
new file mode 100644
index 0000000..3a326ad
--- /dev/null
+++ b/src/components/AssignLabs/AssignLabs.svelte
@@ -0,0 +1,151 @@
+<script lang="ts">
+ import type PeerTeacher from "../../models/PeerTeacher";
+ import { labStore, ptStore } from "../../stores";
+ import Lab from "./LabBox.svelte";
+ import PT from "./PTBox.svelte";
+ import { onMount } from "svelte";
+ import { parseDatabaseLocal } from "../../util/parser";
+
+ let selectedPeerTeacher: PeerTeacher | 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);
+
+ $: assignedLabs = [...(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) =>
+ // Lab not already assigned
+ !lab.assigned &&
+ // PT schedule not conflict with lab
+ !selectedPeerTeacher?.conflictsWith(lab.event) &&
+ // PT's labs not conflict with this lab
+ !assignedLabs.some((assignment) =>
+ assignment.event.conflictsWith(lab.event)
+ )
+ );
+
+ function updateReactiveDeclarations() {
+ selectedPeerTeacher = selectedPeerTeacher;
+ 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();
+ }
+
+ // Load db from local storage so I don't have to keep uploading
+ onMount(() => {
+ const db = localStorage.getItem("db");
+ if (db) {
+ parseDatabaseLocal(JSON.parse(db));
+ }
+ });
+</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={selectedPeerTeacher == pt
+ ? "border-l-8 border-blue-500"
+ : ""}
+ 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</div>
+ <div class="assign-box-body">
+ {#each compatibleLabs as lab}
+ <svelte:component
+ this={Lab}
+ {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 assignedLabs as lab}
+ <svelte:component
+ this={Lab}
+ {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</h1>
+ <div
+ class="flex flex-row overflow-auto border-y-4 mt-1 border-slate-500 w-full items-center text-sm"
+ >
+ {#each unassignedLabs as lab}
+ <div
+ class="hover:animate-bounce border rounded-xl hover:bg-sky-100 hover:text-black px-3 py-1 mx-2"
+ >
+ <p>{lab.course}</p>
+ <p>{lab.section}</p>
+ </div>
+ {/each}
+ </div>
+ </div>
+</div>
diff --git a/src/components/AssignLabs/LabBox.svelte b/src/components/AssignLabs/LabBox.svelte
new file mode 100644
index 0000000..9805c51
--- /dev/null
+++ b/src/components/AssignLabs/LabBox.svelte
@@ -0,0 +1,32 @@
+<script lang="ts">
+ import type Lab from "../../models/Lab";
+ import Icon from "../helpers/Icon.svelte";
+ export let lab: Lab;
+ export let iconClick = () => {};
+ export let iconName: string;
+</script>
+
+<!-- Lab box -->
+<div
+ class="block border-b px-3 py-3 hover:bg-sky-100 hover:text-black h-20 overflow-hidden"
+>
+ <!-- Lab content -->
+ <div class="flex flex-col">
+ <!-- Top Half -->
+ <div class="flex flex-row">
+ <strong class="flex-grow">CSCE {lab.course} - {lab.section}</strong>
+ <Icon
+ name={iconName}
+ class="h-6 w-6"
+ handleClick={() => {
+ iconClick();
+ }}
+ />
+ </div>
+ </div>
+ <!-- Bottom half -->
+ <div>
+ <p class="text-xs">{lab.event.info}</p>
+ <p class="text-xs">{lab.building} {lab.room}</p>
+ </div>
+</div>
diff --git a/src/components/AssignLabs/PTBox.svelte b/src/components/AssignLabs/PTBox.svelte
new file mode 100644
index 0000000..3ad50d1
--- /dev/null
+++ b/src/components/AssignLabs/PTBox.svelte
@@ -0,0 +1,44 @@
+<script lang="ts">
+ import type PeerTeacher from "../../models/PeerTeacher";
+ import Icon from "../helpers/Icon.svelte";
+ export let pt: PeerTeacher;
+
+ let modalID = () => {
+ return `my-modal-${pt.id}`;
+ }
+</script>
+
+<!-- PT Box -->
+<div
+ class="block border-b px-3 py-3 hover:bg-sky-100 hover:text-black h-20 overflow-hidden group"
+>
+ <!-- Top half, name and button -->
+ <div class="flex flex-row items-center ">
+ <!-- Left half, name -->
+ <strong class="flex-grow text-sm">{pt.name}</strong>
+
+ <!-- Right half, button -->
+ <!-- The button to open modal -->
+ <label for={modalID()} class="">
+ <Icon name="info" class="h-6 w-6" />
+ </label>
+
+ <!-- Modal PT event info -->
+ <input type="checkbox" id={modalID()} class="modal-toggle" />
+ <label for={modalID()} class="modal cursor-pointer">
+ <label class="modal-box relative bg-slate-300" for="">
+ <h3 class="text-lg font-bold font-serif underline">
+ {pt.name}
+ </h3>
+ {#each pt.events as e}
+ <p class="py-2">
+ {e.info}
+ </p>
+ {/each}
+ </label>
+ </label>
+ </div>
+
+ <!-- Bottom half, hours -->
+ <div class="">Hours: {pt.lab_hours}</div>
+</div>