[FE][Certs] Refactor custom label to use context
This commit is contained in:
parent
b3bfa4a82c
commit
b8296164c5
@ -7,7 +7,8 @@
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview",
|
||||
"lint": "eslint --fix"
|
||||
"lint": "eslint --fix",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
|
45
frontend/src/certs/CustomLabelContext.tsx
Normal file
45
frontend/src/certs/CustomLabelContext.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
import { JSX, createContext, createMemo, createResource, useContext } from "solid-js";
|
||||
import { CustomLabel } from "../types/CustomLabel";
|
||||
import axios from "axios";
|
||||
|
||||
export type CustomLabelsMap = {[custom_label_id: number]: CustomLabel};
|
||||
|
||||
const CustomLabelContext = createContext<{
|
||||
labels: () => CustomLabelsMap
|
||||
}>();
|
||||
|
||||
export function CustomLabelProvider(props: {children: JSX.Element}) {
|
||||
const [labels] = createResource(fetchAllLabels);
|
||||
|
||||
const customLabelData = {
|
||||
labels: createMemo(() => labels() ?? {}),
|
||||
};
|
||||
|
||||
return (
|
||||
<CustomLabelContext.Provider value={customLabelData}>
|
||||
{props.children}
|
||||
</CustomLabelContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
let cachedLabels: CustomLabelsMap | null = null;
|
||||
|
||||
async function fetchAllLabels(useCache = true): Promise<CustomLabelsMap> {
|
||||
if (useCache && cachedLabels !== null) {
|
||||
return cachedLabels;
|
||||
}
|
||||
|
||||
const result = await axios.get<Array<CustomLabel>>(`${import.meta.env.VITE_BACKEND_URL}/api/label`);
|
||||
|
||||
const map: CustomLabelsMap = {};
|
||||
for (const label of result.data) {
|
||||
map[label.custom_label_id] = label;
|
||||
}
|
||||
|
||||
cachedLabels = map;
|
||||
return map;
|
||||
}
|
||||
|
||||
export function useCustomLabel() {
|
||||
return useContext(CustomLabelContext);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { createEffect, createSignal, For, onMount } from "solid-js";
|
||||
import { customLabelsMap } from "../../utils/allCustomLabels";
|
||||
import { useCustomLabel } from "../CustomLabelContext";
|
||||
|
||||
export function CustomLabelSelect(props: {
|
||||
onChange: (value: string) => void,
|
||||
@ -8,6 +8,7 @@ export function CustomLabelSelect(props: {
|
||||
const [filter, setFilter] = createSignal("");
|
||||
const [selected, setSelected] = createSignal<boolean>(false);
|
||||
const [inputValue, setInputValue] = createSignal("");
|
||||
const customLabels = useCustomLabel();
|
||||
|
||||
const iHandler = (ev: KeyboardEvent & {currentTarget: HTMLInputElement, target: Element}) => {
|
||||
const inputEl = ev.target as HTMLInputElement;
|
||||
@ -49,9 +50,13 @@ export function CustomLabelSelect(props: {
|
||||
|
||||
|
||||
const filteredOptions = () => {
|
||||
if (customLabels === undefined) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const filterText = filter();
|
||||
|
||||
return Object.entries(customLabelsMap()).filter(([, label]) => {
|
||||
return Object.entries(customLabels.labels()).filter(([, label]) => {
|
||||
let courseText = label.custom_label_value.toLowerCase();
|
||||
courseText = courseText.replace("á", "a");
|
||||
courseText = courseText.replace("é", "e");
|
||||
|
@ -2,8 +2,8 @@ import { JSX, Show, createSignal } from "solid-js";
|
||||
import { SearchableSelect } from "./SearchableSelect";
|
||||
import { CustomLabelSelect } from "./CustomLabelSelect";
|
||||
import { RegistrationPreview } from ".";
|
||||
import { customLabelsMap } from "../../utils/allCustomLabels";
|
||||
import { useCourses } from "../CourseContext";
|
||||
import { useCustomLabel } from "../CustomLabelContext";
|
||||
|
||||
type HTMLEventFn = JSX.EventHandlerUnion<HTMLFormElement, Event & {
|
||||
submitter: HTMLElement;
|
||||
@ -22,6 +22,7 @@ export function ManualRegistration(props: {
|
||||
const [isPreview, setIsPreview] = createSignal(false);
|
||||
|
||||
const courses = useCourses();
|
||||
const customLabels = useCustomLabel();
|
||||
|
||||
let datePicker: HTMLInputElement | undefined;
|
||||
|
||||
@ -44,7 +45,7 @@ export function ManualRegistration(props: {
|
||||
|
||||
const subject = selectedCourseId();
|
||||
|
||||
if (datePicker === undefined) {
|
||||
if (datePicker === undefined || customLabels === undefined || courses === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -74,7 +75,7 @@ export function ManualRegistration(props: {
|
||||
|
||||
const label = customLabel();
|
||||
// TODO: Refactor along with allCustomLabel.tsx
|
||||
const custom_label_id = Object.entries(customLabelsMap()).find(([, v]) => (v.custom_label_value === label))?.[1].custom_label_id ?? -1;
|
||||
const custom_label_id = Object.entries(customLabels.labels()).find(([, v]) => (v.custom_label_value === label))?.[1].custom_label_id ?? -1;
|
||||
|
||||
const data: RegistrationPreview = {
|
||||
courseId: subject,
|
||||
|
@ -2,7 +2,6 @@ import { Show, createMemo } from "solid-js";
|
||||
import { certGenerator } from "../../certGenerator";
|
||||
import { Person } from "../../types/Person";
|
||||
import { Register } from "../../types/Register";
|
||||
import { customLabelsMap } from "../../utils/allCustomLabels";
|
||||
import { DownloadSimpleIcon } from "../../icons/DownloadSimpleIcon";
|
||||
import { CaretRight } from "../../icons/CaretRight";
|
||||
import { IdentificationCardIcon } from "../../icons/IdentificationCardIcon";
|
||||
@ -14,6 +13,7 @@ import { genMatpelCarnet } from "../../carnetGenerator/matpel";
|
||||
import { genMachineryCarnet } from "../../carnetGenerator/machinery";
|
||||
import { Course } from "../../types/Course";
|
||||
import { useCourses } from "../CourseContext";
|
||||
import { CustomLabelsMap, useCustomLabel } from "../CustomLabelContext";
|
||||
|
||||
const carnetEnabled = [
|
||||
"Matpel 3",
|
||||
@ -27,6 +27,7 @@ const carnetEnabled = [
|
||||
|
||||
export function RegisterElement(props: {register: Register, person: Person, onClick: () => void}) {
|
||||
const courses = useCourses();
|
||||
const customLabels = useCustomLabel();
|
||||
|
||||
const dateComponents = () => {
|
||||
const [, year, month, day] = /(\d{4})-(\d{2})-(\d{2})/.exec(props.register.register_display_date) ?? [];
|
||||
@ -44,13 +45,18 @@ export function RegisterElement(props: {register: Register, person: Person, onCl
|
||||
};
|
||||
|
||||
const customLabel = () => {
|
||||
if (customLabels === undefined) {
|
||||
return "~~Denominaciones no cargadas~~";
|
||||
}
|
||||
|
||||
const labelId = props.register.register_custom_label;
|
||||
if (labelId === 1) return "";
|
||||
return customLabelsMap()[labelId]?.custom_label_value ?? "";
|
||||
|
||||
return customLabels.labels()[labelId]?.custom_label_value ?? "~~Denominación no encontrada~~";
|
||||
};
|
||||
|
||||
const genCert = () => {
|
||||
if (courses === undefined) {
|
||||
if (courses === undefined || customLabels === undefined) {
|
||||
alert("Error. La lista de cursos no esta cargada.");
|
||||
return;
|
||||
}
|
||||
@ -58,7 +64,7 @@ export function RegisterElement(props: {register: Register, person: Person, onCl
|
||||
const person = props.person;
|
||||
const register = props.register;
|
||||
|
||||
generateCert(person, register, courses.idMap());
|
||||
generateCert(person, register, courses.idMap(), customLabels.labels());
|
||||
};
|
||||
|
||||
const generateable = () => {
|
||||
@ -164,7 +170,12 @@ export function RegisterElement(props: {register: Register, person: Person, onCl
|
||||
);
|
||||
}
|
||||
|
||||
export function generateCert(person: Person, register: Register, coursesMap: {[course_id: number]: Course}) {
|
||||
export function generateCert(
|
||||
person: Person,
|
||||
register: Register,
|
||||
coursesMap: {[course_id: number]: Course},
|
||||
labelsMap: CustomLabelsMap,
|
||||
) {
|
||||
const courseN = coursesMap[register.register_course_id]?.course_name ?? "Curso no encontrado";
|
||||
|
||||
const generator = certGenerator[courseN];
|
||||
@ -181,7 +192,7 @@ export function generateCert(person: Person, register: Register, coursesMap: {[c
|
||||
if (register.register_custom_label === 1) {
|
||||
certCustomLabel = "";
|
||||
} else {
|
||||
const customLabel = customLabelsMap()[register.register_custom_label];
|
||||
const customLabel = labelsMap[register.register_custom_label];
|
||||
if (customLabel === undefined) {
|
||||
alert(`Error. No se encontró la denominación con id ${register.register_custom_label}`);
|
||||
return;
|
||||
|
@ -8,6 +8,7 @@ import { JsonResult } from "../../types/JsonResult";
|
||||
import { LoadingIcon } from "../../icons/LoadingIcon";
|
||||
import { RegisterElement, generateCert } from "./RegisterElement";
|
||||
import { useCourses } from "../CourseContext";
|
||||
import { useCustomLabel } from "../CustomLabelContext";
|
||||
|
||||
export function Registers(props: {person: Person | null, count: number}) {
|
||||
const [registers, setRegisters] = createSignal<Array<Register>>([]);
|
||||
@ -16,6 +17,7 @@ export function Registers(props: {person: Person | null, count: number}) {
|
||||
const [loading, setLoading] = createSignal(false);
|
||||
const [error, setError] = createSignal("");
|
||||
const courses = useCourses();
|
||||
const customLabels = useCustomLabel();
|
||||
|
||||
const loadRegisters = async() => {
|
||||
setLoading(true);
|
||||
@ -103,10 +105,10 @@ export function Registers(props: {person: Person | null, count: number}) {
|
||||
|
||||
const [downButtonBg, setDownButtonBg] = createSignal("bg-c-primary text-c-on-primary");
|
||||
const downloadTodayCerts = () => {
|
||||
if (props.person === null || courses === undefined) return;
|
||||
if (props.person === null || courses === undefined || customLabels === undefined) return;
|
||||
|
||||
todayRegisters().forEach((register) => {
|
||||
generateCert(props.person!, register, courses.idMap());
|
||||
generateCert(props.person!, register, courses.idMap(), customLabels.labels());
|
||||
});
|
||||
|
||||
setDownButtonBg("bg-c-success text-c-on-success");
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { CertsImpl } from "./CertsImpl";
|
||||
import { CoursesProvider } from "./CourseContext";
|
||||
import { CustomLabelProvider } from "./CustomLabelContext";
|
||||
|
||||
export function Certs() {
|
||||
return (
|
||||
<CoursesProvider>
|
||||
<CertsImpl />
|
||||
<CustomLabelProvider>
|
||||
<CertsImpl />
|
||||
</CustomLabelProvider>
|
||||
</CoursesProvider>
|
||||
);
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
import { createSignal } from "solid-js";
|
||||
import { CustomLabel } from "../types/CustomLabel";
|
||||
|
||||
type CustomLabelsMap = {[k: number]: CustomLabel};
|
||||
|
||||
// TODO: Refactor, this is inefficient
|
||||
export const [customLabelsMap, setCustomLabelsMap] = createSignal<{[k: number]: CustomLabel}>({});
|
||||
|
||||
export function loadCustomLabels() {
|
||||
fetch(`${import.meta.env.VITE_BACKEND_URL}/api/label`)
|
||||
@ -14,7 +11,6 @@ export function loadCustomLabels() {
|
||||
for (const label of data) {
|
||||
map[label.custom_label_id] = label;
|
||||
}
|
||||
setCustomLabelsMap(map);
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user