updated merchant tab

This commit is contained in:
Joe Arndt 2026-02-26 12:24:47 -06:00
parent 248ded53c0
commit 3d0d63b1d4
9 changed files with 75 additions and 51 deletions

View file

@ -46,8 +46,8 @@ export class ExpenseComponent {
this.savingExpense.set(true); this.savingExpense.set(true);
const snackId = this.snackBar.staticBar('Tracking new expense...'); const snackId = this.snackBar.staticBar('Tracking new expense...');
try { try {
await this.expenseService.postExpense(postExpense); await this.expenseService.create(postExpense);
await this.expenseService.fetchExpenses(); await this.expenseService.fetch();
this.resetForm(); this.resetForm();
this.snackBar.dismiss(snackId); this.snackBar.dismiss(snackId);
this.snackBar.autoBar('Expense tracked!'); this.snackBar.autoBar('Expense tracked!');
@ -79,7 +79,7 @@ export class ExpenseComponent {
this.savingExpense.set(true); this.savingExpense.set(true);
const snackId = this.snackBar.staticBar('Updating expense...'); const snackId = this.snackBar.staticBar('Updating expense...');
try { try {
const expense = await this.expenseService.updateExpense(putExpense); const expense = await this.expenseService.update(putExpense);
this.expense.set(expense); this.expense.set(expense);
this.form()?.refresh(expense); this.form()?.refresh(expense);
this.editingExpense.set(false); this.editingExpense.set(false);

View file

@ -18,12 +18,12 @@ export class CategoriesComponent {
public constructor(private readonly categoryService: CategoryService) { } public constructor(private readonly categoryService: CategoryService) { }
public async createCategory(name: string): Promise<void> { public async createCategory(name: string): Promise<void> {
await this.categoryService.createCategory({ name }); await this.categoryService.create({ name });
await this.categoryService.fetchCategories(); await this.categoryService.fetch();
} }
public async updateCategory(category: Category): Promise<void> { public async updateCategory(category: Category): Promise<void> {
await this.categoryService.updateCategory(category); await this.categoryService.update(category);
await this.categoryService.fetchCategories(); await this.categoryService.fetch();
} }
} }

View file

@ -1,17 +1,24 @@
<div class="merchants-container"> <div class="merchants-container">
<div class="merchant-list-header"> <mat-card appearance="outlined">
<p>Merchants</p> <mat-card-header>
<app-divider /> <mat-card-title>Merchants</mat-card-title>
</div> </mat-card-header>
<div class="merchant-list"> <mat-card-content>
@for (merchant of merchants(); track merchant.id) { <div class="new-merchant">
<div>{{ merchant.name }}</div> <app-metadata-form (newMetaData)="createMerchant($event.name)" [editing]="true" [label]="'New Merchant'"/>
}
@if (!merchants().length) {
<div class="merchant-list-empty">
No merchants to display
</div> </div>
}
</div> <div class="merchant-list">
@for (merchant of merchants(); track merchant.id) {
<app-metadata-form [metadata]="merchant" (newMetaData)="updateMerchant($event)" />
}
@if (!merchants().length) {
<div>
No merchants to display
</div>
}
</div>
</mat-card-content>
</mat-card>
</div> </div>

View file

@ -1,28 +1,21 @@
.merchants-container { @use "variables";
display: grid;
gap: 1rem;
}
.merchant-list-header { .merchants-container {
padding-top: 1rem; padding-top: 0.5rem;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
p { mat-card {
font-size: 1.8rem; max-width: variables.$wide-screen;
line-height: 100%;
font-weight: 400;
margin: 0;
}
app-divider {
width: 100%; width: 100%;
} }
} }
.new-merchant {
padding-top: 0.5rem;
}
.merchant-list { .merchant-list {
display: grid; display: grid;
gap: 1rem;
justify-content: center;
} }

View file

@ -1,11 +1,13 @@
import { Component, computed } from '@angular/core'; import { Component, computed } from '@angular/core';
import { MerchantService } from '../../../services/merchant.service'; import { Merchant, MerchantService } from '../../../services/merchant.service';
import { DividerComponent } from '../../divider/divider.component'; import { MatCardModule } from '@angular/material/card';
import { MetadataFormComponent } from '../metadata-form/metadata-form.component';
@Component({ @Component({
selector: 'app-merchants', selector: 'app-merchants',
imports: [ imports: [
DividerComponent MatCardModule,
MetadataFormComponent
], ],
templateUrl: './merchants.component.html', templateUrl: './merchants.component.html',
styleUrl: './merchants.component.scss' styleUrl: './merchants.component.scss'
@ -14,4 +16,14 @@ export class MerchantsComponent {
protected merchants = computed(() => this.merchantService.merchants()); protected merchants = computed(() => this.merchantService.merchants());
public constructor(private readonly merchantService: MerchantService) { } public constructor(private readonly merchantService: MerchantService) { }
public async createMerchant(name: string): Promise<void> {
await this.merchantService.create({ name });
await this.merchantService.fetch();
}
public async updateMerchant(merchant: Merchant): Promise<void> {
await this.merchantService.update(merchant);
await this.merchantService.fetch();
}
} }

View file

@ -10,18 +10,18 @@ export class CategoryService {
public readonly categoryPath = 'http://localhost:3000/common-cents/categories'; public readonly categoryPath = 'http://localhost:3000/common-cents/categories';
public constructor(private readonly http: HttpService) { public constructor(private readonly http: HttpService) {
void this.fetchCategories(); void this.fetch();
} }
public async fetchCategories(): Promise<void> { public async fetch(): Promise<void> {
this.internalCategories.set(await this.http.get<Category[]>(this.categoryPath)); this.internalCategories.set(await this.http.get<Category[]>(this.categoryPath));
} }
public async createCategory(category: CreateCategory): Promise<Category> { public async create(category: CreateCategory): Promise<Category> {
return await this.http.post<Category>(this.categoryPath, category); return await this.http.post<Category>(this.categoryPath, category);
} }
public async updateCategory(category: Category): Promise<Category> { public async update(category: Category): Promise<Category> {
return await this.http.put<Category>(this.categoryPath, category); return await this.http.put<Category>(this.categoryPath, category);
} }
} }

View file

@ -14,18 +14,18 @@ export class ExpenseService {
public readonly expensePath = 'http://localhost:3000/common-cents/expenses'; // TODO: refactor public readonly expensePath = 'http://localhost:3000/common-cents/expenses'; // TODO: refactor
public constructor(private readonly http: HttpService) { public constructor(private readonly http: HttpService) {
void this.fetchExpenses(); void this.fetch();
} }
public async fetchExpenses(): Promise<void> { public async fetch(): Promise<void> {
this.internalExpenses.set(await this.http.get(this.expensePath)); this.internalExpenses.set(await this.http.get(this.expensePath));
} }
public async postExpense(createExpense: CreateExpense): Promise<Expense> { public async create(createExpense: CreateExpense): Promise<Expense> {
return await this.http.post<Expense>(this.expensePath, createExpense); return await this.http.post<Expense>(this.expensePath, createExpense);
} }
public async updateExpense(updateExpense: UpdateExpense): Promise<Expense> { public async update(updateExpense: UpdateExpense): Promise<Expense> {
return await this.http.put<Expense>(this.expensePath, updateExpense); return await this.http.put<Expense>(this.expensePath, updateExpense);
} }
} }

View file

@ -10,15 +10,27 @@ export class MerchantService {
public readonly merchantPath = 'http://localhost:3000/common-cents/merchants'; public readonly merchantPath = 'http://localhost:3000/common-cents/merchants';
public constructor(private readonly http: HttpService) { public constructor(private readonly http: HttpService) {
void this.fetchMerchants(); void this.fetch();
} }
public async fetchMerchants(): Promise<void> { public async fetch(): Promise<void> {
this.internalMerchants.set(await this.http.get<Merchant[]>(this.merchantPath)); this.internalMerchants.set(await this.http.get<Merchant[]>(this.merchantPath));
} }
public async create(merchant: CreateMerchant): Promise<Merchant> {
return await this.http.post<Merchant>(this.merchantPath, merchant);
}
public async update(merchant: Merchant): Promise<Merchant> {
return await this.http.put<Merchant>(this.merchantPath, merchant);
}
} }
export interface Merchant { export interface Merchant {
id: string; id: string;
name: string; name: string;
} }
export interface CreateMerchant {
name: string;
}

View file

@ -10,10 +10,10 @@ export class TagService {
public readonly tagPath = 'http://localhost:3000/common-cents/tags'; public readonly tagPath = 'http://localhost:3000/common-cents/tags';
public constructor(private readonly http: HttpService) { public constructor(private readonly http: HttpService) {
void this.fetchTags(); void this.fetch();
} }
public async fetchTags(): Promise<void> { public async fetch(): Promise<void> {
this.internalTags.set(await this.http.get<Tag[]>(this.tagPath)); this.internalTags.set(await this.http.get<Tag[]>(this.tagPath));
} }
} }