package templates import "mal/internal/jikan" import "mal/internal/shared/ui" import "fmt" import "strings" templ AnimeDetails(anime jikan.Anime, currentStatus string) { @Layout("mal - " + anime.DisplayTitle(), true) {
if anime.ImageURL() != "" { { } else {
No image
}

{ anime.DisplayTitle() }

if anime.TitleJapanese != "" {

{ anime.TitleJapanese }

}
if anime.ShortRating() != "" { { anime.ShortRating() } } if anime.Type != "" { { anime.Type } } if anime.Episodes > 0 { { fmt.Sprintf("%d ep", anime.Episodes) } } if anime.ShortDuration() != "" { { anime.ShortDuration() } }
@WatchlistDropdown(anime.MalID, anime.Title, anime.TitleEnglish, anime.TitleJapanese, anime.ImageURL(), currentStatus, anime.Airing) Watch
if anime.Synopsis != "" {

{ anime.Synopsis }

} else {

No synopsis available.

}

Related

@ui.LoadingIndicator("Loading relations")

Recommendations

@ui.LoadingIndicator("Loading recommendations")
} } templ AnimePending(id int) { @Layout("mal - anime pending", true) {

Anime data is being fetched

We could not load this anime right now. A background worker is retrying data fetch for anime #{ fmt.Sprintf("%d", id) }.

Refresh this page in a few seconds.

} } func joinNames(entities []jikan.NamedEntity) string { names := make([]string, len(entities)) for i, e := range entities { names[i] = e.Name } return strings.Join(names, ", ") } func joinStreamingNames(anime jikan.Anime) string { names := make([]string, len(anime.Streaming)) for i, s := range anime.Streaming { names[i] = s.Name } return strings.Join(names, ", ") } templ WatchlistDropdown(animeID int, animeTitle string, animeTitleEnglish string, animeTitleJapanese string, animeImage string, currentStatus string, airing bool) {
} templ dropdownStatusOption(animeID int, animeTitle string, animeTitleEnglish string, animeTitleJapanese string, animeImage string, status string, currentStatus string, airing bool) { } func formatStatus(status string) string { switch status { case "watching": return "Watching" case "completed": return "Completed" case "on_hold": return "On hold" case "dropped": return "Dropped" case "plan_to_watch": return "Plan to watch" default: return status } } templ AnimeRelationsList(relations []jikan.RelationEntry) { if len(relations) > 1 {
for _, rel := range relations { @ui.AnimeCard(ui.AnimeCardProps{ ID: rel.Anime.MalID, Title: rel.Anime.DisplayTitle(), ImageURL: rel.Anime.ImageURL(), Class: relationCardClass(rel), ImgClass: "relation-thumb", TitleClass: "relation-title", CurrentNode: rel.IsCurrent, }) { if rel.Relation != "" && rel.Relation != "Current" {
{ rel.Relation }
} } }
} else {

No related anime found.

} } func relationCardClass(rel jikan.RelationEntry) string { base := "relation-card" if rel.IsCurrent { base += " current" } return base } templ AnimeRecommendations(recs []jikan.Anime) { if len(recs) > 0 {
for _, anime := range recs { @ui.AnimeCard(ui.AnimeCardProps{ ID: anime.MalID, Title: anime.DisplayTitle(), ImageURL: anime.ImageURL(), Class: "relation-card", ImgClass: "relation-thumb", TitleClass: "relation-title", }) }
} else {

No recommendations available.

} } func hasExtraSidebarDetails(anime jikan.Anime) bool { return anime.TitleJapanese != "" || len(anime.TitleSynonyms) > 0 || len(anime.Studios) > 0 || len(anime.Producers) > 0 || anime.Source != "" || len(anime.Demographics) > 0 || len(anime.Themes) > 0 || anime.Broadcast.String != "" || len(anime.Streaming) > 0 } templ studioLinks(studios []jikan.NamedEntity) { for i, studio := range studios { { studio.Name } if i < len(studios)-1 { , } } }