feat(ui): redesign job workspace sections
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
|
||||
import {
|
||||
Alert, Box, Chip, Divider, LinearProgress, Paper, Skeleton, Stack, ToggleButton,
|
||||
Alert, Box, Chip, LinearProgress, Stack, ToggleButton,
|
||||
ToggleButtonGroup, Typography,
|
||||
} from "@mui/material";
|
||||
|
||||
@@ -10,6 +10,8 @@ import {
|
||||
CareerMatch, JobAnalysis, Timeline, applicationIntelligenceApi,
|
||||
} from "../applicationWorkspace";
|
||||
import { useI18n } from "../i18n/I18nProvider";
|
||||
import { PageSection } from "../layout/PageLayout";
|
||||
import ViewStateNotice from "./ViewStateNotice";
|
||||
|
||||
// Phase 5.3 — Application Intelligence sections for the workspace.
|
||||
//
|
||||
@@ -62,20 +64,14 @@ function SectionShell({ title, subtitle, loading, error, empty, emptyText, child
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<Paper sx={{ p: { xs: 2, sm: 2.5 }, borderRadius: 3 }}>
|
||||
<Typography variant="subtitle2" sx={{ fontWeight: 800 }}>{title}</Typography>
|
||||
{subtitle && <Typography variant="caption" color="text.secondary">{subtitle}</Typography>}
|
||||
<Divider sx={{ my: 1.5 }} />
|
||||
{loading ? (
|
||||
<Stack spacing={1}>{[0, 1, 2].map((i) => <Skeleton key={i} variant="rounded" height={40} />)}</Stack>
|
||||
) : error ? (
|
||||
<Alert severity="error">{error}</Alert>
|
||||
) : empty ? (
|
||||
<PageSection surface title={title} description={subtitle} level="h3">
|
||||
<ViewStateNotice title={title} loading={loading} error={error ? { kind: "error", message: error, retryable: false } : null} compact />
|
||||
{!loading && !error && (empty ? (
|
||||
<Typography variant="body2" color="text.secondary">{emptyText}</Typography>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</Paper>
|
||||
))}
|
||||
</PageSection>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -123,11 +119,10 @@ export function ApplicationTimeline({ jobId }: { jobId: number }) {
|
||||
return (
|
||||
<Stack spacing={2}>
|
||||
{hasEvents && (data?.milestones.length ?? 0) > 0 && (
|
||||
<Paper sx={{ p: 2, borderRadius: 3 }}>
|
||||
<Typography variant="subtitle2" sx={{ fontWeight: 800, mb: 1 }}>{t("intelligenceMilestones")}</Typography>
|
||||
<PageSection surface title={t("intelligenceMilestones")} level="h3">
|
||||
<Stack spacing={0.75}>
|
||||
{(data?.milestones ?? []).map((m) => (
|
||||
<Stack key={m.id} direction="row" spacing={1} justifyContent="space-between" alignItems="baseline">
|
||||
<Stack key={m.id} direction={{ xs: "column", sm: "row" }} spacing={0.5} justifyContent="space-between" alignItems="baseline">
|
||||
<Typography variant="body2" sx={{ fontWeight: 600 }}>{m.summary}</Typography>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{new Date(m.at).toLocaleDateString(language === "nb" ? "nb-NO" : "en")}
|
||||
@@ -135,7 +130,7 @@ export function ApplicationTimeline({ jobId }: { jobId: number }) {
|
||||
</Stack>
|
||||
))}
|
||||
</Stack>
|
||||
</Paper>
|
||||
</PageSection>
|
||||
)}
|
||||
|
||||
<SectionShell
|
||||
@@ -173,11 +168,12 @@ export function ApplicationTimeline({ jobId }: { jobId: number }) {
|
||||
(data?.days ?? []).map((day) => (
|
||||
<Box key={day.date}>
|
||||
<Typography variant="caption" sx={{ fontWeight: 800, textTransform: "uppercase", letterSpacing: ".06em", color: "text.secondary" }}>
|
||||
{day.label}
|
||||
{new Date(`${day.date.slice(0, 10)}T12:00:00`).toLocaleDateString(language === "nb" ? "nb-NO" : "en", { dateStyle: "long" })}
|
||||
</Typography>
|
||||
<Stack spacing={1} sx={{ mt: 0.75, pl: 1.5, borderLeft: "2px solid", borderColor: "divider" }}>
|
||||
<Stack component="ol" spacing={1.5} sx={{ mt: 0.75, mb: 0, pl: 1.5, listStyle: "none", borderLeft: "2px solid", borderColor: "divider" }}>
|
||||
{day.events.map((e) => (
|
||||
<Box key={e.id} sx={{ pl: 1.5 }}>
|
||||
<Box component="li" key={e.id} sx={{ pl: 1, overflowWrap: "anywhere" }}>
|
||||
<Typography component="time" dateTime={e.at} variant="caption" color="text.secondary">{new Date(e.at).toLocaleTimeString(language === "nb" ? "nb-NO" : "en", { hour: "2-digit", minute: "2-digit", timeZone: "UTC", timeZoneName: "short" })} · {timelineCategoryLabel(t, e.category)}</Typography>
|
||||
<Stack direction="row" spacing={0.75} alignItems="center" flexWrap="wrap">
|
||||
<Typography variant="body2" sx={{ fontWeight: e.isMilestone ? 700 : 500 }}>
|
||||
{e.summary}
|
||||
|
||||
Reference in New Issue
Block a user