diff --git a/job-tracker-ui/src/App.tsx b/job-tracker-ui/src/App.tsx
index 0210bd3..bb8e0cd 100644
--- a/job-tracker-ui/src/App.tsx
+++ b/job-tracker-ui/src/App.tsx
@@ -100,6 +100,16 @@ function titleFor(path: string, t: (k: any) => string): string {
return t("appTitle");
}
+function subtitleFor(path: string, t: (k: any) => string): string | undefined {
+ if (path === "/dashboard") return t("dashboardPageSubtitle");
+ if (path.startsWith("/jobs")) return t("jobsPageSubtitle");
+ if (path.startsWith("/kanban")) return t("kanbanPageSubtitle");
+ if (path.startsWith("/reminders")) return t("remindersPageSubtitle");
+ if (path.startsWith("/correspondence/review")) return t("gmailReviewPageSubtitle");
+ if (path.startsWith("/correspondence")) return t("correspondencePageSubtitle");
+ return undefined;
+}
+
function PageLoader() {
return Loading...;
}
@@ -209,6 +219,7 @@ function Shell({ jobPageSize, setJobPageSize, jobColumns, setJobColumns, themeMo
if (requireAuth && !me) return ;
const pageTitle = titleFor(path, t);
+ const pageSubtitle = subtitleFor(path, t);
const breadcrumbs = breadcrumbsFor(path, t);
const setAndPersistPageSize = (n: 15 | 20 | 25) => { setJobPageSize(n); window.localStorage.setItem("jobPageSize", String(n)); };
const setAndPersistColumns = (next: JobTableColumns) => { setJobColumns(next); window.localStorage.setItem("jobColumns", JSON.stringify(next)); };
@@ -275,6 +286,7 @@ function Shell({ jobPageSize, setJobPageSize, jobColumns, setJobColumns, themeMo
<>
{score.hasEnoughSignal ? (
-
-
+
+
diff --git a/job-tracker-ui/src/components/KanbanBoard.tsx b/job-tracker-ui/src/components/KanbanBoard.tsx
index 8ff8628..81d0164 100644
--- a/job-tracker-ui/src/components/KanbanBoard.tsx
+++ b/job-tracker-ui/src/components/KanbanBoard.tsx
@@ -101,7 +101,18 @@ export default function KanbanBoard() {
/>
{!jobsResource.loading && !jobsResource.error ? (
-
+
{STATUSES.map((status) => {
const c = toneColor(theme, status);
const list = groups.get(status) ?? [];
@@ -114,6 +125,8 @@ export default function KanbanBoard() {
p: 1.5,
borderRadius: 3,
minHeight: 220,
+ flex: { xs: "0 0 85vw", md: "none" },
+ scrollSnapAlign: { xs: "start", md: "none" },
border: "1px solid",
borderColor: "divider",
background: theme.palette.mode === "dark" ? alpha(theme.palette.common.white, 0.02) : alpha(theme.palette.text.primary, 0.015),
diff --git a/job-tracker-ui/src/i18n/translations.ts b/job-tracker-ui/src/i18n/translations.ts
index 76432ce..15a1855 100644
--- a/job-tracker-ui/src/i18n/translations.ts
+++ b/job-tracker-ui/src/i18n/translations.ts
@@ -18,6 +18,12 @@ export const translations = {
home: "Home",
analytics: "Analytics",
overview: "Overview",
+ dashboardPageSubtitle: "Your search at a glance — response rate, funnel, and what needs attention.",
+ jobsPageSubtitle: "Filter, search, and manage every application in one table.",
+ kanbanPageSubtitle: "Drag a card between stages to update its status.",
+ remindersPageSubtitle: "Everything due for follow-up, soonest first.",
+ correspondencePageSubtitle: "Every message linked to a job, in one inbox.",
+ gmailReviewPageSubtitle: "Review Gmail threads before linking them to a job.",
account: "Account",
profile: "Profile",
admin: "Admin",
@@ -981,6 +987,12 @@ export const translations = {
home: "Hjem",
analytics: "Analyse",
overview: "Oversikt",
+ dashboardPageSubtitle: "Søket ditt i korte trekk — svarrate, trakt og hva som trenger oppmerksomhet.",
+ jobsPageSubtitle: "Filtrer, søk og administrer alle søknader i én tabell.",
+ kanbanPageSubtitle: "Dra et kort mellom stadier for å oppdatere status.",
+ remindersPageSubtitle: "Alt som trenger oppfølging, snarest først.",
+ correspondencePageSubtitle: "Alle meldinger koblet til en jobb, i én innboks.",
+ gmailReviewPageSubtitle: "Se gjennom Gmail-tråder før du kobler dem til en jobb.",
account: "Konto",
profile: "Profil",
admin: "Admin",
diff --git a/job-tracker-ui/src/layout/AppShell.tsx b/job-tracker-ui/src/layout/AppShell.tsx
index ca6be3c..24ed3c4 100644
--- a/job-tracker-ui/src/layout/AppShell.tsx
+++ b/job-tracker-ui/src/layout/AppShell.tsx
@@ -59,6 +59,7 @@ const SIDEBAR_SELECTED_ICON = "#a5b4fc";
export default function AppShell({
pageTitle,
+ pageSubtitle,
breadcrumbs,
pathname,
nav,
@@ -76,6 +77,7 @@ export default function AppShell({
children,
}: {
pageTitle: string;
+ pageSubtitle?: string;
breadcrumbs: string[];
pathname: string;
nav: NavItem[];
@@ -481,6 +483,11 @@ export default function AppShell({
{pageTitle}
+ {pageSubtitle ? (
+
+ {pageSubtitle}
+
+ ) : null}
diff --git a/job-tracker-ui/src/views/CorrespondenceInboxPage.tsx b/job-tracker-ui/src/views/CorrespondenceInboxPage.tsx
index 2aed368..85d6b9f 100644
--- a/job-tracker-ui/src/views/CorrespondenceInboxPage.tsx
+++ b/job-tracker-ui/src/views/CorrespondenceInboxPage.tsx
@@ -82,10 +82,11 @@ export default function CorrespondenceInboxPage() {
Cross-job view of imported correspondence and Gmail-linked history.
-
+
} label={`${items.length} items`} variant="outlined" />
0 ? "success" : "default"} />
+
diff --git a/job-tracker-ui/src/views/GmailReviewPage.tsx b/job-tracker-ui/src/views/GmailReviewPage.tsx
index ea6fc33..4b058e9 100644
--- a/job-tracker-ui/src/views/GmailReviewPage.tsx
+++ b/job-tracker-ui/src/views/GmailReviewPage.tsx
@@ -138,6 +138,7 @@ export default function GmailReviewPage() {
+