Consolidated commit message to v22 signals
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { CurrencyPipe, DecimalPipe } from '@angular/common';
|
||||
import { Component, ElementRef, HostListener, inject, OnInit, ViewChild } from '@angular/core';
|
||||
import { FormArray, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
|
||||
import { signal, Component, HostListener, inject, input, computed, linkedSignal } from '@angular/core';
|
||||
import { form as createForm, FormField, FormRoot } from '@angular/forms/signals';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
@@ -9,10 +9,8 @@ import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { Router } from '@angular/router';
|
||||
import moment from 'moment';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { AuthService } from '../auth/auth.service';
|
||||
import { Account } from '../core/account';
|
||||
@@ -23,14 +21,19 @@ import { Voucher } from '../core/voucher';
|
||||
import { VoucherService } from '../core/voucher.service';
|
||||
import { ConfirmDialogComponent } from '../shared/confirm-dialog/confirm-dialog.component';
|
||||
import { LocalTimePipe } from '../shared/local-time.pipe';
|
||||
import { IncentiveDataSource } from './incentive-datasource';
|
||||
|
||||
export interface IncentiveFormData {
|
||||
date: moment.Moment;
|
||||
incentives: { points: number }[];
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-incentive',
|
||||
templateUrl: './incentive.component.html',
|
||||
styleUrls: ['./incentive.component.css'],
|
||||
imports: [
|
||||
ReactiveFormsModule,
|
||||
FormField,
|
||||
FormRoot,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatDatepickerModule,
|
||||
@@ -42,27 +45,31 @@ import { IncentiveDataSource } from './incentive-datasource';
|
||||
LocalTimePipe,
|
||||
],
|
||||
})
|
||||
export class IncentiveComponent implements OnInit {
|
||||
private route = inject(ActivatedRoute);
|
||||
export class IncentiveComponent {
|
||||
id = input(null, { transform: (v: string | null | undefined) => v ?? null });
|
||||
|
||||
private router = inject(Router);
|
||||
private dialog = inject(MatDialog);
|
||||
private snackBar = inject(MatSnackBar);
|
||||
auth = inject(AuthService);
|
||||
private ser = inject(VoucherService);
|
||||
|
||||
@ViewChild('dateElement', { static: true }) dateElement!: ElementRef<HTMLInputElement>;
|
||||
public incentiveObservable = new BehaviorSubject<Incentive[]>([]);
|
||||
dataSource: IncentiveDataSource = new IncentiveDataSource(this.incentiveObservable);
|
||||
form: FormGroup<{
|
||||
date: FormControl<moment.Moment>;
|
||||
incentives: FormArray<
|
||||
FormGroup<{
|
||||
points: FormControl<number>;
|
||||
}>
|
||||
>;
|
||||
}>;
|
||||
voucherResource = this.ser.getVoucher(this.id, signal('Incentive'), signal(null), signal(null));
|
||||
|
||||
voucher = computed(() => this.voucherResource.value() ?? new Voucher());
|
||||
|
||||
model = linkedSignal({
|
||||
source: this.voucher,
|
||||
computation: (v): IncentiveFormData => ({
|
||||
date: moment(v.date, 'DD-MMM-YYYY'),
|
||||
incentives: v.incentives.map((x) => ({ points: x.points })),
|
||||
}),
|
||||
});
|
||||
|
||||
form = createForm(this.model);
|
||||
|
||||
incentives = linkedSignal(() => this.voucher().incentives);
|
||||
|
||||
voucher: Voucher = new Voucher();
|
||||
account: Account = new Account();
|
||||
accBal: AccountBalance | null = null;
|
||||
|
||||
@@ -71,98 +78,68 @@ export class IncentiveComponent implements OnInit {
|
||||
@HostListener('window:keydown.f2', ['$event'])
|
||||
focusDate(event: Event) {
|
||||
event.preventDefault();
|
||||
this.dateElement.nativeElement.focus();
|
||||
this.dateElement.nativeElement.select();
|
||||
this.form().focusBoundControl();
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.form = new FormGroup({
|
||||
date: new FormControl(moment(new Date()), { nonNullable: true }),
|
||||
incentives: new FormArray<FormGroup<{ points: FormControl<number> }>>([]),
|
||||
});
|
||||
// Listen to Date Change
|
||||
this.form.controls.date.valueChanges.pipe(map((x) => moment(x).format('DD-MMM-YYYY'))).subscribe((x) => {
|
||||
if (x !== this.voucher.date && !this.voucher.id) {
|
||||
return this.ser.getIncentive(x).subscribe((voucher: Voucher) => {
|
||||
this.loadVoucher(voucher);
|
||||
});
|
||||
}
|
||||
return '';
|
||||
});
|
||||
}
|
||||
totalPoints = computed(() => {
|
||||
return this.incentives()
|
||||
.map((item: Incentive, i: number) => item.daysWorked * (this.model().incentives[i]?.points ?? 0))
|
||||
.reduce((sum: number, item: number) => sum + item, 0);
|
||||
});
|
||||
|
||||
ngOnInit() {
|
||||
this.route.data.subscribe((value) => {
|
||||
const data = value as { voucher: Voucher };
|
||||
pointValue = computed(() => {
|
||||
const tp = this.totalPoints();
|
||||
if (!tp) return 0;
|
||||
return Math.round(((this.voucher().incentive as number) * 100) / tp) / 100;
|
||||
});
|
||||
|
||||
this.loadVoucher(data.voucher);
|
||||
});
|
||||
}
|
||||
|
||||
loadVoucher(voucher: Voucher) {
|
||||
this.voucher = voucher;
|
||||
this.form.controls.date.setValue(moment(this.voucher.date, 'DD-MMM-YYYY'));
|
||||
this.form.controls.incentives.clear();
|
||||
this.voucher.incentives.forEach((x) =>
|
||||
this.form.controls.incentives.push(
|
||||
new FormGroup({
|
||||
points: new FormControl(x.points, { nonNullable: true }),
|
||||
}),
|
||||
),
|
||||
);
|
||||
this.dataSource = new IncentiveDataSource(this.incentiveObservable);
|
||||
this.incentiveObservable.next(this.voucher.incentives);
|
||||
}
|
||||
|
||||
totalPoints() {
|
||||
return this.voucher.incentives.map((item) => item.daysWorked * item.points).reduce((sum, item) => sum + item);
|
||||
}
|
||||
|
||||
pointValue() {
|
||||
return Math.round(((this.voucher.incentive as number) * 100) / this.totalPoints()) / 100;
|
||||
}
|
||||
|
||||
less(row: Incentive, i: number) {
|
||||
if (row.points >= 1) {
|
||||
row.points -= 1;
|
||||
this.form.controls.incentives.controls[i].setValue({
|
||||
points: row.points,
|
||||
less(i: number) {
|
||||
const currentPoints = this.model().incentives[i]?.points ?? 0;
|
||||
if (currentPoints >= 1) {
|
||||
this.model.update((m) => {
|
||||
const arr = [...m.incentives];
|
||||
if (arr[i]) {
|
||||
arr[i] = { ...arr[i], points: currentPoints - 1 };
|
||||
}
|
||||
return { ...m, incentives: arr };
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
change(row: Incentive, i: number) {
|
||||
row.points = this.form.controls.incentives.controls[i].value.points ?? 0;
|
||||
this.form.controls.incentives.controls[i].setValue({ points: row.points });
|
||||
more(i: number) {
|
||||
const currentPoints = this.model().incentives[i]?.points ?? 0;
|
||||
this.model.update((m) => {
|
||||
const arr = [...m.incentives];
|
||||
if (arr[i]) {
|
||||
arr[i] = { ...arr[i], points: currentPoints + 1 };
|
||||
}
|
||||
return { ...m, incentives: arr };
|
||||
});
|
||||
}
|
||||
|
||||
more(row: Incentive, i: number) {
|
||||
row.points += 1;
|
||||
this.form.controls.incentives.controls[i].setValue({ points: row.points });
|
||||
}
|
||||
|
||||
amount(row: Incentive) {
|
||||
return row.points * row.daysWorked * this.pointValue();
|
||||
amount(row: Incentive, i: number) {
|
||||
const currentPoints = this.model().incentives[i]?.points ?? 0;
|
||||
return currentPoints * row.daysWorked * this.pointValue();
|
||||
}
|
||||
|
||||
canSave() {
|
||||
if (!this.voucher.id) {
|
||||
if (!this.voucher().id) {
|
||||
return true;
|
||||
}
|
||||
if (this.voucher.posted && this.auth.allowed('edit-posted-vouchers')) {
|
||||
if (this.voucher().posted && this.auth.allowed('edit-posted-vouchers')) {
|
||||
return true;
|
||||
}
|
||||
return this.voucher.user.id === (this.auth.user as User).id || this.auth.allowed("edit-other-user's-vouchers");
|
||||
return this.voucher().user.id === (this.auth.user as User).id || this.auth.allowed("edit-other-user's-vouchers");
|
||||
}
|
||||
|
||||
post() {
|
||||
this.ser.post(this.voucher.id as string).subscribe({
|
||||
next: (result) => {
|
||||
this.loadVoucher(result);
|
||||
this.ser.post(this.voucher().id as string).subscribe({
|
||||
next: (result: Voucher) => {
|
||||
this.snackBar.open('Voucher Posted', 'Success');
|
||||
this.router.navigate(['/incentive', (result as Voucher).id], { replaceUrl: true });
|
||||
},
|
||||
error: (error) => {
|
||||
this.snackBar.open(error, 'Danger');
|
||||
this.snackBar.open(error as string, 'Danger');
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -170,38 +147,35 @@ export class IncentiveComponent implements OnInit {
|
||||
save() {
|
||||
const voucher: Voucher = this.getVoucher();
|
||||
this.ser.saveOrUpdate(voucher).subscribe({
|
||||
next: (result) => {
|
||||
if (voucher.id === result.id) {
|
||||
this.loadVoucher(result);
|
||||
} else {
|
||||
this.router.navigate(['/incentive', result.id]);
|
||||
}
|
||||
next: (result: Voucher) => {
|
||||
this.router.navigate(['/incentive', (result as Voucher).id], { replaceUrl: true });
|
||||
},
|
||||
error: (error) => {
|
||||
this.snackBar.open(error, 'Danger');
|
||||
this.snackBar.open(error as string, 'Danger');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getVoucher(): Voucher {
|
||||
const formModel = this.form.value;
|
||||
this.voucher.date = moment(formModel.date).format('DD-MMM-YYYY');
|
||||
const array = this.form.controls.incentives;
|
||||
const formModel = this.model();
|
||||
const v = this.voucher();
|
||||
v.date = formModel.date.format('DD-MMM-YYYY');
|
||||
const array = formModel.incentives;
|
||||
|
||||
this.voucher.incentives.forEach((item, index) => {
|
||||
item.points = array.controls[index].value.points ?? 0;
|
||||
v.incentives.forEach((item: Incentive, index: number) => {
|
||||
item.points = array[index]?.points ?? 0;
|
||||
});
|
||||
return this.voucher;
|
||||
return v;
|
||||
}
|
||||
|
||||
delete() {
|
||||
this.ser.delete(this.voucher.id as string).subscribe({
|
||||
this.ser.delete(this.voucher().id as string).subscribe({
|
||||
next: () => {
|
||||
this.snackBar.open('', 'Success');
|
||||
this.router.navigate(['/incentive'], { replaceUrl: true });
|
||||
},
|
||||
error: (error) => {
|
||||
this.snackBar.open(error, 'Danger');
|
||||
this.snackBar.open(error as string, 'Danger');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user