[Certs] FE & BE Mock for registers

This commit is contained in:
Araozu 2023-08-28 17:28:58 -05:00
parent fadbfbc7be
commit 81157d53de
14 changed files with 186 additions and 66 deletions

View File

@ -7,12 +7,19 @@ pub async fn get_all() -> Json<Vec<Course>> {
// TODO: get from database
let c = Course {
course_id: 1,
course_code: 322,
course_name: "4x4".to_string(),
course_display_name: "Manejo en 4x4 road danger".to_string(),
course_days_amount: 2,
course_has_custom_label: false,
};
Json(vec![c.clone(), c])
let c2 = Course {
course_id: 2,
course_name: "Mec. Basica".to_string(),
course_display_name: "Mecánica Básica".to_string(),
course_days_amount: 2,
course_has_custom_label: false,
};
Json(vec![c, c2])
}

View File

@ -1,2 +1,3 @@
pub mod course;
pub mod person;
pub mod register;

View File

@ -0,0 +1,38 @@
use rocket::{serde::json::Json, http::Status};
use crate::model::register::{RegisterCreate, Register};
#[options("/register/batch")]
pub fn options() -> Status {
Status::Ok
}
#[post("/register/batch", format = "json", data = "<data>")]
pub async fn insert_all(data: Json<Vec<RegisterCreate>>) -> Status {
Status::Ok
}
#[get("/register/<dni>")]
pub async fn get_by_dni(dni: i32) -> Json<Vec<Register>> {
let r1 = Register {
register_id: 1,
register_code: 322,
register_creation_date: "2021-01-01".to_string(),
register_display_date: "2021-01-01".to_string(),
register_custom_label: "".to_string(),
register_person_id: 1,
register_course_id: 1,
};
let r2 = Register {
register_id: 2,
register_code: 323,
register_creation_date: "2021-01-01".to_string(),
register_display_date: "2021-01-03".to_string(),
register_custom_label: "".to_string(),
register_person_id: 1,
register_course_id: 2,
};
Json(vec![r1, r2])
}

View File

@ -40,5 +40,8 @@ fn rocket() -> _ {
.mount("/api", routes![
controller::person::get_by_dni,
controller::course::get_all,
controller::register::insert_all,
controller::register::options,
controller::register::get_by_dni,
])
}

View File

@ -4,11 +4,6 @@ use rocket::serde::Serialize;
#[serde(crate = "rocket::serde")]
pub struct Course {
pub course_id: i32,
/// Display code, shown on the certificate.
/// Currently a 4-digit number. After 9999, it will be a 4-digit hex number.
///
/// Example: `0322`
pub course_code: i32,
/// Internal name, shown in the admin panel
///
/// Example: `4x4`

View File

@ -1,2 +1,3 @@
pub mod course;
pub mod person;
pub mod register;

View File

@ -0,0 +1,36 @@
use rocket::serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Clone)]
#[serde(crate = "rocket::serde")]
/// Represents a single register send by the frontend
/// to create a new register in the database
pub struct RegisterCreate {
person_id: i32,
course_id: i32,
/// YYYY-MM-DD
date: String
}
#[derive(Serialize, Deserialize, Clone)]
#[serde(crate = "rocket::serde")]
pub struct Register {
pub register_id: i32,
/// Display code, shown on the certificate.
/// Currently a 4-digit number. After 9999, it will be a 4-digit hex number.
///
/// Example: `0322``
pub register_code: i32,
/// Date of creation of the register, in YYYY-MM-DD format
pub register_creation_date: String,
/// Date shown on the certificate, in YYYY-MM-DD format
pub register_display_date: String,
/// Some course's names can be extended with a label.
/// Used in machinery courses, where the course name is the type of machinery,
/// and the custom label the manufacturer and series (i.e. `320D CAT`).
pub register_custom_label: String,
/// Foreign key to the person table
pub register_person_id: i32,
/// Foreign key to the course table
pub register_course_id: i32,
}

2
frontend/.env.local Normal file
View File

@ -0,0 +1,2 @@
VITE_BACKEND_URL=http://localhost:8000

View File

@ -7,7 +7,10 @@ const App: Component = () => (
<div class="grid grid-cols-[5rem_auto]">
<NavRail />
<Routes>
<Route path="/" component={() => <p>En construccion</p>} />
<Route path="/certs" component={Certs} />
<Route path="/accesos" component={() => <p>En construccion</p>} />
<Route path="/escaneo" component={() => <p>En construccion</p>} />
</Routes>
</div>
);

View File

@ -67,7 +67,6 @@ export function ManualRegistration(props: {personId: number | null, onAdd: (v: [
</div>
<div class="relative">
<input
ref={datePicker}
id="create-date"
class="bg-c-surface text-c-on-surface border border-c-outline rounded-lg p-2 font-mono w-full
disabled:opacity-50 disabled:cursor-not-allowed"
@ -80,6 +79,9 @@ export function ManualRegistration(props: {personId: number | null, onAdd: (v: [
</div>
</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"
@ -87,14 +89,15 @@ export function ManualRegistration(props: {personId: number | null, onAdd: (v: [
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"}}
class="my-2 p-1 w-fit mx-4 text-c-error inline-block"
// style={{opacity: error() === "" ? "0" : "1", "user-select": "none"}}
>
{error()}&nbsp;
</p>
</div>
</form>
</>
);
}

View File

@ -2,6 +2,7 @@ import { FilledCard } from "../../components/FilledCard";
import { For } from "solid-js";
import { XIcon } from "../../icons/XIcon";
import { allCourses } from "../../utils/allCourses";
import { RegisterBatchCreate } from "../../types/Register";
function isoDateToLocalDate(date: string): string {
@ -13,20 +14,19 @@ export function RegisterPreview(props: {selections: Array<[number, string]>, per
const submit = async() => {
console.log("Submit...");
// TODO: Send all register requests at once
for (const [courseId, date] of props.selections) {
const result = await defaultNewRegisterFn(
props.personId ?? -1,
courseId,
const registers: RegisterBatchCreate = props.selections.map(([courseId, date]) => ({
person_id: props.personId!,
course_id: courseId,
date,
);
}));
const result = await createRegisters(registers);
if (result === null) {
console.log("Success");
} else {
console.log(`error. ${result}`);
}
}
props.onRegister();
};
@ -74,17 +74,13 @@ function Register(props: {courseId: number, date: string, onDelete: (v: number)
}
async function defaultNewRegisterFn(personId: number, subjectId: number, date: string): Promise<null | string> {
const response = await fetch("/certificate", {
async function createRegisters(data: RegisterBatchCreate): Promise<null | string> {
const response = await fetch(`${import.meta.env.VITE_BACKEND_URL}/api/register/batch`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
personId,
subjectId,
date,
}),
body: JSON.stringify(data),
});
if (response.ok) {

View File

@ -1,25 +0,0 @@
import { DownloadIcon } from "../icons/DownloadIcon";
export function Registers() {
return (
<div class="m-4 p-4 rounded-md">
<h3 class="text-xl font-medium py-2">
SUMA BERNAL, MAIKOL
</h3>
<div class="flex flex-wrap justify-start gap-2">
<div class="inline-block w-[12rem] p-1 border border-c-outline rounded-md">
<button 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>
<div class="inline-block h-12 w-32 pl-2 align-middle">
<p class="font-bold">Matpel 2</p>
<p class="font-mono text-sm">12/08/2023 - 6486</p>
</div>
</div>
</div>
</div>
);
}

View File

@ -0,0 +1,31 @@
import { DownloadIcon } from "../../icons/DownloadIcon";
import { Register } from "../../types/Register";
export function Registers() {
return (
<div class="m-4 p-4 rounded-md">
<h3 class="text-xl font-medium py-2">
SUMA BERNAL, MAIKOL
</h3>
<div class="flex flex-wrap justify-start gap-2">
<RegisterEl />
<RegisterEl />
<RegisterEl />
</div>
</div>
);
}
function RegisterEl(props: {register: Register}) {
return (
<div class="inline-block w-[12rem] p-1 border border-c-outline rounded-md">
<button 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>
<div class="inline-block h-12 w-32 pl-2 align-middle">
<p class="font-bold">Matpel 2</p>
<p class="font-mono text-sm">12/08/2023 - 6486</p>
</div>
</div>
);
}

View File

@ -0,0 +1,29 @@
export type RegisterBatchCreate = Array<{
person_id: number,
course_id: number,
/**
* YYYY-MM-DD
*/
date: string,
}>
export type Register = {
register_id: number,
/// Display code, shown on the certificate.
/// Currently a 4-digit number. After 9999, it will be a 4-digit hex number.
///
/// Example: `0322``
register_code: number,
/// Date of creation of the register, in YYYY-MM-DD format
register_creation_date: string,
/// Date shown on the certificate, in YYYY-MM-DD format
register_display_date: string,
/// Some course's names can be extended with a label.
/// Used in machinery courses, where the course name is the type of machinery,
/// and the custom label the manufacturer and series (i.e. `320D CAT`).
register_custom_label: string,
/// Foreign key to the person table
register_person_id: number,
/// Foreign key to the course table
register_course_id: number,
}