import { ChangeDetectionStrategy, Component, computed, input, } from '@angular/core'; import { Home } from '@task-stream/web/tracker/domain'; /** «+30 %» or «−10 %» against the week before (nothing when there was none). */ function change(now: number, before: number): string { if (!before) return now ? 'nuevo' : ''; const pct = Math.round(((now - before) / before) * 100); return `${pct >= 0 ? '+' : '−'}${Math.abs(pct)} %`; } /** How the week goes: mine (and my streak) and my projects' teams. */ @Component({ selector: 'ts-week-stats', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'ts-panel', role: 'region', 'aria-labelledby': 'stats-title', }, styleUrl: './home-panel.scss', template: `

La semana

Tickets terminados, últimos 7 días

Tú

{{ me().thisWeek }} @if (myChange(); as c) { {{ c }} }

@if (me().streak > 1) { {{ me().streak }} días seguidos terminando algo } @else if (me().streak === 1) { Terminaste algo hoy o ayer } @else { Sin racha: hoy puede empezar una }

Tus equipos

{{ team().thisWeek }} @if (teamChange(); as c) { {{ c }} }

`, styles: ` .ts-week { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } .ts-week__label { margin: 0; color: var(--ts-muted); font-size: 0.75rem; } .ts-week__value { display: flex; align-items: baseline; gap: 0.5rem; margin: 0.125rem 0 0.25rem; font-size: 1.75rem; font-weight: 700; } .ts-week__change { color: var(--ts-c-green, #2e9e6a); font-size: 0.8125rem; font-weight: 600; &.is-down { color: var(--ts-muted); } } .ts-week__sub { margin: 0; color: var(--ts-ink-soft); font-size: 0.8125rem; } .ts-week__bars { display: flex; align-items: flex-end; gap: 2px; height: 2.5rem; span { flex: 1; min-height: 2px; border-radius: 2px 2px 0 0; background: color-mix(in srgb, var(--ts-brand) 35%, transparent); &.is-this-week { background: var(--ts-brand); } } } `, }) export class WeekStatsComponent { readonly me = input.required(); readonly team = input.required(); protected readonly myChange = computed(() => change(this.me().thisWeek, this.me().lastWeek), ); protected readonly teamChange = computed(() => change(this.team().thisWeek, this.team().lastWeek), ); private readonly max = computed(() => Math.max(1, ...this.team().perDay)); protected height(n: number): number { return (n / this.max()) * 100; } }