sprechstunden-go/controllers/timetable.go

138 lines
4.6 KiB
Go

// timetable.go
package controllers
import (
"bytes"
"fmt"
"html/template"
"log"
"officeHours/models"
"officeHours/templating"
)
func (b *BaseHandler) GetTimetable(officeHours []models.OfficeHour) (timetable map[models.Date]map[int]models.OfficeHour, slots []int) {
var fullTimetable = make(map[models.Date]map[int]models.OfficeHour)
for _, officeHour := range officeHours {
var slot int = 0
for minute := 0; minute < officeHour.Duration; minute += b.config.Date.MinuteGranularity { // find slot id
_, exists := fullTimetable[models.GetEndDate(officeHour.Date, minute, true)]
if exists {
_, exists := fullTimetable[models.GetEndDate(officeHour.Date, minute, true)][slot]
if exists {
slot += 1
minute = 0
continue
}
} else {
fullTimetable[models.GetEndDate(officeHour.Date, minute, true)] = make(map[int]models.OfficeHour)
}
}
for minute := 0; minute < officeHour.Duration; minute += b.config.Date.MinuteGranularity { // write officeHour id to timetable
fullTimetable[models.GetEndDate(officeHour.Date, minute, true)][slot] = officeHour
}
}
slots = []int{1, 1, 1, 1, 1}
for date, _ := range fullTimetable {
if slots[date.Day] < len(fullTimetable[date]) {
slots[date.Day] = len(fullTimetable[date])
}
}
timetable = make(map[models.Date]map[int]models.OfficeHour)
for _, officeHour := range officeHours {
for slot := 0; slot < slots[officeHour.Date.Day]; slot += 1 {
if fullTimetable[officeHour.Date][slot] == officeHour {
timetable[officeHour.Date] = make(map[int]models.OfficeHour)
timetable[officeHour.Date][slot] = officeHour
}
}
}
return fullTimetable, slots
}
func (b *BaseHandler) printTimetable(timetable map[models.Date]map[int]models.OfficeHour, slots []int, deleteIcons bool) template.HTML {
var tableBody string
var anyOfficeHourExists bool = false // do not show table if no entry in there
for hour := 8; hour < 19; hour += 1 {
for minute := 0; minute < 60; minute += b.config.Date.MinuteGranularity {
tableBody += "<tr>"
if minute == 0 {
tableBody += fmt.Sprintf("<td class=\"timetableRightBorder\">%d Uhr</td>\n", hour)
} else {
tableBody += "<td class=\"timetableRightBorder\"></td>\n"
}
for day := 0; day < 5; day += 1 {
for slot := 0; slot < slots[day]; slot += 1 {
current, currentExists := timetable[models.Date{Week: 0, Day: day, Hour: hour, Minute: minute}][slot]
if currentExists { // This slot is taken by some office hour
var continued bool = false // is this slot occupied by the same office hour the previous minute?
var predecessorExists bool
var predecessor models.OfficeHour
if hour > 0 && minute < b.config.Date.MinuteGranularity {
predecessor, predecessorExists = timetable[models.Date{Week: 0, Day: day, Hour: hour - 1, Minute: 60 - b.config.Date.MinuteGranularity}][slot]
} else {
predecessor, predecessorExists = timetable[models.Date{Week: 0, Day: day, Hour: hour, Minute: minute - b.config.Date.MinuteGranularity}][slot]
}
if predecessorExists {
continued = (predecessor == current)
} else {
continued = false
}
if continued {
continue
} else {
var celldata bytes.Buffer
data := struct {
OfficeHour models.OfficeHour
MinuteGranularity int
DeleteIcons bool
}{OfficeHour: current, MinuteGranularity: b.config.Date.MinuteGranularity, DeleteIcons: deleteIcons}
err := templating.WriteTemplate(&celldata, "td", data)
if err != nil {
err = fmt.Errorf("writing table cell failed:\n%w", err)
log.Println(err.Error())
// TODO: better error wrapping up to top-level request handler
}
tableBody += celldata.String()
anyOfficeHourExists = true
}
} else {
if slot+1 == slots[day] {
tableBody += "<td class=\"timetableRightBorder\"></td>\n"
} else {
tableBody += "<td></td>\n"
}
}
}
}
tableBody += "</tr>\n"
}
}
if !anyOfficeHourExists {
return template.HTML("Aktuell sind keine passenden Sprechstunden eingetragen.")
}
var table bytes.Buffer
tableData := struct {
ColspanMon int
ColspanTue int
ColspanWed int
ColspanThu int
ColspanFri int
TableBody template.HTML
}{
slots[0],
slots[1],
slots[2],
slots[3],
slots[4],
template.HTML(tableBody),
}
err := templating.WriteTemplate(&table, "officeHourTable", tableData)
if err != nil {
err = fmt.Errorf("writing table failed:\n%w", err)
log.Println(err.Error())
// TODO: better error wrapping up to top-level request handler
}
return template.HTML(table.String())
}