feat(giving): add sundayAttendanceCount model field and attendance setCounts API
ci-cd-vm / ci-cd (push) Successful in 2m21s

This commit is contained in:
Chris Chen
2026-06-24 11:26:16 -07:00
parent 28eba8a3ea
commit b0e2e112fc
20 changed files with 653 additions and 5 deletions
@@ -4,6 +4,7 @@
<label class="flex flex-col gap-1">Last name (EN) *<kendo-textbox [(ngModel)]="lastName_en"></kendo-textbox></label>
<label class="flex flex-col gap-1">名 (中)<kendo-textbox [(ngModel)]="firstName_zh"></kendo-textbox></label>
<label class="flex flex-col gap-1">姓 (中)<kendo-textbox [(ngModel)]="lastName_zh"></kendo-textbox></label>
<label class="flex flex-col gap-1 md:col-span-2">公司行號 · Company<kendo-textbox [(ngModel)]="entity"></kendo-textbox></label>
<label class="flex flex-col gap-1 md:col-span-2">Cell phone<kendo-textbox [(ngModel)]="phoneCell"></kendo-textbox></label>
</div>
<kendo-dialog-actions>
@@ -21,6 +21,7 @@ export class MemberQuickAddDialogComponent {
lastName_en = '';
firstName_zh: string | null = null;
lastName_zh: string | null = null;
entity: string | null = null;
phoneCell: string | null = null;
saving = false;
@@ -35,6 +36,7 @@ export class MemberQuickAddDialogComponent {
nickName: null,
firstName_zh: this.firstName_zh,
lastName_zh: this.lastName_zh,
entity: this.entity,
gender: null,
dateOfBirth: null,
baptismDate: null,
@@ -63,6 +65,7 @@ export class MemberQuickAddDialogComponent {
nickName: null,
firstName_zh: this.firstName_zh,
lastName_zh: this.lastName_zh,
entity: this.entity,
status: 'Visitor',
email: null,
phoneCell: this.phoneCell,
@@ -114,6 +114,7 @@ export interface OfferingSessionListItemDto {
difference: number;
lineCount: number;
hasProof: boolean;
sundayAttendanceCount?: number | null;
}
/** A row held in the client-side batch buffer before submit. */
@@ -129,6 +130,7 @@ export interface MemberTypeaheadDto {
nickName: string | null;
firstName_en: string;
lastName_en: string;
entity: string | null;
}
/** A day's session as the mobile page sees it. */
export interface OfferingEntrySummaryDto {
@@ -158,6 +160,7 @@ export interface QuickAddMemberRequest {
nickName: string | null;
firstName_zh: string | null;
lastName_zh: string | null;
entity: string | null;
phoneCell: string | null;
}
/** Returned from append + broadcast over the OfferingEntryHub. */
@@ -130,6 +130,10 @@
<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">公司行號 · Company</label>
<kendo-textbox class="oe__control" [(ngModel)]="quickAdd.entity" 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>
@@ -151,10 +151,11 @@ export class OfferingEntryMobilePageComponent implements OnInit, OnDestroy {
// is no nick name (or it's the same as the legal first name).
private giverLabel(m: MemberTypeaheadDto): string {
const legal = `${m.firstName_en} ${m.lastName_en}`.trim();
if (m.nickName && m.nickName !== m.firstName_en) {
return `${m.nickName} ${m.lastName_en} (${legal})`;
}
return legal;
const base = (m.nickName && m.nickName !== m.firstName_en)
? `${m.nickName} ${m.lastName_en} (${legal})`
: legal;
// Append the company / business name so a company-check giver is unambiguous.
return m.entity ? `${base} · ${m.entity}` : base;
}
onMemberSelected(id: number | null): void {
@@ -206,6 +207,7 @@ export class OfferingEntryMobilePageComponent implements OnInit, OnDestroy {
nickName: this.trimToNull(this.quickAdd.nickName),
firstName_zh: this.trimToNull(this.quickAdd.firstName_zh),
lastName_zh: this.trimToNull(this.quickAdd.lastName_zh),
entity: this.trimToNull(this.quickAdd.entity),
phoneCell: this.trimToNull(this.quickAdd.phoneCell),
};
this.api.quickAddMember(request).subscribe({
@@ -229,7 +231,7 @@ export class OfferingEntryMobilePageComponent implements OnInit, OnDestroy {
private blankQuickAdd(): QuickAddMemberRequest {
return {
firstName_en: '', lastName_en: '', nickName: null,
firstName_zh: null, lastName_zh: null, phoneCell: null,
firstName_zh: null, lastName_zh: null, entity: null, phoneCell: null,
};
}
@@ -22,4 +22,9 @@ export class MealAttendanceApiService {
const params = new HttpParams().set('from', from).set('to', to);
return this.http.get<AttendanceCounts[]>(this.endpoint, { params });
}
/** Overwrite a specific Sunday's counts (back-office editor). */
setCounts(date: string, counts: { adult: number; youth: number; kid: number }): Observable<AttendanceCounts> {
return this.http.put<AttendanceCounts>(`${this.endpoint}/${date}`, counts);
}
}
@@ -33,6 +33,11 @@
<kendo-textbox formControlName="lastName_zh"></kendo-textbox>
</kendo-formfield>
<kendo-formfield class="md:col-span-2">
<kendo-label text="公司行號 · Company / Entity"></kendo-label>
<kendo-textbox formControlName="entity" placeholder="e.g. ABC Trading Inc."></kendo-textbox>
</kendo-formfield>
<kendo-formfield>
<kendo-label text="Gender"></kendo-label>
<kendo-dropdownlist
@@ -43,6 +43,7 @@ export class MemberFormDialogComponent implements OnInit {
nickName: [this.member?.nickName ?? null, Validators.maxLength(100)],
firstName_zh: [this.member?.firstName_zh ?? null, Validators.maxLength(100)],
lastName_zh: [this.member?.lastName_zh ?? null, Validators.maxLength(100)],
entity: [this.member?.entity ?? null, Validators.maxLength(200)],
gender: [this.member?.gender ?? null],
dateOfBirth: [this.member?.dateOfBirth ?? null],
status: [this.member?.status ?? 'Member', Validators.required],
@@ -7,6 +7,7 @@ export interface MemberListItemDto {
nickName: string | null;
firstName_zh: string | null;
lastName_zh: string | null;
entity: string | null;
status: MemberStatus;
email: string | null;
phoneCell: string | null;
@@ -39,6 +40,7 @@ export interface CreateMemberRequest {
nickName: string | null;
firstName_zh: string | null;
lastName_zh: string | null;
entity: string | null;
gender: string | null;
dateOfBirth: string | null;
baptismDate: string | null;