feat(ux): first-time onboarding, empty states, and copy fixes
Implements the six "propose first" items from the product/UX review: - "/" now redirects to /dashboard instead of the empty /jobs table -- a new user's first screen is now an overview with orientation, not a data table with zero rows and four filter dropdowns. - Jobs table gets a real first-time empty state (distinct from "no results match your filters") pointing at Add Job and the bookmarklet, instead of a bare "No jobs found." - Match Score card and Candidate Fit tab now each get a one-line caption explaining what they are and how they differ (deterministic keyword coverage vs. AI opinion) -- they previously sat side by side with no explanation of why there are two. - Google sign-in hint now reflects self-serve signup when Auth:AllowRegistration is on, instead of always implying you need an existing linked account. - Quick Search button now shows its keyboard shortcut (Ctrl+K / ⌘K) inline instead of being undiscoverable.
This commit is contained in:
@@ -123,6 +123,9 @@ function Shell({ jobPageSize, setJobPageSize, jobColumns, setJobColumns, themeMo
|
||||
|
||||
const path = location.pathname;
|
||||
const isJobs = path.startsWith("/jobs");
|
||||
const shortcutHint = useMemo(() => (
|
||||
typeof navigator !== "undefined" && /Mac|iPhone|iPod|iPad/.test(navigator.platform) ? "⌘K" : "Ctrl+K"
|
||||
), []);
|
||||
|
||||
useEffect(() => {
|
||||
api.get<AuthConfig>("/auth/config").then((r) => setRequireAuth(Boolean(r.data?.requireAuth))).catch(() => setRequireAuth(false));
|
||||
@@ -246,14 +249,19 @@ function Shell({ jobPageSize, setJobPageSize, jobColumns, setJobColumns, themeMo
|
||||
<IconButton
|
||||
color="secondary"
|
||||
size="small"
|
||||
title={t("quickSearch")}
|
||||
title={`${t("quickSearch")} (${shortcutHint})`}
|
||||
onClick={() => setQuickOpen(true)}
|
||||
sx={{ border: "1px solid", borderColor: "divider", borderRadius: 2.5, width: 42, height: 42, flex: "0 0 auto" }}
|
||||
>
|
||||
<SearchIcon fontSize="small" />
|
||||
</IconButton>
|
||||
) : (
|
||||
<Button variant="outlined" startIcon={<SearchIcon />} onClick={() => setQuickOpen(true)}>{t("quickSearch")}</Button>
|
||||
<Button variant="outlined" startIcon={<SearchIcon />} onClick={() => setQuickOpen(true)} sx={{ gap: 0.5 }}>
|
||||
{t("quickSearch")}
|
||||
<Box component="span" sx={{ ml: 0.75, px: 0.75, py: 0.125, borderRadius: 1, border: "1px solid", borderColor: "divider", fontSize: 11, fontWeight: 700, color: "text.secondary", lineHeight: 1.6 }}>
|
||||
{shortcutHint}
|
||||
</Box>
|
||||
</Button>
|
||||
)}
|
||||
{isJobs ? (
|
||||
<Button variant="contained" onClick={() => setAddOpen(true)} sx={{ flex: { xs: 1, sm: "0 0 auto" }, minHeight: 42 }}>
|
||||
@@ -284,7 +292,7 @@ function Shell({ jobPageSize, setJobPageSize, jobColumns, setJobColumns, themeMo
|
||||
>
|
||||
<Suspense fallback={<PageLoader />}>
|
||||
<Routes>
|
||||
<Route path="/" element={<Navigate to="/jobs" replace />} />
|
||||
<Route path="/" element={<Navigate to="/dashboard" replace />} />
|
||||
<Route path="/dashboard" element={<DashboardView />} />
|
||||
<Route path="/jobs" element={<JobTable refreshToken={refreshToken} pageSize={jobPageSize} onPageSizeChange={setAndPersistPageSize} columns={jobColumns} onColumnsChange={setAndPersistColumns} mode="jobs" />} />
|
||||
<Route path="/reminders" element={<RemindersView />} />
|
||||
|
||||
Reference in New Issue
Block a user