feat: differentiate area in overview

This commit is contained in:
Max Hohlfeld 2024-06-29 13:51:33 +02:00
parent 7d47b38037
commit 43169b585a
7 changed files with 96 additions and 70 deletions

View File

@ -1,4 +1,5 @@
use actix_web::{web, Responder};
use crate::filters;
use actix_web::{web, HttpResponse, Responder};
use askama::Template;
use askama_actix::TemplateToResponse;
use chrono::{NaiveDate, Utc};
@ -10,6 +11,7 @@ use crate::models::{Area, Availabillity, Event, Function, Role, User};
#[derive(Deserialize)]
pub struct CalendarQuery {
date: Option<NaiveDate>,
area: Option<i32>,
}
#[derive(Template)]
@ -17,6 +19,7 @@ pub struct CalendarQuery {
struct CalendarTemplate {
user: User,
date: NaiveDate,
selected_area: Option<i32>,
areas: Vec<Area>,
events: Vec<Event>,
availabillities: Vec<Availabillity>,
@ -32,19 +35,40 @@ async fn get(
Some(given_date) => given_date,
None => Utc::now().date_naive(),
};
let areas = Area::read_all(pool.get_ref()).await.unwrap();
let events = Event::read_by_date_including_location(pool.get_ref(), date)
let selected_area = match query.area {
Some(id) => {
if !areas.iter().any(|a| a.id == id) {
return HttpResponse::BadRequest().finish();
}
Some(id)
}
None => None,
};
let events = Event::read_by_date_and_area_including_location(
pool.get_ref(),
date,
query.area.unwrap_or(user.area_id),
)
.await
.unwrap();
let availabillities = Availabillity::read_by_date_including_user(pool.get_ref(), date)
let availabillities = Availabillity::read_by_date_and_area_including_user(
pool.get_ref(),
date,
query.area.unwrap_or(user.area_id),
)
.await
.unwrap();
let template = CalendarTemplate {
user: user.into_inner(),
date,
selected_area,
areas,
events,
availabillities,

View File

@ -1,4 +1,3 @@
use actix_identity::Identity;
use actix_web::{web, HttpResponse, Responder};
use serde::Deserialize;
use serde_json::value::Value;

7
src/filters.rs Normal file
View File

@ -0,0 +1,7 @@
pub fn show_area_query(a: &Option<i32>) -> ::askama::Result<String> {
if let Some(a) = a {
return Ok(format!("&area={}", a));
} else {
return Ok(String::new());
}
}

View File

@ -19,8 +19,10 @@ mod endpoints;
mod models;
mod middleware;
mod filters;
mod postgres_session_store;
pub enum Command {
Migrate,
CreateAdmin,

View File

@ -33,33 +33,10 @@ impl Availabillity {
Ok(result)
}
pub async fn read_by_date(
pool: &PgPool,
date: NaiveDate,
) -> anyhow::Result<Vec<Availabillity>> {
let records = query!("SELECT * FROM availabillity WHERE date = $1", date)
.fetch_all(pool)
.await?;
let availabillities = records
.iter()
.map(|a| Availabillity {
id: a.id,
user_id: a.userid,
user: None,
date: a.date,
start_time: a.starttime,
end_time: a.endtime,
comment: a.comment.clone(),
})
.collect();
Ok(availabillities)
}
pub async fn read_by_date_including_user(
pub async fn read_by_date_and_area_including_user(
pool: &PgPool,
date: NaiveDate,
area_id: i32
) -> anyhow::Result<Vec<Availabillity>> {
let records = query!(
r##"
@ -82,9 +59,11 @@ impl Availabillity {
user_.receiveNotifications
FROM availabillity
JOIN user_ ON availabillity.userId = user_.id
WHERE availabillity.date = $1;
WHERE availabillity.date = $1
AND user_.areaId = $2;
"##,
date
date,
area_id
)
.fetch_all(pool)
.await?;

View File

@ -34,34 +34,10 @@ impl Event {
Ok(result.id)
}
pub async fn read_by_date(pool: &PgPool, date: NaiveDate) -> anyhow::Result<Vec<Event>> {
let records = query!("SELECT * FROM event WHERE date = $1;", date)
.fetch_all(pool)
.await?;
let events = records
.iter()
.map(|record| Event {
id: record.id,
date: record.date,
start_time: record.starttime,
end_time: record.endtime,
name: record.name.to_string(),
location_id: record.locationid,
location: None,
voluntary_wachhabender: record.voluntarywachhabender,
amount_of_posten: record.amountofposten,
clothing: record.clothing.to_string(),
canceled: record.canceled,
})
.collect();
Ok(events)
}
pub async fn read_by_date_including_location(
pub async fn read_by_date_and_area_including_location(
pool: &PgPool,
date: NaiveDate,
area_id: i32
) -> anyhow::Result<Vec<Event>> {
let records = query!(
r#"
@ -81,9 +57,11 @@ impl Event {
location.areaId AS locationAreaId
FROM event
JOIN location ON event.locationId = location.id
WHERE date = $1;
WHERE date = $1
AND location.areaId = $2;
"#,
date
date,
area_id
)
.fetch_all(pool)
.await?;

View File

@ -5,14 +5,45 @@
<div class="container">
<div class="level">
<div class="level-left">
<a hx-boost="true" class="button is-link level-item" href="/?date={{ date.pred() }}">&larr;</a>
<a hx-boost="true" class="button is-link level-item"
href="/?date={{ date.pred() }}{{ selected_area|show_area_query }}">
<span class="icon">
<svg class="feather">
<use href="/static/feather-sprite.svg#arrow-left" />
</svg>
</span>
</a>
</div>
<div class="control level-item is-flex-grow-0">
<input id="date-selector" class="input" type="date" value="{{ date }}">
{% if user.role == Role::Admin %}
<div class="select ml-2">
<select hx-get="/?date={{ date }}" hx-target="closest body" hx-push-url="true" name="area">
{% for area in areas %}
{% if (user.area_id == area.id && selected_area.is_none()) || selected_area.is_some() &&
selected_area.unwrap() == area.id %}
<option selected value="{{ area.id }}">{{ area.name }}</option>
{% else %}
<option value="{{ area.id }}">{{ area.name }}</option>
{% endif %}
{% endfor %}
</select>
</div>
{% endif %}
</div>
<div class="level-right">
<a hx-boost="true" class="button is-link level-item" href="/?date={{ date.succ() }}">&rarr;</a>
<a hx-boost="true" class="button is-link level-item"
href="/?date={{ date.succ() }}{{ selected_area|show_area_query }}">
<span class="icon">
<svg class="feather">
<use href="/static/feather-sprite.svg#arrow-right" />
</svg>
</span>
</a>
</div>
</div>
</div>
</section>
@ -25,14 +56,17 @@
Events am {{ date.format("%d.%m.%Y") }}
</h3>
</div>
{% if (user.role == Role::Admin || user.role == Role::AreaManager) && (selected_area.is_none() ||
selected_area.unwrap() == user.area_id) %}
<div class="level-right">
<a class="button" href="/events/new?date={{ date }}">Neues Event für diesen Tag</a>
</div>
{% endif %}
</div>
{% if events.len() == 0 %}
<div class="box">
<h5 class="title is-5">keine Events geplant</h5>
<h5 class="subtitle is-5">keine Events geplant</h5>
</div>
{% else %}
{% for event in events %}
@ -67,14 +101,17 @@
Verfügbarkeiten am {{ date.format("%d.%m.%Y") }}
</h3>
</div>
{% if (user.role == Role::Admin || user.role == Role::AreaManager) && selected_area.is_some() &&
selected_area.unwrap() == user.area_id %}
<div class="level-right">
<a class="button" href="/availabillity/new?date={{ date }}">Neue Verfügbarkeit für diesen Tag</a>
</div>
{% endif %}
</div>
{% if availabillities.len() == 0 %}
<div class="box">
<h5 class="title is-5">keine Verfügbarkeiten eingetragen</h5>
<h5 class="subtitle is-5">keine Verfügbarkeiten eingetragen</h5>
</div>
{% else %}
<div class="box">