[FE][Certs] Refactor custom label to use context

master
Araozu 2023-12-16 11:20:43 -05:00
parent b3bfa4a82c
commit b8296164c5
8 changed files with 83 additions and 19 deletions

View File

@ -7,7 +7,8 @@
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"lint": "eslint --fix"
"lint": "eslint --fix",
"typecheck": "tsc --noEmit"
},
"license": "MIT",
"devDependencies": {

View 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);
}

View File

@ -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");

View File

@ -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,

View File

@ -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;

View File

@ -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");

View File

@ -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>
);
}

View File

@ -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);
});
}