toSignal via Gemini

This commit is contained in:
2026-08-18 07:55:54 +00:00
parent 59eb45da96
commit 993f83c786
350 changed files with 6231 additions and 9801 deletions
@@ -1,6 +1,6 @@
import { CommonModule } from '@angular/common';
import { Component, OnInit, inject } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { Component, inject, computed, linkedSignal, input } from '@angular/core';
import { form, FormField, required } from '@angular/forms/signals';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatDatepickerModule } from '@angular/material/datepicker';
@@ -13,10 +13,21 @@ import { ActivatedRoute, Router } from '@angular/router';
import moment from 'moment';
import { SaleCategory } from '../core/sale-category';
import { SaleCategoryService } from '../sale-category/sale-category.service';
import { ToCsvService } from '../shared/to-csv.service';
import { BeerSaleExportHeaderInterface } from './beer-sale-export-header-interface';
import { BeerSaleReport } from './beer-sale-report';
import { BeerSaleReportDataSource } from './beer-sale-report-datasource';
import { BeerSaleReportService } from './beer-sale-report.service';
export interface BeerSaleReportFormData {
startDate: Date;
finishDate: Date;
saleCategory: string;
regular: boolean;
happy: boolean;
staff: boolean;
nc: boolean;
}
@Component({
selector: 'app-beer-sale-report',
@@ -32,61 +43,72 @@ import { BeerSaleReportDataSource } from './beer-sale-report-datasource';
MatInputModule,
MatSelectModule,
MatTableModule,
ReactiveFormsModule,
FormField,
],
})
export class BeerSaleReportComponent implements OnInit {
private route = inject(ActivatedRoute);
export class BeerSaleReportComponent {
private router = inject(Router);
private route = inject(ActivatedRoute);
private toCsv = inject(ToCsvService);
private ser = inject(BeerSaleReportService);
private saleCategoryService = inject(SaleCategoryService);
startDate = input(null, { transform: (v: string | null | undefined) => v ?? null });
finishDate = input(null, { transform: (v: string | null | undefined) => v ?? null });
saleCategory = input(null, { transform: (v: string | null | undefined) => v ?? null });
regular = input(true, { transform: (v: string | null | undefined) => v !== 'false' });
happy = input(true, { transform: (v: string | null | undefined) => v !== 'false' });
staff = input(true, { transform: (v: string | null | undefined) => v !== 'false' });
nc = input(true, { transform: (v: string | null | undefined) => v !== 'false' });
saleCategories: SaleCategory[] = [];
info: BeerSaleReport = new BeerSaleReport();
dataSource: BeerSaleReportDataSource = new BeerSaleReportDataSource(this.info.data);
form: FormGroup<{
startDate: FormControl<Date>;
finishDate: FormControl<Date>;
saleCategory: FormControl<string>;
regular: FormControl<boolean>;
happy: FormControl<boolean>;
staff: FormControl<boolean>;
nc: FormControl<boolean>;
}>;
saleCategoriesResource = this.saleCategoryService.list();
infoResource = this.ser.get(
this.startDate,
this.finishDate,
this.saleCategory,
this.regular,
this.happy,
this.staff,
this.nc,
);
saleCategories = computed(() => this.saleCategoriesResource.value() ?? []);
info = computed(() => this.infoResource.value());
dataSource = computed(() => this.info()?.data ?? []);
formModel = linkedSignal({
source: () => this.info(),
computation: (info): BeerSaleReportFormData => {
if (info) {
return {
startDate: moment(info.startDate, 'DD-MMM-YYYY').toDate(),
finishDate: moment(info.finishDate, 'DD-MMM-YYYY').toDate(),
saleCategory: info.saleCategory?.id ?? '',
regular: info.regular,
happy: info.happy,
staff: info.staff,
nc: info.nc,
};
}
return {
startDate: new Date(),
finishDate: new Date(),
saleCategory: '',
regular: true,
happy: true,
staff: true,
nc: true,
};
},
});
form = form(this.formModel, (schemaPath) => {
required(schemaPath.saleCategory, { message: 'Sale Category is required' });
});
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns: string[] = ['date'];
constructor() {
// Create form
this.form = new FormGroup({
startDate: new FormControl(new Date(), { nonNullable: true }),
finishDate: new FormControl(new Date(), { nonNullable: true }),
saleCategory: new FormControl('', { nonNullable: true }),
regular: new FormControl<boolean>(true, { nonNullable: true }),
happy: new FormControl<boolean>(true, { nonNullable: true }),
staff: new FormControl<boolean>(true, { nonNullable: true }),
nc: new FormControl<boolean>(true, { nonNullable: true }),
});
}
ngOnInit() {
this.route.data.subscribe((value) => {
const data = value as { info: BeerSaleReport; saleCategories: SaleCategory[] };
this.info = data.info;
this.saleCategories = data.saleCategories;
this.displayedColumns = ['date'].concat(this.info.headers);
this.form.setValue({
startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(),
finishDate: moment(this.info.finishDate, 'DD-MMM-YYYY').toDate(),
saleCategory: this.info.saleCategory?.id ?? '',
regular: this.info.regular,
happy: this.info.happy,
staff: this.info.staff,
nc: this.info.nc,
});
this.dataSource = new BeerSaleReportDataSource(this.info.data);
});
}
displayedColumns = computed(() => {
const headers = this.info()?.headers ?? [];
return ['date'].concat(headers);
});
show() {
const info = this.getInfo();
@@ -104,17 +126,21 @@ export class BeerSaleReportComponent implements OnInit {
}
filterOn(id: string) {
const sc = this.saleCategories.find((x) => x.id === id);
this.info.saleCategory = sc ? sc : new SaleCategory({ id });
const sc = this.saleCategories().find((x: SaleCategory) => x.id === id);
const currentInfo = this.info();
if (currentInfo) {
currentInfo.saleCategory = sc ? sc : new SaleCategory({ id });
}
}
getInfo(): BeerSaleReport {
const formModel = this.form.value;
const formModel = this.formModel();
const currentInfo = this.info();
return new BeerSaleReport({
startDate: moment(formModel.startDate).format('DD-MMM-YYYY'),
finishDate: moment(formModel.finishDate).format('DD-MMM-YYYY'),
saleCategory: this.info.saleCategory,
saleCategory: currentInfo?.saleCategory,
regular: formModel.regular,
happy: formModel.happy,
staff: formModel.staff,
@@ -123,12 +149,18 @@ export class BeerSaleReportComponent implements OnInit {
}
exportCsv() {
const currentInfo = this.info();
if (!currentInfo) return;
const init: BeerSaleExportHeaderInterface = { Date: 'date' };
const headers = this.info.headers.reduce((a, c) => {
a[c] = c;
return a;
}, init);
const csvData = new Blob([this.toCsv.toCsv(headers, this.info.data)], {
const headers = currentInfo.headers.reduce(
(a: Record<string, string>, c: string) => {
a[c] = c;
return a;
},
init as Record<string, string>,
);
const csvData = new Blob([this.toCsv.toCsv(headers, currentInfo.data)], {
type: 'text/csv;charset=utf-8;',
});
const link = document.createElement('a');