add fields for requirement

This commit is contained in:
Sylvain Schneider
2026-05-11 23:32:51 +02:00
parent b742a9a59e
commit 14314de3b8
2 changed files with 54 additions and 34 deletions

View File

@@ -3,7 +3,6 @@ import Button from 'primevue/button'
import Card from 'primevue/card' import Card from 'primevue/card'
import Chip from 'primevue/chip' import Chip from 'primevue/chip'
import Divider from 'primevue/divider' import Divider from 'primevue/divider'
import ProgressBar from 'primevue/progressbar'
import Tag from 'primevue/tag' import Tag from 'primevue/tag'
export interface Requirement { export interface Requirement {
@@ -21,6 +20,9 @@ export interface Requirement {
impactedModules: string[] impactedModules: string[]
blockers: string[] blockers: string[]
notes: string notes: string
stakeholders: string[]
flexibility: string
tolerances: string
} }
interface Props { interface Props {
@@ -74,42 +76,56 @@ const prioritySeverity = (priority: Requirement['priority']) => {
</template> </template>
<template #content> <template #content>
<!-- Status and priority badges --> <!-- Status and priority tags -->
<div class="detail-badges"> <div class="detail-badges">
<Tag :value="requirement.status" :severity="statusSeverity(requirement.status)" /> <Tag :value="requirement.status" :severity="statusSeverity(requirement.status)" />
<Tag :value="requirement.priority" :severity="prioritySeverity(requirement.priority)" rounded /> <Tag :value="requirement.priority" :severity="prioritySeverity(requirement.priority)" rounded />
<Tag value="Target release" severity="contrast" />
</div> </div>
<!-- Requirement description --> <!-- Description -->
<p class="detail-description">{{ requirement.description }}</p> <p class="detail-description">{{ requirement.description }}</p>
<!-- Blockers section (shown only if blockers exist) -->
<article v-if="requirement.blockers.length" class="info-panel info-panel--warning">
<h3>Identified blockers</h3>
<ul class="blockers-list">
<li v-for="blocker in requirement.blockers" :key="blocker">
<i class="pi pi-exclamation-triangle" />
<span>{{ blocker }}</span>
</li>
</ul>
</article>
<Divider /> <Divider />
<!-- Context and commitment section --> <!-- Key attributes: Author, Stakeholders, Priority, Flexibility -->
<div class="detail-grid"> <div class="detail-grid">
<article class="info-panel"> <article class="info-panel">
<h3>Context</h3> <h3>Author</h3>
<p>{{ requirement.rationale }}</p> <p>{{ requirement.owner }}</p>
</article> </article>
<article class="info-panel info-panel--accent"> <article class="info-panel">
<h3>Commitment</h3> <h3>Stakeholders</h3>
<dl> <div class="chip-row">
<div> <Chip v-for="stakeholder in requirement.stakeholders" :key="stakeholder" :label="stakeholder" />
<dt>Due date</dt> </div>
<dd>{{ requirement.dueDate }}</dd> </article>
</div>
<div> <article class="info-panel">
<dt>Progress</dt> <h3>Flexibility</h3>
<dd>{{ requirement.progress }}%</dd> <p>{{ requirement.flexibility }}</p>
</div> </article>
</dl>
<ProgressBar :value="requirement.progress" /> <article class="info-panel">
<h3>Tolerances</h3>
<p>{{ requirement.tolerances }}</p>
</article> </article>
</div> </div>
<!-- Acceptance criteria and modules section --> <Divider />
<!-- Acceptance criteria and impacted modules -->
<div class="detail-columns"> <div class="detail-columns">
<article class="info-panel"> <article class="info-panel">
<h3>Acceptance criteria</h3> <h3>Acceptance criteria</h3>
@@ -129,21 +145,10 @@ const prioritySeverity = (priority: Requirement['priority']) => {
<Divider /> <Divider />
<h3>Notes</h3> <h3>Remarks</h3>
<p>{{ requirement.notes }}</p> <p>{{ requirement.notes }}</p>
</article> </article>
</div> </div>
<!-- Blockers section (shown only if blockers exist) -->
<article v-if="requirement.blockers.length" class="info-panel info-panel--warning">
<h3>Identified blockers</h3>
<ul class="blockers-list">
<li v-for="blocker in requirement.blockers" :key="blocker">
<i class="pi pi-exclamation-triangle" />
<span>{{ blocker }}</span>
</li>
</ul>
</article>
</template> </template>
</Card> </Card>
</section> </section>
@@ -221,7 +226,7 @@ const prioritySeverity = (priority: Requirement['priority']) => {
} }
.detail-grid { .detail-grid {
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(4, minmax(0, 1fr));
margin-top: 0.75rem; margin-top: 0.75rem;
} }

View File

@@ -19,6 +19,9 @@ export interface Requirement {
impactedModules: string[] impactedModules: string[]
blockers: string[] blockers: string[]
notes: string notes: string
stakeholders: string[]
flexibility: string
tolerances: string
} }
export const useRequirementsStore = defineStore('requirements', () => { export const useRequirementsStore = defineStore('requirements', () => {
@@ -44,6 +47,9 @@ export const useRequirementsStore = defineStore('requirements', () => {
impactedModules: ['Backlog', 'Tests', 'Audit', 'Reporting'], impactedModules: ['Backlog', 'Tests', 'Audit', 'Reporting'],
blockers: [], blockers: [],
notes: 'Plan a PDF export for milestone reviews.', notes: 'Plan a PDF export for milestone reviews.',
stakeholders: ['QA Team', 'Product Owner', 'Tech Lead'],
flexibility: 'Low—cannot alter core traceability chain without major rework',
tolerances: 'Maximum 5% of requirements can have incomplete artifact links',
}, },
{ {
id: 102, id: 102,
@@ -66,6 +72,9 @@ export const useRequirementsStore = defineStore('requirements', () => {
impactedModules: ['Workflow', 'Detail', 'Dashboard'], impactedModules: ['Workflow', 'Detail', 'Dashboard'],
blockers: ['Final label approval from the Product Owner'], blockers: ['Final label approval from the Product Owner'],
notes: 'Can be connected to workflow transitions later.', notes: 'Can be connected to workflow transitions later.',
stakeholders: ['Product Managers', 'Business Analysts', 'UI Team'],
flexibility: 'Medium—limited room for additional statuses, current labels are firm',
tolerances: 'Terminology must match approved glossary within 95% confidence',
}, },
{ {
id: 103, id: 103,
@@ -88,6 +97,9 @@ export const useRequirementsStore = defineStore('requirements', () => {
impactedModules: ['Sidebar', 'Search', 'Performance'], impactedModules: ['Sidebar', 'Search', 'Performance'],
blockers: ['Definition of the priority search criteria'], blockers: ['Definition of the priority search criteria'],
notes: 'To be extended with type and batch filters.', notes: 'To be extended with type and batch filters.',
stakeholders: ['End Users', 'Performance Team'],
flexibility: 'High—can adapt search algorithm and UI patterns to user feedback',
tolerances: 'Search response time must stay under 200ms for 99% of queries',
}, },
{ {
id: 104, id: 104,
@@ -110,6 +122,9 @@ export const useRequirementsStore = defineStore('requirements', () => {
impactedModules: ['Release', 'Roadmap', 'Governance'], impactedModules: ['Release', 'Roadmap', 'Governance'],
blockers: ['Architecture decision pending'], blockers: ['Architecture decision pending'],
notes: 'To be linked to a milestone calendar.', notes: 'To be linked to a milestone calendar.',
stakeholders: ['Release Manager', 'Governance Board', 'Architects'],
flexibility: 'Low—release scope is constrained by business commitments',
tolerances: '100% of deliverables must link to a release before code freeze',
}, },
]) ])