You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
60 lines
1.8 KiB
TypeScript
60 lines
1.8 KiB
TypeScript
// frontend/components/weekly/WeeklyReview.tsx — 주간 리뷰(딥워크/회의 집계 + 패턴 제안)
|
|
"use client";
|
|
import { Icon } from "@/components/Icon";
|
|
import type { WeeklyReview as WeeklyReviewT, WeeklyReviewPattern } from "@/lib/types";
|
|
|
|
function Stat({ n, unit, label }: { n: string; unit?: string; label: string }) {
|
|
return (
|
|
<div className="wr-stat">
|
|
<div className="wr-n">
|
|
{n}
|
|
{unit && <span className="wr-u">{unit}</span>}
|
|
</div>
|
|
<div className="wr-l">{label}</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function WeeklyReview({
|
|
review,
|
|
onApply,
|
|
}: {
|
|
review: WeeklyReviewT;
|
|
onApply?: (pattern: WeeklyReviewPattern) => void;
|
|
}) {
|
|
return (
|
|
<section className="card weekly">
|
|
<div className="ch">
|
|
<div className="ico">
|
|
<Icon name="chart" />
|
|
</div>
|
|
<div className="htext">
|
|
<h3>주간 리뷰</h3>
|
|
<div className="sub">{review.week_label}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="wr-stats">
|
|
<Stat n={String(review.deep_work_h)} unit="h" label="딥워크" />
|
|
<Stat n={String(review.meeting_h)} unit="h" label="회의" />
|
|
<Stat n={String(review.done_count)} label="완료" />
|
|
<Stat n={String(review.auto_count)} label="자동" />
|
|
</div>
|
|
|
|
{review.patterns.map((p, i) => (
|
|
<div className="wr-pattern" key={i}>
|
|
<div className="wr-pattern-text">
|
|
<div className="wr-pattern-title">{p.title}</div>
|
|
<div className="wr-pattern-suggest">{p.suggest}</div>
|
|
</div>
|
|
<button className="wr-apply" onClick={() => onApply?.(p)}>
|
|
적용
|
|
</button>
|
|
</div>
|
|
))}
|
|
|
|
{review.note && <div className="wr-note">{review.note}</div>}
|
|
</section>
|
|
);
|
|
}
|