WIP: Implement add transaction page
This commit is contained in:
parent
344ebbf31b
commit
d678eecddd
14 changed files with 199 additions and 23 deletions
|
@ -1,10 +1,14 @@
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
import { TransactionsComponent } from './transactions/transactions.component';
|
import { TransactionsComponent } from './transactions/transactions.component';
|
||||||
|
import { TransactionDetailsComponent } from './transaction-details/transaction-details.component';
|
||||||
|
import { NewTransactionComponent } from './new-transaction/new-transaction.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: '', redirectTo: '/transactions', pathMatch: 'full' },
|
{ path: '', redirectTo: '/transactions', pathMatch: 'full' },
|
||||||
{ path: 'transactions', component: TransactionsComponent },
|
{ path: 'transactions', component: TransactionsComponent },
|
||||||
|
{ path: 'transactions/new', component: NewTransactionComponent },
|
||||||
|
{ path: 'transactions/:id', component: TransactionDetailsComponent },
|
||||||
]
|
]
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|
|
@ -1,25 +1,44 @@
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
import { FormsModule } from '@angular/forms';
|
||||||
import {MatButtonModule, MatIconModule, MatListModule, MatToolbarModule} from '@angular/material';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
import {
|
||||||
|
MatButtonModule,
|
||||||
|
MatDatepickerModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatIconModule,
|
||||||
|
MatInputModule,
|
||||||
|
MatListModule,
|
||||||
|
MatRadioModule,
|
||||||
|
MatToolbarModule,
|
||||||
|
} from '@angular/material';
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { TransactionsComponent } from './transactions/transactions.component';
|
import { TransactionsComponent } from './transactions/transactions.component';
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
|
import { TransactionDetailsComponent } from './transaction-details/transaction-details.component';
|
||||||
|
import { NewTransactionComponent } from './new-transaction/new-transaction.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
TransactionsComponent
|
TransactionsComponent,
|
||||||
|
TransactionDetailsComponent,
|
||||||
|
NewTransactionComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatDatepickerModule,
|
||||||
MatIconModule,
|
MatIconModule,
|
||||||
|
MatInputModule,
|
||||||
MatListModule,
|
MatListModule,
|
||||||
|
MatRadioModule,
|
||||||
MatToolbarModule,
|
MatToolbarModule,
|
||||||
AppRoutingModule
|
AppRoutingModule,
|
||||||
|
FormsModule
|
||||||
],
|
],
|
||||||
providers: [],
|
providers: [],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
|
|
0
src/app/new-transaction/new-transaction.component.css
Normal file
0
src/app/new-transaction/new-transaction.component.css
Normal file
34
src/app/new-transaction/new-transaction.component.html
Normal file
34
src/app/new-transaction/new-transaction.component.html
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<mat-toolbar>
|
||||||
|
<span>
|
||||||
|
<button (click)="goBack()">
|
||||||
|
<mat-icon>arrow_back</mat-icon>
|
||||||
|
</button>
|
||||||
|
Add Transaction
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<a (click)="save()">Save</a>
|
||||||
|
</span>
|
||||||
|
</mat-toolbar>
|
||||||
|
<div class="transaction-form">
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput [(ngModel)]="transaction.title" placeholder="Name" required>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field>
|
||||||
|
<textarea matInput [(ngModel)]="transaction.description" placeholder="Description"></textarea>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput type="number" [(ngModel)]="transaction.amount" placeholder="Amount" required>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput type="date" [(ngModel)]="transaction.date" placeholder="Date" required>
|
||||||
|
<!--
|
||||||
|
<input matInput [matDatePicker]="transactionDatePicker" [(ngModel)]="transaction.date" placeholder="Date" required>
|
||||||
|
<mat-datepicker #transactionDatePicker></mat-datepicker>
|
||||||
|
-->
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-radio-group [(ngModel)]="transaction.type">
|
||||||
|
<mat-radio-button [value]="transactionType.EXPENSE">Expense</mat-radio-button>
|
||||||
|
<mat-radio-button [value]="transactionType.INCOME">Income</mat-radio-button>
|
||||||
|
</mat-radio-group>
|
||||||
|
|
||||||
|
</div>
|
25
src/app/new-transaction/new-transaction.component.spec.ts
Normal file
25
src/app/new-transaction/new-transaction.component.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { NewTransactionComponent } from './new-transaction.component';
|
||||||
|
|
||||||
|
describe('NewTransactionComponent', () => {
|
||||||
|
let component: NewTransactionComponent;
|
||||||
|
let fixture: ComponentFixture<NewTransactionComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ NewTransactionComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(NewTransactionComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
29
src/app/new-transaction/new-transaction.component.ts
Normal file
29
src/app/new-transaction/new-transaction.component.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { TransactionService } from '../transaction.service'
|
||||||
|
import { Transaction } from '../transaction'
|
||||||
|
import { TransactionType } from '../transaction.type'
|
||||||
|
import { Location } from '@angular/common';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-new-transaction',
|
||||||
|
templateUrl: './new-transaction.component.html',
|
||||||
|
styleUrls: ['./new-transaction.component.css']
|
||||||
|
})
|
||||||
|
export class NewTransactionComponent implements OnInit {
|
||||||
|
|
||||||
|
public transaction = new Transaction()
|
||||||
|
public transactionType = TransactionType;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private transactionService: TransactionService,
|
||||||
|
private location: Location
|
||||||
|
) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
save(): void {
|
||||||
|
this.transactionService.saveTransaction(this.transaction);
|
||||||
|
this.location.back()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
<div *ngIf="transaction; then transactionBlock else noTransactionBlock">
|
||||||
|
</div>
|
||||||
|
<ng-template #transactionBlock>
|
||||||
|
transaction-details works!
|
||||||
|
</ng-template>
|
||||||
|
<ng-template #noTransactionBlock>
|
||||||
|
transaction-details works!
|
||||||
|
</ng-template>
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TransactionDetailsComponent } from './transaction-details.component';
|
||||||
|
|
||||||
|
describe('TransactionDetailsComponent', () => {
|
||||||
|
let component: TransactionDetailsComponent;
|
||||||
|
let fixture: ComponentFixture<TransactionDetailsComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ TransactionDetailsComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(TransactionDetailsComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
18
src/app/transaction-details/transaction-details.component.ts
Normal file
18
src/app/transaction-details/transaction-details.component.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { Transaction } from '../transaction'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-transaction-details',
|
||||||
|
templateUrl: './transaction-details.component.html',
|
||||||
|
styleUrls: ['./transaction-details.component.css']
|
||||||
|
})
|
||||||
|
export class TransactionDetailsComponent implements OnInit {
|
||||||
|
|
||||||
|
public transaction: Transaction;
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,21 +7,35 @@ import { TransactionType } from './transaction.type';
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class TransactionService {
|
export class TransactionService {
|
||||||
|
transactions: Transaction[] = [
|
||||||
|
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Spent some money", title: "An Expense", type: TransactionType.EXPENSE, categoryId: 0},
|
||||||
|
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Earned some money", title: "Some Income", type: TransactionType.INCOME, categoryId: 0},
|
||||||
|
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Spent some money", title: "An Expense", type: TransactionType.EXPENSE, categoryId: 0},
|
||||||
|
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Earned some money", title: "Some Income", type: TransactionType.INCOME, categoryId: 0},
|
||||||
|
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Spent some money", title: "An Expense", type: TransactionType.EXPENSE, categoryId: 0},
|
||||||
|
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Earned some money", title: "Some Income", type: TransactionType.INCOME, categoryId: 0},
|
||||||
|
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Spent some money", title: "An Expense", type: TransactionType.EXPENSE, categoryId: 0},
|
||||||
|
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Earned some money", title: "Some Income", type: TransactionType.INCOME, categoryId: 0},
|
||||||
|
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Spent some money", title: "An Expense", type: TransactionType.EXPENSE, categoryId: 0},
|
||||||
|
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Earned some money", title: "Some Income", type: TransactionType.INCOME, categoryId: 0},
|
||||||
|
]
|
||||||
|
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
getTransactions(): Observable<Transaction[]> {
|
getTransactions(): Observable<Transaction[]> {
|
||||||
return of([
|
return of(this.transactions)
|
||||||
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Spent some money", title: "An Expense", type: TransactionType.EXPENSE, categoryId: 0},
|
}
|
||||||
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Earned some money", title: "Some Income", type: TransactionType.INCOME, categoryId: 0},
|
|
||||||
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Spent some money", title: "An Expense", type: TransactionType.EXPENSE, categoryId: 0},
|
saveTransaction(transaction: Transaction): Observable<Transaction> {
|
||||||
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Earned some money", title: "Some Income", type: TransactionType.INCOME, categoryId: 0},
|
// TODO: Replace this with a DB save method
|
||||||
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Spent some money", title: "An Expense", type: TransactionType.EXPENSE, categoryId: 0},
|
var newId = 0;
|
||||||
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Earned some money", title: "Some Income", type: TransactionType.INCOME, categoryId: 0},
|
for (let transaction of this.transactions) {
|
||||||
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Spent some money", title: "An Expense", type: TransactionType.EXPENSE, categoryId: 0},
|
if (transaction.id > newId) {
|
||||||
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Earned some money", title: "Some Income", type: TransactionType.INCOME, categoryId: 0},
|
newId = transaction.id + 1;
|
||||||
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Spent some money", title: "An Expense", type: TransactionType.EXPENSE, categoryId: 0},
|
}
|
||||||
{id: 0, amount: Math.random() * 100, date: new Date(), description: "Earned some money", title: "Some Income", type: TransactionType.INCOME, categoryId: 0},
|
}
|
||||||
])
|
transaction.id = newId;
|
||||||
|
this.transactions.push(transaction)
|
||||||
|
return of(transaction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ export class Transaction {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
amount: number;
|
amount: number;
|
||||||
date: Date;
|
date: Date = new Date();
|
||||||
categoryId: number;
|
categoryId: number;
|
||||||
type: TransactionType;
|
type: TransactionType = TransactionType.EXPENSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,8 @@ p {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.mat-fab {
|
a.mat-fab {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 2em;
|
right: 2em;
|
||||||
bottom: 2em;
|
bottom: 2em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,6 @@
|
||||||
<p matLine class="text-small">{{ transaction.date | date }}</p>
|
<p matLine class="text-small">{{ transaction.date | date }}</p>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
</mat-list>
|
</mat-list>
|
||||||
<button mat-fab>
|
<a mat-fab routerLink="/transactions/new">
|
||||||
<mat-icon aria-label="Add">add</mat-icon>
|
<mat-icon aria-label="Add">add</mat-icon>
|
||||||
</button>
|
</a>
|
||||||
|
|
Loading…
Reference in a new issue