[Certs] FE & BE Mock for registers
This commit is contained in:
parent
fadbfbc7be
commit
81157d53de
@ -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])
|
||||
}
|
||||
|
@ -1,2 +1,3 @@
|
||||
pub mod course;
|
||||
pub mod person;
|
||||
pub mod register;
|
||||
|
38
backend/src/controller/register/mod.rs
Normal file
38
backend/src/controller/register/mod.rs
Normal 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])
|
||||
}
|
@ -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,
|
||||
])
|
||||
}
|
||||
|
@ -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`
|
||||
|
@ -1,2 +1,3 @@
|
||||
pub mod course;
|
||||
pub mod person;
|
||||
pub mod register;
|
||||
|
36
backend/src/model/register.rs
Normal file
36
backend/src/model/register.rs
Normal 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
2
frontend/.env.local
Normal file
@ -0,0 +1,2 @@
|
||||
VITE_BACKEND_URL=http://localhost:8000
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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,21 +79,25 @@ export function ManualRegistration(props: {personId: number | null, onAdd: (v: [
|
||||
</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"
|
||||
type="submit"
|
||||
value="Agregar"
|
||||
disabled={props.personId === null}
|
||||
/>
|
||||
</form>
|
||||
<div>
|
||||
|
||||
<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>
|
||||
|
||||
<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}
|
||||
/>
|
||||
|
||||
<p
|
||||
class="my-2 p-1 w-fit mx-4 text-c-error inline-block"
|
||||
// style={{opacity: error() === "" ? "0" : "1", "user-select": "none"}}
|
||||
>
|
||||
{error()}
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -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,19 +14,18 @@ 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,
|
||||
date,
|
||||
);
|
||||
const registers: RegisterBatchCreate = props.selections.map(([courseId, date]) => ({
|
||||
person_id: props.personId!,
|
||||
course_id: courseId,
|
||||
date,
|
||||
}));
|
||||
|
||||
if (result === null) {
|
||||
console.log("Success");
|
||||
} else {
|
||||
console.log(`error. ${result}`);
|
||||
}
|
||||
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) {
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
31
frontend/src/certs/Registers/index.tsx
Normal file
31
frontend/src/certs/Registers/index.tsx
Normal 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>
|
||||
);
|
||||
}
|
29
frontend/src/types/Register.ts
Normal file
29
frontend/src/types/Register.ts
Normal 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,
|
||||
}
|
Loading…
Reference in New Issue
Block a user