diff --git a/Backend/endpoints/time.go b/Backend/endpoints/time.go index 3179995..477ad96 100644 --- a/Backend/endpoints/time.go +++ b/Backend/endpoints/time.go @@ -116,7 +116,7 @@ func updateBooking(w http.ResponseWriter, r *http.Request) { newBooking := (*models.Booking).New(nil, user.CardUID, 0, int16(check_in_out)) newBooking.Timestamp = timestamp - err = newBooking.InsertTimestamp() + err = newBooking.InsertWithTimestamp() if err != nil { log.Println("Error inserting booking", err) } diff --git a/Backend/helper/time.go b/Backend/helper/time.go index 5abd82c..70ace8a 100644 --- a/Backend/helper/time.go +++ b/Backend/helper/time.go @@ -1,6 +1,7 @@ package helper import ( + "fmt" "time" ) @@ -14,3 +15,23 @@ func GetMonday(ts time.Time) time.Time { } return ts } + +// Converts duration to string +func FormatDuration(d time.Duration) string { + hours := int(d.Abs().Hours()) + minutes := int(d.Abs().Minutes()) % 60 + sign := "" + if d < 0 { + sign = "-" + } + switch { + case hours > 0 && minutes == 0: + return fmt.Sprintf("%s%dh", sign, hours) + case hours > 0: + return fmt.Sprintf("%s%dh %dmin", sign, hours, minutes) + case minutes > 0: + return fmt.Sprintf("%s%dmin", sign, minutes) + default: + return "" + } +} diff --git a/Backend/helper/time_test.go b/Backend/helper/time_test.go index c82c4c4..d106e7f 100644 --- a/Backend/helper/time_test.go +++ b/Backend/helper/time_test.go @@ -15,3 +15,22 @@ func TestGetMonday(t *testing.T) { t.Error("Wrong date conversion!") } } + +func TestFormatDuration(t *testing.T) { + durations := []struct { + name string + duration time.Duration + }{ + {"2h", time.Duration(120 * time.Minute)}, + {"30min", time.Duration(30 * time.Minute)}, + {"1h 30min", time.Duration(90 * time.Minute)}, + {"-1h 30min", time.Duration(-90 * time.Minute)}, + } + for _, d := range durations { + t.Run(d.name, func(t *testing.T) { + if FormatDuration(d.duration) != d.name { + t.Error("Format missmatch in Formatduration.") + } + }) + } +} diff --git a/Backend/models/booking.go b/Backend/models/booking.go index 47c2c47..24533c2 100644 --- a/Backend/models/booking.go +++ b/Backend/models/booking.go @@ -70,7 +70,7 @@ func (b *Booking) Insert() error { return nil } -func (b *Booking) InsertTimestamp() error { +func (b *Booking) InsertWithTimestamp() error { if b.Timestamp.IsZero() { return b.Insert() } diff --git a/Backend/models/workDay.go b/Backend/models/workDay.go index d6d637a..6585742 100644 --- a/Backend/models/workDay.go +++ b/Backend/models/workDay.go @@ -4,7 +4,6 @@ import ( "arbeitszeitmessung/helper" "database/sql" "encoding/json" - "fmt" "log" "strconv" "time" @@ -180,23 +179,9 @@ func (d *WorkDay) getWorkTime() { d.calcPauseTime() } -// Converts duration to string -func formatDuration(d time.Duration) string { - hours := int(d.Abs().Hours()) - minutes := int(d.Abs().Minutes()) % 60 - switch { - case hours > 0: - return fmt.Sprintf("%dh %dmin", hours, minutes) - case minutes > 0: - return fmt.Sprintf("%dmin", minutes) - default: - return "" - } -} - func (d *WorkDay) GetWorkTimeString() (string, string) { - workString := formatDuration(d.workTime) - pauseString := formatDuration(d.pauseTime) + workString := helper.FormatDuration(d.workTime) + pauseString := helper.FormatDuration(d.pauseTime) return workString, pauseString } @@ -210,7 +195,12 @@ func (d *WorkDay) RequiresAction() bool { // returns a integer percentage of how much day has been worked of func (d *WorkDay) GetWorkDayProgress(user User) uint8 { - defaultWorkTime := time.Duration(user.ArbeitszeitPerTag * float32(time.Hour)) + defaultWorkTime := time.Duration(user.ArbeitszeitPerTag * float32(time.Hour)).Round(time.Minute) progress := (d.workTime.Seconds() / defaultWorkTime.Seconds()) * 100 return uint8(progress) } + +func (d *WorkDay) CalcOvertime(user User) time.Duration { + overtime := d.workTime - time.Duration(user.ArbeitszeitPerTag*float32(time.Hour)).Round(time.Minute) + return overtime +} diff --git a/Backend/models/workWeek.go b/Backend/models/workWeek.go index 1ce0a30..7bd4beb 100644 --- a/Backend/models/workWeek.go +++ b/Backend/models/workWeek.go @@ -1,6 +1,7 @@ package models import ( + "arbeitszeitmessung/helper" "database/sql" "errors" "log" @@ -60,7 +61,7 @@ func (w *WorkWeek) CheckStatus() WeekStatus { } func (w *WorkWeek) GetWorkHourString() string { - return formatDuration(w.WorkHours) + return helper.FormatDuration(w.WorkHours) } func aggregateWorkTime(days []WorkDay) time.Duration { diff --git a/Backend/templates/timeComponents.templ b/Backend/templates/timeComponents.templ index 9a7b68a..576ff9e 100644 --- a/Backend/templates/timeComponents.templ +++ b/Backend/templates/timeComponents.templ @@ -1,6 +1,7 @@ package templates import ( + "arbeitszeitmessung/helper" "arbeitszeitmessung/models" "fmt" "net/url" @@ -39,6 +40,8 @@ templ inputForm() { templ dayComponent(workDay models.WorkDay) { {{ work, pause := workDay.GetWorkTimeString() + user := ctx.Value("user").(models.User) + overtime := helper.FormatDuration(workDay.CalcOvertime(user)) justify := "" if len(workDay.Bookings) <= 1 { justify = "justify-content: center" @@ -57,6 +60,7 @@ templ dayComponent(workDay models.WorkDay) {
{ work }
}{ pause }
+{ overtime }
} diff --git a/Backend/templates/timeComponents_templ.go b/Backend/templates/timeComponents_templ.go index c109fb7..75776c4 100644 --- a/Backend/templates/timeComponents_templ.go +++ b/Backend/templates/timeComponents_templ.go @@ -9,6 +9,7 @@ import "github.com/a-h/templ" import templruntime "github.com/a-h/templ/runtime" import ( + "arbeitszeitmessung/helper" "arbeitszeitmessung/models" "fmt" "net/url" @@ -47,7 +48,7 @@ func inputForm() templ.Component { var templ_7745c5c3_Var2 string templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(user.Vorname + " " + user.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 18, Col: 66} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 19, Col: 66} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) if templ_7745c5c3_Err != nil { @@ -68,7 +69,7 @@ func inputForm() templ.Component { var templ_7745c5c3_Var3 string templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(urlParams.Get("time_from")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 27, Col: 57} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 28, Col: 57} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { @@ -81,7 +82,7 @@ func inputForm() templ.Component { var templ_7745c5c3_Var4 string templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(urlParams.Get("time_to")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 28, Col: 55} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 29, Col: 55} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { @@ -118,6 +119,8 @@ func dayComponent(workDay models.WorkDay) templ.Component { ctx = templ.ClearChildren(ctx) work, pause := workDay.GetWorkTimeString() + user := ctx.Value("user").(models.User) + overtime := helper.FormatDuration(workDay.CalcOvertime(user)) justify := "" if len(workDay.Bookings) <= 1 { justify = "justify-content: center" @@ -137,7 +140,7 @@ func dayComponent(workDay models.WorkDay) templ.Component { var templ_7745c5c3_Var6 string templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(workDay.Day.Format("Mon")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 51, Col: 94} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 54, Col: 94} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { @@ -150,7 +153,7 @@ func dayComponent(workDay models.WorkDay) templ.Component { var templ_7745c5c3_Var7 string templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(workDay.Day.Format("02.01.2006")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 51, Col: 139} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 54, Col: 139} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { @@ -178,7 +181,7 @@ func dayComponent(workDay models.WorkDay) templ.Component { var templ_7745c5c3_Var8 string templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(work) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 57, Col: 36} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 60, Col: 36} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { @@ -196,18 +199,31 @@ func dayComponent(workDay models.WorkDay) templ.Component { var templ_7745c5c3_Var9 string templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(pause) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 59, Col: 40} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 62, Col: 40} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var10 string + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(overtime) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 63, Col: 43} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "Ändern
Absenden
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -375,9 +391,9 @@ func timeGaugeComponent(progress uint8, today bool, warning bool) templ.Componen }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var15 := templ.GetChildren(ctx) - if templ_7745c5c3_Var15 == nil { - templ_7745c5c3_Var15 = templ.NopComponent + templ_7745c5c3_Var16 := templ.GetChildren(ctx) + if templ_7745c5c3_Var16 == nil { + templ_7745c5c3_Var16 = templ.NopComponent } ctx = templ.ClearChildren(ctx) @@ -400,65 +416,65 @@ func timeGaugeComponent(progress uint8, today bool, warning bool) templ.Componen break } if today { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var30 string - templ_7745c5c3_Var30, 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: 174, Col: 97} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var31 string - templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs("booking_" + strconv.Itoa(booking.CounterId)) + templ_7745c5c3_Var31, 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: 175, Col: 70} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 178, Col: 97} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "\" type=\"time\" value=\"") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "\" type=\"time\" value=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var33 string - templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(booking.GetBookingType()) + templ_7745c5c3_Var33, 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: 176, Col: 29} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 179, Col: 126} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "