import { DecimalPipe } from '@angular/common'; import { Component, inject, input, computed, afterNextRender, linkedSignal, signal } from '@angular/core'; import { form as createForm, FormField, FormRoot } from '@angular/forms/signals'; import { MatAutocompleteModule } from '@angular/material/autocomplete'; import { MatBadgeModule } from '@angular/material/badge'; import { MatButtonModule } from '@angular/material/button'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatIconModule } from '@angular/material/icon'; import { MatInputModule } from '@angular/material/input'; import { MatPaginatorModule, PageEvent } from '@angular/material/paginator'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTableModule } from '@angular/material/table'; import { MatTooltipModule } from '@angular/material/tooltip'; import { Router } from '@angular/router'; import moment from 'moment'; import { AuthService } from '../auth/auth.service'; import { ErrorStateComponent } from '../shared/error-state/error-state.component'; import { LocalTimePipe } from '../shared/local-time.pipe'; import { SkeletonLoaderComponent } from '../shared/skeleton-loader/skeleton-loader.component'; import { ToCsvService } from '../shared/to-csv.service'; import { MozimoDailyRegister } from './mozimo-daily-register'; import { MozimoDailyRegisterItem } from './mozimo-daily-register-item'; import { MozimoDailyRegisterService } from './mozimo-daily-register.service'; export interface MozimoDailyRegisterFormData { date: Date; items: { received: number; sale: number; nc: number; display: number | null; ageing: number | null; }[]; } @Component({ selector: 'app-mozimo-daily-register', templateUrl: './mozimo-daily-register.component.html', styleUrls: ['./mozimo-daily-register.component.css'], imports: [ DecimalPipe, LocalTimePipe, MatAutocompleteModule, MatBadgeModule, MatButtonModule, MatDatepickerModule, MatFormFieldModule, MatIconModule, MatInputModule, MatPaginatorModule, MatTableModule, MatTooltipModule, FormField, FormRoot, SkeletonLoaderComponent, ErrorStateComponent, ], providers: [LocalTimePipe], }) export class MozimoDailyRegisterComponent { private router = inject(Router); private toCsv = inject(ToCsvService); private localTimePipe = inject(LocalTimePipe); private snackBar = inject(MatSnackBar); auth = inject(AuthService); private ser = inject(MozimoDailyRegisterService); date = input(null, { transform: (v: string | null | undefined) => v ?? null }); pageSize = signal(50); pageIndex = signal(0); infoResource = this.ser.list(this.date); info = computed(() => this.infoResource.value() ?? new MozimoDailyRegister()); model = linkedSignal({ source: this.info, computation: (v): MozimoDailyRegisterFormData => ({ date: moment(v.date, 'DD-MMM-YYYY').toDate(), items: v.body.map((x) => ({ received: x.received, sale: x.sale, nc: x.nc, display: x.display, ageing: x.ageing, })), }), }); body = linkedSignal(() => this.info().body); dataSource = computed(() => { const data = this.info().body ?? []; const pageIndex = this.pageIndex(); const pageSize = this.pageSize(); return data.slice(pageIndex * pageSize, (pageIndex + 1) * pageSize); }); form = createForm(this.model); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['product', 'opening', 'received', 'sale', 'nc', 'display', 'ageing', 'variance', 'closing']; constructor() { afterNextRender(() => { this.form().focusBoundControl(); }); } show() { const date = moment(this.model().date).format('DD-MMM-YYYY'); if (this.date() === date) { this.infoResource.reload(); } else { this.router.navigate(['/mozimo-daily-register', date]); } } save() { this.ser.save(this.getMozimoDailyRegister()).subscribe({ next: () => { this.snackBar.open('', 'Success'); }, error: (error) => { this.snackBar.open(error as string, 'Danger'); }, }); } getMozimoDailyRegister(): MozimoDailyRegister { const formModel = this.model(); const info = this.info(); info.date = moment(formModel.date).format('DD-MMM-YYYY'); const array = formModel.items; if (array) { info.body.forEach((item, index) => { if (array[index]) { item.received = array[index].received ?? 0; item.sale = array[index].sale ?? 0; item.nc = array[index].nc ?? 0; item.display = array[index].display ?? null; item.ageing = array[index].ageing ?? null; } }); } return info; } exportCsv() { const headers = { Product: 'product', Opening: 'opening', Received: 'received', Sale: 'sale', Nc: 'nc', Display: 'display', Ageing: 'ageing', Variance: 'variance', Closing: 'closing', 'Last Edit Date': 'lastEditDate', }; const d = JSON.parse(JSON.stringify(this.info().body ?? [])).map((x: MozimoDailyRegisterItem) => ({ id: x.id, product: x.product.name, opening: x.opening, received: x.received, sale: x.sale, nc: x.nc, display: x.display, ageing: x.ageing, variance: x.variance, closing: x.closing, lastEditDate: x.lastEditDate ? this.localTimePipe.transform(x.lastEditDate ?? '') : 'Unsaved', })); const csvData = new Blob([this.toCsv.toCsv(headers, d)], { type: 'text/csv;charset=utf-8;', }); const link = document.createElement('a'); link.href = window.URL.createObjectURL(csvData); link.setAttribute('download', 'mozimo-product-register.csv'); document.body.appendChild(link); link.click(); document.body.removeChild(link); } updateReceived($event: Event, row: MozimoDailyRegisterItem) { row.received = +($event.target as HTMLInputElement).value; this.body.set([...this.info().body]); } updateSale($event: Event, row: MozimoDailyRegisterItem) { row.sale = +($event.target as HTMLInputElement).value; this.body.set([...this.info().body]); } updateNc($event: Event, row: MozimoDailyRegisterItem) { row.nc = +($event.target as HTMLInputElement).value; this.body.set([...this.info().body]); } updateDisplay($event: Event, row: MozimoDailyRegisterItem) { const val = ($event.target as HTMLInputElement).value; row.display = val === '' ? null : +val; this.body.set([...this.info().body]); } updateAgeing($event: Event, row: MozimoDailyRegisterItem) { const val = ($event.target as HTMLInputElement).value; row.ageing = val === '' ? null : +val; this.body.set([...this.info().body]); } handlePageEvent(e: PageEvent) { this.pageSize.set(e.pageSize); this.pageIndex.set(e.pageIndex); } }