feat(i18n): add central bilingual option lists for enum dropdowns

This commit is contained in:
Chris Chen
2026-05-29 22:04:18 -07:00
parent a99755a5db
commit 4bee06addb
2 changed files with 94 additions and 0 deletions
@@ -0,0 +1,37 @@
import {
PAYMENT_METHOD_OPTIONS, EXPENSE_STATUS_OPTIONS, MEMBER_STATUS_OPTIONS,
GENDER_OPTIONS, LANGUAGE_OPTIONS, ROLE_OPTIONS,
} from './option-lists';
describe('option-lists', () => {
it('payment methods preserve raw values and show bilingual labels', () => {
expect(PAYMENT_METHOD_OPTIONS.map(o => o.value))
.toEqual(['Cash', 'Check', 'Zelle', 'PayPal', 'Other']);
expect(PAYMENT_METHOD_OPTIONS.find(o => o.value === 'Cash')!.label).toBe('Cash/現金');
expect(PAYMENT_METHOD_OPTIONS.find(o => o.value === 'Zelle')!.label).toBe('Zelle');
});
it('expense statuses preserve raw enum values', () => {
expect(EXPENSE_STATUS_OPTIONS.map(o => o.value))
.toEqual(['Draft', 'PendingApproval', 'Approved', 'Paid', 'Rejected']);
});
it('member statuses preserve raw values', () => {
expect(MEMBER_STATUS_OPTIONS.map(o => o.value))
.toEqual(['Member', 'Visitor', 'Inactive', 'Former']);
});
it('gender values stay M/F/Other', () => {
expect(GENDER_OPTIONS.map(o => o.value)).toEqual(['M', 'F', 'Other']);
});
it('language values stay en/zh-TW', () => {
expect(LANGUAGE_OPTIONS.map(o => o.value)).toEqual(['en', 'zh-TW']);
});
it('role options cover all 13 role codes', () => {
expect(ROLE_OPTIONS.length).toBe(13);
expect(ROLE_OPTIONS.map(o => o.value)).toContain('super_admin');
expect(ROLE_OPTIONS.map(o => o.value)).toContain('visitor');
});
});
+57
View File
@@ -0,0 +1,57 @@
/**
* Central bilingual option lists for hard-coded enum dropdowns.
* `value` is the raw value stored/sent to the API (unchanged from before);
* `label` is the display string `英文/中文`. Bind in templates with
* textField="label" valueField="value" [valuePrimitive]="true".
*/
export interface BilingualOption { readonly value: string; readonly label: string; }
export const PAYMENT_METHOD_OPTIONS: readonly BilingualOption[] = [
{ value: 'Cash', label: 'Cash/現金' },
{ value: 'Check', label: 'Check/支票' },
{ value: 'Zelle', label: 'Zelle' },
{ value: 'PayPal', label: 'PayPal' },
{ value: 'Other', label: 'Other/其他' },
];
export const EXPENSE_STATUS_OPTIONS: readonly BilingualOption[] = [
{ value: 'Draft', label: 'Draft/草稿' },
{ value: 'PendingApproval', label: 'PendingApproval/待審核' },
{ value: 'Approved', label: 'Approved/已核准' },
{ value: 'Paid', label: 'Paid/已付款' },
{ value: 'Rejected', label: 'Rejected/已拒絕' },
];
export const MEMBER_STATUS_OPTIONS: readonly BilingualOption[] = [
{ value: 'Member', label: 'Member/會友' },
{ value: 'Visitor', label: 'Visitor/訪客' },
{ value: 'Inactive', label: 'Inactive/未活躍' },
{ value: 'Former', label: 'Former/已離開' },
];
export const GENDER_OPTIONS: readonly BilingualOption[] = [
{ value: 'M', label: 'Male/男' },
{ value: 'F', label: 'Female/女' },
{ value: 'Other', label: 'Other/其他' },
];
export const LANGUAGE_OPTIONS: readonly BilingualOption[] = [
{ value: 'en', label: 'English/英文' },
{ value: 'zh-TW', label: '中文/Chinese' },
];
export const ROLE_OPTIONS: readonly BilingualOption[] = [
{ value: 'super_admin', label: 'Super Admin/系統管理員' },
{ value: 'pastor', label: 'Pastor/牧師' },
{ value: 'board_member', label: 'Board Member/理事' },
{ value: 'coworker_chair', label: 'Coworker Chair/同工會主席' },
{ value: 'ministry_leader', label: 'Ministry Leader/事工領袖' },
{ value: 'district_leader', label: 'District Leader/區長' },
{ value: 'cell_leader', label: 'Cell Leader/小組長' },
{ value: 'coworker', label: 'Coworker/同工' },
{ value: 'finance', label: 'Finance/財務同工' },
{ value: 'secretary', label: 'Secretary/行政秘書' },
{ value: 'worship_leader', label: 'Worship Leader/敬拜領袖' },
{ value: 'member', label: 'Member/一般教友' },
{ value: 'visitor', label: 'Visitor/訪客' },
];