diff --git a/Backend/endpoints/time.go b/Backend/endpoints/time.go
index 0be3f67..b92d3b5 100644
--- a/Backend/endpoints/time.go
+++ b/Backend/endpoints/time.go
@@ -5,6 +5,7 @@ import (
"arbeitszeitmessung/models"
"arbeitszeitmessung/templates"
"context"
+ "database/sql"
"encoding/json"
"log"
"net/http"
@@ -30,6 +31,22 @@ func TimeHandler(w http.ResponseWriter, r *http.Request) {
}
}
+func AbsencHandler(w http.ResponseWriter, r *http.Request) {
+ helper.RequiresLogin(Session, w, r)
+ helper.SetCors(w)
+ switch r.Method {
+ case http.MethodPost:
+ err := updateAbsence(r)
+ if err != nil {
+ http.Error(w, "Internal error", http.StatusInternalServerError)
+ return
+ }
+ http.Redirect(w, r, "/time", 301)
+ default:
+ http.Error(w, "Method not allowed!", http.StatusMethodNotAllowed)
+ }
+}
+
func parseTimestamp(r *http.Request, getKey string, fallback string) (time.Time, error) {
getTimestamp := r.URL.Query().Get(getKey)
if getTimestamp == "" {
@@ -165,6 +182,84 @@ func updateBooking(w http.ResponseWriter, r *http.Request) {
getBookings(w, r)
}
+func updateAbsence(r *http.Request) error {
+ r.ParseForm()
+ var loc *time.Location
+ loc, err := time.LoadLocation(helper.GetEnv("TZ", "Europe/Berlin"))
+ if err != nil {
+ log.Println("Error loading location", err)
+ loc = time.Local
+ }
+
+ dateFrom, err := time.ParseInLocation("2006-01-02", r.FormValue("date_from"), loc)
+ if err != nil {
+ log.Println("Error parsing date_from input for absence", err)
+ return err
+ }
+
+ dateTo, err := time.ParseInLocation("2006-01-02", r.FormValue("date_to"), loc)
+ if err != nil {
+ log.Println("Error parsing date_to input for absence", err)
+ return err
+ }
+
+ absenceTypeId, err := strconv.Atoi(r.FormValue("aw_type"))
+ if err != nil {
+ log.Println("Error parsing aw_type", err)
+ return err
+ }
+
+ absenceId, err := strconv.Atoi(r.FormValue("aw_id"))
+ if err != nil && r.FormValue("aw_id") == "" {
+ absenceId = 0
+ } else if err != nil {
+ log.Println("Error parsing aw_id", err)
+ return err
+ }
+
+ absenceType, err := models.GetAbsenceTypeById(int8(absenceTypeId))
+ if err != nil {
+ log.Println("No matching absence type found!")
+ return err
+ }
+
+ newAbsence := models.Absence{DateFrom: dateFrom, DateTo: dateTo, AbwesenheitTyp: absenceType}
+
+ absence, err := models.GetAbsenceById(absenceId)
+ if err == sql.ErrNoRows {
+ err = nil
+ log.Println("Absence not found creating new!")
+
+ user, err := models.GetUserFromSession(Session, r.Context())
+ if err != nil {
+ log.Println("No user found!", err)
+ return err
+ }
+ newAbsence.CardUID = user.CardUID
+ newAbsence.Insert()
+ }
+ if err != nil {
+ log.Println("Cannot get Absence for id: ", absenceId, err)
+ return err
+ }
+ if r.FormValue("action") == "delete" {
+ log.Println("Deleting Absence!", "Not implemented")
+ // TODO
+ //absence.Delete()
+ return nil
+ }
+
+ if absence.Update(newAbsence) {
+ err = absence.Save()
+ if err != nil {
+ log.Println("Error saving updated absence!", err)
+ return err
+ }
+ }
+ return nil
+
+}
+
func createAbsence(absenceType int, user models.User, loc *time.Location, r *http.Request) {
absenceDate, err := time.ParseInLocation("2006-01-02", r.FormValue("date"), loc)
if err != nil {
diff --git a/Backend/main.go b/Backend/main.go
index 98a5e22..35395e2 100644
--- a/Backend/main.go
+++ b/Backend/main.go
@@ -43,6 +43,7 @@ func main() {
// handles the different http routes
server.HandleFunc("/time/new", endpoints.TimeCreateHandler)
+ server.Handle("/absence", ParamsMiddleware(endpoints.AbsencHandler))
server.Handle("/time", ParamsMiddleware(endpoints.TimeHandler))
server.HandleFunc("/logout", endpoints.LogoutHandler)
server.HandleFunc("/user/{action}", endpoints.UserHandler)
diff --git a/Backend/models/absence.go b/Backend/models/absence.go
index b0fb959..7d9e913 100644
--- a/Backend/models/absence.go
+++ b/Backend/models/absence.go
@@ -109,6 +109,23 @@ func (a *Absence) Insert() error {
return nil
}
+func (a *Absence) Save() error {
+ qStr, err := DB.Prepare(`
+ UPDATE abwesenheit SET card_uid = $2, abwesenheit_typ = $3, datum_from = $4, datum_to = $5 WHERE counter_id = $1;
+ `)
+ if err != nil {
+ log.Println("Error preparing sql Statement (Absence Save)", err)
+ return err
+ }
+ defer qStr.Close()
+ _, err = qStr.Query(a.CounterId, a.CardUID, a.AbwesenheitTyp.Id, a.DateFrom, a.DateTo)
+ if err != nil {
+ log.Println("Error executing update statement", err)
+ return err
+ }
+ return nil
+}
+
func GetAbsenceById(counterId int) (Absence, error) {
var absence Absence = Absence{CounterId: counterId}
qStr, err := DB.Prepare("SELECT card_uid, abwesenheit_typ, datum_from, datum_to FROM abwesenheit WHERE counter_id = $1;")
@@ -179,6 +196,27 @@ func GetAbsencesByCardUID(card_uid string, tsFrom time.Time, tsTo time.Time) ([]
return absences, nil
}
+func (a *Absence) Update(na Absence) bool {
+ change := false
+ if a.CardUID != na.CardUID && na.CardUID != "" {
+ a.CardUID = na.CardUID
+ change = true
+ }
+ if a.AbwesenheitTyp != na.AbwesenheitTyp && na.AbwesenheitTyp.Id != 0 {
+ a.AbwesenheitTyp = na.AbwesenheitTyp
+ change = true
+ }
+ if !a.DateFrom.Equal(na.DateFrom) && !na.DateFrom.IsZero() {
+ a.DateFrom = na.DateFrom
+ change = true
+ }
+ if !a.DateTo.Equal(na.DateTo) && !na.DateTo.IsZero() {
+ a.DateTo = na.DateTo
+ change = true
+ }
+ return change
+}
+
func GetAbsenceTypes() (map[int8]AbsenceType, error) {
var types = make(map[int8]AbsenceType)
qStr, err := DB.Prepare("SELECT abwesenheit_id, abwesenheit_name, arbeitszeit_equivalent FROM s_abwesenheit_typen;")
diff --git a/Backend/models/workDay.go b/Backend/models/workDay.go
index 51025b9..5a99af4 100644
--- a/Backend/models/workDay.go
+++ b/Backend/models/workDay.go
@@ -24,15 +24,16 @@ type IWorkDay interface {
}
type WorkDay struct {
- Day time.Time `json:"day"`
- Bookings []Booking `json:"bookings"`
- workTime time.Duration
- pauseTime time.Duration
- realWorkTime time.Duration
- realPauseTime time.Duration
- TimeFrom time.Time
- TimeTo time.Time
- kurzArbeit bool
+ Day time.Time `json:"day"`
+ Bookings []Booking `json:"bookings"`
+ workTime time.Duration
+ pauseTime time.Duration
+ realWorkTime time.Duration
+ realPauseTime time.Duration
+ TimeFrom time.Time
+ TimeTo time.Time
+ kurzArbeit bool
+ kurzArbeitAbsence Absence
}
func GetDays(user User, tsFrom, tsTo time.Time, orderedForward bool) []IWorkDay {
@@ -53,6 +54,7 @@ func GetDays(user User, tsFrom, tsTo time.Time, orderedForward bool) []IWorkDay
if day.AbwesenheitTyp.WorkTime == 1 {
if workDay, ok := allDays[day.Date().Format("2006-01-02")].(*WorkDay); ok {
workDay.kurzArbeit = true
+ workDay.kurzArbeitAbsence = day
}
} else {
allDays[day.Date().Format("2006-01-02")] = &day
@@ -85,6 +87,10 @@ func (d *WorkDay) TimeWorkVirtual(u User) time.Duration {
return d.workTime
}
+func (d *WorkDay) GetKurzArbeit() Absence {
+ return d.kurzArbeitAbsence
+}
+
func (d *WorkDay) TimeWorkReal(u User) time.Duration {
d.realWorkTime, d.realPauseTime = 0, 0
var lastBooking Booking
diff --git a/Backend/src/main.css b/Backend/src/main.css
index 85ae31e..9afdfb3 100644
--- a/Backend/src/main.css
+++ b/Backend/src/main.css
@@ -1,120 +1,127 @@
@import "tailwindcss";
@source "../templates/*.templ";
@plugin "@iconify/tailwind4" {
- scale: 1.25;
+ scale: 1.25;
}
@theme {
- --color-accent-50: #e7fdea;
- --color-accent-100: #cbfbd1;
- --color-accent-200: #9cf7a8;
- --color-accent-300: #68f37a;
- --color-accent-400: #33ef4d;
- --color-accent-500: #11db2d;
- --color-accent-600: #0eaf23;
- --color-accent-700: #0a851b;
- --color-accent-800: #075a12;
- --color-accent-900: #032b09;
- --color-accent-950: #021805;
- --color-accent: #0eaf23;
- --color-text-50: #f7f8f7;
- --color-text-100: #f2f3f2;
- --color-text-200: #e2e4e2;
- --color-text-300: #d2d6d2;
- --color-text-400: #c2c7c2;
- --color-text-500: #afb6af;
- --color-text-600: #97a097;
- --color-text-700: #7d877d;
- --color-text-800: #5a625a;
- --color-text-900: #161816;
- --color-text-950: #000000;
+ --color-accent-50: #e7fdea;
+ --color-accent-100: #cbfbd1;
+ --color-accent-200: #9cf7a8;
+ --color-accent-300: #68f37a;
+ --color-accent-400: #33ef4d;
+ --color-accent-500: #11db2d;
+ --color-accent-600: #0eaf23;
+ --color-accent-700: #0a851b;
+ --color-accent-800: #075a12;
+ --color-accent-900: #032b09;
+ --color-accent-950: #021805;
+ --color-accent: #0eaf23;
+ --color-text-50: #f7f8f7;
+ --color-text-100: #f2f3f2;
+ --color-text-200: #e2e4e2;
+ --color-text-300: #d2d6d2;
+ --color-text-400: #c2c7c2;
+ --color-text-500: #afb6af;
+ --color-text-600: #97a097;
+ --color-text-700: #7d877d;
+ --color-text-800: #5a625a;
+ --color-text-900: #161816;
+ --color-text-950: #000000;
}
@layer base {
- body {
- -webkit-print-color-adjust: exact !important;
- print-color-adjust: exact !important;
- }
+ body {
+ -webkit-print-color-adjust: exact !important;
+ print-color-adjust: exact !important;
+ background-color: white;
+ }
}
@layer components {
- .grid-main {
- display: grid;
- grid-template-columns: 2fr auto 1fr;
- align-items: stretch;
- }
-
- .grid-sub {
- display: grid;
- grid-template-columns: subgrid;
- grid-column: 1 / -1;
- border-color: var(--color-neutral-400);
- transition: background-color 0.2s ease-in-out;
- }
-
- .grid-sub.responsive {
- display: flex;
- flex-direction: column;
- }
-
- .grid-sub:hover {
- background-color: var(--color-neutral-200);
- }
-
- .grid-cell {
- padding: calc(var(--spacing) * 2);
- border-color: var(--color-neutral-400);
- }
-
- .btn {
- width: 100%;
- cursor: pointer;
- border-radius: var(--radius-md);
- color: var(--color-neutral-800);
- font-size: var(--text-sm);
- text-align: center;
- padding: calc(var(--spacing) * 2);
- border-style: var(--tw-border-style);
- border-width: 1px;
- border-color: var(--color-neutral-800);
- transition-property:
- color, background-color, border-color, outline-color,
- text-decoration-color, fill, stroke, --tw-gradient-from,
- --tw-gradient-via, --tw-gradient-to;
- transition-timing-function: var(
- --tw-ease,
- var(--default-transition-timing-function)
- );
- transition-duration: var(--tw-duration, var(--default-transition-duration));
- }
-
- .btn:hover {
- color: var(--color-white);
- background-color: var(--color-neutral-700);
- }
-
- .btn:disabled {
- opacity: 50%;
- pointer-events: none;
- }
-
- .btn:active,
- .btn:focus {
- background-color: var(--color-neutral-700);
- }
-
- @media (width >=48rem) {
.grid-main {
- grid-template-columns: repeat(5, 1fr);
- margin: 0 10%;
+ display: grid;
+ grid-template-columns: 4fr 6fr 1fr;
+ align-items: stretch;
+ }
+
+ .grid-sub {
+ display: grid;
+ grid-template-columns: subgrid;
+ grid-column: 1 / -1;
+ border-color: var(--color-neutral-400);
+ transition: background-color 0.2s ease-in-out;
}
.grid-sub.responsive {
- display: grid;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .grid-sub:hover {
+ background-color: var(--color-neutral-200);
+ }
+
+ .grid-cell {
+ padding: calc(var(--spacing) * 2);
+ border-color: var(--color-neutral-400);
}
.btn {
- padding-inline: calc(var(--spacing) * 4);
+ width: 100%;
+ cursor: pointer;
+ border-radius: var(--radius-md);
+ color: var(--color-neutral-800);
+ font-size: var(--text-sm);
+ text-align: center;
+ padding: calc(var(--spacing) * 2);
+ border-style: var(--tw-border-style);
+ border-width: 1px;
+ border-color: var(--color-neutral-800);
+ transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;
+ transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
+ transition-duration: var(--tw-duration, var(--default-transition-duration));
+ }
+
+ input.btn,
+ select.btn {
+ transition-duration: 300ms;
+ }
+
+ .btn:hover {
+ color: var(--color-white);
+ background-color: var(--color-neutral-700);
+ }
+
+ .btn:disabled {
+ opacity: 50%;
+ pointer-events: none;
+ }
+
+ input.btn,
+ select.btn {
+ text-align: left;
+ }
+
+ input.btn:hover,
+ select.btn:hover {
+ border-color: var(--color-neutral-300);
+ background-color: var(--color-neutral-100);
+ color: var(--color-neutral-800);
+ }
+
+ @media (width >=48rem) {
+ .grid-main {
+ grid-template-columns: repeat(5, 1fr);
+ margin: 0 10%;
+ }
+
+ .grid-sub.responsive {
+ display: grid;
+ }
+
+ .btn {
+ padding-inline: calc(var(--spacing) * 4);
+ }
}
- }
}
diff --git a/Backend/static/css/styles.css b/Backend/static/css/styles.css
index 143d6f3..1e919bf 100644
--- a/Backend/static/css/styles.css
+++ b/Backend/static/css/styles.css
@@ -9,8 +9,10 @@
"Courier New", monospace;
--color-red-500: oklch(63.7% 0.237 25.331);
--color-red-600: oklch(57.7% 0.245 27.325);
+ --color-red-700: oklch(50.5% 0.213 27.518);
--color-orange-500: oklch(70.5% 0.213 47.604);
--color-purple-600: oklch(55.8% 0.288 302.321);
+ --color-slate-700: oklch(37.2% 0.044 257.287);
--color-neutral-100: oklch(97% 0 0);
--color-neutral-200: oklch(92.2% 0 0);
--color-neutral-300: oklch(87% 0 0);
@@ -190,9 +192,24 @@
.\@container {
container-type: inline-size;
}
+ .absolute {
+ position: absolute;
+ }
.relative {
position: relative;
}
+ .top-2 {
+ top: calc(var(--spacing) * 2);
+ }
+ .top-2\.5 {
+ top: calc(var(--spacing) * 2.5);
+ }
+ .right-2 {
+ right: calc(var(--spacing) * 2);
+ }
+ .right-2\.5 {
+ right: calc(var(--spacing) * 2.5);
+ }
.col-span-2 {
grid-column: span 2 / span 2;
}
@@ -211,9 +228,15 @@
.mt-1 {
margin-top: calc(var(--spacing) * 1);
}
+ .mb-1 {
+ margin-bottom: calc(var(--spacing) * 1);
+ }
.mb-2 {
margin-bottom: calc(var(--spacing) * 2);
}
+ .ml-1 {
+ margin-left: calc(var(--spacing) * 1);
+ }
.icon-\[material-symbols-light--add-circle-outline\] {
display: inline-block;
width: 1.25em;
@@ -253,6 +276,19 @@
mask-size: 100% 100%;
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='black' d='M12.003 21q-1.866 0-3.51-.708q-1.643-.709-2.859-1.924t-1.925-2.856T3 12.003t.709-3.51Q4.417 6.85 5.63 5.634t2.857-1.925T11.997 3t3.51.709q1.643.708 2.859 1.922t1.925 2.857t.709 3.509t-.708 3.51t-1.924 2.859t-2.856 1.925t-3.509.709M12 20q3.35 0 5.675-2.325T20 12t-2.325-5.675T12 4T6.325 6.325T4 12t2.325 5.675T12 20m0-8'/%3E%3C/svg%3E");
}
+ .icon-\[material-symbols-light--delete-outline\] {
+ display: inline-block;
+ width: 1.25em;
+ height: 1.25em;
+ background-color: currentColor;
+ -webkit-mask-image: var(--svg);
+ mask-image: var(--svg);
+ -webkit-mask-repeat: no-repeat;
+ mask-repeat: no-repeat;
+ -webkit-mask-size: 100% 100%;
+ mask-size: 100% 100%;
+ --svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='black' d='M7.616 20q-.672 0-1.144-.472T6 18.385V6H5V5h4v-.77h6V5h4v1h-1v12.385q0 .69-.462 1.153T16.384 20zM17 6H7v12.385q0 .269.173.442t.443.173h8.769q.23 0 .423-.192t.192-.424zM9.808 17h1V8h-1zm3.384 0h1V8h-1zM7 6v13z'/%3E%3C/svg%3E");
+ }
.icon-\[material-symbols-light--more-time\] {
display: inline-block;
width: 1.25em;
@@ -292,6 +328,22 @@
mask-size: 100% 100%;
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='black' d='M14.935 16.223L11.5 12.789V7.923h1v4.464l3.123 3.123zM11.5 6V4h1v2zm6.5 6.5v-1h2v1zM11.5 20v-2h1v2zM4 12.5v-1h2v1zm8.003 8.5q-1.867 0-3.51-.708q-1.643-.709-2.859-1.924t-1.925-2.856T3 12.003t.709-3.51Q4.417 6.85 5.63 5.634t2.857-1.925T11.997 3t3.51.709q1.643.708 2.859 1.922t1.925 2.857t.709 3.509t-.708 3.51t-1.924 2.859t-2.856 1.925t-3.509.709M12 20q3.35 0 5.675-2.325T20 12t-2.325-5.675T12 4T6.325 6.325T4 12t2.325 5.675T12 20m0-8'/%3E%3C/svg%3E");
}
+ .icon-\[material-symbols-light--schedule-outline\] {
+ display: inline-block;
+ width: 1.25em;
+ height: 1.25em;
+ background-color: currentColor;
+ -webkit-mask-image: var(--svg);
+ mask-image: var(--svg);
+ -webkit-mask-repeat: no-repeat;
+ mask-repeat: no-repeat;
+ -webkit-mask-size: 100% 100%;
+ mask-size: 100% 100%;
+ --svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='black' d='m15.646 16.354l.708-.708l-3.854-3.854V7h-1v5.208zM12.003 21q-1.866 0-3.51-.708q-1.643-.709-2.859-1.924t-1.925-2.856T3 12.003t.709-3.51Q4.417 6.85 5.63 5.634t2.857-1.925T11.997 3t3.51.709q1.643.708 2.859 1.922t1.925 2.857t.709 3.509t-.708 3.51t-1.924 2.859t-2.856 1.925t-3.509.709M12 20q3.325 0 5.663-2.337T20 12t-2.337-5.663T12 4T6.337 6.338T4 12t2.338 5.663T12 20'/%3E%3C/svg%3E");
+ }
+ .block {
+ display: block;
+ }
.flex {
display: flex;
}
@@ -315,12 +367,27 @@
width: calc(var(--spacing) * 4);
height: calc(var(--spacing) * 4);
}
+ .size-5 {
+ width: calc(var(--spacing) * 5);
+ height: calc(var(--spacing) * 5);
+ }
+ .size-6 {
+ width: calc(var(--spacing) * 6);
+ height: calc(var(--spacing) * 6);
+ }
+ .size-7 {
+ width: calc(var(--spacing) * 7);
+ height: calc(var(--spacing) * 7);
+ }
.h-2 {
height: calc(var(--spacing) * 2);
}
.h-4 {
height: calc(var(--spacing) * 4);
}
+ .h-5 {
+ height: calc(var(--spacing) * 5);
+ }
.h-8 {
height: calc(var(--spacing) * 8);
}
@@ -336,6 +403,12 @@
.w-4 {
width: calc(var(--spacing) * 4);
}
+ .w-5 {
+ width: calc(var(--spacing) * 5);
+ }
+ .w-9 {
+ width: calc(var(--spacing) * 9);
+ }
.w-9\/10 {
width: calc(9/10 * 100%);
}
@@ -348,9 +421,15 @@
.w-full {
width: 100%;
}
+ .flex-shrink {
+ flex-shrink: 1;
+ }
.flex-shrink-0 {
flex-shrink: 0;
}
+ .shrink {
+ flex-shrink: 1;
+ }
.flex-grow {
flex-grow: 1;
}
@@ -360,9 +439,27 @@
.grow-1 {
flex-grow: 1;
}
+ .basis-\[content\] {
+ flex-basis: content;
+ }
+ .basis-auto {
+ flex-basis: auto;
+ }
+ .border-collapse {
+ border-collapse: collapse;
+ }
.cursor-pointer {
cursor: pointer;
}
+ .resize {
+ resize: both;
+ }
+ .scroll-m-2 {
+ scroll-margin: calc(var(--spacing) * 2);
+ }
+ .appearance-none {
+ appearance: none;
+ }
.break-after-page {
break-after: page;
}
@@ -399,6 +496,9 @@
.items-center {
align-items: center;
}
+ .items-end {
+ align-items: flex-end;
+ }
.justify-around {
justify-content: space-around;
}
@@ -459,6 +559,10 @@
border-right-style: var(--tw-border-style);
border-right-width: 0px;
}
+ .border-r-1 {
+ border-right-style: var(--tw-border-style);
+ border-right-width: 1px;
+ }
.border-b-0 {
border-bottom-style: var(--tw-border-style);
border-bottom-width: 0px;
@@ -496,6 +600,9 @@
.bg-red-600 {
background-color: var(--color-red-600);
}
+ .mask-repeat {
+ mask-repeat: repeat;
+ }
.p-1 {
padding: calc(var(--spacing) * 1);
}
@@ -557,9 +664,19 @@
.text-red-600 {
color: var(--color-red-600);
}
+ .text-slate-700 {
+ color: var(--color-slate-700);
+ }
.uppercase {
text-transform: uppercase;
}
+ .underline {
+ text-decoration-line: underline;
+ }
+ .outline {
+ outline-style: var(--tw-outline-style);
+ outline-width: 1px;
+ }
.filter {
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
}
@@ -656,10 +773,17 @@
}
}
}
- .hover\:bg-red-600 {
+ .hover\:bg-red-500 {
&:hover {
@media (hover: hover) {
- background-color: var(--color-red-600);
+ background-color: var(--color-red-500);
+ }
+ }
+ }
+ .hover\:bg-red-700 {
+ &:hover {
+ @media (hover: hover) {
+ background-color: var(--color-red-700);
}
}
}
@@ -708,11 +832,6 @@
opacity: 50%;
}
}
- .max-md\:flex {
- @media (width < 48rem) {
- display: flex;
- }
- }
.max-md\:grid {
@media (width < 48rem) {
display: grid;
@@ -723,11 +842,6 @@
display: none;
}
}
- .max-md\:flex-col {
- @media (width < 48rem) {
- flex-direction: column;
- }
- }
.max-md\:divide-y-1 {
@media (width < 48rem) {
:where(& > :not(:last-child)) {
@@ -853,12 +967,13 @@
body {
-webkit-print-color-adjust: exact !important;
print-color-adjust: exact !important;
+ background-color: white;
}
}
@layer components {
.grid-main {
display: grid;
- grid-template-columns: 2fr auto 1fr;
+ grid-template-columns: 4fr 6fr 1fr;
align-items: stretch;
}
.grid-sub {
@@ -891,9 +1006,12 @@
border-width: 1px;
border-color: var(--color-neutral-800);
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;
- transition-timing-function: var( --tw-ease, var(--default-transition-timing-function) );
+ transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
transition-duration: var(--tw-duration, var(--default-transition-duration));
}
+ input.btn, select.btn {
+ transition-duration: 300ms;
+ }
.btn:hover {
color: var(--color-white);
background-color: var(--color-neutral-700);
@@ -902,8 +1020,13 @@
opacity: 50%;
pointer-events: none;
}
- .btn:active, .btn:focus {
- background-color: var(--color-neutral-700);
+ input.btn, select.btn {
+ text-align: left;
+ }
+ input.btn:hover, select.btn:hover {
+ border-color: var(--color-neutral-300);
+ background-color: var(--color-neutral-100);
+ color: var(--color-neutral-800);
}
@media (width >=48rem) {
.grid-main {
@@ -937,6 +1060,11 @@
syntax: "*";
inherits: false;
}
+@property --tw-outline-style {
+ syntax: "*";
+ inherits: false;
+ initial-value: solid;
+}
@property --tw-blur {
syntax: "*";
inherits: false;
@@ -1001,6 +1129,7 @@
--tw-border-style: solid;
--tw-divide-y-reverse: 0;
--tw-font-weight: initial;
+ --tw-outline-style: solid;
--tw-blur: initial;
--tw-brightness: initial;
--tw-contrast: initial;
diff --git a/Backend/static/script.js b/Backend/static/script.js
index 520ec52..e5f27bd 100644
--- a/Backend/static/script.js
+++ b/Backend/static/script.js
@@ -12,6 +12,30 @@ function editDay(element, event, formId) {
}
}
+function editAbsence(element, event, absenceId) {
+ var form = document.getElementById("absence_form");
+ console.log(absenceId);
+
+ if (absenceId != 0) {
+ const fieldsToSync = ["date_from", "date_to", "aw_type", "aw_id"];
+
+ var dataForm = document.getElementById(absenceId);
+
+ fieldsToSync.forEach((name) => {
+ const src = dataForm.querySelector(`[name=${name}]`);
+ const target = form.querySelector(`[name=${name}]`);
+ if (!src || !target) return;
+ target.value = src.value;
+ });
+ } else {
+ var dataForm = element.closest(".grid-sub").querySelector(".all-booking-component > form");
+ form.querySelector("[name=date_from]").value = dataForm.id.replace("time-", "");
+ form.querySelector("[name=date_to]").value = dataForm.id.replace("time-", "");
+ }
+ form.classList.remove("hidden");
+ form.scrollIntoView({ behavior: "smooth", block: "start", inline: "nearest" });
+}
+
function editAbwesenheit(element, event) {
var newBookingComponent = element.closest(".grid-sub").querySelector(".new-booking-component");
if (element.value == 0) {
diff --git a/Backend/templates/headerComponent_templ.go b/Backend/templates/headerComponent_templ.go
index 8e59160..aeef6ec 100644
--- a/Backend/templates/headerComponent_templ.go
+++ b/Backend/templates/headerComponent_templ.go
@@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
-// templ: version: v0.3.943
+// templ: version: v0.3.924
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
diff --git a/Backend/templates/pages.templ b/Backend/templates/pages.templ
index 2b938bf..8ca8aff 100644
--- a/Backend/templates/pages.templ
+++ b/Backend/templates/pages.templ
@@ -1,9 +1,6 @@
package templates
-import (
- "arbeitszeitmessung/models"
- "time"
-)
+import "arbeitszeitmessung/models"
templ Base() {
@@ -15,25 +12,6 @@ templ Base() {
}
-templ TimePage(workDays []models.WorkDay, lastSub time.Time) {
- {{
- allDays := ctx.Value("days").([]models.IWorkDay)
- }}
- @Base()
- @headerComponent()
-
- @inputForm()
- for _, day := range allDays {
- @defaultDayComponent(day)
- // @dayComponent(day, day.Day.Before(lastSub))
- if (day.Date().Weekday() == time.Monday) {
-
- }
- }
-
- @LegendComponent()
-}
-
templ LoginPage(success bool, errorMsg string) {
@Base()
diff --git a/Backend/templates/pages_templ.go b/Backend/templates/pages_templ.go
index 0dbe185..3a54c9b 100644
--- a/Backend/templates/pages_templ.go
+++ b/Backend/templates/pages_templ.go
@@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
-// templ: version: v0.3.943
+// templ: version: v0.3.924
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
@@ -8,10 +8,7 @@ package templates
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
-import (
- "arbeitszeitmessung/models"
- "time"
-)
+import "arbeitszeitmessung/models"
func Base() templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
@@ -42,7 +39,7 @@ func Base() templ.Component {
})
}
-func TimePage(workDays []models.WorkDay, lastSub time.Time) templ.Component {
+func LoginPage(success bool, errorMsg string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@@ -63,101 +60,34 @@ func TimePage(workDays []models.WorkDay, lastSub time.Time) templ.Component {
templ_7745c5c3_Var2 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
-
- allDays := ctx.Value("days").([]models.IWorkDay)
templ_7745c5c3_Err = Base().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = headerComponent().Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = inputForm().Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for _, day := range allDays {
- templ_7745c5c3_Err = defaultDayComponent(day).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- if day.Date().Weekday() == time.Monday {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = LegendComponent().Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func LoginPage(success bool, errorMsg string) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var3 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var3 == nil {
- templ_7745c5c3_Var3 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = Base().Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -181,9 +111,9 @@ func UserPage(status int) templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var5 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var5 == nil {
- templ_7745c5c3_Var5 = templ.NopComponent
+ templ_7745c5c3_Var4 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var4 == nil {
+ templ_7745c5c3_Var4 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = Base().Render(ctx, templ_7745c5c3_Buffer)
@@ -194,28 +124,28 @@ func UserPage(status int) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "
Nutzer abmelden
Nutzer von Weboberfläche abmelden.
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -239,18 +169,18 @@ func statusCheckMark(status models.WeekStatus, target models.WeekStatus) templ.C
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var6 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var6 == nil {
- templ_7745c5c3_Var6 = templ.NopComponent
+ templ_7745c5c3_Var5 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var5 == nil {
+ templ_7745c5c3_Var5 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
if status >= target {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -260,6 +190,63 @@ func statusCheckMark(status models.WeekStatus, target models.WeekStatus) templ.C
}
func TeamPage(weeks []models.WorkWeek, userWeek models.WorkWeek) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var6 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var6 == nil {
+ templ_7745c5c3_Var6 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = Base().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = headerComponent().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = workWeekComponent(userWeek, false).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if len(weeks) > 0 {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "
Abrechnung Mitarbeiter
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ for _, week := range weeks {
+ templ_7745c5c3_Err = workWeekComponent(week, true).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func TeamPresencePage(teamPresence map[bool][]models.User) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@@ -288,64 +275,7 @@ func TeamPage(weeks []models.WorkWeek, userWeek models.WorkWeek) templ.Component
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = workWeekComponent(userWeek, false).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- if len(weeks) > 0 {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "
Abrechnung Mitarbeiter
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- for _, week := range weeks {
- templ_7745c5c3_Err = workWeekComponent(week, true).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func TeamPresencePage(teamPresence map[bool][]models.User) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var8 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var8 == nil {
- templ_7745c5c3_Var8 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = Base().Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = headerComponent().Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "
Anwesend
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
Anwesend
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -355,7 +285,7 @@ func TeamPresencePage(teamPresence map[bool][]models.User) templ.Component {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "
Nicht Anwesend
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "
Nicht Anwesend
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -365,7 +295,7 @@ func TeamPresencePage(teamPresence map[bool][]models.User) templ.Component {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -389,12 +319,12 @@ func LogoutButton() templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var9 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var9 == nil {
- templ_7745c5c3_Var9 = templ.NopComponent
+ templ_7745c5c3_Var8 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var8 == nil {
+ templ_7745c5c3_Var8 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
diff --git a/Backend/templates/pdf_templ.go b/Backend/templates/pdf_templ.go
index 57c5998..d9c5e51 100644
--- a/Backend/templates/pdf_templ.go
+++ b/Backend/templates/pdf_templ.go
@@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
-// templ: version: v0.3.943
+// templ: version: v0.3.924
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
diff --git a/Backend/templates/teamComponents.templ b/Backend/templates/teamComponents.templ
index 33be818..e5738b9 100644
--- a/Backend/templates/teamComponents.templ
+++ b/Backend/templates/teamComponents.templ
@@ -44,7 +44,7 @@ templ defaultWeekDayComponent(u models.User, day models.IWorkDay) {
{ helper.FormatDuration(pause) }
-
+
switch {
case !workDay.TimeFrom.Equal(workDay.TimeTo):
{ workDay.TimeFrom.Format("15:04") }
diff --git a/Backend/templates/teamComponents_templ.go b/Backend/templates/teamComponents_templ.go
index 1660f58..ec539f2 100644
--- a/Backend/templates/teamComponents_templ.go
+++ b/Backend/templates/teamComponents_templ.go
@@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
-// templ: version: v0.3.943
+// templ: version: v0.3.924
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
@@ -207,7 +207,7 @@ func defaultWeekDayComponent(u models.User, day models.IWorkDay) templ.Component
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
diff --git a/Backend/templates/timeComponents.templ b/Backend/templates/timeComponents.templ
index a258fb3..f50e3a3 100644
--- a/Backend/templates/timeComponents.templ
+++ b/Backend/templates/timeComponents.templ
@@ -1,130 +1,89 @@
package templates
import (
- "arbeitszeitmessung/helper"
"arbeitszeitmessung/models"
"fmt"
- "net/url"
"strconv"
"time"
)
-templ inputForm() {
- {{
- urlParams := ctx.Value("urlParams").(url.Values)
- user := ctx.Value("user").(models.User)
- }}
-
-
-
{ user.Vorname + " " + user.Name }
-
-
Überstunden
-
{ user.Overtime }
-
-
-
- @lineComponent()
-
-
-
-
-
-
+templ lineComponent() {
+
}
-templ defaultDayComponent(day models.IWorkDay) {
- if day.IsWorkDay() {
- {{
- workDay, _ := day.(*models.WorkDay)
- }}
- @workDayComponent(*workDay, false)
- } else {
- {{
- absentDay, _ := day.(*models.Absence)
- }}
-
-
- @timeGaugeComponent(100, false)
-
{ day.Date().Format("Mon") }: { day.Date().Format("02.01.2006") }
-
-
- @lineComponent()
-
-
{ absentDay.AbwesenheitTyp.Name } bis { absentDay.DateTo.Format("02.01.2006") }
-
-
-
- @changeButtonComponent("time-" + absentDay.Date().Format("2006-01-02"))
-
-
- }
-}
-
-templ workDayComponent(workDay models.WorkDay, submitted bool) {
+// templ workDayComponent(workDay models.WorkDay, submitted bool) {
+// {{
+// // work, pause := workDay.GetWorkTimeString()
+// user := ctx.Value("user").(models.User)
+// work, pause, overtime := workDay.GetAllWorkTimesReal(user)
+// // overtime := helper.FormatDuration(workDay.CalcOvertime(user))
+// justify := ""
+// if len(workDay.Bookings) <= 1 {
+// justify = "justify-content: center"
+// }
+// }}
+//
+//
+// @timeGaugeComponent(workDay.GetDayProgress(user), workDay.Day.Equal(time.Now().Truncate(24*time.Hour)))
+//
+//
{ workDay.Day.Format("Mon") }: { workDay.Day.Format("02.01.2006") }
+// if (workDay.RequiresAction()) {
+//
Bitte anpassen
+// } else {
+// if work > 0 {
+//
Arbeitszeit:
+//
{ helper.FormatDuration(work) }
+// }
+// if pause > 0 {
+// }
+//
{ helper.FormatDuration(pause) }
+// if overtime > 0 {
+//
{ helper.FormatDuration(overtime) }
+// }
+// }
+//
+//
+//
+// @lineComponent()
+//
+// if len(workDay.Bookings) < 1 {
+// Keine Buchung gefunden. Bitte Arbeitsstunden oder Grund der Abwesenheit eingeben!
+// @absenceComponent(workDay)
+// @newBookingComponent(workDay)
+// } else {
+// @absenceComponent(workDay)
+// for _, booking := range workDay.Bookings {
+// @bookingComponent(booking)
+// }
+// if workDay.IsKurzArbeit() {
+// Kurzarbeit
+// }
+// @newBookingComponent(workDay)
+// }
+//
+//
+//
+//
+// @changeButtonComponent("time-" + workDay.Day.Format("2006-01-02"))
+//
+//
+// }
+templ changeButtonComponent(id string, workDay bool) {
{{
- // work, pause := workDay.GetWorkTimeString()
- user := ctx.Value("user").(models.User)
- work, pause, overtime := workDay.GetAllWorkTimesReal(user)
- // overtime := helper.FormatDuration(workDay.CalcOvertime(user))
- justify := ""
- if len(workDay.Bookings) <= 1 {
- justify = "justify-content: center"
+ functionName := "editDay"
+ if !workDay {
+ functionName = "editAbsence"
}
}}
-
-
- @timeGaugeComponent(workDay.GetDayProgress(user), workDay.Day.Equal(time.Now().Truncate(24*time.Hour)))
-
-
{ workDay.Day.Format("Mon") }: { workDay.Day.Format("02.01.2006") }
- if (workDay.RequiresAction()) {
-
Bitte anpassen
- } else {
- if work > 0 {
-
Arbeitszeit:
-
{ helper.FormatDuration(work) }
- }
- if pause > 0 {
-
{ helper.FormatDuration(pause) }
- }
- if overtime > 0 {
-
{ helper.FormatDuration(overtime) }
- }
- }
-
-
-
- @lineComponent()
-
- if len(workDay.Bookings) < 1 {
- Keine Buchung gefunden. Bitte Arbeitsstunden oder Grund der Abwesenheit eingeben!
- @absenceComponent(workDay)
- @newBookingComponent(workDay)
- } else {
- @absenceComponent(workDay)
- for _, booking := range workDay.Bookings {
- @bookingComponent(booking)
- }
- if workDay.IsKurzArbeit() {
- Kurzarbeit
- }
- @newBookingComponent(workDay)
- }
-
-
-
-
- @changeButtonComponent("time-" + workDay.Day.Format("2006-01-02"))
-
-
-}
-
-templ changeButtonComponent(id string) {
-
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -652,7 +256,7 @@ func timeGaugeComponent(progress int8, today bool) templ.Component {
})
}
-func lineComponent() templ.Component {
+func newAbsenceComponent() templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@@ -668,12 +272,29 @@ func lineComponent() templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var31 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var31 == nil {
- templ_7745c5c3_Var31 = templ.NopComponent
+ templ_7745c5c3_Var10 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var10 == nil {
+ templ_7745c5c3_Var10 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, templ.JSFuncCall("editAbsence", templ.JSExpression("this"), templ.JSExpression("event"), 0))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "Abwesenheit
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -681,7 +302,7 @@ func lineComponent() templ.Component {
})
}
-func absenceComponent(d models.WorkDay) templ.Component {
+func newBookingComponent(d *models.WorkDay) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@@ -697,140 +318,58 @@ func absenceComponent(d models.WorkDay) templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var32 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var32 == nil {
- templ_7745c5c3_Var32 = templ.NopComponent
+ templ_7745c5c3_Var12 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var12 == nil {
+ templ_7745c5c3_Var12 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for _, absence := range models.GetAbsenceTypesCached() {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-func newBookingComponent(d models.WorkDay) templ.Component {
- return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
- templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
- if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
- return templ_7745c5c3_CtxErr
- }
- templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
- if !templ_7745c5c3_IsBuffer {
- defer func() {
- templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err == nil {
- templ_7745c5c3_Err = templ_7745c5c3_BufErr
- }
- }()
- }
- ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var36 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var36 == nil {
- templ_7745c5c3_Var36 = templ.NopComponent
- }
- ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, ">Gehen
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -854,64 +393,64 @@ func bookingComponent(booking models.Booking) templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var39 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var39 == nil {
- templ_7745c5c3_Var39 = templ.NopComponent
+ templ_7745c5c3_Var15 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var15 == nil {
+ templ_7745c5c3_Var15 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var40 string
- templ_7745c5c3_Var40, templ_7745c5c3_Err = templ.JoinStringErrs(booking.Timestamp.Format("15:04"))
+ var templ_7745c5c3_Var16 string
+ templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(booking.Timestamp.Format("15:04"))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 206, Col: 97}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 150, Col: 97}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var40))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\" class=\"text-neutral-700 group-[.edit]:inline hidden bg-neutral-100 text-sm border border-neutral-200 rounded-md px-3 py-2 transition duration-300 ease focus:outline-none focus:border-neutral-400 hover:border-neutral-300\"> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var43 string
- templ_7745c5c3_Var43, templ_7745c5c3_Err = templ.JoinStringErrs(booking.GetBookingType())
+ var templ_7745c5c3_Var19 string
+ templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(booking.GetBookingType())
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 208, Col: 29}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 152, Col: 29}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var43))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -935,12 +474,12 @@ func LegendComponent() templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var44 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var44 == nil {
- templ_7745c5c3_Var44 = templ.NopComponent
+ templ_7745c5c3_Var20 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var20 == nil {
+ templ_7745c5c3_Var20 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "
Arbeitszeit unter regulär ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "
Arbeitszeit unter regulär ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
diff --git a/Backend/templates/timePage.templ b/Backend/templates/timePage.templ
new file mode 100644
index 0000000..6f86c77
--- /dev/null
+++ b/Backend/templates/timePage.templ
@@ -0,0 +1,169 @@
+package templates
+
+import (
+ "arbeitszeitmessung/helper"
+ "arbeitszeitmessung/models"
+ "net/url"
+ "strconv"
+ "time"
+)
+
+templ TimePage(workDays []models.WorkDay, lastSub time.Time) {
+ {{
+ allDays := ctx.Value("days").([]models.IWorkDay)
+ }}
+ @Base()
+ @headerComponent()
+
+ @inputForm()
+ for _, day := range allDays {
+ @defaultDayComponent(day)
+ if (day.Date().Weekday() == time.Monday) {
+
+ }
+ }
+
+ @LegendComponent()
+}
+
+templ inputForm() {
+ {{
+ urlParams := ctx.Value("urlParams").(url.Values)
+ user := ctx.Value("user").(models.User)
+ }}
+
+
+
{ user.Vorname + " " + user.Name }
+
+
Überstunden
+
{ user.Overtime }
+
+
+
+ @lineComponent()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+templ defaultDayComponent(day models.IWorkDay) {
+ {{
+ user := ctx.Value("user").(models.User)
+ justify := "justify-center"
+ if day.IsWorkDay() && len(day.(*models.WorkDay).Bookings) > 1 {
+ justify = "justify-between"
+ }
+ }}
+
+
+ @timeGaugeComponent(day.GetDayProgress(user), day.Date().Equal(time.Now().Truncate(24*time.Hour)))
+
+
+ { day.Date().Format("Mon") }: { day.Date().Format(
+
+"02.01.2006") }
+
+ if day.IsWorkDay() {
+ {{
+ workDay, _ := day.(*models.WorkDay)
+ work, pause, overtime := workDay.GetAllWorkTimesVirtual(user)
+ }}
+ if day.RequiresAction() {
+
Bitte anpassen
+ } else {
+ if work > 0 {
+
Arbeitszeit:
+
{ helper.FormatDuration(work) }
+ }
+ if pause > 0 {
+ }
+
{ helper.FormatDuration(pause) }
+ if overtime != 0 {
+
+
+ { helper.FormatDuration(overtime) }
+
+ }
+ }
+ }
+
+
+
+ @lineComponent()
+
+ @newAbsenceComponent()
+ if day.IsWorkDay() {
+ {{
+ workDay, _ := day.(*models.WorkDay)
+ }}
+ if len(workDay.Bookings) < 1 {
+ Keine Buchung gefunden. Bitte Arbeitsstunden oder Grund der Abwesenheit eingeben!
+ }
+ for _, booking := range workDay.Bookings {
+ @bookingComponent(booking)
+ }
+ @newBookingComponent(workDay)
+ if workDay.IsKurzArbeit() {
+ @absentInput(workDay.GetKurzArbeit())
+ Kurzarbeit
+ }
+ } else {
+ {{
+ absentDay, _ := day.(*models.Absence)
+ }}
+ @absentInput(*absentDay)
+ { absentDay.AbwesenheitTyp.Name } bis { absentDay.DateTo.Format("02.01.2006") }
+ }
+
+
+
+ @changeButtonComponent("time-"+day.Date().Format("2006-01-02"), day.IsWorkDay())
+
+
+}
+
+templ absentInput(a models.Absence) {
+
+
+
+
+}
diff --git a/Backend/templates/timePage_templ.go b/Backend/templates/timePage_templ.go
new file mode 100644
index 0000000..36c7b99
--- /dev/null
+++ b/Backend/templates/timePage_templ.go
@@ -0,0 +1,591 @@
+// Code generated by templ - DO NOT EDIT.
+
+// templ: version: v0.3.924
+package templates
+
+//lint:file-ignore SA4006 This context is only used if a nested component is present.
+
+import "github.com/a-h/templ"
+import templruntime "github.com/a-h/templ/runtime"
+
+import (
+ "arbeitszeitmessung/helper"
+ "arbeitszeitmessung/models"
+ "net/url"
+ "strconv"
+ "time"
+)
+
+func TimePage(workDays []models.WorkDay, lastSub time.Time) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var1 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var1 == nil {
+ templ_7745c5c3_Var1 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+
+ allDays := ctx.Value("days").([]models.IWorkDay)
+ templ_7745c5c3_Err = Base().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = headerComponent().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = inputForm().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, day := range allDays {
+ templ_7745c5c3_Err = defaultDayComponent(day).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if day.Date().Weekday() == time.Monday {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = LegendComponent().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func inputForm() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var2 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var2 == nil {
+ templ_7745c5c3_Var2 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+
+ urlParams := ctx.Value("urlParams").(url.Values)
+ user := ctx.Value("user").(models.User)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var3 string
+ templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(user.Vorname + " " + user.Name)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timePage.templ`, Line: 36, Col: 66}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
Überstunden
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var4 string
+ templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(user.Overtime)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timePage.templ`, Line: 39, Col: 42}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = lineComponent().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func defaultDayComponent(day models.IWorkDay) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var9 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var9 == nil {
+ templ_7745c5c3_Var9 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+
+ user := ctx.Value("user").(models.User)
+ justify := "justify-center"
+ if day.IsWorkDay() && len(day.(*models.WorkDay).Bookings) > 1 {
+ justify = "justify-between"
+ }
+ var templ_7745c5c3_Var10 = []any{"grid-sub divide-x-1 hover:bg-neutral-200 transition-colors"}
+ templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = timeGaugeComponent(day.GetDayProgress(user), day.Date().Equal(time.Now().Truncate(24*time.Hour))).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var12 string
+ templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(day.Date().Format("Mon"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timePage.templ`, Line: 101, Col: 82}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, ": ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var13 string
+ templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(day.Date().Format(
+
+ "02.01.2006"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timePage.templ`, Line: 103, Col: 13}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if day.IsWorkDay() {
+
+ workDay, _ := day.(*models.WorkDay)
+ work, pause, overtime := workDay.GetAllWorkTimesVirtual(user)
+ if day.RequiresAction() {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "
Bitte anpassen
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else {
+ if work > 0 {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "
Arbeitszeit:
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var14 string
+ templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(helper.FormatDuration(work))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timePage.templ`, Line: 115, Col: 155}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if pause > 0 {
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var15 string
+ templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(helper.FormatDuration(pause))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timePage.templ`, Line: 119, Col: 172}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if overtime != 0 {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var16 string
+ templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(helper.FormatDuration(overtime))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timePage.templ`, Line: 123, Col: 41}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = lineComponent().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var17 = []any{"flex flex-col gap-2 group w-full ", justify}
+ templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var17...)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = newAbsenceComponent().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if day.IsWorkDay() {
+
+ workDay, _ := day.(*models.WorkDay)
+ if len(workDay.Bookings) < 1 {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "Keine Buchung gefunden. Bitte Arbeitsstunden oder Grund der Abwesenheit eingeben!
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ for _, booking := range workDay.Bookings {
+ templ_7745c5c3_Err = bookingComponent(booking).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = newBookingComponent(workDay).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if workDay.IsKurzArbeit() {
+ templ_7745c5c3_Err = absentInput(workDay.GetKurzArbeit()).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, " Kurzarbeit
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ } else {
+
+ absentDay, _ := day.(*models.Absence)
+ templ_7745c5c3_Err = absentInput(*absentDay).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var20 string
+ templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(absentDay.AbwesenheitTyp.Name)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timePage.templ`, Line: 154, Col: 39}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, " bis ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var21 string
+ templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(absentDay.DateTo.Format("02.01.2006"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timePage.templ`, Line: 154, Col: 116}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = changeButtonComponent("time-"+day.Date().Format("2006-01-02"), day.IsWorkDay()).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func absentInput(a models.Absence) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var22 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var22 == nil {
+ templ_7745c5c3_Var22 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+var _ = templruntime.GeneratedTemplate
diff --git a/db.sql b/db.sql
index 4ba7830..cdc1beb 100644
--- a/db.sql
+++ b/db.sql
@@ -203,7 +203,7 @@ WITH params AS (
14::int AS start_days_ago, -- how many days back to start
0::int AS end_days_ahead, -- how many days forward (0 = today)
0::float AS pause_probability,
- 0.2::float AS absence_probability
+ 0.0::float AS absence_probability
),
days AS (
SELECT gs::date AS work_date, p.card_uid, p.geraet_id, p.pause_probability, p.absence_probability
diff --git a/migrations/20250904114004_intervals.up.sql b/migrations/20250904114004_intervals.up.sql
index 272ceb8..b3c6baf 100644
--- a/migrations/20250904114004_intervals.up.sql
+++ b/migrations/20250904114004_intervals.up.sql
@@ -1,13 +1,19 @@
ALTER TABLE wochen_report
- ALTER COLUMN ueberstunden TYPE interval
- USING
- make_interval(
- hours => floor(ueberstunden)::int,
- mins => round((ueberstunden - floor(ueberstunden)) * 60)::int
- ),
- ALTER COLUMN arbeitszeit TYPE interval
- USING
- make_interval(
- hours => floor(arbeitszeit)::int,
- mins => round((arbeitszeit - floor(arbeitszeit)) * 60)::int
- );
+ ADD COLUMN ueberstunden_interval interval,
+ ADD COLUMN arbeitszeit_interval interval;
+
+UPDATE wochen_report
+SET
+ ueberstunden_interval = CASE WHEN ueberstunden IS NULL THEN NULL ELSE (ueberstunden::double precision * INTERVAL '1 hour') END,
+ arbeitszeit_interval = CASE WHEN arbeitszeit IS NULL THEN NULL ELSE (arbeitszeit::double precision * INTERVAL '1 hour') END;
+
+-- when happy, drop old columns and rename new ones
+ALTER TABLE wochen_report
+ DROP COLUMN ueberstunden,
+ DROP COLUMN arbeitszeit;
+
+ALTER TABLE wochen_report
+ RENAME COLUMN ueberstunden_interval TO ueberstunden;
+
+ALTER TABLE wochen_report
+ RENAME COLUMN arbeitszeit_interval TO arbeitszeit;
diff --git a/migrations/20250916093608.down.sql b/migrations/20250916093608_kurzarbeit.down.sql
similarity index 100%
rename from migrations/20250916093608.down.sql
rename to migrations/20250916093608_kurzarbeit.down.sql
diff --git a/migrations/20250916093608.up.sql b/migrations/20250916093608_kurzarbeit.up.sql
similarity index 100%
rename from migrations/20250916093608.up.sql
rename to migrations/20250916093608_kurzarbeit.up.sql
diff --git a/migrations/atlas.sum b/migrations/atlas.sum
index d57ff83..4950d34 100644
--- a/migrations/atlas.sum
+++ b/migrations/atlas.sum
@@ -1,7 +1,15 @@
-h1:31y/DB0ca2cm603nNckNvVCwm+XuMaVsoGUB+JvrOKs=
-20250901201159_initial.up.sql h1:Mb1RlVdFvcxqU9HrSK6oNeURqFa3O4KzB3rDa+6+3gc=
-20250901201250_control_tables.up.sql h1:a5LATgR/CRiC4GsqxkJ94TyJOxeTcW74eCnodIy+c1E=
-20250901201710_triggers_extension.up.sql h1:z9b6Hk9btE2Ns4mU7B16HjvYBP6EEwHAXVlvPpkn978=
-20250903221313_overtime.up.sql h1:t/B435ShW5ZEnzC81jRABWVZ5gNm7tPZPnOO6/ZY6ow=
-20250903233030_non_null_contraints.up.sql h1:e7d+6ZdpEjPh2cc65N3S06oD2e6diMuG7+klhgYsym8=
-20250904114004_intervals.up.sql h1:Sz8FIVvvcCIS3aIuSjyzFYLs32fjMcMMHk62shj6Qpw=
+h1:3AxgD8mnu/F+JGtJu9FZvA9Ro0UUtGPgyjskKtfTYUQ=
+20250901201159_initial.down.sql h1:cmF5CvNGqEfcmbRgiqaqDWERdNNRaMzarbNLJ/Y35o4=
+20250901201159_initial.up.sql h1:Yrak/+wfQ4Tu/dVR/cUZ/75DlAcv4G/OJXDqpgSw47U=
+20250901201250_control_tables.down.sql h1:f/KmhO9pOI45J8ZRjFonvD3CypB+rOoGOPN2WMFHvOw=
+20250901201250_control_tables.up.sql h1:of5E07p0N1aen9CdQNEOrO7ffbKZC6kp4oK5KPzU9+g=
+20250901201710_triggers_extension.down.sql h1:a9va3FSfHBWzODJSJO+ywNa2hiZwjG/vmvYGb3L1lnM=
+20250901201710_triggers_extension.up.sql h1:nUBPd2eDssi/TwMVF/nOJkIM5rUM0iINdg1K9pZRZN0=
+20250903221313_overtime.down.sql h1:X+jJESqcZ6ZTd2H563z6kRaXb4dn4sA02D3ck2795v8=
+20250903221313_overtime.up.sql h1:C3DSiNVpe9v0Un1DEQ0lsy5yToR8iqcggv91GSr6tRE=
+20250903233030_non_null_contraints.down.sql h1:42TZzPsji2Ze50k6sLwgIuNo4Trk3m3ni/aIfQJ97dE=
+20250903233030_non_null_contraints.up.sql h1:k6zR5YNSAP4fo5QEc58KZ0LxvEz1nl0X/AAcZ+TG3I4=
+20250904114004_intervals.down.sql h1:SquJAPinzFIRN6fJjLLIRsz59Tyr4RwGiGuOFI/N1SQ=
+20250904114004_intervals.up.sql h1:AFqncTGOiEZVBbhWFqN2zlQ7DyhybB5wJr6a36Atk1E=
+20250916093608_kurzarbeit.down.sql h1:ljM1a1pQCxOQiXRaXU04GC4V9yy2y20x5eUNQ/zyx+o=
+20250916093608_kurzarbeit.up.sql h1:pTiw0VfGaf26mhJg4wf98Fqwn1kShJ+PiN2PiM4q1kk=