[FE] Improve batch mode's group UI.
This commit is contained in:
parent
42a16bd30b
commit
3ac8f1321c
@ -1,43 +1,103 @@
|
|||||||
import { createSignal, onMount } from "solid-js";
|
import { createSignal, Match, onMount, Show, Switch } from "solid-js";
|
||||||
import { Person } from "src/types/Person";
|
import { Person } from "src/types/Person";
|
||||||
|
import { DniRegister } from "./DniEntry/DniRegister";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sample data
|
||||||
|
01188994
|
||||||
|
47695703
|
||||||
|
46736668
|
||||||
|
21551382
|
||||||
|
41178747
|
||||||
|
41876027
|
||||||
|
04827012
|
||||||
|
45912508
|
||||||
|
45349984
|
||||||
|
41362975
|
||||||
|
70861152
|
||||||
|
72404776
|
||||||
|
46421911
|
||||||
|
43502556
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
Empty,
|
||||||
|
Loading,
|
||||||
|
Ok,
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
export function DniEntry(props: {dni: string}) {
|
export function DniEntry(props: {dni: string}) {
|
||||||
const [person, setPerson] = createSignal<Person | null>(null);
|
const [person, setPerson] = createSignal<Person | null>(null);
|
||||||
|
const [status, setStatus] = createSignal<Status>(Status.Empty);
|
||||||
|
|
||||||
|
const loadPerson = async() => {
|
||||||
|
setStatus(Status.Loading);
|
||||||
|
|
||||||
onMount(async() => {
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/person/${props.dni}`);
|
const response = await fetch(`/person/${props.dni}`);
|
||||||
const body = await response.json();
|
const body = await response.json();
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
setPerson(body);
|
setPerson(body);
|
||||||
|
setStatus(Status.Ok);
|
||||||
|
|
||||||
} else if (response.status === 404) {
|
} else if (response.status === 404) {
|
||||||
console.error(body);
|
console.error(body);
|
||||||
|
setStatus(Status.Error);
|
||||||
|
|
||||||
// setWarning("Persona no encontrada. Se debe insertar manualmente sus datos.");
|
// setWarning("Persona no encontrada. Se debe insertar manualmente sus datos.");
|
||||||
|
|
||||||
setPerson(null);
|
setPerson(null);
|
||||||
} else {
|
} else {
|
||||||
// setError(body);
|
setStatus(Status.Error);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// setError(JSON.stringify(e));
|
setStatus(Status.Error);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
onMount(loadPerson);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="grid gap-1 grid-cols-[7rem_10rem_10rem_16rem]">
|
<>
|
||||||
<div class="text-center font-mono">
|
<Show when={status() !== Status.Error}>
|
||||||
{props.dni}
|
<div class="grid gap-1 grid-cols-[7rem_10rem_10rem_16rem] hover:bg-c-surface-variant hover:text-c-on-surface-variant">
|
||||||
</div>
|
<div class="text-center font-mono">
|
||||||
<div class="text-center font-mono">
|
{props.dni}
|
||||||
{person()?.apellidoPaterno ?? "..."}
|
</div>
|
||||||
</div>
|
|
||||||
<div class="text-center font-mono">
|
<Switch>
|
||||||
{person()?.apellidoMaterno ?? "..."}
|
<Match when={status() === Status.Empty}>
|
||||||
</div>
|
<div class="text-center font-mono"></div>
|
||||||
<div class="text-center font-mono">
|
<div class="text-center font-mono"></div>
|
||||||
{person()?.nombres ?? "..."}
|
<div class="text-center font-mono"></div>
|
||||||
</div>
|
</Match>
|
||||||
</div>
|
|
||||||
|
<Match when={status() === Status.Loading}>
|
||||||
|
<div class="text-center font-mono">...</div>
|
||||||
|
<div class="text-center font-mono">...</div>
|
||||||
|
<div class="text-center font-mono">...</div>
|
||||||
|
</Match>
|
||||||
|
|
||||||
|
<Match when={status() === Status.Ok}>
|
||||||
|
<div class="text-center font-mono">
|
||||||
|
{person()?.apellidoPaterno ?? "!"}
|
||||||
|
</div>
|
||||||
|
<div class="text-center font-mono">
|
||||||
|
{person()?.apellidoMaterno ?? "!"}
|
||||||
|
</div>
|
||||||
|
<div class="text-center font-mono">
|
||||||
|
{person()?.nombres ?? "!"}
|
||||||
|
</div>
|
||||||
|
</Match>
|
||||||
|
|
||||||
|
</Switch>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
|
<Show when={status() === Status.Error}>
|
||||||
|
<DniRegister dni={props.dni} onSuccess={loadPerson} />
|
||||||
|
</Show>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
104
src/views/AulaVirtual/DniEntry/DniRegister.tsx
Normal file
104
src/views/AulaVirtual/DniEntry/DniRegister.tsx
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import { createSignal, JSX } from "solid-js";
|
||||||
|
|
||||||
|
type HTMLEventFn = JSX.EventHandlerUnion<HTMLFormElement, Event & {
|
||||||
|
submitter: HTMLElement;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export function DniRegister(props: {dni: string, onSuccess: () => void}) {
|
||||||
|
const [nombres, setNombres] = createSignal("");
|
||||||
|
const [apellidoP, setApellidoP] = createSignal("");
|
||||||
|
const [apellidoM, setApellidoM] = createSignal("");
|
||||||
|
const [loading, setLoading] = createSignal(false);
|
||||||
|
const [error, setError] = createSignal("");
|
||||||
|
|
||||||
|
const register: HTMLEventFn = async(ev) => {
|
||||||
|
ev.preventDefault();
|
||||||
|
setLoading(true);
|
||||||
|
setError("");
|
||||||
|
|
||||||
|
if (props.dni.length !== 8) {
|
||||||
|
setLoading(false);
|
||||||
|
setError("DNI es invalido");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch("/person", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
dni: props.dni.toUpperCase(),
|
||||||
|
apellidoPaterno: apellidoP().toUpperCase(),
|
||||||
|
apellidoMaterno: apellidoM().toUpperCase(),
|
||||||
|
nombres: nombres().toUpperCase(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
props.onSuccess();
|
||||||
|
} else {
|
||||||
|
const d = await response.json();
|
||||||
|
setError(`Error creando persona en BD. ${d}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form class="grid gap-1 grid-cols-[7rem_10rem_10rem_16rem_7rem] w-full" onsubmit={register}>
|
||||||
|
<div class="text-center font-mono">
|
||||||
|
{props.dni}
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
id="add-person-apellido-paterno"
|
||||||
|
class="bg-c-background text-c-on-background border-c-outline border-2 rounded px-2 py-1
|
||||||
|
invalid:border-c-error invalid:text-c-error
|
||||||
|
focus:border-c-primary outline-none
|
||||||
|
disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
type="text"
|
||||||
|
placeholder="Apellido paterno"
|
||||||
|
value={apellidoP()}
|
||||||
|
required={true}
|
||||||
|
onChange={(e) => setApellidoP(e.target.value.toUpperCase())}
|
||||||
|
disabled={loading()}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
id="add-person-apellido-materno"
|
||||||
|
class="bg-c-background text-c-on-background border-c-outline border-2 rounded px-2 py-1
|
||||||
|
invalid:border-c-error invalid:text-c-error
|
||||||
|
focus:border-c-primary outline-none
|
||||||
|
disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
type="text"
|
||||||
|
placeholder="Apellido materno"
|
||||||
|
value={apellidoM()}
|
||||||
|
required={true}
|
||||||
|
onChange={(e) => setApellidoM(e.target.value.toUpperCase())}
|
||||||
|
disabled={loading()}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
id="add-person-nombres"
|
||||||
|
name="add-person-nombres"
|
||||||
|
class="bg-c-background text-c-on-background border-c-outline border-2 rounded px-2 py-1
|
||||||
|
invalid:border-c-error invalid:text-c-error
|
||||||
|
focus:border-c-primary outline-none
|
||||||
|
disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
type="text"
|
||||||
|
placeholder="Nombres"
|
||||||
|
value={nombres()}
|
||||||
|
required={true}
|
||||||
|
onChange={(e) => setNombres(e.target.value.toUpperCase())}
|
||||||
|
disabled={loading()}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<input
|
||||||
|
class={`bg-c-primary text-c-on-primary px-4 py-2 rounded-md cursor-pointer
|
||||||
|
disabled:opacity-50 disabled:cursor-not-allowed
|
||||||
|
${loading() ? "animate-pulse" : ""}`}
|
||||||
|
type="submit"
|
||||||
|
value="Registrar"
|
||||||
|
disabled={loading()}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
@ -1,23 +1,32 @@
|
|||||||
import { For } from "solid-js";
|
import { For } from "solid-js";
|
||||||
import { DniEntry } from "./DniEntry";
|
import { DniEntry } from "./DniEntry";
|
||||||
|
|
||||||
export function DniGroup(props: {group: string}) {
|
export function DniGroup(props: {group: string, index: number}) {
|
||||||
const dnis = () => [...props.group.matchAll(/\d+/g)];
|
const dnis = () => [...props.group.matchAll(/\d+/g)];
|
||||||
|
|
||||||
return (
|
console.log("Loading group...");
|
||||||
<div>
|
|
||||||
<h2>DNI Group</h2>
|
|
||||||
|
|
||||||
<div class="grid gap-1 grid-cols-[7rem_10rem_10rem_16rem]">
|
return (
|
||||||
<div class="text-center">DNI</div>
|
<div class="grid grid-cols-[53rem_auto] gap-2 my-8">
|
||||||
<div class="text-center">Apellido Paterno</div>
|
<div class="border border-c-outline rounded-xl">
|
||||||
<div class="text-center">Apellido Materno</div>
|
<div class="grid gap-1 grid-cols-[7rem_10rem_10rem_16rem] border-b">
|
||||||
<div class="text-center">Nombres</div>
|
<div class="text-center">DNI</div>
|
||||||
|
<div class="text-center">Apellido Paterno</div>
|
||||||
|
<div class="text-center">Apellido Materno</div>
|
||||||
|
<div class="text-center">Nombres</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<For each={dnis()}>
|
||||||
|
{(dni) => <DniEntry dni={dni.toString()} />}
|
||||||
|
</For>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<For each={dnis()}>
|
<div class="border border-c-outline rounded-xl p-2">
|
||||||
{(dni) => <DniEntry dni={dni.toString()} />}
|
<h2 class="font-medium text-xl text-c-success pb-2">
|
||||||
</For>
|
Grupo #{props.index + 1} - cursos y fechas
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ export function DniTable(props: {dniGroups: Array<string>}) {
|
|||||||
<h2 class="my-2 font-bold text-xl">2. Revisar grupos</h2>
|
<h2 class="my-2 font-bold text-xl">2. Revisar grupos</h2>
|
||||||
|
|
||||||
<For each={props.dniGroups}>
|
<For each={props.dniGroups}>
|
||||||
{(g) => <DniGroup group={g} />}
|
{(g, index) => <DniGroup group={g} index={index()} />}
|
||||||
</For>
|
</For>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -42,7 +42,7 @@ export function Dnis(props: {addDniGroup: (v: string) => void}) {
|
|||||||
|
|
||||||
<input
|
<input
|
||||||
class="bg-c-primary text-c-on-primary px-4 py-2 rounded-md cursor-pointer
|
class="bg-c-primary text-c-on-primary px-4 py-2 rounded-md cursor-pointer
|
||||||
disabled:opacity-50 disabled:cursor-not-allowed"
|
disabled:opacity-50 disabled:cursor-not-allowed mt-2"
|
||||||
type="submit"
|
type="submit"
|
||||||
value="Agregar grupo"
|
value="Agregar grupo"
|
||||||
/>
|
/>
|
||||||
|
Loading…
Reference in New Issue
Block a user