[FE][Certs] Refactor courses context to its own file
This commit is contained in:
parent
1feeb70af8
commit
b3bfa4a82c
44
frontend/src/certs/CertsImpl.tsx
Normal file
44
frontend/src/certs/CertsImpl.tsx
Normal file
@ -0,0 +1,44 @@
|
||||
import { Show, createSignal } from "solid-js";
|
||||
import { NewRegister } from "./NewRegister";
|
||||
import { Registers } from "./Registers";
|
||||
import { Search } from "./Search";
|
||||
import { Person } from "../types/Person";
|
||||
import { useCourses } from "./CourseContext";
|
||||
|
||||
export function CertsImpl() {
|
||||
const [person, setPerson] = createSignal<Person | null>(null);
|
||||
const [count, setCount] = createSignal(0);
|
||||
const courses = useCourses()!;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div class={`top-0 left-0 w-screen h-1 ${courses.loading() ? "fixed" : "hidden"}`}>
|
||||
<div class='h-1 w-full bg-c-on-primary overflow-hidden'>
|
||||
<div class='progress w-full h-full bg-c-primary left-right' />
|
||||
</div>
|
||||
</div>
|
||||
<Show when={!courses.errored()}>
|
||||
<div class={`grid grid-cols-[16rem_25rem_1fr] ${courses.ready() ? "" : "opacity-25"}`}>
|
||||
<Search setPerson={setPerson} />
|
||||
<NewRegister
|
||||
personId={person()?.person_id ?? null}
|
||||
onSuccess={() => setCount((x) => x + 1)}
|
||||
/>
|
||||
<Registers person={person()} count={count()} />
|
||||
</div>
|
||||
</Show>
|
||||
<Show when={courses.errored()}>
|
||||
<div>
|
||||
<div class="p-2 m-8 text-c-on-error bg-c-error rounded-md">
|
||||
Error al cargar recursos vitales del sistema (lista de cursos)
|
||||
<br />
|
||||
Recargue la página para intentar de nuevo
|
||||
<br />
|
||||
<br />
|
||||
{courses?.errorMessage()}
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
</>
|
||||
);
|
||||
}
|
81
frontend/src/certs/CourseContext.tsx
Normal file
81
frontend/src/certs/CourseContext.tsx
Normal file
@ -0,0 +1,81 @@
|
||||
import { JSX, Resource, createContext, createMemo, createResource, useContext } from "solid-js";
|
||||
import axios from "axios";
|
||||
import { Course } from "../types/Course";
|
||||
|
||||
const CoursesContext = createContext<{
|
||||
data: Resource<Course[]>,
|
||||
nameMap: () => {[course_name: string]: Course},
|
||||
idMap: () => {[course_name: string]: Course},
|
||||
loading: () => boolean,
|
||||
ready: () => boolean,
|
||||
errored: () => boolean,
|
||||
errorMessage: () => string,
|
||||
}>();
|
||||
|
||||
export function CoursesProvider(props: {children: JSX.Element}) {
|
||||
const [courses] = createResource(fetchAllCourses);
|
||||
|
||||
const courseMapMemo = createMemo(() => {
|
||||
if (courses === undefined || courses?.state !== "ready") {
|
||||
return {};
|
||||
}
|
||||
|
||||
const data = courses();
|
||||
|
||||
type CourseMap = {[course_name: string]: Course};
|
||||
const map: CourseMap = {};
|
||||
for (const course of data) {
|
||||
map[course.course_name] = course;
|
||||
}
|
||||
|
||||
return map;
|
||||
});
|
||||
|
||||
const courseIdMapMemo = createMemo(() => {
|
||||
if (courses === undefined || courses?.state !== "ready") {
|
||||
return {};
|
||||
}
|
||||
|
||||
const data = courses();
|
||||
|
||||
type CourseMap = {[course_id: number]: Course};
|
||||
const map: CourseMap = {};
|
||||
for (const course of data) {
|
||||
map[course.course_id] = course;
|
||||
}
|
||||
|
||||
return map;
|
||||
});
|
||||
|
||||
const coursesData = {
|
||||
data: courses,
|
||||
nameMap: courseMapMemo,
|
||||
idMap: courseIdMapMemo,
|
||||
loading: createMemo(() => courses.state === "pending"),
|
||||
ready: createMemo(() => courses.state === "ready"),
|
||||
errored: createMemo(() => courses.state === "errored"),
|
||||
errorMessage: createMemo(() => courses.error?.message ?? ""),
|
||||
};
|
||||
|
||||
return (
|
||||
<CoursesContext.Provider value={coursesData}>
|
||||
{props.children}
|
||||
</CoursesContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
let cachedCourses: Array<Course> | null = null;
|
||||
|
||||
async function fetchAllCourses(): Promise<Array<Course>> {
|
||||
if (cachedCourses !== null) {
|
||||
return cachedCourses;
|
||||
}
|
||||
|
||||
const result = await axios.get<Array<Course>>(`${import.meta.env.VITE_BACKEND_URL}/api/course`);
|
||||
cachedCourses = result.data;
|
||||
return result.data;
|
||||
}
|
||||
|
||||
export function useCourses() {
|
||||
return useContext(CoursesContext);
|
||||
}
|
@ -3,7 +3,7 @@ import { SearchableSelect } from "./SearchableSelect";
|
||||
import { CustomLabelSelect } from "./CustomLabelSelect";
|
||||
import { RegistrationPreview } from ".";
|
||||
import { customLabelsMap } from "../../utils/allCustomLabels";
|
||||
import { useCourses } from "..";
|
||||
import { useCourses } from "../CourseContext";
|
||||
|
||||
type HTMLEventFn = JSX.EventHandlerUnion<HTMLFormElement, Event & {
|
||||
submitter: HTMLElement;
|
||||
|
@ -2,7 +2,7 @@ import { For, createMemo, createSignal } from "solid-js";
|
||||
import { Chip } from "../../components/Chip";
|
||||
import { Course } from "../../types/Course";
|
||||
import { RegistrationPreview } from ".";
|
||||
import { useCourses } from "..";
|
||||
import { useCourses } from "../CourseContext";
|
||||
|
||||
type PresetName = "None" | "2 Matpel" | "3 Matpel" | "4 Escolta" | "MD, 2 Matpel" | "3 4x4" | "2 4x4" | "6 Sibia";
|
||||
|
||||
|
@ -6,7 +6,7 @@ import { RegistrationPreview } from ".";
|
||||
import { loadCustomLabels } from "../../utils/allCustomLabels";
|
||||
import { FileDashedIcon } from "../../icons/FileDashedIcon";
|
||||
import { LoadingIcon } from "../../icons/LoadingIcon";
|
||||
import { useCourses } from "..";
|
||||
import { useCourses } from "../CourseContext";
|
||||
|
||||
|
||||
function isoDateToLocalDate(date: string): string {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { createEffect, createSignal, For, onMount } from "solid-js";
|
||||
import { useCourses } from "..";
|
||||
import { useCourses } from "../CourseContext";
|
||||
|
||||
export function SearchableSelect(props: {
|
||||
onChange: (id: number | null) => void,
|
||||
|
@ -12,8 +12,8 @@ import QR from "qrcode";
|
||||
import saveAs from "file-saver";
|
||||
import { genMatpelCarnet } from "../../carnetGenerator/matpel";
|
||||
import { genMachineryCarnet } from "../../carnetGenerator/machinery";
|
||||
import { useCourses } from "..";
|
||||
import { Course } from "../../types/Course";
|
||||
import { useCourses } from "../CourseContext";
|
||||
|
||||
const carnetEnabled = [
|
||||
"Matpel 3",
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { createMemo } from "solid-js";
|
||||
import { useCourses } from "..";
|
||||
import { Register } from "../../types/Register";
|
||||
import { formatDate } from "../../utils/functions";
|
||||
import { useCourses } from "../CourseContext";
|
||||
|
||||
export function RegisterSidebar(props: {
|
||||
register: Register,
|
||||
|
@ -7,7 +7,7 @@ import { backend, wait } from "../../utils/functions";
|
||||
import { JsonResult } from "../../types/JsonResult";
|
||||
import { LoadingIcon } from "../../icons/LoadingIcon";
|
||||
import { RegisterElement, generateCert } from "./RegisterElement";
|
||||
import { useCourses } from "..";
|
||||
import { useCourses } from "../CourseContext";
|
||||
|
||||
export function Registers(props: {person: Person | null, count: number}) {
|
||||
const [registers, setRegisters] = createSignal<Array<Register>>([]);
|
||||
|
@ -1,120 +1,10 @@
|
||||
import { JSX, Resource, Show, createContext, createMemo, createResource, createSignal, useContext } from "solid-js";
|
||||
import { NewRegister } from "./NewRegister";
|
||||
import { Registers } from "./Registers";
|
||||
import { Search } from "./Search";
|
||||
import { Person } from "../types/Person";
|
||||
import axios from "axios";
|
||||
import { Course } from "../types/Course";
|
||||
import { CertsImpl } from "./CertsImpl";
|
||||
import { CoursesProvider } from "./CourseContext";
|
||||
|
||||
export function Certs() {
|
||||
const [person, setPerson] = createSignal<Person | null>(null);
|
||||
const [count, setCount] = createSignal(0);
|
||||
|
||||
const [courses] = createResource(fetchAllCourses);
|
||||
|
||||
const coursesReady = createMemo(() => courses.state === "ready");
|
||||
const coursesLoading = createMemo(() => courses.state === "pending");
|
||||
|
||||
return (
|
||||
<>
|
||||
<div class={`top-0 left-0 w-screen h-1 ${coursesLoading() ? "fixed" : "hidden"}`}>
|
||||
<div class='h-1 w-full bg-c-on-primary overflow-hidden'>
|
||||
<div class='progress w-full h-full bg-c-primary left-right' />
|
||||
</div>
|
||||
</div>
|
||||
<CoursesProvider courses={courses}>
|
||||
<Show when={courses.state !== "errored"}>
|
||||
<div class={`grid grid-cols-[16rem_25rem_1fr] ${coursesReady() ? "" : "opacity-25"}`}>
|
||||
<Search setPerson={setPerson} />
|
||||
<NewRegister
|
||||
personId={person()?.person_id ?? null}
|
||||
onSuccess={() => setCount((x) => x + 1)}
|
||||
/>
|
||||
<Registers person={person()} count={count()} />
|
||||
</div>
|
||||
</Show>
|
||||
</CoursesProvider>
|
||||
<Show when={courses.state === "errored"}>
|
||||
<div>
|
||||
<div class="p-2 m-8 text-c-on-error bg-c-error rounded-md">
|
||||
Error al cargar recursos vitales del sistema (lista de cursos)
|
||||
<br />
|
||||
Recargue la página para intentar de nuevo
|
||||
<br />
|
||||
<br />
|
||||
{courses.error?.message}
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
</>
|
||||
<CoursesProvider>
|
||||
<CertsImpl />
|
||||
</CoursesProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const CoursesContext = createContext<{
|
||||
data: Resource<Course[]>,
|
||||
nameMap: () => {[course_name: string]: Course},
|
||||
idMap: () => {[course_name: string]: Course},
|
||||
}>();
|
||||
|
||||
function CoursesProvider(props: {courses: Resource<Course[]>, children: JSX.Element}) {
|
||||
const courseMapMemo = createMemo(() => {
|
||||
if (props.courses === undefined || props.courses?.state !== "ready") {
|
||||
return {};
|
||||
}
|
||||
|
||||
const data = props.courses();
|
||||
|
||||
type CourseMap = {[course_name: string]: Course};
|
||||
const map: CourseMap = {};
|
||||
for (const course of data) {
|
||||
map[course.course_name] = course;
|
||||
}
|
||||
|
||||
return map;
|
||||
});
|
||||
|
||||
const courseIdMapMemo = createMemo(() => {
|
||||
if (props.courses === undefined || props.courses?.state !== "ready") {
|
||||
return {};
|
||||
}
|
||||
|
||||
const data = props.courses();
|
||||
|
||||
type CourseMap = {[course_id: number]: Course};
|
||||
const map: CourseMap = {};
|
||||
for (const course of data) {
|
||||
map[course.course_id] = course;
|
||||
}
|
||||
|
||||
return map;
|
||||
});
|
||||
|
||||
const coursesData = {
|
||||
data: props.courses,
|
||||
nameMap: courseMapMemo,
|
||||
idMap: courseIdMapMemo,
|
||||
};
|
||||
|
||||
return (
|
||||
<CoursesContext.Provider value={coursesData}>
|
||||
{props.children}
|
||||
</CoursesContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
let cachedCourses: Array<Course> | null = null;
|
||||
|
||||
async function fetchAllCourses(): Promise<Array<Course>> {
|
||||
if (cachedCourses !== null) {
|
||||
return cachedCourses;
|
||||
}
|
||||
|
||||
const result = await axios.get<Array<Course>>(`${import.meta.env.VITE_BACKEND_URL}/api/course`);
|
||||
cachedCourses = result.data;
|
||||
return result.data;
|
||||
}
|
||||
|
||||
export function useCourses() {
|
||||
return useContext(CoursesContext);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user