-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added chart data remove the clutter used html5 datetime fixed the date padding and current date
- Loading branch information
technbuzz
committed
Aug 1, 2022
1 parent
b774d4c
commit e7adad2
Showing
7 changed files
with
252 additions
and
124 deletions.
There are no files selected for viewing
24 changes: 24 additions & 0 deletions
24
apps/kharchay/src/app/summary/doughnut/doughnut.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||
|
||
import { DoughnutComponent } from './doughnut.component'; | ||
|
||
describe('DoughnutComponent', () => { | ||
let component: DoughnutComponent; | ||
let fixture: ComponentFixture<DoughnutComponent>; | ||
|
||
beforeEach(async () => { | ||
await TestBed.configureTestingModule({ | ||
declarations: [DoughnutComponent], | ||
}).compileComponents(); | ||
}); | ||
|
||
beforeEach(() => { | ||
fixture = TestBed.createComponent(DoughnutComponent); | ||
component = fixture.componentInstance; | ||
fixture.detectChanges(); | ||
}); | ||
|
||
it('should create', () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
}); |
101 changes: 101 additions & 0 deletions
101
apps/kharchay/src/app/summary/doughnut/doughnut.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core'; | ||
import { ArcElement, Chart, Legend, PieController, Tooltip } from 'chart.js'; | ||
|
||
@Component({ | ||
selector: 'kh-doughnut', | ||
template: ` | ||
<div class="wrapper"> | ||
<canvas #container width="400" height="400"></canvas> | ||
</div> | ||
` | ||
}) | ||
export class DoughnutComponent implements OnInit, AfterViewInit { | ||
@Input() set chartData(data: number[]) { | ||
this.updateData(this.chart, data) | ||
} | ||
|
||
@Input() set chartLabel(label: string[]) { | ||
this.updateLabels(this.chart, label) | ||
} | ||
|
||
|
||
@ViewChild('container') container!: ElementRef<HTMLCanvasElement>; | ||
chart!: Chart; | ||
|
||
ngOnInit(): void {} | ||
|
||
ngAfterViewInit(): void { | ||
Chart.register(PieController, ArcElement, Legend, Tooltip); | ||
this.chart = new Chart(this.container.nativeElement, { | ||
type: 'doughnut', | ||
data: { | ||
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'], | ||
datasets: [ | ||
{ | ||
label: '# of Votes', | ||
hoverOffset: 4, | ||
data: [12, 19, 3, 5, 2, 3], | ||
backgroundColor: [ | ||
'tomato', | ||
'#FF9020', | ||
'#059BFF', | ||
'rebeccapurple', | ||
'gold', | ||
'#FF6384', | ||
'indigo', | ||
'#FFC234', | ||
] | ||
}, | ||
], | ||
}, | ||
options: { | ||
layout: { | ||
padding: 10, | ||
}, | ||
plugins: { | ||
legend: { | ||
display: true, | ||
position: 'bottom' | ||
} | ||
} | ||
} | ||
}); | ||
|
||
} | ||
|
||
updateLabels(chart: Chart, label: string[]) { | ||
if(!chart) return; | ||
chart.data.labels = []; | ||
chart.data.labels = [...label] | ||
chart.update(); | ||
} | ||
|
||
updateData(chart: Chart, data:number[]) { | ||
if(!chart) return; | ||
chart.data.datasets.forEach((dataset) => { | ||
dataset.data == []; | ||
}); | ||
chart.data.datasets.forEach((dataset) => { | ||
dataset.data = [...data]; | ||
}); | ||
chart.update(); | ||
|
||
} | ||
|
||
addData(chart: Chart, label: string[], data: number[]) { | ||
chart.data.labels = [...label] | ||
chart.data.datasets.forEach((dataset) => { | ||
dataset.data = [...data]; | ||
}); | ||
chart.update(); | ||
} | ||
|
||
removeData(chart: Chart) { | ||
chart.data.labels = []; | ||
chart.data.datasets.forEach((dataset) => { | ||
dataset.data == []; | ||
}); | ||
chart.update(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,114 +1,113 @@ | ||
import { Component, OnInit, ViewChild, ViewContainerRef, ComponentFactoryResolver, AfterViewInit } from '@angular/core'; | ||
import { Stepper } from '../shared/stepper'; | ||
import { | ||
AfterViewInit, | ||
Component, ElementRef, OnInit, | ||
ViewChild | ||
} from '@angular/core'; | ||
import { collection, Firestore } from '@angular/fire/firestore'; | ||
import { Observable } from 'rxjs'; | ||
import { BaseExpense } from '../home/expense-base.model'; | ||
import { fromEvent, Observable } from 'rxjs'; | ||
import { Stepper } from '../shared/stepper'; | ||
|
||
import { | ||
DocumentData, | ||
query, | ||
where | ||
} from '@firebase/firestore'; | ||
import endOfMonth from 'date-fns/esm/endOfMonth'; | ||
import startOfMonth from 'date-fns/esm/startOfMonth'; | ||
|
||
// import { groupBy, forIn, reduce } from 'lodash'; | ||
import forIn from 'lodash-es/forIn'; | ||
import groupBy from 'lodash-es/groupBy'; | ||
import forIn from 'lodash-es/forIn'; | ||
import reduce from 'lodash-es/reduce'; | ||
import startOfMonth from 'date-fns/esm/startOfMonth'; | ||
import endOfMonth from 'date-fns/esm/endOfMonth'; | ||
import { GestureController, IonDatetime } from '@ionic/angular'; | ||
import { collectionData } from 'rxfire/firestore'; | ||
import { CollectionReference, DocumentData, query, where } from '@firebase/firestore'; | ||
import { map, switchMap } from 'rxjs/operators'; | ||
import format from 'date-fns/esm/format' | ||
|
||
|
||
@Component({ | ||
selector: 'app-summary', | ||
templateUrl: './summary.page.html', | ||
styleUrls: ['./summary.page.scss'], | ||
}) | ||
export class SummaryPage extends Stepper implements OnInit, AfterViewInit { | ||
@ViewChild('container', { read: ViewContainerRef, static: true }) | ||
container!: ViewContainerRef; | ||
export class SummaryPage extends Stepper implements AfterViewInit { | ||
@ViewChild('dateItem') dateItem: any; | ||
@ViewChild('expenseMonth', { static: true }) | ||
expenseMonth!: IonDatetime; | ||
@ViewChild('expenseDate', { static: true }) | ||
expenseDate!: ElementRef<HTMLInputElement>; | ||
|
||
chartData: number[] = []; | ||
chartLabels: string[] = []; | ||
|
||
month = new Date().toISOString(); | ||
loading = true; | ||
month = format(new Date(), 'yyyy-MM') | ||
// month = new Date().toISOString(); | ||
total = 0; | ||
expRef!: CollectionReference<any>; | ||
|
||
expenses$!: Observable<DocumentData[]>; | ||
constructor( | ||
private afs: Firestore, | ||
private gestureCtrl: GestureController | ||
) { | ||
private expensesRef = collection(this.afs, 'expense'); | ||
constructor(private afs: Firestore) { | ||
super(); | ||
} | ||
|
||
ngOnInit() { | ||
this.loadBasic(); | ||
} | ||
|
||
|
||
ngAfterViewInit() { | ||
const gesture = this.gestureCtrl.create({ | ||
el: this.dateItem.el, | ||
gestureName: 'move', | ||
onEnd: detail => { | ||
const type = detail.type; | ||
const currentX = detail.currentX; | ||
const deltaX = detail.deltaX; | ||
const velocityX = detail.velocityX; | ||
if (deltaX > 0) { | ||
// this.addMonth(this.month, this.expenseMonth); | ||
} else { | ||
// this.subMonth(this.month, this.expenseMonth); | ||
} | ||
} | ||
}); | ||
console.log('month', format(new Date(), 'yyyy-MM')) | ||
fromEvent(this.expenseDate.nativeElement, 'change').pipe( | ||
map(( value: any ) => value.currentTarget.value), | ||
map(value => { | ||
const start = startOfMonth(new Date(value)); | ||
const end = endOfMonth(new Date(this.month)); | ||
return { start, end } | ||
}), | ||
map(value => this.buildQuery(value)), | ||
switchMap(value => collectionData(value)) | ||
).subscribe((event) => { | ||
// | ||
this.generateDataForChart(event) | ||
}) | ||
} | ||
|
||
gesture.enable(); | ||
private buildQuery(value: {start: Date, end: Date}) { | ||
const expensesQuery = query( | ||
this.expensesRef, | ||
where('date', '>=', value.start), | ||
where('date', '<=', value.end) | ||
); | ||
// 8001717, | ||
return expensesQuery | ||
} | ||
|
||
|
||
loadBasic() { | ||
const basicStartMonth = startOfMonth(new Date(this.month)); | ||
const basicEndMonth = endOfMonth(new Date(this.month)); | ||
|
||
this.loading = true; | ||
const expensesRef = collection(this.afs, 'expense'); | ||
const expensesQuery = query(expensesRef, where('date', '>=', basicStartMonth),where('date', '<=', basicEndMonth)); | ||
|
||
// this.expRef = collection(this.afs, 'expense', ref => | ||
// ref | ||
// .where('date', '>=', basicStartMonth) | ||
// .where('date', '<=', basicEndMonth) | ||
// ); | ||
const expensesQuery = query( | ||
this.expensesRef, | ||
where('date', '>=', basicStartMonth), | ||
where('date', '<=', basicEndMonth) | ||
); | ||
|
||
// Finding Total | ||
this.expenses$ = collectionData(expensesQuery); | ||
// this.expenses$ = this.expRef.valueChanges(); | ||
this.expenses$.forEach(values => { | ||
this.expenses$.forEach((values) => { | ||
this.generateDataForChart(values); | ||
}); | ||
} | ||
|
||
generateDataForChart(values: any) { | ||
|
||
this.chartData = []; | ||
this.chartLabels = []; | ||
|
||
|
||
// Previously for format like {category:'food'} | ||
// grouped = lodash.groupBy(values, ('category.title')); | ||
|
||
// FIXME: Replace lodash with groupBy rxjs function | ||
// Backward compat becuse new format is {category:{title:'food'}} | ||
const grouped = groupBy(values, (item) => item.category.title ? item.category.title : item.category); | ||
const grouped = groupBy(values, (item) => | ||
item.category.title ? item.category.title : item.category | ||
); | ||
|
||
forIn(grouped, (value, key, item) => { | ||
this.chartLabels.push(key.toUpperCase()); | ||
this.chartData.push(reduce( | ||
value, (sum, n) => sum + Number(n.price), 0) | ||
); | ||
this.chartData.push(reduce(value, (sum, n) => sum + Number(n.price), 0)); | ||
}); | ||
|
||
} | ||
|
||
} |
Oops, something went wrong.