feat(giving): keyboard-first Sunday offering batch entry page + routes
- Add MemberQuickAddDialogComponent for fast in-session member creation - Add OfferingSessionPageComponent: client-side buffer, reconcile totals, date-conflict check, submit to API - Wire finance/giving-categories, finance/givings, finance/offering-session routes (RoleGuard: finance + super_admin) - Fix givings-page: replace [total] + data[] with GridDataResult for Kendo v20 server-side paging Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+70
@@ -0,0 +1,70 @@
|
||||
<div class="page">
|
||||
<header class="page-header">
|
||||
<h2>Sunday Offering Entry / 主日奉獻錄入</h2>
|
||||
<label>Date
|
||||
<kendo-datepicker [(ngModel)]="sessionDate" (valueChange)="checkDate()"></kendo-datepicker>
|
||||
</label>
|
||||
</header>
|
||||
|
||||
<div *ngIf="dateConflict" class="warn">
|
||||
An offering session for this date already exists. Pick another date, or reopen the existing session to edit.
|
||||
</div>
|
||||
|
||||
<section class="entry-row">
|
||||
<label *ngIf="!entry.isAnonymous">Giver
|
||||
<kendo-dropdownlist [data]="memberResults" textField="displayName" valueField="id"
|
||||
[valuePrimitive]="true" [filterable]="true"
|
||||
(filterChange)="onMemberFilter($event)" [(ngModel)]="selectedMemberId"
|
||||
(valueChange)="onMemberSelected($event)" placeholder="Search by name"></kendo-dropdownlist>
|
||||
</label>
|
||||
<span *ngIf="entry.isAnonymous" class="anon-chip">Anonymous</span>
|
||||
|
||||
<label>Type
|
||||
<kendo-dropdownlist [data]="categories" textField="name_en" valueField="id"
|
||||
[valuePrimitive]="true" [(ngModel)]="entry.givingCategoryId"></kendo-dropdownlist>
|
||||
</label>
|
||||
<label>Method
|
||||
<kendo-dropdownlist [data]="paymentMethods" [(ngModel)]="entry.paymentMethod"></kendo-dropdownlist>
|
||||
</label>
|
||||
<label *ngIf="entry.paymentMethod === 'Check'">Check #<kendo-textbox [(ngModel)]="entry.checkNumber"></kendo-textbox></label>
|
||||
<label>Amount
|
||||
<kendo-numerictextbox [(ngModel)]="entry.amount" [min]="0" [format]="'c2'" (keydown.enter)="addLine()"></kendo-numerictextbox>
|
||||
</label>
|
||||
<label>Notes<kendo-textbox [(ngModel)]="entry.notes" (keydown.enter)="addLine()"></kendo-textbox></label>
|
||||
|
||||
<div class="entry-actions">
|
||||
<button kendoButton (click)="markAnonymous()">Anonymous</button>
|
||||
<button kendoButton (click)="showQuickAdd = true">+ Quick add member</button>
|
||||
<button kendoButton themeColor="primary" (click)="addLine()">+ Add (Enter)</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<kendo-grid [data]="buffer">
|
||||
<kendo-grid-column title="Giver">
|
||||
<ng-template kendoGridCellTemplate let-l>{{ l.isAnonymous ? '(Anonymous)' : l.memberName }}</ng-template>
|
||||
</kendo-grid-column>
|
||||
<kendo-grid-column field="categoryName" title="Type"></kendo-grid-column>
|
||||
<kendo-grid-column field="paymentMethod" title="Method" [width]="90"></kendo-grid-column>
|
||||
<kendo-grid-column field="checkNumber" title="Check #" [width]="90"></kendo-grid-column>
|
||||
<kendo-grid-column field="amount" title="Amount" [width]="110" format="c2"></kendo-grid-column>
|
||||
<kendo-grid-column title="" [width]="120">
|
||||
<ng-template kendoGridCellTemplate let-l let-i="rowIndex">
|
||||
<button kendoButton fillMode="flat" (click)="editLine(i)">Edit</button>
|
||||
<button kendoButton fillMode="flat" (click)="removeLine(i)">×</button>
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
</kendo-grid>
|
||||
|
||||
<section class="reconcile">
|
||||
<div>Lines: {{ buffer.length }} | System total: {{ systemTotal | currency }}</div>
|
||||
<label>Cash counted<kendo-numerictextbox [(ngModel)]="cashTotal" [min]="0" [format]="'c2'"></kendo-numerictextbox></label>
|
||||
<label>Check counted<kendo-numerictextbox [(ngModel)]="checkTotal" [min]="0" [format]="'c2'"></kendo-numerictextbox></label>
|
||||
<div [class.ok]="difference === 0" [class.bad]="difference !== 0">Difference: {{ difference | currency }}</div>
|
||||
<button kendoButton themeColor="primary"
|
||||
[disabled]="buffer.length === 0 || dateConflict || submitting" (click)="submit()">Submit</button>
|
||||
</section>
|
||||
|
||||
<app-member-quick-add-dialog *ngIf="showQuickAdd"
|
||||
(created)="onMemberQuickCreated($event)"
|
||||
(cancelled)="showQuickAdd = false"></app-member-quick-add-dialog>
|
||||
</div>
|
||||
Reference in New Issue
Block a user