basic booking information for registered people

This commit is contained in:
Jottyfan 2022-10-08 18:17:54 +02:00
parent 0e9088dc1c
commit 21b2887d94
8 changed files with 497 additions and 6 deletions

View File

@ -18,7 +18,7 @@ apply plugin: 'war'
apply plugin: 'application' apply plugin: 'application'
group = 'de.jottyfan.camporganizer' group = 'de.jottyfan.camporganizer'
version = '0.0.0' version = '0.0.1'
sourceCompatibility = 17 sourceCompatibility = 17
mainClassName = "de.jottyfan.camporganizer.Main" mainClassName = "de.jottyfan.camporganizer.Main"

View File

@ -0,0 +1,352 @@
package de.jottyfan.camporganizer.module.common;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
/**
*
* @author jotty
*
*/
public class BookingBean implements Serializable {
private static final long serialVersionUID = 1L;
private Integer pk;
private String forename;
private String surname;
private String street;
private String zip;
private String city;
private String phone;
private LocalDate birthdate;
private EnumCamprole camprole;
private String comment;
private Boolean consentCatalogPhoto;
private LocalDateTime created;
private String email;
private EnumSex sex;
private String locationName;
private String price;
private Double year;
private LocalDateTime arrive;
private LocalDateTime depart;
private String countries;
private String url;
private Boolean isOver;
private String campName;
/**
* @return the forename
*/
public String getForename() {
return forename;
}
/**
* @param forename the forename to set
*/
public void setForename(String forename) {
this.forename = forename;
}
/**
* @return the surname
*/
public String getSurname() {
return surname;
}
/**
* @param surname the surname to set
*/
public void setSurname(String surname) {
this.surname = surname;
}
/**
* @return the street
*/
public String getStreet() {
return street;
}
/**
* @param street the street to set
*/
public void setStreet(String street) {
this.street = street;
}
/**
* @return the zip
*/
public String getZip() {
return zip;
}
/**
* @param zip the zip to set
*/
public void setZip(String zip) {
this.zip = zip;
}
/**
* @return the city
*/
public String getCity() {
return city;
}
/**
* @param city the city to set
*/
public void setCity(String city) {
this.city = city;
}
/**
* @return the phone
*/
public String getPhone() {
return phone;
}
/**
* @param phone the phone to set
*/
public void setPhone(String phone) {
this.phone = phone;
}
/**
* @return the birthdate
*/
public LocalDate getBirthdate() {
return birthdate;
}
/**
* @param birthdate the birthdate to set
*/
public void setBirthdate(LocalDate birthdate) {
this.birthdate = birthdate;
}
/**
* @return the camprole
*/
public EnumCamprole getCamprole() {
return camprole;
}
/**
* @param camprole the camprole to set
*/
public void setCamprole(EnumCamprole camprole) {
this.camprole = camprole;
}
/**
* @return the comment
*/
public String getComment() {
return comment;
}
/**
* @param comment the comment to set
*/
public void setComment(String comment) {
this.comment = comment;
}
/**
* @return the consentCatalogPhoto
*/
public Boolean getConsentCatalogPhoto() {
return consentCatalogPhoto;
}
/**
* @param consentCatalogPhoto the consentCatalogPhoto to set
*/
public void setConsentCatalogPhoto(Boolean consentCatalogPhoto) {
this.consentCatalogPhoto = consentCatalogPhoto;
}
/**
* @return the created
*/
public LocalDateTime getCreated() {
return created;
}
/**
* @param created the created to set
*/
public void setCreated(LocalDateTime created) {
this.created = created;
}
/**
* @return the email
*/
public String getEmail() {
return email;
}
/**
* @param email the email to set
*/
public void setEmail(String email) {
this.email = email;
}
/**
* @return the sex
*/
public EnumSex getSex() {
return sex;
}
/**
* @param sex the sex to set
*/
public void setSex(EnumSex sex) {
this.sex = sex;
}
/**
* @return the locationName
*/
public String getLocationName() {
return locationName;
}
/**
* @param locationName the location_name to set
*/
public void setLocationName(String locationName) {
this.locationName = locationName;
}
/**
* @return the price
*/
public String getPrice() {
return price;
}
/**
* @param price the price to set
*/
public void setPrice(String price) {
this.price = price;
}
/**
* @return the year
*/
public Double getYear() {
return year;
}
/**
* @param year the year to set
*/
public void setYear(Double year) {
this.year = year;
}
/**
* @return the arrive
*/
public LocalDateTime getArrive() {
return arrive;
}
/**
* @param arrive the arrive to set
*/
public void setArrive(LocalDateTime arrive) {
this.arrive = arrive;
}
/**
* @return the depart
*/
public LocalDateTime getDepart() {
return depart;
}
/**
* @param depart the depart to set
*/
public void setDepart(LocalDateTime depart) {
this.depart = depart;
}
/**
* @return the countries
*/
public String getCountries() {
return countries;
}
/**
* @param countries the countries to set
*/
public void setCountries(String countries) {
this.countries = countries;
}
/**
* @return the url
*/
public String getUrl() {
return url;
}
/**
* @param url the url to set
*/
public void setUrl(String url) {
this.url = url;
}
/**
* @return the is_over
*/
public Boolean getIsOver() {
return isOver;
}
/**
* @param isOver the isOver to set
*/
public void setIsOver(Boolean isOver) {
this.isOver = isOver;
}
public Integer getPk() {
return pk;
}
public void setPk(Integer pk) {
this.pk = pk;
}
public String getCampName() {
return campName;
}
public void setCampName(String campName) {
this.campName = campName;
}
}

View File

@ -18,7 +18,7 @@ public abstract class CommonController {
* @param request the request * @param request the request
* @return the preferred username or null * @return the preferred username or null
*/ */
private String getCurrentUser(HttpServletRequest request) { public String getCurrentUser(HttpServletRequest request) {
KeycloakSecurityContext ksc = (KeycloakSecurityContext) request KeycloakSecurityContext ksc = (KeycloakSecurityContext) request
.getAttribute(KeycloakSecurityContext.class.getName()); .getAttribute(KeycloakSecurityContext.class.getName());
return ksc == null ? null : ksc.getIdToken().getPreferredUsername(); return ksc == null ? null : ksc.getIdToken().getPreferredUsername();

View File

@ -35,6 +35,7 @@ public class IndexController extends CommonController {
@GetMapping("/dashboard") @GetMapping("/dashboard")
public String dashboard(Model model) { public String dashboard(Model model) {
super.setupSession(model, request); super.setupSession(model, request);
model.addAttribute("mybookings", service.getBookingsOf(super.getCurrentUser(request)));
return "/dashboard"; return "/dashboard";
} }

View File

@ -1,18 +1,28 @@
package de.jottyfan.camporganizer.module.common; package de.jottyfan.camporganizer.module.common;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PERSON;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE;
import static de.jottyfan.camporganizer.db.jooq.Tables.V_CAMP; import static de.jottyfan.camporganizer.db.jooq.Tables.V_CAMP;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.jooq.Condition; import org.jooq.Condition;
import org.jooq.DSLContext; import org.jooq.DSLContext;
import org.jooq.Record;
import org.jooq.Record22;
import org.jooq.SelectConditionStep; import org.jooq.SelectConditionStep;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
import de.jottyfan.camporganizer.db.jooq.tables.records.VCampRecord; import de.jottyfan.camporganizer.db.jooq.tables.records.VCampRecord;
/** /**
@ -33,4 +43,67 @@ public class IndexGateway {
LOGGER.debug(sql.toString()); LOGGER.debug(sql.toString());
return sql.fetchStream(); return sql.fetchStream();
} }
public List<BookingBean> getAllBookings(String username) {
SelectConditionStep<Record> sql = jooq
// @formatter:off
.select(T_PERSON.PK,
T_PERSON.FORENAME,
T_PERSON.SURNAME,
T_PERSON.STREET,
T_PERSON.ZIP,
T_PERSON.CITY,
T_PERSON.PHONE,
T_PERSON.BIRTHDATE,
T_PERSON.CAMPROLE,
T_PERSON.COMMENT,
T_PERSON.CONSENT_CATALOG_PHOTO,
T_PERSON.CREATED,
T_PERSON.EMAIL,
T_PERSON.SEX,
V_CAMP.NAME,
V_CAMP.LOCATION_NAME,
V_CAMP.PRICE,
V_CAMP.YEAR,
V_CAMP.ARRIVE,
V_CAMP.DEPART,
V_CAMP.COUNTRIES,
V_CAMP.URL,
V_CAMP.IS_OVER)
.from(T_PROFILE)
.leftJoin(T_PERSON).on(T_PERSON.FK_PROFILE.eq(T_PROFILE.PK))
.leftJoin(V_CAMP).on(V_CAMP.PK.eq(T_PERSON.FK_CAMP))
.where(T_PROFILE.USERNAME.eq(username));
// @formatter:on
LOGGER.debug(sql.toString());
List<BookingBean> list = new ArrayList<>();
for (Record r : sql.fetch()) {
BookingBean bean = new BookingBean();
bean.setPk(r.get(T_PERSON.PK));
bean.setForename(r.get(T_PERSON.FORENAME));
bean.setSurname(r.get(T_PERSON.SURNAME));
bean.setStreet(r.get(T_PERSON.STREET));
bean.setZip(r.get(T_PERSON.ZIP));
bean.setCity(r.get(T_PERSON.CITY));
bean.setPhone(r.get(T_PERSON.PHONE));
bean.setBirthdate(r.get(T_PERSON.BIRTHDATE));
bean.setCamprole(r.get(T_PERSON.CAMPROLE));
bean.setComment(r.get(T_PERSON.COMMENT));
bean.setConsentCatalogPhoto(r.get(T_PERSON.CONSENT_CATALOG_PHOTO));
bean.setCreated(r.get(T_PERSON.CREATED));
bean.setEmail(r.get(T_PERSON.EMAIL));
bean.setSex(r.get(T_PERSON.SEX));
bean.setLocationName(r.get(V_CAMP.LOCATION_NAME));
bean.setPrice(r.get(V_CAMP.PRICE));
bean.setYear(r.get(V_CAMP.YEAR));
bean.setArrive(r.get(V_CAMP.ARRIVE));
bean.setDepart(r.get(V_CAMP.DEPART));
bean.setCountries(r.get(V_CAMP.COUNTRIES));
bean.setUrl(r.get(V_CAMP.URL));
bean.setIsOver(r.get(V_CAMP.IS_OVER));
bean.setCampName(r.get(V_CAMP.NAME));
list.add(bean);
}
return list;
}
} }

View File

@ -1,5 +1,6 @@
package de.jottyfan.camporganizer.module.common; package de.jottyfan.camporganizer.module.common;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE;
import static de.jottyfan.camporganizer.db.jooq.Tables.V_CAMP; import static de.jottyfan.camporganizer.db.jooq.Tables.V_CAMP;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -35,4 +36,8 @@ public class IndexService {
stream.forEach(o -> list.add(o)); stream.forEach(o -> list.add(o));
return list; return list;
} }
public List<BookingBean> getBookingsOf(String username) {
return gateway.getAllBookings(username);
}
} }

View File

@ -130,6 +130,11 @@ body {
cursor: not-allowed; cursor: not-allowed;
} }
.usercard {
width: 480px;
background-color: rgba(255, 255, 255, 0.8) !important;
}
.mytoggle_collapsed { .mytoggle_collapsed {
display: none; display: none;
} }

View File

@ -7,13 +7,68 @@
</head> </head>
<body> <body>
<header> <header>
<a th:href="@{/}" class="btn btn-secondary btn-icon-silent" title="aktualisieren"><i class="fas fa-sync"></i></a> <a th:href="@{/dashboard}" class="btn btn-secondary btn-icon-silent" title="aktualisieren"><i class="fas fa-sync"></i></a> <a th:href="@{/business}" class="btn btn-secondary btn-icon-silent"
<a th:href="@{/business}" class="btn btn-secondary btn-icon-silent" title="Abrechnungen" sec:authorize="hasRole('business')"><i class="far fa-money-bill-alt"></i></a> title="Abrechnungen" sec:authorize="hasRole('business')"><i class="far fa-money-bill-alt"></i></a> <a th:href="@{/confirmation}" class="btn btn-secondary btn-icon-silent"
<a th:href="@{/confirmation}" class="btn btn-secondary btn-icon-silent" title="Anmeldungen" sec:authorize="hasRole('registrator')"><i class="fas fa-user-check"></i></a> title="Anmeldungen" sec:authorize="hasRole('registrator')"><i class="fas fa-user-check"></i></a> <a href="https://www.onkelwernerfreizeiten.de/nextcloud"
<a href="https://www.onkelwernerfreizeiten.de/nextcloud" class="btn btn-secondary btn-icon-silent" title="Nextcloud" target="_blank"><img th:src="@{images/nextcloud.png}" width="20px"/></a> class="btn btn-secondary btn-icon-silent" title="Nextcloud" target="_blank"><img th:src="@{images/nextcloud.png}" width="20px" /></a>
</header> </header>
<content> <content>
<div class="mainpage"> <div class="mainpage">
<div class="card usercard" th:each="b : ${mybookings}">
<div class="card-header">
<span th:text="${b.campName + ' ' + #numbers.formatInteger(b.year, 4)}" style="font-weight: bolder"></span>&nbsp;in&nbsp;<a th:href="${b.url}" target="_blank" th:text="${b.locationName}"></a>
<div class="container">
<div class="row">
<div class="col-sm-4">Zeit:</div>
<div class="col-sm-8">
<span th:text="${#temporals.format(b.arrive, 'dd.MM.') + ' - ' + #temporals.format(b.depart, 'dd.MM.yyyy')}" th:if="${b.arrive != null and b.depart != null}"></span>
</div>
<div class="col-sm-4">Preis:</div>
<div class="col-sm-8" th:text="${b.price}"></div>
<div class="col-sm-4">Ferien:</div>
<div class="col-sm-8" th:text="${b.countries}"></div>
</div>
</div>
</div>
<div class="card-body">
<div class="container">
<div class="row">
<div class="col-sm-4">Rolle:</div>
<span class="col-sm-8" th:text="${b.camprole}"></span>
<div class="col-sm-4">ID:</div>
<span class="col-sm-8" th:text="${b.pk}"></span>
<div class="col-sm-4">Vorname:</div>
<span class="col-sm-8" th:text="${b.forename}"></span>
<div class="col-sm-4">Nachname:</div>
<span class="col-sm-8" th:text="${b.surname}"></span>
<div class="col-sm-4">Straße:</div>
<span class="col-sm-8" th:text="${b.street}"></span>
<div class="col-sm-4">PLZ:</div>
<span class="col-sm-8" th:text="${b.zip}"></span>
<div class="col-sm-4">Ort:</div>
<span class="col-sm-8" th:text="${b.city}"></span>
<div class="col-sm-4">Telefon:</div>
<span class="col-sm-8" th:text="${b.phone}"></span>
<div class="col-sm-4">Geburtstag:</div>
<span class="col-sm-8" th:text="${#temporals.format(b.birthdate, 'dd.MM.yyyy')}"></span>
<div class="col-sm-4">E-Mail:</div>
<span class="col-sm-8" th:text="${b.email}"></span>
<div class="col-sm-4">Geschlecht:</div>
<span class="col-sm-8" th:text="${b.sex}"></span>
<div class="col-sm-4">Foto-Einverständnis:</div>
<span class="col-sm-8" th:text="${b.consentCatalogPhoto}"></span>
<div class="col-sm-4">Kommentar:</div>
<span class="col-sm-8" th:text="${b.comment}"></span>
</div>
</div>
</div>
<div class="card-footer">
<div>
angemeldet am <span th:text="${#temporals.format(b.created, 'dd.MM.yyyy')}" th:if="${b.created != null}"></span>
</div>
<span th:if="${b.isOver}">Die Freizeit ist bereits vorbei.</span>
</div>
</div>
</div> </div>
</content> </content>
</body> </body>