package models import ( "sort" "time" ) // TimelineEntry represents any item that can appear in the timeline. type TimelineEntry struct { Date time.Time Type EntryType Event *Event Diary *DiaryEntry Photo *Photo } // EntryType indicates what kind of entry this is. type EntryType string const ( EntryTypeEvent EntryType = "event" EntryTypeDiary EntryType = "diary" EntryTypePhoto EntryType = "photo" ) // DayContent aggregates all content for a specific day. type DayContent struct { Date time.Time Events []*Event Diary *DiaryEntry Photos []*Photo } // HasContent returns true if there is any content for this day. func (d *DayContent) HasContent() bool { return len(d.Events) > 0 || d.Diary != nil || len(d.Photos) > 0 } // HasEvents returns true if there are events on this day. func (d *DayContent) HasEvents() bool { return len(d.Events) > 0 } // HasDiary returns true if there is a diary entry for this day. func (d *DayContent) HasDiary() bool { return d.Diary != nil } // HasPhotos returns true if there are photos for this day. func (d *DayContent) HasPhotos() bool { return len(d.Photos) > 0 } // ToTimelineEntries converts day content to a sorted slice of timeline entries. func (d *DayContent) ToTimelineEntries() []TimelineEntry { var entries []TimelineEntry for _, event := range d.Events { entries = append(entries, TimelineEntry{ Date: event.Start, Type: EntryTypeEvent, Event: event, }) } if d.Diary != nil { entries = append(entries, TimelineEntry{ Date: d.Diary.Date, Type: EntryTypeDiary, Diary: d.Diary, }) } for _, photo := range d.Photos { entries = append(entries, TimelineEntry{ Date: photo.Date, Type: EntryTypePhoto, Photo: photo, }) } sort.Slice(entries, func(i, j int) bool { return entries[i].Date.Before(entries[j].Date) }) return entries } // MonthData holds all data for a specific month. type MonthData struct { Year int Month time.Month Days map[int]*DayContent } // GetDay returns the day content for a specific day number. func (m *MonthData) GetDay(day int) *DayContent { if content, ok := m.Days[day]; ok { return content } return &DayContent{ Date: time.Date(m.Year, m.Month, day, 0, 0, 0, 0, time.Local), } }