Migrate all repos into monorepo context folders
Bahn: aisupport, Analyse-O2C-C2S, awesome-bahn-mcp-servers, beam-mcp,
Confluence_Bot, db-planet-mcp-server, O2C-Harness, project-audit,
Projekt-KIQ-HP, teamlandkarte-mcp
Dhive: Jury-Voting
Privat: CV, NoteGraph (NOTE: NoteGraph needs complete redo after consolidation)
Shared: AI-Orchestrator, OrgMyLife, power_skills_and_more
Shared/references: symphony (read-only)
Bahn repos remain available as independent remotes - this monorepo
pulls them in via subtree, the originals are untouched.
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
interface JurorProgress {
|
||||
completed: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays juror voting progress (X/11 teams completed per juror).
|
||||
* Fetches from GET /api/progress. No individual scores shown.
|
||||
*/
|
||||
export default function ProgressMatrix() {
|
||||
const [progress, setProgress] = useState<Record<string, JurorProgress>>({});
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
fetchProgress();
|
||||
const interval = setInterval(fetchProgress, 5000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
function fetchProgress() {
|
||||
fetch('/api/progress')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
setProgress(data);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(() => setLoading(false));
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return <div className="progress-loading">Lade Fortschritt...</div>;
|
||||
}
|
||||
|
||||
const entries = Object.entries(progress);
|
||||
const allComplete = entries.length > 0 && entries.every(([, p]) => p.completed === p.total);
|
||||
|
||||
return (
|
||||
<div className="progress-matrix">
|
||||
<h3 className="progress-title">Fortschritt</h3>
|
||||
|
||||
{allComplete && (
|
||||
<div className="progress-complete-badge">
|
||||
✓ Alle Bewertungen abgeschlossen
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="progress-list">
|
||||
{entries.map(([jurorId, { completed, total }]) => {
|
||||
const percent = total > 0 ? (completed / total) * 100 : 0;
|
||||
const isComplete = completed === total;
|
||||
|
||||
return (
|
||||
<div key={jurorId} className="progress-item">
|
||||
<div className="progress-item-header">
|
||||
<span className="progress-juror-name">
|
||||
{jurorId.charAt(0).toUpperCase() + jurorId.slice(1)}
|
||||
</span>
|
||||
<span className={`progress-count ${isComplete ? 'complete' : ''}`}>
|
||||
{completed}/{total}
|
||||
</span>
|
||||
</div>
|
||||
<div className="progress-bar-track">
|
||||
<div
|
||||
className={`progress-bar-fill ${isComplete ? 'complete' : ''}`}
|
||||
style={{ width: `${percent}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user