Support registering & displaying preview certs

master
Araozu 2023-09-20 12:26:40 -05:00
parent 6bd0acc03e
commit e8e5835236
9 changed files with 88 additions and 31 deletions

View File

@ -1,6 +1,5 @@
use crate::db;
use serde::{Deserialize, Serialize};
use sqlx::Row;
#[derive(sqlx::FromRow, Serialize, Deserialize)]
pub struct CustomLabel {

View File

@ -16,6 +16,7 @@ pub struct RegisterCreate {
date: String,
/// Foreign key to the custom_label table
custom_label: String,
is_preview: bool,
}
impl RegisterCreate {
@ -57,7 +58,7 @@ impl RegisterCreate {
current_date,
self.date,
custom_label_id,
false,
self.is_preview,
self.person_id,
self.course_id
)

View File

@ -18,6 +18,7 @@ export function ManualRegistration(props: {
const [selectedCourseId, seSelectedCourseId] = createSignal<number | null>(null);
const [customLabel, setCustomLabel] = createSignal("");
const [isPreview, setIsPreview] = createSignal(false);
let datePicker: HTMLInputElement | undefined;
@ -68,6 +69,7 @@ export function ManualRegistration(props: {
courseId: subject,
date,
customLabel: customLabel(),
is_preview: isPreview(),
};
props.onAdd(data);
@ -86,7 +88,7 @@ export function ManualRegistration(props: {
/>
</div>
<div class="my-4 grid grid-cols-[9.5rem_auto] gap-2">
<div class="mt-4 mb-2 grid grid-cols-[9.5rem_auto] gap-2">
<div class="relative">
<input
ref={datePicker}
@ -108,7 +110,16 @@ export function ManualRegistration(props: {
</div>
</Show>
</div>
<div>
<input
oninput={(ev) => setIsPreview(ev.target.checked)}
checked={isPreview()}
type="checkbox"
name="is_preview"
id="manual-is-preview"
/>
<label class="px-2 py-2 select-none" for="manual-is-preview">Cert sin firmas</label>
</div>
<div>

View File

@ -46,6 +46,7 @@ export function RegisterPresets(props: {
}) {
let datePicker: HTMLInputElement | undefined;
const [selectedPreset, setSelectedPreset] = createSignal<PresetName>("None");
const [isPreview, setIsPreview] = createSignal(false);
const [error, setError] = createSignal("");
const presets = genPresets();
@ -86,6 +87,7 @@ export function RegisterPresets(props: {
courseId,
date: dateYYYYMMDD,
customLabel: "",
is_preview: isPreview(),
});
// Substract current date for the next course
@ -112,7 +114,7 @@ export function RegisterPresets(props: {
</For>
</div>
</div>
<div class="my-4">
<div class="mt-4 mb-2">
<div class="relative">
<input
ref={datePicker}
@ -123,6 +125,16 @@ export function RegisterPresets(props: {
<label for="create-date" class="absolute -top-2 left-2 text-xs bg-c-surface px-1">Fecha</label>
</div>
</div>
<div>
<input
oninput={(ev) => setIsPreview(ev.target.checked)}
checked={isPreview()}
type="checkbox"
name="is_preview"
id="preset-is-preview"
/>
<label class="px-2 py-2 select-none" for="preset-is-preview">Cert sin firmas</label>
</div>
<div>
<input
class="bg-c-primary text-c-on-primary px-4 py-2 rounded-full cursor-pointer

View File

@ -1,10 +1,11 @@
import { FilledCard } from "../../components/FilledCard";
import { For, createSignal } from "solid-js";
import { For, Show, createSignal } from "solid-js";
import { XIcon } from "../../icons/XIcon";
import { allCourses } from "../../utils/allCourses";
import { RegisterBatchCreate } from "../../types/Register";
import { RegistrationPreview } from ".";
import { loadCustomLabels } from "../../utils/allCustomLabels";
import { FileDashedIcon } from "../../icons/FileDashedIcon";
function isoDateToLocalDate(date: string): string {
@ -24,11 +25,12 @@ export function RegisterPreview(props: {selections: Array<RegistrationPreview>,
await wait(2000);
const registers: RegisterBatchCreate = props.selections.map(({courseId, date, customLabel}) => ({
const registers: RegisterBatchCreate = props.selections.map(({courseId, date, customLabel, is_preview}) => ({
person_id: props.personId!,
course_id: courseId,
date,
custom_label: customLabel,
is_preview,
}));
const result = await createRegisters(registers);
@ -50,12 +52,13 @@ export function RegisterPreview(props: {selections: Array<RegistrationPreview>,
<h2 class="p-4 font-bold text-xl">Confirmar registro</h2>
<div class="bg-c-surface p-4">
<For each={props.selections}>
{({courseId, date, customLabel}) => (
{({courseId, date, customLabel, is_preview}) => (
<Register
courseId={courseId}
date={date}
onDelete={props.onDelete}
customLabel={customLabel}
isPreview={is_preview}
/>
)}
</For>
@ -74,23 +77,38 @@ export function RegisterPreview(props: {selections: Array<RegistrationPreview>,
);
}
function Register(props: {courseId: number, date: string, customLabel: string, onDelete: (v: number) => void}) {
function Register(props: {
courseId: number,
date: string,
customLabel: string,
onDelete: (v: number) => void,
isPreview: boolean,
}) {
const courseName = () => {
const courses = allCourses();
return courses.find((course) => course.course_id === props.courseId)?.course_name ?? `Curso invalido! (${props.courseId})`;
};
return (
<div class="grid grid-cols-[auto_4rem_1.5rem] py-1 px-2 rounded-md border border-c-outline my-1">
<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 class="font-mono">{isoDateToLocalDate(props.date)}</span>
</span>
<span class="font-mono">
{isoDateToLocalDate(props.date)}
</span>
<button
class="hover:bg-c-surface-variant rounded-md"
onclick={() => props.onDelete(props.courseId)}
>
<XIcon fill="var(--c-on-surface)" />
</button>
<span>
{props.customLabel}
</span>
</div>
);
}

View File

@ -11,6 +11,7 @@ export type RegistrationPreview = {
courseId: number,
date: string,
customLabel: string,
is_preview: boolean,
}
export function NewRegister(props: {
@ -32,7 +33,7 @@ export function NewRegister(props: {
<RegisterTabs active={active()} setActive={setActive} />
<div class="bg-c-surface p-4 h-[22rem]">
<div class="bg-c-surface p-4 h-[23rem]">
<Show when={active() === "Presets"}>
<RegisterPresets
onAdd={(v) => setSelections((x) => [...x, v])}

View File

@ -1,4 +1,4 @@
import { For, Show, createEffect, createMemo, createSignal } from "solid-js";
import { For, Match, Show, createEffect, createMemo, createSignal } from "solid-js";
import { Person } from "../../types/Person";
import { Register } from "../../types/Register";
import { courseMap } from "../../utils/allCourses";
@ -180,18 +180,6 @@ function RegisterEl(props: {register: Register, person: Person, onClick: () => v
return (
<div class="grid grid-cols-[11rem_1.5rem_1.25rem] border border-c-outline rounded-md">
{/*
<div class=" w-12 inline-block">
<Show when={generateable()}>
<button
onclick={genCert}
class="rounded-full bg-c-primary-container hover:bg-c-primary transition-colors h-12 w-12"
>
<DownloadIcon fill="var(--c-on-primary-container)" />
</button>
</Show>
</div>
*/}
<div class="p-1 border-r border-c-outline-50 align-middle">
<p
class="font-bold overflow-hidden whitespace-nowrap"
@ -205,10 +193,21 @@ function RegisterEl(props: {register: Register, person: Person, onClick: () => v
</span>
&nbsp;
</p>
<p class="font-mono text-sm">
<p class="text-sm">
<span class="font-mono">
{displayDate()}
&nbsp;-&nbsp;
{props.register.register_code}
</span>
<Show when={props.register.register_is_preview}>
<span class="text-c-error font-bold select-none">
&nbsp;sin firmas
</span>
</Show>
<Show when={!props.register.register_is_preview}>
<span class="font-mono">
&nbsp;- {props.register.register_code}
</span>
</Show>
</p>
</div>
<button

View File

@ -0,0 +1,15 @@
export function FileDashedIcon(props: {fill: string, size?: number, class?: string}) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
class={`inline-block w-6 ${props.class}`}
width={props.size ?? 32}
height={props.size ?? 32}
fill={props.fill}
viewBox="0 0 256 256"
>
<path d="M80,224a8,8,0,0,1-8,8H56a16,16,0,0,1-16-16V184a8,8,0,0,1,16,0v32H72A8,8,0,0,1,80,224ZM216,88v48a8,8,0,0,1-16,0V96H152a8,8,0,0,1-8-8V40H120a8,8,0,0,1,0-16h32a8,8,0,0,1,5.66,2.34l56,56A8,8,0,0,1,216,88Zm-56-8h28.69L160,51.31ZM80,24H56A16,16,0,0,0,40,40V64a8,8,0,0,0,16,0V40H80a8,8,0,0,0,0-16ZM208,168a8,8,0,0,0-8,8v40h-8a8,8,0,0,0,0,16h8a16,16,0,0,0,16-16V176A8,8,0,0,0,208,168ZM48,152a8,8,0,0,0,8-8V104a8,8,0,0,0-16,0v40A8,8,0,0,0,48,152Zm104,64H112a8,8,0,0,0,0,16h40a8,8,0,0,0,0-16Z" />
</svg>
);
}

View File

@ -9,6 +9,7 @@ export type RegisterBatchCreate = Array<{
* Value of the custom label
*/
custom_label: string,
is_preview: boolean,
}>
export type Register = {