@include('partials.project-tabs', ['tabBase' => '/quarter-targets', 'tabActive' => $project, 'tabQuery' => request('period') ? '?period=' . request('period') : ''])

{{ $project }} · Quarter Targets @if ($quarter)· {{ $quarter }}@endif

@if (! $quarter)

No targets imported yet for {{ $project }}. Upload the BA sheet in Settings → Import Dashboard.

@else
{{ $percent }}% of quarter targets done ({{ $done }}/{{ $total }})
{{ $done }} done {{ $matched - $done }} in progress {{ $toMatchCount }} to match @if ($preDevCount){{ $preDevCount }} no dev yet@endif @if (count($excluded)){{ count($excluded) }} excluded@endif
@if ($toMatchCount + $preDevCount)
@endif @endif
{{-- Matching popup — opens automatically after an import (?match=1) or via the button. Cards stay listed once they are linked (see $matchQueue) so a sheet row delivered as several Jira stories can be linked to all of them in one pass. --}} @if ($quarter && $showMatch && (count($needsMatching) || count($preDev)))
Match imported rows — {{ $project }} · {{ $quarter }}
@if ($similarCount)
{{ $similarCount }} keyless row{{ $similarCount === 1 ? '' : 's' }} share a title with an already-linked story.
@endif @if (count($needsMatching))

Needs matching · {{ count($needsMatching) }} keyless rows in development

These developed rows have no Jira key. Pick a suggestion, search Jira to link the right story, or mark “No match”. A row can link several stories — keep linking and it stays listed until you close this popup.

@foreach ($needsMatching as $row) @endforeach @endif @if (count($preDev))

Not yet in development · {{ count($preDev) }} rows

@if ($preDevCount) @endif

These rows have no development progress (empty stage columns) and usually have no Jira story yet. Link one — or several — only if they already exist, or mark “No Jira”.

@foreach ($preDev as $row) @endforeach @endif
@endif @if ($quarter && count($matchedRows)) @once @endonce

Target stories · {{ count($matchedRows) }} resolved

@foreach ($matchedRows as $r) {{-- One per linked Jira story. The target-story and action cells are merged across them (rowspan), so a sheet row delivered as several stories reads as one block with each story's own summary and status on its line. --}} @php $span = max(1, count($r['keys'])); $rowSearch = \Illuminate\Support\Str::lower($r['title'].' '.implode(' ', array_column($r['keys'], 'key')) .' '.implode(' ', array_filter(array_column($r['keys'], 'summary')))); $lines = $r['keys'] ?: [null]; // a "no match" row still needs one line @endphp @foreach ($lines as $i => $k) @if ($i === 0) @endif {{-- Test suites covering this story. Each chip deep-links into the Test Cases breakdown (/test-cases?open=), where the rows, the uploaded results and the evidence document all live — no second copy of that UI here. --}} @if ($i === 0) @endif @endforeach {{-- "change" opens the picker in place. The row keeps its current link until another story is picked, so Cancel is a true no-op. --}} @if ($rematch === $r['id']) @endif @endforeach
Target storyTypeJiraLinked storyStatusTest cases
{{ $r['title'] }} @if ($span > 1) {{ $span }} linked stories @endif @if (! empty($r['empty_stages'])) ⚠ {{ count($r['empty_stages']) }} incomplete stage{{ count($r['empty_stages']) === 1 ? '' : 's' }} @endif @if ($k && $k['type'])@endif @if ($k) {{ $k['key'] }} @if (($k['share_count'] ?? 1) > 1) 🔗 shared ×{{ $k['share_count'] }} @endif @else no match@endif @if ($k && $k['summary']){{ $k['summary'] }}@else @endif @if ($k && $k['raw_status'])@else @endif @if ($k && ! empty($k['tests'])) @foreach ($k['tests'] as $tc) 📋 {{ \Illuminate\Support\Str::limit($tc['name'], 34) }} @if ($tc['has_results']) {{ $tc['pass_pct'] }}% @else @endif @if ($tc['has_evidence'])📎@endif @endforeach @elseif ($k) no test cases @else @endif
Re-link {{ $r['title'] }} — “Link” replaces the primary story, “Add” links another one alongside it.
@php $rowLinked = array_map(fn ($k) => ['key' => $k['key'], 'summary' => $k['summary'] ?? null, 'status' => $k['raw_status'] ?? null], $r['keys']); @endphp @include('partials.qt-linked-keys', ['row' => ['id' => $r['id'], 'linked' => $rowLinked]]) @if (! empty($rematchResults))
@foreach ($rematchResults as $res)
{{ $res['key'] }} {{ $res['summary'] }} @if ($res['status'])· {{ $res['status'] }}@endif @if (($keyUsage[$res['key']] ?? 0) > (in_array($res['key'], array_column($r['keys'], 'key'), true) ? 1 : 0)) 🔗 shared @endif @if (in_array($res['key'], array_column($r['keys'], 'key'), true)) · already linked @else @endif
@endforeach
@elseif (! empty($this->search[$r['id']] ?? ''))

No Jira stories match “{{ $this->search[$r['id']] }}”.

@endif
@if ($r['key']) @endif
@endif @if ($quarter && count($excluded))

Excluded from targets · {{ count($excluded) }}

Not counted in the quarter-target progress. Include a row to bring it back.

@foreach ($excluded as $r) @endforeach
StoryJira
{{ $r['title'] }} @forelse ($r['keys'] as $k){{ $k }} @empty@endforelse
@endif