diff --git a/package-lock.json b/package-lock.json
index 79f7ee8..37680ab 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,10 +8,12 @@
"name": "common-cents-web",
"version": "0.0.0",
"dependencies": {
+ "@angular/cdk": "~21.1.4",
"@angular/common": "^21.1.0",
"@angular/compiler": "^21.1.0",
"@angular/core": "^21.1.0",
"@angular/forms": "^21.1.0",
+ "@angular/material": "~21.1.4",
"@angular/platform-browser": "^21.1.0",
"@angular/router": "^21.1.0",
"rxjs": "~7.8.0",
@@ -21,6 +23,7 @@
"@angular/build": "^21.1.3",
"@angular/cli": "^21.1.3",
"@angular/compiler-cli": "^21.1.0",
+ "@angular/material": "^21.1.4",
"jsdom": "^27.1.0",
"typescript": "~5.9.2",
"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": {
"version": "21.1.3",
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-21.1.3.tgz",
@@ -563,6 +582,24 @@
"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": {
"version": "21.1.3",
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-21.1.3.tgz",
@@ -6845,7 +6882,6 @@
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz",
"integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"entities": "^6.0.0"
@@ -6899,7 +6935,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
"integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
- "dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
diff --git a/package.json b/package.json
index 6c41d2b..e3c47c6 100644
--- a/package.json
+++ b/package.json
@@ -23,10 +23,12 @@
"private": true,
"packageManager": "npm@10.9.2",
"dependencies": {
+ "@angular/cdk": "~21.1.4",
"@angular/common": "^21.1.0",
"@angular/compiler": "^21.1.0",
"@angular/core": "^21.1.0",
"@angular/forms": "^21.1.0",
+ "@angular/material": "~21.1.4",
"@angular/platform-browser": "^21.1.0",
"@angular/router": "^21.1.0",
"rxjs": "~7.8.0",
@@ -36,6 +38,7 @@
"@angular/build": "^21.1.3",
"@angular/cli": "^21.1.3",
"@angular/compiler-cli": "^21.1.0",
+ "@angular/material": "^21.1.4",
"jsdom": "^27.1.0",
"typescript": "~5.9.2",
"vitest": "^4.0.8"
diff --git a/src/app/components/add-expense/add-expense.component.html b/src/app/components/add-expense/add-expense.component.html
index 8c2bfde..8d16c98 100644
--- a/src/app/components/add-expense/add-expense.component.html
+++ b/src/app/components/add-expense/add-expense.component.html
@@ -1,44 +1,96 @@
-
-
-
-
- Merchant (optional):
-
-
+
+ Note (optional):
+
-
- Note (optional):
-
+
Tags
-
Tags
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/components/add-expense/add-expense.component.scss b/src/app/components/add-expense/add-expense.component.scss
index 45d6dd6..9bf429e 100644
--- a/src/app/components/add-expense/add-expense.component.scss
+++ b/src/app/components/add-expense/add-expense.component.scss
@@ -1,5 +1,5 @@
-.add-expense-body {
- display: flex;
- justify-content: flex-start;
- gap: 0.5rem;
-}
+//.add-expense-body {
+// display: flex;
+// justify-content: flex-start;
+// gap: 0.5rem;
+//}
diff --git a/src/app/components/add-expense/add-expense.component.ts b/src/app/components/add-expense/add-expense.component.ts
index fc685de..b0d0ccb 100644
--- a/src/app/components/add-expense/add-expense.component.ts
+++ b/src/app/components/add-expense/add-expense.component.ts
@@ -1,9 +1,9 @@
import {Component, computed, signal} from '@angular/core';
-import { CardComponent } from '../card/card.component';
import {Category, CategoryService} from '../../services/category.service';
import {Merchant, MerchantService} from '../../services/merchant.service';
import { Tag } from '../../services/tag.service';
import {form, FormField} from '@angular/forms/signals';
+import {MatCard, MatCardContent, MatCardHeader, MatCardTitle} from '@angular/material/card';
interface AddExpenseForm {
date: Date,
@@ -17,8 +17,11 @@ interface AddExpenseForm {
@Component({
selector: 'app-add-expense',
imports: [
- CardComponent,
- FormField
+ FormField,
+ MatCard,
+ MatCardHeader,
+ MatCardTitle,
+ MatCardContent
],
templateUrl: './add-expense.component.html',
styleUrl: './add-expense.component.scss',
diff --git a/src/app/components/card/card.component.html b/src/app/components/card/card.component.html
deleted file mode 100644
index 7826017..0000000
--- a/src/app/components/card/card.component.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
- @if (header()) {
-
- } @else {
-
- }
-
-
-
- @if (footer()) {
-
- } @else {
-
- }
-
diff --git a/src/app/components/card/card.component.scss b/src/app/components/card/card.component.scss
deleted file mode 100644
index 8256ece..0000000
--- a/src/app/components/card/card.component.scss
+++ /dev/null
@@ -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;
-}
diff --git a/src/app/components/card/card.component.ts b/src/app/components/card/card.component.ts
deleted file mode 100644
index 3e45981..0000000
--- a/src/app/components/card/card.component.ts
+++ /dev/null
@@ -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('');
- public footer = input('');
-}
diff --git a/src/app/components/expense-list/expense-list.component.html b/src/app/components/expense-list/expense-list.component.html
index c5fb02f..bed23d2 100644
--- a/src/app/components/expense-list/expense-list.component.html
+++ b/src/app/components/expense-list/expense-list.component.html
@@ -1,7 +1,34 @@
- @for (expense of expenses(); track expense.id) {
-
- }
+
+
+ Tracked Expenses
+
+
+
+
+
+ | Date |
+ {{ `${expense.year}/${expense.month}/${expense.day}` | date }} |
+
+
+
+ Amount |
+ {{ (expense.cents / 100) | currency: 'USD' }} |
+
+
+
+ Category |
+ {{ expense.category.name }} |
+
+
+
+ Merchant |
+ {{ expense.merchant?.name ?? '--' }} |
+
+
+
+
+
+
+
diff --git a/src/app/components/expense-list/expense-list.component.scss b/src/app/components/expense-list/expense-list.component.scss
index afbad75..e69de29 100644
--- a/src/app/components/expense-list/expense-list.component.scss
+++ b/src/app/components/expense-list/expense-list.component.scss
@@ -1,3 +0,0 @@
-.expense-item {
- padding-bottom: 1rem;
-}
diff --git a/src/app/components/expense-list/expense-list.component.ts b/src/app/components/expense-list/expense-list.component.ts
index 15cc613..5a7d57d 100644
--- a/src/app/components/expense-list/expense-list.component.ts
+++ b/src/app/components/expense-list/expense-list.component.ts
@@ -1,17 +1,43 @@
import { Component, computed } from '@angular/core';
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({
selector: 'app-expense-list',
imports: [
- ExpenseComponent
+ MatTable,
+ MatColumnDef,
+ MatHeaderCell,
+ MatHeaderCellDef,
+ DatePipe,
+ MatCell,
+ MatCellDef,
+ CurrencyPipe,
+ MatHeaderRow,
+ MatHeaderRowDef,
+ MatRow,
+ MatRowDef,
+ MatCard,
+ MatCardHeader,
+ MatCardTitle,
+ MatCardContent
],
templateUrl: './expense-list.component.html',
styleUrl: './expense-list.component.scss',
})
export class ExpenseListComponent {
protected expenses = computed(() => this.expensesService.expenses())
+ protected columns = ['date', 'amount', 'category', 'merchant'];
public constructor(private readonly expensesService: ExpenseService) { }
}
diff --git a/src/app/components/expense/expense.component.html b/src/app/components/expense/expense.component.html
deleted file mode 100644
index 45ab8ab..0000000
--- a/src/app/components/expense/expense.component.html
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
Merchant: {{ expense().merchant?.name ?? '--' }}
-
-
Category: {{ expense().category.name }}
-
-
Note: {{ expense().note ?? '--' }}
-
-
-
-
-
diff --git a/src/app/components/expense/expense.component.scss b/src/app/components/expense/expense.component.scss
deleted file mode 100644
index e27f306..0000000
--- a/src/app/components/expense/expense.component.scss
+++ /dev/null
@@ -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;
-}
diff --git a/src/app/components/expense/expense.component.ts b/src/app/components/expense/expense.component.ts
deleted file mode 100644
index 647ed96..0000000
--- a/src/app/components/expense/expense.component.ts
+++ /dev/null
@@ -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();
-}
diff --git a/src/index.html b/src/index.html
index 81d82d7..1da5b0f 100644
--- a/src/index.html
+++ b/src/index.html
@@ -6,6 +6,10 @@
+
+
+
+
diff --git a/src/styles.scss b/src/styles.scss
index 90d4ee0..cf6f56c 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -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 */