계약 DTO SSOT 3차
This commit is contained in:
parent
1007eaf7d9
commit
480fbd543a
10 changed files with 90 additions and 162 deletions
|
|
@ -291,7 +291,7 @@ export default function Professor() {
|
|||
() => [
|
||||
{
|
||||
label: "검토 대기",
|
||||
value: dashboard?.pending_reviews.length ?? 0,
|
||||
value: dashboard?.pending_reviews?.length ?? 0,
|
||||
hint: "종료 회기",
|
||||
icon: "review" as const,
|
||||
},
|
||||
|
|
@ -303,13 +303,13 @@ export default function Professor() {
|
|||
},
|
||||
{
|
||||
label: "최근 세션",
|
||||
value: dashboard?.recent_sessions.length ?? 0,
|
||||
value: dashboard?.recent_sessions?.length ?? 0,
|
||||
hint: "종료 · 진행",
|
||||
icon: "play" as const,
|
||||
},
|
||||
{
|
||||
label: "위기 알림",
|
||||
value: dashboard?.safety_alerts.length ?? 0,
|
||||
value: dashboard?.safety_alerts?.length ?? 0,
|
||||
hint: "109 확인",
|
||||
icon: "alert" as const,
|
||||
},
|
||||
|
|
@ -328,12 +328,14 @@ export default function Professor() {
|
|||
],
|
||||
[dashboard, personaReviews.length],
|
||||
);
|
||||
const pendingCount = dashboard?.pending_reviews.length ?? 0;
|
||||
const pendingCount = dashboard?.pending_reviews?.length ?? 0;
|
||||
const hasPending = pendingCount > 0;
|
||||
const totalSessions = (dashboard?.active_sessions ?? 0) + (dashboard?.ended_sessions ?? 0);
|
||||
const personaReviewCount = personaReviews.length;
|
||||
const safetyAlerts = dashboard?.safety_alerts ?? [];
|
||||
const learnerGrowth = dashboard?.learner_growth ?? [];
|
||||
const pendingReviews = dashboard?.pending_reviews ?? [];
|
||||
const recentSessions = dashboard?.recent_sessions ?? [];
|
||||
|
||||
return (
|
||||
<AppShell>
|
||||
|
|
@ -630,13 +632,13 @@ export default function Professor() {
|
|||
<Kicker>검토 대기</Kicker>
|
||||
<h2>종료된 실제 회기</h2>
|
||||
</div>
|
||||
<Badge tone="accent">{dashboard?.pending_reviews.length ?? 0}건</Badge>
|
||||
<Badge tone="accent">{pendingReviews.length}건</Badge>
|
||||
</div>
|
||||
|
||||
<Card className="pf-panel">
|
||||
{dashboard && dashboard.pending_reviews.length > 0 ? (
|
||||
{pendingReviews.length > 0 ? (
|
||||
<div className="pf-list">
|
||||
{dashboard.pending_reviews.map((session) => (
|
||||
{pendingReviews.map((session) => (
|
||||
<article className="pf-session" key={session.session_id}>
|
||||
<span className="pf-session__dot" aria-hidden="true" />
|
||||
<div className="pf-session__main">
|
||||
|
|
@ -647,7 +649,7 @@ export default function Professor() {
|
|||
<code>{session.session_id}</code>
|
||||
</div>
|
||||
<div className="pf-session__meta">
|
||||
<span>{formatDateTime(session.ended_at)}</span>
|
||||
<span>{formatDateTime(session.ended_at ?? null)}</span>
|
||||
<Badge tone="neutral">교수자 리뷰 대기</Badge>
|
||||
</div>
|
||||
</article>
|
||||
|
|
@ -669,11 +671,11 @@ export default function Professor() {
|
|||
<Kicker>최근 세션</Kicker>
|
||||
<h2>최근 회기 기록</h2>
|
||||
</div>
|
||||
<Badge tone="neutral">{dashboard?.recent_sessions.length ?? 0}건</Badge>
|
||||
<Badge tone="neutral">{recentSessions.length}건</Badge>
|
||||
</div>
|
||||
|
||||
<Card className="pf-panel">
|
||||
{dashboard && dashboard.recent_sessions.length > 0 ? (
|
||||
{recentSessions.length > 0 ? (
|
||||
<div className="pf-recent-list">
|
||||
<div className="pf-recent-head" aria-hidden="true">
|
||||
<span>학습자</span>
|
||||
|
|
@ -684,7 +686,7 @@ export default function Professor() {
|
|||
<span>시작</span>
|
||||
<span>종료</span>
|
||||
</div>
|
||||
{dashboard.recent_sessions.map((session) => (
|
||||
{recentSessions.map((session) => (
|
||||
<article
|
||||
className="pf-recent-row"
|
||||
key={session.session_id}
|
||||
|
|
@ -712,7 +714,7 @@ export default function Professor() {
|
|||
{formatDateTime(session.started_at)}
|
||||
</span>
|
||||
<span className="pf-recent__cell tabular" data-label="종료">
|
||||
{formatDateTime(session.ended_at)}
|
||||
{formatDateTime(session.ended_at ?? null)}
|
||||
</span>
|
||||
</article>
|
||||
))}
|
||||
|
|
@ -732,7 +734,9 @@ export default function Professor() {
|
|||
}
|
||||
|
||||
function GrowthCard({ learner }: { learner: TeacherLearnerGrowth }) {
|
||||
const recentPoints = learner.points.slice(-3).reverse();
|
||||
const points = learner.points ?? [];
|
||||
const topTechniques = learner.top_techniques ?? [];
|
||||
const recentPoints = points.slice(-3).reverse();
|
||||
return (
|
||||
<article className={`pf-growth-card trend-${learner.trend}`}>
|
||||
<div className="pf-growth-card__top">
|
||||
|
|
@ -763,14 +767,14 @@ function GrowthCard({ learner }: { learner: TeacherLearnerGrowth }) {
|
|||
</div>
|
||||
|
||||
<div className="pf-growth-bars" aria-label="회기별 적절성 추이">
|
||||
{learner.points.map((point) => (
|
||||
{points.map((point) => (
|
||||
<GrowthBar point={point} key={point.session_id} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="pf-growth-card__tags">
|
||||
{learner.top_techniques.length > 0 ? (
|
||||
learner.top_techniques.map((tag) => <span key={tag}>{tag}</span>)
|
||||
{topTechniques.length > 0 ? (
|
||||
topTechniques.map((tag) => <span key={tag}>{tag}</span>)
|
||||
) : (
|
||||
<span>기법 태그 부족</span>
|
||||
)}
|
||||
|
|
@ -1092,6 +1096,9 @@ const PF_CSS = `
|
|||
background:linear-gradient(180deg,var(--bg-surface),color-mix(in srgb,var(--accent-tint) 18%,var(--bg-surface)));
|
||||
}
|
||||
.pf-growth-list{
|
||||
max-height:min(540px,52vh);
|
||||
overflow:auto;
|
||||
scrollbar-gutter:stable;
|
||||
display:grid;
|
||||
grid-template-columns:repeat(3,minmax(0,1fr));
|
||||
gap:12px;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue