eeg_certs/frontend/src/OnlineClassroom/ClassroomVinculation.tsx
2023-10-03 17:55:58 -05:00

149 lines
5.2 KiB
TypeScript

import { ClassroomRegistrationUser } from "../types/ClassroomRegistrationUser";
import { QuestionIcon } from "../icons/QuestionIcon";
import { JsonResult } from "../types/JsonResult";
import { XcircleIcon } from "../icons/XCircleIcon";
import { LoadingStatus, backend, useLoading, wait } from "../utils/functions";
import { LinkIcon } from "../icons/LinkIcon";
import { For, Show, createSignal, onMount } from "solid-js";
import { LoadingIcon } from "../icons/LoadingIcon";
type Status = "Init" | "Ok" | "Loading" | "Error";
export function ClassroomVinculation(props: {person_surname: string, personId: number, onLink: (classroom_id: number) => void,}) {
const [classroomUsers, setClassroomUsers] = createSignal<ClassroomRegistrationUser[]>([]);
const [error, setError] = createSignal("");
const [status, setStatus] = createSignal<Status>("Init");
const loadUsers = async() => {
setStatus("Loading");
const response = await fetch(`${import.meta.env.VITE_BACKEND_URL}/api/classroom/users/${encodeURIComponent(props.person_surname)}`);
const json: JsonResult<Array<ClassroomRegistrationUser>> = await response.json();
if (response.ok) {
setClassroomUsers(json.Ok);
setStatus("Ok");
} else {
console.error("Error loading users", json);
setError(json.Err.reason);
setStatus("Error");
}
};
onMount(loadUsers);
return (
<div>
<p class="py-2 px-4">
Vincule un usuario existente:
</p>
<Show when={status() === "Loading"}>
<div class="text-center h-12 scale-150">
<LoadingIcon class="animate-spin" fill="var(--c-primary)" />
</div>
</Show>
<Show when={status() === "Ok"}>
<Show when={classroomUsers().length === 0}>
<div class="px-4 pb-2">
<div class="text-center pt-6 pb-4">
<QuestionIcon class="scale-[200%]" fill="var(--c-outline)" />
</div>
<p>No se encontraron usuarios en el aula virtual.</p>
</div>
</Show>
<For each={classroomUsers()}>
{(u) => (
<ClassroomSingleUser
user={u}
personId={props.personId}
onLink={props.onLink}
/>
)}
</For>
</Show>
<Show when={status() === "Error"}>
<div class="px-4 pb-2 text-c-error">
<div class="text-center pt-6 pb-4">
<XcircleIcon class="scale-[200%]" fill="var(--c-error)" />
</div>
<p>Error buscando usuarios: {error()}.</p>
</div>
</Show>
</div>
);
}
function ClassroomSingleUser(props: {
user: ClassroomRegistrationUser,
onLink: (classroom_id: number) => void,
personId: number,
}) {
const {setError, status, setStatus} = useLoading();
const linkUser = async() => {
setStatus(LoadingStatus.Loading);
if (import.meta.env.DEV) await wait(1500);
backend.put<JsonResult<null>>(
"/api/person/link",
{
person_id: props.personId,
person_classroom_id: parseInt(props.user.user_id, 10),
},
)
.then((response) => {
if (response.status === 200) {
setStatus(LoadingStatus.Ok);
props.onLink(parseInt(props.user.user_id, 10));
} else {
console.error(response.data);
setError(response.data.Err.reason);
setStatus(LoadingStatus.Error);
}
})
.catch((err) => {
setError(`Error fatal: ${err.message}`);
console.error(err);
setStatus(LoadingStatus.Error);
});
};
return (
<div
class="hover:bg-c-surface-variant hover:text-c-on-surface-variant transition-colors
grid grid-cols-[auto_3rem] gap-4"
>
<div class="pl-4 py-2">
{props.user.name} {props.user.surname}
<br />
<div class="grid grid-cols-[auto_10rem]">
<span class="font-mono">
{props.user.username}
</span>
<div>
registrado:&nbsp;
<span class="font-mono">
??/??/????
</span>
</div>
</div>
</div>
<button
title="Vincular usuario"
class="border-2 border-c-transparent hover:border-c-primary transition-colors rounded"
onclick={linkUser}
disabled={status() === LoadingStatus.Loading}
>
<LinkIcon fill="var(--c-primary)" />
</button>
</div>
);
}