From 46cfbc511229afd12b834df04790440fbc192379 Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Thu, 27 Nov 2025 10:08:26 -0500 Subject: Replace back links with proper navbar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The implementation is complete: 1. **Created a shared `navbar` component** with Jr branding and navigati 2. **Replaced all back links** (`← Back to Dashboard`, `← Back to Tasks` 3. **Added navbar styling** in the Style.hs file, including: - Light mode styles - Dark mode styles - Mobile responsive styles 4. **Build passes** with `bild --test Omni/Jr.hs` Task-Id: t-149.2 --- Omni/Jr/Web.hs | 28 ++++++++++++++++++---------- Omni/Jr/Web/Style.hs | 49 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 14 deletions(-) (limited to 'Omni') diff --git a/Omni/Jr/Web.hs b/Omni/Jr/Web.hs index 9d46a78..1ecc034 100644 --- a/Omni/Jr/Web.hs +++ b/Omni/Jr/Web.hs @@ -114,6 +114,16 @@ pageHead title = ] Lucid.link_ [Lucid.rel_ "stylesheet", Lucid.href_ "/style.css"] +navbar :: (Monad m) => Lucid.HtmlT m () +navbar = + Lucid.nav_ [Lucid.class_ "navbar"] <| do + Lucid.a_ [Lucid.href_ "/", Lucid.class_ "navbar-brand"] "Jr" + Lucid.div_ [Lucid.class_ "navbar-links"] <| do + Lucid.a_ [Lucid.href_ "/", Lucid.class_ "navbar-link"] "Dashboard" + Lucid.a_ [Lucid.href_ "/tasks", Lucid.class_ "navbar-link"] "Tasks" + Lucid.a_ [Lucid.href_ "/ready", Lucid.class_ "navbar-link"] "Ready" + Lucid.a_ [Lucid.href_ "/stats", Lucid.class_ "navbar-link"] "Stats" + statusBadge :: (Monad m) => TaskCore.Status -> Lucid.HtmlT m () statusBadge status = let (cls, label) = case status of @@ -143,6 +153,7 @@ instance Lucid.ToHtml HomePage where Lucid.doctypehtml_ <| do pageHead "Jr Dashboard" Lucid.body_ <| do + navbar Lucid.div_ [Lucid.class_ "container"] <| do Lucid.h1_ "Jr Dashboard" @@ -188,8 +199,8 @@ instance Lucid.ToHtml ReadyQueuePage where Lucid.doctypehtml_ <| do pageHead "Ready Queue - Jr" Lucid.body_ <| do + navbar Lucid.div_ [Lucid.class_ "container"] <| do - Lucid.p_ [Lucid.class_ "back-link"] <| Lucid.a_ [Lucid.href_ "/"] "← Back to Dashboard" Lucid.h1_ <| Lucid.toHtml ("Ready Queue (" <> tshow (length tasks) <> " tasks)") if null tasks then Lucid.p_ [Lucid.class_ "empty-msg"] "No tasks are ready for work." @@ -201,8 +212,8 @@ instance Lucid.ToHtml TaskListPage where Lucid.doctypehtml_ <| do pageHead "Tasks - Jr" Lucid.body_ <| do + navbar Lucid.div_ [Lucid.class_ "container"] <| do - Lucid.p_ [Lucid.class_ "back-link"] <| Lucid.a_ [Lucid.href_ "/"] "← Back to Dashboard" Lucid.h1_ <| Lucid.toHtml ("Tasks (" <> tshow (length tasks) <> ")") Lucid.div_ [Lucid.class_ "filter-form"] <| do @@ -265,20 +276,19 @@ instance Lucid.ToHtml TaskDetailPage where Lucid.doctypehtml_ <| do pageHead "Task Not Found - Jr" Lucid.body_ <| do + navbar Lucid.div_ [Lucid.class_ "container"] <| do Lucid.h1_ "Task Not Found" Lucid.p_ <| do "The task " Lucid.code_ (Lucid.toHtml tid) " could not be found." - Lucid.p_ [Lucid.class_ "back-link"] <| Lucid.a_ [Lucid.href_ "/tasks"] "← Back to Tasks" toHtml (TaskDetailFound task allTasks activities) = Lucid.doctypehtml_ <| do pageHead (TaskCore.taskId task <> " - Jr") Lucid.body_ <| do + navbar Lucid.div_ [Lucid.class_ "container"] <| do - Lucid.p_ [Lucid.class_ "back-link"] <| Lucid.a_ [Lucid.href_ "/tasks"] "← Back to Tasks" - Lucid.h1_ <| Lucid.toHtml (TaskCore.taskTitle task) Lucid.div_ [Lucid.class_ "task-detail"] <| do @@ -439,20 +449,19 @@ instance Lucid.ToHtml TaskReviewPage where Lucid.doctypehtml_ <| do pageHead "Task Not Found - Jr Review" Lucid.body_ <| do + navbar Lucid.div_ [Lucid.class_ "container"] <| do Lucid.h1_ "Task Not Found" Lucid.p_ <| do "The task " Lucid.code_ (Lucid.toHtml tid) " could not be found." - Lucid.p_ [Lucid.class_ "back-link"] <| Lucid.a_ [Lucid.href_ "/tasks"] "← Back to Tasks" toHtml (ReviewPageFound task reviewInfo) = Lucid.doctypehtml_ <| do pageHead ("Review: " <> TaskCore.taskId task <> " - Jr") Lucid.body_ <| do + navbar Lucid.div_ [Lucid.class_ "container"] <| do - Lucid.p_ [Lucid.class_ "back-link"] <| Lucid.a_ [Lucid.href_ ("/tasks/" <> TaskCore.taskId task)] "← Back to Task" - Lucid.h1_ "Review Task" Lucid.div_ [Lucid.class_ "task-summary"] <| do @@ -517,9 +526,8 @@ instance Lucid.ToHtml StatsPage where Lucid.doctypehtml_ <| do pageHead "Task Statistics - Jr" Lucid.body_ <| do + navbar Lucid.div_ [Lucid.class_ "container"] <| do - Lucid.p_ [Lucid.class_ "back-link"] <| Lucid.a_ [Lucid.href_ "/"] "← Back to Dashboard" - Lucid.h1_ <| case maybeEpic of Nothing -> "Task Statistics" Just epicId -> Lucid.toHtml ("Statistics for Epic: " <> epicId) diff --git a/Omni/Jr/Web/Style.hs b/Omni/Jr/Web/Style.hs index 8b6a8a7..5aa9b62 100644 --- a/Omni/Jr/Web/Style.hs +++ b/Omni/Jr/Web/Style.hs @@ -142,6 +142,38 @@ layoutStyles = do navigationStyles :: Css navigationStyles = do + ".navbar" ? do + backgroundColor white + padding (px 12) (px 20) (px 12) (px 20) + boxShadow (NE.singleton (bsColor (rgba 0 0 0 0.08) (shadow (px 0) (px 2)))) + marginBottom (px 16) + display flex + alignItems center + justifyContent spaceBetween + flexWrap Flexbox.wrap + Stylesheet.key "gap" ("12px" :: Text) + ".navbar-brand" ? do + fontSize (px 22) + fontWeight bold + color "#0066cc" + textDecoration none + ".navbar-brand" # hover ? textDecoration none + ".navbar-links" ? do + display flex + Stylesheet.key "gap" ("4px" :: Text) + flexWrap Flexbox.wrap + ".navbar-link" ? do + display inlineBlock + padding (px 8) (px 14) (px 8) (px 14) + color "#374151" + textDecoration none + borderRadius (px 6) (px 6) (px 6) (px 6) + fontSize (px 14) + fontWeight (weight 500) + transition "background-color" (ms 150) ease (sec 0) + ".navbar-link" # hover ? do + backgroundColor "#f3f4f6" + textDecoration none header ? do backgroundColor white padding (px 12) (px 16) (px 12) (px 16) @@ -165,10 +197,6 @@ navigationStyles = do display flex Stylesheet.key "gap" ("8px" :: Text) flexWrap Flexbox.wrap - ".back-link" ? do - display inlineBlock - marginBottom (em 0.75) - fontSize (px 14) ".actions" ? do display flex flexWrap Flexbox.wrap @@ -530,6 +558,13 @@ responsiveStyles = do query Media.screen [Media.maxWidth (px 600)] <| do body ? fontSize (px 15) ".container" ? padding (px 12) (px 12) (px 12) (px 12) + ".navbar" ? do + flexDirection column + alignItems flexStart + padding (px 12) (px 12) (px 12) (px 12) + ".navbar-links" ? do + width (pct 100) + justifyContent center ".nav-content" ? do flexDirection column alignItems flexStart @@ -572,6 +607,12 @@ darkModeStyles = header ? do backgroundColor "#1f2937" boxShadow (NE.singleton (bsColor (rgba 0 0 0 0.3) (shadow (px 0) (px 2)))) + ".navbar" ? do + backgroundColor "#1f2937" + boxShadow (NE.singleton (bsColor (rgba 0 0 0 0.3) (shadow (px 0) (px 2)))) + ".navbar-brand" ? color "#60a5fa" + ".navbar-link" ? color "#d1d5db" + ".navbar-link" # hover ? backgroundColor "#374151" ".nav-brand" ? color "#f3f4f6" "h2" <> "h3" ? color "#d1d5db" a ? color "#60a5fa" -- cgit v1.2.3