Skip to content

Commit 4678165

Browse files
committed
keyboard sale cash cashier
1 parent c956e06 commit 4678165

15 files changed

Lines changed: 576 additions & 110 deletions

eslint.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ module.exports = defineConfig([
3131
style: "kebab-case",
3232
},
3333
],
34+
"@typescript-eslint/no-unused-vars": "warn",
35+
"@typescript-eslint/no-explicit-any": "warn",
3436
},
3537
},
3638
{

src/app/components/cashier/cashier.component.html

Lines changed: 22 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,12 @@ <h3>
183183
<span>{{ "CASHIER.PAYMENTS.CARD" | translate }}</span>
184184
</button>
185185
<button
186-
class="payment-btn transfer"
187-
(click)="completeSale('transfer')"
186+
class="payment-btn internal"
187+
(click)="completeSale('internal')"
188188
[disabled]="items().length === 0 || isProcessing()"
189189
>
190-
<i class="fas fa-exchange-alt"></i>
191-
<span>{{ "CASHIER.PAYMENTS.TRANSFER" | translate }}</span>
190+
<i class="fas fa-building"></i>
191+
<span>{{ "CASHIER.PAYMENTS.INTERNAL" | translate }}</span>
192192
</button>
193193
</div>
194194
</div>
@@ -211,14 +211,14 @@ <h2>
211211
class="fas"
212212
[class.fa-money-bill-wave]="selectedPaymentMethod() === 'cash'"
213213
[class.fa-credit-card]="selectedPaymentMethod() === 'card'"
214-
[class.fa-exchange-alt]="selectedPaymentMethod() === 'transfer'"
214+
[class.fa-building]="selectedPaymentMethod() === 'internal'"
215215
></i>
216216
{{
217217
selectedPaymentMethod() === "cash"
218218
? ("CASHIER.PAYMENT.TITLE.CASH" | translate)
219219
: selectedPaymentMethod() === "card"
220220
? ("CASHIER.PAYMENT.TITLE.CARD" | translate)
221-
: ("CASHIER.PAYMENT.TITLE.TRANSFER" | translate)
221+
: ("CASHIER.PAYMENT.TITLE.INTERNAL" | translate)
222222
}}
223223
</h2>
224224
<button class="close-btn" (click)="cancelPayment()">
@@ -237,47 +237,26 @@ <h2>
237237
<!-- Cash Payment Form -->
238238
@if (selectedPaymentMethod() === "cash") {
239239
<div class="cash-payment">
240-
<div class="form-group">
241-
<label for="cashReceived">{{
242-
"CASHIER.PAYMENT.CASH_RECEIVED" | translate
243-
}}</label>
244-
<input
245-
#cashReceivedInput
246-
id="cashReceived"
247-
type="number"
248-
step="0.01"
249-
min="0"
250-
[(ngModel)]="cashReceived"
251-
(ngModelChange)="onCashReceivedChange()"
252-
placeholder="{{
253-
'CASHIER.PAYMENT.CASH_RECEIVED' | translate
254-
}}"
255-
class="cash-input"
256-
[class.invalid]="
257-
cashReceived() && parseFloat(cashReceived()) < total()
258-
"
259-
/>
260-
</div>
261-
262-
@if (change() > 0) {
263-
<div class="change-display">
264-
<span class="change-label">{{
265-
"CASHIER.PAYMENT.CHANGE" | translate
266-
}}</span>
267-
<span class="change-value">{{ change() | appCurrency }}</span>
268-
</div>
269-
}
240+
<!-- Number Keyboard -->
241+
<app-number-keyboard
242+
(valueChange)="onKeyboardInput($event)"
243+
></app-number-keyboard>
270244

271-
@if (cashReceived() && parseFloat(cashReceived()) < total()) {
272-
<div class="error-message">
273-
<i class="fas fa-exclamation-triangle"></i>
274-
{{ "CASHIER.PAYMENT.AMOUNT_TOO_LOW" | translate }}
275-
</div>
276-
}
245+
<div
246+
class="change-display"
247+
[class.insufficient]="
248+
!cashReceived() || parseFloat(cashReceived()) < total()
249+
"
250+
>
251+
<span class="change-label">{{
252+
"CASHIER.PAYMENT.CHANGE" | translate
253+
}}</span>
254+
<span class="change-value">{{ change() | appCurrency }}</span>
255+
</div>
277256
</div>
278257
}
279258

280-
<!-- Card/Transfer Confirmation -->
259+
<!-- Card/Internal Confirmation -->
281260
@if (selectedPaymentMethod() !== "cash") {
282261
<div class="confirmation-message">
283262
<i class="fas fa-check-circle"></i>

src/app/components/cashier/cashier.component.scss

Lines changed: 31 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -762,12 +762,12 @@
762762
}
763763
}
764764

765-
&.transfer {
766-
background: $info;
765+
&.internal {
766+
background: $warning;
767767
color: white;
768768

769769
&:hover:not(:disabled) {
770-
background: color.adjust($info, $lightness: -10%);
770+
background: color.adjust($warning, $lightness: -10%);
771771
}
772772
}
773773
}
@@ -801,7 +801,7 @@
801801
background: white;
802802
border-radius: 16px;
803803
width: 90%;
804-
max-width: 500px;
804+
max-width: 600px;
805805
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
806806
animation: slideUp 0.3s ease-out;
807807

@@ -817,7 +817,7 @@
817817
}
818818

819819
.modal-header {
820-
padding: 2rem;
820+
padding: $spacing-sm;
821821
border-bottom: 2px solid $secondary-dark;
822822
display: flex;
823823
justify-content: space-between;
@@ -865,17 +865,17 @@
865865
}
866866
}
867867
.modal-body {
868-
padding: 2rem;
868+
padding: $spacing-md;
869869
background: $neumorphic-surface;
870870

871871
.sale-total {
872872
display: flex;
873873
justify-content: space-between;
874874
align-items: center;
875-
padding: 1.5rem;
875+
padding: $spacing-md $spacing-lg;
876876
background: $white;
877877
border-radius: 12px;
878-
margin-bottom: 2rem;
878+
margin-bottom: $spacing-md;
879879

880880
.label {
881881
font-size: 1.25rem;
@@ -891,41 +891,13 @@
891891
}
892892

893893
.cash-payment {
894-
.form-group {
895-
margin-bottom: 1.5rem;
896-
897-
label {
898-
display: block;
899-
font-weight: 600;
900-
color: var(--text-primary);
901-
margin-bottom: 0.5rem;
902-
font-size: 1rem;
903-
}
904-
905-
.cash-input {
906-
width: 100%;
907-
padding: 1rem;
908-
border: 2px solid var(--border-color);
909-
border-radius: 8px;
910-
font-size: 1.5rem;
911-
font-weight: 600;
912-
transition: all 0.2s;
913-
914-
&:focus {
915-
outline: none;
916-
border-color: $primary;
917-
box-shadow: 0 0 0 3px rgba($primary, 0.1);
918-
}
919-
920-
&.invalid {
921-
border-color: $danger;
894+
display: flex;
895+
flex-direction: column;
896+
gap: 1.5rem;
922897

923-
&:focus {
924-
border-color: $danger;
925-
box-shadow: 0 0 0 3px rgba($danger, 0.1);
926-
}
927-
}
928-
}
898+
app-number-keyboard {
899+
display: block;
900+
width: 100%;
929901
}
930902

931903
.change-display {
@@ -937,17 +909,33 @@
937909
border: 2px solid $success;
938910
border-radius: 12px;
939911
margin-bottom: 1rem;
912+
transition: all 0.3s ease;
940913

941914
.change-label {
942915
font-size: 1.25rem;
943916
font-weight: 600;
944917
color: $success;
918+
transition: color 0.3s ease;
945919
}
946920

947921
.change-value {
948922
font-size: 2rem;
949923
font-weight: 700;
950924
color: $success;
925+
transition: color 0.3s ease;
926+
}
927+
928+
&.insufficient {
929+
background: rgba($danger, 0.1);
930+
border-color: $danger;
931+
932+
.change-label {
933+
color: $danger;
934+
}
935+
936+
.change-value {
937+
color: $danger;
938+
}
951939
}
952940
}
953941

@@ -987,7 +975,7 @@
987975
}
988976

989977
.modal-footer {
990-
padding: 1.5rem 2rem;
978+
padding: 1rem 2rem;
991979
border-top: 1px solid var(--border-color);
992980
display: flex;
993981
gap: 1rem;

src/app/components/cashier/cashier.component.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ import {
2727
CalculatorAddEvent,
2828
CalculatorMultiplyConfirmEvent,
2929
} from "../calculator/calculator.component";
30+
import {
31+
NumberKeyboardComponent,
32+
NumberKeyboardInputEvent,
33+
} from "../number-keyboard/number-keyboard.component";
3034
import { TranslatePipe } from "../../pipes/translate.pipe";
3135
import { CurrencyPipe } from "../../pipes/currency.pipe";
3236
import { environment } from "@environments/environment";
@@ -39,6 +43,7 @@ import { OpenRegisterComponent } from "../open-register/open-register.component"
3943
CommonModule,
4044
FormsModule,
4145
CalculatorComponent,
46+
NumberKeyboardComponent,
4247
TranslatePipe,
4348
CurrencyPipe,
4449
OpenRegisterComponent,
@@ -83,7 +88,7 @@ export class CashierComponent implements OnInit, AfterViewInit {
8388
selectedItemId = signal<number | null>(null);
8489

8590
showPaymentModal = signal<boolean>(false);
86-
selectedPaymentMethod = signal<"cash" | "card" | "transfer" | null>(null);
91+
selectedPaymentMethod = signal<"cash" | "card" | "internal" | null>(null);
8792
cashReceived = signal<string>("");
8893
change = signal<number>(0);
8994

@@ -844,7 +849,7 @@ export class CashierComponent implements OnInit, AfterViewInit {
844849
}
845850
}
846851

847-
completeSale(paymentMethod: "cash" | "card" | "transfer"): void {
852+
completeSale(paymentMethod: "cash" | "card" | "internal"): void {
848853
// Check if register is open
849854
if (!this.currentRegister()) {
850855
this.toastService.show(
@@ -889,6 +894,11 @@ export class CashierComponent implements OnInit, AfterViewInit {
889894
}
890895
}
891896

897+
onKeyboardInput(event: NumberKeyboardInputEvent): void {
898+
this.cashReceived.set(event.value);
899+
this.onCashReceivedChange();
900+
}
901+
892902
cancelPayment(): void {
893903
this.showPaymentModal.set(false);
894904
this.selectedPaymentMethod.set(null);
@@ -940,6 +950,7 @@ export class CashierComponent implements OnInit, AfterViewInit {
940950
: {},
941951
status: "completed" as const,
942952
register: register?._id,
953+
isInternal: paymentMethod === "internal",
943954
};
944955

945956
this.saleService.createSale(sale).subscribe({

src/app/components/layout/layout.component.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,20 @@
2222
<!-- Global Search Component -->
2323
<app-global-search></app-global-search>
2424

25+
<!-- Print Receipt Toggle -->
26+
<div class="header-print-toggle">
27+
<label class="print-toggle-label">
28+
<input
29+
type="checkbox"
30+
[(ngModel)]="printReceiptsEnabled"
31+
(ngModelChange)="onPrintToggleChange()"
32+
class="print-checkbox"
33+
/>
34+
<span class="toggle-slider-header"></span>
35+
<i class="fas fa-receipt toggle-icon"></i>
36+
</label>
37+
</div>
38+
2539
<button class="user-swap" (click)="switchUser()">
2640
<i class="fa-solid fa-people-arrows"></i>
2741
</button>

0 commit comments

Comments
 (0)