From 68649223d963cb9b44d82258b1a7509faa364e75 Mon Sep 17 00:00:00 2001 From: Chris Chen Date: Tue, 23 Jun 2026 14:15:20 -0700 Subject: [PATCH] update mobile view. --- .../receipt-sign-dialog.component.html | 6 +- .../check-register-page.component.html | 135 +++++++++++++----- .../check-register-page.component.scss | 109 ++++++++++++++ .../check-register-page.component.ts | 15 ++ .../expense-form-dialog.component.html | 7 + .../expense-form-dialog.component.ts | 37 ++++- .../expenses-page.component.html | 3 + .../expenses-page.component.scss | 17 +++ .../expenses-page/expenses-page.component.ts | 17 ++- .../my-reimbursements-page.component.html | 2 +- .../my-reimbursements-page.component.scss | 8 +- 11 files changed, 304 insertions(+), 52 deletions(-) diff --git a/APP/src/app/features/disbursement/components/receipt-sign-dialog/receipt-sign-dialog.component.html b/APP/src/app/features/disbursement/components/receipt-sign-dialog/receipt-sign-dialog.component.html index a0a0d06..d4707d8 100644 --- a/APP/src/app/features/disbursement/components/receipt-sign-dialog/receipt-sign-dialog.component.html +++ b/APP/src/app/features/disbursement/components/receipt-sign-dialog/receipt-sign-dialog.component.html @@ -1,4 +1,4 @@ - +
Check #{{ check.checkNumber }} · {{ check.payeeName }} · {{ check.amount | currency }} @@ -12,8 +12,8 @@
Signature / 簽名 Apply
- + + + + +
+
Loading…
+
No checks found.
+ +
+
+ Check #{{ row.checkNumber }} + {{ row.amount | currency:'USD':'symbol':'1.2-2' }} +
+ +
{{ row.payeeName }}
+ +
+
+
Date
+
{{ row.checkDate }}
+
+
+
Lines
+
{{ row.lineCount }}
+
+
+
Receipt / 簽收
+
+ + {{ row.receiptSignedName }} · {{ row.receiptSignedAt | date:'short' }} + + +
+
+
+ + + +
+ + + + + +
+
+ +
+ + Page {{ page }} of {{ totalPages }} + +
+
diff --git a/APP/src/app/features/disbursement/pages/check-register-page/check-register-page.component.scss b/APP/src/app/features/disbursement/pages/check-register-page/check-register-page.component.scss index 7741d97..1e311b4 100644 --- a/APP/src/app/features/disbursement/pages/check-register-page/check-register-page.component.scss +++ b/APP/src/app/features/disbursement/pages/check-register-page/check-register-page.component.scss @@ -24,3 +24,112 @@ background-color: #fee2e2; color: #991b1b; } + +// Mobile card list +// NOTE: display/flex layout lives on the element via Tailwind (flex flex-col gap-3) +// so the responsive `md:hidden` utility wins on desktop. Setting `display: flex` +// here would override `md:hidden` and leak the card list onto the desktop view. + +.chk-empty { + padding: 24px 0; + text-align: center; + color: #6b7280; +} + +.chk-card { + border: 1px solid #e5e7eb; + border-radius: 12px; + background: #fff; + padding: 14px 16px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04); + + &__top { + display: flex; + align-items: baseline; + justify-content: space-between; + gap: 12px; + } + + &__number { + font-size: 0.85rem; + font-weight: 600; + color: #374151; + } + + &__amount { + font-size: 1.1rem; + font-weight: 700; + color: #111827; + } + + &__payee { + margin-top: 4px; + font-weight: 600; + color: #1f2937; + } + + &__meta { + margin: 10px 0 0; + display: flex; + flex-direction: column; + gap: 6px; + + div { + display: flex; + justify-content: space-between; + gap: 12px; + font-size: 0.85rem; + } + + dt { + margin: 0; + color: #6b7280; + } + + dd { + margin: 0; + color: #374151; + text-align: right; + } + } + + &__footer { + margin-top: 12px; + display: flex; + flex-wrap: wrap; + gap: 8px; + } + + &__actions { + margin-top: 12px; + padding-top: 12px; + border-top: 1px solid #f3f4f6; + display: flex; + flex-wrap: wrap; + gap: 8px; + + // Comfortable tap targets; let buttons share the row evenly + .k-button { + flex: 1 1 auto; + min-height: 40px; + justify-content: center; + } + } +} + +.chk-pager { + margin-top: 16px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + + &__info { + font-size: 0.85rem; + color: #6b7280; + } + + .k-button { + min-height: 40px; + } +} diff --git a/APP/src/app/features/disbursement/pages/check-register-page/check-register-page.component.ts b/APP/src/app/features/disbursement/pages/check-register-page/check-register-page.component.ts index 595e8a3..5588671 100644 --- a/APP/src/app/features/disbursement/pages/check-register-page/check-register-page.component.ts +++ b/APP/src/app/features/disbursement/pages/check-register-page/check-register-page.component.ts @@ -49,9 +49,24 @@ export class CheckRegisterPageComponent implements OnInit { } get skip(): number { return (this.page - 1) * this.pageSize; } + get totalPages(): number { return Math.max(1, Math.ceil(this.total / this.pageSize)); } applyFilter(): void { this.page = 1; this.load(); } onPageChange(e: PageChangeEvent): void { this.page = Math.floor(e.skip / this.pageSize) + 1; this.load(); } + prevPage(): void { + if (this.page > 1) { + this.page--; + this.load(); + } + } + + nextPage(): void { + if (this.page < this.totalPages) { + this.page++; + this.load(); + } + } + view(row: CheckListItemDto): void { this.api.getCheck(row.id).subscribe(d => (this.detail = d)); } diff --git a/APP/src/app/features/expense/components/expense-form-dialog/expense-form-dialog.component.html b/APP/src/app/features/expense/components/expense-form-dialog/expense-form-dialog.component.html index dc49b79..b7d7b9a 100644 --- a/APP/src/app/features/expense/components/expense-form-dialog/expense-form-dialog.component.html +++ b/APP/src/app/features/expense/components/expense-form-dialog/expense-form-dialog.component.html @@ -1,6 +1,12 @@
+ + +
\ No newline at end of file diff --git a/APP/src/app/features/expense/pages/expenses-page/expenses-page.component.scss b/APP/src/app/features/expense/pages/expenses-page/expenses-page.component.scss index cba4215..0da4322 100644 --- a/APP/src/app/features/expense/pages/expenses-page/expenses-page.component.scss +++ b/APP/src/app/features/expense/pages/expenses-page/expenses-page.component.scss @@ -44,3 +44,20 @@ color: #1d4ed8; text-decoration: underline; } + +// Save confirmation pill. z-index sits above the Kendo dialog overlay so it +// stays visible while the continuous-entry dialog remains open. +.save-toast { + position: fixed; + left: 50%; + bottom: 2rem; + transform: translateX(-50%); + z-index: 20000; + padding: 0.7rem 1.2rem; + border-radius: 9999px; + font-size: 0.95rem; + font-weight: 600; + color: #f0fdf4; + background: #16a34a; + box-shadow: 0 12px 30px -12px rgba(22, 163, 74, 0.7); +} diff --git a/APP/src/app/features/expense/pages/expenses-page/expenses-page.component.ts b/APP/src/app/features/expense/pages/expenses-page/expenses-page.component.ts index 9a25e49..6f47c47 100644 --- a/APP/src/app/features/expense/pages/expenses-page/expenses-page.component.ts +++ b/APP/src/app/features/expense/pages/expenses-page/expenses-page.component.ts @@ -49,6 +49,10 @@ export class ExpensesPageComponent implements OnInit { rejectRow: ExpenseListItemDto | null = null; rejectNotes = ''; + /** Transient confirmation pill, used so the user gets feedback during continuous entry. */ + toast: string | null = null; + private toastTimer?: ReturnType; + constructor(private api: ExpenseApiService, private ministryApi: MinistryApiService) { } ngOnInit(): void { @@ -82,7 +86,12 @@ export class ExpensesPageComponent implements OnInit { switchMap(c => result.receipt ? this.api.uploadReceipt(c.id, result.receipt).pipe(switchMap(() => of(c))) : of(c)), - ).subscribe(() => { this.reimbDialogOpen = false; this.load(); }); + ).subscribe(() => { + // In continuous-entry mode the dialog resets itself and stays open for the next entry. + if (!result.continueEntry) this.reimbDialogOpen = false; + this.showToast('已儲存 ✓ Saved'); + this.load(); + }); } openEdit(row: ExpenseListItemDto): void { @@ -150,6 +159,12 @@ export class ExpensesPageComponent implements OnInit { //should be pay by disbursement } + private showToast(message: string): void { + this.toast = message; + if (this.toastTimer) clearTimeout(this.toastTimer); + this.toastTimer = setTimeout(() => (this.toast = null), 2200); + } + statusClass(status: string): string { return ({ Draft: 'badge-draft', diff --git a/APP/src/app/features/expense/pages/my-reimbursements-page/my-reimbursements-page.component.html b/APP/src/app/features/expense/pages/my-reimbursements-page/my-reimbursements-page.component.html index 0dc3598..92de8b7 100644 --- a/APP/src/app/features/expense/pages/my-reimbursements-page/my-reimbursements-page.component.html +++ b/APP/src/app/features/expense/pages/my-reimbursements-page/my-reimbursements-page.component.html @@ -33,7 +33,7 @@
-
+
Loading…
No reimbursements yet.
diff --git a/APP/src/app/features/expense/pages/my-reimbursements-page/my-reimbursements-page.component.scss b/APP/src/app/features/expense/pages/my-reimbursements-page/my-reimbursements-page.component.scss index c18b130..88b237f 100644 --- a/APP/src/app/features/expense/pages/my-reimbursements-page/my-reimbursements-page.component.scss +++ b/APP/src/app/features/expense/pages/my-reimbursements-page/my-reimbursements-page.component.scss @@ -46,11 +46,9 @@ } // Mobile card list -.rmb-cards { - display: flex; - flex-direction: column; - gap: 12px; -} +// NOTE: display/flex layout lives on the element via Tailwind (flex flex-col gap-3) +// so the responsive `md:hidden` utility wins on desktop. Setting `display: flex` +// here would override `md:hidden` and leak the card list onto the desktop view. .rmb-empty { padding: 24px 0;