[Classroom][FE] Request to enrollment to backend. Improve UI

This commit is contained in:
Araozu 2023-10-04 17:15:37 -05:00
parent 2f924d875c
commit f57c200163
6 changed files with 68 additions and 8 deletions

View File

@ -27,6 +27,8 @@ pub async fn get_courses(user_id: i32) -> (Status, Json<JsonResult<Vec<Classroom
} }
} }
#[options("/classroom/course/<_u>")]
pub fn register_course_contr_options(_u: i32) -> Status {Status::Ok}
#[post("/classroom/course/<user_id>", format = "json", data = "<data>")] #[post("/classroom/course/<user_id>", format = "json", data = "<data>")]
pub async fn register_course_contr(user_id: i32, data: Json<ClassroomCourseRegistration>) -> (Status, Json<JsonResult<()>>) { pub async fn register_course_contr(user_id: i32, data: Json<ClassroomCourseRegistration>) -> (Status, Json<JsonResult<()>>) {

View File

@ -62,6 +62,7 @@ async fn rocket() -> _ {
controller::classroom::create_user_options, controller::classroom::create_user_options,
controller::classroom::create_user, controller::classroom::create_user,
controller::classroom::get_courses, controller::classroom::get_courses,
controller::classroom::register_course_contr_options,
controller::classroom::register_course_contr, controller::classroom::register_course_contr,
], ],
) )

View File

@ -4,7 +4,10 @@ import { ClassroomRegistrationPreview } from "./ClassroomRegistrationPreview";
import { ClassroomSearchableSelect } from "./ClassroomSearchableSelect"; import { ClassroomSearchableSelect } from "./ClassroomSearchableSelect";
import { ClassroomCourseValue } from "../types/ClassroomCourse"; import { ClassroomCourseValue } from "../types/ClassroomCourse";
export function ClassroomRegistration() { export function ClassroomRegistration(props: {
surname_first_letter: string, userId: number | null,
onSuccess: () => void,
}) {
const [selections, setSelections] = createSignal<Array<ClassroomCourseValue>>([]); const [selections, setSelections] = createSignal<Array<ClassroomCourseValue>>([]);
return ( return (
@ -20,8 +23,11 @@ export function ClassroomRegistration() {
</FilledCard> </FilledCard>
<ClassroomRegistrationPreview <ClassroomRegistrationPreview
surname_first_letter={props.surname_first_letter}
userId={props.userId}
selections={selections()} selections={selections()}
deleteRegister={(course_key) => setSelections((course) => course.filter((v) => v !== course_key))} deleteRegister={(course_key) => setSelections((course) => course.filter((v) => v !== course_key))}
onSuccess={props.onSuccess}
/> />
</div> </div>
); );

View File

@ -1,19 +1,52 @@
import { For, createMemo } from "solid-js"; import { For, createMemo } from "solid-js";
import { FilledCard } from "../components/FilledCard"; import { FilledCard } from "../components/FilledCard";
import { LoadingIcon } from "../icons/LoadingIcon"; import { LoadingIcon } from "../icons/LoadingIcon";
import { LoadingStatus, useLoading } from "../utils/functions"; import { LoadingStatus, backend, useLoading, wait } from "../utils/functions";
import { ClassroomCourseValue, allClassrooomCourses } from "../types/ClassroomCourse"; import { ClassroomCourseValue, allClassrooomCourses } from "../types/ClassroomCourse";
import { XIcon } from "../icons/XIcon"; import { XIcon } from "../icons/XIcon";
import { JsonResult } from "../types/JsonResult";
import { AxiosError } from "axios";
export function ClassroomRegistrationPreview(props: { export function ClassroomRegistrationPreview(props: {
surname_first_letter: string,
userId: number | null,
selections: Array<ClassroomCourseValue>, selections: Array<ClassroomCourseValue>,
deleteRegister: (k: string) => void, deleteRegister: (k: string) => void,
onSuccess: () => void,
}) { }) {
const {status} = useLoading(); const {status, setStatus, setError} = useLoading();
const loading = createMemo(() => status() === LoadingStatus.Loading); const loading = createMemo(() => status() === LoadingStatus.Loading);
const submit = async() => { const submit = async() => {
if (props.userId === null) return;
setStatus(LoadingStatus.Loading);
if (import.meta.env.DEV) await wait(1500);
backend.post<JsonResult<null>>(`/api/classroom/course/${props.userId}`, {
surname_first_letter: "A",
courses: props.selections,
})
.then((response) => {
if (response.status === 200) {
setStatus(LoadingStatus.Ok);
props.onSuccess();
} else {
console.error(response.data);
setError(response.data.Err.reason);
setStatus(LoadingStatus.Error);
}
})
.catch((err: AxiosError<JsonResult<null>>) => {
console.error(err);
if (err.response?.data?.Err?.reason) {
setError(err.response.data.Err.reason);
}
setStatus(LoadingStatus.Error);
});
}; };
return ( return (
@ -40,7 +73,7 @@ export function ClassroomRegistrationPreview(props: {
class="bg-c-primary text-c-on-primary px-4 py-2 rounded-full cursor-pointer mt-4 class="bg-c-primary text-c-on-primary px-4 py-2 rounded-full cursor-pointer mt-4
disabled:opacity-50 disabled:cursor-not-allowed relative" disabled:opacity-50 disabled:cursor-not-allowed relative"
type="button" type="button"
disabled={props.selections.length === 0 || loading()} disabled={props.userId === null || props.selections.length === 0 || loading()}
onclick={submit} onclick={submit}
> >
<span <span

View File

@ -1,16 +1,17 @@
import { For, Show, createSignal, onMount } from "solid-js"; import { For, Show, createEffect, createSignal, onMount } from "solid-js";
import { LoadingStatus, backend, useLoading, wait } from "../utils/functions"; import { LoadingStatus, backend, useLoading, wait } from "../utils/functions";
import { JsonResult } from "../types/JsonResult"; import { JsonResult } from "../types/JsonResult";
import { ClassroomCourse } from "../types/ClassroomCourse"; import { ClassroomCourse } from "../types/ClassroomCourse";
import { LoadingIcon } from "../icons/LoadingIcon"; import { LoadingIcon } from "../icons/LoadingIcon";
export function ClassroomUserCourses(props: {userid: number}) { export function ClassroomUserCourses(props: {userid: number, updateSignal: number}) {
const [courses, setCourses] = createSignal<Array<ClassroomCourse>>([]); const [courses, setCourses] = createSignal<Array<ClassroomCourse>>([]);
const {setError, status, setStatus} = useLoading(); const {setError, status, setStatus} = useLoading();
const loadCourses = async() => { const loadCourses = async() => {
setStatus(LoadingStatus.Loading); setStatus(LoadingStatus.Loading);
setError(""); setError("");
setCourses([]);
if (import.meta.env.DEV) await wait(1500); if (import.meta.env.DEV) await wait(1500);
@ -29,6 +30,14 @@ export function ClassroomUserCourses(props: {userid: number}) {
onMount(loadCourses); onMount(loadCourses);
createEffect(() => {
// Update courses when updateSignal changes
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const _ = props.updateSignal;
loadCourses();
});
return ( return (
<div class="w-full"> <div class="w-full">
<h2 class="text-2xl"> <h2 class="text-2xl">

View File

@ -11,12 +11,18 @@ type TabType = "Vinculate" | "Create";
export function OnlineClassroom() { export function OnlineClassroom() {
const [person, setPerson] = createSignal<Person | null>(null); const [person, setPerson] = createSignal<Person | null>(null);
// Used to update ClassroomUserCourses
const [updateSignal, setUpdateSIgnal] = createSignal(0);
return ( return (
<div class="grid grid-cols-[16rem_25rem_1fr]"> <div class="grid grid-cols-[16rem_25rem_1fr]">
<Search setPerson={setPerson} /> <Search setPerson={setPerson} />
<ClassroomRegistration /> <ClassroomRegistration
surname_first_letter={person()?.person_paternal_surname[0] ?? ""}
userId={person()?.person_classroom_id ?? null}
onSuccess={() => setUpdateSIgnal((s) => s + 1)}
/>
<Show when={person() !== null && person()!.person_classroom_id === null}> <Show when={person() !== null && person()!.person_classroom_id === null}>
<ClassroomUser <ClassroomUser
@ -25,7 +31,10 @@ export function OnlineClassroom() {
/> />
</Show> </Show>
<Show when={person() !== null && person()!.person_classroom_id !== null}> <Show when={person() !== null && person()!.person_classroom_id !== null}>
<ClassroomUserCourses userid={person()!.person_classroom_id!} /> <ClassroomUserCourses
userid={person()!.person_classroom_id!}
updateSignal={updateSignal()}
/>
</Show> </Show>
</div> </div>