Compare commits

...

2 Commits

5 changed files with 58 additions and 21 deletions

View File

@@ -48,9 +48,22 @@ async fn index(State(backend): State<Arc<Backend>>, cookies: CookieJar) -> Respo
(sightings.len()) (sightings.len())
"/" "/"
(amount_total_cameras) (amount_total_cameras)
" cameras." " cameras:"
progress value=(sightings.len()) max=(amount_total_cameras); progress value=(sightings.len()) max=(amount_total_cameras);
} }
p {
ul.iterated {
@for (idx, sighting) in sightings.iter().enumerate() {
li.card {
span {
span.font-headline.rank.text-muted { (idx+1) }
(sighting.camera.name)
}
}
}
}
}
p { p {
h2 { "Highscore" } h2 { "Highscore" }
ul.iterated { ul.iterated {
@@ -83,7 +96,7 @@ async fn game(
return Err(not_found().await.into_response()); return Err(not_found().await.into_response());
}; };
let Some(camera) = backend.camera_by_uuid(uuid).await else { let Some(camera) = backend.get_camera(&uuid).await else {
return Err(not_found().await.into_response()); return Err(not_found().await.into_response());
}; };

View File

@@ -72,13 +72,7 @@ impl Backend {
async fn client_full(&self, cookies: CookieJar, headers: &HeaderMap) -> (CookieJar, Req) { async fn client_full(&self, cookies: CookieJar, headers: &HeaderMap) -> (CookieJar, Req) {
let (cookies, client) = self.client(cookies).await; let (cookies, client) = self.client(cookies).await;
let lang = language::language(&cookies, headers); let lang = language::language(&cookies, headers);
( (cookies, Req { client, lang })
cookies,
Req {
client,
lang: lang.into(),
},
)
} }
} }

View File

@@ -11,7 +11,7 @@ pub struct Camera {
} }
impl Backend { impl Backend {
pub(crate) async fn camera_by_uuid(&self, uuid: Uuid) -> Option<Camera> { pub(crate) async fn get_camera(&self, uuid: &Uuid) -> Option<Camera> {
let uuid = uuid.to_string(); let uuid = uuid.to_string();
match self { match self {
Backend::Sqlite(db) => sqlx::query_as!( Backend::Sqlite(db) => sqlx::query_as!(

View File

@@ -34,7 +34,6 @@ impl Backend {
}, },
amount: row.amount, amount: row.amount,
}) })
.map(|r| r.into())
.collect() .collect()
} }
} }

View File

@@ -6,24 +6,55 @@ use serde::{Deserialize, Serialize};
use sqlx::{types::chrono::NaiveDateTime, FromRow}; use sqlx::{types::chrono::NaiveDateTime, FromRow};
#[derive(FromRow, Debug, Serialize, Deserialize)] #[derive(FromRow, Debug, Serialize, Deserialize)]
pub struct Sighting { pub struct SightingDb {
pub client_uuid: String, pub client_uuid: String,
pub sighted_at: NaiveDateTime, pub sighted_at: NaiveDateTime,
pub camera_id: String, // Changed from i64 to String to match TEXT/UUID in schema pub camera_id: String,
}
impl SightingDb {
async fn to_sighting(&self, backend: &Backend) -> Sighting {
let client_uuid = uuid::Uuid::parse_str(&self.client_uuid).expect("db constraints");
let camera_uuid = uuid::Uuid::parse_str(&self.camera_id).expect("db constraints");
Sighting {
client: backend.get_client(&client_uuid).await,
sighted_at: self.sighted_at,
camera: backend
.get_camera(&camera_uuid)
.await
.expect("db constraints"),
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Sighting {
pub client: Client,
pub sighted_at: NaiveDateTime,
pub camera: Camera,
} }
impl Backend { impl Backend {
pub(crate) async fn sightings_for_client(&self, client: &Client) -> Vec<Sighting> { pub(crate) async fn sightings_for_client(&self, client: &Client) -> Vec<Sighting> {
let uuid = client.uuid.to_string(); let uuid = client.uuid.to_string();
match self { match self {
Backend::Sqlite(db) => sqlx::query_as!( Backend::Sqlite(db) => {
Sighting, let sighting_dbs = sqlx::query_as!(
"SELECT client_uuid, sighted_at, camera_id FROM sightings WHERE client_uuid = ?", SightingDb,
uuid "SELECT client_uuid, sighted_at, camera_id FROM sightings WHERE client_uuid = ?",
) uuid
.fetch_all(db) )
.await .fetch_all(db)
.unwrap(), .await
.unwrap();
// Convert SightingDb to Sighting
let mut sightings = Vec::new();
for sighting_db in sighting_dbs {
sightings.push(sighting_db.to_sighting(self).await);
}
sightings
}
} }
} }