added material design components
This commit is contained in:
parent
8bf9875e8e
commit
17531f7c29
16 changed files with 236 additions and 164 deletions
39
package-lock.json
generated
39
package-lock.json
generated
|
|
@ -8,10 +8,12 @@
|
||||||
"name": "common-cents-web",
|
"name": "common-cents-web",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@angular/cdk": "~21.1.4",
|
||||||
"@angular/common": "^21.1.0",
|
"@angular/common": "^21.1.0",
|
||||||
"@angular/compiler": "^21.1.0",
|
"@angular/compiler": "^21.1.0",
|
||||||
"@angular/core": "^21.1.0",
|
"@angular/core": "^21.1.0",
|
||||||
"@angular/forms": "^21.1.0",
|
"@angular/forms": "^21.1.0",
|
||||||
|
"@angular/material": "~21.1.4",
|
||||||
"@angular/platform-browser": "^21.1.0",
|
"@angular/platform-browser": "^21.1.0",
|
||||||
"@angular/router": "^21.1.0",
|
"@angular/router": "^21.1.0",
|
||||||
"rxjs": "~7.8.0",
|
"rxjs": "~7.8.0",
|
||||||
|
|
@ -21,6 +23,7 @@
|
||||||
"@angular/build": "^21.1.3",
|
"@angular/build": "^21.1.3",
|
||||||
"@angular/cli": "^21.1.3",
|
"@angular/cli": "^21.1.3",
|
||||||
"@angular/compiler-cli": "^21.1.0",
|
"@angular/compiler-cli": "^21.1.0",
|
||||||
|
"@angular/material": "^21.1.4",
|
||||||
"jsdom": "^27.1.0",
|
"jsdom": "^27.1.0",
|
||||||
"typescript": "~5.9.2",
|
"typescript": "~5.9.2",
|
||||||
"vitest": "^4.0.8"
|
"vitest": "^4.0.8"
|
||||||
|
|
@ -422,6 +425,22 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@angular/cdk": {
|
||||||
|
"version": "21.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-21.1.4.tgz",
|
||||||
|
"integrity": "sha512-PElA4Ww4TIa3+B/ND+fm8ZPDKONTIqc9a/s0qNxhcAD9IpDqjaBVi/fyg+ZWBtS+x0DQgJtKeCsSZ6sr2aFQaQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"parse5": "^8.0.0",
|
||||||
|
"tslib": "^2.3.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": "^21.0.0 || ^22.0.0",
|
||||||
|
"@angular/core": "^21.0.0 || ^22.0.0",
|
||||||
|
"@angular/platform-browser": "^21.0.0 || ^22.0.0",
|
||||||
|
"rxjs": "^6.5.3 || ^7.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@angular/cli": {
|
"node_modules/@angular/cli": {
|
||||||
"version": "21.1.3",
|
"version": "21.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-21.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-21.1.3.tgz",
|
||||||
|
|
@ -563,6 +582,24 @@
|
||||||
"rxjs": "^6.5.3 || ^7.4.0"
|
"rxjs": "^6.5.3 || ^7.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@angular/material": {
|
||||||
|
"version": "21.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@angular/material/-/material-21.1.4.tgz",
|
||||||
|
"integrity": "sha512-Vte+4os5JexhtaPk7Duk5bIC+zU5SYF7ZHUnpmAJxW0u4D4C9lpTVepm2bfMVV2AxHjHVAnW+/anINIS401UsA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.3.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/cdk": "21.1.4",
|
||||||
|
"@angular/common": "^21.0.0 || ^22.0.0",
|
||||||
|
"@angular/core": "^21.0.0 || ^22.0.0",
|
||||||
|
"@angular/forms": "^21.0.0 || ^22.0.0",
|
||||||
|
"@angular/platform-browser": "^21.0.0 || ^22.0.0",
|
||||||
|
"rxjs": "^6.5.3 || ^7.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@angular/platform-browser": {
|
"node_modules/@angular/platform-browser": {
|
||||||
"version": "21.1.3",
|
"version": "21.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-21.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-21.1.3.tgz",
|
||||||
|
|
@ -6845,7 +6882,6 @@
|
||||||
"version": "8.0.0",
|
"version": "8.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz",
|
||||||
"integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==",
|
"integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"entities": "^6.0.0"
|
"entities": "^6.0.0"
|
||||||
|
|
@ -6899,7 +6935,6 @@
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
|
||||||
"integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
|
"integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
|
||||||
"dev": true,
|
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.12"
|
"node": ">=0.12"
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,12 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"packageManager": "npm@10.9.2",
|
"packageManager": "npm@10.9.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@angular/cdk": "~21.1.4",
|
||||||
"@angular/common": "^21.1.0",
|
"@angular/common": "^21.1.0",
|
||||||
"@angular/compiler": "^21.1.0",
|
"@angular/compiler": "^21.1.0",
|
||||||
"@angular/core": "^21.1.0",
|
"@angular/core": "^21.1.0",
|
||||||
"@angular/forms": "^21.1.0",
|
"@angular/forms": "^21.1.0",
|
||||||
|
"@angular/material": "~21.1.4",
|
||||||
"@angular/platform-browser": "^21.1.0",
|
"@angular/platform-browser": "^21.1.0",
|
||||||
"@angular/router": "^21.1.0",
|
"@angular/router": "^21.1.0",
|
||||||
"rxjs": "~7.8.0",
|
"rxjs": "~7.8.0",
|
||||||
|
|
@ -36,6 +38,7 @@
|
||||||
"@angular/build": "^21.1.3",
|
"@angular/build": "^21.1.3",
|
||||||
"@angular/cli": "^21.1.3",
|
"@angular/cli": "^21.1.3",
|
||||||
"@angular/compiler-cli": "^21.1.0",
|
"@angular/compiler-cli": "^21.1.0",
|
||||||
|
"@angular/material": "^21.1.4",
|
||||||
"jsdom": "^27.1.0",
|
"jsdom": "^27.1.0",
|
||||||
"typescript": "~5.9.2",
|
"typescript": "~5.9.2",
|
||||||
"vitest": "^4.0.8"
|
"vitest": "^4.0.8"
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,96 @@
|
||||||
<div class="add-expense-container">
|
<div class="add-expense-container">
|
||||||
<app-card [header]="'Add Expense'">
|
<mat-card appearance="outlined">
|
||||||
<div class="add-expense-body">
|
<mat-card-header>
|
||||||
<div>
|
<mat-card-title>Track new Expense</mat-card-title>
|
||||||
Date: <input type="date" [formField]="expenseForm.date">
|
</mat-card-header>
|
||||||
|
|
||||||
|
|
||||||
|
<mat-card-content>
|
||||||
|
<div class="add-expense-body">
|
||||||
|
<div>
|
||||||
|
Date: <input type="date" [formField]="expenseForm.date">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Cents (required):
|
||||||
|
<input type="number" placeholder="Enter amount" [formField]="expenseForm.amount">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Category (required):
|
||||||
|
<select [formField]="expenseForm.categoryId">
|
||||||
|
<option value="">Select a category</option>
|
||||||
|
@for (category of categories(); track category.id) {
|
||||||
|
<option [value]="category.id">{{ category.name }}</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
Cents (required):
|
Merchant (optional):
|
||||||
<input type="number" placeholder="Enter amount" [formField]="expenseForm.amount">
|
<select [formField]="expenseForm.merchantId">
|
||||||
</div>
|
<option value="">Select a merchant</option>
|
||||||
|
@for (merchant of merchants(); track merchant.id) {
|
||||||
<div>
|
<option [value]="merchant.id">{{ merchant.name }}</option>
|
||||||
Category (required):
|
|
||||||
<select [formField]="expenseForm.categoryId">
|
|
||||||
<option value="">Select a category</option>
|
|
||||||
@for (category of categories(); track category.id) {
|
|
||||||
<option [value]="category.id">{{ category.name }}</option>
|
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
Merchant (optional):
|
Note (optional): <input type="text" [formField]="expenseForm.note">
|
||||||
<select [formField]="expenseForm.merchantId">
|
</div>
|
||||||
<option value="">Select a merchant</option>
|
|
||||||
@for (merchant of merchants(); track merchant.id) {
|
|
||||||
<option [value]="merchant.id">{{ merchant.name }}</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div>Tags</div>
|
||||||
Note (optional): <input type="text" [formField]="expenseForm.note">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>Tags</div>
|
<div class="card-footer">
|
||||||
|
<button>Save</button>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
|
||||||
<div class="card-footer">
|
|
||||||
<button>Save</button>
|
|
||||||
</div>
|
<!-- <app-card [header]="'Add Expense'">-->
|
||||||
</app-card>
|
<!-- <div class="add-expense-body">-->
|
||||||
|
<!-- <div>-->
|
||||||
|
<!-- Date: <input type="date" [formField]="expenseForm.date">-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <div>-->
|
||||||
|
<!-- Cents (required):-->
|
||||||
|
<!-- <input type="number" placeholder="Enter amount" [formField]="expenseForm.amount">-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <div>-->
|
||||||
|
<!-- Category (required):-->
|
||||||
|
<!-- <select [formField]="expenseForm.categoryId">-->
|
||||||
|
<!-- <option value="">Select a category</option>-->
|
||||||
|
<!-- @for (category of categories(); track category.id) {-->
|
||||||
|
<!-- <option [value]="category.id">{{ category.name }}</option>-->
|
||||||
|
<!-- }-->
|
||||||
|
<!-- </select>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <div>-->
|
||||||
|
<!-- Merchant (optional):-->
|
||||||
|
<!-- <select [formField]="expenseForm.merchantId">-->
|
||||||
|
<!-- <option value="">Select a merchant</option>-->
|
||||||
|
<!-- @for (merchant of merchants(); track merchant.id) {-->
|
||||||
|
<!-- <option [value]="merchant.id">{{ merchant.name }}</option>-->
|
||||||
|
<!-- }-->
|
||||||
|
<!-- </select>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <div>-->
|
||||||
|
<!-- Note (optional): <input type="text" [formField]="expenseForm.note">-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <div>Tags</div>-->
|
||||||
|
|
||||||
|
<!-- <div class="card-footer">-->
|
||||||
|
<!-- <button>Save</button>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </app-card>-->
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
.add-expense-body {
|
//.add-expense-body {
|
||||||
display: flex;
|
// display: flex;
|
||||||
justify-content: flex-start;
|
// justify-content: flex-start;
|
||||||
gap: 0.5rem;
|
// gap: 0.5rem;
|
||||||
}
|
//}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import {Component, computed, signal} from '@angular/core';
|
import {Component, computed, signal} from '@angular/core';
|
||||||
import { CardComponent } from '../card/card.component';
|
|
||||||
import {Category, CategoryService} from '../../services/category.service';
|
import {Category, CategoryService} from '../../services/category.service';
|
||||||
import {Merchant, MerchantService} from '../../services/merchant.service';
|
import {Merchant, MerchantService} from '../../services/merchant.service';
|
||||||
import { Tag } from '../../services/tag.service';
|
import { Tag } from '../../services/tag.service';
|
||||||
import {form, FormField} from '@angular/forms/signals';
|
import {form, FormField} from '@angular/forms/signals';
|
||||||
|
import {MatCard, MatCardContent, MatCardHeader, MatCardTitle} from '@angular/material/card';
|
||||||
|
|
||||||
interface AddExpenseForm {
|
interface AddExpenseForm {
|
||||||
date: Date,
|
date: Date,
|
||||||
|
|
@ -17,8 +17,11 @@ interface AddExpenseForm {
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-add-expense',
|
selector: 'app-add-expense',
|
||||||
imports: [
|
imports: [
|
||||||
CardComponent,
|
FormField,
|
||||||
FormField
|
MatCard,
|
||||||
|
MatCardHeader,
|
||||||
|
MatCardTitle,
|
||||||
|
MatCardContent
|
||||||
],
|
],
|
||||||
templateUrl: './add-expense.component.html',
|
templateUrl: './add-expense.component.html',
|
||||||
styleUrl: './add-expense.component.scss',
|
styleUrl: './add-expense.component.scss',
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
<div class="card-container">
|
|
||||||
@if (header()) {
|
|
||||||
<div class="card-header">{{ header() }}</div>
|
|
||||||
} @else {
|
|
||||||
<ng-content select="card-header" />
|
|
||||||
}
|
|
||||||
|
|
||||||
<ng-content />
|
|
||||||
|
|
||||||
@if (footer()) {
|
|
||||||
<div class="card-footer">{{ footer() }}</div>
|
|
||||||
} @else {
|
|
||||||
<ng-content select="card-footer" />
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
.card-container {
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 1rem;
|
|
||||||
box-shadow: rgba(99, 99, 99, 0.2) 0 2px 8px 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-header {
|
|
||||||
font-size: 1.25rem;
|
|
||||||
font-weight: 700;
|
|
||||||
font-family: sans-serif;
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
import { Component, input } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-card',
|
|
||||||
imports: [],
|
|
||||||
templateUrl: './card.component.html',
|
|
||||||
styleUrl: './card.component.scss',
|
|
||||||
})
|
|
||||||
export class CardComponent {
|
|
||||||
public header = input<string>('');
|
|
||||||
public footer = input<string>('');
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,34 @@
|
||||||
<div class="expense-list-container">
|
<div class="expense-list-container">
|
||||||
@for (expense of expenses(); track expense.id) {
|
<mat-card appearance="outlined" class="expense-table-card">
|
||||||
<div class="expense-item">
|
<mat-card-header>
|
||||||
<app-expense [expense]="expense" />
|
<mat-card-title>Tracked Expenses</mat-card-title>
|
||||||
</div>
|
</mat-card-header>
|
||||||
}
|
|
||||||
|
<mat-card-content>
|
||||||
|
<table mat-table [dataSource]="expenses()" class="expense-table">
|
||||||
|
<ng-container matColumnDef="date">
|
||||||
|
<th mat-header-cell *matHeaderCellDef>Date</th>
|
||||||
|
<td mat-cell *matCellDef="let expense">{{ `${expense.year}/${expense.month}/${expense.day}` | date }}</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="amount">
|
||||||
|
<th mat-header-cell *matHeaderCellDef>Amount</th>
|
||||||
|
<td mat-cell *matCellDef="let expense">{{ (expense.cents / 100) | currency: 'USD' }}</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="category">
|
||||||
|
<th mat-header-cell *matHeaderCellDef>Category</th>
|
||||||
|
<td mat-cell *matCellDef="let expense">{{ expense.category.name }}</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container matColumnDef="merchant">
|
||||||
|
<th mat-header-cell *matHeaderCellDef>Merchant</th>
|
||||||
|
<td mat-cell *matCellDef="let expense">{{ expense.merchant?.name ?? '--' }}</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="columns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let rowData; columns: columns"></tr>
|
||||||
|
</table>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
.expense-item {
|
|
||||||
padding-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +1,43 @@
|
||||||
import { Component, computed } from '@angular/core';
|
import { Component, computed } from '@angular/core';
|
||||||
import { ExpenseService } from '../../services/expense.service';
|
import { ExpenseService } from '../../services/expense.service';
|
||||||
import { ExpenseComponent } from '../expense/expense.component';
|
import {
|
||||||
|
MatCell,
|
||||||
|
MatCellDef,
|
||||||
|
MatColumnDef,
|
||||||
|
MatHeaderCell,
|
||||||
|
MatHeaderCellDef,
|
||||||
|
MatHeaderRow, MatHeaderRowDef, MatRow, MatRowDef,
|
||||||
|
MatTable
|
||||||
|
} from '@angular/material/table';
|
||||||
|
import {CurrencyPipe, DatePipe} from '@angular/common';
|
||||||
|
import {MatCard, MatCardContent, MatCardHeader, MatCardTitle} from '@angular/material/card';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-expense-list',
|
selector: 'app-expense-list',
|
||||||
imports: [
|
imports: [
|
||||||
ExpenseComponent
|
MatTable,
|
||||||
|
MatColumnDef,
|
||||||
|
MatHeaderCell,
|
||||||
|
MatHeaderCellDef,
|
||||||
|
DatePipe,
|
||||||
|
MatCell,
|
||||||
|
MatCellDef,
|
||||||
|
CurrencyPipe,
|
||||||
|
MatHeaderRow,
|
||||||
|
MatHeaderRowDef,
|
||||||
|
MatRow,
|
||||||
|
MatRowDef,
|
||||||
|
MatCard,
|
||||||
|
MatCardHeader,
|
||||||
|
MatCardTitle,
|
||||||
|
MatCardContent
|
||||||
],
|
],
|
||||||
templateUrl: './expense-list.component.html',
|
templateUrl: './expense-list.component.html',
|
||||||
styleUrl: './expense-list.component.scss',
|
styleUrl: './expense-list.component.scss',
|
||||||
})
|
})
|
||||||
export class ExpenseListComponent {
|
export class ExpenseListComponent {
|
||||||
protected expenses = computed(() => this.expensesService.expenses())
|
protected expenses = computed(() => this.expensesService.expenses())
|
||||||
|
protected columns = ['date', 'amount', 'category', 'merchant'];
|
||||||
|
|
||||||
public constructor(private readonly expensesService: ExpenseService) { }
|
public constructor(private readonly expensesService: ExpenseService) { }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
<div class="expense-container">
|
|
||||||
<app-card>
|
|
||||||
<div class="expense-header">
|
|
||||||
{{ `${expense().year}/${expense().month}/${expense().day}` | date }}: {{ (expense().cents / 100) | currency: 'USD' }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="expense-body">
|
|
||||||
<div>Merchant: {{ expense().merchant?.name ?? '--' }}</div>
|
|
||||||
|
|
||||||
<div>Category: {{ expense().category.name }}</div>
|
|
||||||
|
|
||||||
<div>Note: {{ expense().note ?? '--' }}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="expense-footer">
|
|
||||||
<div>Tags:</div>
|
|
||||||
|
|
||||||
@if (expense().tags.length) {
|
|
||||||
@for (tag of expense().tags; track tag.id) {
|
|
||||||
<div class="expense-tag">{{ tag.name }}</div>
|
|
||||||
}
|
|
||||||
} @else {
|
|
||||||
<div>--</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</app-card>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
.expense-header {
|
|
||||||
font-family: sans-serif;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.expense-body {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.expense-footer {
|
|
||||||
font-family: sans-serif;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
font-weight: lighter;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
color: #515151;
|
|
||||||
}
|
|
||||||
|
|
||||||
.expense-tag {
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
background-color: #f1f1f1;
|
|
||||||
padding: 0.1rem 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
import { Component, input } from '@angular/core';
|
|
||||||
import { Expense } from '../../services/expense.service';
|
|
||||||
import { CurrencyPipe, DatePipe } from '@angular/common';
|
|
||||||
import { CardComponent } from '../card/card.component';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-expense',
|
|
||||||
imports: [
|
|
||||||
CurrencyPipe,
|
|
||||||
DatePipe,
|
|
||||||
CardComponent
|
|
||||||
],
|
|
||||||
templateUrl: './expense.component.html',
|
|
||||||
styleUrl: './expense.component.scss',
|
|
||||||
})
|
|
||||||
export class ExpenseComponent {
|
|
||||||
public expense = input.required<Expense>();
|
|
||||||
}
|
|
||||||
|
|
@ -6,6 +6,10 @@
|
||||||
<base href="/">
|
<base href="/">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
|
||||||
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<app-root></app-root>
|
<app-root></app-root>
|
||||||
|
|
|
||||||
|
|
@ -1 +1,38 @@
|
||||||
|
|
||||||
|
// Include theming for Angular Material with `mat.theme()`.
|
||||||
|
// This Sass mixin will define CSS variables that are used for styling Angular Material
|
||||||
|
// components according to the Material 3 design spec.
|
||||||
|
// Learn more about theming and how to use it for your application's
|
||||||
|
// custom components at https://material.angular.dev/guide/theming
|
||||||
|
@use '@angular/material' as mat;
|
||||||
|
|
||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
@include mat.theme((
|
||||||
|
color: (
|
||||||
|
primary: mat.$cyan-palette,
|
||||||
|
tertiary: mat.$orange-palette,
|
||||||
|
),
|
||||||
|
typography: Roboto,
|
||||||
|
density: 0
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
// Default the application to a light color theme. This can be changed to
|
||||||
|
// `dark` to enable the dark color theme, or to `light dark` to defer to the
|
||||||
|
// user's system settings.
|
||||||
|
color-scheme: light; // TODO: choose 'light dark'
|
||||||
|
|
||||||
|
// Set a default background, font and text colors for the application using
|
||||||
|
// Angular Material's system-level CSS variables. Learn more about these
|
||||||
|
// variables at https://material.angular.dev/guide/system-variables
|
||||||
|
background-color: var(--mat-sys-surface);
|
||||||
|
color: var(--mat-sys-on-surface);
|
||||||
|
font: var(--mat-sys-body-medium);
|
||||||
|
|
||||||
|
// Reset the user agent margin.
|
||||||
|
margin: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
/* You can add global styles to this file, and also import other style files */
|
/* You can add global styles to this file, and also import other style files */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue