Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<section class="d-flex flex-column h-100 justif-content-between p-2 pb-0 p-sm-3 p-md-4 gap-0">
<section class="d-flex flex-column h-100 justify-content-between p-2 pb-0 p-sm-3 p-md-4 gap-0">
<div class="d-flex flex-row justify-content-center justify-content-md-between align-items-center gap-2">
<div>
<h1 class="m-0 text-center text-md-start {{ display.isSm() ? 'fs-1' : 'fs-2' }}">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<section class="d-flex flex-column h-100 justif-content-between p-2 pb-0 p-sm-3 p-md-4 gap-0">
<section class="d-flex flex-column h-100 justify-content-between p-2 pb-0 p-sm-3 p-md-4 gap-0">
<!-- Profile data -->
<form class="d-flex flex-column gap-4" [formGroup]="userDataForm" (submit)="saveUserData()" stopPropagation>
<div
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Component } from '@angular/core';
import { MatCardModule } from '@angular/material/card';
import { MatIconModule } from '@angular/material/icon';

@Component({
selector: 'ex-empty-statistic-card',
template: `
<mat-card class="justify-content-center align-items-center">
<mat-icon size="xxl">add_2</mat-icon>
</mat-card>
`,
styles: `
:host {
cursor: pointer;
min-width: 350px;
max-width: 600px;
width: 100%;
height: 100%;

&:hover {
mat-card.mat-mdc-card {
background-color: color-mix(in srgb, var(--app-card-color), white 5%);
transform: scale(1.015);
box-shadow: 1px 1px 10px var(--shadow-color);
}
}
&:active {
mat-card.mat-mdc-card {
transform: scale(1.015) translateY(3px);
}
}
}

mat-card.mat-mdc-card {
transition:
background-color,
transform 0.3s ease-in-out;
height: 100%;
width: 100%;
border: 2px solid var(--primary-color);
}

mat-icon {
color: var(--primary-color);
}
`,
imports: [MatCardModule, MatIconModule],
})
export class EmptyStatisticCardComponent {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<ng-content />

@if (numberOfCards() < 4) {
<ex-empty-statistic-card />
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
:host {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
gap: 1.5rem;

scrollbar-gutter: stable;
padding-top: 0.5rem;
padding-bottom: 0.5rem;

width: 100%;
overflow-x: auto;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Component, input } from '@angular/core';
import { EmptyStatisticCardComponent } from '../empty-statistic-card.component';

@Component({
selector: 'ex-stat-card-list',
templateUrl: './stat-card-list.component.html',
styleUrl: './stat-card-list.component.scss',
imports: [EmptyStatisticCardComponent],
})
export class StatCardListComponent {
numberOfCards = input.required<number>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<mat-card class="d-flex flex-column justify-content-center gap-3 p-4 position-relative h-100">
<ex-info-button [tooltip]="info()" />

@if (type() === 'metric') {
<div class="d-flex flex-column gap-0 align-items-center">
<div class="fs-4 fw-bold">{{ data().label }}</div>
<div class="fs-2 fw-bold">
@switch (valueType()) {
@case ('currency') {
{{ data().value | currency: 'Ft' : 'symbol' : '1.0-0' }}
}
@case ('percentage') {
{{ data().value }}%
}
@default {
{{ data().value }}
}
}
</div>
<div class="fs-6 fw-lighter">{{ data().contextLabel }}</div>
</div>
} @else if (type() === 'spotlight') {
<div class="d-flex flex-row flex-nowrap gap-3 align-items-center justify-content-center">
<div ex-card-icon [style.--icon-color]="data().icon!.color">
<mat-icon size="xl">{{ data().icon!.icon }}</mat-icon>
</div>
<div class="d-flex flex-column gap-0 justify-content-center align-items-start">
<div class="fw-bolder fs-6">{{ data().label }}</div>
<div class="fw-bold fs-3">{{ data().value | currency: 'Ft' : 'symbol' : '1.0-0' }}</div>
<div class="fw-lighter fs-6">"{{ data().contextLabel }}"</div>
</div>
</div>
}

@if (type() === 'metric') {
<div class="trend" [attr.trend]="data().trend">
@if (data().changePercentage !== 0) {
<span class="mt-1">{{ assets().prefix + data().changePercentage }}</span>
}
<mat-icon size="sm">{{ assets().suffix }}</mat-icon>
</div>
}
</mat-card>
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
$trend-colors: (
'UP': var(--tertiary-color),
'DOWN': var(--error-color),
'NEUTRAL': var(--accnet-text-color),
);

:host {
max-width: 600px;
height: 100%;
flex-grow: 1;
}

.trend {
position: absolute;
bottom: 1rem;
right: 1rem;
font-weight: bold;
display: flex;
flex-wrap: nowrap;
align-items: center;

@each $trend, $color in $trend-colors {
&[trend='#{$trend}'] {
color: $color;
}
}

mat-icon {
display: inline;
}
}

mat-card.mat-mdc-card {
min-width: 350px;
width: 100%;
border: 2px solid var(--primary-color);

[ex-card-icon] {
height: 5rem;
width: 5rem;
background-color: color-mix(in srgb, var(--icon-color), transparent 60%);

mat-icon {
color: var(--icon-color);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Component, computed, input } from '@angular/core';
import { MatCardModule } from '@angular/material/card';
import { MatIconModule } from '@angular/material/icon';
import { InfoButtonComponent } from '../../../shared/info-button/info-button.component';
import { CurrencyPipe } from '@angular/common';
import { MaterialIcon } from '../../../data-model/modules/category/MaterialIcon';

export interface StatCardDTO {
label: string;
value: number;
changePercentage?: number;
trend?: 'UP' | 'DOWN' | 'NEUTRAL';
contextLabel?: string;
icon?: {
icon: MaterialIcon;
color: string;
};
}

interface StatCardAssetInfo {
prefix: string;
suffix: string;
}

@Component({
selector: 'ex-stat-card',
templateUrl: './stat-card.component.html',
styleUrl: './stat-card.component.scss',
imports: [MatCardModule, MatIconModule, InfoButtonComponent, CurrencyPipe],
})
export class StatCardComponent {
data = input.required<StatCardDTO>();
info = input.required<string>();
type = input<'metric' | 'spotlight'>('spotlight');
valueType = input<'currency' | 'percentage'>('currency');

assets = computed<StatCardAssetInfo>(() => {
switch (this.data().trend) {
case 'UP':
return { prefix: '+', suffix: 'arrow_upward' };
case 'DOWN':
return { prefix: '-', suffix: 'arrow_downward' };
default:
return { prefix: '', suffix: 'check_indeterminate_small' };
}
});
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<section
class="d-flex flex-column h-100 justif-content-between p-2 pb-0 p-sm-3 p-md-4 gap-2"
class="d-flex flex-column h-100 justify-content-between p-2 pb-0 p-sm-3 p-md-4 gap-2"
[class.overflow-hidden]="display.isMd()"
>
<div
Expand Down Expand Up @@ -85,7 +85,7 @@ <h2 class="m-0 text-center text-md-start {{ display.isSm() ? 'fs-1' : 'fs-2' }}"
</div>

<div class="d-flex flex-column h-100 gap-2 bigger-row" [class.overflow-hidden]="display.isMd()">
<div class="d-flex flex-row flex-nowrap justif-content-between">
<div class="d-flex flex-row flex-nowrap justify-content-between">
<div
class="d-flex flex-row flex-nowrap justify-content-between gap-3 w-100"
[matTooltip]="!canCreateTransaction ? 'First create a category!' : ''"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Component, input } from '@angular/core';
import { MatTooltipModule } from '@angular/material/tooltip';
import { ButtonComponent } from '../button/button.component';
import { StopPropagationDirective } from '../stop-propagation.directive';

@Component({
selector: 'ex-info-button',
template: `
<ex-button
#tooltipButton="matTooltip"
iconButton
stopPropagation
color="accent"
[matTooltip]="tooltip()"
(click)="$event.preventDefault(); tooltipButton.toggle()"
/>
`,
styles: `
:host {
position: absolute;
top: 1rem;
right: 1rem;
}
`,
imports: [ButtonComponent, MatTooltipModule, StopPropagationDirective],
})
export class InfoButtonComponent {
tooltip = input.required<string>();
}
Loading