feat: add DangerBadge shared component
Renders the 5 HuntEncounter danger tiers as German text plus a per-tier BEM modifier class, mirroring travel-panel's text+class danger pattern so color is never the sole signal. Colors map across the existing 3 semantic tokens (success/warning/danger).
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
<span
|
||||||
|
class="danger-badge"
|
||||||
|
[class.danger-badge--weak]="rating === 'WEAK'"
|
||||||
|
[class.danger-badge--match]="rating === 'MATCH'"
|
||||||
|
[class.danger-badge--strong]="rating === 'STRONG'"
|
||||||
|
[class.danger-badge--very-dangerous]="rating === 'VERY_DANGEROUS'"
|
||||||
|
[class.danger-badge--deadly]="rating === 'DEADLY'"
|
||||||
|
>{{ label }}</span
|
||||||
|
>
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
:host {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.danger-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: var(--ar-space-1) var(--ar-space-2);
|
||||||
|
border: 1px solid var(--ar-border);
|
||||||
|
border-radius: var(--ar-radius-sm);
|
||||||
|
background: var(--ar-panel-muted);
|
||||||
|
color: var(--ar-text);
|
||||||
|
font-family: Georgia, 'Times New Roman', serif;
|
||||||
|
font-size: var(--ar-font-sm);
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.danger-badge--weak {
|
||||||
|
color: var(--ar-success);
|
||||||
|
border-color: var(--ar-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.danger-badge--match {
|
||||||
|
color: var(--ar-success);
|
||||||
|
border-color: var(--ar-success);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.danger-badge--strong {
|
||||||
|
color: var(--ar-warning);
|
||||||
|
border-color: var(--ar-warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
.danger-badge--very-dangerous {
|
||||||
|
color: var(--ar-danger);
|
||||||
|
border-color: var(--ar-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.danger-badge--deadly {
|
||||||
|
color: var(--ar-danger);
|
||||||
|
border-color: var(--ar-danger);
|
||||||
|
font-weight: 700;
|
||||||
|
background: color-mix(in srgb, var(--ar-danger) 18%, var(--ar-panel-muted));
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import type { DangerRating } from '../../core/api/game-api.models';
|
||||||
|
import { DangerBadgeComponent } from './danger-badge.component';
|
||||||
|
|
||||||
|
const expectations: Array<{ rating: DangerRating; label: string; modifierClass: string }> = [
|
||||||
|
{ rating: 'WEAK', label: 'Schwach', modifierClass: 'danger-badge--weak' },
|
||||||
|
{ rating: 'MATCH', label: 'Passend', modifierClass: 'danger-badge--match' },
|
||||||
|
{ rating: 'STRONG', label: 'Stark', modifierClass: 'danger-badge--strong' },
|
||||||
|
{
|
||||||
|
rating: 'VERY_DANGEROUS',
|
||||||
|
label: 'Sehr gefährlich',
|
||||||
|
modifierClass: 'danger-badge--very-dangerous',
|
||||||
|
},
|
||||||
|
{ rating: 'DEADLY', label: 'Tödlich', modifierClass: 'danger-badge--deadly' },
|
||||||
|
];
|
||||||
|
|
||||||
|
describe('DangerBadgeComponent', () => {
|
||||||
|
for (const { rating, label, modifierClass } of expectations) {
|
||||||
|
it(`renders the German label "${label}" and modifier class for ${rating}`, () => {
|
||||||
|
const fixture = TestBed.createComponent(DangerBadgeComponent);
|
||||||
|
fixture.componentRef.setInput('rating', rating);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const badge = fixture.nativeElement.querySelector('.danger-badge') as HTMLElement;
|
||||||
|
|
||||||
|
expect(badge.textContent?.trim()).toBe(label);
|
||||||
|
expect(badge.classList.contains(modifierClass)).toBe(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
import { DangerRating } from '../../core/api/game-api.models';
|
||||||
|
|
||||||
|
const DANGER_LABELS: Record<DangerRating, string> = {
|
||||||
|
WEAK: 'Schwach',
|
||||||
|
MATCH: 'Passend',
|
||||||
|
STRONG: 'Stark',
|
||||||
|
VERY_DANGEROUS: 'Sehr gefährlich',
|
||||||
|
DEADLY: 'Tödlich',
|
||||||
|
};
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-danger-badge',
|
||||||
|
templateUrl: './danger-badge.component.html',
|
||||||
|
styleUrl: './danger-badge.component.scss',
|
||||||
|
})
|
||||||
|
export class DangerBadgeComponent {
|
||||||
|
@Input({ required: true }) rating!: DangerRating;
|
||||||
|
|
||||||
|
protected get label(): string {
|
||||||
|
return DANGER_LABELS[this.rating];
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user