diff --git a/pages/calendar/calendar.go b/pages/calendar/calendar.go new file mode 100644 index 00000000..5329a753 --- /dev/null +++ b/pages/calendar/calendar.go @@ -0,0 +1,80 @@ +package calendar + +import ( + "sort" + "time" + + "github.com/aerogo/aero" + "github.com/animenotifier/arn" + "github.com/animenotifier/arn/validator" + "github.com/animenotifier/notify.moe/components" + "github.com/animenotifier/notify.moe/utils" +) + +var weekdayNames = []string{ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", +} + +// Get ... +func Get(ctx *aero.Context) string { + user := utils.GetUser(ctx) + oneWeek := 7 * 24 * time.Hour + + now := time.Now() + year, month, day := now.Date() + now = time.Date(year, month, day, 0, 0, 0, 0, time.UTC) + + // Weekday index that we start with, Sunday is 0. + weekdayIndex := int(now.Weekday()) + + // Create days + days := make([]*utils.CalendarDay, 7, 7) + + for i := 0; i < 7; i++ { + days[i] = &utils.CalendarDay{ + Name: weekdayNames[(weekdayIndex+i)%7], + Entries: []*utils.CalendarEntry{}, + } + } + + // Add anime episodes to the days + for animeEpisodes := range arn.StreamAnimeEpisodes() { + for _, episode := range animeEpisodes.Items { + if !validator.IsValidDate(episode.AiringDate.Start) { + continue + } + + airingDate, _ := time.Parse(time.RFC3339, episode.AiringDate.Start) + since := airingDate.Sub(now) + + if since >= 0 && since < oneWeek { + dayIndex := int(since / (24 * time.Hour)) + days[dayIndex].Entries = append(days[dayIndex].Entries, &utils.CalendarEntry{ + Anime: animeEpisodes.Anime(), + Episode: episode, + }) + } + } + } + + for i := 0; i < 7; i++ { + sort.Slice(days[i].Entries, func(a, b int) bool { + airingA := days[i].Entries[a].Episode.AiringDate.Start + airingB := days[i].Entries[b].Episode.AiringDate.Start + + if airingA == airingB { + return days[i].Entries[a].Anime.Title.Canonical < days[i].Entries[b].Anime.Title.Canonical + } + + return airingA < airingB + }) + } + + return ctx.HTML(components.Calendar(days, user)) +} diff --git a/pages/calendar/calendar.pixy b/pages/calendar/calendar.pixy new file mode 100644 index 00000000..4848fd8b --- /dev/null +++ b/pages/calendar/calendar.pixy @@ -0,0 +1,10 @@ +component Calendar(days []*utils.CalendarDay, user *arn.User) + h1 Calendar + + .week + each day in days + .weekday + h3.weekday-name= day.Name + ol + each entry in day.Entries + li= entry.Anime.Title.ByUser(user) + " (Ep: " + strconv.Itoa(entry.Episode.Number) + ")" \ No newline at end of file diff --git a/pages/calendar/calendar.scarlet b/pages/calendar/calendar.scarlet new file mode 100644 index 00000000..e2254012 --- /dev/null +++ b/pages/calendar/calendar.scarlet @@ -0,0 +1,24 @@ +.week + vertical + +.weekday + flex 1 + text-align left + border-bottom 1px solid ui-border-color + + :last-child + border-bottom none + +.weekday-name + text-align center + +> 800px + .week + horizontal + + .weekday + border-bottom none + border-right 1px solid ui-border-color + + :last-child + border-right none \ No newline at end of file diff --git a/pages/index.go b/pages/index.go index 5d8c7e6b..f61ec5b4 100644 --- a/pages/index.go +++ b/pages/index.go @@ -11,6 +11,7 @@ import ( "github.com/animenotifier/notify.moe/pages/animelist" "github.com/animenotifier/notify.moe/pages/animelistitem" "github.com/animenotifier/notify.moe/pages/apiview" + "github.com/animenotifier/notify.moe/pages/calendar" "github.com/animenotifier/notify.moe/pages/character" "github.com/animenotifier/notify.moe/pages/charge" "github.com/animenotifier/notify.moe/pages/companies" @@ -94,6 +95,9 @@ func Configure(app *aero.Application) { // Characters l.Page("/character/:id", character.Get) + // Calendar + l.Page("/calendar", calendar.Get) + // Companies l.Page("/company/:id", company.Get) l.Page("/company/:id/edit", company.Edit) diff --git a/utils/Calendar.go b/utils/Calendar.go new file mode 100644 index 00000000..499bfba2 --- /dev/null +++ b/utils/Calendar.go @@ -0,0 +1,15 @@ +package utils + +import "github.com/animenotifier/arn" + +// CalendarDay is a calendar day. +type CalendarDay struct { + Name string + Entries []*CalendarEntry +} + +// CalendarEntry is a calendar entry. +type CalendarEntry struct { + Anime *arn.Anime + Episode *arn.AnimeEpisode +}