@animeCardPoster(props.ImageURL, props.Title, props.ImgClass)
if !props.HideTitle {
@@ -37,6 +38,14 @@ templ AnimeCard(props AnimeCardProps) {
}
}
+func cardHref(props AnimeCardProps) string {
+ if props.Href != "" {
+ return props.Href
+ }
+
+ return fmt.Sprintf("/anime/%d", props.ID)
+}
+
templ animeCardPoster(imageURL, title, imgClass string) {
if imageURL != "" {
diff --git a/internal/templates/continue_watching.templ b/internal/templates/continue_watching.templ
new file mode 100644
index 0000000..da177cc
--- /dev/null
+++ b/internal/templates/continue_watching.templ
@@ -0,0 +1,67 @@
+package templates
+
+import (
+ "fmt"
+ "mal/internal/database"
+ "mal/internal/shared/ui"
+)
+
+templ ContinueWatching(entries []database.GetContinueWatchingEntriesRow) {
+ @Layout("mal - continue watching", true) {
+
+
Continue watching
+
Pick up where you left off.
+ if len(entries) == 0 {
+ @ui.EmptyState("Nothing to continue yet") {
+ Start watching any anime and your progress will show up here.
+ }
+ } else {
+
+ for _, entry := range entries {
+
+ @ui.AnimeCard(ui.AnimeCardProps{
+ ID: int(entry.AnimeID),
+ Title: displayContinueWatchingTitle(entry),
+ ImageURL: entry.ImageUrl,
+ Href: continueWatchingURL(entry),
+ Class: "notification-card min-w-0 flex flex-col bg-transparent text-inherit no-underline",
+ HideTitle: true,
+ }) {
+
+
{ displayContinueWatchingTitle(entry) }
+
+ if entry.CurrentEpisode.Valid && entry.CurrentEpisode.Int64 > 0 {
+ Continue ep { fmt.Sprintf("%d", entry.CurrentEpisode.Int64) }
+ }
+ if entry.CurrentTimeSeconds > 0 {
+ { formatProgressTime(entry.CurrentTimeSeconds) }
+ }
+
+
+ }
+
×
+
+ }
+
+ }
+
+ }
+}
+
+func continueWatchingURL(entry database.GetContinueWatchingEntriesRow) string {
+ episode := 1
+ if entry.CurrentEpisode.Valid && entry.CurrentEpisode.Int64 > 0 {
+ episode = int(entry.CurrentEpisode.Int64)
+ }
+
+ return fmt.Sprintf("/watch/%d/%d", entry.AnimeID, episode)
+}
+
+func displayContinueWatchingTitle(entry database.GetContinueWatchingEntriesRow) string {
+ return database.DisplayTitle(entry.TitleEnglish, entry.TitleJapanese, entry.TitleOriginal)
+}
diff --git a/internal/templates/layout.templ b/internal/templates/layout.templ
index af58828..90dd0e0 100644
--- a/internal/templates/layout.templ
+++ b/internal/templates/layout.templ
@@ -26,9 +26,8 @@ templ Layout(title string, showHeader bool) {
@icons.LogoIcon("h-7 w-7")
diff --git a/internal/templates/notifications.templ b/internal/templates/notifications.templ
deleted file mode 100644
index 4e5e251..0000000
--- a/internal/templates/notifications.templ
+++ /dev/null
@@ -1,184 +0,0 @@
-package templates
-
-import "mal/internal/jikan"
-import "mal/internal/database"
-import "mal/internal/shared/ui"
-import "fmt"
-import "strings"
-
-type WatchingAnimeWithDetails struct {
- Entry database.GetWatchingAnimeRow
- Anime jikan.Anime
-}
-
-templ Notifications(watching []WatchingAnimeWithDetails, activeTab string) {
- @Layout("mal - notifications", true) {
-
-
Notifications
-
-
- if activeTab == "sequels" {
-
- @ui.LoadingIndicator("Syncing sequel graphs...")
-
- } else {
-
Shows you're currently watching or planning to watch.
- if len(watching) == 0 {
- @ui.EmptyState("No airing anime in your watching list.") {
-
Add currently airing shows to your watching list to see upcoming episodes here.
- }
- } else {
-
- for _, item := range watching {
- @NotificationCard(item)
- }
-
- }
- }
-
- }
-}
-
-func splitUpcomingSeasons(items []database.GetUpcomingSeasonsRow) (airing []database.GetUpcomingSeasonsRow, upcoming []database.GetUpcomingSeasonsRow) {
- for _, item := range items {
- if item.Status.Valid && item.Status.String == "Currently Airing" {
- airing = append(airing, item)
- } else {
- upcoming = append(upcoming, item)
- }
- }
- return
-}
-
-templ UpcomingSeasonsList(upcomingSeasons []database.GetUpcomingSeasonsRow) {
- if len(upcomingSeasons) == 0 {
- @ui.EmptyState("No upcoming seasons for anime you've watched.") {
- As you watch more shows, new seasons will appear here.
- }
- } else {
- @renderSplitSeasons(upcomingSeasons)
- }
-}
-
-templ renderSplitSeasons(upcomingSeasons []database.GetUpcomingSeasonsRow) {
- if airing, upcoming := splitUpcomingSeasons(upcomingSeasons); true {
- if len(airing) > 0 {
-
- Airing now
- These are the currently airing anime, but you're not tracking any of these.
-
- for _, item := range airing {
- @UpcomingSeasonCard(item)
- }
-
-
- }
-
- if len(upcoming) > 0 {
-
- Announced & upcoming
- Newly announced or upcoming seasons related to anime you've watched.
-
- for _, item := range upcoming {
- @UpcomingSeasonCard(item)
- }
-
-
- }
- }
-}
-
-templ UpcomingSeasonCard(item database.GetUpcomingSeasonsRow) {
- @ui.AnimeCard(ui.AnimeCardProps{
- ID: int(item.ID),
- Title: displaySeasonTitle(item),
- ImageURL: item.ImageUrl,
- Class: "notification-card min-w-0 flex flex-col bg-transparent text-inherit no-underline",
- HideTitle: true,
- }) {
-
-
- { displaySeasonTitle(item) }
-
-
- if item.Status.Valid {
- { seasonStatusLabel(item.Status.String) }
- }
- if strings.TrimSpace(item.PrequelTitle) != "" {
- { fmt.Sprintf("Sequel to %s", item.PrequelTitle) }
- }
-
-
- }
-}
-
-func displaySeasonTitle(entry database.GetUpcomingSeasonsRow) string {
- return database.DisplayTitle(entry.TitleEnglish, entry.TitleJapanese, entry.TitleOriginal)
-}
-
-templ NotificationCard(item WatchingAnimeWithDetails) {
- @ui.AnimeCard(ui.AnimeCardProps{
- ID: int(item.Entry.AnimeID),
- Title: displayTitle(item.Entry),
- ImageURL: item.Entry.ImageUrl,
- Class: "notification-card min-w-0 flex flex-col bg-transparent text-inherit no-underline",
- HideTitle: true,
- }) {
-
-
- { displayTitle(item.Entry) }
-
-
- if item.Anime.Broadcast.String != "" {
- { item.Anime.Broadcast.String }
- Calculating next episode time...
- }
- if item.Anime.Episodes > 0 {
-
- if item.Entry.CurrentEpisode.Valid {
- { fmt.Sprintf("%d / %d eps", item.Entry.CurrentEpisode.Int64, item.Anime.Episodes) }
- } else {
- { fmt.Sprintf("0 / %d eps", item.Anime.Episodes) }
- }
-
- } else if item.Entry.CurrentEpisode.Valid && item.Entry.CurrentEpisode.Int64 > 0 {
-
- { fmt.Sprintf("%d eps watched", item.Entry.CurrentEpisode.Int64) }
-
- }
-
-
- }
-}
-
-func displayTitle(entry database.GetWatchingAnimeRow) string {
- return database.DisplayTitle(entry.TitleEnglish, entry.TitleJapanese, entry.TitleOriginal)
-}
-
-func seasonStatusLabel(status string) string {
- statusText := strings.TrimSpace(status)
- if statusText == "" {
- return ""
- }
-
- if statusText == "Currently Airing" {
- return "Airing now"
- }
-
- if statusText == "Not yet aired" {
- return "Upcoming"
- }
-
- return statusText
-}
-
-func statusTabClass(active bool) string {
- base := "shrink-0 whitespace-nowrap bg-(--panel-soft) px-2 py-1 text-xs text-(--text-muted) no-underline hover:bg-(--surface-tab-hover) hover:text-(--text) hover:no-underline"
- if active {
- return "shrink-0 whitespace-nowrap bg-(--surface-tab-active) px-2 py-1 text-xs text-(--accent) no-underline hover:no-underline"
- }
- return base
-}
diff --git a/internal/templates/watchlist.templ b/internal/templates/watchlist.templ
index dd3ad2a..408d50a 100644
--- a/internal/templates/watchlist.templ
+++ b/internal/templates/watchlist.templ
@@ -29,7 +29,6 @@ templ Watchlist(entries []database.GetUserWatchListRow, layout string, currentSt
All
Watching
-
Continuing
On hold
Plan to watch
Dropped
@@ -40,8 +39,6 @@ templ Watchlist(entries []database.GetUserWatchListRow, layout string, currentSt
@ui.EmptyState("Nothing here yet") {
if currentStatus == "all" {
Your watchlist is empty.
Search for anime to get started.
- } else if currentStatus == "continuing" {
- No airing anime with watching or plan to watch status.
} else {
No anime in this category.
}