Skip to content

Commit 59bbfa3

Browse files
committed
added attendance
1 parent 51f3615 commit 59bbfa3

File tree

7 files changed

+140
-3
lines changed

7 files changed

+140
-3
lines changed

Makefile.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
[tasks.backend]
32
workspace = false
43
command = "cargo"

usr-backend/src/attendance.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use axum::{
2+
extract::State, http::StatusCode, routing::post, Form, Router
3+
};
4+
use sea_orm::{
5+
sea_query::Table, sqlx::types::chrono::Local, ActiveModelTrait, ActiveValue,
6+
ConnectionTrait, DatabaseConnection, Schema,
7+
};
8+
use serde::Deserialize;
9+
use tracing::error;
10+
11+
use crate::{backup::backup_db, UsrState};
12+
13+
mod attendance;
14+
15+
#[derive(Deserialize)]
16+
struct CheckIn {
17+
uid: String,
18+
}
19+
20+
#[axum::debug_handler]
21+
async fn add_attendance(
22+
State(state): State<&'static UsrState>,
23+
Form(CheckIn { uid }): Form<CheckIn>,
24+
) -> (StatusCode, &'static str) {
25+
let Some(uid) = uid.strip_prefix('u') else {
26+
return (StatusCode::BAD_REQUEST, "");
27+
};
28+
let Ok(uid) = uid.parse::<u32>() else {
29+
return (StatusCode::BAD_REQUEST, "");
30+
};
31+
let active_model = attendance::ActiveModel {
32+
uid: ActiveValue::Set(uid),
33+
date: ActiveValue::Set(Local::now().naive_local()),
34+
};
35+
36+
match active_model.insert(&state.db).await {
37+
Ok(_) => {
38+
backup_db(state);
39+
(StatusCode::OK, "")
40+
}
41+
Err(e) => {
42+
error!("Failed to add attendance: {e}");
43+
(StatusCode::INTERNAL_SERVER_ERROR, "")
44+
}
45+
}
46+
}
47+
48+
pub fn router() -> Router<&'static UsrState> {
49+
Router::new()
50+
.route("/add/attendance", post(add_attendance))
51+
}
52+
53+
pub async fn reset_tables(db: &DatabaseConnection) -> Result<(), sea_orm::DbErr> {
54+
let builder = db.get_database_backend();
55+
let schema = Schema::new(builder);
56+
57+
db.execute(builder.build(Table::drop().table(attendance::Entity).if_exists()))
58+
.await?;
59+
db.execute(builder.build(&schema.create_table_from_entity(attendance::Entity)))
60+
.await?;
61+
62+
Ok(())
63+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
use sea_orm::entity::prelude::*;
2+
use serde::Serialize;
3+
4+
5+
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize)]
6+
#[sea_orm(table_name = "attendance")]
7+
pub struct Model {
8+
#[sea_orm(primary_key)]
9+
pub uid: u32,
10+
#[sea_orm(primary_key)]
11+
pub date: DateTime,
12+
}
13+
14+
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
15+
pub enum Relation {
16+
}
17+
18+
impl ActiveModelBehavior for ActiveModel {}

usr-backend/src/main.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ mod scheduler;
1818
mod manifest;
1919
mod webhook;
2020
mod backup;
21+
mod attendance;
2122

2223
struct LogWriter {
2324
inner: &'static Mutex<LineWriter<std::fs::File>>,
@@ -99,9 +100,14 @@ async fn main() -> anyhow::Result<()> {
99100
manifest::reset_tables(&db).await?;
100101
info!("Reset manifest tables");
101102
}
103+
"attendance" => {
104+
attendance::reset_tables(&db).await?;
105+
info!("Reset attendance tables");
106+
}
102107
"all" => {
103108
scheduler::reset_tables(&db).await?;
104109
manifest::reset_tables(&db).await?;
110+
attendance::reset_tables(&db).await?;
105111
info!("Reset all tables");
106112
}
107113
_ => {
@@ -122,7 +128,8 @@ async fn main() -> anyhow::Result<()> {
122128
"/api",
123129
Router::new()
124130
.nest("/scheduler", scheduler::router())
125-
.nest("/manifest", manifest::router()),
131+
.nest("/manifest", manifest::router())
132+
.nest("/attendance", attendance::router()),
126133
)
127134
.layer(
128135
ServiceBuilder::new()

usr-web/src/routes/(apps)/+layout.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55

66
<header class="fixed top-0 w-full p-2 shadow">
77
<nav class="flex flex-row items-center gap-4">
8-
<a href={`${base}`}>
8+
<a href={`${base}`} aria-label="Home">
99
<enhanced:img src="$lib/icon.png" alt="Utah Student Robotics" class="logo" />
1010
</a>
1111
<a href={`${base}/scheduler`}>Scheduler</a>
12+
<a href={`${base}/attendance`}>Attendance</a>
1213
<!-- <a href={`${base}/manifest`}>Manifest</a> -->
1314
</nav>
1415
</header>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<script lang=ts>
2+
import { PUBLIC_API_ENDPOINT } from '$env/static/public';
3+
</script>
4+
5+
<!-- This iframe prevents redirection -->
6+
<!-- svelte-ignore a11y_missing_attribute -->
7+
<iframe name="dummyframe" id="dummyframe" style="display: none;"></iframe>
8+
9+
<form method="POST" action="{PUBLIC_API_ENDPOINT}/api/attendance/add/attendance" target="dummyframe">
10+
<label>
11+
uID
12+
<input name="uid" placeholder="u1234567" pattern="u[0-9]+" />
13+
</label>
14+
<button onclick={() => {
15+
alert("Checked In");
16+
}}>Check in</button>
17+
</form>
18+
19+
<style>
20+
form {
21+
display: flex;
22+
flex-direction: column;
23+
align-items: start;
24+
margin: 2rem;
25+
}
26+
form label {
27+
display: flex;
28+
flex-direction: column;
29+
margin-bottom: 1rem;
30+
font-weight: bold;
31+
}
32+
form input {
33+
padding: 0.5rem;
34+
font-weight: normal;
35+
}
36+
form button {
37+
padding: 0.5rem;
38+
background-color: lightcoral;
39+
border: 1px solid black;
40+
border-radius: 0.25rem;
41+
}
42+
</style>

usr-web/src/routes/+page.svelte

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
<h2>Scheduler</h2>
1111
<p>A unified schedule for Utah Student Robotics</p>
1212
</a>
13+
<a class="app-card attendance" href={`${base}/attendance`}>
14+
<h2>Attendance</h2>
15+
<p>Add your attendance here if you are contributing!</p>
16+
</a>
1317
<!-- <a class="app-card manifest" href={`${base}/manifest`}>
1418
<h2>Manifest</h2>
1519
<p>Internal tracking of orders and inventory</p>
@@ -34,6 +38,9 @@
3438
.scheduler {
3539
background-color: aquamarine;
3640
}
41+
.attendance {
42+
background-color: lightcoral;
43+
}
3744
/* .manifest {
3845
background-color: cornflowerblue;
3946
} */

0 commit comments

Comments
 (0)