AI Skill Report Card
Implementing Angular Retail Banking
Quick Start15 / 15
TypeScriptimport { Component, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { Button, ListItem, Loader } from '@shared/ui'; import { SomeQuery } from '@shared/api'; @Component({ selector: 'app-component-name', imports: [CommonModule, Button, ListItem, Loader], templateUrl: './component-name.html', styleUrl: './component-name.css', }) export class ComponentName { private someQuery = inject(SomeQuery); data = this.someQuery.getDataQuery(); handleAction() { // Implementation } }
Recommendation▾
Remove the extensive design system utilities section - Claude knows CSS utilities and this over-explains basics
Workflow13 / 15
Progress:
- Create component folder with
.ts,.html,.css,.spec.tsfiles - Import required shared UI components from
@shared/ui - Set up state management with TanStack Query and signals
- Build template using utility classes and control flow syntax
- Apply design system tokens and spacing utilities
- Test component with loading/error/success states
Recommendation▾
Compress the workflow section into a simpler checklist without explanatory text
Design System Utilities
Spacing (4px base, 16 levels)
CSS.m-1 to .m-16 /* margin: 4px to 88px */ .p-1 to .p-16 /* padding: 4px to 88px */ .gap-4 /* 16px gap */
Colors
CSS.bg-accent-500 /* Primary blue */ .text-secondary /* Muted text */ .text-green-500 /* Success */ .text-red-500 /* Error */
Layout
HTML<div class="grid-container max-w-full"> <div class="w-5">5/12 width</div> <div class="w-7">7/12 width</div> </div> <div class="flex justify-center align-items-center gap-4"> <!-- Flexbox content --> </div>
Examples18 / 20
Example 1: Data List Component
Input: Create a component showing account transactions with loading state
Output:
TypeScript// account-transactions.ts import { Component, inject } from '@angular/core'; import { ListItem, Loader } from '@shared/ui'; import { AccountsQuery } from '@shared/api'; @Component({ selector: 'app-account-transactions', imports: [ListItem, Loader], templateUrl: './account-transactions.html', styleUrl: './account-transactions.css', }) export class AccountTransactions { private accountsQuery = inject(AccountsQuery); transactions = this.accountsQuery.getTransactionsQuery(); }
HTML<!-- account-transactions.html --> <div class="card p-4"> <h2 class="text-xl font-semibold mb-4">Recent Transactions</h2> @if (transactions.isLoading()) { <lib-loader variant="list" [rows]="5"></lib-loader> } @else { @for (transaction of transactions.data()?.content; track transaction.id) { <lib-list-item [heading]="transaction.description" [subheading]="transaction.date" [prefixIcon]="transaction.type === 'DEBIT' ? 'solar:arrow-right-up-linear' : 'solar:arrow-left-down-linear'" > <div slot="suffix"> <span [class]="transaction.type === 'DEBIT' ? 'text-red-500' : 'text-green-500'"> {{ transaction.amount | currency:transaction.currency:'symbol':'1.2-2':'fr' }} </span> </div> </lib-list-item> } } </div>
Example 2: Form Dialog Component
Input: Create a dialog for adding a new payee with form validation
Output:
TypeScript// add-payee-dialog.ts import { Component, inject, signal } from '@angular/core'; import { DialogComponent, Button, Input } from '@shared/ui'; import { PayeesQuery } from '@shared/api'; @Component({ selector: 'app-add-payee-dialog', imports: [DialogComponent, Button, Input], templateUrl: './add-payee-dialog.html', styleUrl: './add-payee-dialog.css', }) export class AddPayeeDialog { private payeesQuery = inject(PayeesQuery); visible = signal(false); payeeData = signal({ name: '', accountNumber: '' }); createMutation = this.payeesQuery.CreatePayeeMutation(); handleSubmit() { this.createMutation.mutate(this.payeeData()); } }
HTML<!-- add-payee-dialog.html --> <lib-dialog [(visible)]="visible"> <div class="bg-screen p-6 border-radius-2xl"> <h2 class="text-2xl font-semibold mb-6">Add New Payee</h2> <div class="flex flex-column gap-4"> <lib-input label="Payee Name" placeholder="Enter payee name" [(ngModel)]="payeeData().name" /> <lib-input label="Account Number" placeholder="Enter account number" [(ngModel)]="payeeData().accountNumber" /> <div class="flex gap-3 justify-end"> <lib-button label="Cancel" variant="outline" (onClick)="visible.set(false)" /> <lib-button label="Add Payee" variant="primary" [loading]="createMutation.isPending()" (onClick)="handleSubmit()" /> </div> </div> </div> </lib-dialog>
Recommendation▾
Add a third example showing error handling or edge case scenarios to demonstrate robustness
Best Practices
- Use
.cssfiles, not.scss - Import shared UI components from
@shared/uipath - Use
inject()for dependency injection instead of constructor - Leverage utility classes before writing custom CSS
- Use signals for reactive state management
- Apply TanStack Query pattern for server state
- Follow Angular 17+ control flow syntax (
@if,@for,@switch) - Include proper TypeScript typing for component inputs/outputs
- Use
::ng-deepsparingly, only for PrimeNG component overrides
Common Pitfalls
- Don't use SCSS - stick to CSS files
- Don't import PrimeNG components directly - use shared wrappers
- Don't use constructor-based DI - prefer
inject() - Don't write custom spacing CSS - use utility classes (
.p-4,.m-2) - Don't forget loading and error states in templates
- Don't skip the
.spec.tstest files - Don't use inline styles in component decorator
- Don't create new color values - use design system tokens