Files
sis/src/Sis/Page/Activity.hs
T
jbrechtel 95ac550191 fix: update to correct NeoBrutalismCSS CDN and class names
- Switch CDN to jsdelivr (matches design spec)
- Use nb-card, nb-card-title, nb-button default, nb-checkbox, nb-navbar-link
- Add Google Fonts import for Lexend Mega
- Style all route links as nb-button default buttons
- Fix navbar to use nb-navbar-brand and nb-navbar-nav
- Update style.css for new NB version compatibility
2026-07-16 07:34:45 -04:00

108 lines
4.6 KiB
Haskell

{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-unused-imports -Wno-unused-do-bind -Wno-name-shadowing -Wno-redundant-constraints -Wno-redundant-constraints #-}
module Sis.Page.Activity (page) where
import Data.Text (Text)
import Data.Text qualified as T
import Effectful
import Sis.Database
import Sis.Route
import Sis.Style (nbBoxClass, nbButtonDefaultClass, nbInputClass, nbLabelClass, nbBadgeClass, nbHeadingClass, nbContainerClass, nbListItemClass, colorRed, colorYellow, colorGreen)
import Sis.Types
import Sis.View.Layout
import Web.Hyperbole
import Web.Hyperbole.Effect.Session
import Web.Hyperbole.Page
data ActivityPage = ActivityPage
deriving stock (Generic)
deriving anyclass (ViewId)
instance (DB :> es, IOE :> es) => HyperView ActivityPage es where
data Action ActivityPage
= RefreshActivity
| GoToPage Int
deriving stock (Generic)
deriving anyclass (ViewAction)
update RefreshActivity = do
update (GoToPage 1)
update (GoToPage pageNum) = do
mUser <- lookupSession @UserSession
case mUser of
Nothing -> pure (el "Not authenticated")
Just us -> do
hhs <- getUserHouseholds (UserId (usUserId us))
case hhs of
[] -> pure $ hyper ActivityPage $ el "No households"
(h : _) -> do
log <- getActivityLog (unHouseholdId (householdId h)) pageNum 20
pure $ hyper ActivityPage $ activityView log
activityView :: ActivityLogPage -> View ActivityPage ()
activityView log = do
el @ att "class" nbContainerClass @ att "style" "max-width:960px;margin:0 auto" $ do
el @ att "class" nbHeadingClass $ text "Activity Log"
if null (alpEntries log)
then el @ att "style" "opacity:0.5" $ text "No activity recorded yet."
else el @ att "class" nbBoxClass $ mapM_ entryRow (alpEntries log)
if alpTotal log > alpPerPage log
then el @ att "style" "margin-top:1rem;display:flex;gap:0.5rem;justify-content:center" $ do
let totalPages = (alpTotal log + alpPerPage log - 1) `div` alpPerPage log
if alpPage log > 1
then button (GoToPage (alpPage log - 1)) @ att "class" nbButtonDefaultClass $ text "Previous"
else none
el @ att "style" "align-self:center" $
text ("Page " <> T.pack (show (alpPage log)) <> " of " <> T.pack (show totalPages))
if alpPage log < totalPages
then button (GoToPage (alpPage log + 1)) @ att "class" nbButtonDefaultClass $ text "Next"
else none
else none
entryRow :: ActivityLogEntry -> View ActivityPage ()
entryRow e = do
let act = aleActivity e
statusText = case activityStatus act of
ActivityCompleted -> "COMPLETED"
ActivitySkipped -> "SKIPPED"
statusColor = case activityStatus act of
ActivityCompleted -> colorGreen
ActivitySkipped -> "var(--nb-orange)"
el @ att "class" nbListItemClass @ att "style" "padding:0.5rem" $ do
el @ att "class" nbBadgeClass @ att "style" ("margin-right:0.5rem;background:" <> statusColor <> ";color:#000") $
text statusText
el @ att "style" "font-weight:500" $ text (aleUserName e)
text (" " <> statusText <> " ")
el @ att "style" "font-weight:500" $ text (aleChoreName e)
el @ att "style" "opacity:0.5" $
text ("on " <> T.pack (show (aleOccurrenceDate e)))
case activityNote act of
Just note ->
el @ att "style" "opacity:0.5;font-style:italic;margin-left:0.5rem" $
text ("\"" <> note <> "\"")
Nothing -> none
page :: (Hyperbole :> es, DB :> es, IOE :> es) => Page es '[ActivityPage]
page = do
mSession <- lookupSession @UserSession
case mSession of
Nothing -> do
redirect (routeUri RLogin)
Just us -> do
hhs <- getUserHouseholds (UserId (usUserId us))
case hhs of
[] -> pure $ hyper ActivityPage $ el "No households"
(h : _) -> do
log <- getActivityLog (unHouseholdId (householdId h)) 1 20
pure $ hyper ActivityPage $ activityView log