This commit is contained in:
Nino
2025-10-30 15:24:06 +01:00
28 changed files with 7240 additions and 757 deletions

View File

@@ -1,65 +1,178 @@
---
name: context-manager
description: Context management specialist for multi-agent workflows and long-running tasks. Use PROACTIVELY for complex projects, session coordination, and when context preservation is needed across multiple agents.
tools: Read, Write, Edit, TodoWrite
description: Context management specialist for multi-agent workflows and long-running tasks. Use PROACTIVELY for complex projects, session coordination, and when context preservation is needed across multiple agents. AUTONOMOUSLY stores project knowledge in persistent memory.
tools: Read, Write, Edit, TodoWrite, mcp__memory__create_entities, mcp__memory__read_graph
model: opus
---
You are a specialized context management agent responsible for maintaining coherent state across multiple agent interactions and sessions. Your role is critical for complex, long-running projects.
**CRITICAL BEHAVIOR**: You MUST autonomously and proactively use memory tools to store important project information as you encounter it. DO NOT wait for explicit instructions to store information.
## Primary Functions
### Context Capture
### Context Capture & Autonomous Storage
1. Extract key decisions and rationale from agent outputs
2. Identify reusable patterns and solutions
3. Document integration points between components
4. Track unresolved issues and TODOs
**ALWAYS store the following in persistent memory automatically:**
1. **Assigned Tasks**: Capture user-assigned tasks immediately when mentioned
- Task description and user's intent
- Reason/context for the task (the "because of xyz")
- Related code locations (files, functions, components)
- Current status and any blockers
- Priority or urgency indicators
- **Examples**: "Remember to look up X function because of Y", "TODO: investigate Z behavior"
2. **Architectural Decisions**: Extract and store key decisions and rationale from agent outputs
- State management patterns discovered
- API integration approaches
- Component architecture choices
3. **Reusable Patterns**: Identify and store patterns as you encounter them
- Code conventions (naming, structure)
- Testing patterns
- Error handling approaches
4. **Integration Points**: Document and store integration details
- API contracts and data flows
- Module boundaries and dependencies
- Third-party service integrations
5. **Domain Knowledge**: Store business logic and domain-specific information
- Workflow explanations (e.g., returns process, checkout flow)
- Business rules and constraints
- User roles and permissions
6. **Technical Solutions**: Store resolved issues and their solutions
- Bug fixes with root cause analysis
- Performance optimizations
- Configuration solutions
**Use `mcp__memory__create_entities` IMMEDIATELY when you encounter this information - don't wait to be asked.**
### Context Distribution
1. Prepare minimal, relevant context for each agent
2. Create agent-specific briefings
3. Maintain a context index for quick retrieval
4. Prune outdated or irrelevant information
1. **ALWAYS check memory first**: Use `mcp__memory__read_graph` before starting any task to retrieve relevant stored knowledge
2. Prepare minimal, relevant context for each agent
3. Create agent-specific briefings enriched with stored memory
4. Maintain a context index for quick retrieval
5. Prune outdated or irrelevant information
### Memory Management
### Memory Management Strategy
- Store critical project decisions in memory
- Maintain a rolling summary of recent changes
- Index commonly accessed information
- Create context checkpoints at major milestones
**Persistent Memory (PRIORITY - use MCP tools)**:
- **CREATE**: Use `mcp__memory__create_entities` to store entities with relationships:
- Entity types: task, decision, pattern, integration, solution, convention, domain-knowledge
- Include observations (what was learned/assigned) and relations (how entities connect)
- **RETRIEVE**: Use `mcp__memory__read_graph` to query stored knowledge:
- Before starting new work (check for pending tasks, related patterns/decisions)
- When user asks "what was I working on?" (retrieve task history)
- When encountering similar problems (find previous solutions)
- When making architectural choices (review past decisions)
- At session start (remind user of pending/incomplete tasks)
**Ephemeral Memory (File-based - secondary)**:
- Maintain rolling summaries in temporary files
- Create session checkpoints
- Index recent activities
## Workflow Integration
When activated, you should:
**On every activation, you MUST:**
1. Review the current conversation and agent outputs
2. Extract and store important context
3. Create a summary for the next agent/session
4. Update the project's context index
5. Suggest when full context compression is needed
1. **Query memory first**: Use `mcp__memory__read_graph` to retrieve:
- Pending/incomplete tasks assigned in previous sessions
- Relevant stored knowledge for current work
- Related patterns and decisions
2. **Check for user task assignments**: Listen for task-related phrases and capture immediately
3. **Review current work**: Analyze conversation and agent outputs
4. **Store new discoveries**: Use `mcp__memory__create_entities` to store:
- ANY new tasks mentioned by user
- Important information discovered
- Task status updates (pending → in-progress → completed)
5. **Create summaries**: Prepare briefings enriched with memory context
6. **Update indexes**: Maintain project context index
7. **Suggest compression**: Recommend when full context compression is needed
**Key behaviors:**
- **TASK PRIORITY**: Capture and store user task assignments IMMEDIATELY when mentioned
- Store information PROACTIVELY without being asked
- Query memory BEFORE making recommendations
- Link new entities to existing ones for knowledge graph building
- Update existing entities when information evolves (especially task status)
- **Session Start**: Proactively remind user of pending/incomplete tasks from memory
## Context Formats
### Quick Context (< 500 tokens)
- Current task and immediate goals
- Recent decisions affecting current work
- Recent decisions affecting current work (query memory first)
- Active blockers or dependencies
- Relevant stored patterns from memory
### Full Context (< 2000 tokens)
- Project architecture overview
- Key design decisions
- Integration points and APIs
- Project architecture overview (enriched with stored decisions)
- Key design decisions (retrieved from memory)
- Integration points and APIs (from stored knowledge)
- Active work streams
### Archived Context (stored in memory)
### Persistent Context (stored in memory via MCP)
- Historical decisions with rationale
- Resolved issues and solutions
- Pattern library
- Performance benchmarks
**Store these entity types:**
- `task`: User-assigned tasks, reminders, TODOs with context and status
- `decision`: Architectural and design decisions with rationale
- `pattern`: Reusable code patterns and conventions
- `integration`: API contracts and integration points
- `solution`: Resolved issues with root cause and fix
- `convention`: Coding standards and project conventions
- `domain-knowledge`: Business logic and workflow explanations
Always optimize for relevance over completeness. Good context accelerates work; bad context creates confusion.
**Entity structure examples:**
**Task entity (NEW - PRIORITY):**
```json
{
"name": "investigate-checkout-pricing-calculation",
"entityType": "task",
"observations": [
"User requested: 'Remember to look up the pricing calculation function'",
"Reason: Pricing appears incorrect for bundle products in checkout",
"Located in: libs/checkout/feature-cart/src/lib/services/pricing.service.ts",
"Status: pending",
"Priority: high - affects production checkout",
"Related components: checkout-summary, cart-item-list"
],
"relations": [
{"type": "relates_to", "entity": "checkout-domain-knowledge"},
{"type": "blocks", "entity": "bundle-pricing-bug-fix"}
]
}
```
**Other entity types:**
```json
{
"name": "descriptive-entity-name",
"entityType": "decision|pattern|integration|solution|convention|domain-knowledge",
"observations": ["what was learned", "why it matters", "how it's used"],
"relations": [
{"type": "relates_to|depends_on|implements|solves|blocks", "entity": "other-entity-name"}
]
}
```
**Task Status Values**: `pending`, `in-progress`, `blocked`, `completed`, `cancelled`
**Task Capture Triggers**: Listen for phrases like:
- "Remember to..."
- "TODO: ..."
- "Don't forget..."
- "Look into..."
- "Investigate..."
- "Need to check..."
- "Follow up on..."
Always optimize for relevance over completeness. Good context accelerates work; bad context creates confusion. **Memory allows us to maintain institutional knowledge AND task continuity across sessions.**

View File

@@ -1,197 +0,0 @@
# /dev:add-e2e-attrs - Add E2E Test Attributes
Add required E2E test attributes (`data-what`, `data-which`, dynamic `data-*`) to component templates for QA automation.
## Parameters
- `component-path`: Path to component directory or HTML template file
## Required E2E Attributes
### Core Attributes (Required)
1. **`data-what`**: Semantic description of element's purpose
- Example: `data-what="submit-button"`, `data-what="search-input"`
2. **`data-which`**: Unique identifier for the specific instance
- Example: `data-which="primary"`, `data-which="customer-{{ customerId }}"`
### Dynamic Attributes (Contextual)
3. **`data-*`**: Additional context based on state/data
- Example: `data-status="active"`, `data-index="0"`
## Tasks
### 1. Analyze Component Template
- Read component HTML template
- Identify interactive elements that need E2E attributes:
- Buttons (`button`, `ui-button`)
- Inputs (`input`, `textarea`, `select`)
- Links (`a`, `routerLink`)
- Custom interactive components
- Form elements
- Clickable elements (`(click)` handlers)
### 2. Add Missing Attributes
**Buttons:**
```html
<!-- BEFORE -->
<button (click)="submit()">Submit</button>
<!-- AFTER -->
<button
(click)="submit()"
data-what="submit-button"
data-which="form-primary">
Submit
</button>
```
**Inputs:**
```html
<!-- BEFORE -->
<input [(ngModel)]="searchTerm" placeholder="Search..." />
<!-- AFTER -->
<input
[(ngModel)]="searchTerm"
placeholder="Search..."
data-what="search-input"
data-which="main-search" />
```
**Dynamic Lists:**
```html
<!-- BEFORE -->
@for (item of items; track item.id) {
<li (click)="selectItem(item)">{{ item.name }}</li>
}
<!-- AFTER -->
@for (item of items; track item.id) {
<li
(click)="selectItem(item)"
data-what="list-item"
[attr.data-which]="item.id"
[attr.data-status]="item.status">
{{ item.name }}
</li>
}
```
**Links:**
```html
<!-- BEFORE -->
<a routerLink="/orders/{{ orderId }}">View Order</a>
<!-- AFTER -->
<a
[routerLink]="['/orders', orderId]"
data-what="order-link"
[attr.data-which]="orderId">
View Order
</a>
```
**Custom Components:**
```html
<!-- BEFORE -->
<ui-button (click)="save()">Save</ui-button>
<!-- AFTER -->
<ui-button
(click)="save()"
data-what="save-button"
data-which="order-form">
Save
</ui-button>
```
### 3. Naming Conventions
**`data-what` Guidelines:**
- Use kebab-case
- Be descriptive but concise
- Common patterns:
- `*-button` (submit-button, cancel-button, delete-button)
- `*-input` (email-input, search-input, quantity-input)
- `*-link` (product-link, order-link, customer-link)
- `*-item` (list-item, menu-item, card-item)
- `*-dialog` (confirm-dialog, error-dialog)
- `*-dropdown` (status-dropdown, category-dropdown)
**`data-which` Guidelines:**
- Unique identifier for the instance
- Use dynamic binding for list items: `[attr.data-which]="item.id"`
- Static for unique elements: `data-which="primary"`
- Combine with context: `data-which="customer-{{ customerId }}-edit"`
### 4. Scan for Coverage
Check template coverage:
```bash
# Count interactive elements
grep -E '(click)=|routerLink|button|input|select|textarea' [template-file]
# Count elements with data-what
grep -c 'data-what=' [template-file]
# List elements missing E2E attributes
grep -E '(click)=|button' [template-file] | grep -v 'data-what='
```
### 5. Validate Attributes
- No duplicates in `data-which` within same view
- All interactive elements have both `data-what` and `data-which`
- Dynamic attributes use proper Angular binding: `[attr.data-*]`
- Attributes don't contain sensitive data (passwords, tokens)
### 6. Update Component Tests
Add E2E attribute selectors to tests:
```typescript
// Use E2E attributes for element selection
const submitButton = fixture.nativeElement.querySelector('[data-what="submit-button"][data-which="primary"]');
expect(submitButton).toBeTruthy();
```
### 7. Document Attributes
Add comment block at top of template:
```html
<!--
E2E Test Attributes:
- data-what="submit-button" data-which="primary" - Main form submission
- data-what="cancel-button" data-which="primary" - Cancel action
- data-what="search-input" data-which="main" - Product search field
-->
```
## Output
Provide summary:
- Template analyzed: [path]
- Interactive elements found: [count]
- Attributes added: [count]
- Coverage: [percentage]% (elements with E2E attrs / total interactive elements)
- List of added attributes with descriptions
- Validation status: ✅/❌
## Common Patterns by Component Type
**Form Components:**
- `data-what="[field]-input" data-which="[form-name]"`
- `data-what="submit-button" data-which="[form-name]"`
- `data-what="cancel-button" data-which="[form-name]"`
**List/Table Components:**
- `data-what="list-item" [attr.data-which]="item.id"`
- `data-what="edit-button" [attr.data-which]="item.id"`
- `data-what="delete-button" [attr.data-which]="item.id"`
**Navigation Components:**
- `data-what="nav-link" data-which="[destination]"`
- `data-what="breadcrumb" data-which="[level]"`
**Dialog Components:**
- `data-what="confirm-button" data-which="dialog"`
- `data-what="close-button" data-which="dialog"`
## References
- CLAUDE.md Code Quality section (E2E Testing Requirements)
- docs/guidelines/testing.md
- QA team E2E test documentation (if available)

View File

@@ -0,0 +1,434 @@
---
allowed-tools: Read, Write, Bash, Grep
argument-hint: [date] | --yesterday | --save-only
description: Generate End of Day report summarizing commits and work across all branches
---
# End of Day Report
Generate daily work summary: $ARGUMENTS
## Current State
- Current Date: !`date +%Y-%m-%d`
- Current Time: !`date +%H:%M`
- Current Branch: !`git branch --show-current`
- Git User: !`git config user.name`
- Git Email: !`git config user.email`
## Tasks
### 1. Determine Report Date and Scope
**Objective**: Identify the date range for the report
- [ ] Ask user for their work start time
- Use AskUserQuestion to ask: "What time did you start working today?"
- Provide options: "First commit time", "08:00", "09:00", "10:00", "Custom time"
- If "Custom time" selected, ask for specific time (HH:MM format)
- Default to first commit time if not specified
- Use this for accurate "Work Duration" calculation
- [ ] Check if date argument provided
- If `[date]` provided: Use specific date (format: YYYY-MM-DD)
- If `--yesterday` provided: Use yesterday's date
- Otherwise: Use today's date
```bash
# Get today's date
TODAY=$(date +%Y-%m-%d)
# Get yesterday's date
YESTERDAY=$(date -d "yesterday" +%Y-%m-%d)
# Get start of day
START_TIME="${TODAY} 00:00:00"
# Get end of day
END_TIME="${TODAY} 23:59:59"
```
- [ ] Set report scope
- Search across **all branches** (local and remote)
- Filter by git user name and email
- Include commits from start to end of specified day
### 2. Collect Commit Information
**Objective**: Gather all commits made by the user on the specified date (excluding merge commits)
- [ ] Fetch commits across all branches (non-merge commits only)
```bash
# Get all non-merge commits by current user today across all branches
git log --all \
--author="$(git config user.name)" \
--since="$START_TIME" \
--until="$END_TIME" \
--pretty=format:"%h|%ai|%s|%D" \
--no-merges
```
**Important**: Use `--no-merges` flag to exclude PR merge commits. These will be tracked separately in section 3.
- [ ] Extract commit details:
- Commit hash (short)
- Commit time
- Commit message
- Branch references (if any)
- [ ] Group commits by branch
- Parse branch references from commit output
- Identify which branch each commit belongs to
- Track branch switches during the day
- Exclude "Merged PR" commits from this section (they appear in Merge Activity instead)
**Example Output**:
```
c208327db|2025-10-28 14:23:45|feat(crm-data-access,checkout): improve primary bonus card selection logic|feature/5202-Praemie
9020cb305|2025-10-28 10:15:32|✨ feat(navigation): implement title management and enhance tab system|feature/5351-navigation
```
### 3. Identify PR and Merge Activity
**Objective**: Find pull requests created or merged today, distinguishing between PRs I merged vs PRs merged by colleagues
- [ ] Find ALL merge commits with "Merged PR" (check both author and committer)
```bash
# Get all PR merge activity with author and committer info
git log --all \
--since="$START_TIME" \
--until="$END_TIME" \
--grep="Merged PR" \
--pretty=format:"%h|%ai|%s|Author: %an <%ae>|Committer: %cn <%ce>"
```
- [ ] Categorize PR merges:
- **PRs I merged**: Where I am the COMMITTER (git config user.name matches committer name)
- **My PRs merged by colleagues**: Where I am the AUTHOR but someone else is the COMMITTER
- **Colleague PRs I merged**: Where someone else is the AUTHOR and I am the COMMITTER
- [ ] Parse PR numbers from commit messages
- Look for patterns: "Merged PR 1234:", "PR #1234", etc.
- Extract PR title/description
- Note which branch was merged
- Note who performed the merge (committer name)
- [ ] Identify branch merges
- Look for merge commits to develop/main
- Note feature branches merged
### 4. Analyze Branch Activity
**Objective**: Summarize branches worked on today
- [ ] List all branches with commits today
```bash
# Get unique branches with activity today
git log --all \
--author="$(git config user.name)" \
--since="$START_TIME" \
--until="$END_TIME" \
--pretty=format:"%D" | \
grep -v '^$' | \
tr ',' '\n' | \
sed 's/^ *//' | \
grep -E '^(origin/)?[a-zA-Z]' | \
sort -u
```
- [ ] Identify:
- Primary branch worked on (most commits)
- Other branches touched
- New branches created today
- Branches merged today
- [ ] Check current branch status
- Uncommitted changes
- Untracked files
- Ahead/behind develop
### 5. Generate Report Summary
**Objective**: Create formatted markdown report
- [ ] Build report structure:
```markdown
# End of Day Report - YYYY-MM-DD
**Developer**: [Name] <email>
**Date**: Day, Month DD, YYYY
**Time**: HH:MM
---
## 📊 Summary
- **Commits**: X commits across Y branches
- **PRs I Merged**: Z pull requests (as committer)
- **My PRs Merged by Colleagues**: W pull requests
- **Primary Branch**: branch-name
- **Work Duration**: Started at HH:MM, worked for Xh Ym
## 🔨 Commits Today
### Branch: feature/5351-navigation (5 commits)
- `9020cb3` (10:15) ✨ feat(navigation): implement title management and enhance tab system
- `abc1234` (11:30) fix(navigation): resolve routing edge case
- `def5678` (14:45) test(navigation): add comprehensive test coverage
- `ghi9012` (15:20) refactor(navigation): improve code organization
- `jkl3456` (16:00) docs(navigation): update README with usage examples
### Branch: feature/5202-Praemie (2 commits)
- `c208327` (14:23) feat(crm-data-access,checkout): improve primary bonus card selection logic
- `mno7890` (16:45) fix(checkout): handle edge case for bonus points
## 🔀 Merge Activity
### PRs I Merged (as committer)
- **PR #1990**: feat(ui): add new button variants → develop
- **PR #1991**: fix(api): resolve timeout issues → develop
### My PRs Merged by Colleagues
- **PR #1987**: Carousel Library → develop (merged by Nino Righi)
- **PR #1989**: fix(checkout): resolve currency constraint violations → develop (merged by Nino Righi)
### Branch Merges
- `feature/5202-Praemie-stock-info-request-batching``feature/5202-Praemie`
## 🌿 Branch Activity
**Primary Branch**: feature/5351-navigation (5 commits)
**Other Branches**:
- feature/5202-Praemie (2 commits)
- develop (merged 2 PRs)
**Current Branch**: feature/5351-navigation
**Status**: 3 files changed, 2 files staged, 1 file untracked
## 📝 Notes
[Optional section for manual notes - left empty by default]
---
_Report generated on YYYY-MM-DD at HH:MM_
```
**Formatting Rules**:
- Use emoji for section headers (📊 📝 🔨 🔀 🌿)
- Group commits by branch
- Show time for each commit in (HH:MM) format
- Include commit prefixes (feat:, fix:, docs:, etc.)
- Sort branches by number of commits (most active first)
- Highlight primary branch (most commits)
### 6. Save and Display Report
**Objective**: Output report to terminal and save to file
**Display to Terminal**:
- [ ] Print formatted report to stdout
- [ ] Use clear visual separators
- [ ] Ensure easy copy/paste to Slack/Teams/Email
**Save to File**:
- [ ] Create reports directory if it doesn't exist
```bash
mkdir -p reports/eod
```
- [ ] Determine filename
- Format: `reports/eod/YYYY-MM-DD.md`
- Example: `reports/eod/2025-10-28.md`
- [ ] Write report to file
```bash
# Save report
cat > "reports/eod/${TODAY}.md" << 'EOF'
[report content]
EOF
```
- [ ] Provide file location feedback
- Show absolute path to saved file
- Confirm successful save
**If `--save-only` flag**:
- [ ] Skip terminal display
- [ ] Only save to file
- [ ] Show success message with file path
### 7. Provide Summary Statistics
**Objective**: Show quick statistics and next steps
- [ ] Calculate and display:
- Total commits today (excluding PR merge commits)
- Number of branches worked on
- PRs I merged (as committer)
- My PRs merged by colleagues (authored by me, committed by others)
- Work duration (user-specified start time → last commit time)
- Lines of code changed (optional, if available)
- [ ] Suggest next steps:
- Commit uncommitted changes
- Push branches to remote
- Create PR for completed work
- Update task tracking system
## Output Format
### Standard Display
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 End of Day Report - 2025-10-28
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
**Developer**: Lorenz Hilpert <lorenz@example.com>
**Date**: Monday, October 28, 2025
**Time**: 17:30
---
## 📊 Summary
- **Commits**: 5 commits across 1 branch
- **PRs I Merged**: 2 pull requests (as committer)
- **My PRs Merged by Colleagues**: 0
- **Primary Branch**: feature/5351-navigation
- **Work Duration**: Started at 09:00, worked for 7h 45m (last commit at 16:45)
## 🔨 Commits Today
### Branch: feature/5351-navigation (5 commits)
- `9020cb3` (10:15) ✨ feat(navigation): implement title management and enhance tab system
- `abc1234` (11:30) 🐛 fix(navigation): resolve routing edge case
- `def5678` (14:45) ✅ test(navigation): add comprehensive test coverage
- `ghi9012` (15:20) ♻️ refactor(navigation): improve code organization
- `jkl3456` (16:00) 📝 docs(navigation): update README with usage examples
### Branch: feature/5202-Praemie (2 commits)
- `c208327` (14:23) ✨ feat(crm-data-access,checkout): improve primary bonus card selection logic
- `mno7890` (16:45) 🐛 fix(checkout): handle edge case for bonus points
## 🔀 Merge Activity
### PRs I Merged (as committer)
- **PR #1987**: Carousel Library → develop
- **PR #1989**: fix(checkout): resolve currency constraint violations → develop
### My PRs Merged by Colleagues
_None today_
## 🌿 Branch Activity
**Primary Branch**: feature/5351-navigation (5 commits)
**Other Branches**:
- feature/5202-Praemie (2 commits)
- develop (2 PR merges)
**Current Status**:
- Branch: feature/5351-navigation
- Changes: 3 files changed, 2 files staged, 1 file untracked
- Remote: 5 commits ahead of origin/feature/5351-navigation
## 📝 Notes
_No additional notes_
---
✅ Report saved to: /home/lorenz/Projects/ISA-Frontend/reports/eod/2025-10-28.md
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 Daily Statistics
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Total Commits: 5 (excluding PR merges)
Branches: 1 active branch
PRs I Merged: 2
My PRs Merged by Colleagues: 0
Work Duration: 7h 45m (started at 09:00, last commit at 16:45)
📋 Next Steps
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. ✅ Push feature/5351-navigation to remote
2. ⚠️ Consider creating PR for completed work
3. 💾 1 untracked file - review and commit if needed
```
### No Activity Case
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 End of Day Report - 2025-10-28
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
**Developer**: Lorenz Hilpert <lorenz@example.com>
**Date**: Monday, October 28, 2025
**Time**: 17:30
---
## 📊 Summary
No commits found for today (2025-10-28).
**Possible Reasons**:
- No development work performed
- Working on uncommitted changes
- Using different git user configuration
**Current Branch**: feature/5351-navigation
**Uncommitted Changes**: 5 files modified, 2 files staged
---
💡 Tip: If you have uncommitted work, commit it before generating the report.
```
### Yesterday's Report
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 End of Day Report - 2025-10-27 (Yesterday)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[Report content for yesterday]
✅ Report saved to: /home/lorenz/Projects/ISA-Frontend/reports/eod/2025-10-27.md
```
## Usage Examples
```bash
# Generate today's EOD report
/eod-report
# Generate yesterday's report (if you forgot)
/eod-report --yesterday
# Generate report for specific date
/eod-report 2025-10-25
# Save to file only (no terminal output)
/eod-report --save-only
# Generate yesterday's report and save only
/eod-report --yesterday --save-only
```
## References
- Git Log Documentation: https://git-scm.com/docs/git-log
- Conventional Commits: https://www.conventionalcommits.org/
- Project Conventions: See CLAUDE.md for commit message standards
- Git Configuration: `git config user.name` and `git config user.email`

View File

@@ -0,0 +1,309 @@
---
allowed-tools: Read, Write, Edit, Bash, Grep
argument-hint: [version] | --since [tag] | --dry-run
description: Generate changelog entries from git tags using Keep a Changelog format
---
# Generate Changelog
Generate changelog entries from git commits between version tags: $ARGUMENTS
## Current State
- Latest Tag: !`git tag --sort=-creatordate | head -n 1`
- CHANGELOG.md: !`test -f CHANGELOG.md && echo "exists" || echo "does not exist"`
- Commits Since Last Tag: !`git log $(git tag --sort=-creatordate | head -n 1)..HEAD --oneline | wc -l`
- Current Branch: !`git branch --show-current`
## Tasks
### 1. Determine Version Range
**Objective**: Identify the commit range for changelog generation
- [ ] Check if version argument provided
- If `[version]` provided: Use as the new version number
- If `--since [tag]` provided: Use custom tag as starting point
- Otherwise: Use latest tag as starting point
```bash
# Find latest tag
LATEST_TAG=$(git tag --sort=-creatordate | head -n 1)
# Get commits since tag
git log ${LATEST_TAG}..HEAD --oneline
# If no tags exist, use entire history
if [ -z "$LATEST_TAG" ]; then
git log --oneline
fi
```
**Edge Cases**:
- No tags exist → Use entire commit history and suggest version 0.1.0
- No commits since last tag → Notify user, no changelog needed
- Invalid tag provided → Error with available tags list
### 2. Extract and Categorize Commits
**Objective**: Parse commit messages and group by Keep a Changelog categories
- [ ] Fetch commits with detailed information
```bash
# Get commits with format: hash | date | message
git log ${LATEST_TAG}..HEAD --pretty=format:"%h|%as|%s" --no-merges
```
- [ ] Parse conventional commit patterns and map to categories:
**Mapping Rules**:
- `feat:` or `feature:`**Added**
- `fix:` or `bugfix:`**Fixed**
- `refactor:`**Changed**
- `perf:` or `performance:`**Changed**
- `docs:`**Changed** (or skip if only documentation)
- `style:`**Changed**
- `test:` → (skip from changelog)
- `chore:` → (skip from changelog)
- `build:` or `ci:` → (skip from changelog)
- `revert:`**Changed** or **Fixed**
- `security:`**Security**
- `deprecate:` or `deprecated:`**Deprecated**
- `remove:` or `breaking:`**Removed**
- Non-conventional commits → **Changed** (default)
- [ ] Extract scope and description from commit messages
**Commit Pattern**: `type(scope): description`
Example:
```
feat(checkout): add reward delivery order support
fix(remission): resolve currency constraint violations
refactor(navigation): implement title management system
```
### 3. Generate Changelog Entry
**Objective**: Create properly formatted changelog section
- [ ] Determine version number
- Use provided `[version]` argument
- Or prompt for new version if not provided
- Format: `[X.Y.Z]` following semantic versioning
- [ ] Get current date in ISO format: `YYYY-MM-DD`
```bash
TODAY=$(date +%Y-%m-%d)
```
- [ ] Build changelog entry following Keep a Changelog format:
```markdown
## [VERSION] - YYYY-MM-DD
### Added
- New feature description from feat: commits
- Another feature
### Changed
- Refactored component description
- Performance improvements
### Deprecated
- Feature marked for removal
### Removed
- Deleted feature or breaking change
### Fixed
- Bug fix description
- Another fix
### Security
- Security improvement description
```
**Rules**:
- Only include sections that have entries
- Sort entries alphabetically within each section
- Use sentence case for descriptions
- Remove commit type prefix from descriptions
- Include scope in parentheses if present: `(scope) description`
- Add reference links to commits/PRs if available
### 4. Update or Preview CHANGELOG.md
**Objective**: Append new entry to changelog file or show preview
**If `--dry-run` flag provided**:
- [ ] Display generated changelog entry to stdout
- [ ] Show preview of where it would be inserted
- [ ] Do NOT modify CHANGELOG.md
- [ ] Exit with success
**Otherwise (append mode)**:
- [ ] Check if CHANGELOG.md exists
- If not, create with standard header:
```markdown
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
```
- [ ] Read existing CHANGELOG.md content
- [ ] Find insertion point (after "## [Unreleased]" section, or after main header)
- [ ] Insert new changelog entry
- [ ] Maintain reverse chronological order (newest first)
- [ ] Write updated content back to CHANGELOG.md
```bash
# Backup existing file
cp CHANGELOG.md CHANGELOG.md.bak
# Insert new entry
# (Implementation handled by Edit tool)
```
### 5. Validate and Report
**Objective**: Verify changelog quality and provide summary
- [ ] Validate generated entry:
- Version format is valid (X.Y.Z)
- Date is correct (YYYY-MM-DD)
- At least one category has entries
- No duplicate entries
- Proper markdown formatting
- [ ] Report statistics:
- Number of commits processed
- Entries per category
- Version number used
- File status (preview/updated)
- [ ] Show next steps:
- Review changelog entry
- Update version in package.json if needed
- Create git tag if appropriate
- Commit changelog changes
## Output Format
### Dry Run Preview
```
🔍 Changelog Preview (--dry-run mode)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
## [1.5.0] - 2025-10-28
### Added
- (checkout) Add reward delivery order support
- (navigation) Implement title management and tab system
### Changed
- (carousel) Update carousel library implementation
- (remission) Enhance returns processing workflow
### Fixed
- (checkout) Resolve currency constraint violations in price handling
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 Statistics
─────────────
Commits processed: 12
Added: 2 entries
Changed: 2 entries
Fixed: 1 entry
Version: 1.5.0
Date: 2025-10-28
⚠️ This is a preview. Run without --dry-run to update CHANGELOG.md
```
### Append Mode Success
```
✅ Changelog Updated Successfully
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
## [1.5.0] - 2025-10-28
### Added
- (checkout) Add reward delivery order support
- (navigation) Implement title management and tab system
### Changed
- (carousel) Update carousel library implementation
- (remission) Enhance returns processing workflow
### Fixed
- (checkout) Resolve currency constraint violations in price handling
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 Statistics
─────────────
Commits processed: 12
Added: 2 entries
Changed: 2 entries
Fixed: 1 entry
Version: 1.5.0
File: CHANGELOG.md (updated)
Backup: CHANGELOG.md.bak
📋 Next Steps
─────────────
1. Review the changelog entry in CHANGELOG.md
2. Update version in package.json: npm version 1.5.0
3. Commit the changelog: git add CHANGELOG.md && git commit -m "docs: update changelog for v1.5.0"
4. Create git tag: git tag -a v1.5.0 -m "Release v1.5.0"
5. Push changes: git push && git push --tags
```
### Error Cases
```
❌ No Changes Found
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
No commits found since last tag (v1.4.5).
Nothing to add to changelog.
```
```
❌ No Tags Found
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
No git tags found in this repository.
Suggestions:
- Create your first tag: git tag v0.1.0
- Or specify a commit range: /generate-changelog --since HEAD~10
- Or generate from all commits: /generate-changelog 0.1.0
```
```
⚠️ Invalid Version Format
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Version "1.5" is invalid.
Expected format: X.Y.Z (e.g., 1.5.0)
Please provide a valid semantic version.
```
## References
- Keep a Changelog: https://keepachangelog.com/
- Semantic Versioning: https://semver.org/
- Conventional Commits: https://www.conventionalcommits.org/
- Project Conventions: See CLAUDE.md for commit message standards

View File

@@ -15,6 +15,8 @@ Guide for modern Angular 20+ template patterns: control flow, lazy loading, proj
- Designing reusable components with `ng-content`
- Template performance optimization
**Related Skill:** For E2E testing attributes (`data-what`, `data-which`) and ARIA accessibility attributes, see the **[html-template](../html-template/SKILL.md)** skill. Both skills work together when writing Angular templates.
## Control Flow (Angular 17+)
### @if / @else if / @else
@@ -211,7 +213,7 @@ Groups elements without DOM footprint:
1. **Use signals:** `isExpanded = signal(false)`
2. **Prefer control flow over directives:** Use `@if` not `*ngIf`
3. **Keep expressions simple:** Use `computed()` for complex logic
4. **E2E attributes:** Always add `[attr.data-what]` and `[attr.data-which]`
4. **Testing & Accessibility:** Always add E2E and ARIA attributes (see **[html-template](../html-template/SKILL.md)** skill)
5. **Track expressions:** Required in `@for`, use unique IDs
## Migration

View File

@@ -1,203 +0,0 @@
---
name: Git Commit Helper
description: Generate descriptive commit messages by analyzing git diffs. Use when the user asks for help writing commit messages or reviewing staged changes.
---
# Git Commit Helper
## Quick start
Analyze staged changes and generate commit message:
```bash
# View staged changes
git diff --staged
# Generate commit message based on changes
# (Claude will analyze the diff and suggest a message)
```
## Commit message format
Follow conventional commits format:
```
<type>(<scope>): <description>
[optional body]
[optional footer]
```
### Types
- **feat**: New feature
- **fix**: Bug fix
- **docs**: Documentation changes
- **style**: Code style changes (formatting, missing semicolons)
- **refactor**: Code refactoring
- **test**: Adding or updating tests
- **chore**: Maintenance tasks
### Examples
**Feature commit:**
```
feat(auth): add JWT authentication
Implement JWT-based authentication system with:
- Login endpoint with token generation
- Token validation middleware
- Refresh token support
```
**Bug fix:**
```
fix(api): handle null values in user profile
Prevent crashes when user profile fields are null.
Add null checks before accessing nested properties.
```
**Refactor:**
```
refactor(database): simplify query builder
Extract common query patterns into reusable functions.
Reduce code duplication in database layer.
```
## Analyzing changes
Review what's being committed:
```bash
# Show files changed
git status
# Show detailed changes
git diff --staged
# Show statistics
git diff --staged --stat
# Show changes for specific file
git diff --staged path/to/file
```
## Commit message guidelines
**DO:**
- Use imperative mood ("add feature" not "added feature")
- Keep first line under 50 characters
- Capitalize first letter
- No period at end of summary
- Explain WHY not just WHAT in body
**DON'T:**
- Use vague messages like "update" or "fix stuff"
- Include technical implementation details in summary
- Write paragraphs in summary line
- Use past tense
## Multi-file commits
When committing multiple related changes:
```
refactor(core): restructure authentication module
- Move auth logic from controllers to service layer
- Extract validation into separate validators
- Update tests to use new structure
- Add integration tests for auth flow
Breaking change: Auth service now requires config object
```
## Scope examples
**Frontend:**
- `feat(ui): add loading spinner to dashboard`
- `fix(form): validate email format`
**Backend:**
- `feat(api): add user profile endpoint`
- `fix(db): resolve connection pool leak`
**Infrastructure:**
- `chore(ci): update Node version to 20`
- `feat(docker): add multi-stage build`
## Breaking changes
Indicate breaking changes clearly:
```
feat(api)!: restructure API response format
BREAKING CHANGE: All API responses now follow JSON:API spec
Previous format:
{ "data": {...}, "status": "ok" }
New format:
{ "data": {...}, "meta": {...} }
Migration guide: Update client code to handle new response structure
```
## Template workflow
1. **Review changes**: `git diff --staged`
2. **Identify type**: Is it feat, fix, refactor, etc.?
3. **Determine scope**: What part of the codebase?
4. **Write summary**: Brief, imperative description
5. **Add body**: Explain why and what impact
6. **Note breaking changes**: If applicable
## Interactive commit helper
Use `git add -p` for selective staging:
```bash
# Stage changes interactively
git add -p
# Review what's staged
git diff --staged
# Commit with message
git commit -m "type(scope): description"
```
## Amending commits
Fix the last commit message:
```bash
# Amend commit message only
git commit --amend
# Amend and add more changes
git add forgotten-file.js
git commit --amend --no-edit
```
## Best practices
1. **Atomic commits** - One logical change per commit
2. **Test before commit** - Ensure code works
3. **Reference issues** - Include issue numbers if applicable
4. **Keep it focused** - Don't mix unrelated changes
5. **Write for humans** - Future you will read this
## Commit message checklist
- [ ] Type is appropriate (feat/fix/docs/etc.)
- [ ] Scope is specific and clear
- [ ] Summary is under 50 characters
- [ ] Summary uses imperative mood
- [ ] Body explains WHY not just WHAT
- [ ] Breaking changes are clearly marked
- [ ] Related issue numbers are included

View File

@@ -0,0 +1,352 @@
---
name: git-workflow
description: Enforces ISA-Frontend project Git workflow conventions including branch naming, conventional commits, and PR creation against develop branch
---
# Git Workflow Skill
Enforces Git workflow conventions specific to the ISA-Frontend project.
## When to Use
- Creating new branches for features or bugfixes
- Writing commit messages
- Creating pull requests
- Any Git operations requiring adherence to project conventions
## Core Principles
### 1. Default Branch is `develop` (NOT `main`)
- **All PRs target**: `develop` branch
- **Feature branches from**: `develop`
- **Never push directly to**: `develop` or `main`
### 2. Branch Naming Convention
**Format**: `<type>/{task-id}-{short-description}`
**Types**:
- `feature/` - New features or enhancements
- `bugfix/` - Bug fixes
- `hotfix/` - Emergency production fixes
**Rules**:
- Use English kebab-case for descriptions
- Start with task/issue ID (e.g., `5391`)
- Keep description concise - shorten if too long
- Use hyphens to separate words
**Examples**:
```bash
# Good
feature/5391-praemie-checkout-action-card-delivery-order
bugfix/6123-fix-login-redirect-loop
hotfix/7890-critical-payment-error
# Bad
feature/praemie-checkout # Missing task ID
feature/5391_praemie # Using underscores
feature-5391-very-long-description-that-goes-on-forever # Too long
```
### 3. Conventional Commits (WITHOUT Co-Author Tags)
**Format**: `<type>(<scope>): <description>`
**Types**:
- `feat`: New feature
- `fix`: Bug fix
- `docs`: Documentation only
- `style`: Code style (formatting, missing semicolons)
- `refactor`: Code restructuring without feature changes
- `perf`: Performance improvements
- `test`: Adding or updating tests
- `build`: Build system or dependencies
- `ci`: CI configuration
- `chore`: Maintenance tasks
**Rules**:
-**NO** "Generated with Claude Code" tags
-**NO** "Co-Authored-By: Claude" tags
- ✅ Keep first line under 72 characters
- ✅ Use imperative mood ("add" not "added")
- ✅ Body optional but recommended for complex changes
**Examples**:
```bash
# Good
feat(checkout): add bonus card selection for delivery orders
fix(crm): resolve customer search filter reset issue
refactor(oms): extract return validation logic into service
# Bad
feat(checkout): add bonus card selection
Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
# Also bad
Added new feature # Wrong tense
Fix bug # Missing scope
```
### 4. Pull Request Creation
**Target Branch**: Always `develop`
**PR Title Format**: Same as conventional commit
```
feat(domain): concise description of changes
```
**PR Body Structure**:
```markdown
## Summary
- Brief bullet points of changes
## Related Tasks
- Closes #{task-id}
- Refs #{related-task}
## Test Plan
- [ ] Unit tests added/updated
- [ ] E2E attributes added
- [ ] Manual testing completed
## Breaking Changes
None / List breaking changes
## Screenshots (if UI changes)
[Add screenshots]
```
## Common Workflows
### Creating a Feature Branch
```bash
# 1. Update develop
git checkout develop
git pull origin develop
# 2. Create feature branch
git checkout -b feature/5391-praemie-checkout-action-card
# 3. Work and commit
git add .
git commit -m "feat(checkout): add primary bonus card selection logic"
# 4. Push to remote
git push -u origin feature/5391-praemie-checkout-action-card
# 5. Create PR targeting develop (use gh CLI or web UI)
```
### Creating a Bugfix Branch
```bash
# From develop
git checkout develop
git pull origin develop
git checkout -b bugfix/6123-login-redirect-loop
# Commit
git commit -m "fix(auth): resolve infinite redirect on logout"
```
### Creating a Hotfix Branch
```bash
# From main (production)
git checkout main
git pull origin main
git checkout -b hotfix/7890-payment-processing-error
# Commit
git commit -m "fix(checkout): critical payment API timeout handling"
# Merge to both main and develop
```
## Commit Message Guidelines
### Good Commit Messages
```bash
feat(crm): add customer loyalty tier calculation
Implements three-tier loyalty system based on annual spend.
Includes migration for existing customer data.
Refs #5234
---
fix(oms): prevent duplicate return submissions
Adds debouncing to return form submission and validates
against existing returns in the last 60 seconds.
Closes #5891
---
refactor(catalogue): extract product search into dedicated service
Moves search logic from component to ProductSearchService
for better testability and reusability.
---
perf(remission): optimize remission list query with pagination
Reduces initial load time from 3s to 800ms by implementing
cursor-based pagination.
Closes #6234
```
### Bad Commit Messages
```bash
# Too vague
fix: bug fixes
# Missing scope
feat: new feature
# Wrong tense
fixed the login issue
# Including banned tags
feat(checkout): add feature
Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
```
## Git Configuration Checks
### Verify Git Setup
```bash
# Check current branch
git branch --show-current
# Verify remote
git remote -v # Should show origin pointing to ISA-Frontend
# Check for uncommitted changes
git status
```
## Common Mistakes to Avoid
```bash
# ❌ Creating PR against main
gh pr create --base main # WRONG
# ✅ Always target develop
gh pr create --base develop # CORRECT
# ❌ Using underscores in branch names
git checkout -b feature/5391_my_feature # WRONG
# ✅ Use hyphens
git checkout -b feature/5391-my-feature # CORRECT
# ❌ Adding co-author tags
git commit -m "feat: something
Co-Authored-By: Claude <noreply@anthropic.com>" # WRONG
# ✅ Clean commit message
git commit -m "feat(scope): something" # CORRECT
# ❌ Forgetting task ID in branch name
git checkout -b feature/new-checkout-flow # WRONG
# ✅ Include task ID
git checkout -b feature/5391-new-checkout-flow # CORRECT
```
## Integration with Claude Code
When Claude Code creates commits or PRs:
### Commit Creation
```bash
# Claude uses conventional commits WITHOUT attribution
git commit -m "feat(checkout): implement bonus card selection
Adds logic for selecting primary bonus card during checkout
for delivery orders. Includes validation and error handling.
Refs #5391"
```
### PR Creation
```bash
# Target develop by default
gh pr create --base develop \
--title "feat(checkout): implement bonus card selection" \
--body "## Summary
- Add primary bonus card selection logic
- Implement validation for delivery orders
- Add error handling for API failures
## Related Tasks
- Closes #5391
## Test Plan
- [x] Unit tests added
- [x] E2E attributes added
- [x] Manual testing completed"
```
## Branch Cleanup
### After PR Merge
```bash
# Update develop
git checkout develop
git pull origin develop
# Delete local feature branch
git branch -d feature/5391-praemie-checkout
# Delete remote branch (usually done by PR merge)
git push origin --delete feature/5391-praemie-checkout
```
## Quick Reference
```bash
# Branch naming
feature/{task-id}-{description}
bugfix/{task-id}-{description}
hotfix/{task-id}-{description}
# Commit format
<type>(<scope>): <description>
# Common types
feat, fix, docs, style, refactor, perf, test, build, ci, chore
# PR target
Always: develop (NOT main)
# Banned in commits
- "Generated with Claude Code"
- "Co-Authored-By: Claude"
- Any AI attribution
```
## Resources
- [Conventional Commits](https://www.conventionalcommits.org/)
- Project PR template: `.github/pull_request_template.md`
- Code review standards: `.github/review-instructions.md`

View File

@@ -0,0 +1,291 @@
# HTML Template - Testing & Accessibility Attributes
This skill should be used when writing or reviewing HTML templates to ensure proper testing and accessibility attributes are included.
## When to Use This Skill
Use this skill when:
- Writing or modifying Angular component templates
- Creating any HTML templates or markup
- Reviewing code for testing and accessibility compliance
- Adding interactive elements (buttons, inputs, links, etc.)
- Implementing forms, lists, navigation, or dialogs
**Works seamlessly with:** `angular-template` skill for complete Angular template guidance.
## Overview
This skill provides comprehensive guidance for two critical HTML attribute categories:
### 1. E2E Testing Attributes
Enable automated end-to-end testing by providing stable selectors for QA automation:
- **`data-what`**: Semantic description of element's purpose
- **`data-which`**: Unique identifier for specific instances
- **`data-*`**: Additional contextual information
### 2. ARIA Accessibility Attributes
Ensure web applications are accessible to all users, including those using assistive technologies:
- **Roles**: Define element purpose (button, navigation, dialog, etc.)
- **Properties**: Provide additional context (aria-label, aria-describedby)
- **States**: Indicate dynamic states (aria-expanded, aria-disabled)
- **Live Regions**: Announce dynamic content changes
## Why Both Are Essential
- **E2E Attributes**: Enable reliable automated testing without brittle CSS or XPath selectors
- **ARIA Attributes**: Ensure compliance with WCAG standards and improve user experience for people with disabilities
- **Together**: Create robust, testable, and accessible web applications
## Quick Reference
### Button Example
```html
<button
type="button"
(click)="onSubmit()"
data-what="submit-button"
data-which="registration-form"
aria-label="Submit registration form">
Submit
</button>
```
### Input Example
```html
<input
type="text"
[(ngModel)]="email"
data-what="email-input"
data-which="registration-form"
aria-label="Email address"
aria-describedby="email-hint"
aria-required="true" />
<span id="email-hint">We'll never share your email</span>
```
### Dynamic List Example
```html
@for (item of items; track item.id) {
<li
(click)="selectItem(item)"
data-what="list-item"
[attr.data-which]="item.id"
[attr.data-status]="item.status"
[attr.aria-label]="'Select ' + item.name"
role="button"
tabindex="0">
{{ item.name }}
</li>
}
```
### Link Example
```html
<a
[routerLink]="['/orders', orderId]"
data-what="order-link"
[attr.data-which]="orderId"
[attr.aria-label]="'View order ' + orderNumber">
View Order #{{ orderNumber }}
</a>
```
### Dialog Example
```html
<div
class="dialog"
data-what="confirmation-dialog"
data-which="delete-item"
role="dialog"
aria-modal="true"
aria-labelledby="dialog-title"
aria-describedby="dialog-description">
<h2 id="dialog-title">Confirm Deletion</h2>
<p id="dialog-description">Are you sure you want to delete this item?</p>
<button
(click)="confirm()"
data-what="confirm-button"
data-which="delete-dialog"
aria-label="Confirm deletion">
Delete
</button>
<button
(click)="cancel()"
data-what="cancel-button"
data-which="delete-dialog"
aria-label="Cancel deletion">
Cancel
</button>
</div>
```
## Common Patterns by Element Type
### Interactive Elements That Need Attributes
**Required attributes for:**
- Buttons (`<button>`, `<ui-button>`, custom button components)
- Form inputs (`<input>`, `<textarea>`, `<select>`)
- Links (`<a>`, `[routerLink]`)
- Clickable elements (elements with `(click)` handlers)
- Custom interactive components
- List items in dynamic lists
- Navigation items
- Dialog/modal controls
### Naming Conventions
**E2E `data-what` patterns:**
- `*-button` (submit-button, cancel-button, delete-button)
- `*-input` (email-input, search-input, quantity-input)
- `*-link` (product-link, order-link, customer-link)
- `*-item` (list-item, menu-item, card-item)
- `*-dialog` (confirm-dialog, error-dialog, info-dialog)
- `*-dropdown` (status-dropdown, category-dropdown)
**E2E `data-which` guidelines:**
- Use unique identifiers: `data-which="primary"`, `data-which="customer-list"`
- Bind dynamically for lists: `[attr.data-which]="item.id"`
- Combine with context: `data-which="customer-{{ customerId }}-edit"`
**ARIA role patterns:**
- Interactive elements: `button`, `link`, `menuitem`
- Structural: `navigation`, `main`, `complementary`, `contentinfo`
- Widget: `dialog`, `alertdialog`, `tooltip`, `tablist`, `tab`
- Landmark: `banner`, `search`, `form`, `region`
## Best Practices
### E2E Attributes
1. ✅ Add to ALL interactive elements
2. ✅ Use kebab-case for `data-what` values
3. ✅ Ensure `data-which` is unique within the view
4. ✅ Use Angular binding for dynamic values: `[attr.data-*]`
5. ✅ Avoid including sensitive data in attributes
6. ✅ Document complex attribute patterns in template comments
### ARIA Attributes
1. ✅ Use semantic HTML first (use `<button>` instead of `<div role="button">`)
2. ✅ Provide text alternatives for all interactive elements
3. ✅ Ensure proper keyboard navigation (tabindex, focus management)
4. ✅ Use `aria-label` when visual label is missing
5. ✅ Use `aria-labelledby` to reference existing visible labels
6. ✅ Keep ARIA attributes in sync with visual states
7. ✅ Test with screen readers (NVDA, JAWS, VoiceOver)
### Combined Best Practices
1. ✅ Add both E2E and ARIA attributes to every interactive element
2. ✅ Keep attributes close together in the HTML for readability
3. ✅ Update tests to use `data-what` and `data-which` selectors
4. ✅ Validate coverage: all interactive elements should have both types
5. ✅ Review with QA and accessibility teams
## Detailed References
For comprehensive guides, examples, and patterns, see:
- **[E2E Testing Attributes](references/e2e-attributes.md)** - Complete E2E attribute patterns and conventions
- **[ARIA Accessibility Attributes](references/aria-attributes.md)** - Comprehensive ARIA guidance and WCAG compliance
- **[Combined Patterns](references/combined-patterns.md)** - Real-world examples with both attribute types
## Project-Specific Links
- **Testing Guidelines**: `docs/guidelines/testing.md` - Project testing standards including E2E attributes
- **CLAUDE.md**: Project conventions and requirements
- **Angular Template Skill**: `.claude/skills/angular-template` - For Angular-specific syntax
## Validation Checklist
Before considering template complete:
- [ ] All buttons have `data-what`, `data-which`, and `aria-label`
- [ ] All inputs have `data-what`, `data-which`, and appropriate ARIA attributes
- [ ] All links have `data-what`, `data-which`, and descriptive ARIA labels
- [ ] Dynamic lists use `[attr.data-*]` bindings with unique identifiers
- [ ] Dialogs have proper ARIA roles and relationships
- [ ] Forms have proper field associations and error announcements
- [ ] Interactive elements are keyboard accessible (tabindex where needed)
- [ ] No duplicate `data-which` values within the same view
- [ ] Screen reader testing completed (if applicable)
## Example: Complete Form
```html
<form
data-what="registration-form"
data-which="user-signup"
role="form"
aria-labelledby="form-title">
<h2 id="form-title">User Registration</h2>
<div class="form-field">
<label for="username-input">Username</label>
<input
id="username-input"
type="text"
[(ngModel)]="username"
data-what="username-input"
data-which="registration-form"
aria-required="true"
aria-describedby="username-hint" />
<span id="username-hint">Must be at least 3 characters</span>
</div>
<div class="form-field">
<label for="email-input">Email</label>
<input
id="email-input"
type="email"
[(ngModel)]="email"
data-what="email-input"
data-which="registration-form"
aria-required="true"
[attr.aria-invalid]="emailError ? 'true' : null"
aria-describedby="email-error" />
@if (emailError) {
<span
id="email-error"
role="alert"
aria-live="polite">
{{ emailError }}
</span>
}
</div>
<div class="form-actions">
<button
type="submit"
(click)="onSubmit()"
data-what="submit-button"
data-which="registration-form"
[attr.aria-disabled]="!isValid"
aria-label="Submit registration form">
Register
</button>
<button
type="button"
(click)="onCancel()"
data-what="cancel-button"
data-which="registration-form"
aria-label="Cancel registration">
Cancel
</button>
</div>
</form>
```
## Remember
- **Always use both E2E and ARIA attributes together**
- **E2E attributes enable automated testing** - your QA team relies on them
- **ARIA attributes enable accessibility** - legal requirement and right thing to do
- **Test with real users and assistive technologies** - automated checks aren't enough
- **Keep attributes up-to-date** - maintain as code changes
---
**This skill works automatically with Angular templates. Both E2E and ARIA attributes should be added to every interactive element.**

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,842 @@
# E2E Testing Attributes - Complete Reference
This reference provides comprehensive guidance for adding E2E (End-to-End) testing attributes to HTML templates for reliable automated testing.
## Table of Contents
- [Overview](#overview)
- [Core Attribute Types](#core-attribute-types)
- [Why E2E Attributes?](#why-e2e-attributes)
- [Naming Conventions](#naming-conventions)
- [Patterns by Element Type](#patterns-by-element-type)
- [Patterns by Component Type](#patterns-by-component-type)
- [Dynamic Attributes](#dynamic-attributes)
- [Best Practices](#best-practices)
- [Validation](#validation)
- [Testing Integration](#testing-integration)
## Overview
E2E testing attributes provide stable, semantic selectors for automated testing. They enable QA automation without relying on brittle CSS classes, IDs, or XPath selectors that frequently break when styling changes.
## Core Attribute Types
### 1. `data-what` (Required)
**Purpose**: Semantic description of the element's purpose or type
**Format**: kebab-case string
**Examples**:
- `data-what="submit-button"`
- `data-what="search-input"`
- `data-what="product-link"`
- `data-what="list-item"`
**Guidelines**:
- Describes WHAT the element is or does
- Should be consistent across similar elements
- Use descriptive, semantic names
- Keep it concise but clear
### 2. `data-which` (Required)
**Purpose**: Unique identifier for the specific instance of this element type
**Format**: kebab-case string or dynamic binding
**Examples**:
- `data-which="primary"` (static)
- `data-which="customer-form"` (static)
- `[attr.data-which]="item.id"` (dynamic)
- `[attr.data-which]="'customer-' + customerId"` (dynamic with context)
**Guidelines**:
- Identifies WHICH specific instance of this element type
- Must be unique within the same view/component
- Use dynamic binding for list items: `[attr.data-which]="item.id"`
- Can combine multiple identifiers: `data-which="customer-123-edit"`
### 3. `data-*` (Contextual)
**Purpose**: Additional contextual information about state, status, or data
**Format**: Custom attributes with kebab-case names
**Examples**:
- `data-status="active"`
- `data-index="0"`
- `data-role="admin"`
- `[attr.data-count]="items.length"`
**Guidelines**:
- Use for additional context that helps testing
- Avoid sensitive data (passwords, tokens, PII)
- Use Angular binding for dynamic values: `[attr.data-*]`
- Keep attribute names semantic and clear
## Why E2E Attributes?
### Problems with Traditional Selectors
**CSS Classes (Bad)**:
```html
<!-- Brittle - breaks when styling changes -->
<button class="btn btn-primary submit">Submit</button>
```
```javascript
// Test breaks when class names change
await page.click('.btn-primary.submit');
```
**XPath (Bad)**:
```javascript
// Brittle - breaks when structure changes
await page.click('//div[@class="form"]/button[2]');
```
**IDs (Better, but limited)**:
```html
<!-- IDs must be unique across entire page -->
<button id="submit-btn">Submit</button>
```
### Benefits of E2E Attributes
**Stable, Semantic Selectors (Good)**:
```html
<button
class="btn btn-primary"
data-what="submit-button"
data-which="registration-form">
Submit
</button>
```
```javascript
// Stable - survives styling and structure changes
await page.click('[data-what="submit-button"][data-which="registration-form"]');
```
**Advantages**:
- ✅ Decoupled from styling (CSS classes can change freely)
- ✅ Semantic and self-documenting
- ✅ Consistent across the application
- ✅ Easy to read and maintain
- ✅ Survives refactoring and restructuring
- ✅ QA and developers speak the same language
## Naming Conventions
### Common `data-what` Patterns
| Pattern | Use Case | Examples |
|---------|----------|----------|
| `*-button` | All button elements | `submit-button`, `cancel-button`, `delete-button`, `save-button` |
| `*-input` | Text inputs and textareas | `email-input`, `search-input`, `quantity-input`, `password-input` |
| `*-select` | Dropdown/select elements | `status-select`, `category-select`, `country-select` |
| `*-checkbox` | Checkbox inputs | `terms-checkbox`, `subscribe-checkbox`, `remember-checkbox` |
| `*-radio` | Radio button inputs | `payment-radio`, `shipping-radio` |
| `*-link` | Navigation links | `product-link`, `order-link`, `customer-link`, `home-link` |
| `*-item` | List/grid items | `list-item`, `menu-item`, `card-item`, `row-item` |
| `*-dialog` | Modals and dialogs | `confirm-dialog`, `error-dialog`, `info-dialog` |
| `*-dropdown` | Dropdown menus | `actions-dropdown`, `filter-dropdown` |
| `*-toggle` | Toggle switches | `theme-toggle`, `notifications-toggle` |
| `*-tab` | Tab navigation | `profile-tab`, `settings-tab` |
| `*-badge` | Status badges | `status-badge`, `count-badge` |
| `*-icon` | Interactive icons | `close-icon`, `menu-icon`, `search-icon` |
### `data-which` Naming Guidelines
**Static unique identifiers** (single instance):
- `data-which="primary"` - Primary action button
- `data-which="secondary"` - Secondary action button
- `data-which="main-search"` - Main search input
- `data-which="customer-form"` - Customer form context
**Dynamic identifiers** (multiple instances):
- `[attr.data-which]="item.id"` - List item by ID
- `[attr.data-which]="'product-' + product.id"` - Product item
- `[attr.data-which]="index"` - By array index (use sparingly)
**Contextual identifiers** (combine context):
- `data-which="customer-{{ customerId }}-edit"` - Edit button for specific customer
- `data-which="order-{{ orderId }}-cancel"` - Cancel button for specific order
## Patterns by Element Type
### Buttons
```html
<!-- Submit Button -->
<button
type="submit"
(click)="onSubmit()"
data-what="submit-button"
data-which="registration-form">
Submit
</button>
<!-- Cancel Button -->
<button
type="button"
(click)="onCancel()"
data-what="cancel-button"
data-which="registration-form">
Cancel
</button>
<!-- Delete Button with Confirmation -->
<button
(click)="onDelete(item)"
data-what="delete-button"
[attr.data-which]="item.id"
[attr.data-status]="item.canDelete ? 'enabled' : 'disabled'">
Delete
</button>
<!-- Icon Button -->
<button
(click)="toggleMenu()"
data-what="menu-button"
data-which="main-nav"
aria-label="Toggle menu">
<i class="icon-menu"></i>
</button>
<!-- Custom Button Component -->
<ui-button
(click)="save()"
data-what="save-button"
data-which="order-form">
Save Order
</ui-button>
```
### Inputs
```html
<!-- Text Input -->
<input
type="text"
[(ngModel)]="email"
placeholder="Email address"
data-what="email-input"
data-which="registration-form" />
<!-- Textarea -->
<textarea
[(ngModel)]="comments"
data-what="comments-textarea"
data-which="feedback-form"
rows="4"></textarea>
<!-- Number Input with State -->
<input
type="number"
[(ngModel)]="quantity"
data-what="quantity-input"
data-which="order-form"
[attr.data-min]="minQuantity"
[attr.data-max]="maxQuantity" />
<!-- Search Input -->
<input
type="search"
[(ngModel)]="searchTerm"
(input)="onSearch()"
placeholder="Search products..."
data-what="search-input"
data-which="product-catalog" />
<!-- Password Input -->
<input
type="password"
[(ngModel)]="password"
data-what="password-input"
data-which="login-form" />
```
### Select/Dropdown
```html
<!-- Basic Select -->
<select
[(ngModel)]="selectedStatus"
data-what="status-select"
data-which="order-filter">
<option value="">All Statuses</option>
<option value="pending">Pending</option>
<option value="completed">Completed</option>
</select>
<!-- Custom Dropdown Component -->
<ui-dropdown
[(value)]="selectedCategory"
data-what="category-dropdown"
data-which="product-filter">
</ui-dropdown>
```
### Checkboxes and Radios
```html
<!-- Checkbox -->
<label>
<input
type="checkbox"
[(ngModel)]="agreedToTerms"
data-what="terms-checkbox"
data-which="registration-form" />
I agree to the terms
</label>
<!-- Radio Group -->
<div data-what="payment-radio-group" data-which="checkout-form">
<label>
<input
type="radio"
name="payment"
value="credit"
[(ngModel)]="paymentMethod"
data-what="payment-radio"
data-which="credit-card" />
Credit Card
</label>
<label>
<input
type="radio"
name="payment"
value="paypal"
[(ngModel)]="paymentMethod"
data-what="payment-radio"
data-which="paypal" />
PayPal
</label>
</div>
```
### Links
```html
<!-- Static Link -->
<a
routerLink="/about"
data-what="nav-link"
data-which="about">
About Us
</a>
<!-- Dynamic Link with ID -->
<a
[routerLink]="['/products', product.id]"
data-what="product-link"
[attr.data-which]="product.id">
{{ product.name }}
</a>
<!-- External Link -->
<a
href="https://example.com"
target="_blank"
data-what="external-link"
data-which="documentation">
Documentation
</a>
<!-- Action Link (not navigation) -->
<a
(click)="downloadReport()"
data-what="download-link"
data-which="sales-report">
Download Report
</a>
```
### Lists and Tables
```html
<!-- Dynamic List with @for -->
<ul data-what="product-list" data-which="catalog">
@for (product of products; track product.id) {
<li
(click)="selectProduct(product)"
data-what="list-item"
[attr.data-which]="product.id"
[attr.data-status]="product.stock > 0 ? 'in-stock' : 'out-of-stock'">
{{ product.name }}
</li>
}
</ul>
<!-- Table Row -->
<table data-what="orders-table" data-which="customer-orders">
<tbody>
@for (order of orders; track order.id) {
<tr
data-what="table-row"
[attr.data-which]="order.id">
<td>{{ order.id }}</td>
<td>{{ order.date }}</td>
<td>
<button
data-what="view-button"
[attr.data-which]="order.id">
View
</button>
</td>
</tr>
}
</tbody>
</table>
```
### Dialogs and Modals
```html
<!-- Confirmation Dialog -->
<div
*ngIf="showDialog"
data-what="confirmation-dialog"
data-which="delete-item">
<h2>Confirm Deletion</h2>
<p>Are you sure you want to delete this item?</p>
<button
(click)="confirmDelete()"
data-what="confirm-button"
data-which="delete-dialog">
Delete
</button>
<button
(click)="cancelDelete()"
data-what="cancel-button"
data-which="delete-dialog">
Cancel
</button>
</div>
<!-- Info Dialog with Close -->
<div
data-what="info-dialog"
data-which="welcome-message">
<button
(click)="closeDialog()"
data-what="close-button"
data-which="dialog">
×
</button>
<div data-what="dialog-content" data-which="welcome">
<h2>Welcome!</h2>
<p>Thank you for joining us.</p>
</div>
</div>
```
## Patterns by Component Type
### Form Components
```html
<form data-what="user-form" data-which="registration">
<!-- Field inputs -->
<input
data-what="username-input"
data-which="registration-form"
type="text" />
<input
data-what="email-input"
data-which="registration-form"
type="email" />
<!-- Action buttons -->
<button
data-what="submit-button"
data-which="registration-form"
type="submit">
Submit
</button>
<button
data-what="cancel-button"
data-which="registration-form"
type="button">
Cancel
</button>
</form>
```
### List/Table Components
```html
<!-- Each item needs unique data-which -->
@for (item of items; track item.id) {
<div
data-what="list-item"
[attr.data-which]="item.id">
<span data-what="item-name" [attr.data-which]="item.id">
{{ item.name }}
</span>
<button
data-what="edit-button"
[attr.data-which]="item.id">
Edit
</button>
<button
data-what="delete-button"
[attr.data-which]="item.id">
Delete
</button>
</div>
}
```
### Navigation Components
```html
<nav data-what="main-navigation" data-which="header">
<a
routerLink="/dashboard"
data-what="nav-link"
data-which="dashboard">
Dashboard
</a>
<a
routerLink="/orders"
data-what="nav-link"
data-which="orders">
Orders
</a>
<a
routerLink="/customers"
data-what="nav-link"
data-which="customers">
Customers
</a>
</nav>
<!-- Breadcrumbs -->
<nav data-what="breadcrumb" data-which="page-navigation">
@for (crumb of breadcrumbs; track $index) {
<a
[routerLink]="crumb.url"
data-what="breadcrumb-link"
[attr.data-which]="crumb.id">
{{ crumb.label }}
</a>
}
</nav>
```
### Dialog/Modal Components
```html
<!-- All dialog buttons need clear identifiers -->
<div data-what="modal" data-which="user-settings">
<button
data-what="close-button"
data-which="modal">
Close
</button>
<button
data-what="save-button"
data-which="modal">
Save Changes
</button>
<button
data-what="reset-button"
data-which="modal">
Reset to Defaults
</button>
</div>
```
## Dynamic Attributes
### Using Angular Binding
When values need to be dynamic, use Angular's attribute binding:
```html
<!-- Static (simple values) -->
<button data-what="submit-button" data-which="form">
<!-- Dynamic (from component properties) -->
<button
data-what="submit-button"
[attr.data-which]="formId">
<!-- Dynamic (from loop variables) -->
@for (item of items; track item.id) {
<div
data-what="list-item"
[attr.data-which]="item.id"
[attr.data-status]="item.status"
[attr.data-index]="$index">
</div>
}
<!-- Dynamic (computed values) -->
<button
data-what="action-button"
[attr.data-which]="'customer-' + customerId + '-' + action">
</button>
```
### Loop Variables
Angular's `@for` provides special variables:
```html
@for (item of items; track item.id; let idx = $index; let isFirst = $first) {
<div
data-what="list-item"
[attr.data-which]="item.id"
[attr.data-index]="idx"
[attr.data-first]="isFirst">
{{ item.name }}
</div>
}
```
## Best Practices
### Do's ✅
1. **Add to ALL interactive elements**
- Buttons, inputs, links, clickable elements
- Custom components that handle user interaction
- Form controls and navigation items
2. **Use consistent naming**
- Follow the naming patterns (e.g., `*-button`, `*-input`)
- Use kebab-case consistently
- Be descriptive but concise
3. **Ensure uniqueness**
- `data-which` must be unique within the view
- Use item IDs for list items: `[attr.data-which]="item.id"`
- Combine context when needed: `data-which="form-primary-submit"`
4. **Use Angular binding for dynamic values**
- `[attr.data-which]="item.id"`
- `data-which="{{ item.id }}"` ❌ (avoid interpolation)
5. **Document complex patterns**
- Add comments for non-obvious attribute choices
- Document the expected test selectors
6. **Keep attributes updated**
- Update when element purpose changes
- Remove when elements are removed
- Maintain consistency across refactoring
### Don'ts ❌
1. **Don't include sensitive data**
-`data-which="password-{{ userPassword }}"`
-`data-token="{{ authToken }}"`
-`data-ssn="{{ socialSecurity }}"`
2. **Don't use generic values**
-`data-what="button"` (too generic)
-`data-what="submit-button"` (specific)
3. **Don't duplicate `data-which` in the same view**
- ❌ Two buttons with `data-which="primary"`
-`data-which="form-primary"` and `data-which="dialog-primary"`
4. **Don't rely only on index for lists**
-`[attr.data-which]="$index"` (changes when list reorders)
-`[attr.data-which]="item.id"` (stable identifier)
5. **Don't forget about custom components**
- Custom components need attributes too
- Attributes should be on the component tag, not just internal elements
## Validation
### Coverage Check
Ensure all interactive elements have E2E attributes:
```bash
# Count interactive elements
grep -E '\(click\)|routerLink|button|input|select|textarea' component.html | wc -l
# Count elements with data-what
grep -c 'data-what=' component.html
# Find elements missing E2E attributes
grep -E '\(click\)|button' component.html | grep -v 'data-what='
```
### Uniqueness Check
Verify no duplicate `data-which` values in the same template:
```typescript
// In component tests
it('should have unique data-which attributes', () => {
const elements = fixture.nativeElement.querySelectorAll('[data-which]');
const dataWhichValues = Array.from(elements).map(
(el: any) => el.getAttribute('data-which')
);
const uniqueValues = new Set(dataWhichValues);
expect(dataWhichValues.length).toBe(uniqueValues.size);
});
```
### Validation Checklist
- [ ] All buttons have `data-what` and `data-which`
- [ ] All inputs have `data-what` and `data-which`
- [ ] All links have `data-what` and `data-which`
- [ ] All clickable elements have attributes
- [ ] Dynamic lists use `[attr.data-which]="item.id"`
- [ ] No duplicate `data-which` values in the same view
- [ ] No sensitive data in attributes
- [ ] Custom components have attributes
- [ ] Attributes use kebab-case
- [ ] Coverage: 100% of interactive elements
## Testing Integration
### Using E2E Attributes in Tests
**Unit Tests (Angular Testing Utilities)**:
```typescript
import { ComponentFixture, TestBed } from '@angular/core/testing';
describe('MyComponent', () => {
let fixture: ComponentFixture<MyComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MyComponent],
}).compileComponents();
fixture = TestBed.createComponent(MyComponent);
fixture.detectChanges();
});
it('should have submit button with E2E attributes', () => {
const button = fixture.nativeElement.querySelector(
'[data-what="submit-button"][data-which="registration-form"]'
);
expect(button).toBeTruthy();
expect(button.textContent).toContain('Submit');
});
it('should have unique data-which for list items', () => {
const items = fixture.nativeElement.querySelectorAll('[data-what="list-item"]');
const dataWhichValues = Array.from(items).map(
(item: any) => item.getAttribute('data-which')
);
// All should have unique IDs
const uniqueValues = new Set(dataWhichValues);
expect(dataWhichValues.length).toBe(uniqueValues.size);
});
});
```
**E2E Tests (Playwright)**:
```typescript
import { test, expect } from '@playwright/test';
test('user registration flow', async ({ page }) => {
await page.goto('/register');
// Fill form using E2E attributes
await page.fill(
'[data-what="username-input"][data-which="registration-form"]',
'johndoe'
);
await page.fill(
'[data-what="email-input"][data-which="registration-form"]',
'john@example.com'
);
// Click submit using E2E attributes
await page.click(
'[data-what="submit-button"][data-which="registration-form"]'
);
// Verify success
await expect(page.locator('[data-what="success-message"]')).toBeVisible();
});
```
**E2E Tests (Cypress)**:
```typescript
describe('Order Management', () => {
it('should edit an order', () => {
cy.visit('/orders');
// Find specific order by ID using data-which
cy.get('[data-what="list-item"][data-which="order-123"]')
.should('be.visible');
// Click edit button for that specific order
cy.get('[data-what="edit-button"][data-which="order-123"]')
.click();
// Update quantity
cy.get('[data-what="quantity-input"][data-which="order-form"]')
.clear()
.type('5');
// Save changes
cy.get('[data-what="save-button"][data-which="order-form"]')
.click();
});
});
```
## Documentation in Templates
Add comment blocks to document E2E attributes:
```html
<!--
E2E Test Attributes:
- data-what="submit-button" data-which="registration-form" - Main form submission
- data-what="cancel-button" data-which="registration-form" - Cancel registration
- data-what="username-input" data-which="registration-form" - Username field
- data-what="email-input" data-which="registration-form" - Email field
- data-what="password-input" data-which="registration-form" - Password field
-->
<form data-what="registration-form" data-which="user-signup">
<!-- Form content -->
</form>
```
## Related Documentation
- **[ARIA Accessibility Attributes](aria-attributes.md)** - Accessibility guidance
- **[Combined Patterns](combined-patterns.md)** - Examples with E2E + ARIA together
- **Testing Guidelines**: `docs/guidelines/testing.md` - Project testing standards
- **CLAUDE.md**: Project code quality requirements
## Summary
E2E testing attributes are essential for:
- ✅ Stable, maintainable automated tests
- ✅ Clear communication between developers and QA
- ✅ Tests that survive styling and structural changes
- ✅ Self-documenting code that expresses intent
- ✅ Reliable CI/CD pipelines
**Always add `data-what` and `data-which` to every interactive element.**

View File

@@ -1,5 +1,5 @@
---
name: tailwind-isa
name: tailwind
description: This skill should be used when working with Tailwind CSS styling in the ISA-Frontend project. Use it when writing component styles, choosing color values, applying typography, creating buttons, or determining appropriate spacing and layout utilities. Essential for maintaining design system consistency.
---

2
.gitignore vendored
View File

@@ -78,3 +78,5 @@ vitest.config.*.timestamp*
nx.instructions.md
CLAUDE.md
*.pyc
.vite
reports/

View File

@@ -17,6 +17,13 @@
"figma-desktop": {
"type": "http",
"url": "http://127.0.0.1:3845/mcp"
},
"memory": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-memory"],
"env": {
"MEMORY_FILE_PATH": "~/Projects/ISA-Frontend/memory.json"
}
}
}
}

139
CHANGELOG.md Normal file
View File

@@ -0,0 +1,139 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- (checkout-reward) Disable and hide delivery options for reward feature purchases
- (purchase-options) Add disabledPurchaseOptions with flexible visibility control
- (reward-catalog) Pre-select in-store option for reward purchases
- (checkout) Complete reward order confirmation with reusable product info component
- (checkout) Implement reward order confirmation UI and confirmation list item action card component
- (checkout) Add reward order confirmation feature with schema migrations
- (stock-info) Implement request batching with BatchingResource
- (crm) Introduce PrimaryCustomerCardResource and format-name utility
- Angular template skill for modern template patterns
- Tailwind ISA design system skill
### Changed
- (checkout-reward) Implement hierarchical grouping on rewards order confirmation
- (checkout) Move reward selection helpers to data-access for reusability
- (common) Add validation for notification channel flag combinations
- (customer) Merge continueReward and continue methods into unified flow
- Comprehensive CLAUDE.md overhaul with library reference system
- Add Claude Code agents, commands, and skills infrastructure
### Fixed
- (checkout) Resolve currency constraint violations in price handling
- (checkout) Add complete price structure for reward delivery orders
- (checkout) Correct reward output desktop/mobile layout and add insufficient stock warnings
- (customer-card) Implement navigation flow from customer card to reward search
- (purchase-options) Correct customer features mapping
- (reward-order-confirmation) Group items by item-level delivery type
- (reward-order-confirmation) Correct typo and add loading state to collect button
- (reward-confirmation) Improve action card visibility and status messages
- (reward-selection-pop-up) Fix width issue
## [4.2] - 2025-10-23
### Added
- (checkout-reward) Add reward checkout feature (#5258)
- (crm) Add crm-data-access library with initial component and tests
- (shared-filter) Add canApply input to filter input menu components
- Architecture Decision Records (ADRs) documentation
- Error handling and validation infrastructure enhancements
### Changed
- (tabs) Implement backwards compatibility for Process → Tabs migration
- (notifications) Update remission path logic to use Date.now()
- (customer-card) Deactivate Create Customer with Card feature
- Update package.json and recreate package-lock.json for npm@11.6
- Disable markdown format on save in VSCode settings
### Fixed
- (process) Simulate "old tab logic" for compatibility
- (tabs) Correct singleton tabs interaction with new tab areas
- (remission-list) Prioritize reload trigger over exact search
- (remission-list-item, remission-list-empty-state) Improve empty state handling
## [4.1] - 2025-10-06
### Added
- (isa-app) Migrate remission navigation to tab-based routing system
- (utils) Add scroll-top button component
- (remission-list, empty-state) Add comprehensive empty state handling with user guidance
- (remission) Ensure package assignment before completing return receipts
- (libs-ui-dialog-feedback-dialog) Add auto-close functionality with configurable delay
- (old-ui-tooltip) Add pointer-events-auto to tooltip panel
### Changed
- (remission-list) Improve item update handling and UI feedback
- (remission-list, search-item-to-remit-dialog) Simplify dialog flow by removing intermediate steps
### Fixed
- (remission-list) Ensure list reload after search dialog closes
- (remission-list) Auto-select single search result when remission started
- (remission-list, remission-return-receipt-details, libs-dialog) Improve error handling with dedicated error dialog
- (remission-error) Simplify error handling in remission components
- (remission) Filter search results by stock availability and display stock info
- (remission-list, remission-data-access) Add impediment comment and remaining quantity tracking
- (remission-quantity-and-reason-item) Correct quantity input binding and dropdown behavior
- (remission-quantity-reason) Correct dropdown placeholder and remove hardcoded values
- (remission-filter-label) Improve filter button label display and default text
- (remission-data-access) Remove automatic date defaulting in fetchRemissions
- (remission-shared-search-item-to-remit-dialog) Display context-aware feedback on errors
- (isa-app-shell) Improve navigation link targeting for remission sub-routes
- (oms-data-access) Adjust tolino return eligibility logic for display damage
- (ui-input-controls-dropdown) Prevent multiple dropdowns from being open simultaneously
## [4.0] - 2025-07-23
### Added
- (oms-data-access) Initial implementation of OMS data access layer
- (oms-return-review) Implement return review feature
- (print-button) Implement reusable print button component with service integration
- (scanner) Add full-screen scanner styles and components
- (product-router-link) Add shared product router link directive and builder
- (tooltip) Add tooltip component and directive with customizable triggers
- (shared-scanner) Move scanner to shared/scanner location
- (common-data-access) Add takeUntil operators for keydown events
### Changed
- (oms-return-review, oms-return-summary) Fix return receipt mapping and ensure process completion
- (ui-tooltip) Remove native title attribute from tooltip icon host
- (oms-return-details) Improve layout and styling of order group item controls
- (searchbox) Improve formatting and add showScannerButton getter
- (libs-ui-item-rows) Improve data value wrapping and label sizing
- (shared-filter, search-bar, search-main) Add E2E data attributes for filtering and search
### Fixed
- (return-details) Update email validation and improve error handling
- (return-details) Correct storage key retrieval in ReturnDetailsStore
- (return-details) Small layout fix (#5171)
- (isa-app-moment-locale) Correct locale initialization for date formatting
- (oms-return-search) Fix display and logic issues in return search results
- (oms-return-search) Resolve issues in return search result item rendering
- (oms-task-list-item) Address styling and layout issues in return task list
- (ui-dropdown) Improve dropdown usability and conditional rendering
- (return-search) Correct typo in tooltip content
- (libs-shared-filter) Improve date range equality for default filter inputs
## [3.4] - 2025-02-10
_Earlier versions available in git history. Detailed changelog entries start from version 4.0._
### Historical Versions
Previous versions (3.3, 3.2, 3.1, 3.0, 2.x, 1.x) are available in the git repository.
For detailed information about changes in these versions, please refer to:
- Git tags: `git tag --sort=-creatordate`
- Commit history: `git log <tag-from>..<tag-to>`
- Pull requests in the repository
---
_This changelog was initially generated from git commit history. Future entries will be maintained manually following the Keep a Changelog format._

348
CLAUDE.md
View File

@@ -1,277 +1,34 @@
# CLAUDE.md
> **Last Updated:** 2025-10-22
> **Angular Version:** 20.1.2
> **Nx Version:** 21.3.2
> **Node.js:** ≥22.0.0
> **npm:** ≥10.0.0
This file contains meta-instructions for how Claude should work with the ISA-Frontend codebase.
## 🔴 CRITICAL: Mandatory Agent Usage
**You MUST use these subagents for ALL research tasks:**
**You MUST use these subagents for ALL research and knowledge management tasks:**
- **`docs-researcher`**: For ALL documentation (packages, libraries, READMEs)
- **`docs-researcher-advanced`**: Auto-escalate when docs-researcher fails
- **`Explore`**: For ALL code pattern searches and multi-file analysis
- **`context-manager`**: For complex projects and knowledge preservation with **persistent memory**
- **Direct tools (Read/Bash)**: ONLY for single specific files or commands
**NEW**: The `context-manager` now autonomously stores project knowledge (decisions, patterns, solutions) in persistent memory for cross-session learning.
**Violations of this rule degrade performance and context quality. NO EXCEPTIONS.**
## Project Overview
## Communication Guidelines
This is a sophisticated Angular 20.1.2 monorepo managed by Nx 21.3.2. The main application is `isa-app`, a comprehensive inventory and returns management system for retail/e-commerce operations. The system handles complex workflows including order management (OMS), returns processing (remission), customer relationship management (CRM), product cataloging, and checkout/reward systems.
**Keep answers concise and focused:**
- Provide direct, actionable responses without unnecessary elaboration
- Skip verbose explanations unless specifically requested
- Focus on what the user needs to know, not everything you know
- Use bullet points and structured formatting for clarity
- Only provide detailed explanations when complexity requires it
## Architecture
### Monorepo Structure
- **apps/isa-app**: Main Angular application
- **libs/**: Reusable libraries organized by domain and type
- **core/**: Core utilities (config, logging, storage, tabs, navigation)
- **common/**: Shared utilities (data-access, decorators, print)
- **ui/**: UI component libraries (buttons, dialogs, inputs, etc.)
- **shared/**: Shared domain components (filter, scanner, product components)
- **oms/**: Order Management System features and utilities
- **remission/**: Remission/returns management features
- **catalogue/**: Product catalogue functionality
- **utils/**: General utilities (validation, scroll position, parsing)
- **icons/**: Icon library
- **generated/swagger/**: Auto-generated API client code from OpenAPI specs
### Key Architectural Patterns
- **Domain-Driven Design**: Clear domain boundaries with dedicated modules (OMS, remission, CRM, catalogue, checkout)
- **Layered Architecture**: Strict dependency hierarchy (Feature → Shared/UI → Data Access → Infrastructure)
- **Standalone Components**: All new components use Angular standalone architecture with explicit imports
- **Feature Libraries**: Domain features organized as separate libraries (e.g., `oms-feature-return-search`, `remission-feature-remission-list`)
- **Data Access Layer**: Separate data-access libraries for each domain with NgRx Signals stores
- **Shared UI Components**: 17 dedicated UI component libraries with design system integration
- **Generated API Clients**: 10 auto-generated Swagger/OpenAPI clients with post-processing pipeline
- **Path Aliases**: Comprehensive TypeScript path mapping (`@isa/domain/layer/feature`)
- **Component Prefixes**: Domain-specific prefixes (OMS: `oms-feature-*`, Remission: `remi-*`, UI: `ui-*`)
- **Modern State Management**: NgRx Signals with entities, session persistence, and reactive patterns
## Common Development Commands
### Essential Commands (Project-Specific)
```bash
# Start development server with SSL (required for authentication flows)
npm start
# Run tests for all libraries (excludes main app)
npm test
# Build for development
npm run build
# Build for production
npm run build-prod
# Regenerate all API clients from Swagger/OpenAPI specs
npm run generate:swagger
# Regenerate library reference documentation
npm run docs:generate
# Format code with Prettier
npm run prettier
# Format only staged files (pre-commit hook)
npm run pretty-quick
# Run CI tests with coverage
npm run ci
```
### Standard Nx Commands
For complete command reference, see [Nx Documentation](https://nx.dev/reference/commands).
**Common patterns:**
```bash
# Test specific library (always use --skip-nx-cache)
npx nx test <project-name> --skip-nx-cache
# Lint a project
npx nx lint <project-name>
# Show project dependencies
npx nx graph
# Run tests for affected projects (CI/CD)
npx nx affected:test --skip-nx-cache
```
**Important:** Always use `--skip-nx-cache` flag when running tests to ensure fresh results.
## Testing Framework
> **Last Reviewed:** 2025-10-22
> **Status:** Migration in Progress (Jest → Vitest)
### Current Setup (Migration in Progress)
- **Jest**: 40 libraries (65.6% - legacy/existing code)
- **Vitest**: 21 libraries (34.4% - new standard)
- All formal libraries now have test executors configured
### Testing Strategy
- **New libraries**: Use Vitest + Angular Testing Utilities (TestBed, ComponentFixture)
- **Legacy libraries**: Continue with Jest + Spectator until migrated
- **Advanced mocking**: Use ng-mocks for complex scenarios
### Key Requirements
- Test files must end with `.spec.ts`
- Use AAA pattern (Arrange-Act-Assert)
- **Always include E2E attributes**: `data-what`, `data-which`, and dynamic `data-*` in HTML templates
- Mock external dependencies appropriately for your framework
**For detailed testing guidelines, framework comparison, and migration instructions, see [`docs/guidelines/testing.md`](docs/guidelines/testing.md).**
**References:**
- [Jest Documentation](https://jestjs.io/)
- [Vitest Documentation](https://vitest.dev/)
- [Angular Testing Guide](https://angular.io/guide/testing)
- [Spectator](https://ngneat.github.io/spectator/)
## State Management
- **NgRx Signals**: Primary state management with modern functional approach using `signalStore()`
- **Entity Management**: Uses `withEntities()` for normalized data storage
- **Session Persistence**: State persistence with `withStorage()` using SessionStorageProvider
- **Reactive Methods**: `rxMethod()` with `takeUntilKeydownEscape()` for user-cancellable operations
- **Custom RxJS Operators**: Specialized operators like `takeUntilAborted()`, `takeUntilKeydown()`
- **Error Handling**: `tapResponse()` for handling success/error states in stores
- **Lifecycle Hooks**: `withHooks()` for cleanup and initialization (e.g., orphaned entity cleanup)
- **Navigation State**: Use `@isa/core/navigation` for temporary navigation context (return URLs, wizard state) instead of query parameters
## Styling and Design System
- **Framework**: [Tailwind CSS](https://tailwindcss.com/docs) with extensive ISA-specific customization
- **Custom Breakpoints**: `isa-desktop` (1024px), `isa-desktop-l` (1440px), `isa-desktop-xl` (1920px)
- **Brand Color System**: `isa-*` color palette with semantic naming
- **Custom Tailwind Plugins** (7): button, typography, menu, label, input, section, select-bullet
- **Typography System**: 14 custom utilities (`.isa-text-heading-1-bold`, `.isa-text-body-2-regular`, etc.)
- **UI Component Libraries**: 17 specialized libraries with consistent APIs (see Library Reference)
- **Storybook**: Component documentation and development at `npm run storybook`
### Responsive Design with Breakpoint Service
Use `@isa/ui/layout` for reactive breakpoint detection instead of CSS-only solutions:
```typescript
import { breakpoint, Breakpoint } from '@isa/ui/layout';
// Detect screen size reactively
isDesktop = breakpoint([Breakpoint.Desktop, Breakpoint.DekstopL, Breakpoint.DekstopXL]);
```
**Available Breakpoints:**
- `Tablet`: max-width: 1279px (mobile/tablet)
- `Desktop`: 1280px - 1439px (standard desktop)
- `DekstopL`: 1440px - 1919px (large desktop)
- `DekstopXL`: 1920px+ (extra large)
**Template Usage:**
```html
@if (isDesktop) {
<!-- Desktop-specific content -->
}
```
**Why:** Prefer breakpoint service over CSS-only (hidden/flex) for SSR and maintainability.
## API Integration and Data Access
**Generated Swagger Clients:** 10 auto-generated TypeScript clients in `generated/swagger/`
- Available APIs: availability-api, cat-search-api, checkout-api, crm-api, eis-api, inventory-api, isa-api, oms-api, print-api, wws-api
- Tool: [ng-swagger-gen](https://www.npmjs.com/package/ng-swagger-gen) with custom per-API configuration
- Post-processing: Automatic Unicode cleanup via `tools/fix-files.js`
- Regenerate: `npm run generate:swagger`
**Architecture Pattern:**
- Business logic services wrap generated API clients
- Type safety: TypeScript + [Zod](https://zod.dev/) schema validation
- Error handling: Global HTTP interceptor with automatic re-authentication
- Modern injection: Uses `inject()` function with private field pattern
- Request cancellation: Built-in via AbortSignal and custom RxJS operators (`takeUntilAborted()`, `takeUntilKeydown()`)
**Data Access Libraries:** See Library Reference section for domain-specific implementations (`@isa/[domain]/data-access`).
## Build Configuration
- **Framework**: Angular with TypeScript (see `package.json` for current versions)
- **Requirements**:
- Node.js >= 22.0.0 (specified in package.json engines)
- npm >= 10.0.0 (specified in package.json engines)
- **Build System**: Nx monorepo with Vite for testing (Vitest)
- **Development Server**: Serves with SSL by default (required for authentication flows)
## Important Conventions and Patterns
### Library Organization
- **Naming Pattern**: `[domain]-[layer]-[feature]` (e.g., `oms-feature-return-search`, `ui-buttons`)
- **Path Aliases**: `@isa/[domain]/[layer]/[feature]` (e.g., `@isa/oms/data-access`, `@isa/ui/buttons`)
- **Project Names**: Found in each library's `project.json` file, following consistent naming
### Component Architecture
- **Standalone Components**: All new components must be standalone with explicit imports
- **Component Prefixes**: Domain-specific prefixes for clear identification
- OMS features: `oms-feature-*` (e.g., `oms-feature-return-search-main`)
- Remission features: `remi-*`
- UI components: `ui-*`
- Core utilities: `core-*`
- **Signal-based Inputs**: Use Angular signals (`input()`, `computed()`) for reactive properties
- **Host Binding**: Dynamic CSS classes via Angular host properties
### Dependency Rules
- **Unidirectional Dependencies**: Feature → Shared/UI → Data Access → Infrastructure
- **Import Boundaries**: Use path aliases, avoid relative imports across domain boundaries
- **Generated API Imports**: Import from `@generated/swagger/[api-name]` for API clients
### Code Quality
- **Modern Angular Patterns**: Prefer `inject()` over constructor injection
- **Type Safety**: Use Zod schemas for runtime validation alongside TypeScript
- **Error Handling**: Custom error classes with specific error codes
- **E2E Testing**: Always include `data-what` and `data-which` attributes in templates
## Development Workflow and Best Practices
### Project Conventions
- **Default Branch**: `develop` (not main) - Always create PRs against develop
- **Branch Naming**: When starting work on a new feature or bug, create a branch following this pattern:
- Format: `feature/{task-id}-{short-description}` or `bugfix/{task-id}-{short-description}`
- Use English kebab-case for the description
- Start with the task/issue ID (e.g., `5391`)
- Keep description concise - shorten if the full title is too long
- Example: For task "#5391 Prämie Checkout // Action Card - Versandbestellung"
- Branch: `feature/5391-praemie-checkout-action-card-delivery-order`
- **Commit Style**: [Conventional commits](https://www.conventionalcommits.org/) without co-author tags
- **Nx Cache**: Always use `--skip-nx-cache` for tests to ensure fresh results
- **Testing**: New libraries use Vitest + Angular Testing Utilities; legacy use Jest + Spectator
- **E2E Attributes**: Always include `data-what`, `data-which`, and dynamic `data-*` in templates
- **Design System**: Use ISA-specific Tailwind utilities (`isa-accent-*`, `isa-text-*`)
### Code Quality Tools
- **Linting**: [ESLint](https://eslint.org/) with Nx dependency checks
- **Formatting**: [Prettier](https://prettier.io/) with Husky + lint-staged pre-commit hooks
- **Type Safety**: [TypeScript](https://www.typescriptlang.org/) strict mode + [Zod](https://zod.dev/) validation
- **Bundle Size**: Monitor carefully (2MB warning, 5MB error for main bundle)
### Nx Workflow Tips
- Use `npx nx graph` to visualize dependencies
- Use `npx nx affected:test` for CI/CD optimization
- Reference: [Nx Documentation](https://nx.dev/getting-started/intro)
## Development Notes and Guidelines
### Getting Started
- **Application Startup**: Only `isa-app` can be started - it's the main application entry point
- **SSL Development**: The development server runs with SSL by default (`npm start`), which is crucial for production-like authentication flows
- **Node Requirements**: Ensure Node.js ≥22.0.0 and npm ≥10.0.0 before starting development
- **First-Time Setup**: After cloning, run `npm install` then `npm start` to verify everything works
### Essential Documentation References
- **Testing Guidelines**: Review `docs/guidelines/testing.md` before writing any tests - it covers the Jest→Vitest migration, Spectator→Angular Testing Utilities transition, and E2E attribute requirements
- **Code Review Standards**: Follow the structured review process in `.github/review-instructions.md` with categorized feedback (🚨 Critical, ❗ Minor, ⚠️ Warnings, ✅ Good Practices)
- **E2E Testing Requirements**: Always include `data-what`, `data-which`, and dynamic `data-*` attributes in HTML templates - these are essential for automated testing by QA colleagues
### Researching and Investigating the Codebase
## Researching and Investigating the Codebase
**🔴 MANDATORY: You MUST use subagents for research. Direct file reading/searching is FORBIDDEN except for single specific files.**
#### Required Agent Usage
### Required Agent Usage
| Task Type | Required Agent | Escalation Path |
|-----------|---------------|-----------------|
@@ -281,7 +38,7 @@ isDesktop = breakpoint([Breakpoint.Desktop, Breakpoint.DekstopL, Breakpoint.Deks
| **Implementation Analysis** | `Explore` | Multiple file analysis |
| **Single Specific File** | Read tool directly | No agent needed |
#### Documentation Research System (Two-Tier)
### Documentation Research System (Two-Tier)
1. **ALWAYS start with `docs-researcher`** (Haiku, 30-120s) for any documentation need
2. **Auto-escalate to `docs-researcher-advanced`** (Sonnet, 2-7min) when:
@@ -290,7 +47,7 @@ isDesktop = breakpoint([Breakpoint.Desktop, Breakpoint.DekstopL, Breakpoint.Deks
- Need code inference
- Complex architectural questions
#### Enforcement Examples
### Enforcement Examples
```
❌ WRONG: Read libs/ui/buttons/README.md
@@ -305,60 +62,35 @@ isDesktop = breakpoint([Breakpoint.Desktop, Breakpoint.DekstopL, Breakpoint.Deks
**Remember: Using subagents is NOT optional - it's mandatory for maintaining context efficiency and search quality.**
#### Common Research Patterns
## Project Knowledge Management with Context-Manager
| Information Need | Required Approach |
|-----------------|-------------------|
| **Library documentation** | `docs-researcher` → Check library-reference.md → Escalate if needed |
| **Code patterns/examples** | `Explore` with "medium" or "very thorough" |
| **Architecture understanding** | `npx nx graph` + `Explore` for implementation |
| **Debugging/errors** | Direct tool use (Read specific error file, check console) |
**NEW CAPABILITY**: The `context-manager` subagent has **persistent memory** that autonomously stores and retrieves project knowledge across sessions.
#### Debugging Tips
- **TypeScript errors**: Follow error path to exact file:line
- **Test failures**: Use `--skip-nx-cache` for fresh output
- **Module resolution**: Check `tsconfig.base.json` path aliases
- **State issues**: Use Angular DevTools browser extension
### What Gets Stored Automatically
### Library Development Patterns
- **Library Documentation**: Use `docs-researcher` for ALL library READMEs (mandatory for context management)
- **New Library Creation**: Use Nx generators with domain-specific naming (`[domain]-[layer]-[feature]`)
- **Standalone Components**: All new components must be standalone with explicit imports - no NgModules
- **Testing Framework**: New = Vitest + Angular Testing Utilities, Legacy = Jest + Spectator
- **Path Aliases**: Always use `@isa/[domain]/[layer]/[feature]` - avoid relative imports
- **Assigned Tasks**: User-assigned tasks with context ("Remember to look up X because of Y"), TODO items, status tracking
- **Architectural Decisions**: State management patterns, API integration approaches, component architecture choices
- **Reusable Patterns**: Code conventions, testing patterns, error handling approaches
- **Integration Points**: API contracts, data flows, module boundaries
- **Domain Knowledge**: Business workflows, business rules, user roles/permissions
- **Technical Solutions**: Bug fixes with root causes, performance optimizations
#### Library Reference Guide
### When to Use Context-Manager
The monorepo contains **62 libraries** organized across 12 domains. For quick lookup, see **[`docs/library-reference.md`](docs/library-reference.md)**.
Use the `context-manager` subagent PROACTIVELY for:
- **Task Management**: Assigning tasks for later ("Remember to investigate X because of Y")
- **Session Continuity**: Starting a new session (it will remind you of pending tasks)
- Complex, multi-step projects requiring coordination
- Long-running tasks that span multiple sessions
- Preserving architectural context
- Learning about resolved issues and their solutions
**Quick Overview by Domain:**
- Availability (1) | Catalogue (1) | Checkout (6) | Common (3) | Core (5) | CRM (1) | Icons (1)
- OMS (9) | Remission (8) | Shared Components (7) | UI Components (17) | Utilities (3)
### How It Works
### API Integration Workflow
- **Swagger Generation**: Run `npm run generate:swagger` to regenerate all 10 API clients when backend changes
- **Data Services**: Wrap generated API clients in domain-specific data-access services with proper error handling and Zod validation
- **State Management**: Use NgRx Signals with `signalStore()`, entity management, and session persistence for complex state
1. **Task Capture**: Listens for "Remember to...", "TODO:", "Don't forget...", stores them with full context
2. **Automatic Storage**: Proactively stores important discoveries in persistent memory
3. **Knowledge Retrieval**: Queries stored knowledge before starting new work
4. **Task Reminders**: Proactively reminds you of pending/incomplete tasks at session start
5. **Cross-Session Persistence**: Information persists across Claude Code sessions
### Performance and Quality Considerations
- **Bundle Monitoring**: Watch bundle sizes (2MB warning, 5MB error for main bundle)
- **Testing Cache**: Always use `--skip-nx-cache` flag when running tests to ensure reliable results
- **Code Quality**: Pre-commit hooks enforce Prettier formatting and ESLint rules automatically
- **Memory Management**: Clean up subscriptions and use OnPush change detection for optimal performance
### Common Troubleshooting
- **Build Issues**: Check Node version and run `npm install` if encountering module resolution errors
- **Test Failures**: Use `--skip-nx-cache` flag and ensure test isolation (no shared state between tests)
- **Nx Cache Issues**: If you see `existing outputs match the cache, left as is` during build or testing:
- **Option 1**: Run `npx nx reset` to clear the Nx cache completely
- **Option 2**: Use `--skip-nx-cache` flag to bypass Nx cache for a specific command (e.g., `npx nx test <project> --skip-nx-cache`)
- **When to use**: Always use `--skip-nx-cache` when you need guaranteed fresh builds or test results
- **SSL Certificates**: Development server uses SSL - accept certificate warnings in browser for localhost
- **Import Errors**: Verify path aliases in `tsconfig.base.json` and use absolute imports for cross-library dependencies
### Domain-Specific Conventions
- **Component Prefixes**: Use `oms-feature-*` for OMS, `remi-*` for remission, `ui-*` for shared components
- **Git Workflow**: Default branch is `develop` (not main), use conventional commits without co-author tags
- **Design System**: Use ISA-specific Tailwind utilities (`isa-accent-*`, `isa-text-*`) and custom breakpoints (`isa-desktop-*`)
- **Logging**: Use centralized logging service (`@isa/core/logging`) with contextual information for debugging
- **Navigation State**: Use `@isa/core/navigation` for passing temporary state between routes (return URLs, form context) instead of query parameters - keeps URLs clean and state reliable
**Benefits**: Eliminates context loss, maintains project knowledge, provides task continuity across sessions.

287
docs/ARCHITECTURE.md Normal file
View File

@@ -0,0 +1,287 @@
# ISA-Frontend Architecture Documentation
Complete architectural analysis of the ISA-Frontend monorepo with C4 models, dependency analysis, and implementation patterns.
## Documentation Files
### 1. **Architecture Analysis** (`architecture-analysis.md`) - 51 KB
Comprehensive architectural overview including:
- Complete project structure analysis
- All 63 libraries organized by domain
- Strict layered dependency model
- Technology stack (Angular 20.3.6, Nx 21.3.2, etc.)
- 6 primary domains (OMS, Remission, Checkout, Catalogue, Availability, CRM)
- Core infrastructure (5 libs), UI components (17 libs), shared components (7 libs)
- Modern architecture patterns (standalone components, NgRx Signals, responsive design)
- Complete C4 Model visualization (Levels 1-4)
- State management patterns with code examples
- Component architecture and dependency enforcement
### 2. **Dependency Hierarchy** (`dependency-hierarchy.md`) - 13 KB
Visual dependency organization:
- Layer-based dependency model (4 levels)
- Complete OMS domain dependency tree
- Remission domain dependency tree
- Checkout domain dependency tree
- Cross-domain dependency matrix
- Import path conventions and examples
- NO circular dependencies guarantee
- Bundle dependency impact analysis
- Development workflow for adding features
- Performance considerations (lazy loading, tree shaking)
- Quick reference lookup table
### 3. **Quick Reference** (`architecture-quick-reference.md`) - 15 KB
Developer quick reference guide:
- Project overview at a glance
- Domain summary with key libraries
- Architecture layers visualization
- State management pattern example
- Component structure template
- Common development patterns (search, dialogs, forms, responsive design)
- Essential command cheatsheet
- File organization by domain
- TypeScript path alias mapping
- Design system utilities (Tailwind ISA-specific)
- Testing approach (Vitest vs Jest)
- Troubleshooting guide
- Performance budgets
- Monorepo statistics
---
## Quick Navigation
### For Architecture Understanding
Start with **architecture-analysis.md** → C4 Model section
- Understand the 6 primary domains
- Learn the 4-layer dependency model
- See how all 63 libraries fit together
### For Dependency Details
Read **dependency-hierarchy.md** for:
- How libraries depend on each other
- Where to import from (path aliases)
- Why circular dependencies are prevented
- How to add new features without breaking the graph
### For Hands-On Development
Use **architecture-quick-reference.md** for:
- Quick lookup of library purposes
- Code patterns and examples
- Common commands
- File locations and conventions
- Troubleshooting tips
---
## Project Structure Overview
```
ISA-Frontend (Angular 20.3.6 Monorepo)
├── 63 Libraries organized by domain
│ ├── 6 Primary Domains (OMS, Remission, Checkout, Catalogue, Availability, CRM)
│ ├── 17 UI Component Libraries
│ ├── 7 Shared Component Libraries
│ ├── 5 Core Infrastructure Libraries
│ ├── 3 Common Utility Libraries
│ ├── 3 General Utility Libraries
│ ├── 1 Icon Library
│ └── 10 Auto-generated Swagger API Clients
├── 1 Main Application (isa-app)
└── Strict Layered Architecture (Feature → Shared → Data Access → Infrastructure)
```
---
## Key Architecture Principles
### 1. Domain-Driven Design
- 6 distinct business domains (OMS, Remission, Checkout, etc.)
- Each domain has data-access, feature, and shared components
- Clear domain boundaries prevent unnecessary coupling
### 2. Strict Layering
- **Feature Layer**: Route components, user interaction
- **Shared Layer**: Reusable UI and domain-specific components
- **Data Access Layer**: NgRx Signals stores and API services
- **Infrastructure Layer**: Core, common, and generated APIs
### 3. No Circular Dependencies
- Enforced by TypeScript path aliases
- Verified by ESLint nx plugin
- Enables scalability and maintainability
### 4. Modern Angular Patterns
- **Standalone Components**: All new components (no NgModule)
- **Signal-based State**: NgRx Signals with functional composition
- **Type Safety**: TypeScript strict mode + Zod validation
- **Responsive Design**: Breakpoint service instead of CSS media queries
---
## Statistics
| Metric | Count |
|--------|-------|
| Total Libraries | 63 |
| Primary Domains | 6 |
| UI Components | 17 |
| Feature Components | 20 |
| Data Access Stores | 6 |
| Core Infrastructure | 5 |
| Shared Components | 7 |
| Common Utilities | 3 |
| General Utilities | 3 |
| Generated APIs | 10 |
| Lines of Documentation | 2,165+ |
---
## Technology Stack
- **Framework**: Angular 20.3.6
- **Build Tool**: Nx 21.3.2
- **Language**: TypeScript 5.8.3
- **State Management**: NgRx Signals 20.0.0
- **Styling**: Tailwind CSS 3.4.14 + 7 custom plugins
- **Testing**: Jest (legacy) + Vitest (modern)
- **HTTP Client**: HttpClient 20.3.6
- **Validation**: Zod 3.24.2
- **API Generation**: ng-swagger-gen 2.3.1
- **Authentication**: OAuth2/OIDC via angular-oauth2-oidc
---
## Development Quick Start
```bash
# Install and start
npm install
npm start # Runs on https://localhost:4200
# Testing
npm test # All libraries
npx nx test [project] --skip-nx-cache # Specific library (fresh results)
# Building
npm run build # Development
npm run build-prod # Production
# Regenerate APIs
npm run generate:swagger # From OpenAPI specs
npm run fix:files:swagger # Unicode cleanup
# Analysis
npx nx graph # Visualize dependencies
npx nx show project [project] # Show project details
```
---
## Common Patterns
### Injecting and Using a Store
```typescript
export class MyComponent {
protected store = inject(omsStore);
onSearch(term: string) {
this.store.searchReceipts(term);
}
}
```
### Creating a New Feature
1. Create standalone component in `[domain]/feature/[feature-name]`
2. Import from data-access, shared, and UI libraries via path aliases
3. Inject store directly (don't inject individual services)
4. Use reactive template syntax (@if, @for, @switch)
### Adding E2E Attributes
```html
<button
data-what="submit"
data-which="primary-action"
[attr.data-order-id]="orderId"
>
Submit
</button>
```
---
## Architecture Decisions
### Why NgRx Signals?
- Modern, functional composition
- Signals for reactive properties
- Entity management for normalized state
- Auto-persistence with withStorage()
- Request cancellation support
### Why Standalone Components?
- No NgModule boilerplate
- Explicit dependencies (in imports)
- Tree-shakeable code
- Easier testing
### Why Path Aliases?
- Prevent relative imports across domains
- Enforce architectural boundaries
- Clear import intent (@isa/domain/layer/feature)
- Enable refactoring safety
### Why Strict Layering?
- Prevent circular dependencies
- Enable parallel development
- Facilitate testing
- Support scalability
---
## Getting Help
1. **Library Documentation**: Check `/libs/[domain]/[layer]/[feature]/README.md`
2. **Architecture Details**: See the appropriate documentation file above
3. **Code Examples**: Look for similar implementations in the codebase
4. **Nx Visualization**: Run `npx nx graph` to see dependency graph
5. **Project Configuration**: Review `nx.json` and `tsconfig.base.json`
---
## Related Documentation
- **Library Reference**: See `/docs/library-reference.md` for all 63 libraries
- **Testing Guidelines**: See `/docs/guidelines/testing.md` for testing patterns
- **Code Review Standards**: See `/.github/review-instructions.md` for review process
- **CLAUDE.md**: Project-specific conventions and best practices
---
## Maintenance
These documentation files are maintained manually. When:
- Adding new libraries: Update library reference and domain counts
- Changing architecture patterns: Update quick reference and analysis
- Adding new domains: Document domain structure and dependencies
- Migrating frameworks: Update testing approach sections
---
## Document Generation
To regenerate library reference:
```bash
npm run docs:generate
```
This updates `/docs/library-reference.md` automatically.
---
**Last Updated**: 2025-10-29
**Angular Version**: 20.3.6
**Nx Version**: 21.3.2
**Documentation Format**: Markdown (3 comprehensive files)

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,587 @@
# ISA-Frontend Architecture: Quick Reference Guide
## Project Overview at a Glance
| Aspect | Details |
|--------|---------|
| **Project Type** | Angular 20.3.6 Monorepo (Domain-Driven Design) |
| **Build Tool** | Nx 21.3.2 |
| **Total Libraries** | 63 (organized by domain + infrastructure) |
| **Main Application** | `isa-app` (only runnable app) |
| **Domains** | OMS, Remission, Checkout, Catalogue, Availability, CRM |
| **UI Components** | 17 specialized design system libraries |
| **Testing** | Jest (legacy) + Vitest (modern) - migration in progress |
| **State Management** | NgRx Signals with entity normalization |
| **API Clients** | 10 auto-generated from Swagger/OpenAPI specs |
| **Styling** | Tailwind CSS + 7 custom plugins |
| **Authentication** | OAuth2/OIDC via `angular-oauth2-oidc` |
| **Barcode Support** | Scandit Web Datacapture |
| **Analytics** | Matomo integration |
---
## Domain Summary
### 1. Order Management System (OMS) - 9 Libraries
**Focus:** Return workflows and receipt management
| Library | Purpose |
|---------|---------|
| `oms-data-access` | State + API integration |
| `oms-feature-return-search` | Receipt search interface |
| `oms-feature-return-details` | Item selection & configuration |
| `oms-feature-return-process` | Dynamic return questions |
| `oms-feature-return-summary` | Confirmation & printing |
| `oms-feature-return-review` | Completion review |
| `oms-shared-product-info` | Product display |
| `oms-shared-task-list` | Task management UI |
| `oms-utils-translation` | Receipt type labels |
**Key APIs:** oms-api, isa-api, print-api
---
### 2. Remission (Returns Management) - 8 Libraries
**Focus:** Warehouse return processing (mandatory + department)
| Library | Purpose |
|---------|---------|
| `remission-data-access` | State + API integration |
| `remission-feature-remission-list` | Main list view |
| `remission-feature-remission-return-receipt-list` | Receipt list |
| `remission-feature-remission-return-receipt-details` | Receipt details |
| `remission-shared-product` | Product components |
| `remission-shared-remission-start-dialog` | Start workflow |
| `remission-shared-return-receipt-actions` | Action buttons |
| `remission-shared-search-item-to-remit-dialog` | Item search |
**Key APIs:** Remission-specific via ISA backend
---
### 3. Checkout & Rewards - 6 Libraries
**Focus:** Shopping cart, orders, loyalty rewards
| Library | Purpose |
|---------|---------|
| `checkout-data-access` | Cart state + API |
| `checkout-feature-reward-catalog` | Reward browsing |
| `checkout-feature-reward-shopping-cart` | Cart with rewards |
| `checkout-feature-reward-order-confirmation` | Order confirmation |
| `checkout-shared-product-info` | Product display |
| `checkout-shared-reward-selection-dialog` | Reward selection |
**Key APIs:** checkout-api, crm-api (bonus cards)
---
### 4. Catalogue - 1 Library
**Focus:** Product search and discovery
| Library | Purpose |
|---------|---------|
| `catalogue-data-access` | Search + filtering |
**Key APIs:** cat-search-api, availability-api
---
### 5. Availability - 1 Library
**Focus:** Product stock checking
| Library | Purpose |
|---------|---------|
| `availability-data-access` | Stock queries |
**Key APIs:** availability-api
---
### 6. CRM - 1 Library
**Focus:** Customer data and bonus cards
| Library | Purpose |
|---------|---------|
| `crm-data-access` | Customer + bonus card state |
**Key APIs:** crm-api
---
## Architecture Layers
```
┌─────────────────────────────────┐
│ FEATURE LAYER (User-Facing) │
│ - Components with routes │
│ - User interactions │
│ - Navigation handlers │
└──────────────┬──────────────────┘
│ imports
┌──────────────▼──────────────────┐
│ SHARED LAYER (Reusable) │
│ - UI components (17 libs) │
│ - Shared components (7 libs) │
│ - Domain shared │
└──────────────┬──────────────────┘
│ imports
┌──────────────▼──────────────────┐
│ DATA ACCESS LAYER (State) │
│ - NgRx Signal Stores │
│ - API Services │
│ - Entity management │
└──────────────┬──────────────────┘
│ imports
┌──────────────▼──────────────────┐
│ INFRASTRUCTURE (Foundation) │
│ - Core libraries (5) │
│ - Common utilities (3) │
│ - Generated APIs (10) │
│ - Utilities (3) │
└─────────────────────────────────┘
```
---
## State Management Pattern
### NgRx Signals Store Structure
```typescript
export const orderStore = signalStore(
// 1. State definition
withState({
orders: [] as Order[],
selected: null as Order | null,
loading: false,
error: null as Error | null,
}),
// 2. Entity management (auto-normalization)
withEntities({ entity: type<Order>() }),
// 3. Computed values
withComputed((store) => ({
orderCount: computed(() => store.orders().length),
hasSelected: computed(() => store.selected() !== null),
})),
// 4. Methods for state mutations
withMethods((store, api = inject(OmsApiService)) => ({
load: rxMethod<void>(
pipe(
tapResponse(
(orders) => patchState(store, setAllEntities(orders)),
(error) => handleError(error)
)
)
),
select: (order: Order) => {
patchState(store, { selected: order });
},
})),
// 5. Auto persistence
withStorage({ key: 'orders' }),
// 6. Cleanup hooks
withHooks({
onInit: ({ load }) => load(),
onDestroy: () => console.log('Store destroyed'),
})
);
```
**Key Features:**
- Signals: Reactive properties
- Entity management: Auto-normalized state
- Methods: Encapsulated mutations
- Storage: Automatic persistence
- Hooks: Lifecycle management
---
## Component Structure
### Standalone Component Example
```typescript
@Component({
selector: 'oms-return-search',
standalone: true,
imports: [
CommonModule,
ReactiveFormsModule,
// Shared components
UiSearchBar,
UiButton,
OmsProductInfo,
UiEmptyState,
],
template: `
<div class="container">
<ui-search-bar (search)="onSearch($event)" />
@if (store.receipts(); as receipts) {
@if (receipts.length > 0) {
<oms-product-info
*ngFor="let receipt of receipts"
[receipt]="receipt"
/>
} @else {
<ui-empty-state title="Keine Belege" />
}
} @loading {
<ui-skeleton-loader />
}
</div>
`,
styles: [`...`],
})
export class OmsReturnSearchComponent {
protected store = inject(omsStore);
private api = inject(OmsApiService);
onSearch(term: string) {
this.store.searchReceipts(term);
}
}
```
**Best Practices:**
- ✅ Standalone components only
- ✅ Explicit imports
- ✅ Inject store, not services
- ✅ Use store methods directly
- ✅ Let control flow (@if, @for)
---
## Common Patterns
### 1. Search with Debouncing
```typescript
export class SearchComponent {
private searchTerm$ = new Subject<string>();
results$ = this.searchTerm$.pipe(
debounceTime(300),
distinctUntilChanged(),
switchMap((term) => this.api.search(term)),
takeUntilKeydown('Escape')
);
onSearch(term: string) {
this.searchTerm$.next(term);
}
}
```
### 2. Modal/Dialog Handling
```typescript
export class DialogComponent {
private dialog = inject(DialogService);
openRewardSelection() {
this.dialog.open(RewardSelectionDialog, {
data: { cart: this.cart },
}).afterClosed$.subscribe((reward) => {
if (reward) {
this.store.selectReward(reward);
}
});
}
}
```
### 3. Form Validation
```typescript
export class ReturnProcessComponent {
form = new FormGroup({
reason: new FormControl('', [Validators.required]),
quantity: new FormControl(1, [Validators.min(1)]),
comments: new FormControl(''),
});
submit() {
if (this.form.valid) {
this.store.submitReturn(this.form.value);
}
}
}
```
### 4. Responsive Design
```typescript
export class ResponsiveComponent {
// Use breakpoint service instead of CSS-only
isDesktop = breakpoint([
Breakpoint.Desktop,
Breakpoint.DesktopL,
Breakpoint.DesktopXL,
]);
template = `
@if (isDesktop()) {
<desktop-layout />
} @else {
<mobile-layout />
}
`;
}
```
---
## Common Commands
### Development
```bash
npm start # Start with SSL
npm test # Test all libraries
npm run build # Dev build
npm run build-prod # Production build
```
### Testing
```bash
npx nx test oms-data-access --skip-nx-cache
npx nx affected:test --skip-nx-cache
npm run ci # CI with coverage
```
### Code Quality
```bash
npm run lint # ESLint
npm run prettier # Format code
npm run docs:generate # Update library ref
```
### API & Swagger
```bash
npm run generate:swagger # Regenerate all APIs
npm run fix:files:swagger # Unicode cleanup
```
### Dependency Analysis
```bash
npx nx graph # Visual dependency graph
npx nx show project oms-data-access --web false
npx nx affected:lint --skip-nx-cache
```
---
## File Organization by Domain
### OMS Domain Structure
```
libs/oms/
├── data-access/
│ └── src/
│ ├── index.ts
│ ├── stores/
│ │ ├── receipt.store.ts
│ │ └── return.store.ts
│ └── services/
│ ├── oms-api.service.ts
│ └── print.service.ts
├── feature/
│ ├── return-search/
│ ├── return-details/
│ ├── return-process/
│ ├── return-summary/
│ └── return-review/
├── shared/
│ ├── product-info/
│ └── task-list/
└── utils/
└── translation/
```
### UI Component Structure
```
libs/ui/buttons/
├── src/
│ ├── index.ts
│ ├── primary-button.component.ts
│ ├── secondary-button.component.ts
│ ├── ...
│ └── buttons.module.ts
├── README.md
├── project.json
└── ...
```
---
## TypeScript Path Aliases
```json
{
"paths": {
// Domain data-access
"@isa/oms/data-access": ["libs/oms/data-access/src/index.ts"],
"@isa/remission/data-access": ["libs/remission/data-access/src/index.ts"],
// UI components
"@isa/ui/buttons": ["libs/ui/buttons/src/index.ts"],
"@isa/ui/dialog": ["libs/ui/dialog/src/index.ts"],
// Core infrastructure
"@isa/core/logging": ["libs/core/logging/src/index.ts"],
"@isa/core/storage": ["libs/core/storage/src/index.ts"],
// Generated APIs
"@generated/swagger/oms-api": ["generated/swagger/oms-api/src/index.ts"]
}
}
```
---
## Styling & Design System
### Tailwind Utilities (ISA-Specific)
```html
<!-- Brand Colors -->
<div class="text-isa-accent-primary">Primary text</div>
<button class="bg-isa-accent-primary">Primary button</button>
<!-- Typography -->
<h1 class="isa-text-heading-1-bold">Large heading</h1>
<p class="isa-text-body-2-regular">Body text</p>
<!-- Custom Breakpoints -->
<div class="hidden isa-desktop:block">Desktop only</div>
<div class="block isa-desktop:hidden">Mobile only</div>
<!-- Custom Plugins -->
<button class="isa-button-primary">ISA Button</button>
<div class="isa-input-group">...</div>
```
### Custom Tailwind Plugins
1. button - Button styling
2. typography - Text utilities
3. menu - Menu styling
4. label - Label & tag styling
5. input - Input styling
6. section - Section containers
7. select-bullet - Select styling
---
## Testing Approach
### New Libraries (Vitest + Angular Testing Utils)
```typescript
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { OmsReturnSearchComponent } from './oms-return-search.component';
describe('OmsReturnSearchComponent', () => {
let component: OmsReturnSearchComponent;
let fixture: ComponentFixture<OmsReturnSearchComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [OmsReturnSearchComponent],
}).compileComponents();
fixture = TestBed.createComponent(OmsReturnSearchComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
```
### E2E Attributes
All templates must include data attributes:
```html
<button
data-what="submit-return"
data-which="primary-action"
[attr.data-order-id]="orderId"
>
Submit Return
</button>
```
---
## Troubleshooting
| Issue | Solution |
|-------|----------|
| **Build cache stale** | `npx nx reset` or `--skip-nx-cache` |
| **Test failures** | Always use `--skip-nx-cache` |
| **Import not found** | Check `tsconfig.base.json` path alias |
| **Circular dependency** | Run `npx nx lint` to identify |
| **SSL certificate error** | Accept localhost certificate in browser |
| **State not persisting** | Check `withStorage()` in store |
| **API 401 Unauthorized** | Verify OAuth2 token in auth service |
---
## Quick Links
- **Library Reference:** `/docs/library-reference.md`
- **Architecture Analysis:** `/docs/architecture-analysis.md`
- **Dependency Hierarchy:** `/docs/dependency-hierarchy.md`
- **Testing Guidelines:** `/docs/guidelines/testing.md`
- **Nx Documentation:** https://nx.dev/
- **Angular Documentation:** https://angular.io/
- **NgRx Signals:** https://ngrx.io/guide/signals
---
## Getting Help
1. Check library README: `libs/[domain]/[layer]/[feature]/README.md`
2. Review existing examples in similar domains
3. Check `npx nx show project [project-name]`
4. Read CLAUDE.md for project-specific conventions
5. Review git history: `git log --oneline libs/[domain]`
---
## Performance Budgets
- **Main bundle:** 2MB warning, 5MB error (gzipped)
- **Initial load:** < 2s on 4G
- **Core (after auth):** < 5s
**Bundle Analysis:**
```bash
npx nx build isa-app --configuration=production --stats-json
webpack-bundle-analyzer dist/isa-app/browser/stats.json
```
---
## Monorepo Statistics
| Metric | Count |
|--------|-------|
| Total Libraries | 63 |
| Feature Components | 20 |
| UI Components | 17 |
| Data Access | 6 |
| Core Infrastructure | 5 |
| Shared Components | 7 |
| Utilities | 3 |
| Generated APIs | 10 |
| Lines of Code | ~500K+ |
| TypeScript Files | ~1,500 |
| Test Files | ~400 |
| Generated Test Coverage | Vitest: 34%, Jest: 65% |

View File

@@ -0,0 +1,458 @@
# ISA-Frontend: Dependency Hierarchy Diagram
## 1. Layer-Based Dependency Model
```
Level 4: Feature Components (Entry Points)
├── oms-feature-return-search
├── oms-feature-return-details
├── oms-feature-return-process
├── oms-feature-return-summary
├── oms-feature-return-review
├── remission-feature-remission-list
├── remission-feature-remission-return-receipt-list
├── remission-feature-remission-return-receipt-details
├── checkout-feature-reward-catalog
├── checkout-feature-reward-shopping-cart
└── checkout-feature-reward-order-confirmation
Level 3: Shared & UI Components
├── OMS Shared
│ ├── oms-shared-product-info
│ └── oms-shared-task-list
├── Remission Shared
│ ├── remission-shared-product
│ ├── remission-shared-remission-start-dialog
│ ├── remission-shared-return-receipt-actions
│ └── remission-shared-search-item-to-remit-dialog
├── Checkout Shared
│ ├── checkout-shared-product-info
│ └── checkout-shared-reward-selection-dialog
└── UI Component Library (17)
├── ui-buttons
├── ui-input-controls
├── ui-dialog
├── ui-datepicker
├── ui-layout
├── ui-menu
├── ui-toolbar
├── ui-search-bar
├── ui-expandable
├── ui-empty-state
├── ui-skeleton-loader
├── ui-carousel
├── ui-item-rows
├── ui-progress-bar
├── ui-tooltip
├── ui-label
└── ui-bullet-list
Level 2: Data Access Layer
├── oms-data-access
├── remission-data-access
├── checkout-data-access
├── catalogue-data-access
├── availability-data-access
└── crm-data-access
Level 1: Infrastructure & Core
├── Core Libraries (5)
│ ├── core-config
│ ├── core-logging
│ ├── core-navigation
│ ├── core-storage
│ └── core-tabs
├── Common Utilities (3)
│ ├── common-data-access
│ ├── common-decorators
│ └── common-print
├── Shared Components (7)
│ ├── shared-address
│ ├── shared-filter
│ ├── shared-product-image
│ ├── shared-product-format
│ ├── shared-product-router-link
│ ├── shared-quantity-control
│ └── shared-scanner
├── Generated APIs (10)
│ ├── @generated/swagger/oms-api
│ ├── @generated/swagger/checkout-api
│ ├── @generated/swagger/crm-api
│ ├── @generated/swagger/cat-search-api
│ ├── @generated/swagger/availability-api
│ ├── @generated/swagger/isa-api
│ ├── @generated/swagger/eis-api
│ ├── @generated/swagger/inventory-api
│ ├── @generated/swagger/print-api
│ └── @generated/swagger/wws-api
└── Utilities (3)
├── utils-ean-validation
├── utils-scroll-position
└── utils-z-safe-parse
```
---
## 2. OMS Domain Dependency Tree
```
oms-feature-return-search
├── oms-data-access
│ ├── @generated/swagger/oms-api
│ ├── @generated/swagger/print-api
│ ├── @isa/core/logging
│ └── @isa/common/data-access
├── oms-shared-product-info
│ ├── shared-product-image
│ ├── shared-product-format
│ ├── ui-item-rows
│ └── ui-label
└── ui-* (search-bar, buttons, empty-state, etc.)
oms-feature-return-details
├── oms-data-access (store)
├── oms-shared-product-info
├── ui-input-controls (quantity selector)
├── ui-buttons
└── shared-quantity-control
oms-feature-return-process
├── oms-data-access (update store)
├── ui-input-controls (forms)
├── ui-buttons
└── common-data-access (validation)
oms-feature-return-summary
├── oms-data-access (confirmation)
├── oms-shared-product-info
├── oms-shared-task-list
├── common-print (printing)
└── ui-buttons
oms-feature-return-review
├── oms-data-access (state)
├── oms-shared-product-info
├── common-print (reprint)
└── ui-empty-state
```
---
## 3. Remission Domain Dependency Tree
```
remission-feature-remission-list
├── remission-data-access
│ ├── @generated/swagger/remission-api
│ ├── @isa/core/logging
│ └── @isa/common/data-access
├── remission-shared-remission-start-dialog
├── ui-dialog
├── ui-buttons
└── shared-filter
remission-feature-remission-return-receipt-list
├── remission-data-access
├── remission-shared-search-item-to-remit-dialog
├── remission-shared-return-receipt-actions
├── ui-buttons
└── ui-empty-state
remission-feature-remission-return-receipt-details
├── remission-data-access
├── remission-shared-product
│ ├── shared-product-image
│ ├── shared-product-format
│ └── ui-item-rows
├── remission-shared-return-receipt-actions
├── ui-expandable
└── ui-buttons
```
---
## 4. Checkout Domain Dependency Tree
```
checkout-feature-reward-shopping-cart
├── checkout-data-access
│ ├── @generated/swagger/checkout-api
│ ├── @generated/swagger/crm-api
│ ├── @isa/core/logging
│ └── @isa/common/data-access
├── checkout-shared-product-info
│ ├── shared-product-image
│ └── ui-item-rows
├── checkout-shared-reward-selection-dialog
├── shared-quantity-control
├── ui-buttons
└── ui-empty-state
checkout-feature-reward-catalog
├── checkout-data-access
├── checkout-shared-product-info
├── shared-product-image
├── ui-buttons
├── ui-carousel
└── ui-skeleton-loader
checkout-feature-reward-order-confirmation
├── checkout-data-access
├── checkout-shared-product-info
├── ui-buttons
└── shared-address
```
---
## 5. Complete Cross-Domain Dependency Matrix
```
Domain → Depends On
────────────────────────────────
OMS Features → oms-data-access, oms-shared-*, ui-*, shared-*
OMS Data Access → @generated/swagger/*, core-*, common-*
Remission Features → remission-data-access, remission-shared-*, ui-*, shared-*
Remission D.A. → @generated/swagger/*, core-*, common-*
Checkout Features → checkout-data-access, checkout-shared-*, ui-*, shared-*
Checkout D.A. → @generated/swagger/*, core-*, common-*
Catalogue D.A. → @generated/swagger/*, core-*, common-*
Availability D.A. → @generated/swagger/*, core-*, common-*
CRM D.A. → @generated/swagger/crm-api, core-*, common-*
UI Components → core-config, common-*, no data-access deps
Shared Components → core-*, ui-*, no data-access deps
Core Libraries → No monorepo dependencies
Common Libraries → core-*, no domain deps
Generated APIs → External (backend)
Utilities → core-config, no domain deps
```
---
## 6. Import Path Conventions
All imports follow strict path aliases:
```typescript
// Domain-specific data-access
import { OrderStore, orderStore } from '@isa/oms/data-access';
import { ReturnStore, returnStore } from '@isa/remission/data-access';
import { CartStore, cartStore } from '@isa/checkout/data-access';
// Domain-specific shared components
import { OmsProductInfo } from '@isa/oms/shared/product-info';
import { RemissionProduct } from '@isa/remission/shared/product';
import { CheckoutProductInfo } from '@isa/checkout/shared/product-info';
// UI component library
import { UiButton, UiPrimaryButton } from '@isa/ui/buttons';
import { UiDialog } from '@isa/ui/dialog';
import { UiEmptyState } from '@isa/ui/empty-state';
// Shared components
import { SharedAddress } from '@isa/shared/address';
import { SharedFilter } from '@isa/shared/filter';
import { SharedProductImage } from '@isa/shared/product-image';
// Core infrastructure
import { Config } from '@isa/core/config';
import { logger } from '@isa/core/logging';
import { navigationState } from '@isa/core/navigation';
import { storageProvider } from '@isa/core/storage';
import { tabManager } from '@isa/core/tabs';
// Common utilities
import { tapResponse } from '@isa/common/data-access';
import { Cached, Debounce } from '@isa/common/decorators';
import { PrintService } from '@isa/common/print';
// General utilities
import { validateEan } from '@isa/utils/ean-validation';
import { restoreScrollPosition } from '@isa/utils/scroll-position';
import { safeParse } from '@isa/utils/z-safe-parse';
// Generated Swagger APIs
import { OmsApiClient } from '@generated/swagger/oms-api';
import { CheckoutApiClient } from '@generated/swagger/checkout-api';
import { CrmApiClient } from '@generated/swagger/crm-api';
```
---
## 7. NO Circular Dependencies
The architecture enforces strict acyclic dependencies:
```
Feature Layer (Level 4)
↓ (one-way only)
Shared/UI Layer (Level 3)
↓ (one-way only)
Data Access Layer (Level 2)
↓ (one-way only)
Infrastructure Layer (Level 1)
↓ (one-way only)
External APIs & Services (Backend)
```
**Verification Command:**
```bash
npx nx affected:lint --skip-nx-cache
```
---
## 8. Bundle Dependency Impact
### Smallest Dependencies (Infrastructure)
- `core-config` (~2KB)
- `core-logging` (~5KB)
- `utils-ean-validation` (~3KB)
### Medium Dependencies (Shared)
- `shared-product-image` (~8KB)
- `ui-buttons` (~12KB)
- `ui-input-controls` (~20KB)
### Larger Dependencies (Domain)
- `oms-data-access` (~25KB including API client)
- `checkout-data-access` (~30KB including API client)
- `remission-data-access` (~20KB including API client)
### Impact on Main Bundle
- All 63 libraries + isa-app = ~2MB (production gzipped)
- Tree-shaking removes unused code
- Lazy-loaded routes reduce initial load
---
## 9. Development Workflow
### Adding a New Feature
```
1. Create feature component
→ Depends on shared components
2. Create shared component (if needed)
→ Depends on UI & core libraries
3. Update data-access if needed
→ Depends on generated APIs & common
4. Import via path aliases
import { NewFeature } from '@isa/domain/feature/new-feature'
5. Verify no circular deps
npx nx affected:lint
```
### Dependency Investigation
```bash
# Show all dependencies of a library
npx nx show project oms-feature-return-search --web false
# Visualize dependency graph
npx nx graph --filter=oms-data-access
# Check for circular dependencies
npx nx lint
# View detailed dependency tree
npx nx show project oms-data-access --web false
```
---
## 10. Performance Considerations
### Lazy Loading
- Each feature module can be lazy-loaded via routing
- Reduces initial bundle size
- Loads on demand
### Tree Shaking
- Unused exports automatically removed
- All libraries use ES6 modules
- Named exports encouraged
### Code Splitting
- Generated APIs included only when imported
- UI components tree-shakeable
- Shared components bundled separately
### Module Boundaries
```
isa-app (main bundle)
├── core/ (always loaded)
├── routing (root)
└── route bundles (lazy)
├── oms/ (on route navigation)
├── remission/ (on route navigation)
└── checkout/ (on route navigation)
```
---
## 11. Breaking Changes Prevention
Strict dependency enforcement prevents:
- ✅ Feature importing data-access from other features
- ✅ UI components importing domain logic
- ✅ Core libraries importing domain logic
- ✅ Circular dependencies
- ✅ Implicit dependencies
Violations caught by:
1. ESLint nx plugin (import-rules)
2. TypeScript compiler (path alias validation)
3. Bundle analysis tools
4. Code review process
---
## 12. Updating Dependencies
### Safe Dependency Diagram Update
```
1. Update generated API
→ Automatically updates data-access
2. Update core library
→ Cascades to all dependent layers
3. Update UI component
→ Only affects features using it
4. Update data-access
→ Only affects features in domain
```
### Testing Strategy
- Update → Run affected tests → Deploy
- `npx nx affected:test --skip-nx-cache`
---
## Quick Reference: Which Library to Import
**I need a component for...**
| Use Case | Import From |
|----------|------------|
| Button styling | `@isa/ui/buttons` |
| Form inputs | `@isa/ui/input-controls` |
| Modal dialog | `@isa/ui/dialog` |
| Data fetching | `@isa/[domain]/data-access` |
| Product display | `@isa/shared/product-*` |
| Address display | `@isa/shared/address` |
| Logging | `@isa/core/logging` |
| Configuration | `@isa/core/config` |
| State storage | `@isa/core/storage` |
| Tab navigation | `@isa/core/tabs` |
| Context preservation | `@isa/core/navigation` |
| Printer management | `@isa/common/print` |
| EAN validation | `@isa/utils/ean-validation` |
| API client | `@generated/swagger/[api-name]` |

View File

@@ -173,6 +173,7 @@ export class ShoppingCartService {
return res.result as ShoppingCart;
}
// TODO: Code Kommentieren + Beschreiben
async completeRewardSelection({
tabId,
rewardSelectionItems,
@@ -222,6 +223,7 @@ export class ShoppingCartService {
}
}
// TODO: If Logik in eigene Funktionen auslagern - Für Remove die Update Funktion mit Quantity 0 nutzen, Code Kommentieren
async #handleCart({
shoppingCartId,
itemId,
@@ -295,6 +297,7 @@ export class ShoppingCartService {
}
}
// TODO: If Logik in eigene Funktionen auslagern - Für Remove die Update Funktion mit Quantity 0 nutzen, Code Kommentieren
async #handleRewardCart({
rewardShoppingCartId,
itemId,

View File

@@ -7,6 +7,7 @@ describe('getPrimaryBonusCard', () => {
// Arrange
const bonusCards: BonusCardInfo[] = [
{
code: 'CARD-B',
firstName: 'John',
lastName: 'Doe',
isActive: true,
@@ -14,19 +15,13 @@ describe('getPrimaryBonusCard', () => {
totalPoints: 100,
} as BonusCardInfo,
{
code: 'CARD-A',
firstName: 'Jane',
lastName: 'Smith',
isActive: true,
isPrimary: true,
totalPoints: 200,
} as BonusCardInfo,
{
firstName: 'Bob',
lastName: 'Johnson',
isActive: true,
isPrimary: false,
totalPoints: 50,
} as BonusCardInfo,
];
// Act
@@ -35,14 +30,14 @@ describe('getPrimaryBonusCard', () => {
// Assert
expect(result).toBeDefined();
expect(result?.isPrimary).toBe(true);
expect(result?.firstName).toBe('Jane');
expect(result?.lastName).toBe('Smith');
expect(result?.code).toBe('CARD-A');
});
it('should return undefined when no primary bonus card exists', () => {
it('should return first alphabetically when no primary card exists', () => {
// Arrange
const bonusCards: BonusCardInfo[] = [
{
code: 'CARD-C',
firstName: 'John',
lastName: 'Doe',
isActive: true,
@@ -50,6 +45,7 @@ describe('getPrimaryBonusCard', () => {
totalPoints: 100,
} as BonusCardInfo,
{
code: 'CARD-A',
firstName: 'Jane',
lastName: 'Smith',
isActive: true,
@@ -62,7 +58,8 @@ describe('getPrimaryBonusCard', () => {
const result = getPrimaryBonusCard(bonusCards);
// Assert
expect(result).toBeUndefined();
expect(result).toBeDefined();
expect(result?.code).toBe('CARD-A');
});
it('should return undefined when bonus cards array is empty', () => {
@@ -76,10 +73,11 @@ describe('getPrimaryBonusCard', () => {
expect(result).toBeUndefined();
});
it('should return the first primary card when multiple primary cards exist', () => {
it('should return first alphabetically when multiple primary cards exist', () => {
// Arrange
const bonusCards: BonusCardInfo[] = [
{
code: 'CARD-Z',
firstName: 'John',
lastName: 'Doe',
isActive: true,
@@ -87,6 +85,7 @@ describe('getPrimaryBonusCard', () => {
totalPoints: 100,
} as BonusCardInfo,
{
code: 'CARD-A',
firstName: 'Jane',
lastName: 'Smith',
isActive: true,
@@ -101,6 +100,6 @@ describe('getPrimaryBonusCard', () => {
// Assert
expect(result).toBeDefined();
expect(result?.isPrimary).toBe(true);
expect(result?.firstName).toBe('John');
expect(result?.code).toBe('CARD-A');
});
});

View File

@@ -1,5 +1,22 @@
import { BonusCardInfo } from '../models';
export function getPrimaryBonusCard(bonusCards: BonusCardInfo[]) {
return bonusCards.find((card) => card.isPrimary);
export function getPrimaryBonusCard(
bonusCards: BonusCardInfo[],
): BonusCardInfo | undefined {
if (bonusCards.length === 0) {
return undefined;
}
// Filter primary cards if any exist
const primaryCards = bonusCards.filter((card) => card.isPrimary);
// Use primary cards if available, otherwise use all cards
const cardsToSort = primaryCards.length > 0 ? primaryCards : bonusCards;
// Sort alphabetically by code and return the first one
return cardsToSort.sort((a, b) => {
const codeA = a.code?.toLowerCase() ?? '';
const codeB = b.code?.toLowerCase() ?? '';
return codeA.localeCompare(codeB);
})[0];
}