feat: add salary insights
CI and Deploy / test (push) Successful in 2m41s
CI and Deploy / deploy (push) Successful in 58s

This commit is contained in:
cesnimda
2026-07-31 00:15:38 +02:00
parent af3cf1cdaa
commit 235d22c059
5 changed files with 83 additions and 4 deletions
@@ -50,6 +50,7 @@ type OverviewAnalytics = {
totalResponses: number;
totalActive: number;
timeInStage?: { stage: string; medianDays: number; count: number }[];
salaryInsights?: { currency: string; period: string; count: number; minimum: number; maximum: number; averageMidpoint: number }[];
};
type TagTrendResponse = { months: string[]; series: { tag: string; counts: number[] }[] };
@@ -528,6 +529,28 @@ export default function DashboardView() {
) : null}
</Box>
{(overview?.salaryInsights?.length ?? 0) > 0 ? (
<Box sx={{ mt: 2 }}>
<SectionCard>
<Typography variant="h6">Salary insights</Typography>
<Typography variant="body2" color="text.secondary" sx={{ mt: 0.5, mb: 1.5 }}>Comparable ranges from jobs in your tracker. Currencies and pay periods stay separate.</Typography>
<Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", md: "repeat(3, 1fr)" }, gap: 1.5 }}>
{overview!.salaryInsights!.map((item) => {
const money = new Intl.NumberFormat(undefined, { style: "currency", currency: item.currency, maximumFractionDigits: 0 });
return (
<Box key={item.currency + item.period} sx={{ p: 1.5, borderRadius: 3, backgroundColor: alpha(theme.palette.primary.main, 0.05) }}>
<Typography variant="caption" color="text.secondary">{item.currency} · per {item.period} · {item.count} {item.count === 1 ? "job" : "jobs"}</Typography>
<Typography variant="h6" sx={{ mt: 0.5 }}>{money.format(item.averageMidpoint)}</Typography>
<Typography variant="body2" color="text.secondary">Range {money.format(item.minimum)}{money.format(item.maximum)}</Typography>
</Box>
);
})}
</Box>
</SectionCard>
</Box>
) : null}
<Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", xl: "1.15fr 0.85fr" }, gap: 2, mt: 2 }}>
{!summaryResource.loading && !summaryResource.error ? (
<SectionCard>