[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 { CustomLabelSelect } from "./CustomLabelSelect";
|
||||||
import { RegistrationPreview } from ".";
|
import { RegistrationPreview } from ".";
|
||||||
import { customLabelsMap } from "../../utils/allCustomLabels";
|
import { customLabelsMap } from "../../utils/allCustomLabels";
|
||||||
import { useCourses } from "..";
|
import { useCourses } from "../CourseContext";
|
||||||
|
|
||||||
type HTMLEventFn = JSX.EventHandlerUnion<HTMLFormElement, Event & {
|
type HTMLEventFn = JSX.EventHandlerUnion<HTMLFormElement, Event & {
|
||||||
submitter: HTMLElement;
|
submitter: HTMLElement;
|
||||||
|
@ -2,7 +2,7 @@ import { For, createMemo, createSignal } from "solid-js";
|
|||||||
import { Chip } from "../../components/Chip";
|
import { Chip } from "../../components/Chip";
|
||||||
import { Course } from "../../types/Course";
|
import { Course } from "../../types/Course";
|
||||||
import { RegistrationPreview } from ".";
|
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";
|
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 { loadCustomLabels } from "../../utils/allCustomLabels";
|
||||||
import { FileDashedIcon } from "../../icons/FileDashedIcon";
|
import { FileDashedIcon } from "../../icons/FileDashedIcon";
|
||||||
import { LoadingIcon } from "../../icons/LoadingIcon";
|
import { LoadingIcon } from "../../icons/LoadingIcon";
|
||||||
import { useCourses } from "..";
|
import { useCourses } from "../CourseContext";
|
||||||
|
|
||||||
|
|
||||||
function isoDateToLocalDate(date: string): string {
|
function isoDateToLocalDate(date: string): string {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { createEffect, createSignal, For, onMount } from "solid-js";
|
import { createEffect, createSignal, For, onMount } from "solid-js";
|
||||||
import { useCourses } from "..";
|
import { useCourses } from "../CourseContext";
|
||||||
|
|
||||||
export function SearchableSelect(props: {
|
export function SearchableSelect(props: {
|
||||||
onChange: (id: number | null) => void,
|
onChange: (id: number | null) => void,
|
||||||
|
@ -12,8 +12,8 @@ import QR from "qrcode";
|
|||||||
import saveAs from "file-saver";
|
import saveAs from "file-saver";
|
||||||
import { genMatpelCarnet } from "../../carnetGenerator/matpel";
|
import { genMatpelCarnet } from "../../carnetGenerator/matpel";
|
||||||
import { genMachineryCarnet } from "../../carnetGenerator/machinery";
|
import { genMachineryCarnet } from "../../carnetGenerator/machinery";
|
||||||
import { useCourses } from "..";
|
|
||||||
import { Course } from "../../types/Course";
|
import { Course } from "../../types/Course";
|
||||||
|
import { useCourses } from "../CourseContext";
|
||||||
|
|
||||||
const carnetEnabled = [
|
const carnetEnabled = [
|
||||||
"Matpel 3",
|
"Matpel 3",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { createMemo } from "solid-js";
|
import { createMemo } from "solid-js";
|
||||||
import { useCourses } from "..";
|
|
||||||
import { Register } from "../../types/Register";
|
import { Register } from "../../types/Register";
|
||||||
import { formatDate } from "../../utils/functions";
|
import { formatDate } from "../../utils/functions";
|
||||||
|
import { useCourses } from "../CourseContext";
|
||||||
|
|
||||||
export function RegisterSidebar(props: {
|
export function RegisterSidebar(props: {
|
||||||
register: Register,
|
register: Register,
|
||||||
|
@ -7,7 +7,7 @@ import { backend, wait } from "../../utils/functions";
|
|||||||
import { JsonResult } from "../../types/JsonResult";
|
import { JsonResult } from "../../types/JsonResult";
|
||||||
import { LoadingIcon } from "../../icons/LoadingIcon";
|
import { LoadingIcon } from "../../icons/LoadingIcon";
|
||||||
import { RegisterElement, generateCert } from "./RegisterElement";
|
import { RegisterElement, generateCert } from "./RegisterElement";
|
||||||
import { useCourses } from "..";
|
import { useCourses } from "../CourseContext";
|
||||||
|
|
||||||
export function Registers(props: {person: Person | null, count: number}) {
|
export function Registers(props: {person: Person | null, count: number}) {
|
||||||
const [registers, setRegisters] = createSignal<Array<Register>>([]);
|
const [registers, setRegisters] = createSignal<Array<Register>>([]);
|
||||||
|
@ -1,120 +1,10 @@
|
|||||||
import { JSX, Resource, Show, createContext, createMemo, createResource, createSignal, useContext } from "solid-js";
|
import { CertsImpl } from "./CertsImpl";
|
||||||
import { NewRegister } from "./NewRegister";
|
import { CoursesProvider } from "./CourseContext";
|
||||||
import { Registers } from "./Registers";
|
|
||||||
import { Search } from "./Search";
|
|
||||||
import { Person } from "../types/Person";
|
|
||||||
import axios from "axios";
|
|
||||||
import { Course } from "../types/Course";
|
|
||||||
|
|
||||||
export function Certs() {
|
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 (
|
return (
|
||||||
<>
|
<CoursesProvider>
|
||||||
<div class={`top-0 left-0 w-screen h-1 ${coursesLoading() ? "fixed" : "hidden"}`}>
|
<CertsImpl />
|
||||||
<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>
|
</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>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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