Add stats endpoint
continuous-integration/drone/push Build is passing Details

main
Julius 2022-06-28 20:09:24 +02:00
parent 55bd482551
commit 0e5f70e7a4
Signed by: j00lz
GPG Key ID: AF241B0AA237BBA2
2 changed files with 36 additions and 7 deletions

View File

@ -376,6 +376,23 @@ async fn remove_ticket(
"OK" "OK"
} }
#[derive(Debug, Clone, Serialize, Deserialize)]
struct StatResponse {
total: i32,
inside: i32,
}
async fn stats(
_: User,
Extension(pool): Extension<Database>,
Path(party): Path<i32>,
) -> Json<StatResponse> {
let tickets = pool.get_all_tickets_for_party(party).await;
let total = tickets.len() as i32;
let inside = tickets.iter().filter(|t| t.inside).count() as i32;
Json(StatResponse { total, inside })
}
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let url = if let Some(url) = std::env::var("DATABASE_URL").ok() { let url = if let Some(url) = std::env::var("DATABASE_URL").ok() {
@ -383,10 +400,7 @@ async fn main() {
} else { } else {
"postgres://tickets:verysecure@localhost:5432/tickets".to_string() "postgres://tickets:verysecure@localhost:5432/tickets".to_string()
}; };
let pool = PgPoolOptions::new() let pool = PgPoolOptions::new().connect(&url).await.unwrap();
.connect(&url)
.await
.unwrap();
db::setup_db(&pool).await; db::setup_db(&pool).await;
let pool = Arc::new(Db::new(pool)); let pool = Arc::new(Db::new(pool));
if let None = pool.get_user_by_username("admin").await { if let None = pool.get_user_by_username("admin").await {
@ -419,6 +433,7 @@ async fn main() {
"/static", "/static",
get_service(ServeDir::new("static")).handle_error(handle_error), get_service(ServeDir::new("static")).handle_error(handle_error),
) )
.route("/api/party/:id/stats", get(stats))
.layer(Extension(pool)); .layer(Extension(pool));
axum::Server::bind(&"0.0.0.0:8080".parse().unwrap()) axum::Server::bind(&"0.0.0.0:8080".parse().unwrap())

View File

@ -12,15 +12,16 @@
<input type="radio" name="mode" value="true"><i class="form-icon"></i> Controleren <input type="radio" name="mode" value="true"><i class="form-icon"></i> Controleren
</label> </label>
</div> </div>
<h2>Camera</h2> <h2>Informatie</h2>
<div> <div>
<p><select id="videoSource"></select><button class="btn btn-primary" id="start_scan_btn">Start <p><select id="videoSource"></select><button class="btn btn-primary" id="start_scan_btn">Start
Scannen</button> </p> Scannen</button> </p>
<h4><span id="last-scanned">Nog geen gescand</span></h4>
<h3><span id="scan-status">Nog geen gescand</span></h3>
<div class="columns"> <div class="columns">
<video autoplay playsinline controls="false" class="column col-12"></video> <video autoplay playsinline controls="false" class="column col-12"></video>
</div> </div>
<h4><span id="last-scanned">Nog geen gescand</span></h4>
<h3><span id="scan-status">Nog geen gescand</span></h3>
<h3>Binnen/Betaald: <span id="stats">Laden...</span></h3>
</div> </div>
<div class="columns"> <div class="columns">
<div class="column col-md-12 col-6"> <div class="column col-md-12 col-6">
@ -104,7 +105,19 @@
} else { } else {
alert("Error"); alert("Error");
} }
fetch_stats()
} }
function fetch_stats() {
let party_id = +document.getElementById("party_id").value;
fetch(`/api/party/${party_id}/stats`)
.then(response => response.json())
.then(data => {
document.getElementById("stats").innerText = `${data.inside}/${data.total}`;
});
}
function scan_ticket(code) { function scan_ticket(code) {
let check = document.querySelector('input[name="mode"]:checked').value === "true"; let check = document.querySelector('input[name="mode"]:checked').value === "true";
let party_id = +document.getElementById("party_id").value; let party_id = +document.getElementById("party_id").value;
@ -256,6 +269,7 @@
let elem = document.getElementById("student_number"); let elem = document.getElementById("student_number");
elem.focus(); elem.focus();
elem.select(); elem.select();
fetch_stats();
</script> </script>
{% endblock %} {% endblock %}