[FE][Certs] Implement register presets

This commit is contained in:
Araozu 2023-08-31 12:11:48 -05:00
parent 45e56b4b79
commit 85887f2460
10 changed files with 149 additions and 31 deletions

View File

@ -1,6 +1,6 @@
CREATE TABLE course ( CREATE TABLE course (
course_id INTEGER PRIMARY KEY AUTO_INCREMENT, course_id INTEGER PRIMARY KEY AUTO_INCREMENT,
course_name VARCHAR(50) NOT NULL, course_name VARCHAR(75) NOT NULL,
course_display_name VARCHAR(100) NOT NULL, course_display_name VARCHAR(100) NOT NULL,
course_days_amount INTEGER NOT NULL, course_days_amount INTEGER NOT NULL,
course_has_custom_label BOOLEAN NOT NULL course_has_custom_label BOOLEAN NOT NULL

View File

@ -2,7 +2,7 @@
CREATE TABLE person ( CREATE TABLE person (
person_id INTEGER PRIMARY KEY AUTO_INCREMENT, person_id INTEGER PRIMARY KEY AUTO_INCREMENT,
person_dni VARCHAR(8) NOT NULL, person_dni VARCHAR(20) NOT NULL,
person_names VARCHAR(100) NOT NULL, person_names VARCHAR(100) NOT NULL,
person_paternal_surname VARCHAR(50) NOT NULL, person_paternal_surname VARCHAR(50) NOT NULL,
person_maternal_surname VARCHAR(50) NOT NULL person_maternal_surname VARCHAR(50) NOT NULL

View File

@ -43,8 +43,6 @@ export function ManualRegistration(props: {personId: number | null, onAdd: (v: [
setCount((x) => x + 1); setCount((x) => x + 1);
}; };
console.log(`Person ID: ${props.personId}`);
return ( return (
<> <>
<form onsubmit={register}> <form onsubmit={register}>

View File

@ -1,20 +1,107 @@
import { Accessor, For, createSignal } from "solid-js";
import { Chip } from "../../components/Chip"; import { Chip } from "../../components/Chip";
import { getCourseMemo } from "../../utils/allCourses";
import { Course } from "../../types/Course";
export function RegisterPresets() { type PresetName = "None" | "2 Matpel" | "3 Matpel" | "4 Escolta" | "MD, 2 Matpel" | "3 4x4" | "2 4x4";
function genPresets(): {[k: string]: Array<Accessor<Course | null>>} {
return {
"2 Matpel": [
getCourseMemo("Matpel 2"),
getCourseMemo("Matpel 1"),
],
"3 Matpel": [
getCourseMemo("Matpel 3"),
getCourseMemo("Matpel 2"),
getCourseMemo("Matpel 1"),
],
"4 Escolta": [
getCourseMemo("Sup. Escolta"),
getCourseMemo("Matpel 3"),
getCourseMemo("Matpel 2"),
getCourseMemo("Matpel 1"),
],
"MD, 2 Matpel": [
getCourseMemo("Matpel 2"),
getCourseMemo("Matpel 1"),
getCourseMemo("Manejo Defensivo"),
],
"3 4x4": [
getCourseMemo("4x4"),
getCourseMemo("Mecanica Basica"),
getCourseMemo("Manejo Defensivo"),
],
"2 4x4": [
getCourseMemo("4x4"),
getCourseMemo("Manejo Defensivo"),
],
};
}
export function RegisterPresets(props: {disableCreation: boolean, onAdd: (v: [number, string]) => void}) {
let datePicker: HTMLInputElement | undefined; let datePicker: HTMLInputElement | undefined;
const [selectedPreset, setSelectedPreset] = createSignal<PresetName>("None");
const [error, setError] = createSignal("");
const presets = genPresets();
const add = () => {
if (datePicker === undefined) {
return;
}
const date = datePicker.value;
const preset = selectedPreset();
if (date === "") {
setError("Selecciona una fecha");
setTimeout(() => setError(""), 5000);
return;
}
if (preset === "None") {
setError("Selecciona un preset");
setTimeout(() => setError(""), 5000);
return;
}
const presetIds = presets[preset];
const currentDate = new Date(date);
for (const courseMemo of presetIds) {
// Get course and course duration from the memo
const course = courseMemo();
if (course === null) {
setError(`Un curso no existe. Error fatal. (${preset})`);
return;
}
const courseId = course.course_id;
const courseDuration = course.course_days_amount;
const dateYYYYMMDD = currentDate.toISOString().split("T")[0];
// Add
props.onAdd([courseId, dateYYYYMMDD]);
// Substract current date for the next course
currentDate.setDate(currentDate.getDate() - courseDuration);
}
setSelectedPreset("None");
};
return ( return (
<> <>
<div class="h-52"> <div class="h-52">
<p>Las fechas se colocan automáticamente según la duración del curso.</p> <p>Las fechas se colocan automáticamente según la duración del curso y su jeraquía.</p>
<br /> <br />
<div class="flex flex-wrap gap-2"> <div class="flex flex-wrap gap-2">
<Chip text="2 Matpel" /> <For each={Object.keys(presets)}>
<Chip text="3 Matpel" /> {(key) => (
<Chip text="4 Escolta" /> <Chip
<Chip text="MD, 2 Matpel" /> selected={selectedPreset() === key}
<Chip text="3 4x4" /> select={() => setSelectedPreset(key as PresetName)}
<Chip text="2 4x4" /> text={key}
/>
)}
</For>
</div> </div>
</div> </div>
<div class="my-4"> <div class="my-4">
@ -28,13 +115,22 @@ export function RegisterPresets() {
<label for="create-date" class="absolute -top-2 left-2 text-xs bg-c-surface px-1">Fecha</label> <label for="create-date" class="absolute -top-2 left-2 text-xs bg-c-surface px-1">Fecha</label>
</div> </div>
</div> </div>
<input <div>
class="bg-c-primary text-c-on-primary px-4 py-2 rounded-full cursor-pointer <input
disabled:opacity-50 disabled:cursor-not-allowed" class="bg-c-primary text-c-on-primary px-4 py-2 rounded-full cursor-pointer
type="submit" disabled:opacity-50 disabled:cursor-not-allowed"
value="Agregar" type="button"
// disabled={props.personId === null} value="Agregar"
/> onclick={add}
disabled={props.disableCreation}
/>
<p
class="my-2 p-1 w-fit mx-4 text-c-error inline-block"
>
{error()}&nbsp;
</p>
</div>
</> </>
); );
} }

View File

@ -21,7 +21,7 @@ export function RegisterPreview(props: {selections: Array<[number, string]>, per
const result = await createRegisters(registers); const result = await createRegisters(registers);
if (result === null) { if (result === null) {
console.log("Success"); console.log("Create register: success");
} else { } else {
console.log(`error. ${result}`); console.log(`error. ${result}`);
} }
@ -54,7 +54,7 @@ export function RegisterPreview(props: {selections: Array<[number, string]>, per
function Register(props: {courseId: number, date: string, onDelete: (v: number) => void}) { function Register(props: {courseId: number, date: string, onDelete: (v: number) => void}) {
const courseName = () => { const courseName = () => {
const courses = allCourses(); const courses = allCourses();
return courses.find((course) => course.course_id === props.courseId)?.course_name ?? "!"; return courses.find((course) => course.course_id === props.courseId)?.course_name ?? `Curso invalido! (${props.courseId})`;
}; };
return ( return (

View File

@ -30,8 +30,9 @@ export function SearchableSelect(props: {
}); });
createEffect(() => { createEffect(() => {
// Makes reactivity happen // Makes reactivity happen, don't remove
console.log(props.count); // eslint-disable-next-line @typescript-eslint/no-unused-vars
const _count = props.count;
setFilter(""); setFilter("");
setSelected(null); setSelected(null);

View File

@ -12,7 +12,7 @@ export function NewRegister(props: {
personId: number | null, personId: number | null,
onSuccess: () => void, onSuccess: () => void,
}) { }) {
const [active, setActive] = createSignal<TabType>("Manual"); const [active, setActive] = createSignal<TabType>("Presets");
const [selections, setSelections] = createSignal<Array<[number, string]>>([]); const [selections, setSelections] = createSignal<Array<[number, string]>>([]);
const onRegister = () => { const onRegister = () => {
@ -29,7 +29,10 @@ export function NewRegister(props: {
<div class="bg-c-surface p-4 h-[22rem]"> <div class="bg-c-surface p-4 h-[22rem]">
<Show when={active() === "Presets"}> <Show when={active() === "Presets"}>
<RegisterPresets /> <RegisterPresets
onAdd={(v) => setSelections((x) => [...x, v])}
disableCreation={props.personId === null}
/>
</Show> </Show>
<Show when={active() === "Manual"}> <Show when={active() === "Manual"}>
<ManualRegistration <ManualRegistration

View File

@ -12,7 +12,7 @@ export function Certs() {
<div class="grid grid-cols-[16rem_25rem_1fr]"> <div class="grid grid-cols-[16rem_25rem_1fr]">
<Search setPerson={setPerson} /> <Search setPerson={setPerson} />
<NewRegister <NewRegister
personId={person()?.person_id ?? -1} personId={person()?.person_id ?? null}
onSuccess={() => setCount((x) => x + 1)} onSuccess={() => setCount((x) => x + 1)}
/> />
<Registers person={person()} count={count()} /> <Registers person={person()} count={count()} />

View File

@ -1,7 +1,18 @@
export function Chip(props: {text: string}) { export function Chip(props: {text: string, selected: boolean, select: () => void}) {
const selectedClasses = () => {
if (props.selected) {
return "bg-c-surface-variant text-c-on-surface-variant shadow";
} else {
return "";
}
};
return ( return (
<div class="inline-block px-3 py-1 border border-c-outline rounded-md text-sm cursor-pointer <div
hover:bg-c-surface-variant hover:text-c-on-surface-variant transition-colors" class={`inline-block px-3 py-1 border border-c-outline rounded-md text-sm cursor-pointer
hover:bg-c-surface-variant hover:text-c-on-surface-variant transition-colors
select-none ${selectedClasses()}`}
onClick={props.select}
> >
{props.text} {props.text}
</div> </div>

View File

@ -1,4 +1,4 @@
import { createSignal } from "solid-js"; import { Accessor, createMemo, createSignal } from "solid-js";
import { Course } from "../types/Course"; import { Course } from "../types/Course";
type CourseMap = {[k: number]: Course}; type CourseMap = {[k: number]: Course};
@ -17,8 +17,17 @@ export const [courseMap, setCourseMap] = createSignal<CourseMap>({});
for (const course of data) { for (const course of data) {
map[course.course_id] = course; map[course.course_id] = course;
} }
console.log("course map", map);
setCourseMap(map); setCourseMap(map);
}); });
})(); })();
export function getCourseMemo(name: string): Accessor<Course | null> {
return createMemo(() => {
const course = allCourses().find((course) => course.course_name === name);
if (course) {
return course;
}
return null;
});
}