← Back to task

Commit 39e94ca2

commit 39e94ca23b77af5634abfa7787033e23960e08d4
Author: Coder Agent <coder@agents.omni>
Date:   Mon Feb 16 19:04:25 2026

    Unify top nav links across tasks, news, and files
    
    Add shared top-level links (/tasks, /news, /files)
    in Task Web, Newsreader, and Serve pages.
    This keeps navigation consistent from every entrypoint.
    
    Also handle TaskCore.Verified in Task Web status
    badge and dropdown rendering.
    
    Task-Id: t-613
    Task-Id: t-614

diff --git a/Omni/Newsreader/Web.hs b/Omni/Newsreader/Web.hs
index 38259a69..5d6064ad 100644
--- a/Omni/Newsreader/Web.hs
+++ b/Omni/Newsreader/Web.hs
@@ -318,8 +318,11 @@ articleCard p' feedMap art = do
 nav :: Pfx -> L.Html ()
 nav p' =
   L.nav_ <| do
-    L.a_ [L.href_ (p' "/"), L.class_ "brand"] "newsreader"
+    L.a_ [L.href_ "/tasks", L.class_ "brand"] "omni"
     L.span_ [L.class_ "nav-links"] <| do
+      L.a_ [L.href_ "/tasks"] "tasks"
+      L.a_ [L.href_ "/news/"] "news"
+      L.a_ [L.href_ "/files/"] "files"
       L.a_ [L.href_ (p' "/topics")] "topics"
       L.a_ [L.href_ (p' "/feeds")] "feeds"
       L.a_ [L.href_ (p' "/search")] "search"
diff --git a/Omni/Serve.hs b/Omni/Serve.hs
index 9fd6de9d..077a92d1 100755
--- a/Omni/Serve.hs
+++ b/Omni/Serve.hs
@@ -183,6 +183,14 @@ breadcrumbs p' relPath = do
   where
     parts = filter (/= ".") (FP.splitDirectories relPath)
 
+-- | Shared Omni top navigation.
+topNav :: L.Html ()
+topNav =
+  L.nav_ [L.class_ "topnav"] <| do
+    L.a_ [L.href_ "/tasks", L.class_ "topnav-link"] "tasks"
+    L.a_ [L.href_ "/news/", L.class_ "topnav-link"] "news"
+    L.a_ [L.href_ "/files/", L.class_ "topnav-link"] "files"
+
 -- | Common page shell with CSS.
 pageShell :: Text -> L.Html () -> L.Html ()
 pageShell title body =
@@ -192,7 +200,9 @@ pageShell title body =
       L.meta_ [L.name_ "viewport", L.content_ "width=device-width, initial-scale=1"]
       L.title_ (L.toHtml title)
       L.style_ css
-    L.body_ body
+    L.body_ <| do
+      topNav
+      body
 
 -- | Stylesheet.
 css :: Text
@@ -210,6 +220,10 @@ css =
       "  background: var(--bg); color: var(--fg); line-height: 1.6; }",
       "a { color: var(--link); text-decoration: none; }",
       "a:hover { text-decoration: underline; }",
+      ".topnav { display: flex; gap: 1rem; align-items: baseline;",
+      "  border-bottom: 1px solid var(--border); margin: 0 0 1rem; padding: 0.5rem 0; }",
+      ".topnav-link { color: var(--muted); font-size: 0.95rem; }",
+      ".topnav-link:hover { color: var(--fg); }",
       ".breadcrumb { font-size: 0.85rem; color: var(--muted); margin-bottom: 1rem; }",
       "h1 { font-size: 1.5rem; margin: 0 0 1rem; }",
       "",
diff --git a/Omni/Task/Web/Components.hs b/Omni/Task/Web/Components.hs
index 364f5235..275d542e 100644
--- a/Omni/Task/Web/Components.hs
+++ b/Omni/Task/Web/Components.hs
@@ -569,7 +569,9 @@ navbar =
         Lucid.span_ [Lucid.class_ "hamburger-line"] ""
         Lucid.span_ [Lucid.class_ "hamburger-line"] ""
     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_ "/news/", Lucid.class_ "navbar-link"] "News"
+      Lucid.a_ [Lucid.href_ "/files/", Lucid.class_ "navbar-link"] "Files"
       Lucid.div_ [Lucid.class_ "navbar-dropdown"] <| do
         Lucid.button_ [Lucid.class_ "navbar-dropdown-btn"] "Tasks ▾"
         Lucid.div_ [Lucid.class_ "navbar-dropdown-content"] <| do
@@ -596,6 +598,7 @@ statusBadge status =
         TaskCore.ReviewInProgress -> ("badge badge-review", "Review In Progress")
         TaskCore.Approved -> ("badge badge-approved", "Approved")
         TaskCore.Integrating -> ("badge badge-inprogress", "Integrating")
+        TaskCore.Verified -> ("badge badge-approved", "Verified")
         TaskCore.Done -> ("badge badge-done", "Done")
         TaskCore.NeedsHelp -> ("badge badge-needshelp", "Needs Help")
    in Lucid.span_ [Lucid.class_ cls] label
@@ -734,6 +737,7 @@ clickableBadge status _tid =
         TaskCore.ReviewInProgress -> ("badge badge-review status-badge-clickable", "Review In Progress")
         TaskCore.Approved -> ("badge badge-approved status-badge-clickable", "Approved")
         TaskCore.Integrating -> ("badge badge-inprogress status-badge-clickable", "Integrating")
+        TaskCore.Verified -> ("badge badge-approved status-badge-clickable", "Verified")
         TaskCore.Done -> ("badge badge-done status-badge-clickable", "Done")
         TaskCore.NeedsHelp -> ("badge badge-needshelp status-badge-clickable", "Needs Help")
    in Lucid.span_
@@ -764,6 +768,7 @@ statusDropdownOptions currentStatus tid =
       statusOption TaskCore.ReviewInProgress currentStatus tid
       statusOption TaskCore.Approved currentStatus tid
       statusOption TaskCore.Integrating currentStatus tid
+      statusOption TaskCore.Verified currentStatus tid
       statusOption TaskCore.Done currentStatus tid
       statusOption TaskCore.NeedsHelp currentStatus tid
 
@@ -777,6 +782,7 @@ statusOption opt currentStatus tid =
         TaskCore.ReviewInProgress -> ("badge badge-review", "Review In Progress")
         TaskCore.Approved -> ("badge badge-approved", "Approved")
         TaskCore.Integrating -> ("badge badge-inprogress", "Integrating")
+        TaskCore.Verified -> ("badge badge-approved", "Verified")
         TaskCore.Done -> ("badge badge-done", "Done")
         TaskCore.NeedsHelp -> ("badge badge-needshelp", "Needs Help")
       isSelected = opt == currentStatus