// dashboard.jsx — D-01 메인 대시보드
const { Icon, Pill, Tag, Avatar, Button, Progress, KPI } = window.RAlly;
const Dashboard = ({ go }) => {
const [data, setData] = React.useState(null);
React.useEffect(() => {
fetch('/api/dashboard').then((r) => r.json()).then(setData).catch(() => {});
}, []);
const d = data || { kpis: [], tracks: [], team: [], dueSoon: [], recent: [] };
const topTrack = d.topTrack || (d.tracks[0] && d.tracks[0].name) || '진행 중 트랙';
return (
{/* Header */}
안녕하세요{(window.RAlly.getUser && window.RAlly.getUser()) ? ', ' + window.RAlly.getUser().name + '님' : ''} 👋
오늘은 {topTrack}에 집중하기 좋은 날이에요.
{/* KPI */}
{d.kpis.map((k, i) => (
))}
{/* Body grid: 2:1 */}
{/* Left column */}
{/* Track cards */}
진행 중 트랙
go('track')}>모두 보기 →
{d.tracks.map((t, i) => (
{ window.__RALLY_TRACK = t.id; go('track'); }}
/>
))}
{/* Activity feed */}
{(d.recent || []).length === 0 && (
아직 활동이 없어요. 품목 정보로 문서를 생성하면 여기에 기록됩니다.
)}
{(d.recent || []).map((a, i) => (
{a.name}님이 {a.doc}을 {a.verb}어요>}
time={a.time} tone={a.tone} />
))}
{/* Right column */}
{/* Due soon */}
{d.dueSoon.map((r, i) => (
))}
{/* Team */}
{/* AI nudge */}
품목 정보만 입력하면 적용 문서종을 실제 심사 수준으로 한 번에 생성합니다. 생성 후 증거값([입력 필요])만 채우고 RA 검토로 넘기면 됩니다.
);
};
// ---------- helpers ----------
const DashTrackCard = ({ stage, stageActive, title, meta, progress, dDay, members, comments, nextAction, onClick }) => (
e.currentTarget.style.borderColor = 'var(--line-2)'}
onMouseLeave={(e) => e.currentTarget.style.borderColor = 'var(--line)'}
>
{title}
{meta}
주행 거리
{progress}%
{dDay}
{members.map((m, i) =>
)}
{comments}
다음 액션
{nextAction}
);
const ActivityRow = ({ avatar, text, time, tone }) => (
);
const DueRow = ({ tone, dDay, title, sub }) => (
);
const TeamRow = ({ initials, variant, name, role, status, muted, coral }) => (
);
window.RAlly.Dashboard = Dashboard;