157 lines
5.0 KiB
TypeScript
157 lines
5.0 KiB
TypeScript
|
import { createSignal, Show } from "solid-js";
|
||
|
import { SearchableSelect } from "./SearchableSelect";
|
||
|
import { JSX } from "solid-js/jsx-runtime";
|
||
|
// import { subjects } from "../subjects";
|
||
|
import { FilledCard } from "../../components/FilledCard";
|
||
|
import { RegisterPreview } from "./RegisterPreview";
|
||
|
|
||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||
|
const subjects: () => Array<any> = () => [];
|
||
|
|
||
|
type HTMLEventFn = JSX.EventHandlerUnion<HTMLFormElement, Event & {
|
||
|
submitter: HTMLElement;
|
||
|
}>;
|
||
|
|
||
|
|
||
|
type TabType = "Presets" | "Manual";
|
||
|
|
||
|
export function NewRegister(props: {
|
||
|
personId: number | null,
|
||
|
onSuccess: () => void,
|
||
|
}) {
|
||
|
const [active, setActive] = createSignal<TabType>("Manual");
|
||
|
const [selections, setSelections] = createSignal<Array<[number, string]>>([]);
|
||
|
|
||
|
const onRegister = () => {
|
||
|
setSelections([]);
|
||
|
props.onSuccess();
|
||
|
};
|
||
|
|
||
|
return (
|
||
|
<div class="h-screen overflow-y-scroll">
|
||
|
<FilledCard class="border border-c-outline overflow-hidden">
|
||
|
<h2 class="p-4 font-bold text-xl">Registrar certs</h2>
|
||
|
|
||
|
<RegisterTabs active={active()} setActive={setActive} />
|
||
|
|
||
|
<div class="bg-c-surface p-4 h-[22rem]">
|
||
|
<Show when={active() === "Presets"}>
|
||
|
<p>Proximamente...</p>
|
||
|
</Show>
|
||
|
<Show when={active() === "Manual"}>
|
||
|
<ManualCerts personId={props.personId} onAdd={(v) => setSelections((x) => [...x, v])} />
|
||
|
</Show>
|
||
|
</div>
|
||
|
</FilledCard>
|
||
|
|
||
|
<RegisterPreview
|
||
|
selections={selections()}
|
||
|
personId={props.personId}
|
||
|
onDelete={(deleteId) => setSelections((s) => [...s.filter(([id]) => id !== deleteId)])}
|
||
|
onRegister={onRegister}
|
||
|
/>
|
||
|
</div>
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
function RegisterTabs(props: {active: TabType, setActive: (v: TabType) => void}) {
|
||
|
const presetsClasses = () => ((props.active === "Presets") ? "font-bold border-c-primary" : "border-c-transparent");
|
||
|
const manualClasses = () => ((props.active === "Manual") ? "font-bold border-c-primary" : "border-c-transparent");
|
||
|
|
||
|
return (
|
||
|
<div class="grid grid-cols-2">
|
||
|
<button
|
||
|
class={`py-2 border-b-4 ${presetsClasses()}`}
|
||
|
onclick={() => props.setActive("Presets")}
|
||
|
>
|
||
|
Presets
|
||
|
</button>
|
||
|
<button
|
||
|
class={`py-2 border-b-4 ${manualClasses()}`}
|
||
|
onclick={() => props.setActive("Manual")}
|
||
|
>
|
||
|
Manual
|
||
|
</button>
|
||
|
</div>
|
||
|
);
|
||
|
}
|
||
|
|
||
|
function ManualCerts(props: {personId: number | null, onAdd: (v: [number, string]) => void}) {
|
||
|
// Used to update SearchableSelect.tsx manually
|
||
|
const [count, setCount] = createSignal(0);
|
||
|
const [error, setError] = createSignal("");
|
||
|
|
||
|
const [selectedSubject, setSelectedSubject] = createSignal<number | null>(null);
|
||
|
|
||
|
const datePicker = (
|
||
|
<input
|
||
|
id="create-date"
|
||
|
class="bg-c-surface text-c-on-surface border border-c-outline rounded-lg p-2"
|
||
|
type="date"
|
||
|
/>
|
||
|
);
|
||
|
|
||
|
const register: HTMLEventFn = async(ev) => {
|
||
|
ev.preventDefault();
|
||
|
|
||
|
const subject = selectedSubject();
|
||
|
const date = (datePicker as HTMLInputElement).value;
|
||
|
|
||
|
if (subject === null) {
|
||
|
setError("Selecciona un curso");
|
||
|
|
||
|
setTimeout(() => setError(""), 5000);
|
||
|
return;
|
||
|
}
|
||
|
if (date === "") {
|
||
|
setError("Selecciona una fecha");
|
||
|
|
||
|
setTimeout(() => setError(""), 5000);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
props.onAdd([subject, date]);
|
||
|
// This is used to update & refresh the <SearchableSelect> component
|
||
|
setCount((x) => x + 1);
|
||
|
};
|
||
|
|
||
|
console.log(`Person ID: ${props.personId}`);
|
||
|
|
||
|
return (
|
||
|
<>
|
||
|
<form onsubmit={register}>
|
||
|
<div>
|
||
|
<SearchableSelect
|
||
|
subjects={subjects()}
|
||
|
onChange={setSelectedSubject}
|
||
|
count={count()}
|
||
|
/>
|
||
|
</div>
|
||
|
|
||
|
<div class="relative my-4">
|
||
|
{datePicker}
|
||
|
<label for="create-date" class="absolute -top-2 left-2 text-xs bg-c-surface px-1">Fecha</label>
|
||
|
</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}
|
||
|
/>
|
||
|
</form>
|
||
|
|
||
|
<p
|
||
|
class="my-2 p-1 rounded w-fit mx-4 bg-c-error text-c-on-error"
|
||
|
style={{opacity: error() === "" ? "0" : "1", "user-select": "none"}}
|
||
|
>
|
||
|
{error()}
|
||
|
</p>
|
||
|
</>
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|