style(ui): reduce initial dashboard gaps and flatten discovery rows
This commit is contained in:
@@ -38,6 +38,21 @@ test('default catalogue preserves every section and supported widths', () => {
|
||||
expect(defaultDashboardLayout().widgets[0].visible).toBe(true);
|
||||
});
|
||||
|
||||
test('initial dashboard keeps every widget in a denser bounded layout without resizing saved geometry', () => {
|
||||
const fresh = defaultDashboardLayout();
|
||||
expect(fresh.widgets).toHaveLength(10);
|
||||
expect(fresh.widgets.every(widget => widget.visible)).toBe(true);
|
||||
expect(Math.max(...fresh.widgets.map(widget => widget.y + widget.h))).toBeLessThanOrEqual(42);
|
||||
const saved = { version: 2, revision: 4, widgets: [
|
||||
{ id: 'sources', visible: true, size: 'standard', x: 0, y: 14, w: 6, h: 8 },
|
||||
{ id: 'salary', visible: false, size: 'full', x: 0, y: 26, w: 12, h: 12 },
|
||||
] };
|
||||
const normalized = normalizeDashboardLayout(saved);
|
||||
expect(normalized.revision).toBe(4);
|
||||
expect(normalized.widgets.slice(0, 2)).toEqual(saved.widgets);
|
||||
expect(normalized.widgets.slice(2).every(widget => !widget.visible)).toBe(true);
|
||||
});
|
||||
|
||||
test.each([1, 2])('new schema %s preferences use task-first A1 defaults without omitting widgets', version => {
|
||||
const layout = normalizeDashboardLayout({ version, revision: 0, widgets: [] });
|
||||
expect(layout.widgets[0]).toMatchObject({ id: 'attention', visible: true, x: 0, y: 0, w: 12 });
|
||||
|
||||
@@ -34,7 +34,8 @@ export function defaultDashboardLayout(): DashboardLayout {
|
||||
return { version: 2, revision: 0, widgets: arrangeDashboardWidgets(order.map(id => {
|
||||
const definition = WIDGETS.find(widget => widget.id === id)!;
|
||||
const w = id === 'attention' ? 12 : id === 'agenda' ? 8 : id === 'funnel' ? 4 : definition.defaultSize === 'full' ? 12 : 6;
|
||||
return { id, visible: true, size: w === 12 ? 'full' : 'standard', x: 0, y: 0, w, h: id === 'cards' ? 5 : id === 'attention' ? 9 : 8 };
|
||||
const h = id === 'cards' ? 5 : id === 'attention' ? 9 : ['stageAge', 'sources', 'salary', 'companies', 'skills'].includes(id) ? 4 : 8;
|
||||
return { id, visible: true, size: w === 12 ? 'full' : 'standard', x: 0, y: 0, w, h };
|
||||
})) };
|
||||
}
|
||||
|
||||
|
||||
@@ -192,8 +192,8 @@ export default function JobDiscoveryPage() {
|
||||
<TextField label={t("jobDiscoveryMunicipality")} value={location} disabled={busy} onChange={(event) => setLocation(event.target.value)} />
|
||||
<Button type="submit" variant="contained" startIcon={loading ? <CircularProgress aria-hidden="true" size={18} color="inherit" /> : <SearchIcon />} disabled={busy}>{t("jobDiscoverySearchNav")}</Button>
|
||||
</Box>
|
||||
<Card variant="outlined" aria-busy={savedSearchState === "loading"}>
|
||||
<CardContent sx={{ display: "grid", gap: 1.5, p: "var(--app-card-padding)", "&:last-child": { pb: "var(--app-card-padding)" } }}>
|
||||
<Box aria-busy={savedSearchState === "loading"}>
|
||||
<Box sx={{ display: "grid", gap: 1.5 }}>
|
||||
<Box>
|
||||
<Typography component="h2" variant="sectionTitle">{t("jobDiscoverySavedSearches")}</Typography>
|
||||
<Typography variant="body2" color="text.secondary">{t("jobDiscoverySavedSearchesHelp")}</Typography>
|
||||
@@ -226,8 +226,8 @@ export default function JobDiscoveryPage() {
|
||||
))}
|
||||
</Stack>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box role="region" aria-label={t("jobDiscoveryResults")} tabIndex={-1} ref={resultsRef} aria-busy={loading} sx={{ display: "grid", gap: 2, minWidth: 0 }}>
|
||||
<PageHeader level="h2" title={t("jobDiscoveryResults")} actions={<Button disabled={busy} onClick={() => queryRef.current?.focus()}>{t("jobDiscoveryReturnFilters")}</Button>} />
|
||||
@@ -252,8 +252,8 @@ export default function JobDiscoveryPage() {
|
||||
) : null}
|
||||
<Box sx={{ display: "grid", gridTemplateColumns: "minmax(0, 1fr)", gap: 2 }}>
|
||||
{sortedJobs.map((job) => (
|
||||
<Card key={job.id} component="article" aria-label={job.title} variant="outlined" sx={{ display: "flex", flexDirection: "column", minWidth: 0 }}>
|
||||
<CardContent sx={{ p: "var(--app-card-padding)" }}>
|
||||
<Card key={job.id} component="article" aria-label={job.title} variant="outlined" sx={{ display: "flex", flexDirection: "column", minWidth: 0, border: 0, borderBottom: 1, borderColor: "divider", borderRadius: 0, bgcolor: "transparent", overflow: "visible" }}>
|
||||
<CardContent sx={{ px: 0, py: 1.5 }}>
|
||||
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 1, mb: 1 }}>
|
||||
<Chip label={job.sourceName || job.source.toUpperCase()} size="small" color="primary" variant="outlined" />
|
||||
{job.isNew ? <Chip label={t("jobDiscoveryNewResult")} size="small" color="success" /> : null}
|
||||
@@ -270,7 +270,7 @@ export default function JobDiscoveryPage() {
|
||||
<Typography variant="caption" color="text.secondary">{t("jobDiscoveryWorkArrangementMissing")}</Typography>
|
||||
</Stack>
|
||||
</CardContent>
|
||||
<CardActions sx={{ mt: "auto", p: "var(--app-card-padding)", pt: 0, flexWrap: "wrap", gap: 1, "& .MuiButton-root": { ml: 0, whiteSpace: "normal", maxWidth: "100%" } }}>
|
||||
<CardActions sx={{ mt: "auto", px: 0, pt: 0, pb: 1.5, flexWrap: "wrap", gap: 1, "& .MuiButton-root": { ml: 0, whiteSpace: "normal", maxWidth: "100%" } }}>
|
||||
<Button href={job.url} target="_blank" rel="noreferrer">{t("jobDiscoveryViewListing")}</Button>
|
||||
<Button startIcon={<AddIcon />} onClick={() => navigate("/jobs?add=" + encodeURIComponent(job.url))}>{t("jobDiscoverySaveTracker")}</Button>
|
||||
{activeSavedSearchId !== null ? <Button color="inherit" disabled={busy} onClick={() => void dismissJob(job.id)}>{t("jobDiscoveryDismiss")}</Button> : null}
|
||||
|
||||
Reference in New Issue
Block a user