Files
ROLAC/APP/src/app/features/giving/pages/offering-entry-mobile-page/offering-entry-mobile-page.component.html
T
Chris Chen 2e226e60f5
ci-cd-vm / ci-cd (push) Failing after 1m13s
update mobile view.
2026-06-23 14:18:55 -07:00

231 lines
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div class="oe">
<div class="oe__inner">
<header class="oe__head">
<span class="oe__eyebrow">River of Life · Offering</span>
<h1 class="oe__title">主日奉獻錄入 <span>Sunday Offering Entry</span></h1>
<div class="oe__date">{{ sessionDate | date:'EEE, MMM d, y' }}</div>
<div class="oe__status" [class.is-on]="connected">
<span class="oe__dot"></span>
{{ connected ? '即時同步中 · Live' : '連線中… · Connecting' }}
</div>
</header>
<!-- Today's running tally (live across phones) -->
<div class="oe__tally">
<div class="oe__tally-item">
<span class="oe__tally-num">{{ lineCount }}</span>
<span class="oe__tally-label">今日筆數 · Lines</span>
</div>
<div class="oe__tally-divider"></div>
<button type="button" class="oe__tally-item oe__tally-item--btn" (click)="openTotals()">
<span class="oe__tally-num">{{ systemTotal | currency }}</span>
<span class="oe__tally-label">今日總額 · Total <span class="oe__tally-hint"></span></span>
</button>
<div class="oe__tally-divider"></div>
<!-- Day-level paper proof (the whole session's count sheet / envelopes), not
any single line — lives here, beside the running tally, on purpose. -->
<button type="button" class="oe__tally-item oe__tally-item--btn oe__tally-item--proof"
[class.is-attached]="hasProof" (click)="openPaperProof()">
<span class="oe__tally-num oe__tally-icon">{{ hasProof ? '📎' : '' }}</span>
<span class="oe__tally-label">紙本證明 · Proof</span>
</button>
</div>
<!-- Entry form -->
<section class="oe__card">
<div class="oe__field">
<label class="oe__label">奉獻人 · Giver</label>
<kendo-combobox *ngIf="!entry.isAnonymous"
class="oe__control"
[data]="memberResults" textField="displayName" valueField="id" [valuePrimitive]="true"
[filterable]="true" (filterChange)="onMemberFilter($event)"
[(ngModel)]="selectedMemberId" (valueChange)="onMemberSelected($event)"
size="large" placeholder="輸入姓名搜尋 · Search by name"></kendo-combobox>
<div *ngIf="entry.isAnonymous" class="oe__anon">
<span class="oe__anon-chip">匿名 · Anonymous</span>
<button kendoButton fillMode="flat" themeColor="primary" size="large"
(click)="clearAnonymous()">改回填寫 · Clear</button>
</div>
<div *ngIf="!entry.isAnonymous" class="oe__giver-actions">
<button kendoButton fillMode="outline" size="large"
(click)="openQuickAdd()"> 快速新增 · Quick add</button>
<button kendoButton fillMode="outline" size="large"
(click)="markAnonymous()">設為匿名 · Anonymous</button>
</div>
</div>
<div class="oe__field">
<label class="oe__label">類別 · Type</label>
<kendo-dropdownlist class="oe__control"
[data]="categories" textField="label" valueField="id" [valuePrimitive]="true"
[(ngModel)]="entry.givingCategoryId" size="large"></kendo-dropdownlist>
</div>
<div class="oe__field">
<label class="oe__label">付款方式 · Method</label>
<kendo-dropdownlist class="oe__control"
[data]="paymentMethods" textField="label" valueField="value" [valuePrimitive]="true"
[(ngModel)]="entry.paymentMethod" size="large"></kendo-dropdownlist>
</div>
<div class="oe__field" *ngIf="entry.paymentMethod === 'Check'">
<label class="oe__label">支票號碼 · Check #</label>
<kendo-textbox class="oe__control" [(ngModel)]="entry.checkNumber" size="large"></kendo-textbox>
</div>
<div class="oe__field" *ngIf="entry.paymentMethod === 'Zelle'">
<label class="oe__label">Zelle 參考碼 · Reference</label>
<kendo-textbox class="oe__control" [(ngModel)]="entry.zelleReferenceCode" size="large"></kendo-textbox>
</div>
<div class="oe__field" *ngIf="entry.paymentMethod === 'PayPal'">
<label class="oe__label">PayPal 交易編號 · Txn ID</label>
<kendo-textbox class="oe__control" [(ngModel)]="entry.payPalTransactionId" size="large"></kendo-textbox>
</div>
<div class="oe__field">
<label class="oe__label">金額 · Amount</label>
<kendo-numerictextbox class="oe__control"
[(ngModel)]="entry.amount" [min]="0" [format]="'c2'" size="large"></kendo-numerictextbox>
</div>
<div class="oe__field">
<label class="oe__label">備註 · Notes</label>
<kendo-textbox class="oe__control" [(ngModel)]="entry.notes" size="large"></kendo-textbox>
</div>
</section>
</div>
<!-- Sticky submit bar -->
<div class="oe__submit">
<button kendoButton themeColor="primary" size="large" class="oe__submit-btn"
[disabled]="!canSubmit" (click)="submit()">
{{ submitting ? '送出中… · Submitting' : '送出 · Submit' }}
</button>
</div>
<div *ngIf="toast" class="oe__toast">{{ toast }}</div>
<!-- Quick-add member -->
<kendo-dialog *ngIf="showQuickAdd" title="快速新增會友 · Quick add member"
(close)="cancelQuickAdd()" [minWidth]="280" [width]="'95vw'" [maxWidth]="360">
<div class="oe__qa">
<div class="oe__field">
<label class="oe__label">英文名 · Legal first name *</label>
<kendo-textbox class="oe__control" [(ngModel)]="quickAdd.firstName_en" size="large"></kendo-textbox>
</div>
<div class="oe__field">
<label class="oe__label">英文姓 · Last name *</label>
<kendo-textbox class="oe__control" [(ngModel)]="quickAdd.lastName_en" size="large"></kendo-textbox>
</div>
<div class="oe__field">
<label class="oe__label">暱稱 · Nick name</label>
<kendo-textbox class="oe__control" [(ngModel)]="quickAdd.nickName" size="large"></kendo-textbox>
</div>
<div class="oe__field">
<label class="oe__label">中文名 · Chinese first name</label>
<kendo-textbox class="oe__control" [(ngModel)]="quickAdd.firstName_zh" size="large"></kendo-textbox>
</div>
<div class="oe__field">
<label class="oe__label">中文姓 · Chinese last name</label>
<kendo-textbox class="oe__control" [(ngModel)]="quickAdd.lastName_zh" size="large"></kendo-textbox>
</div>
<div class="oe__field">
<label class="oe__label">手機 · Cell phone</label>
<kendo-textbox class="oe__control" [(ngModel)]="quickAdd.phoneCell" size="large"></kendo-textbox>
</div>
</div>
<kendo-dialog-actions>
<button kendoButton (click)="cancelQuickAdd()">取消 · Cancel</button>
<button kendoButton themeColor="primary" [disabled]="!canSaveQuickAdd" (click)="saveQuickAdd()">
{{ quickAddSaving ? '新增中… · Saving' : '新增 · Add' }}
</button>
</kendo-dialog-actions>
</kendo-dialog>
<!-- Today's totals: payment-method breakdown + per-check detail -->
<kendo-dialog *ngIf="showTotals" title="今日總計 · Today's Totals"
(close)="closeTotals()" [minWidth]="280" [width]="'95vw'" [maxWidth]="360">
<div class="oe__qa">
<p *ngIf="totalsLoading" class="oe__totals-loading">載入中… · Loading</p>
<ng-container *ngIf="!totalsLoading">
<!-- By payment method -->
<div class="oe__totals-section">
<h3 class="oe__totals-heading">各付款方式 · By method</h3>
<ul class="oe__totals-list">
<li *ngFor="let row of methodSubtotals" class="oe__totals-row">
<span class="oe__totals-name">{{ row.label }}</span>
<span class="oe__totals-amount">{{ row.total | currency }}</span>
</li>
<li *ngIf="!methodSubtotals.length" class="oe__totals-empty">今日尚無紀錄 · No entries yet</li>
</ul>
</div>
<!-- Per-check detail -->
<div class="oe__totals-section">
<h3 class="oe__totals-heading">各支票 · Checks</h3>
<ul class="oe__totals-list">
<li *ngFor="let check of checkLines" class="oe__totals-row">
<span class="oe__totals-name"># {{ check.checkNumber || '(無號碼 · no #)' }}</span>
<span class="oe__totals-amount">{{ check.amount | currency }}</span>
</li>
<li *ngIf="!checkLines.length" class="oe__totals-empty">今日無支票 · No checks</li>
</ul>
<div *ngIf="checkLines.length" class="oe__totals-row oe__totals-row--subtotal">
<span class="oe__totals-name">支票合計 · Check total</span>
<span class="oe__totals-amount">{{ checkTotal | currency }}</span>
</div>
</div>
<!-- Grand total -->
<div class="oe__totals-row oe__totals-row--grand">
<span class="oe__totals-name">今日總計 · Total</span>
<span class="oe__totals-amount">{{ grandTotal | currency }}</span>
</div>
</ng-container>
</div>
<kendo-dialog-actions>
<button kendoButton themeColor="primary" (click)="closeTotals()">關閉 · Close</button>
</kendo-dialog-actions>
</kendo-dialog>
<!-- Add paper proof: capture photos / pick files → compress + merge to one PDF -->
<kendo-dialog *ngIf="showPaperProof" title="新增 Paper Proof · 紙本證明"
(close)="cancelPaperProof()" [minWidth]="280" [width]="'95vw'" [maxWidth]="360">
<div class="oe__qa">
<p class="oe__proof-hint">附上點算單/信封的照片或 PDF · Photo or PDF of the count sheet / envelopes</p>
<!-- Hidden native inputs, driven by the buttons below. -->
<input #cameraInput type="file" hidden accept="image/*" capture="environment"
(change)="onProofFilesSelected($event)" />
<input #libraryInput type="file" hidden multiple accept="image/*,application/pdf"
(change)="onProofFilesSelected($event)" />
<div class="oe__proof-actions">
<button kendoButton fillMode="outline" size="large" (click)="cameraInput.click()">
📷 拍照 · Camera
</button>
<button kendoButton fillMode="outline" size="large" (click)="libraryInput.click()">
🖼️ 相簿/檔案 · Library
</button>
</div>
<ul *ngIf="paperProofFiles.length" class="oe__proof-list">
<li *ngFor="let file of paperProofFiles; let i = index" class="oe__proof-item">
<span class="oe__proof-name">{{ file.name }}</span>
<button kendoButton fillMode="flat" size="small" (click)="removeProofFile(i)">×</button>
</li>
</ul>
<p *ngIf="hasProof" class="oe__proof-merge">將與現有證明合併 · Will be merged with the existing proof</p>
</div>
<kendo-dialog-actions>
<button kendoButton (click)="cancelPaperProof()">取消 · Cancel</button>
<button kendoButton themeColor="primary" [disabled]="!canSavePaperProof" (click)="savePaperProof()">
{{ paperProofSaving ? '處理中… · Saving' : '附加 · Attach' }}
</button>
</kendo-dialog-actions>
</kendo-dialog>
</div>