metadata-management #10

Merged
joe merged 18 commits from metadata-management into master 2026-02-26 18:35:33 +00:00
6 changed files with 98 additions and 31 deletions
Showing only changes of commit 4a84b70ed6 - Show all commits

View file

@ -48,13 +48,18 @@ export class ExpenseFormComponent implements OnInit {
private readonly merchantService: MerchantService,
private readonly tagService: TagService) {
effect(() => {
const form = this.form().value();
const valid = this.formValid();
const dirty = this.formDirty();
const value = this.form().value();
const value = {
...form,
merchant: Boolean(form.merchant) ? form.merchant : null,
note: Boolean(form.note) ? form.note : null
};
this.valid.emit(valid);
this.dirty.emit(dirty);
this.value.emit(value);
this.value.emit(value as ExpenseForm);
this.lastDate.set(value.date);
});
}
@ -98,8 +103,8 @@ export class ExpenseFormComponent implements OnInit {
date: new Date(year, month, day),
cents: expense.cents,
category: expense.category,
merchant: expense.merchant ?? {},
note: expense.note ?? '',
merchant: expense.merchant ?? null,
note: expense.note,
tags: expense.tags ?? []
} as ExpenseForm;
}

View file

@ -38,10 +38,10 @@ export class ExpenseComponent {
const postExpense: CreateExpense = {
date: this.dateToPlainDate(form.date),
cents: form.cents,
categoryId: form.category.id,
note: !!form.note ? form.note : undefined,
merchantId: !!form.merchant ? form.merchant.id : undefined,
tagIds: form.tags.map(tag => tag.id)
category: form.category,
merchant: form.merchant,
note: form.note,
tags: form.tags
};
this.savingExpense.set(true);
const snackId = this.snackBar.staticBar('Tracking new expense...');
@ -70,10 +70,10 @@ export class ExpenseComponent {
id: this.expense()!.id,
date: this.dateToPlainDate(form.date),
cents: form.cents,
categoryId: form.category.id,
note: !!form.note ? form.note : undefined,
merchantId: !!form.merchant ? form.merchant.id : undefined,
tagIds: form.tags.map(tag => tag.id)
category: form.category,
merchant: form.merchant,
note: form.note,
tags: form.tags
};
this.savingExpense.set(true);
const snackId = this.snackBar.staticBar('Updating expense...');

View file

@ -1,17 +1,44 @@
<div class="categories-container">
<div class="category-list-header">
<p>Categories</p>
<mat-form-field appearance="outline">
<mat-label>New Category</mat-label>
<input type="text" matInput [(ngModel)]="newCategory" [ngModelOptions]="{ standalone: true }">
@if (!!newCategory()) {
<button matSuffix matIconButton (click)="addClick()">
<mat-icon>add</mat-icon>
</button>
}
</mat-form-field>
<app-divider />
</div>
<div class="category-list">
@for (category of categories(); track category.id) {
<div>{{ category.name }}</div>
}
@if (!categories().length) {
<div class="category-list-empty">
No categories to display
</div>
}
<!-- <mat-list>-->
<!-- <mat-list-item>-->
<!-- <div class="category-item">-->
<!-- <mat-form-field appearance="outline">-->
<!-- <mat-label>New Category</mat-label>-->
<!-- <input type="text" matInput [(ngModel)]="newCategory">-->
<!-- <button matSuffix matIconButton (click)="addClick()">-->
<!-- <mat-icon>shopping_cart</mat-icon>-->
<!-- </button>-->
<!-- </mat-form-field>-->
<!-- </div>-->
<!-- </mat-list-item>-->
@for (category of categories(); track category.id) {
<!-- <mat-list-item>-->
{{ category.name }}
<!-- </mat-list-item>-->
}
@if (!categories().length) {
<!-- <mat-list-item>No categories to display</mat-list-item>-->
<!-- <div class="category-list-empty">-->
<!-- No categories to display-->
<!-- </div>-->
}
<!-- </mat-list>-->
</div>
</div>

View file

@ -21,8 +21,20 @@
}
}
.category-list {
display: grid;
gap: 1rem;
justify-content: center;
//.add-category {
// display: flex;
// align-items: baseline;
// gap: 0.5rem;
//}
//.category-list {
// display: grid;
// gap: 1rem;
// justify-content: center;
//}
.category-item {
padding: 1rem;
}
mat-form-field {
width: 400px;
}

View file

@ -1,11 +1,24 @@
import { Component, computed } from '@angular/core';
import {Component, computed, effect, model} from '@angular/core';
import { CategoryService } from '../../../services/category.service';
import { DividerComponent } from '../../divider/divider.component';
import {MatFormField, MatInput, MatLabel} from '@angular/material/input';
import {FormsModule} from '@angular/forms';
import {MatList, MatListItem} from '@angular/material/list';
import {MatIconButton} from '@angular/material/button';
import {MatIcon} from '@angular/material/icon';
@Component({
selector: 'app-categories',
imports: [
DividerComponent
DividerComponent,
MatInput,
MatFormField,
MatLabel,
FormsModule,
// MatList,
// MatListItem,
MatIconButton,
MatIcon
],
templateUrl: './categories.component.html',
styleUrl: './categories.component.scss'
@ -13,5 +26,15 @@ import { DividerComponent } from '../../divider/divider.component';
export class CategoriesComponent {
protected categories = computed(() => this.categoryService.categories());
public constructor(private readonly categoryService: CategoryService) { }
public newCategory = model<string>('');
public constructor(private readonly categoryService: CategoryService) {
effect(() => {
console.log(this.newCategory());
});
}
public addClick(): void {
console.log('add clicked');
}
}

View file

@ -38,18 +38,18 @@ export interface Expense {
date: Date;
cents: number;
category: Category;
note?: string;
merchant?: Merchant;
note?: string;
tags: Tag[];
}
export interface CreateExpense {
date: Temporal.PlainDate;
cents: number;
categoryId: string;
category: Category;
merchant?: Merchant;
note?: string;
merchantId?: string;
tagIds?: string[];
tags: Tag[];
}
export interface UpdateExpense extends CreateExpense {