refactor(campaigns): move CampaignTimingPanel next to Progress panel
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled

Progress and Timing now share a 2-column grid at the top of the detail page.
Removed CampaignTimingPanel from the bottom Jira section.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
kitos
2026-06-03 16:42:45 +02:00
parent 7c6aaeda30
commit 3db9809be5

View File

@@ -309,44 +309,50 @@ export default function CampaignDetailPage() {
</div> </div>
</div> </div>
{/* Progress Panel */} {/* Progress + Timing side by side */}
<div className="rounded-xl border border-gray-800 bg-gray-900 p-6"> <div className="grid gap-6 lg:grid-cols-2">
<h2 className="mb-4 text-lg font-semibold text-white">Progress</h2> {/* Progress Panel */}
<div className="flex items-center gap-6 mb-4"> <div className="rounded-xl border border-gray-800 bg-gray-900 p-6">
<div> <h2 className="mb-4 text-lg font-semibold text-white">Progress</h2>
<span className="text-3xl font-bold text-white">{progress.completion_pct}%</span> <div className="flex items-center gap-6 mb-4">
<span className="ml-1 text-sm text-gray-400">complete</span> <div>
</div> <span className="text-3xl font-bold text-white">{progress.completion_pct}%</span>
<div className="flex-1"> <span className="ml-1 text-sm text-gray-400">complete</span>
<div className="h-3 w-full rounded-full bg-gray-800 overflow-hidden">
<div
className={`h-full rounded-full transition-all ${
progress.completion_pct === 100 ? "bg-green-500" : "bg-cyan-500"
}`}
style={{ width: `${progress.completion_pct}%` }}
/>
</div> </div>
<div className="flex-1">
<div className="h-3 w-full rounded-full bg-gray-800 overflow-hidden">
<div
className={`h-full rounded-full transition-all ${
progress.completion_pct === 100 ? "bg-green-500" : "bg-cyan-500"
}`}
style={{ width: `${progress.completion_pct}%` }}
/>
</div>
</div>
<span className="text-sm text-gray-400">
{progress.by_state?.validated || 0} / {progress.total} tests
</span>
</div> </div>
<span className="text-sm text-gray-400">
{progress.by_state?.validated || 0} / {progress.total} tests {/* State breakdown */}
</span> {progress.total > 0 && (
<div className="flex flex-wrap gap-3">
{Object.entries(progress.by_state || {}).map(([state, count]) => (
<div
key={state}
className={`rounded-lg border px-3 py-1.5 text-xs font-medium ${
testStateColors[state] || testStateColors.draft
}`}
>
{state.replace(/_/g, " ")}: {count}
</div>
))}
</div>
)}
</div> </div>
{/* State breakdown */} {/* Campaign Timing */}
{progress.total > 0 && ( <CampaignTimingPanel campaignId={campaignId!} />
<div className="flex flex-wrap gap-3">
{Object.entries(progress.by_state || {}).map(([state, count]) => (
<div
key={state}
className={`rounded-lg border px-3 py-1.5 text-xs font-medium ${
testStateColors[state] || testStateColors.draft
}`}
>
{state.replace(/_/g, " ")}: {count}
</div>
))}
</div>
)}
</div> </div>
{/* Kill Chain Timeline */} {/* Kill Chain Timeline */}
@@ -630,11 +636,8 @@ export default function CampaignDetailPage() {
)} )}
</div> </div>
{/* Jira + Campaign Timing */} {/* Jira */}
<div className="grid gap-6 lg:grid-cols-2"> <JiraLinkPanel entityType="campaign" entityId={campaignId!} readOnly label={campaign.name} />
<JiraLinkPanel entityType="campaign" entityId={campaignId!} readOnly label={campaign.name} />
<CampaignTimingPanel campaignId={campaignId!} />
</div>
{/* Add Test to Campaign Modal */} {/* Add Test to Campaign Modal */}
<AddTestToCampaignModal <AddTestToCampaignModal