wikimusic-ssr-1.0.1.6: src/WikiMusic/SSR/View/Components/Other.hs
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module WikiMusic.SSR.View.Components.Other
( likeCount,
dislikeCount,
simpleEntityCard,
imageCarousel,
warningBanner,
entityDetails,
)
where
import Principium
import Text.Blaze.Html5 as H hiding (head, map)
import Text.Blaze.Html5.Attributes as A
import WikiMusic.Model.Artwork
import WikiMusic.SSR.View.Components.DetailList
import WikiMusic.SSR.View.Components.Forms
likeCount entity =
packText
. show
. length
$ mapElems
$ mapFilter (^. #opinion % #isLike) (entity ^. #opinions)
dislikeCount entity =
packText
. show
. length
$ mapElems
$ mapFilter (^. #opinion % #isDislike) (entity ^. #opinions)
mkIdentifierHref :: Text -> UUID -> AttributeValue
mkIdentifierHref path identifier = fromString ("/" <> unpackText path <> "/" <> show identifier)
-- use dark: in tailwind to use system dark / light mode, or use vv to read from cookie
simpleEntityCard vv path entity = article
! css'
[ "bg-slate-100",
"rounded-2xl",
"flex",
"flex-wrap",
"gap-4",
"flex-row",
"md:flex-col",
"max-w-56",
"border",
if vv ^. #uiMode % #value == "dark" then "dark:bg-black/70" else "bg-white/80",
"border-" <> vv ^. #palette % #value <> "-300/50"
]
$ do
maybeImg
H.div ! css' ["px-4", "py-4", "flex", "flex-col", "gap-4", "align-center"] $ do
a
! href (mkIdentifierHref path (entity ^. #identifier))
$ (h3 ! css' ["text-xl", "font-bold", "break-words", "text-center", if vv ^. #uiMode % #value == "dark" then "text-white" else "text-black"])
. text
$ entity
^. #displayName
detailList $ do
detailListEntry vv ((^. #more % #likes) |##| (vv ^. #language)) (text $ likeCount entity)
detailListEntry vv ((^. #more % #dislikes) |##| (vv ^. #language)) (text $ dislikeCount entity)
detailListEntry vv ((^. #more % #views) |##| (vv ^. #language)) (text . packText . show $ entity ^. #viewCount)
where
artworks = map (\x -> x ^. #artwork) (mapElems $ entity ^. #artworks) :: [Artwork]
sortedArts = sortBy (\x y -> compare (x ^. #orderValue) (y ^. #orderValue)) artworks
maybeImg = maybe (H.span "") (toImg . head) (nonEmpty sortedArts)
toImg x =
a
! href (mkIdentifierHref path (entity ^. #identifier))
$ img
! css' ["object-cover", "w-60", "h-60", "rounded-2xl"]
! customAttribute "loading" "lazy"
! src (fromString . unpackText $ x ^. #contentUrl)
imageCarousel :: [Artwork] -> Html
imageCarousel artworks =
section ! class_ "flex flex-wrap flex-col gap-6" $ do
mapM_
( \x ->
H.div $ do
img
! css' ["object-cover", "w-72", "h-72", "rounded-2xl"]
! customAttribute "loading" "lazy"
! src (fromString . unpackText $ x ^. #contentUrl)
mapM_ (H.span . text) (x ^. #contentCaption)
)
artworks
entityDetailsSkeleton :: Html -> Html -> Html
entityDetailsSkeleton slot0 slot1 =
H.div ! css' ["flex", "flex-row", "flex-wrap", "container", "mx-auto"] $ do
H.div ! css' ["flex", "flex-col", "flex-wrap", "w-full", "md:w-1/2"] $ do
slot0
H.div ! css' ["flex", "flex-col", "flex-wrap", "w-full", "md:w-1/2", "my-4"] $ do
slot1
hiddenUriLink' vv txt uri = a ! target "_blank" ! css (cssLink vv) ! href (fromString . unpackText $ uri) $ text ("🔗 " <> txt)
entityLinks vv x = do
mapM_
(hiddenUriLink' vv "Spotify")
(x ^. #spotifyUrl)
mapM_
(hiddenUriLink' vv "Wikipedia")
(x ^. #wikipediaUrl)
mapM_
(hiddenUriLink' vv "YouTube")
(x ^. #youtubeUrl)
mapM_
(hiddenUriLink' vv "SoundCloud")
(x ^. #soundcloudUrl)
slot0 vv x = do
H.div ! css' ["flex", "flex-col", "flex-wrap", "justify-center", "align-center", "gap-4"] $ do
imageCarousel (map (^. #artwork) (mapElems $ x ^. #artworks))
mapM_ ((p ! css' ["white-space-break-spaces", if vv ^. #uiMode % #value == "dark" then "text-white" else "text-black"]) . text) (x ^. #description)
slot1 vv path x = section
! css'
[ "flex",
"flex-col",
"flex-wrap",
"items-center",
"gap-8"
]
$ do
( h3
! css'
[ "text-3xl",
"text-black",
"font-bold",
if vv ^. #uiMode % #value == "dark" then "text-white" else "text-black"
]
)
. fromString
. unpackText
$ (x ^. #displayName)
H.div ! css' ["flex", "flex-row", "flex-wrap", "justify-center", "gap-4"] $ do
likesDislikes vv path' x
entityButtons vv path' x
section
! css' ["flex", "flex-row", "flex-wrap", "justify-center", "gap-4"]
$ detailList
$ do
entityBaseDetails vv x
hr
H.div ! css' ["flex", "flex-row", "flex-wrap", "justify-center", "gap-6"] $ entityLinks vv x
where
path' = unpackText path
entityDetails vv path x = do
entityDetailsSkeleton (slot0 vv x) (slot1 vv path x)
likesDislikes vv path' x = do
postForm (fromString ("/" <> path' <> "/like/" <> show (x ^. #identifier))) $ do
button ! css (cssButton vv) ! type_ "submit" $ do
H.span "+"
text ((^. #buttons % #like) |##| (vv ^. #language))
postForm (fromString ("/" <> path' <> "/dislike/" <> show (x ^. #identifier))) $ do
button ! css (cssButton vv) ! type_ "submit" $ do
H.span "-"
text ((^. #buttons % #dislike) |##| (vv ^. #language))
entityBaseDetails vv x = do
detailListEntry vv ((^. #more % #likes) |##| (vv ^. #language)) (text $ likeCount x)
detailListEntry vv ((^. #more % #dislikes) |##| (vv ^. #language)) (text $ dislikeCount x)
detailListEntry vv ((^. #more % #views) |##| (vv ^. #language)) (show $ x ^. #viewCount)
detailListEntry vv ((^. #more % #createdAt) |##| (vv ^. #language)) (show $ x ^. #createdAt)
mapM_
(detailListEntry vv ((^. #more % #lastEditedAt) |##| (vv ^. #language)))
(show <$> x ^. #lastEditedAt)
detailListEntry vv ((^. #more % #createdBy) |##| (vv ^. #language)) (show $ x ^. #createdBy)
entityButtons vv path' x = do
a
! href (fromString ("/" <> path' <> "/edit/" <> show (x ^. #identifier)))
$ button
! css (cssButton vv)
$ text ((^. #buttons % #edit) |##| (vv ^. #language))
dangerPostForm vv (fromString ("/" <> path' <> "/delete/" <> show (x ^. #identifier))) $ do
deleteButton vv
warningBanner :: ViewVars -> Html
warningBanner vv =
section $ do
small
! class_ "warning-text"
$ text
((^. #more % #warningHeavyDevelopment) |##| (vv ^. #language))