2023-08-24 22:31:40 +00:00
|
|
|
import { FilledCard } from "../../components/FilledCard";
|
2023-09-20 17:26:40 +00:00
|
|
|
import { For, Show, createSignal } from "solid-js";
|
2023-08-24 22:31:40 +00:00
|
|
|
import { XIcon } from "../../icons/XIcon";
|
2023-08-25 22:54:30 +00:00
|
|
|
import { allCourses } from "../../utils/allCourses";
|
2023-08-28 22:28:58 +00:00
|
|
|
import { RegisterBatchCreate } from "../../types/Register";
|
2023-09-02 23:49:13 +00:00
|
|
|
import { RegistrationPreview } from ".";
|
2023-09-03 00:42:57 +00:00
|
|
|
import { loadCustomLabels } from "../../utils/allCustomLabels";
|
2023-09-20 17:26:40 +00:00
|
|
|
import { FileDashedIcon } from "../../icons/FileDashedIcon";
|
2023-10-03 02:33:29 +00:00
|
|
|
import { LoadingIcon } from "../../icons/LoadingIcon";
|
2023-08-24 22:31:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
function isoDateToLocalDate(date: string): string {
|
|
|
|
const [,month, day] = /\d{4}-(\d{2})-(\d{2})/.exec(date) ?? "";
|
|
|
|
return `${day}/${month}`;
|
|
|
|
}
|
|
|
|
|
2023-09-07 22:18:21 +00:00
|
|
|
function wait(ms: number) {
|
|
|
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
|
}
|
|
|
|
|
2023-09-02 23:49:13 +00:00
|
|
|
export function RegisterPreview(props: {selections: Array<RegistrationPreview>, personId: number | null, onDelete: (v: number) => void, onRegister: () => void}) {
|
2023-09-07 22:18:21 +00:00
|
|
|
const [loading, setLoading] = createSignal(false);
|
|
|
|
|
2023-08-24 22:31:40 +00:00
|
|
|
const submit = async() => {
|
2023-09-07 22:18:21 +00:00
|
|
|
setLoading(true);
|
|
|
|
|
|
|
|
await wait(2000);
|
|
|
|
|
2023-10-04 21:53:54 +00:00
|
|
|
const registers: RegisterBatchCreate = props.selections.map(({courseId, date, customLabel, is_preview, custom_label_id}) => ({
|
2023-08-28 22:28:58 +00:00
|
|
|
person_id: props.personId!,
|
|
|
|
course_id: courseId,
|
|
|
|
date,
|
2023-09-03 00:42:57 +00:00
|
|
|
custom_label: customLabel,
|
2023-09-20 17:26:40 +00:00
|
|
|
is_preview,
|
2023-10-04 21:53:54 +00:00
|
|
|
custom_label_id,
|
2023-08-28 22:28:58 +00:00
|
|
|
}));
|
|
|
|
|
|
|
|
const result = await createRegisters(registers);
|
2023-08-24 22:31:40 +00:00
|
|
|
|
2023-08-28 22:28:58 +00:00
|
|
|
if (result === null) {
|
2023-08-31 17:11:48 +00:00
|
|
|
console.log("Create register: success");
|
2023-09-03 00:42:57 +00:00
|
|
|
// Custom labels may have changed, reload them
|
|
|
|
loadCustomLabels();
|
2023-08-28 22:28:58 +00:00
|
|
|
} else {
|
|
|
|
console.log(`error. ${result}`);
|
2023-08-24 22:31:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
props.onRegister();
|
2023-09-07 22:18:21 +00:00
|
|
|
setLoading(false);
|
2023-08-24 22:31:40 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
|
|
<FilledCard class="border border-c-outline overflow-hidden">
|
|
|
|
<h2 class="p-4 font-bold text-xl">Confirmar registro</h2>
|
|
|
|
<div class="bg-c-surface p-4">
|
|
|
|
<For each={props.selections}>
|
2023-09-20 17:26:40 +00:00
|
|
|
{({courseId, date, customLabel, is_preview}) => (
|
2023-09-02 23:49:13 +00:00
|
|
|
<Register
|
|
|
|
courseId={courseId}
|
|
|
|
date={date}
|
|
|
|
onDelete={props.onDelete}
|
|
|
|
customLabel={customLabel}
|
2023-09-20 17:26:40 +00:00
|
|
|
isPreview={is_preview}
|
2023-09-02 23:49:13 +00:00
|
|
|
/>
|
|
|
|
)}
|
2023-08-24 22:31:40 +00:00
|
|
|
</For>
|
|
|
|
|
|
|
|
<button
|
|
|
|
class="bg-c-primary text-c-on-primary px-4 py-2 rounded-full cursor-pointer mt-4
|
2023-10-03 02:33:29 +00:00
|
|
|
disabled:opacity-50 disabled:cursor-not-allowed relative"
|
2023-08-24 22:31:40 +00:00
|
|
|
type="button"
|
2023-09-07 22:18:21 +00:00
|
|
|
disabled={props.selections.length === 0 || loading()}
|
2023-08-24 22:31:40 +00:00
|
|
|
onclick={submit}
|
|
|
|
>
|
2023-10-03 02:33:29 +00:00
|
|
|
<span
|
|
|
|
class="absolute top-1 left-2"
|
|
|
|
style={{display: loading() ? "inline-block" : "none"}}
|
|
|
|
>
|
|
|
|
<LoadingIcon
|
|
|
|
class="animate-spin"
|
|
|
|
fill="var(--c-primary-container)"
|
|
|
|
/>
|
|
|
|
</span>
|
|
|
|
<span class="ml-6">
|
|
|
|
Registrar {props.selections.length} cursos
|
|
|
|
</span>
|
2023-08-24 22:31:40 +00:00
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</FilledCard>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-09-20 17:26:40 +00:00
|
|
|
function Register(props: {
|
|
|
|
courseId: number,
|
2023-10-03 02:33:29 +00:00
|
|
|
date: string,
|
|
|
|
customLabel: string,
|
|
|
|
onDelete: (v: number) => void,
|
|
|
|
isPreview: boolean,
|
|
|
|
}) {
|
2023-08-24 22:31:40 +00:00
|
|
|
const courseName = () => {
|
2023-08-25 22:54:30 +00:00
|
|
|
const courses = allCourses();
|
2023-08-31 17:11:48 +00:00
|
|
|
return courses.find((course) => course.course_id === props.courseId)?.course_name ?? `Curso invalido! (${props.courseId})`;
|
2023-08-24 22:31:40 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
2023-09-20 17:26:40 +00:00
|
|
|
<div class="grid grid-cols-[auto_3rem_1.5rem] py-1 px-2 rounded-md border border-c-outline my-1">
|
|
|
|
<span title={props.isPreview ? "Sin firmas" : ""}>
|
|
|
|
<Show when={props.isPreview}>
|
|
|
|
<FileDashedIcon size={16} class="pr-2" fill="var(--c-on-surface)" />
|
|
|
|
</Show>
|
|
|
|
{courseName()}
|
|
|
|
</span>
|
|
|
|
<span class="font-mono">
|
|
|
|
{isoDateToLocalDate(props.date)}
|
|
|
|
</span>
|
2023-08-24 22:31:40 +00:00
|
|
|
<button
|
|
|
|
class="hover:bg-c-surface-variant rounded-md"
|
|
|
|
onclick={() => props.onDelete(props.courseId)}
|
|
|
|
>
|
|
|
|
<XIcon fill="var(--c-on-surface)" />
|
|
|
|
</button>
|
2023-09-20 17:26:40 +00:00
|
|
|
<span>
|
|
|
|
{props.customLabel}
|
|
|
|
</span>
|
2023-08-24 22:31:40 +00:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-08-28 22:28:58 +00:00
|
|
|
async function createRegisters(data: RegisterBatchCreate): Promise<null | string> {
|
|
|
|
const response = await fetch(`${import.meta.env.VITE_BACKEND_URL}/api/register/batch`, {
|
2023-08-24 22:31:40 +00:00
|
|
|
method: "POST",
|
|
|
|
headers: {
|
|
|
|
"Content-Type": "application/json",
|
|
|
|
},
|
2023-08-28 22:28:58 +00:00
|
|
|
body: JSON.stringify(data),
|
2023-08-24 22:31:40 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
if (response.ok) {
|
|
|
|
return null;
|
|
|
|
} else {
|
|
|
|
const data = await response.json();
|
|
|
|
return JSON.stringify(data);
|
|
|
|
}
|
|
|
|
}
|