Compare commits
	
		
			3 Commits
		
	
	
		
			0.2.2
			...
			656d4c2340
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 656d4c2340 | |||
| 2d0b117403 | |||
| ccded6d76b | 
| @@ -11,9 +11,14 @@ import ( | |||||||
|  |  | ||||||
| func PDFHandler(w http.ResponseWriter, r *http.Request) { | func PDFHandler(w http.ResponseWriter, r *http.Request) { | ||||||
| 	helper.RequiresLogin(Session, w, r) | 	helper.RequiresLogin(Session, w, r) | ||||||
| 	startDate, err := time.Parse("2006-01-02", "2025-08-01") | 	startDate, err := parseTimestamp(r, "start", time.Now().Format("2006-01-02")) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Println("Error") | 		log.Println("Error parsing 'start_date' time", err) | ||||||
|  | 		http.Error(w, "Timestamp 'start_date' cannot be parsed!", http.StatusBadRequest) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	if startDate.Day() > 1 { | ||||||
|  | 		startDate = startDate.AddDate(0, 0, -(startDate.Day() - 1)) | ||||||
| 	} | 	} | ||||||
| 	endDate := startDate.AddDate(0, 1, -1) | 	endDate := startDate.AddDate(0, 1, -1) | ||||||
|  |  | ||||||
| @@ -22,8 +27,10 @@ func PDFHandler(w http.ResponseWriter, r *http.Request) { | |||||||
| 		log.Println("Error getting user!") | 		log.Println("Error getting user!") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	weeks := models.GetWorkDays(user.CardUID, startDate, endDate) | 	//TODO: only accepted weeks | ||||||
|  |  | ||||||
| 	log.Printf("Using Dates: %s - %s\n", startDate.String(), endDate.String()) | 	weeks := models.GetWorkDays(user, startDate, endDate) | ||||||
|  |  | ||||||
|  | 	// log.Printf("Using Dates: %s - %s\n", startDate.String(), endDate.String()) | ||||||
| 	templates.PDFReportEmploye(user, weeks, startDate, endDate).Render(r.Context(), w) | 	templates.PDFReportEmploye(user, weeks, startDate, endDate).Render(r.Context(), w) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -66,7 +66,7 @@ func getBookings(w http.ResponseWriter, r *http.Request) { | |||||||
| 	} | 	} | ||||||
| 	tsTo = tsTo.AddDate(0, 0, 1) // so that today is inside | 	tsTo = tsTo.AddDate(0, 0, 1) // so that today is inside | ||||||
|  |  | ||||||
| 	workDays := models.GetWorkDays(user.CardUID, tsFrom, tsTo) | 	workDays := models.GetWorkDays(user, tsFrom, tsTo) | ||||||
| 	sort.Slice(workDays, func(i, j int) bool { | 	sort.Slice(workDays, func(i, j int) bool { | ||||||
| 		return workDays[i].Day.After(workDays[j].Day) | 		return workDays[i].Day.After(workDays[j].Day) | ||||||
| 	}) | 	}) | ||||||
| @@ -182,82 +182,3 @@ func createAbsence(absenceType int, user models.User, loc *time.Location, r *htt | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func getBookingsAPI(w http.ResponseWriter, r *http.Request) { |  | ||||||
| 	_user_pn := r.URL.Query().Get("personal_nummer") |  | ||||||
| 	user_pn, err := strconv.Atoi(_user_pn) |  | ||||||
| 	if err != nil { |  | ||||||
| 		log.Println("No personal numver found!") |  | ||||||
| 		http.Error(w, "No personal number found", http.StatusBadRequest) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	user, err := models.GetUserByPersonalNr(user_pn) |  | ||||||
| 	if err != nil { |  | ||||||
| 		log.Println("No user found with the given personal number!") |  | ||||||
| 		http.Error(w, "No user found", http.StatusNotFound) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// TODO add config for timeoffset |  | ||||||
| 	tsFrom, err := parseTimestamp(r, "time_from", time.Now().AddDate(0, -1, 0).Format("2006-01-02")) |  | ||||||
| 	if err != nil { |  | ||||||
| 		log.Println("Error parsing 'from' time", err) |  | ||||||
| 		http.Error(w, "Timestamp 'from' cannot be parsed!", http.StatusBadRequest) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	tsTo, err := parseTimestamp(r, "time_to", time.Now().Format("2006-01-02")) |  | ||||||
| 	if err != nil { |  | ||||||
| 		log.Println("Error parsing 'to' time", err) |  | ||||||
| 		http.Error(w, "Timestamp 'to' cannot be parsed!", http.StatusBadRequest) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	tsTo = tsTo.AddDate(0, 0, 1) // so that today is inside |  | ||||||
|  |  | ||||||
| 	bookings, err := (*models.Booking).GetBookingsGrouped(nil, user.CardUID, tsFrom, tsTo) |  | ||||||
| 	if err != nil { |  | ||||||
| 		log.Println("Error getting bookings: ", err) |  | ||||||
| 		http.Error(w, "Internal Server Error", http.StatusInternalServerError) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	w.Header().Set("Content-Type", "application/json") |  | ||||||
| 	json.NewEncoder(w).Encode(bookings) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Updates a booking form the given json body |  | ||||||
| func updateBookingAPI(w http.ResponseWriter, r *http.Request) { |  | ||||||
| 	_booking_id := r.URL.Query().Get("counter_id") |  | ||||||
| 	if _booking_id == "" { |  | ||||||
| 		http.Error(w, "Missing bookingID query parameter", http.StatusBadRequest) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	booking_id, err := strconv.Atoi(_booking_id) |  | ||||||
| 	if err != nil { |  | ||||||
| 		http.Error(w, "Invalid bookingID query parameter", http.StatusBadRequest) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	bookingDB, err := (*models.Booking).GetBookingById(nil, booking_id) |  | ||||||
| 	if err != nil { |  | ||||||
| 		log.Println("Error getting booking: ", err) |  | ||||||
| 		http.Error(w, "Internal Server Error", http.StatusInternalServerError) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	var booking models.Booking |  | ||||||
| 	dec := json.NewDecoder(r.Body) |  | ||||||
| 	dec.DisallowUnknownFields() |  | ||||||
| 	err = dec.Decode(&booking) |  | ||||||
| 	if err != nil { |  | ||||||
| 		log.Println("Error parsing booking: ", err) |  | ||||||
| 		http.Error(w, "Internal Server Error", http.StatusInternalServerError) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	if booking.CounterId != 0 && booking.CounterId != bookingDB.CounterId { |  | ||||||
| 		log.Println("Booking Ids do not match") |  | ||||||
| 		http.Error(w, "Booking Ids do not match", http.StatusBadRequest) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	bookingDB.Update(booking) |  | ||||||
| 	bookingDB.Save() |  | ||||||
| 	w.Header().Set("Content-Type", "application/json") |  | ||||||
| 	json.NewEncoder(w).Encode(bookingDB) |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -17,4 +17,5 @@ require ( | |||||||
| 	github.com/hashicorp/errwrap v1.1.0 // indirect | 	github.com/hashicorp/errwrap v1.1.0 // indirect | ||||||
| 	github.com/hashicorp/go-multierror v1.1.1 // indirect | 	github.com/hashicorp/go-multierror v1.1.1 // indirect | ||||||
| 	go.uber.org/atomic v1.7.0 // indirect | 	go.uber.org/atomic v1.7.0 // indirect | ||||||
|  | 	golang.org/x/sys v0.36.0 // indirect | ||||||
| ) | ) | ||||||
|   | |||||||
| @@ -68,7 +68,7 @@ go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt3 | |||||||
| go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= | go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= | ||||||
| go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= | go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= | ||||||
| go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= | ||||||
| golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= | golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= | ||||||
| golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= | golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= | ||||||
| gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||||||
| gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||||
|   | |||||||
| @@ -25,8 +25,12 @@ func GetKW(t time.Time) int { | |||||||
| 	return kw | 	return kw | ||||||
| } | } | ||||||
|  |  | ||||||
| // Converts duration to string |  | ||||||
| func FormatDuration(d time.Duration) string { | func FormatDuration(d time.Duration) string { | ||||||
|  | 	return FormatDurationFill(d, false) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Converts duration to string | ||||||
|  | func FormatDurationFill(d time.Duration, fill bool) string { | ||||||
| 	hours := int(d.Abs().Hours()) | 	hours := int(d.Abs().Hours()) | ||||||
| 	minutes := int(d.Abs().Minutes()) % 60 | 	minutes := int(d.Abs().Minutes()) % 60 | ||||||
| 	sign := "" | 	sign := "" | ||||||
| @@ -41,6 +45,13 @@ func FormatDuration(d time.Duration) string { | |||||||
| 	case minutes > 0: | 	case minutes > 0: | ||||||
| 		return fmt.Sprintf("%s%dmin", sign, minutes) | 		return fmt.Sprintf("%s%dmin", sign, minutes) | ||||||
| 	default: | 	default: | ||||||
|  | 		if fill { | ||||||
|  | 			return "0min" | ||||||
|  | 		} | ||||||
| 		return "" | 		return "" | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func IsSameDate(a, b time.Time) bool { | ||||||
|  | 	return a.Truncate(24 * time.Hour).Equal(b.Truncate(24 * time.Hour)) | ||||||
|  | } | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ import ( | |||||||
| type AbsenceType struct { | type AbsenceType struct { | ||||||
| 	Id       int8 | 	Id       int8 | ||||||
| 	Name     string | 	Name     string | ||||||
| 	WorkTime float32 | 	WorkTime int8 | ||||||
| } | } | ||||||
|  |  | ||||||
| type Absence struct { | type Absence struct { | ||||||
|   | |||||||
| @@ -7,7 +7,6 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"log" | 	"log" | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 	"sort" |  | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
| @@ -163,37 +162,6 @@ func (b *Booking) GetBookingsByCardID(card_uid string, tsFrom time.Time, tsTo ti | |||||||
| 	return bookings, nil | 	return bookings, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *Booking) GetBookingsGrouped(card_uid string, tsFrom time.Time, tsTo time.Time) ([]WorkDay, error) { |  | ||||||
| 	var grouped = make(map[string][]Booking) |  | ||||||
| 	bookings, err := b.GetBookingsByCardID(card_uid, tsFrom, tsTo) |  | ||||||
| 	if err != nil { |  | ||||||
| 		log.Println("Failed to get bookings", err) |  | ||||||
| 		return []WorkDay{}, nil |  | ||||||
| 	} |  | ||||||
| 	for _, booking := range bookings { |  | ||||||
| 		day := booking.Timestamp.Truncate(24 * time.Hour) |  | ||||||
| 		key := day.Format("2006-01-02") |  | ||||||
| 		grouped[key] = append(grouped[key], booking) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	var result []WorkDay |  | ||||||
| 	for key, bookings := range grouped { |  | ||||||
| 		day, _ := time.Parse("2006-01-02", key) |  | ||||||
| 		sort.Slice(bookings, func(i, j int) bool { |  | ||||||
| 			return bookings[i].Timestamp.Before(bookings[j].Timestamp) |  | ||||||
| 		}) |  | ||||||
| 		workDay := WorkDay{Day: day, Bookings: bookings} |  | ||||||
| 		workDay.getWorkTime() |  | ||||||
| 		result = append(result, workDay) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	sort.Slice(result, func(i, j int) bool { |  | ||||||
| 		return result[i].Day.After(result[j].Day) |  | ||||||
| 	}) |  | ||||||
|  |  | ||||||
| 	return result, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (b Booking) Save() { | func (b Booking) Save() { | ||||||
| 	qStr, err := DB.Prepare((`UPDATE "anwesenheit" SET "card_uid" = $2, "geraet_id" = $3, "check_in_out" = $4, "timestamp" = $5 WHERE "counter_id" = $1;`)) | 	qStr, err := DB.Prepare((`UPDATE "anwesenheit" SET "card_uid" = $2, "geraet_id" = $3, "check_in_out" = $4, "timestamp" = $5 WHERE "counter_id" = $1;`)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|   | |||||||
							
								
								
									
										47
									
								
								Backend/models/booking_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								Backend/models/booking_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | package models_test | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"arbeitszeitmessung/models" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var testBookingType = models.BookingType{ | ||||||
|  | 	Id:   1, | ||||||
|  | 	Name: "Büro", | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var testBookings8hrs = []models.Booking{models.Booking{ | ||||||
|  | 	CardUID:     "aaaa-aaaa", | ||||||
|  | 	CheckInOut:  1, | ||||||
|  | 	Timestamp:   CatchError(time.Parse("2006-01-02 15:04", "2025-01-01 08:00")), | ||||||
|  | 	BookingType: testBookingType, | ||||||
|  | }, models.Booking{ | ||||||
|  | 	CardUID:     "aaaa-aaaa", | ||||||
|  | 	CheckInOut:  2, | ||||||
|  | 	Timestamp:   CatchError(time.Parse("2006-01-02 15:04", "2025-01-01 16:00")), | ||||||
|  | 	BookingType: testBookingType, | ||||||
|  | }} | ||||||
|  |  | ||||||
|  | var testBookings6hrs = []models.Booking{models.Booking{ | ||||||
|  | 	CardUID:     "aaaa-aaaa", | ||||||
|  | 	CheckInOut:  1, | ||||||
|  | 	Timestamp:   CatchError(time.Parse("2006-01-02 15:04", "2025-01-01 08:00")), | ||||||
|  | 	BookingType: testBookingType, | ||||||
|  | }, models.Booking{ | ||||||
|  | 	CardUID:     "aaaa-aaaa", | ||||||
|  | 	CheckInOut:  2, | ||||||
|  | 	Timestamp:   CatchError(time.Parse("2006-01-02 15:04", "2025-01-01 14:00")), | ||||||
|  | 	BookingType: testBookingType, | ||||||
|  | }} | ||||||
|  |  | ||||||
|  | var testBookings10hrs = []models.Booking{models.Booking{ | ||||||
|  | 	CardUID:     "aaaa-aaaa", | ||||||
|  | 	CheckInOut:  1, | ||||||
|  | 	Timestamp:   CatchError(time.Parse("2006-01-02 15:04", "2025-01-01 08:00")), | ||||||
|  | 	BookingType: testBookingType, | ||||||
|  | }, models.Booking{ | ||||||
|  | 	CardUID:     "aaaa-aaaa", | ||||||
|  | 	CheckInOut:  2, | ||||||
|  | 	Timestamp:   CatchError(time.Parse("2006-01-02 15:04", "2025-01-01 18:00")), | ||||||
|  | 	BookingType: testBookingType, | ||||||
|  | }} | ||||||
| @@ -22,6 +22,9 @@ type DBFixture struct { | |||||||
|  |  | ||||||
| func SetupDBFixture(t *testing.T) *DBFixture { | func SetupDBFixture(t *testing.T) *DBFixture { | ||||||
| 	t.Helper() | 	t.Helper() | ||||||
|  | 	if helper.GetEnv("TEST_SQL", "false") != "true" { | ||||||
|  | 		t.Skip("Skipping Test because TEST_SQL is not 'true'!") | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	dbHost := helper.GetEnv("POSTGRES_HOST", "localhost") | 	dbHost := helper.GetEnv("POSTGRES_HOST", "localhost") | ||||||
| 	dbPort := helper.GetEnv("POSTGRES_PORT", "5433") | 	dbPort := helper.GetEnv("POSTGRES_PORT", "5433") | ||||||
|   | |||||||
| @@ -198,17 +198,6 @@ func (u *User) IsTeamLeader() bool { | |||||||
| 	return len(team) > 0 | 	return len(team) > 0 | ||||||
| } | } | ||||||
|  |  | ||||||
| func (u *User) GetWeek(tsFrom time.Time) WorkWeek { |  | ||||||
| 	var bookings []WorkDay |  | ||||||
| 	weekStart := tsFrom.AddDate(0, 0, -1*int(tsFrom.Local().Weekday())-1) |  | ||||||
| 	bookings, err := (*Booking).GetBookingsGrouped(nil, u.CardUID, weekStart, time.Now()) |  | ||||||
| 	if err != nil { |  | ||||||
| 		log.Println("Error fetching bookings!") |  | ||||||
| 		return WorkWeek{WorkDays: bookings} |  | ||||||
| 	} |  | ||||||
| 	return WorkWeek{WorkDays: bookings} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // gets the first week, that needs to be submitted | // gets the first week, that needs to be submitted | ||||||
| func (u *User) GetNextWeek() WorkWeek { | func (u *User) GetNextWeek() WorkWeek { | ||||||
| 	var week WorkWeek | 	var week WorkWeek | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ type WorkDay struct { | |||||||
| 	Absence   Absence | 	Absence   Absence | ||||||
| } | } | ||||||
|  |  | ||||||
| func GetWorkDays(card_uid string, tsFrom, tsTo time.Time) []WorkDay { | func GetWorkDays(user User, tsFrom, tsTo time.Time) []WorkDay { | ||||||
| 	var workDays []WorkDay | 	var workDays []WorkDay | ||||||
| 	var workSec, pauseSec float64 | 	var workSec, pauseSec float64 | ||||||
|  |  | ||||||
| @@ -97,7 +97,7 @@ ORDER BY d.work_date ASC;`) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	defer qStr.Close() | 	defer qStr.Close() | ||||||
| 	rows, err := qStr.Query(card_uid, tsFrom, tsTo) | 	rows, err := qStr.Query(user.CardUID, tsFrom, tsTo) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Println("Error getting rows!") | 		log.Println("Error getting rows!") | ||||||
| 		return workDays | 		return workDays | ||||||
| @@ -125,21 +125,20 @@ ORDER BY d.work_date ASC;`) | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if absenceType.Valid { | 		if absenceType.Valid { | ||||||
| 			workDay.Absence, err = NewAbsence(card_uid, int(absenceType.Int16), workDay.Day) | 			workDay.Absence, err = NewAbsence(user.CardUID, int(absenceType.Int16), workDay.Day) | ||||||
| 			// log.Println("Found absence", workDay.Absence) | 			workDay.CalcRealWorkTime(user) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if workDay.Day.Equal(time.Now().Truncate(24 * time.Hour)) { | 		if workDay.Day.Equal(time.Now().Truncate(24 * time.Hour)) { | ||||||
| 			workDay.getWorkTime() | 			workDay.CalcRealWorkTime(user) | ||||||
|  | 			workDay.CalcWorkPauseDiff(user) | ||||||
| 		} else { | 		} else { | ||||||
| 			workDay.calcPauseTime() | 			workDay.CalcWorkPauseDiff(user) | ||||||
| 		} | 		} | ||||||
| 		if emptyDays && workDay.Day.Weekday() >= 1 && workDay.Day.Weekday() <= 5 { | 		if emptyDays && workDay.Day.Weekday() >= 1 && workDay.Day.Weekday() <= 5 { | ||||||
| 			workDays = append(workDays, workDay) | 			workDays = append(workDays, workDay) | ||||||
| 		} else if len(workDay.Bookings) > 0 || (workDay.Absence != Absence{}) { | 		} else if len(workDay.Bookings) > 0 || (workDay.Absence != Absence{}) { | ||||||
| 			workDays = append(workDays, workDay) | 			workDays = append(workDays, workDay) | ||||||
| 			// } else { |  | ||||||
| 			// 	log.Println("no booking on day", workDay.Day.Format("02.01.2006")) |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if err = rows.Err(); err != nil { | 	if err = rows.Err(); err != nil { | ||||||
| @@ -148,8 +147,16 @@ ORDER BY d.work_date ASC;`) | |||||||
| 	return workDays | 	return workDays | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *WorkDay) calcPauseTime() { | func (d *WorkDay) CalcWorkPauseDiff(user User) (work, pause time.Duration) { | ||||||
| 	if d.workTime > 6*time.Hour && d.pauseTime < 45*time.Minute { | 	if d.workTime == 0 { | ||||||
|  | 		d.CalcRealWorkTime(user) | ||||||
|  | 	} | ||||||
|  | 	if d.Absence.AbwesenheitTyp.WorkTime > 0 { | ||||||
|  | 		return d.workTime, d.pauseTime | ||||||
|  | 	} | ||||||
|  | 	if d.workTime <= 6*time.Hour || d.pauseTime > 45*time.Minute { | ||||||
|  | 		return d.workTime, d.pauseTime | ||||||
|  | 	} | ||||||
| 	if d.workTime <= (9*time.Hour) && d.pauseTime < 30*time.Minute { | 	if d.workTime <= (9*time.Hour) && d.pauseTime < 30*time.Minute { | ||||||
| 		diff := 30*time.Minute - d.pauseTime | 		diff := 30*time.Minute - d.pauseTime | ||||||
| 		d.workTime -= diff | 		d.workTime -= diff | ||||||
| @@ -159,34 +166,36 @@ func (d *WorkDay) calcPauseTime() { | |||||||
| 		d.workTime -= diff | 		d.workTime -= diff | ||||||
| 		d.pauseTime += diff | 		d.pauseTime += diff | ||||||
| 	} | 	} | ||||||
| 	} |  | ||||||
|  | 	return d.workTime, d.pauseTime | ||||||
| } | } | ||||||
|  |  | ||||||
| // Gets the duration someone worked that day | func (d *WorkDay) CalcRealWorkTime(user User) time.Duration { | ||||||
| func (d *WorkDay) getWorkTime() { | 	if (len(d.Bookings) < 1 && d.Absence == Absence{}) { | ||||||
| 	if len(d.Bookings) < 1 { | 		return 0 | ||||||
| 		return |  | ||||||
| 	} | 	} | ||||||
| 	var workTime, pauseTime time.Duration | 	var realWorkTime, realPauseTime time.Duration | ||||||
| 	var lastBooking Booking | 	var lastBooking Booking | ||||||
| 	for _, booking := range d.Bookings { | 	for _, booking := range d.Bookings { | ||||||
| 		if booking.CheckInOut%2 == 1 { | 		if booking.CheckInOut%2 == 1 { | ||||||
| 			if !lastBooking.Timestamp.IsZero() { | 			if !lastBooking.Timestamp.IsZero() { | ||||||
| 				pauseTime += booking.Timestamp.Sub(lastBooking.Timestamp) | 				realPauseTime += booking.Timestamp.Sub(lastBooking.Timestamp) | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			workTime += booking.Timestamp.Sub(lastBooking.Timestamp) | 			realWorkTime += booking.Timestamp.Sub(lastBooking.Timestamp) | ||||||
| 		} | 		} | ||||||
| 		lastBooking = booking | 		lastBooking = booking | ||||||
| 	} | 	} | ||||||
| 	// checks if booking is today and has no gehen yet, so the time since last kommen booking is added to workTime | 	if helper.IsSameDate(d.Day, time.Now()) && len(d.Bookings)%2 == 1 { | ||||||
| 	if d.Day.Day() == time.Now().Day() && len(d.Bookings)%2 == 1 { | 		realWorkTime += time.Since(lastBooking.Timestamp.Local()) | ||||||
| 		workTime += time.Since(lastBooking.Timestamp.Local()) |  | ||||||
| 	} | 	} | ||||||
| 	d.workTime = workTime | 	if d.Absence.AbwesenheitTyp.WorkTime > 0 { | ||||||
| 	d.pauseTime = pauseTime | 		realWorkTime = time.Duration(user.ArbeitszeitPerTag * float32(time.Hour)).Round(time.Minute) | ||||||
|  | 	} | ||||||
|  | 	d.workTime = realWorkTime | ||||||
|  | 	d.pauseTime = realPauseTime | ||||||
|  |  | ||||||
| 	d.calcPauseTime() | 	return realWorkTime | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *WorkDay) GetWorkTimeString() (work string, pause string) { | func (d *WorkDay) GetWorkTimeString() (work string, pause string) { | ||||||
| @@ -195,6 +204,10 @@ func (d *WorkDay) GetWorkTimeString() (work string, pause string) { | |||||||
| 	return workString, pauseString | 	return workString, pauseString | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (d *WorkDay) GetAllWorkTimes(user User) (work, pause, overtime time.Duration) { | ||||||
|  | 	return d.workTime.Round(time.Minute), d.pauseTime.Round(time.Minute), d.CalcOvertime(user) | ||||||
|  | } | ||||||
|  |  | ||||||
| // returns bool wheter the workday was ended with an automatic logout | // returns bool wheter the workday was ended with an automatic logout | ||||||
| func (d *WorkDay) RequiresAction() bool { | func (d *WorkDay) RequiresAction() bool { | ||||||
| 	if len(d.Bookings) == 0 { | 	if len(d.Bookings) == 0 { | ||||||
| @@ -211,15 +224,13 @@ func (d *WorkDay) GetWorkDayProgress(user User) uint8 { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (d *WorkDay) CalcOvertime(user User) time.Duration { | func (d *WorkDay) CalcOvertime(user User) time.Duration { | ||||||
|  | 	if d.workTime == 0 { | ||||||
|  | 		d.CalcWorkPauseDiff(user) | ||||||
|  | 	} | ||||||
| 	if helper.IsWeekend(d.Day) && len(d.Bookings) == 0 { | 	if helper.IsWeekend(d.Day) && len(d.Bookings) == 0 { | ||||||
| 		return 0 | 		return 0 | ||||||
| 	} | 	} | ||||||
| 	var overtime time.Duration | 	var overtime time.Duration | ||||||
| 	overtime = d.workTime - time.Duration(user.ArbeitszeitPerTag*float32(time.Hour)).Round(time.Minute) | 	overtime = d.workTime - time.Duration(user.ArbeitszeitPerTag*float32(time.Hour)).Round(time.Minute) | ||||||
| 	// weekday is WE |  | ||||||
| 	if (d.Absence != Absence{}) { |  | ||||||
| 		overtime = 0 |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return overtime | 	return overtime | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										82
									
								
								Backend/models/workDay_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								Backend/models/workDay_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | |||||||
|  | package models_test | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"arbeitszeitmessung/helper" | ||||||
|  | 	"arbeitszeitmessung/models" | ||||||
|  | 	"log" | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func CatchError[T any](val T, err error) T { | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalln(err) | ||||||
|  | 	} | ||||||
|  | 	return val | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var testWorkDay = models.WorkDay{ | ||||||
|  | 	Day:      CatchError(time.Parse("2006-01-02", "2025-01-01")), | ||||||
|  | 	Bookings: testBookings8hrs, | ||||||
|  | 	TimeFrom: CatchError(time.Parse("2006-01-02 15:04", "2025-01-01 08:00")), | ||||||
|  | 	TimeTo:   CatchError(time.Parse("2006-01-02 15:04", "2025-01-01 16:30")), | ||||||
|  | 	Absence:  models.Absence{}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestCalcRealWorkTime(t *testing.T) { | ||||||
|  | 	workTime := testWorkDay.CalcRealWorkTime(testUser) | ||||||
|  | 	if workTime != time.Hour*8 { | ||||||
|  | 		t.Errorf("Calc Worktime Default not working, time should be 8h, but was %s", helper.FormatDuration(workTime)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestCalcWorkPauseDiff(t *testing.T) { | ||||||
|  | 	type testCase struct { | ||||||
|  | 		Name              string | ||||||
|  | 		bookings          []models.Booking | ||||||
|  | 		expectedWorkTime  time.Duration | ||||||
|  | 		expectedPauseTime time.Duration | ||||||
|  | 		expectedOvertime  time.Duration | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	testCases := []testCase{testCase{ | ||||||
|  | 		Name:              "6hrs no pause", | ||||||
|  | 		bookings:          testBookings6hrs, | ||||||
|  | 		expectedWorkTime:  6 * time.Hour, | ||||||
|  | 		expectedPauseTime: 0, | ||||||
|  | 		expectedOvertime:  -2 * time.Hour, | ||||||
|  | 	}, | ||||||
|  | 		testCase{ | ||||||
|  | 			Name:              "8hrs - 30min pause", | ||||||
|  | 			bookings:          testBookings8hrs, | ||||||
|  | 			expectedWorkTime:  7*time.Hour + 30*time.Minute, | ||||||
|  | 			expectedPauseTime: 30 * time.Minute, | ||||||
|  | 			expectedOvertime:  -30 * time.Minute, | ||||||
|  | 		}, | ||||||
|  | 		testCase{ | ||||||
|  | 			Name:              "10hrs - 45min pause", | ||||||
|  | 			bookings:          testBookings10hrs, | ||||||
|  | 			expectedWorkTime:  9*time.Hour + 15*time.Minute, | ||||||
|  | 			expectedPauseTime: 45 * time.Minute, | ||||||
|  | 			expectedOvertime:  1*time.Hour + 15*time.Minute, | ||||||
|  | 		}} | ||||||
|  |  | ||||||
|  | 	for _, test := range testCases { | ||||||
|  | 		t.Run(test.Name, func(t *testing.T) { | ||||||
|  | 			testWorkDay.Bookings = test.bookings | ||||||
|  | 			testWorkDay.CalcRealWorkTime(testUser) | ||||||
|  | 			testWorkDay.CalcWorkPauseDiff(testUser) | ||||||
|  | 			testWorkDay.CalcOvertime(testUser) | ||||||
|  | 			workTime, pauseTime, overTime := testWorkDay.GetAllWorkTimes(testUser) | ||||||
|  | 			if workTime != test.expectedWorkTime { | ||||||
|  | 				t.Errorf("Calculated wrong workTime: should be %s, but was %s", helper.FormatDuration(test.expectedWorkTime), helper.FormatDuration(workTime)) | ||||||
|  | 			} | ||||||
|  | 			if pauseTime != test.expectedPauseTime { | ||||||
|  | 				t.Errorf("Calculated wrong pauseTime: should be %s, but was %s", helper.FormatDuration(test.expectedPauseTime), helper.FormatDuration(pauseTime)) | ||||||
|  | 			} | ||||||
|  | 			if overTime != test.expectedOvertime { | ||||||
|  | 				t.Errorf("Calculated wrong overtime: should be %s, but was %s", helper.FormatDuration(test.expectedOvertime), helper.FormatDuration(overTime)) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -45,7 +45,7 @@ func NewWorkWeek(user User, tsMonday time.Time, populate bool) WorkWeek { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (w *WorkWeek) PopulateWithBookings(worktime time.Duration, overtime time.Duration) { | func (w *WorkWeek) PopulateWithBookings(worktime time.Duration, overtime time.Duration) { | ||||||
| 	w.WorkDays = GetWorkDays(w.User.CardUID, w.WeekStart, w.WeekStart.Add(7*24*time.Hour)) | 	w.WorkDays = GetWorkDays(w.User, w.WeekStart, w.WeekStart.Add(7*24*time.Hour)) | ||||||
| 	if absences, err := GetAbsencesByCardUID(w.User.CardUID, w.WeekStart, w.WeekStart.Add(7*24*time.Hour)); err == nil { | 	if absences, err := GetAbsencesByCardUID(w.User.CardUID, w.WeekStart, w.WeekStart.Add(7*24*time.Hour)); err == nil { | ||||||
| 		w.Absences = absences | 		w.Absences = absences | ||||||
| 	} else { | 	} else { | ||||||
| @@ -108,10 +108,11 @@ func (w *WorkWeek) aggregateWorkTime() time.Duration { | |||||||
| 	for _, day := range w.WorkDays { | 	for _, day := range w.WorkDays { | ||||||
| 		workTime += day.workTime | 		workTime += day.workTime | ||||||
| 	} | 	} | ||||||
| 	for _, absences := range w.Absences { | 	// for _, absence := range w.Absences { | ||||||
| 		absenceWorkTime := absences.AbwesenheitTyp.WorkTime - (absences.AbwesenheitTyp.WorkTime - w.User.ArbeitszeitPerTag) // workTime Equivalent of Absence is capped at user Worktime per Day | 	// 	log.Println(absence) | ||||||
| 		workTime += time.Duration(absenceWorkTime * float32(time.Hour)).Round(time.Minute) | 	// 	absenceWorkTime := float32(8) // := absences.AbwesenheitTyp.WorkTime - (absences.AbwesenheitTyp.WorkTime - w.User.ArbeitszeitPerTag) // workTime Equivalent of Absence is capped at user Worktime per Day | ||||||
| 	} | 	// 	workTime += time.Duration(absenceWorkTime * float32(time.Hour)).Round(time.Minute) | ||||||
|  | 	// } | ||||||
| 	return workTime | 	return workTime | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -28,6 +28,7 @@ func TestNewWorkWeekNoPopulate(t *testing.T) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func TestCheckStatus(t *testing.T) { | func TestCheckStatus(t *testing.T) { | ||||||
|  | 	SetupDBFixture(t) | ||||||
| 	testWeek := SetupWorkWeekFixture(t) | 	testWeek := SetupWorkWeekFixture(t) | ||||||
| 	testCases := []struct { | 	testCases := []struct { | ||||||
| 		name       string | 		name       string | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| @import "tailwindcss"; | @import "tailwindcss"; | ||||||
| @source "../templates/*.templ"; | @source "../templates/*.templ"; | ||||||
| @plugin "@iconify/tailwind4" { | @plugin "@iconify/tailwind4" { | ||||||
|     scale: 1.5; |   scale: 1.25; | ||||||
| } | } | ||||||
|  |  | ||||||
| @theme { | @theme { | ||||||
| @@ -30,6 +30,13 @@ | |||||||
|   --color-text-950: #000000; |   --color-text-950: #000000; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @layer base { | ||||||
|  |   body { | ||||||
|  |     -webkit-print-color-adjust: exact !important; | ||||||
|  |     print-color-adjust: exact !important; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| @layer components { | @layer components { | ||||||
|   .grid-main { |   .grid-main { | ||||||
|     display: grid; |     display: grid; | ||||||
| @@ -70,8 +77,14 @@ | |||||||
|     border-style: var(--tw-border-style); |     border-style: var(--tw-border-style); | ||||||
|     border-width: 1px; |     border-width: 1px; | ||||||
|     border-color: var(--color-neutral-800); |     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-property: | ||||||
|         transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); |       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)); |     transition-duration: var(--tw-duration, var(--default-transition-duration)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -16,6 +16,7 @@ | |||||||
|     --color-neutral-300: oklch(87% 0 0); |     --color-neutral-300: oklch(87% 0 0); | ||||||
|     --color-neutral-400: oklch(70.8% 0 0); |     --color-neutral-400: oklch(70.8% 0 0); | ||||||
|     --color-neutral-500: oklch(55.6% 0 0); |     --color-neutral-500: oklch(55.6% 0 0); | ||||||
|  |     --color-neutral-600: oklch(43.9% 0 0); | ||||||
|     --color-neutral-700: oklch(37.1% 0 0); |     --color-neutral-700: oklch(37.1% 0 0); | ||||||
|     --color-neutral-800: oklch(26.9% 0 0); |     --color-neutral-800: oklch(26.9% 0 0); | ||||||
|     --color-neutral-900: oklch(20.5% 0 0); |     --color-neutral-900: oklch(20.5% 0 0); | ||||||
| @@ -198,12 +199,6 @@ | |||||||
|   .col-span-3 { |   .col-span-3 { | ||||||
|     grid-column: span 3 / span 3; |     grid-column: span 3 / span 3; | ||||||
|   } |   } | ||||||
|   .col-span-6 { |  | ||||||
|     grid-column: span 6 / span 6; |  | ||||||
|   } |  | ||||||
|   .col-span-7 { |  | ||||||
|     grid-column: span 7 / span 7; |  | ||||||
|   } |  | ||||||
|   .col-span-full { |   .col-span-full { | ||||||
|     grid-column: 1 / -1; |     grid-column: 1 / -1; | ||||||
|   } |   } | ||||||
| @@ -221,8 +216,8 @@ | |||||||
|   } |   } | ||||||
|   .icon-\[material-symbols-light--add-circle-outline\] { |   .icon-\[material-symbols-light--add-circle-outline\] { | ||||||
|     display: inline-block; |     display: inline-block; | ||||||
|     width: 1.5em; |     width: 1.25em; | ||||||
|     height: 1.5em; |     height: 1.25em; | ||||||
|     background-color: currentColor; |     background-color: currentColor; | ||||||
|     -webkit-mask-image: var(--svg); |     -webkit-mask-image: var(--svg); | ||||||
|     mask-image: var(--svg); |     mask-image: var(--svg); | ||||||
| @@ -234,8 +229,8 @@ | |||||||
|   } |   } | ||||||
|   .icon-\[material-symbols-light--check-circle-outline\] { |   .icon-\[material-symbols-light--check-circle-outline\] { | ||||||
|     display: inline-block; |     display: inline-block; | ||||||
|     width: 1.5em; |     width: 1.25em; | ||||||
|     height: 1.5em; |     height: 1.25em; | ||||||
|     background-color: currentColor; |     background-color: currentColor; | ||||||
|     -webkit-mask-image: var(--svg); |     -webkit-mask-image: var(--svg); | ||||||
|     mask-image: var(--svg); |     mask-image: var(--svg); | ||||||
| @@ -247,8 +242,8 @@ | |||||||
|   } |   } | ||||||
|   .icon-\[material-symbols-light--circle-outline\] { |   .icon-\[material-symbols-light--circle-outline\] { | ||||||
|     display: inline-block; |     display: inline-block; | ||||||
|     width: 1.5em; |     width: 1.25em; | ||||||
|     height: 1.5em; |     height: 1.25em; | ||||||
|     background-color: currentColor; |     background-color: currentColor; | ||||||
|     -webkit-mask-image: var(--svg); |     -webkit-mask-image: var(--svg); | ||||||
|     mask-image: var(--svg); |     mask-image: var(--svg); | ||||||
| @@ -260,8 +255,8 @@ | |||||||
|   } |   } | ||||||
|   .icon-\[material-symbols-light--more-time\] { |   .icon-\[material-symbols-light--more-time\] { | ||||||
|     display: inline-block; |     display: inline-block; | ||||||
|     width: 1.5em; |     width: 1.25em; | ||||||
|     height: 1.5em; |     height: 1.25em; | ||||||
|     background-color: currentColor; |     background-color: currentColor; | ||||||
|     -webkit-mask-image: var(--svg); |     -webkit-mask-image: var(--svg); | ||||||
|     mask-image: var(--svg); |     mask-image: var(--svg); | ||||||
| @@ -273,8 +268,8 @@ | |||||||
|   } |   } | ||||||
|   .icon-\[material-symbols-light--motion-photos-paused-outline\] { |   .icon-\[material-symbols-light--motion-photos-paused-outline\] { | ||||||
|     display: inline-block; |     display: inline-block; | ||||||
|     width: 1.5em; |     width: 1.25em; | ||||||
|     height: 1.5em; |     height: 1.25em; | ||||||
|     background-color: currentColor; |     background-color: currentColor; | ||||||
|     -webkit-mask-image: var(--svg); |     -webkit-mask-image: var(--svg); | ||||||
|     mask-image: var(--svg); |     mask-image: var(--svg); | ||||||
| @@ -284,6 +279,19 @@ | |||||||
|     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='M9.808 14.616h1V9.385h-1zm3.384 0h1V9.385h-1zM12.003 21q-1.866 0-3.51-.705q-1.643-.706-2.859-1.915t-1.925-2.843T3 12.039q0-.905.167-1.778t.497-1.713l.78.78q-.219.65-.331 1.32T4 12q0 3.35 2.325 5.675T12 20t5.675-2.325T20 12t-2.325-5.675T12 4q-.675 0-1.332.112t-1.3.332l-.776-.775q.789-.315 1.606-.492T11.885 3q1.887 0 3.546.701t2.894 1.926t1.955 2.866t.72 3.505t-.708 3.509t-1.924 2.859t-2.856 1.925t-3.509.709M5.923 6.808q-.356 0-.62-.265q-.264-.264-.264-.62t.264-.62t.62-.264t.62.264t.265.62t-.265.62t-.62.265M12 12'/%3E%3C/svg%3E"); |     --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='M9.808 14.616h1V9.385h-1zm3.384 0h1V9.385h-1zM12.003 21q-1.866 0-3.51-.705q-1.643-.706-2.859-1.915t-1.925-2.843T3 12.039q0-.905.167-1.778t.497-1.713l.78.78q-.219.65-.331 1.32T4 12q0 3.35 2.325 5.675T12 20t5.675-2.325T20 12t-2.325-5.675T12 4q-.675 0-1.332.112t-1.3.332l-.776-.775q.789-.315 1.606-.492T11.885 3q1.887 0 3.546.701t2.894 1.926t1.955 2.866t.72 3.505t-.708 3.509t-1.924 2.859t-2.856 1.925t-3.509.709M5.923 6.808q-.356 0-.62-.265q-.264-.264-.264-.62t.264-.62t.62-.264t.62.264t.265.62t-.265.62t-.62.265M12 12'/%3E%3C/svg%3E"); | ||||||
|   } |   } | ||||||
|  |   .icon-\[material-symbols-light--nest-clock-farsight-analog-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='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"); | ||||||
|  |   } | ||||||
|   .flex { |   .flex { | ||||||
|     display: flex; |     display: flex; | ||||||
|   } |   } | ||||||
| @@ -322,15 +330,15 @@ | |||||||
|   .h-full { |   .h-full { | ||||||
|     height: 100%; |     height: 100%; | ||||||
|   } |   } | ||||||
|  |   .w-1\/7 { | ||||||
|  |     width: calc(1/7 * 100%); | ||||||
|  |   } | ||||||
|   .w-2 { |   .w-2 { | ||||||
|     width: calc(var(--spacing) * 2); |     width: calc(var(--spacing) * 2); | ||||||
|   } |   } | ||||||
|   .w-4 { |   .w-4 { | ||||||
|     width: calc(var(--spacing) * 4); |     width: calc(var(--spacing) * 4); | ||||||
|   } |   } | ||||||
|   .w-9 { |  | ||||||
|     width: calc(var(--spacing) * 9); |  | ||||||
|   } |  | ||||||
|   .w-9\/10 { |   .w-9\/10 { | ||||||
|     width: calc(9/10 * 100%); |     width: calc(9/10 * 100%); | ||||||
|   } |   } | ||||||
| @@ -343,9 +351,6 @@ | |||||||
|   .w-full { |   .w-full { | ||||||
|     width: 100%; |     width: 100%; | ||||||
|   } |   } | ||||||
|   .flex-shrink { |  | ||||||
|     flex-shrink: 1; |  | ||||||
|   } |  | ||||||
|   .flex-shrink-0 { |   .flex-shrink-0 { | ||||||
|     flex-shrink: 0; |     flex-shrink: 0; | ||||||
|   } |   } | ||||||
| @@ -364,8 +369,11 @@ | |||||||
|   .cursor-pointer { |   .cursor-pointer { | ||||||
|     cursor: pointer; |     cursor: pointer; | ||||||
|   } |   } | ||||||
|   .resize { |   .break-after-page { | ||||||
|     resize: both; |     break-after: page; | ||||||
|  |   } | ||||||
|  |   .auto-rows-min { | ||||||
|  |     grid-auto-rows: min-content; | ||||||
|   } |   } | ||||||
|   .grid-cols-2 { |   .grid-cols-2 { | ||||||
|     grid-template-columns: repeat(2, minmax(0, 1fr)); |     grid-template-columns: repeat(2, minmax(0, 1fr)); | ||||||
| @@ -373,11 +381,8 @@ | |||||||
|   .grid-cols-5 { |   .grid-cols-5 { | ||||||
|     grid-template-columns: repeat(5, minmax(0, 1fr)); |     grid-template-columns: repeat(5, minmax(0, 1fr)); | ||||||
|   } |   } | ||||||
|   .grid-cols-\[auto_1fr_1fr_1fr_1fr_1fr\] { |   .grid-cols-\[3fr_2fr_2fr_2fr_3fr_3fr_3fr\] { | ||||||
|     grid-template-columns: auto 1fr 1fr 1fr 1fr 1fr; |     grid-template-columns: 3fr 2fr 2fr 2fr 3fr 3fr 3fr; | ||||||
|   } |  | ||||||
|   .grid-cols-\[auto_1fr_1fr_1fr_1fr_1fr_1fr\] { |  | ||||||
|     grid-template-columns: auto 1fr 1fr 1fr 1fr 1fr 1fr; |  | ||||||
|   } |   } | ||||||
|   .grid-cols-subgrid { |   .grid-cols-subgrid { | ||||||
|     grid-template-columns: subgrid; |     grid-template-columns: subgrid; | ||||||
| @@ -432,6 +437,11 @@ | |||||||
|       border-bottom-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); |       border-bottom-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |   .divide-neutral-300 { | ||||||
|  |     :where(& > :not(:last-child)) { | ||||||
|  |       border-color: var(--color-neutral-300); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|   .justify-self-end { |   .justify-self-end { | ||||||
|     justify-self: flex-end; |     justify-self: flex-end; | ||||||
|   } |   } | ||||||
| @@ -448,12 +458,35 @@ | |||||||
|     border-style: var(--tw-border-style); |     border-style: var(--tw-border-style); | ||||||
|     border-width: 1px; |     border-width: 1px; | ||||||
|   } |   } | ||||||
|  |   .border-1 { | ||||||
|  |     border-style: var(--tw-border-style); | ||||||
|  |     border-width: 1px; | ||||||
|  |   } | ||||||
|  |   .border-t-1 { | ||||||
|  |     border-top-style: var(--tw-border-style); | ||||||
|  |     border-top-width: 1px; | ||||||
|  |   } | ||||||
|  |   .border-r-0 { | ||||||
|  |     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; | ||||||
|  |   } | ||||||
|   .border-neutral-200 { |   .border-neutral-200 { | ||||||
|     border-color: var(--color-neutral-200); |     border-color: var(--color-neutral-200); | ||||||
|   } |   } | ||||||
|   .border-neutral-300 { |   .border-neutral-300 { | ||||||
|     border-color: var(--color-neutral-300); |     border-color: var(--color-neutral-300); | ||||||
|   } |   } | ||||||
|  |   .border-neutral-600 { | ||||||
|  |     border-color: var(--color-neutral-600); | ||||||
|  |   } | ||||||
|   .border-neutral-900 { |   .border-neutral-900 { | ||||||
|     border-color: var(--color-neutral-900); |     border-color: var(--color-neutral-900); | ||||||
|   } |   } | ||||||
| @@ -478,12 +511,6 @@ | |||||||
|   .bg-red-600 { |   .bg-red-600 { | ||||||
|     background-color: var(--color-red-600); |     background-color: var(--color-red-600); | ||||||
|   } |   } | ||||||
|   .mask-repeat { |  | ||||||
|     mask-repeat: repeat; |  | ||||||
|   } |  | ||||||
|   .p-0 { |  | ||||||
|     padding: calc(var(--spacing) * 0); |  | ||||||
|   } |  | ||||||
|   .p-1 { |   .p-1 { | ||||||
|     padding: calc(var(--spacing) * 1); |     padding: calc(var(--spacing) * 1); | ||||||
|   } |   } | ||||||
| @@ -493,9 +520,6 @@ | |||||||
|   .p-8 { |   .p-8 { | ||||||
|     padding: calc(var(--spacing) * 8); |     padding: calc(var(--spacing) * 8); | ||||||
|   } |   } | ||||||
|   .px-2 { |  | ||||||
|     padding-inline: calc(var(--spacing) * 2); |  | ||||||
|   } |  | ||||||
|   .px-3 { |   .px-3 { | ||||||
|     padding-inline: calc(var(--spacing) * 3); |     padding-inline: calc(var(--spacing) * 3); | ||||||
|   } |   } | ||||||
| @@ -530,6 +554,9 @@ | |||||||
|   .text-accent { |   .text-accent { | ||||||
|     color: var(--color-accent); |     color: var(--color-accent); | ||||||
|   } |   } | ||||||
|  |   .text-neutral-300 { | ||||||
|  |     color: var(--color-neutral-300); | ||||||
|  |   } | ||||||
|   .text-neutral-500 { |   .text-neutral-500 { | ||||||
|     color: var(--color-neutral-500); |     color: var(--color-neutral-500); | ||||||
|   } |   } | ||||||
| @@ -548,13 +575,6 @@ | |||||||
|   .uppercase { |   .uppercase { | ||||||
|     text-transform: uppercase; |     text-transform: uppercase; | ||||||
|   } |   } | ||||||
|   .underline { |  | ||||||
|     text-decoration-line: underline; |  | ||||||
|   } |  | ||||||
|   .outline { |  | ||||||
|     outline-style: var(--tw-outline-style); |  | ||||||
|     outline-width: 1px; |  | ||||||
|   } |  | ||||||
|   .filter { |   .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,); |     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,); | ||||||
|   } |   } | ||||||
| @@ -572,6 +592,28 @@ | |||||||
|     --tw-duration: 300ms; |     --tw-duration: 300ms; | ||||||
|     transition-duration: 300ms; |     transition-duration: 300ms; | ||||||
|   } |   } | ||||||
|  |   .\*\:\*\:\*\:border-1 { | ||||||
|  |     :is(& > *) { | ||||||
|  |       :is(& > *) { | ||||||
|  |         :is(& > *) { | ||||||
|  |           border-style: var(--tw-border-style); | ||||||
|  |           border-width: 1px; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   .\*\:text-center { | ||||||
|  |     :is(& > *) { | ||||||
|  |       text-align: center; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   .\*\:not-print\:p-2 { | ||||||
|  |     :is(& > *) { | ||||||
|  |       @media not print { | ||||||
|  |         padding: calc(var(--spacing) * 2); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|   .group-hover\:text-black { |   .group-hover\:text-black { | ||||||
|     &:is(:where(.group):hover *) { |     &:is(:where(.group):hover *) { | ||||||
|       @media (hover: hover) { |       @media (hover: hover) { | ||||||
| @@ -832,6 +874,12 @@ | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | @layer base { | ||||||
|  |   body { | ||||||
|  |     -webkit-print-color-adjust: exact !important; | ||||||
|  |     print-color-adjust: exact !important; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @layer components { | @layer components { | ||||||
|   .grid-main { |   .grid-main { | ||||||
|     display: grid; |     display: grid; | ||||||
| @@ -868,7 +916,7 @@ | |||||||
|     border-width: 1px; |     border-width: 1px; | ||||||
|     border-color: var(--color-neutral-800); |     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-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)); |     transition-duration: var(--tw-duration, var(--default-transition-duration)); | ||||||
|   } |   } | ||||||
|   .btn:hover { |   .btn:hover { | ||||||
| @@ -914,11 +962,6 @@ | |||||||
|   syntax: "*"; |   syntax: "*"; | ||||||
|   inherits: false; |   inherits: false; | ||||||
| } | } | ||||||
| @property --tw-outline-style { |  | ||||||
|   syntax: "*"; |  | ||||||
|   inherits: false; |  | ||||||
|   initial-value: solid; |  | ||||||
| } |  | ||||||
| @property --tw-blur { | @property --tw-blur { | ||||||
|   syntax: "*"; |   syntax: "*"; | ||||||
|   inherits: false; |   inherits: false; | ||||||
| @@ -983,7 +1026,6 @@ | |||||||
|       --tw-border-style: solid; |       --tw-border-style: solid; | ||||||
|       --tw-divide-y-reverse: 0; |       --tw-divide-y-reverse: 0; | ||||||
|       --tw-font-weight: initial; |       --tw-font-weight: initial; | ||||||
|       --tw-outline-style: solid; |  | ||||||
|       --tw-blur: initial; |       --tw-blur: initial; | ||||||
|       --tw-brightness: initial; |       --tw-brightness: initial; | ||||||
|       --tw-contrast: initial; |       --tw-contrast: initial; | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // Code generated by templ - DO NOT EDIT. | // Code generated by templ - DO NOT EDIT. | ||||||
|  |  | ||||||
| // templ: version: v0.3.833 | // templ: version: v0.3.943 | ||||||
| package templates | package templates | ||||||
|  |  | ||||||
| //lint:file-ignore SA4006 This context is only used if a nested component is present. | //lint:file-ignore SA4006 This context is only used if a nested component is present. | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // Code generated by templ - DO NOT EDIT. | // Code generated by templ - DO NOT EDIT. | ||||||
|  |  | ||||||
| // templ: version: v0.3.833 | // templ: version: v0.3.943 | ||||||
| package templates | package templates | ||||||
|  |  | ||||||
| //lint:file-ignore SA4006 This context is only used if a nested component is present. | //lint:file-ignore SA4006 This context is only used if a nested component is present. | ||||||
|   | |||||||
| @@ -1,50 +1,200 @@ | |||||||
| package templates | package templates | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"arbeitszeitmessung/models" |  | ||||||
| 	"arbeitszeitmessung/helper" | 	"arbeitszeitmessung/helper" | ||||||
|  | 	"arbeitszeitmessung/models" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| templ PDFReportEmploye(e models.User, workDays []models.WorkDay, tsStart time.Time, tsEnd time.Time) { | templ PDFReportEmploye(e models.User, workDays []models.WorkDay, tsStart time.Time, tsEnd time.Time) { | ||||||
| 	{{ | 	{{ | ||||||
| 		_, kw := tsStart.ISOWeek() | 		_, kw := tsStart.ISOWeek() | ||||||
|  | 		noBorder := "" | ||||||
| 	}} | 	}} | ||||||
| 	@Base() | 	@Base() | ||||||
| 	<content class="p-8 relative flex flex-col gap-4"> | 	<content class="p-8 relative flex flex-col gap-4 break-after-page"> | ||||||
| 		<div> | 		<div> | ||||||
| 			<h1 class="text-2xl font-bold">Kim Mustermensch</h1> | 			<h1 class="text-2xl font-bold">Kim Mustermensch</h1> | ||||||
| 			<p>Zeitraum: <span>{ tsStart.Format("02.01.2006") }</span> - <span>{ tsEnd.Format("02.01.2006") }</span></p> | 			<p>Zeitraum: <span>{ tsStart.Format("02.01.2006") }</span> - <span>{ tsEnd.Format("02.01.2006") }</span></p> | ||||||
| 			<p>Arbeitszeit: <span></span></p> | 			<p>Arbeitszeit: <span></span></p> | ||||||
| 			<p>Überstunden: <span></span></p> | 			<p>Überstunden: <span></span></p> | ||||||
| 		</div> | 		</div> | ||||||
| 		<div class="grid grid-rows-6 grid-cols-[auto_1fr_1fr_1fr_1fr_1fr_1fr] divide-x-1 divide-y-1"> | 		<div class="grid grid-rows-6 grid-cols-[3fr_2fr_2fr_2fr_3fr_3fr_3fr] *:not-print:p-2 *:text-center auto-rows-min divide-neutral-300 divide-x-1 divide-y-1"> | ||||||
| 			<p class="p-2 text-center">{ kw }</p> | 			<p class="bg-neutral-300 border-neutral-600">{ kw }</p> | ||||||
| 			<p class="p-2 text-center">Kommen</p> | 			<p class="bg-neutral-300 border-neutral-600">Kommen</p> | ||||||
| 			<p class="p-2 text-center">Gehen</p> | 			<p class="bg-neutral-300 border-neutral-600">Gehen</p> | ||||||
| 			<p class="p-2 text-center">Arbeitsart</p> | 			<p class="bg-neutral-300 border-neutral-600">Arbeitsart</p> | ||||||
| 			<p class="p-2 text-center">Stunden gesamt</p> | 			<p class="bg-neutral-300 border-neutral-600">Stunden</p> | ||||||
| 			<p class="p-2 text-center">Pause</p> | 			<p class="bg-neutral-300 border-neutral-600">Pause</p> | ||||||
| 			<p class="p-2 text-center">Überstunden</p> | 			<p class="bg-neutral-300 border-neutral-600 border-r-0">Überstunden</p> | ||||||
| 			for _, day := range workDays{ | 			for index, day := range workDays { | ||||||
| 				if day.Day.Weekday() == time.Monday { | 				{{ | ||||||
| 					<p class="p-2 col-span-7 text-center bg-neutral-300">Wochenende</p> | 					if index == len(workDays)-1 { | ||||||
|  | 						noBorder = "border-b-0" | ||||||
| 					} | 					} | ||||||
| 				<p class="p-2 text-center">{ day.Day.Format("02.01.2006") }</p> | 				}} | ||||||
|  | 				<p class={ noBorder }>{ day.Day.Format("02.01.2006") }</p> | ||||||
|  |  | ||||||
| 				<div class="grid grid-cols-subgrid col-span-3"> | 				<div class={ "grid grid-cols-subgrid col-span-3 " + noBorder }> | ||||||
| 					for bookingI := 0; bookingI < len(day.Bookings); bookingI+= 2 { | 					for bookingI := 0; bookingI < len(day.Bookings); bookingI+= 2 { | ||||||
| 					<p class="p-2 text-center">{ day.Bookings[bookingI].Timestamp.Format("15:04") }</p> | 						<p>{ day.Bookings[bookingI].Timestamp.Format("15:04") }</p> | ||||||
| 					<p class="p-2 text-center">{ day.Bookings[bookingI+1].Timestamp.Format("15:04") }</p> | 						<p>{ day.Bookings[bookingI+1].Timestamp.Format("15:04") }</p> | ||||||
| 					<p class="p-2 text-center">{ day.Bookings[bookingI].BookingType.Name } </p> | 						<p>{ day.Bookings[bookingI].BookingType.Name } </p> | ||||||
|  | 					} | ||||||
|  | 					if (day.Absence != models.Absence{}) { | ||||||
|  | 						<p class="col-span-full">{ day.Absence.AbwesenheitTyp.Name }</p> | ||||||
| 					} | 					} | ||||||
| 				</div> | 				</div> | ||||||
| 				{{ work, pause := day.GetWorkTimeString() }} | 				{{ work, pause, overtime := day.GetAllWorkTimes(e) }} | ||||||
| 					<p class="p-2 text-center">{ work }</p> | 				@ColorDuration(work, noBorder) | ||||||
| 					<p class="p-2 text-center">{ pause }</p> | 				@ColorDuration(pause, noBorder) | ||||||
| 					<p class="p-2 text-center">{ helper.FormatDuration(day.CalcOvertime(e)) }</p> | 				@ColorDuration(overtime, noBorder + " border-r-0") | ||||||
|  | 				if day.Day.Weekday() == time.Friday { | ||||||
|  | 					<p class="col-span-full bg-neutral-300">Wochenende</p> | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 		</div> | 		</div> | ||||||
| 	</content> | 	</content> | ||||||
| } | } | ||||||
|  |  | ||||||
|  | templ PDFReportEmployeTable(e models.User, workDays []models.WorkDay, tsStart time.Time, tsEnd time.Time) { | ||||||
|  | 	{{ | ||||||
|  | 		_, kw := tsStart.ISOWeek() | ||||||
|  | 		noBorder := "" | ||||||
|  | 	}} | ||||||
|  | 	@Base() | ||||||
|  | 	<content class="p-8 relative flex flex-col gap-4 break-after-page"> | ||||||
|  | 		<div> | ||||||
|  | 			<h1 class="text-2xl font-bold">Kim Mustermensch</h1> | ||||||
|  | 			<p>Zeitraum: <span>{ tsStart.Format("02.01.2006") }</span> - <span>{ tsEnd.Format("02.01.2006") }</span></p> | ||||||
|  | 			<p>Arbeitszeit: <span></span></p> | ||||||
|  | 			<p>Überstunden: <span></span></p> | ||||||
|  | 		</div> | ||||||
|  | 		<table class="*:*:*:border-1 *:text-center border-1 border-collapse"> | ||||||
|  | 			<tr> | ||||||
|  | 				<th class="bg-neutral-300 border-neutral-600 w-1/7">{ kw }</th> | ||||||
|  | 				<th class="bg-neutral-300 border-neutral-600 w-1/7">Kommen</th> | ||||||
|  | 				<th class="bg-neutral-300 border-neutral-600 w-1/7">Gehen</th> | ||||||
|  | 				<th class="bg-neutral-300 border-neutral-600 w-1/7">Arbeitsart</th> | ||||||
|  | 				<th class="bg-neutral-300 border-neutral-600 w-1/7">Stunden</th> | ||||||
|  | 				<th class="bg-neutral-300 border-neutral-600 w-1/7">Pause</th> | ||||||
|  | 				<th class="bg-neutral-300 border-neutral-600 w-1/7 border-r-0">Überstunden</th> | ||||||
|  | 			</tr> | ||||||
|  | 			for index, day := range workDays { | ||||||
|  | 				{{ | ||||||
|  | 					if index == len(workDays)-1 { | ||||||
|  | 						noBorder = "border-b-0" | ||||||
|  | 					} | ||||||
|  | 				}} | ||||||
|  | 				<tr> | ||||||
|  | 					<td class={ noBorder }>{ day.Day.Format("02.01.2006") }</td> | ||||||
|  | 					<td colspan="3"> | ||||||
|  | 				<table  class={ "w-full border-collapse" + noBorder }> | ||||||
|  | 					for bookingI := 0; bookingI < len(day.Bookings); bookingI+= 2 { | ||||||
|  | 						<tr class="flex"> | ||||||
|  | 							<td class="border-r-1 grow">{ day.Bookings[bookingI].Timestamp.Format("15:04") }</td> | ||||||
|  | 							<td class="border-r-1 grow">{ day.Bookings[bookingI+1].Timestamp.Format("15:04") }</td> | ||||||
|  | 							<td class="grow">{ day.Bookings[bookingI].BookingType.Name } </td> | ||||||
|  | 						</tr> | ||||||
|  | 					} | ||||||
|  | 					if (day.Absence != models.Absence{}) { | ||||||
|  | 						if len(day.Bookings) > 0 { | ||||||
|  | 						<tr class="border-t-1"> | ||||||
|  | 							<td colspan="2" class="col-span-full">{ day.Absence.AbwesenheitTyp.Name }</td> | ||||||
|  | 						</tr> | ||||||
|  | 						} | ||||||
|  | 						else { | ||||||
|  | 						<tr> | ||||||
|  | 							<td colspan="2" class="col-span-full">{ day.Absence.AbwesenheitTyp.Name }</td> | ||||||
|  | 						</tr> | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 					} | ||||||
|  | 				</table> | ||||||
|  | 					</td> | ||||||
|  | 				{{ work, pause, overtime := day.GetAllWorkTimes(e) }} | ||||||
|  | 				@ColorDuration(work, noBorder) | ||||||
|  | 				@ColorDuration(pause, noBorder) | ||||||
|  | 				@ColorDuration(overtime, noBorder + " border-r-0") | ||||||
|  | 				if day.Day.Weekday() == time.Friday { | ||||||
|  | 					<tr> | ||||||
|  | 					<td colspan="7" class="col-span-full bg-neutral-300">Wochenende</td> | ||||||
|  | 					</tr> | ||||||
|  | 				} | ||||||
|  | 				</tr> | ||||||
|  | 			} | ||||||
|  | 		</table> | ||||||
|  | 	</content> | ||||||
|  | 	<div class="p-8 relative flex flex-col gap-4 break-after-page"> | ||||||
|  | 		<div> | ||||||
|  | 			<h1 class="text-2xl font-bold">Kim Mustermensch</h1> | ||||||
|  | 			<p>Zeitraum: <span>{ tsStart.Format("02.01.2006") }</span> - <span>{ tsEnd.Format("02.01.2006") }</span></p> | ||||||
|  | 			<p>Arbeitszeit: <span></span></p> | ||||||
|  | 			<p>Überstunden: <span></span></p> | ||||||
|  | 		</div> | ||||||
|  | 		<table class="*:*:*:border-1 *:text-center border-1 border-collapse"> | ||||||
|  | 			<tr> | ||||||
|  | 				<th class="bg-neutral-300 border-neutral-600 w-1/7">{ kw }</th> | ||||||
|  | 				<th class="bg-neutral-300 border-neutral-600 w-1/7">Kommen</th> | ||||||
|  | 				<th class="bg-neutral-300 border-neutral-600 w-1/7">Gehen</th> | ||||||
|  | 				<th class="bg-neutral-300 border-neutral-600 w-1/7">Arbeitsart</th> | ||||||
|  | 				<th class="bg-neutral-300 border-neutral-600 w-1/7">Stunden</th> | ||||||
|  | 				<th class="bg-neutral-300 border-neutral-600 w-1/7">Pause</th> | ||||||
|  | 				<th class="bg-neutral-300 border-neutral-600 w-1/7 border-r-0">Überstunden</th> | ||||||
|  | 			</tr> | ||||||
|  | 			for index, day := range workDays { | ||||||
|  | 				{{ | ||||||
|  | 					if index == len(workDays)-1 { | ||||||
|  | 						noBorder = "border-b-0" | ||||||
|  | 					} | ||||||
|  | 				}} | ||||||
|  | 				<tr> | ||||||
|  | 					<td class={ noBorder }>{ day.Day.Format("02.01.2006") }</td> | ||||||
|  | 					<td colspan="3"> | ||||||
|  | 				<table  class={ "w-full border-collapse" + noBorder }> | ||||||
|  | 					for bookingI := 0; bookingI < len(day.Bookings); bookingI+= 2 { | ||||||
|  | 						<tr class="flex"> | ||||||
|  | 							<td class="border-r-1 grow">{ day.Bookings[bookingI].Timestamp.Format("15:04") }</td> | ||||||
|  | 							<td class="border-r-1 grow">{ day.Bookings[bookingI+1].Timestamp.Format("15:04") }</td> | ||||||
|  | 							<td class="grow">{ day.Bookings[bookingI].BookingType.Name } </td> | ||||||
|  | 						</tr> | ||||||
|  | 					} | ||||||
|  | 					if (day.Absence != models.Absence{}) { | ||||||
|  | 						if len(day.Bookings) > 0 { | ||||||
|  | 						<tr class="border-t-1"> | ||||||
|  | 							<td colspan="2" class="col-span-full">{ day.Absence.AbwesenheitTyp.Name }</td> | ||||||
|  | 						</tr> | ||||||
|  | 						} | ||||||
|  | 						else { | ||||||
|  | 						<tr> | ||||||
|  | 							<td colspan="2" class="col-span-full">{ day.Absence.AbwesenheitTyp.Name }</td> | ||||||
|  | 						</tr> | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 					} | ||||||
|  | 				</table> | ||||||
|  | 					</td> | ||||||
|  | 				{{ work, pause, overtime := day.GetAllWorkTimes(e) }} | ||||||
|  | 				@ColorDuration(work, noBorder) | ||||||
|  | 				@ColorDuration(pause, noBorder) | ||||||
|  | 				@ColorDuration(overtime, noBorder + " border-r-0") | ||||||
|  | 				if day.Day.Weekday() == time.Friday { | ||||||
|  | 					<tr> | ||||||
|  | 					<td colspan="7" class="col-span-full bg-neutral-300">Wochenende</td> | ||||||
|  | 					</tr> | ||||||
|  | 				} | ||||||
|  | 				</tr> | ||||||
|  | 			} | ||||||
|  | 		</table> | ||||||
|  | 	</div> | ||||||
|  | } | ||||||
|  |  | ||||||
|  | templ ColorDuration(d time.Duration, classes string){ | ||||||
|  | {{ | ||||||
|  | 	color := "" | ||||||
|  | 	if d.Abs() < time.Minute{ | ||||||
|  | 		color = "text-neutral-300" | ||||||
|  | 	} | ||||||
|  | }} | ||||||
|  | <p class={ color + " " + classes }>{ helper.FormatDurationFill(d, true) }</p> | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // Code generated by templ - DO NOT EDIT. | // Code generated by templ - DO NOT EDIT. | ||||||
|  |  | ||||||
| // templ: version: v0.3.833 | // templ: version: v0.3.943 | ||||||
| package templates | package templates | ||||||
|  |  | ||||||
| //lint:file-ignore SA4006 This context is only used if a nested component is present. | //lint:file-ignore SA4006 This context is only used if a nested component is present. | ||||||
| @@ -37,18 +37,19 @@ func PDFReportEmploye(e models.User, workDays []models.WorkDay, tsStart time.Tim | |||||||
| 		ctx = templ.ClearChildren(ctx) | 		ctx = templ.ClearChildren(ctx) | ||||||
|  |  | ||||||
| 		_, kw := tsStart.ISOWeek() | 		_, kw := tsStart.ISOWeek() | ||||||
|  | 		noBorder := "" | ||||||
| 		templ_7745c5c3_Err = Base().Render(ctx, templ_7745c5c3_Buffer) | 		templ_7745c5c3_Err = Base().Render(ctx, templ_7745c5c3_Buffer) | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
| 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<content class=\"p-8 relative flex flex-col gap-4\"><div><h1 class=\"text-2xl font-bold\">Kim Mustermensch</h1><p>Zeitraum: <span>") | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<content class=\"p-8 relative flex flex-col gap-4 break-after-page\"><div><h1 class=\"text-2xl font-bold\">Kim Mustermensch</h1><p>Zeitraum: <span>") | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
| 		var templ_7745c5c3_Var2 string | 		var templ_7745c5c3_Var2 string | ||||||
| 		templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(tsStart.Format("02.01.2006")) | 		templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(tsStart.Format("02.01.2006")) | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 17, Col: 52} | 			return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 18, Col: 52} | ||||||
| 		} | 		} | ||||||
| 		_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) | 		_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| @@ -61,148 +62,735 @@ func PDFReportEmploye(e models.User, workDays []models.WorkDay, tsStart time.Tim | |||||||
| 		var templ_7745c5c3_Var3 string | 		var templ_7745c5c3_Var3 string | ||||||
| 		templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(tsEnd.Format("02.01.2006")) | 		templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(tsEnd.Format("02.01.2006")) | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 17, Col: 98} | 			return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 18, Col: 98} | ||||||
| 		} | 		} | ||||||
| 		_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) | 		_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
| 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span></p><p>Arbeitszeit: <span></span></p><p>Überstunden: <span></span></p></div><div class=\"grid grid-rows-6 grid-cols-[auto_1fr_1fr_1fr_1fr_1fr_1fr] divide-x-1 divide-y-1\"><p class=\"p-2 text-center\">") | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span></p><p>Arbeitszeit: <span></span></p><p>Überstunden: <span></span></p></div><div class=\"grid grid-rows-6 grid-cols-[3fr_2fr_2fr_2fr_3fr_3fr_3fr] *:not-print:p-2 *:text-center auto-rows-min divide-neutral-300 divide-x-1 divide-y-1\"><p class=\"bg-neutral-300 border-neutral-600\">") | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
| 		var templ_7745c5c3_Var4 string | 		var templ_7745c5c3_Var4 string | ||||||
| 		templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(kw) | 		templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(kw) | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 22, Col: 34} | 			return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 23, Col: 52} | ||||||
| 		} | 		} | ||||||
| 		_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) | 		_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
| 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</p><p class=\"p-2 text-center\">Kommen</p><p class=\"p-2 text-center\">Gehen</p><p class=\"p-2 text-center\">Arbeitsart</p><p class=\"p-2 text-center\">Stunden gesamt</p><p class=\"p-2 text-center\">Pause</p><p class=\"p-2 text-center\">Überstunden</p>") | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</p><p class=\"bg-neutral-300 border-neutral-600\">Kommen</p><p class=\"bg-neutral-300 border-neutral-600\">Gehen</p><p class=\"bg-neutral-300 border-neutral-600\">Arbeitsart</p><p class=\"bg-neutral-300 border-neutral-600\">Stunden</p><p class=\"bg-neutral-300 border-neutral-600\">Pause</p><p class=\"bg-neutral-300 border-neutral-600 border-r-0\">Überstunden</p>") | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
| 		for _, day := range workDays { | 		for index, day := range workDays { | ||||||
| 			if day.Day.Weekday() == time.Monday { |  | ||||||
| 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<p class=\"p-2 col-span-7 text-center bg-neutral-300\">Wochenende</p>") | 			if index == len(workDays)-1 { | ||||||
|  | 				noBorder = "border-b-0" | ||||||
|  | 			} | ||||||
|  | 			var templ_7745c5c3_Var5 = []any{noBorder} | ||||||
|  | 			templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			} | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<p class=\"") | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, " <p class=\"p-2 text-center\">") |  | ||||||
| 			if templ_7745c5c3_Err != nil { |  | ||||||
| 				return templ_7745c5c3_Err |  | ||||||
| 			} |  | ||||||
| 			var templ_7745c5c3_Var5 string |  | ||||||
| 			templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(day.Day.Format("02.01.2006")) |  | ||||||
| 			if templ_7745c5c3_Err != nil { |  | ||||||
| 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 33, Col: 61} |  | ||||||
| 			} |  | ||||||
| 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) |  | ||||||
| 			if templ_7745c5c3_Err != nil { |  | ||||||
| 				return templ_7745c5c3_Err |  | ||||||
| 			} |  | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</p><div class=\"grid grid-cols-subgrid col-span-3\">") |  | ||||||
| 			if templ_7745c5c3_Err != nil { |  | ||||||
| 				return templ_7745c5c3_Err |  | ||||||
| 			} |  | ||||||
| 			for bookingI := 0; bookingI < len(day.Bookings); bookingI += 2 { |  | ||||||
| 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<p class=\"p-2 text-center\">") |  | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			var templ_7745c5c3_Var6 string | 			var templ_7745c5c3_Var6 string | ||||||
| 				templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(day.Bookings[bookingI].Timestamp.Format("15:04")) | 			templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var5).String()) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 37, Col: 82} | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 1, Col: 0} | ||||||
| 			} | 			} | ||||||
| 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) | 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</p><p class=\"p-2 text-center\">") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\">") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			var templ_7745c5c3_Var7 string | 			var templ_7745c5c3_Var7 string | ||||||
| 				templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(day.Bookings[bookingI+1].Timestamp.Format("15:04")) | 			templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(day.Day.Format("02.01.2006")) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 38, Col: 84} | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 36, Col: 56} | ||||||
| 			} | 			} | ||||||
| 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) | 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</p><p class=\"p-2 text-center\">") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</p>") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 				var templ_7745c5c3_Var8 string | 			var templ_7745c5c3_Var8 = []any{"grid grid-cols-subgrid col-span-3 " + noBorder} | ||||||
| 				templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(day.Bookings[bookingI].BookingType.Name) | 			templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var8...) | ||||||
| 				if templ_7745c5c3_Err != nil { |  | ||||||
| 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 39, Col: 73} |  | ||||||
| 				} |  | ||||||
| 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) |  | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</p>") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<div class=\"") | ||||||
| 				if templ_7745c5c3_Err != nil { |  | ||||||
| 					return templ_7745c5c3_Err |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div>") |  | ||||||
| 			if templ_7745c5c3_Err != nil { |  | ||||||
| 				return templ_7745c5c3_Err |  | ||||||
| 			} |  | ||||||
| 			work, pause := day.GetWorkTimeString() |  | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<p class=\"p-2 text-center\">") |  | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			var templ_7745c5c3_Var9 string | 			var templ_7745c5c3_Var9 string | ||||||
| 			templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(work) | 			templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var8).String()) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 43, Col: 38} | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 1, Col: 0} | ||||||
| 			} | 			} | ||||||
| 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) | 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</p><p class=\"p-2 text-center\">") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\">") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			for bookingI := 0; bookingI < len(day.Bookings); bookingI += 2 { | ||||||
|  | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<p>") | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 				var templ_7745c5c3_Var10 string | 				var templ_7745c5c3_Var10 string | ||||||
| 			templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(pause) | 				templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(day.Bookings[bookingI].Timestamp.Format("15:04")) | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 44, Col: 39} | 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 40, Col: 59} | ||||||
| 				} | 				} | ||||||
| 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) | 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</p><p class=\"p-2 text-center\">") | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</p><p>") | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 				var templ_7745c5c3_Var11 string | 				var templ_7745c5c3_Var11 string | ||||||
| 			templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(helper.FormatDuration(day.CalcOvertime(e))) | 				templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(day.Bookings[bookingI+1].Timestamp.Format("15:04")) | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 45, Col: 76} | 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 41, Col: 61} | ||||||
| 				} | 				} | ||||||
| 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) | 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</p>") | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</p><p>") | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 				var templ_7745c5c3_Var12 string | ||||||
|  | 				templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(day.Bookings[bookingI].BookingType.Name) | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 42, Col: 50} | ||||||
|  | 				} | ||||||
|  | 				_, 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, 13, "</p>") | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</div></content>") | 			if (day.Absence != models.Absence{}) { | ||||||
|  | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<p class=\"col-span-full\">") | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 				var templ_7745c5c3_Var13 string | ||||||
|  | 				templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(day.Absence.AbwesenheitTyp.Name) | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 45, Col: 64} | ||||||
|  | 				} | ||||||
|  | 				_, 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, 15, "</p>") | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</div>") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			work, pause, overtime := day.GetAllWorkTimes(e) | ||||||
|  | 			templ_7745c5c3_Err = ColorDuration(work, noBorder).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 | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = ColorDuration(pause, noBorder).Render(ctx, templ_7745c5c3_Buffer) | ||||||
|  | 			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 | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = ColorDuration(overtime, noBorder+" border-r-0").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 | ||||||
|  | 			} | ||||||
|  | 			if day.Day.Weekday() == time.Friday { | ||||||
|  | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<p class=\"col-span-full bg-neutral-300\">Wochenende</p>") | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</div></content>") | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		return nil | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func PDFReportEmployeTable(e models.User, workDays []models.WorkDay, tsStart time.Time, tsEnd 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_Var14 := templ.GetChildren(ctx) | ||||||
|  | 		if templ_7745c5c3_Var14 == nil { | ||||||
|  | 			templ_7745c5c3_Var14 = templ.NopComponent | ||||||
|  | 		} | ||||||
|  | 		ctx = templ.ClearChildren(ctx) | ||||||
|  |  | ||||||
|  | 		_, kw := tsStart.ISOWeek() | ||||||
|  | 		noBorder := "" | ||||||
|  | 		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, 22, "<content class=\"p-8 relative flex flex-col gap-4 break-after-page\"><div><h1 class=\"text-2xl font-bold\">Kim Mustermensch</h1><p>Zeitraum: <span>") | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		var templ_7745c5c3_Var15 string | ||||||
|  | 		templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(tsStart.Format("02.01.2006")) | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 69, Col: 52} | ||||||
|  | 		} | ||||||
|  | 		_, 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, 23, "</span> - <span>") | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		var templ_7745c5c3_Var16 string | ||||||
|  | 		templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(tsEnd.Format("02.01.2006")) | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 69, Col: 98} | ||||||
|  | 		} | ||||||
|  | 		_, 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, 24, "</span></p><p>Arbeitszeit: <span></span></p><p>Überstunden: <span></span></p></div><table class=\"*:*:*:border-1 *:text-center border-1 border-collapse\"><tr><th class=\"bg-neutral-300 border-neutral-600 w-1/7\">") | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		var templ_7745c5c3_Var17 string | ||||||
|  | 		templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(kw) | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 75, Col: 60} | ||||||
|  | 		} | ||||||
|  | 		_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</th><th class=\"bg-neutral-300 border-neutral-600 w-1/7\">Kommen</th><th class=\"bg-neutral-300 border-neutral-600 w-1/7\">Gehen</th><th class=\"bg-neutral-300 border-neutral-600 w-1/7\">Arbeitsart</th><th class=\"bg-neutral-300 border-neutral-600 w-1/7\">Stunden</th><th class=\"bg-neutral-300 border-neutral-600 w-1/7\">Pause</th><th class=\"bg-neutral-300 border-neutral-600 w-1/7 border-r-0\">Überstunden</th></tr>") | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		for index, day := range workDays { | ||||||
|  |  | ||||||
|  | 			if index == len(workDays)-1 { | ||||||
|  | 				noBorder = "border-b-0" | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<tr>") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			var templ_7745c5c3_Var18 = []any{noBorder} | ||||||
|  | 			templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var18...) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "<td class=\"") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			var templ_7745c5c3_Var19 string | ||||||
|  | 			templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var18).String()) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 1, Col: 0} | ||||||
|  | 			} | ||||||
|  | 			_, 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, 28, "\">") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			var templ_7745c5c3_Var20 string | ||||||
|  | 			templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(day.Day.Format("02.01.2006")) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 90, Col: 58} | ||||||
|  | 			} | ||||||
|  | 			_, 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, 29, "</td><td colspan=\"3\">") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			var templ_7745c5c3_Var21 = []any{"w-full border-collapse" + noBorder} | ||||||
|  | 			templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var21...) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<table class=\"") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			var templ_7745c5c3_Var22 string | ||||||
|  | 			templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var21).String()) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 1, Col: 0} | ||||||
|  | 			} | ||||||
|  | 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "\">") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			for bookingI := 0; bookingI < len(day.Bookings); bookingI += 2 { | ||||||
|  | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "<tr class=\"flex\"><td class=\"border-r-1 grow\">") | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 				var templ_7745c5c3_Var23 string | ||||||
|  | 				templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(day.Bookings[bookingI].Timestamp.Format("15:04")) | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 95, Col: 85} | ||||||
|  | 				} | ||||||
|  | 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "</td><td class=\"border-r-1 grow\">") | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 				var templ_7745c5c3_Var24 string | ||||||
|  | 				templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(day.Bookings[bookingI+1].Timestamp.Format("15:04")) | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 96, Col: 87} | ||||||
|  | 				} | ||||||
|  | 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</td><td class=\"grow\">") | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 				var templ_7745c5c3_Var25 string | ||||||
|  | 				templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(day.Bookings[bookingI].BookingType.Name) | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 97, Col: 65} | ||||||
|  | 				} | ||||||
|  | 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</td></tr>") | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			if (day.Absence != models.Absence{}) { | ||||||
|  | 				if len(day.Bookings) > 0 { | ||||||
|  | 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<tr class=\"border-t-1\"><td colspan=\"2\" class=\"col-span-full\">") | ||||||
|  | 					if templ_7745c5c3_Err != nil { | ||||||
|  | 						return templ_7745c5c3_Err | ||||||
|  | 					} | ||||||
|  | 					var templ_7745c5c3_Var26 string | ||||||
|  | 					templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(day.Absence.AbwesenheitTyp.Name) | ||||||
|  | 					if templ_7745c5c3_Err != nil { | ||||||
|  | 						return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 103, Col: 78} | ||||||
|  | 					} | ||||||
|  | 					_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) | ||||||
|  | 					if templ_7745c5c3_Err != nil { | ||||||
|  | 						return templ_7745c5c3_Err | ||||||
|  | 					} | ||||||
|  | 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "</td></tr>") | ||||||
|  | 					if templ_7745c5c3_Err != nil { | ||||||
|  | 						return templ_7745c5c3_Err | ||||||
|  | 					} | ||||||
|  | 				} else { | ||||||
|  | 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "<tr><td colspan=\"2\" class=\"col-span-full\">") | ||||||
|  | 					if templ_7745c5c3_Err != nil { | ||||||
|  | 						return templ_7745c5c3_Err | ||||||
|  | 					} | ||||||
|  | 					var templ_7745c5c3_Var27 string | ||||||
|  | 					templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(day.Absence.AbwesenheitTyp.Name) | ||||||
|  | 					if templ_7745c5c3_Err != nil { | ||||||
|  | 						return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 108, Col: 78} | ||||||
|  | 					} | ||||||
|  | 					_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) | ||||||
|  | 					if templ_7745c5c3_Err != nil { | ||||||
|  | 						return templ_7745c5c3_Err | ||||||
|  | 					} | ||||||
|  | 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</td></tr>") | ||||||
|  | 					if templ_7745c5c3_Err != nil { | ||||||
|  | 						return templ_7745c5c3_Err | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "</table></td>") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			work, pause, overtime := day.GetAllWorkTimes(e) | ||||||
|  | 			templ_7745c5c3_Err = ColorDuration(work, noBorder).Render(ctx, templ_7745c5c3_Buffer) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = ColorDuration(pause, noBorder).Render(ctx, templ_7745c5c3_Buffer) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = ColorDuration(overtime, noBorder+" border-r-0").Render(ctx, templ_7745c5c3_Buffer) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			if day.Day.Weekday() == time.Friday { | ||||||
|  | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "<tr><td colspan=\"7\" class=\"col-span-full bg-neutral-300\">Wochenende</td></tr>") | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</tr>") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</table></content><div class=\"p-8 relative flex flex-col gap-4 break-after-page\"><div><h1 class=\"text-2xl font-bold\">Kim Mustermensch</h1><p>Zeitraum: <span>") | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		var templ_7745c5c3_Var28 string | ||||||
|  | 		templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(tsStart.Format("02.01.2006")) | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 131, Col: 52} | ||||||
|  | 		} | ||||||
|  | 		_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28)) | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "</span> - <span>") | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		var templ_7745c5c3_Var29 string | ||||||
|  | 		templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(tsEnd.Format("02.01.2006")) | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 131, Col: 98} | ||||||
|  | 		} | ||||||
|  | 		_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29)) | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "</span></p><p>Arbeitszeit: <span></span></p><p>Überstunden: <span></span></p></div><table class=\"*:*:*:border-1 *:text-center border-1 border-collapse\"><tr><th class=\"bg-neutral-300 border-neutral-600 w-1/7\">") | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		var templ_7745c5c3_Var30 string | ||||||
|  | 		templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(kw) | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 137, Col: 60} | ||||||
|  | 		} | ||||||
|  | 		_, 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, 46, "</th><th class=\"bg-neutral-300 border-neutral-600 w-1/7\">Kommen</th><th class=\"bg-neutral-300 border-neutral-600 w-1/7\">Gehen</th><th class=\"bg-neutral-300 border-neutral-600 w-1/7\">Arbeitsart</th><th class=\"bg-neutral-300 border-neutral-600 w-1/7\">Stunden</th><th class=\"bg-neutral-300 border-neutral-600 w-1/7\">Pause</th><th class=\"bg-neutral-300 border-neutral-600 w-1/7 border-r-0\">Überstunden</th></tr>") | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		for index, day := range workDays { | ||||||
|  |  | ||||||
|  | 			if index == len(workDays)-1 { | ||||||
|  | 				noBorder = "border-b-0" | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "<tr>") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			var templ_7745c5c3_Var31 = []any{noBorder} | ||||||
|  | 			templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var31...) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "<td class=\"") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			var templ_7745c5c3_Var32 string | ||||||
|  | 			templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var31).String()) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 1, Col: 0} | ||||||
|  | 			} | ||||||
|  | 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32)) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "\">") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			var templ_7745c5c3_Var33 string | ||||||
|  | 			templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(day.Day.Format("02.01.2006")) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 152, Col: 58} | ||||||
|  | 			} | ||||||
|  | 			_, 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, 50, "</td><td colspan=\"3\">") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			var templ_7745c5c3_Var34 = []any{"w-full border-collapse" + noBorder} | ||||||
|  | 			templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var34...) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "<table class=\"") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			var templ_7745c5c3_Var35 string | ||||||
|  | 			templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var34).String()) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 1, Col: 0} | ||||||
|  | 			} | ||||||
|  | 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35)) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "\">") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			for bookingI := 0; bookingI < len(day.Bookings); bookingI += 2 { | ||||||
|  | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "<tr class=\"flex\"><td class=\"border-r-1 grow\">") | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 				var templ_7745c5c3_Var36 string | ||||||
|  | 				templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(day.Bookings[bookingI].Timestamp.Format("15:04")) | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 157, Col: 85} | ||||||
|  | 				} | ||||||
|  | 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36)) | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "</td><td class=\"border-r-1 grow\">") | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 				var templ_7745c5c3_Var37 string | ||||||
|  | 				templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.JoinStringErrs(day.Bookings[bookingI+1].Timestamp.Format("15:04")) | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 158, Col: 87} | ||||||
|  | 				} | ||||||
|  | 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var37)) | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "</td><td class=\"grow\">") | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 				var templ_7745c5c3_Var38 string | ||||||
|  | 				templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinStringErrs(day.Bookings[bookingI].BookingType.Name) | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 159, Col: 65} | ||||||
|  | 				} | ||||||
|  | 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var38)) | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "</td></tr>") | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			if (day.Absence != models.Absence{}) { | ||||||
|  | 				if len(day.Bookings) > 0 { | ||||||
|  | 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "<tr class=\"border-t-1\"><td colspan=\"2\" class=\"col-span-full\">") | ||||||
|  | 					if templ_7745c5c3_Err != nil { | ||||||
|  | 						return templ_7745c5c3_Err | ||||||
|  | 					} | ||||||
|  | 					var templ_7745c5c3_Var39 string | ||||||
|  | 					templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.JoinStringErrs(day.Absence.AbwesenheitTyp.Name) | ||||||
|  | 					if templ_7745c5c3_Err != nil { | ||||||
|  | 						return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 165, Col: 78} | ||||||
|  | 					} | ||||||
|  | 					_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39)) | ||||||
|  | 					if templ_7745c5c3_Err != nil { | ||||||
|  | 						return templ_7745c5c3_Err | ||||||
|  | 					} | ||||||
|  | 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "</td></tr>") | ||||||
|  | 					if templ_7745c5c3_Err != nil { | ||||||
|  | 						return templ_7745c5c3_Err | ||||||
|  | 					} | ||||||
|  | 				} else { | ||||||
|  | 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "<tr><td colspan=\"2\" class=\"col-span-full\">") | ||||||
|  | 					if templ_7745c5c3_Err != nil { | ||||||
|  | 						return templ_7745c5c3_Err | ||||||
|  | 					} | ||||||
|  | 					var templ_7745c5c3_Var40 string | ||||||
|  | 					templ_7745c5c3_Var40, templ_7745c5c3_Err = templ.JoinStringErrs(day.Absence.AbwesenheitTyp.Name) | ||||||
|  | 					if templ_7745c5c3_Err != nil { | ||||||
|  | 						return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 170, Col: 78} | ||||||
|  | 					} | ||||||
|  | 					_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var40)) | ||||||
|  | 					if templ_7745c5c3_Err != nil { | ||||||
|  | 						return templ_7745c5c3_Err | ||||||
|  | 					} | ||||||
|  | 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "</td></tr>") | ||||||
|  | 					if templ_7745c5c3_Err != nil { | ||||||
|  | 						return templ_7745c5c3_Err | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "</table></td>") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			work, pause, overtime := day.GetAllWorkTimes(e) | ||||||
|  | 			templ_7745c5c3_Err = ColorDuration(work, noBorder).Render(ctx, templ_7745c5c3_Buffer) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = ColorDuration(pause, noBorder).Render(ctx, templ_7745c5c3_Buffer) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = ColorDuration(overtime, noBorder+" border-r-0").Render(ctx, templ_7745c5c3_Buffer) | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			if day.Day.Weekday() == time.Friday { | ||||||
|  | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "<tr><td colspan=\"7\" class=\"col-span-full bg-neutral-300\">Wochenende</td></tr>") | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "</tr>") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "</table></div>") | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		return nil | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ColorDuration(d time.Duration, classes 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_Var41 := templ.GetChildren(ctx) | ||||||
|  | 		if templ_7745c5c3_Var41 == nil { | ||||||
|  | 			templ_7745c5c3_Var41 = templ.NopComponent | ||||||
|  | 		} | ||||||
|  | 		ctx = templ.ClearChildren(ctx) | ||||||
|  |  | ||||||
|  | 		color := "" | ||||||
|  | 		if d.Abs() < time.Minute { | ||||||
|  | 			color = "text-neutral-300" | ||||||
|  | 		} | ||||||
|  | 		var templ_7745c5c3_Var42 = []any{color + " " + classes} | ||||||
|  | 		templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var42...) | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "<p class=\"") | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		var templ_7745c5c3_Var43 string | ||||||
|  | 		templ_7745c5c3_Var43, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var42).String()) | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 1, Col: 0} | ||||||
|  | 		} | ||||||
|  | 		_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var43)) | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "\">") | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		var templ_7745c5c3_Var44 string | ||||||
|  | 		templ_7745c5c3_Var44, templ_7745c5c3_Err = templ.JoinStringErrs(helper.FormatDurationFill(d, true)) | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pdf.templ`, Line: 199, Col: 71} | ||||||
|  | 		} | ||||||
|  | 		_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var44)) | ||||||
|  | 		if templ_7745c5c3_Err != nil { | ||||||
|  | 			return templ_7745c5c3_Err | ||||||
|  | 		} | ||||||
|  | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "</p>") | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // Code generated by templ - DO NOT EDIT. | // Code generated by templ - DO NOT EDIT. | ||||||
|  |  | ||||||
| // templ: version: v0.3.833 | // templ: version: v0.3.943 | ||||||
| package templates | package templates | ||||||
|  |  | ||||||
| //lint:file-ignore SA4006 This context is only used if a nested component is present. | //lint:file-ignore SA4006 This context is only used if a nested component is present. | ||||||
|   | |||||||
| @@ -57,7 +57,7 @@ templ dayComponent(workDay models.WorkDay, submitted bool) { | |||||||
| 					if (workDay.RequiresAction()) { | 					if (workDay.RequiresAction()) { | ||||||
| 						<p class="text-red-600">Bitte anpassen</p> | 						<p class="text-red-600">Bitte anpassen</p> | ||||||
| 					} else { | 					} else { | ||||||
| 						<p class="text-accent">{ work }</p> | 						<p class="text-accent flex flex-row items-center"><span class="icon-[material-symbols-light--nest-clock-farsight-analog-outline]"></span>{ work }</p> | ||||||
| 						if pause != "" { | 						if pause != "" { | ||||||
| 							<p class="text-neutral-500 flex flex-row items-center"><span class="icon-[material-symbols-light--motion-photos-paused-outline]"></span>{ pause }</p> | 							<p class="text-neutral-500 flex flex-row items-center"><span class="icon-[material-symbols-light--motion-photos-paused-outline]"></span>{ pause }</p> | ||||||
| 						} | 						} | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| // Code generated by templ - DO NOT EDIT. | // Code generated by templ - DO NOT EDIT. | ||||||
|  |  | ||||||
| // templ: version: v0.3.833 | // templ: version: v0.3.943 | ||||||
| package templates | package templates | ||||||
|  |  | ||||||
| //lint:file-ignore SA4006 This context is only used if a nested component is present. | //lint:file-ignore SA4006 This context is only used if a nested component is present. | ||||||
| @@ -205,14 +205,14 @@ func dayComponent(workDay models.WorkDay, submitted bool) templ.Component { | |||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<p class=\"text-accent\">") | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<p class=\"text-accent flex flex-row items-center\"><span class=\"icon-[material-symbols-light--nest-clock-farsight-analog-outline]\"></span>") | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 				var templ_7745c5c3_Var11 string | 				var templ_7745c5c3_Var11 string | ||||||
| 				templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(work) | 				templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(work) | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 60, Col: 35} | 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 60, Col: 149} | ||||||
| 				} | 				} | ||||||
| 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) | 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user