[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 (
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_days_amount INTEGER NOT NULL,
course_has_custom_label BOOLEAN NOT NULL

View File

@ -2,7 +2,7 @@
CREATE TABLE person (
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_paternal_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);
};
console.log(`Person ID: ${props.personId}`);
return (
<>
<form onsubmit={register}>

View File

@ -1,20 +1,107 @@
import { Accessor, For, createSignal } from "solid-js";
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;
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 (
<>
<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 />
<div class="flex flex-wrap gap-2">
<Chip text="2 Matpel" />
<Chip text="3 Matpel" />
<Chip text="4 Escolta" />
<Chip text="MD, 2 Matpel" />
<Chip text="3 4x4" />
<Chip text="2 4x4" />
<For each={Object.keys(presets)}>
{(key) => (
<Chip
selected={selectedPreset() === key}
select={() => setSelectedPreset(key as PresetName)}
text={key}
/>
)}
</For>
</div>
</div>
<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>
</div>
</div>
<input
class="bg-c-primary text-c-on-primary px-4 py-2 rounded-full cursor-pointer
disabled:opacity-50 disabled:cursor-not-allowed"
type="submit"
value="Agregar"
// disabled={props.personId === null}
/>
<div>
<input
class="bg-c-primary text-c-on-primary px-4 py-2 rounded-full cursor-pointer
disabled:opacity-50 disabled:cursor-not-allowed"
type="button"
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);
if (result === null) {
console.log("Success");
console.log("Create register: success");
} else {
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}) {
const courseName = () => {
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 (

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
import { createSignal } from "solid-js";
import { Accessor, createMemo, createSignal } from "solid-js";
import { Course } from "../types/Course";
type CourseMap = {[k: number]: Course};
@ -17,8 +17,17 @@ export const [courseMap, setCourseMap] = createSignal<CourseMap>({});
for (const course of data) {
map[course.course_id] = course;
}
console.log("course map", 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;
});
}