Moved to Angular 20

Moved to Tailwind 4
Moved to Python 3.13
Enabled arm64/v8 Builds
This commit is contained in:
2025-07-02 04:32:35 +00:00
parent 86722e3558
commit 44513dd6be
203 changed files with 2942 additions and 5628 deletions

View File

@ -1,5 +1,5 @@
import { ScrollingModule } from '@angular/cdk/scrolling';
import { Component, Inject, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatOptionModule } from '@angular/material/core';
@ -25,6 +25,9 @@ import { Regime } from 'src/app/core/regime';
],
})
export class BillNumberComponent implements OnInit {
dialogRef = inject<MatDialogRef<BillNumberComponent>>(MatDialogRef);
data = inject(MAT_DIALOG_DATA);
form: FormGroup<{
regime: FormControl<Regime | null>;
billNumber: FormControl<number>;
@ -32,11 +35,9 @@ export class BillNumberComponent implements OnInit {
regimes: Regime[] = [];
constructor(
public dialogRef: MatDialogRef<BillNumberComponent>,
@Inject(MAT_DIALOG_DATA)
public data: Regime[],
) {
constructor() {
const data = this.data;
this.regimes = data;
// Create form
this.form = new FormGroup({

View File

@ -1,5 +1,5 @@
import { CdkScrollableModule } from '@angular/cdk/scrolling';
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatRippleModule } from '@angular/material/core';
@ -14,9 +14,10 @@ import { VoucherType } from '../bills/voucher-type';
imports: [CdkScrollableModule, MatButtonModule, MatCardModule, MatDialogModule, MatRippleModule],
})
export class BillTypeComponent {
dialogRef = inject<MatDialogRef<BillTypeComponent>>(MatDialogRef);
selected?: string;
selectedVal?: VoucherType;
constructor(public dialogRef: MatDialogRef<BillTypeComponent>) {}
select(voucherType: string) {
this.selected = voucherType;

View File

@ -1,5 +1,5 @@
import { SelectionModel } from '@angular/cdk/collections';
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { BehaviorSubject, throwError, Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@ -13,7 +13,6 @@ import { Table } from '../core/table';
import { ToasterService } from '../core/toaster.service';
import { ModifierCategoryService } from '../modifier-categories/modifier-category.service';
import { MathService } from '../shared/math.service';
import { Bill } from './bills/bill';
import { Inventory } from './bills/inventory';
import { Kot } from './bills/kot';
@ -25,6 +24,12 @@ import { ModifiersComponent } from './modifiers/modifiers.component';
providedIn: 'root',
})
export class BillService {
private dialog = inject(MatDialog);
private toaster = inject(ToasterService);
private math = inject(MathService);
private ser = inject(VoucherService);
private modifierCategoryService = inject(ModifierCategoryService);
public dataObs: BehaviorSubject<BillViewItem[]>;
public bill: Bill = new Bill();
private originalBill: Bill = new Bill();
@ -37,15 +42,11 @@ export class BillService {
public selection = new SelectionModel<string>(true, []);
private amountBs: BehaviorSubject<number>;
private updateTable: boolean;
private allowDeactivate: boolean; // To disable Deactivate Guard on navigation after printing bill or kot.
private allowDeactivate: boolean;
constructor(
private dialog: MatDialog,
private toaster: ToasterService,
private math: MathService,
private ser: VoucherService,
private modifierCategoryService: ModifierCategoryService,
) {
// To disable Deactivate Guard on navigation after printing bill or kot.
constructor() {
this.dataObs = new BehaviorSubject<BillViewItem[]>([]);
this.grossAmount = new BehaviorSubject(0);
this.discountAmount = new BehaviorSubject(0);

View File

@ -1,7 +1,6 @@
import { Table } from '../../core/table';
import { User } from '../../core/user';
import { GuestBook } from '../../guest-book/guest-book';
import { Kot } from './kot';
import { VoucherType } from './voucher-type';

View File

@ -1,5 +1,5 @@
import { AsyncPipe, CurrencyPipe } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatCheckboxModule } from '@angular/material/checkbox';
@ -23,7 +23,6 @@ import { ChooseCustomerComponent } from '../choose-customer/choose-customer.comp
import { PaxComponent } from '../pax/pax.component';
import { QuantityComponent } from '../quantity/quantity.component';
import { TablesDialogComponent } from '../tables-dialog/tables-dialog.component';
import { Bill } from './bill';
import { BillSelectionItem } from './bill-selection-item';
import { BillsDataSource } from './bills-datasource';
@ -48,20 +47,18 @@ import { VoucherType } from './voucher-type';
],
})
export class BillsComponent implements OnInit {
private route = inject(ActivatedRoute);
private router = inject(Router);
private dialog = inject(MatDialog);
private toaster = inject(ToasterService);
private auth = inject(AuthService);
bs = inject(BillService);
private tSer = inject(TableService);
dataSource: BillsDataSource = new BillsDataSource(this.bs.dataObs);
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns: string[] = ['select', 'info', 'quantity'];
constructor(
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private toaster: ToasterService,
private auth: AuthService,
public bs: BillService,
private tSer: TableService,
) {}
ngOnInit() {
this.route.data.subscribe((value) => {
const data = value as { item: Bill; updateTable: boolean };

View File

@ -1,5 +1,4 @@
import { User } from '../../core/user';
import { Inventory } from './inventory';
export class Kot {

View File

@ -1,11 +1,10 @@
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { ErrorLoggerService } from '../../core/error-logger.service';
import { Table } from '../../core/table';
import { Bill } from './bill';
import { VoucherType } from './voucher-type';
@ -17,10 +16,8 @@ const serviceName = 'VoucherService';
@Injectable({ providedIn: 'root' })
export class VoucherService {
constructor(
private http: HttpClient,
private log: ErrorLoggerService,
) {}
private http = inject(HttpClient);
private log = inject(ErrorLoggerService);
get(id: string): Observable<Bill> {
return this.http

View File

@ -1,17 +1,17 @@
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { Observable, of as observableOf } from 'rxjs';
import { map } from 'rxjs/operators';
import { ConfirmDialogComponent } from '../shared/confirm-dialog/confirm-dialog.component';
import { BillsComponent } from './bills/bills.component';
@Injectable({
providedIn: 'root',
})
export class CanDeactivateBillGuard {
constructor(private dialog: MatDialog) {}
private dialog = inject(MatDialog);
canDeactivate(component: BillsComponent): Observable<boolean> | boolean {
if (component.bs.canDeactivate()) {
return observableOf(true);

View File

@ -1,6 +1,6 @@
import { CdkScrollableModule } from '@angular/cdk/scrolling';
import { AsyncPipe } from '@angular/common';
import { Component, Inject } from '@angular/core';
import { Component, inject } from '@angular/core';
import { FormArray, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteSelectedEvent, MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatButtonModule } from '@angular/material/button';
@ -34,6 +34,10 @@ import { CustomerService } from '../../customers/customer.service';
],
})
export class ChooseCustomerComponent {
dialogRef = inject<MatDialogRef<ChooseCustomerComponent>>(MatDialogRef);
data = inject(MAT_DIALOG_DATA);
private ser = inject(CustomerService);
form: FormGroup<{
name: FormControl<string>;
phone: FormControl<string>;
@ -49,11 +53,9 @@ export class ChooseCustomerComponent {
item: Customer = new Customer();
customers: Observable<Customer[]>;
constructor(
public dialogRef: MatDialogRef<ChooseCustomerComponent>,
@Inject(MAT_DIALOG_DATA) public data: string | undefined,
private ser: CustomerService,
) {
constructor() {
const data = this.data;
// Create form
this.form = new FormGroup({
name: new FormControl<string>('', { nonNullable: true }),

View File

@ -1,10 +1,9 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { ErrorLoggerService } from '../../core/error-logger.service';
import { DiscountItem } from './discount-item';
const url = '/api/customer-discounts';
@ -14,10 +13,8 @@ const serviceName = 'CustomerService';
providedIn: 'root',
})
export class CustomerDiscountsService {
constructor(
private http: HttpClient,
private log: ErrorLoggerService,
) {}
private http = inject(HttpClient);
private log = inject(ErrorLoggerService);
list(id: string | undefined): Observable<DiscountItem[]> {
const getUrl: string = id === undefined ? `${url}` : `${url}/${id}`;

View File

@ -1,6 +1,6 @@
import { CdkScrollableModule } from '@angular/cdk/scrolling';
import { PercentPipe } from '@angular/common';
import { Component, Inject } from '@angular/core';
import { Component, inject } from '@angular/core';
import { FormArray, FormControl, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog';
@ -29,6 +29,9 @@ import { DiscountItem } from './discount-item';
],
})
export class DiscountComponent {
dialogRef = inject<MatDialogRef<DiscountComponent>>(MatDialogRef);
data = inject<Observable<DiscountItem[]>>(MAT_DIALOG_DATA);
list: DiscountItem[] = [];
form: FormGroup<{
discounts: FormArray<
@ -44,11 +47,7 @@ export class DiscountComponent {
displayedColumns = ['name', 'discount'];
constructor(
public dialogRef: MatDialogRef<DiscountComponent>,
@Inject(MAT_DIALOG_DATA)
public data: Observable<DiscountItem[]>,
) {
constructor() {
this.form = new FormGroup({
discounts: new FormArray<
FormGroup<{

View File

@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import { MatCardModule } from '@angular/material/card';
import { MatRippleModule } from '@angular/material/core';
import { MatDialog } from '@angular/material/dialog';
@ -31,17 +31,15 @@ import { TablesDialogComponent } from '../tables-dialog/tables-dialog.component'
imports: [MatCardModule, MatRippleModule, RouterLink],
})
export class SalesHomeComponent {
constructor(
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private auth: AuthService,
private toaster: ToasterService,
private saleCategoryService: SaleCategoryService,
private tableService: TableService,
private customerDiscountsService: CustomerDiscountsService,
private bs: BillService,
) {}
private route = inject(ActivatedRoute);
private router = inject(Router);
private dialog = inject(MatDialog);
private auth = inject(AuthService);
private toaster = inject(ToasterService);
private saleCategoryService = inject(SaleCategoryService);
private tableService = inject(TableService);
private customerDiscountsService = inject(CustomerDiscountsService);
private bs = inject(BillService);
printKotAllowed(): boolean {
if (!this.auth.allowed('print-kot')) {

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { MatCardModule } from '@angular/material/card';
import { MatRippleModule } from '@angular/material/core';
import { ActivatedRoute, RouterLink } from '@angular/router';
@ -12,9 +12,9 @@ import { MenuCategory } from '../../core/menu-category';
imports: [MatCardModule, MatRippleModule, RouterLink],
})
export class MenuCategoriesComponent implements OnInit {
list: MenuCategory[] = [];
private route = inject(ActivatedRoute);
constructor(private route: ActivatedRoute) {}
list: MenuCategory[] = [];
ngOnInit() {
this.route.data.subscribe((value) => {

View File

@ -1,6 +1,6 @@
import { CdkScrollable } from '@angular/cdk/scrolling';
import { AsyncPipe } from '@angular/common';
import { Component, Inject } from '@angular/core';
import { Component, inject } from '@angular/core';
import { MatBadgeModule } from '@angular/material/badge';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
@ -30,14 +30,18 @@ import { ModifierCategory } from '../../core/modifier-category';
],
})
export class ModifiersComponent {
data = inject<{
list: Observable<ModifierCategory[]>;
selected: Modifier[];
}>(MAT_DIALOG_DATA);
list: Observable<ModifierCategory[]>;
selected: Modifier[];
selectedIds: (string | undefined)[];
constructor(
@Inject(MAT_DIALOG_DATA)
public data: { list: Observable<ModifierCategory[]>; selected: Modifier[] },
) {
constructor() {
const data = this.data;
this.list = data.list;
this.selected = data.selected;
this.selectedIds = this.selected.map((e) => e.id);

View File

@ -1,5 +1,5 @@
import { CdkScrollableModule } from '@angular/cdk/scrolling';
import { Component, Inject, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog';
@ -20,14 +20,14 @@ import { MatInputModule } from '@angular/material/input';
],
})
export class PaxComponent implements OnInit {
dialogRef = inject<MatDialogRef<PaxComponent>>(MatDialogRef);
data = inject(MAT_DIALOG_DATA);
form: FormGroup<{
pax: FormControl<number>;
}>;
constructor(
public dialogRef: MatDialogRef<PaxComponent>,
@Inject(MAT_DIALOG_DATA) public data: number,
) {
constructor() {
// Create form
this.form = new FormGroup({
pax: new FormControl<number>(0, { nonNullable: true }),

View File

@ -1,5 +1,5 @@
import { CurrencyPipe } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { MatCardModule } from '@angular/material/card';
import { MatRippleModule } from '@angular/material/core';
import { ActivatedRoute, RouterLink } from '@angular/router';
@ -14,12 +14,10 @@ import { BillService } from '../bill.service';
imports: [CurrencyPipe, MatCardModule, MatRippleModule, RouterLink],
})
export class ProductsComponent implements OnInit {
list: Product[] = [];
private route = inject(ActivatedRoute);
private bs = inject(BillService);
constructor(
private route: ActivatedRoute,
private bs: BillService,
) {}
list: Product[] = [];
ngOnInit() {
this.route.data.subscribe((value) => {

View File

@ -1,5 +1,5 @@
import { CdkScrollableModule } from '@angular/cdk/scrolling';
import { Component, Inject, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog';
@ -22,15 +22,15 @@ import { MathService } from '../../shared/math.service';
],
})
export class QuantityComponent implements OnInit {
dialogRef = inject<MatDialogRef<QuantityComponent>>(MatDialogRef);
data = inject(MAT_DIALOG_DATA);
private math = inject(MathService);
form: FormGroup<{
quantity: FormControl<string>;
}>;
constructor(
public dialogRef: MatDialogRef<QuantityComponent>,
@Inject(MAT_DIALOG_DATA) public data: number,
private math: MathService,
) {
constructor() {
// Create form
this.form = new FormGroup({
quantity: new FormControl<string>('', { nonNullable: true }),

View File

@ -1,5 +1,5 @@
import { CdkScrollableModule } from '@angular/cdk/scrolling';
import { Component, ElementRef, Inject, ViewChild } from '@angular/core';
import { Component, ElementRef, ViewChild, inject } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog';
@ -24,6 +24,12 @@ import { ReasonDatasource } from './reason-datasource';
],
})
export class ReasonComponent {
dialogRef = inject<MatDialogRef<ReasonComponent>>(MatDialogRef);
private data = inject<{
title: string;
reasons: string[];
}>(MAT_DIALOG_DATA);
@ViewChild('son', { static: true }) son?: ElementRef;
form: FormGroup<{
son: FormControl<string>;
@ -35,10 +41,9 @@ export class ReasonComponent {
reasons: string[];
displayedColumns = ['reason'];
constructor(
public dialogRef: MatDialogRef<ReasonComponent>,
@Inject(MAT_DIALOG_DATA) private data: { title: string; reasons: string[] },
) {
constructor() {
const data = this.data;
this.reasons = data.reasons ?? [];
this.title = data.title;
this.form = new FormGroup({

View File

@ -1,6 +1,6 @@
import { CdkScrollableModule } from '@angular/cdk/scrolling';
import { CurrencyPipe } from '@angular/common';
import { Component, ElementRef, Inject, ViewChild } from '@angular/core';
import { Component, ElementRef, ViewChild, inject } from '@angular/core';
import { FormArray, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog';
@ -14,7 +14,6 @@ import { ReceivePaymentItem } from '../../core/receive-payment-item';
import { SettleOption } from '../../core/settle-option';
import { SettleOptionService } from '../../settle-option/settle-option.service';
import { VoucherType } from '../bills/voucher-type';
import { ReceivePaymentDatasource } from './receive-payment-datasource';
@Component({
@ -33,6 +32,13 @@ import { ReceivePaymentDatasource } from './receive-payment-datasource';
],
})
export class ReceivePaymentComponent {
dialogRef = inject<MatDialogRef<ReceivePaymentComponent>>(MatDialogRef);
private ser = inject(SettleOptionService);
data = inject<{
type: VoucherType;
amount: number;
}>(MAT_DIALOG_DATA);
@ViewChild('son', { static: true }) son?: ElementRef;
choices: ReceivePaymentItem[] = [];
choicesSubject = new BehaviorSubject<ReceivePaymentItem[]>([]);
@ -57,11 +63,9 @@ export class ReceivePaymentComponent {
displayedColumns = ['name', 'amount'];
constructor(
public dialogRef: MatDialogRef<ReceivePaymentComponent>,
private ser: SettleOptionService,
@Inject(MAT_DIALOG_DATA) public data: { type: VoucherType; amount: number },
) {
constructor() {
const data = this.data;
this.form = new FormGroup({
amounts: new FormArray<
FormGroup<{

View File

@ -1,5 +1,5 @@
import { CurrencyPipe } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { MatCardModule } from '@angular/material/card';
import { MatRippleModule } from '@angular/material/core';
import { MatDialog } from '@angular/material/dialog';
@ -18,16 +18,14 @@ import { BillNumberComponent } from '../bill-number/bill-number.component';
imports: [CurrencyPipe, MatCardModule, MatRippleModule],
})
export class RunningTablesComponent implements OnInit {
private dialog = inject(MatDialog);
private router = inject(Router);
private route = inject(ActivatedRoute);
private toaster = inject(ToasterService);
regimes: Regime[] = [];
list: Table[] = [];
constructor(
private dialog: MatDialog,
private router: Router,
private route: ActivatedRoute,
private toaster: ToasterService,
) {}
ngOnInit() {
this.route.data.subscribe((value) => {
const data = value as { list: Table[]; regimes: Regime[] };

View File

@ -2,7 +2,6 @@ import { Routes } from '@angular/router';
import { authGuard } from '../auth/auth-guard.service';
import { regimeListResolver } from '../regimes/regime-list.resolver';
import { billResolver } from './bills/bill.resolver';
import { BillsComponent } from './bills/bills.component';
import { updateTableResolver } from './bills/update-table.resolver';

View File

@ -1,5 +1,5 @@
import { CdkScrollableModule } from '@angular/cdk/scrolling';
import { Component, Inject } from '@angular/core';
import { Component, inject } from '@angular/core';
import { FormArray, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
@ -13,6 +13,17 @@ import { Observable } from 'rxjs';
imports: [CdkScrollableModule, MatButtonModule, MatCheckboxModule, MatDialogModule, ReactiveFormsModule],
})
export class SplitBillComponent {
dialogRef = inject<MatDialogRef<SplitBillComponent>>(MatDialogRef);
data = inject<
Observable<
{
id: string;
name: string;
selected: boolean;
}[]
>
>(MAT_DIALOG_DATA);
list: { id: string; name: string; selected: boolean }[] = [];
form: FormGroup<{
saleCategories: FormArray<
@ -22,11 +33,7 @@ export class SplitBillComponent {
>;
}>;
constructor(
public dialogRef: MatDialogRef<SplitBillComponent>,
@Inject(MAT_DIALOG_DATA)
public data: Observable<{ id: string; name: string; selected: boolean }[]>,
) {
constructor() {
this.form = new FormGroup({
saleCategories: new FormArray<
FormGroup<{

View File

@ -1,6 +1,6 @@
import { CdkScrollableModule } from '@angular/cdk/scrolling';
import { CurrencyPipe } from '@angular/common';
import { Component, Inject } from '@angular/core';
import { Component, inject } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatRippleModule } from '@angular/material/core';
@ -16,13 +16,19 @@ import { Table } from '../../core/table';
imports: [CdkScrollableModule, CurrencyPipe, MatButtonModule, MatCardModule, MatDialogModule, MatRippleModule],
})
export class TablesDialogComponent {
dialogRef = inject<MatDialogRef<TablesDialogComponent>>(MatDialogRef);
data = inject<{
list: Observable<Table[]>;
canChooseRunning: boolean;
}>(MAT_DIALOG_DATA);
list: Table[] = [];
canChooseRunning: boolean;
selected: Table | null;
constructor(
public dialogRef: MatDialogRef<TablesDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: { list: Observable<Table[]>; canChooseRunning: boolean },
) {
constructor() {
const data = this.data;
this.data.list.subscribe((list: Table[]) => {
this.list = list;
});