Initial commit: monorepo scaffold for ROLAC

- Add .gitignore covering C#/.NET and Angular/Node
- Add placeholder structure for API (C#) and APP (Angular)
- Add project docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Chris Chen
2026-05-24 20:54:10 -07:00
commit 9b28fbcfb6
11 changed files with 4215 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
# ============================================================
# C# / .NET
# ============================================================
bin/
obj/
*.user
*.suo
.vs/
*.vspscc
*.vssscc
_ReSharper*/
*.DotSettings.user
TestResults/
*.ncrunch*
*.pidb
*.swp
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp_proj
*.vsix
publish/
PublishProfiles/
# ASP.NET / EF
appsettings.Development.json
appsettings.Production.json
appsettings.Staging.json
Migrations/
# ============================================================
# Angular / Node
# ============================================================
node_modules/
dist/
.angular/
.cache/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnp
.pnp.js
*.tsbuildinfo
# ============================================================
# Environment & Secrets
# ============================================================
.env
.env.*
*.pfx
*.p12
secrets.json
serviceAccountKey.json
# ============================================================
# OS
# ============================================================
.DS_Store
Thumbs.db
Desktop.ini
$RECYCLE.BIN/
# ============================================================
# IDE
# ============================================================
.idea/
*.iml
.vscode/
*.code-workspace
# ============================================================
# Claude Code (local settings only)
# ============================================================
.claude/settings.local.json
# ============================================================
# Logs & Temp
# ============================================================
logs/
*.log
*.tmp
*.temp
View File
View File
+205
View File
@@ -0,0 +1,205 @@
# River Of Life Christian Church In Arcadia
# 教會管理系統 — 理事會報告
**報告日期:** 2026 年 5 月 24 日
**系統名稱:** ROLAC Church Management System
**目標上線:** 2026 年 6 月(第一階段)
---
## 一、為什麼需要這套系統?
| 目前痛點 | 系統解決方案 |
|----------|-------------|
| 教友資料分散於多份 Excel | 集中管理,隨時查詢 |
| 奉獻記錄手工計算,容易出錯 | 系統自動加總,月底一鍵對帳 |
| 年底收據需人工製作 | 自動產生 IRS 合規 PDFEmail 寄出 |
| 支出報銷流程不透明 | 線上申請、財務審核、留存記錄 |
| 教會網站資訊無法即時更新 | 行政同工自行發佈消息,無需工程師 |
---
## 二、系統架構概覽
系統分為三個部分,**全部使用同一套系統管理**:
```
┌─────────────────────────────────────────────┐
│ rolac.org(教會公開網站) │
│ 供訪客、慕道友瀏覽 │
├─────────────────────────────────────────────┤
│ 後台管理系統(行政、財務、事工負責人使用) │
├─────────────────────────────────────────────┤
│ 教友 App(手機 App,教友查看個人資訊) │
└─────────────────────────────────────────────┘
```
**支援語言:** 英文 + 繁體中文雙語切換
**支援設備:** 電腦、平板、手機(iOS + Android App
---
## 四、開發階段規劃
---
### 🏗️ 準備階段(現在 → 6 月初,約 2 週)
> 建立技術基礎,為所有功能打地基。教友不會直接感受到,但這是系統能正常運作的前提。
**主要工作:**
- 架設雲端伺服器
- 建立系統骨架與帳號安全機制
- 設定自動部署流程
---
### 🚀 第一階段(Phase 1)— 目標 2026 年 6 月上線
> **核心目標:** 網站上線 + 教友資料數位化 + 財務透明化
#### 📌 功能 1:教會官方網站(rolac.org
| 功能 | 說明 |
|------|------|
| 教會首頁 | 歡迎頁面、教會簡介、異象 |
| 主日資訊 | 聚會時間、地點、Google Maps |
| 消息公告 | 行政同工自行發佈,雙語顯示 |
| 講道影片 | 嵌入 YouTube 最新講道 |
| 聯絡表單 | 訪客留言,通知指定同工 |
**誰受益:** 訪客、慕道友、全體教友
---
#### 📌 功能 2:教友管理
| 功能 | 說明 |
|------|------|
| 教友資料建檔 | 姓名(中英)、照片、聯絡資料、受洗日期 |
| 家庭單元 | 一個家庭多位成員,清楚呈現家庭關係 |
| 教友狀態 | 會員 / 訪客 / 前會員 分類管理 |
| 搜尋篩選 | 按姓名、狀態、事工快速搜尋 |
| 事工歸屬 | 記錄每位教友參與的事工部門 |
**誰受益:** 牧師、行政秘書、各事工負責人
---
#### 📌 功能 3:財務管理(奉獻 + 支出 + 月結)
**奉獻記錄**
| 功能 | 說明 |
|------|------|
| 主日奉獻快速錄入 | 財務同工開袋後逐筆輸入,系統即時加總,最後核對實收金額 |
| 支付方式 | 現金、支票(含支票號碼)、Zelle、PayPal |
| 個人奉獻查詢 | 教友可在 App 查看自己的歷年奉獻記錄 |
| **年度奉獻收據** | 年底自動產生 IRS 合規 PDF,Email 寄給每位教友 |
**支出記錄**
| 功能 | 說明 |
|------|------|
| 廠商付款 | 直接記錄(如:愛宴外燴支票),含支票號碼 |
| 同工代墊報銷 | 同工提交申請 + 拍收據照片 → 財務審核 → 標記已還款 |
| 支出分類 | 依事工部門 + 類別(餐飲、設備、教材…)分類 |
**月底對帳**
| 功能 | 說明 |
|------|------|
| 收支月結報表 | 期初餘額 + 奉獻收入 − 各項支出 = 帳面結餘 |
| 銀行對帳 | 輸入銀行對帳單餘額,系統顯示差異,目標為零 |
**誰受益:** 財務同工、牧師、理事會
---
### 📦 第二階段(Phase 2
| 功能模組 | 說明 |
|----------|------|
| **服事表排班** | 各事工排班、自動提醒(服事前 3 天通知)、缺席替換 |
| **主日出席統計** | 每週記錄大人 / 青少年 / 兒童人數,產生趨勢圖 |
| **小組管理** | 管理小組架構、組長指派、小組聚會出席記錄 |
### 📦 第三階段(Phase 3
| 功能模組 | 說明 |
|----------|------|
| **事工預算** | 各事工年度預算設定,對比實際支出,超支自動警示 |
### 📦 第四階段(Phase 4
| 功能模組 | 說明 |
|----------|------|
| **線上奉獻** | 網站直接刷卡奉獻(Stripe)、定期自動扣款 |
### ⏸️ 暫緩功能(未來再評估)
| 功能模組 | 說明 |
|----------|------|
| **敬拜歌曲庫** | 詩歌歌詞管理、敬拜歌單規劃(待 CCLI 版權確認後排入) |
| **事工報表** | 教友成長趨勢、出席率、奉獻摘要圖表 |
| **廣播通知** | 向全體或特定事工群發 Email / 推播 / 簡訊 |
---
## 五、各事工部門對應
以下 10 個事工部門已納入系統,各部門負責人擁有專屬的資料存取權限:
| 事工部門 | 可管理的資料 |
|----------|-------------|
| 行政 | 全教友資料、財務報表 |
| 講道 | 自身服事排班 |
| 司會 | 自身服事排班 |
| 敬拜 | 服事排班、敬拜歌曲庫 |
| PPT/影音 | 服事排班、影音設備支出 |
| 音控 | 服事排班 |
| 場地組 | 服事排班、場地支出 |
| 招待 | 服事排班 |
| 兒牧 | 自身教友資料、兒童出席 |
| 餐飲 | 服事排班、餐飲支出(愛宴) |
---
## 六、用戶角色與權限
不同角色的同工看到的功能不同,**確保敏感資料只有授權人員可查看**:
| 角色 | 可查看的資料範圍 |
|------|----------------|
| 牧師 | 全部,含財務摘要 |
| 理事 | 教友概覽、財務摘要(唯讀)|
| 同工會主席 | 教友資料、服事排班、小組管理、報表 |
| 事工領袖 | 僅限自身事工的教友與排班資料 |
| 區長 | 轄下小組的教友資料 |
| 小組長 | 自身小組成員資料 |
| 財務同工 | 全部奉獻與支出記錄 |
| 行政秘書 | 教友資料、排班管理 |
| 同工 | 自身事工資料、可申請費用報銷 |
| 一般教友 | 個人資料、個人奉獻記錄、公開服事表 |
---
## 七、里程碑時間表
```
Phase 0 → Phase 1 → Phase 2 → Phase 3 → Phase 4
準備 上線 服事/ 預算 線上
建設 網站+ 小組管理 奉獻
教友+
財務
```
| 里程碑 | 階段 |
|--------|------|
| 伺服器建置完成 | Phase 0 |
| 教會網站上線(rolac.org| Phase 1 |
| 教友管理系統上線 | Phase 1 |
| 財務記錄系統上線 | Phase 1 |
| 服事表 + 小組管理 | Phase 2 |
| 事工預算 | Phase 3 |
| 線上奉獻 | Phase 4 |
+1097
View File
File diff suppressed because it is too large Load Diff
+462
View File
@@ -0,0 +1,462 @@
# ROLAC — Infrastructure Design
**平台:** Microsoft Azure (Nonprofit $2,000 Credit)
**文件版本:** v0.1 (2026-05-24)
---
## 目錄
1. [Azure 資源規劃](#1-azure-資源規劃)
2. [VM 容器架構](#2-vm-容器架構)
3. [Docker Compose 服務清單](#3-docker-compose-服務清單)
4. [網路與 DNS](#4-網路與-dns)
5. [Nginx 反向代理路由](#5-nginx-反向代理路由)
6. [CI/CD Pipeline (Jenkins + Gitea)](#6-cicd-pipeline-jenkins--gitea)
7. [Azure Storage Account 使用規劃](#7-azure-storage-account-使用規劃)
8. [備份策略](#8-備份策略)
9. [成本估算 (Monthly)](#9-成本估算-monthly)
10. [部署步驟清單](#10-部署步驟清單)
---
## 1. Azure 資源規劃
| 資源 | 規格 | 用途 | 估計月費 |
|------|------|------|----------|
| **Azure VM** | Standard B2s (2 vCPU / 4 GB RAM) | 主機:所有 Docker 容器 | ~$3035/月 |
| **Azure Storage Account** | LRS, Cool tier | Blob 儲存(照片/PDF/媒體) | ~$25/月 |
| **Azure Static Public IP** | Standard | 固定對外 IP | ~$4/月 |
| **Azure DNS Zone** *(可選)* | — | 管理 DNS 記錄 | ~$0.5/月 |
| **OS Disk** | Premium SSD 64 GB | VM 系統碟 | ~$10/月 |
| **資料磁碟** | Standard SSD 128 GB | Docker volumesDB、Gitea、Jenkins | ~$11/月 |
> **總估算: ~$5765/月**,年約 $700,在 $2,000 Credit 範圍內可運行約 **30 個月**。
> 若流量低,可降級至 **B1ms (1 vCPU / 2 GB)** 節省至 ~$15/月。
---
## 2. VM 容器架構
```
Azure VM (Ubuntu 22.04 LTS)
├── /data/ ← 資料磁碟掛載點
│ ├── postgres/ ← PostgreSQL data
│ ├── gitea/ ← Gitea repos & config
│ ├── jenkins/ ← Jenkins home
│ └── nginx/certs/ ← SSL 憑證
└── Docker Engine
├── [nginx] :80, :443 ← 反向代理 + SSL 終止
├── [angular-app] :4200 ← Angular SPA (nginx serve)
├── [rolac-api] :5000 ← ASP.NET Core API
├── [postgres] :5432 ← PostgreSQL 14+
├── [gitea] :3000, :22 ← 原始碼管理
└── [jenkins] :8080 ← CI/CD
```
---
## 3. Docker Compose 服務清單
```yaml
# docker-compose.yml (簡化草圖)
version: '3.9'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/certs:/etc/letsencrypt
depends_on:
- angular-app
- rolac-api
angular-app:
image: rolac/frontend:latest # 由 Jenkins build
expose:
- "80"
restart: unless-stopped
rolac-api:
image: rolac/api:latest # 由 Jenkins build
expose:
- "5000"
environment:
- ConnectionStrings__Default=Host=postgres;...
- Azure__StorageAccount__ConnectionString=...
- Jwt__Secret=${JWT_SECRET}
depends_on:
- postgres
restart: unless-stopped
postgres:
image: postgres:16-alpine
volumes:
- /data/postgres:/var/lib/postgresql/data
environment:
- POSTGRES_DB=rolac
- POSTGRES_USER=${DB_USER}
- POSTGRES_PASSWORD=${DB_PASSWORD}
expose:
- "5432"
restart: unless-stopped
gitea:
image: gitea/gitea:latest
ports:
- "2222:22" # Git SSH
expose:
- "3000" # Web UI (透過 nginx 代理)
volumes:
- /data/gitea:/data
restart: unless-stopped
jenkins:
image: jenkins/jenkins:lts-jdk21
expose:
- "8080" # Web UI (透過 nginx 代理)
volumes:
- /data/jenkins:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock # Jenkins 可操作 Docker
restart: unless-stopped
```
> **Secrets 管理:** 使用 `.env` 檔搭配 `docker-compose --env-file`**不得** commit 到 Gitea。
---
## 4. 網路與 DNS
```
Internet
Azure Public IP (Static)
Azure NSG (Network Security Group)
├── Port 80 (HTTP → 轉 443)
├── Port 443 (HTTPS)
└── Port 2222 (Git SSH)
Ubuntu VM → Docker → Nginx
```
**DNS 記錄 — rolac.org**
| 子域名 | 完整網址 | 類型 | 指向 | 用途 |
|--------|----------|------|------|------|
| `@` | rolac.org | A | VM Public IP | 教會公開網站(根域名) |
| `www` | www.rolac.org | CNAME | rolac.org | 同上(重定向) |
| `app` | app.rolac.org | A | VM Public IP | Angular 後台管理入口 |
| `api` | api.rolac.org | A | VM Public IP | ASP.NET Core REST API |
| `git` | git.rolac.org | A | VM Public IP | Gitea 原始碼管理 |
| `ci` | ci.rolac.org | A | VM Public IP | Jenkins CI/CD |
---
## 5. Nginx 反向代理路由
```nginx
# /nginx/conf.d/rolac.conf (草圖)
# HTTP → HTTPS redirect
server {
listen 80;
server_name *.rolac.org rolac.org;
return 301 https://$host$request_uri;
}
# 教會公開網站 (Angular SSR or static)
server {
listen 443 ssl;
server_name rolac.org www.rolac.org;
location / { proxy_pass http://angular-app:80; }
}
# 後台管理 App
server {
listen 443 ssl;
server_name app.rolac.org;
location / { proxy_pass http://angular-app:80; }
}
# API
server {
listen 443 ssl;
server_name api.rolac.org;
location / {
proxy_pass http://rolac-api:5000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
}
# Gitea
server {
listen 443 ssl;
server_name git.rolac.org;
location / { proxy_pass http://gitea:3000; }
}
# Jenkins
server {
listen 443 ssl;
server_name ci.rolac.org;
location / { proxy_pass http://jenkins:8080; }
}
```
**SSL 憑證 (Let's Encrypt)**
```bash
certbot certonly --webroot -w /data/nginx/www \
-d rolac.org \
-d www.rolac.org \
-d app.rolac.org \
-d api.rolac.org \
-d git.rolac.org \
-d ci.rolac.org
```
---
## 6. CI/CD Pipeline (Jenkins + Gitea)
### 流程圖
```
開發者 push → Gitea
│ Webhook (HTTP POST)
Jenkins Job
┌───────────┼───────────┐
▼ ▼ ▼
Build Test Lint
Docker dotnet ng lint
image test
Push image (Web) ← rolac.org & app.rolac.org 用
docker compose up -d
▼ (main branch only)
Capacitor Build ← 產出 iOS .ipa / Android .apk
npx cap build ios
npx cap build android
Health check
通知結果 (Email)
```
> **注意:** Capacitor build (iOS) 需要 macOS 環境,Jenkins 跑在 Linux VM 上只能產 Android APKiOS `.ipa` 需在 Mac 上另外 build 或使用 Xcode Cloud。
### Jenkinsfile 草圖
```groovy
pipeline {
agent any
environment {
API_IMAGE = "rolac/api:${BUILD_NUMBER}"
WEB_IMAGE = "rolac/frontend:${BUILD_NUMBER}"
}
stages {
stage('Checkout') {
steps { checkout scm }
}
stage('Test API') {
steps {
sh 'dotnet test ./backend/ROLAC.Tests'
}
}
stage('Build Images') {
parallel {
stage('API') {
steps {
sh 'docker build -t ${API_IMAGE} -t rolac/api:latest ./backend'
}
}
stage('Frontend (Web)') {
steps {
sh 'docker build -t ${WEB_IMAGE} -t rolac/frontend:latest ./frontend'
}
}
}
}
stage('Deploy Web') {
when { branch 'main' }
steps {
sh 'docker compose -f /opt/rolac/docker-compose.yml up -d --no-deps rolac-api angular-app'
}
}
stage('Build Android APK') {
when { branch 'main' }
steps {
dir('frontend') {
sh 'npm ci'
sh 'npm run build -- --configuration production'
sh 'npx cap sync android'
sh 'cd android && ./gradlew assembleRelease'
}
archiveArtifacts artifacts: 'frontend/android/app/build/outputs/apk/release/*.apk'
}
}
}
post {
failure { mail to: 'admin@rolac.org', subject: "Build FAILED: ${env.JOB_NAME} #${BUILD_NUMBER}" }
success { mail to: 'admin@rolac.org', subject: "Build OK: ${env.JOB_NAME} #${BUILD_NUMBER}" }
}
}
```
### Branch 策略
| Branch | 說明 | 部署 |
|--------|------|------|
| `main` | 正式版本 | 自動部署 Production |
| `develop` | 開發整合 | 自動部署 Staging (同 VM,不同 port) |
| `feature/*` | 功能開發 | 僅跑 Build + Test,不部署 |
| `hotfix/*` | 緊急修復 | 審核後 merge 至 main |
---
## 7. Azure Storage Account 使用規劃
### Container (Blob) 結構
```
rolac-storage (Storage Account)
├── members/
│ ├── photos/ ← 教友大頭照
│ └── documents/ ← 個人相關文件
├── receipts/
│ └── {year}/ ← 年度奉獻收據 PDF
├── cms/
│ ├── images/ ← 網站上傳圖片
│ └── attachments/ ← 公告附件
└── reports/
└── exports/ ← 匯出的報表 PDF/CSV
```
### 存取控制
| Container | 存取層級 | 說明 |
|-----------|----------|------|
| `members/` | **Private** | 僅 API 透過 SAS Token 存取 |
| `receipts/` | **Private** | API 產生限時下載連結給教友 |
| `cms/images/` | **Blob (Public Read)** | 網站圖片可公開存取 |
| `reports/` | **Private** | 僅管理員 API 存取 |
### C# 整合
```csharp
// 使用 Azure.Storage.Blobs SDK
// 上傳教友照片範例
var blobClient = new BlobContainerClient(connectionString, "members");
await blobClient.UploadBlobAsync($"photos/{memberId}.jpg", fileStream);
// 產生限時 SAS URL (收據下載)
var sasUri = blobClient.GenerateSasUri(BlobSasPermissions.Read,
DateTimeOffset.UtcNow.AddHours(1));
```
---
## 8. 備份策略
### PostgreSQL 備份
```bash
# crontab (每日 02:00 UTC 備份)
0 2 * * * docker exec postgres pg_dump -U rolac_user rolac \
| gzip > /data/backups/rolac_$(date +%Y%m%d).sql.gz
# 保留 30 天
find /data/backups -name "*.sql.gz" -mtime +30 -delete
```
### 備份上傳至 Azure Blob
```bash
# 使用 azcopy 或 Azure CLI 將備份上傳
azcopy copy "/data/backups/rolac_$(date +%Y%m%d).sql.gz" \
"https://rolacstorage.blob.core.windows.net/backups/"
```
### 備份範圍
| 資料 | 方式 | 頻率 | 保留 |
|------|------|------|------|
| PostgreSQL DB | pg_dump → Azure Blob | 每日 | 30 天 |
| Gitea repos | volume backup → Azure Blob | 每日 | 14 天 |
| Jenkins config | volume backup | 每週 | 4 週 |
| Azure Blob 本身 | Azure Soft Delete | 自動 | 7 天 |
---
## 9. 成本估算 (Monthly)
| 項目 | 規格 | 月費 (USD) |
|------|------|-----------|
| Azure VM | Standard_B2s | $30 |
| OS Disk | Premium SSD 64 GB | $10 |
| 資料磁碟 | Standard SSD 128 GB | $11 |
| Static Public IP | Standard | $4 |
| Storage Account | LRS 50 GB | $2 |
| 出站流量 | ~10 GB/月 | $1 |
| **合計** | | **~$58/月** |
> 💡 **$2,000 nonprofit credit → 約 34 個月 (接近 3 年)**
> 如規模成長,可升級 VM 規格但仍在 credit 範圍內。
---
## 10. 部署步驟清單
### Phase 0 — Azure 環境建置
- [ ] 申請 Microsoft Nonprofit Azure 帳號
- [ ] 建立 Resource Group: `rg-rolac-prod`
- [ ] 建立 Azure VM (Ubuntu 22.04, Standard_B2s)
- [ ] 建立資料磁碟 (128 GB) 並掛載至 `/data`
- [ ] 設定 NSG (開放 80, 443, 2222)
- [ ] 建立 Static Public IP 並綁定
- [ ] 建立 Storage Account (`rolacstorage`)
- [ ] 設定 DNS A 記錄指向 VM IP
### Phase 0 — VM 環境初始化
- [ ] 安裝 Docker Engine + Docker Compose
- [ ] 安裝 Certbot (Let's Encrypt)
- [ ] 建立目錄結構 (`/data/postgres`, `/data/gitea`, `/data/jenkins`)
- [ ] 啟動 Gitea 容器,建立組織與 Repo
- [ ] 啟動 Jenkins 容器,安裝 Plugins (Git, Docker, Pipeline)
- [ ] 設定 Gitea Webhook → Jenkins
- [ ] 申請 SSL 憑證 (certbot)
- [ ] 啟動 Nginx 容器,配置反向代理
### Phase 1+ — 每次 Release
- [ ] Push code to Gitea `main` branch
- [ ] Jenkins 自動觸發 Build → Test → Deploy
- [ ] 確認 Health Check endpoint 回應正常
- [ ] 必要時執行 EF Core Migration: `dotnet ef database update`
+156
View File
@@ -0,0 +1,156 @@
# ROLAC — 年度奉獻收據 (IRS Annual Giving Statement)
**文件版本:** v0.1 (2026-05-24)
> **重要提示:** 本文件為技術設計參考。正式收據的法律用語及符合性,請在發送前諮詢持牌會計師或稅務顧問。
---
## 法律背景
- ROLAC 為 IRS **501(c)(3)** 免稅組織
- **EIN:** `42-2682968`(儲存為環境變數 `CHURCH_EIN`,不 hardcode
- 依 IRS 規定,單筆奉獻 **$250 或以上** 需提供書面確認
- 年度收據通常在每年 **1 月 31 日前** 寄出,供教友報稅使用
- **現金奉獻** 若無同時期的銀行記錄,IRS 要求有組織的書面記錄
---
## 收據必要欄位(IRS 要求)
| 欄位 | 說明 |
|------|------|
| 組織全名 | River Of Life Christian Church In Arcadia |
| EIN | 42-2682968 |
| 教友姓名 | 依登錄姓名 |
| 奉獻年度 | 例:January 1 December 31, 2025 |
| 奉獻明細 | 日期、金額、類型(每筆逐一列出) |
| 年度奉獻總計 | 所有非匿名奉獻的 Net Amount 加總 |
| 免稅聲明語 | 見下方標準語句 |
| 未提供商品或服務聲明 | 見下方標準語句 |
| 組織代表簽名 | 財務同工姓名、職稱、日期 |
---
## 標準免稅聲明語(中英雙語)
**英文版(收據上必須包含)**
```
River Of Life Christian Church In Arcadia is a tax-exempt organization
under Section 501(c)(3) of the Internal Revenue Code.
EIN: 42-2682968
No goods or services were provided in exchange for this contribution.
This letter serves as your official receipt for income tax purposes.
```
**繁體中文版(附於英文後,供教友參考)**
```
River Of Life Christian Church In Arcadia 為依據美國國稅局
第 501(c)(3) 條款登記之免稅組織。
稅務識別號碼 (EIN)42-2682968
貴教友所奉獻之款項未換取任何商品或服務。
本信函作為您申報所得稅之正式收據。
```
---
## PDF 收據版面設計
```
┌─────────────────────────────────────────────┐
│ [教會 Logo] │
│ River Of Life Christian Church In Arcadia │
│ [教會地址] | EIN: 42-2682968 │
├─────────────────────────────────────────────┤
│ Annual Giving Statement / 年度奉獻收據 │
│ Tax Year: January 1 December 31, {Year} │
├─────────────────────────────────────────────┤
│ Prepared for: {Member Full Name} │
│ Date Issued: {Issue Date} │
├─────────────────────────────────────────────┤
│ Giving Detail / 奉獻明細 │
│ ───────────────────────────────────── │
│ Date Type Method Amount │
│ 2025-01-05 Tithe Check $500.00 │
│ 2025-01-05 Offering Cash $50.00 │
│ 2025-02-02 Tithe Zelle $500.00 │
│ ... │
│ ───────────────────────────────────── │
│ Total Contributions: $X,XXX.XX │
│ (PayPal fees are excluded) │
├─────────────────────────────────────────────┤
│ [免稅聲明語(英文)] │
│ [免稅聲明語(繁中)] │
├─────────────────────────────────────────────┤
│ Authorized by: {Finance Staff Name} │
│ Title: Church Finance │
│ Date: {Issue Date} │
└─────────────────────────────────────────────┘
```
---
## 金額計算規則
| 支付方式 | 收據金額 | 備注 |
|----------|----------|------|
| 現金 | `Amount` | 以信封記錄為準 |
| 支票 | `Amount` | 以支票金額為準 |
| Zelle | `Amount` | 以轉入金額為準 |
| PayPal | `NetAmount`= Amount FeeAmount | PayPal 手續費不計入可扣稅金額 |
| 匿名奉獻 | **不列入** 個人收據 | 匿名奉獻無法與個人對應 |
---
## 系統流程
```
財務同工觸發 → 選擇年度
系統查詢該年度所有
非匿名 Giving 記錄
依 MemberId 分組加總
├── 產生個人 PDFQuestPDF
├── 上傳至 Azure Blob
│ receipts/{year}/{memberId}.pdf
└── Email 寄送給教友
(含 PDF 附件 + 語言偏好)
記錄至 ReceiptLog
(誰產生、何時、寄送狀態)
```
---
## 資料模型補充
```
GivingReceipt
├── Id
├── MemberId
├── TaxYear (int, e.g. 2025)
├── TotalAmount (decimal)
├── PdfBlobPath (Azure Blob 路徑)
├── GeneratedAt
├── GeneratedByUserId
├── SentAt (Email 寄送時間,null = 未寄)
├── SentToEmail
└── IsVoided (bool, 作廢旗標)
```
---
## 重要注意事項
1. **不要 hardcode EIN** — 存於環境變數 `CHURCH_EIN`,設定頁面可修改
2. **收據一旦發出即存檔** — 即使奉獻記錄事後修改,已發出的 PDF 不可覆蓋,只能補發新版
3. **補發流程** — 財務同工可為特定教友重新產生,系統記錄「重新發出」事件至 Audit Log
4. **作廢** — 設 `IsVoided = true`,但 PDF 原檔仍保留於 Blob,不可刪除
5. **稅務諮詢** — 建議每年收據發出前,讓持牌會計師審閱格式一次
+157
View File
@@ -0,0 +1,157 @@
# ROLAC — 通知系統設計
**文件版本:** v0.1 (2026-05-24)
---
## 通知渠道總覽
| 渠道 | 技術 | 適用場景 | 狀態 |
|------|------|----------|------|
| **Email** | SendGrid / SMTP | 年度收據、週報、重要公告 | Phase 0 |
| **Push Notification** | Capacitor Push | 服事提醒、排班更新、活動通知 | Phase 1 |
| **SMS** | Twilio | 緊急通知、服事前一天提醒 | Phase 2 |
| **App 內通知** | Angular 元件 | 所有通知的 in-app 備份 | Phase 1 |
---
## 各渠道設計
### Email (SendGrid)
**觸發時機**
| 事件 | 收件人 | 說明 |
|------|--------|------|
| 年度奉獻收據產生 | 個別教友 | 含 PDF 附件 |
| 歡迎新教友 | 新教友 | 帳號啟用信 |
| 密碼重設 | 帳號持有人 | OTP / Reset Link |
| 服事排班確認 | 當週服事同工 | 每週四自動發送 |
| 系統 Build 失敗 | admin@rolac.org | Jenkins CI 通知 |
**Email 範本要求**
- 雙語(EN / zh-TW),依教友語言偏好發送
- 教會 Logo header
- 手機版 Responsive HTML
- Unsubscribe 連結(行銷類)
---
### Push Notification (Capacitor)
**使用 `@capacitor/push-notifications`**
後端使用 **Firebase Cloud Messaging (FCM)** 作為推播服務(Android + iOS 共用)。
**推播事件**
| 事件 | 時機 | 內容範例 |
|------|------|----------|
| 服事提醒 | 服事前 2 天 09:00 | "您下週日的敬拜服事提醒" |
| 排班更新 | 立即 | "您的服事排班已更新,請查閱" |
| 新消息公告 | 發佈後立即 | "[公告] 復活節特別聚會" |
| 生日祝福 | 當天 08:00 | 可選,需教友同意 |
**裝置 Token 管理**
```
UserDevice
├── Id
├── UserId
├── DeviceToken (FCM token)
├── Platform (ios | android)
├── AppVersion
├── LastSeenAt
└── IsActive
```
- Token 登入時更新,登出時標記 `IsActive = false`
- FCM token 失效時(delivery failure)自動清理
---
### SMS (Twilio)
**使用時機:輔助通知,非主要渠道**
| 事件 | 觸發條件 | 說明 |
|------|----------|------|
| 服事前一天提醒 | 前一天 16:00 | 確保沒裝 App 的同工也收到 |
| 緊急取消通知 | 手動觸發 | 主日緊急狀況(天氣、設備) |
| 新教友歡迎 | 首次建立帳號 | 可選 |
**教友設定**
- 預設 **關閉** SMS,教友自行在個人設定開啟
- 須明確同意才接收(Opt-in 機制)
- 每則 SMS 結尾附 "Reply STOP to unsubscribe"
**Twilio 設定**
```csharp
// appsettings.json(實際值存環境變數)
"Twilio": {
"AccountSid": "${TWILIO_ACCOUNT_SID}",
"AuthToken": "${TWILIO_AUTH_TOKEN}",
"FromNumber": "${TWILIO_FROM_NUMBER}" // e.g. +1-xxx-xxx-xxxx
}
```
**費用估算(50100 人教會)**
- 假設 30 人開啟 SMS、每月約 8 次通知
- 30 人 × 8 次 = 240 SMS/月
- Twilio 美國 SMS ~$0.0079/則 → **約 $2/月**
---
## 通知偏好設定(教友端)
教友在 App 個人設定頁面可控制:
```
通知設定
├── Email 通知
│ ├── ✅ 服事排班(必開,不可關)
│ ├── ✅ 重要公告
│ └── ☐ 活動資訊
├── Push 通知
│ ├── ✅ 服事提醒
│ ├── ✅ 排班更新
│ └── ☐ 生日祝福
└── SMS 通知(預設關閉)
├── ☐ 服事前一天提醒
└── ☐ 緊急通知
```
---
## 後端通知服務架構
```csharp
// INotificationService 統一介面
public interface INotificationService
{
Task SendEmailAsync(NotificationRequest request);
Task SendPushAsync(NotificationRequest request);
Task SendSmsAsync(NotificationRequest request);
Task SendAllAsync(NotificationRequest request); // 依偏好自動選渠道
}
// NotificationRequest
public record NotificationRequest(
string UserId,
string TemplateKey, // e.g. "roster.reminder"
Dictionary<string, string> Data,
NotificationChannel[] Channels
);
```
**排程通知(Hangfire 或 Quartz.NET**
- 服事提醒:每週六 09:00 掃描下週服事表,批次發送
- SMS 提醒:每週六 16:00 補發 SMS(對已開啟 SMS 的教友)
- 生日提醒:每天 08:00 掃描當天生日教友
---
## 通知語言規則
1. 以教友個人語言偏好為準(`Member.LanguagePreference: en | zh-TW`
2. 若未設定,預設英文
3. 批次發送(如年度收據)依每人偏好分別產生對應語言的郵件
+1466
View File
File diff suppressed because it is too large Load Diff
+115
View File
@@ -0,0 +1,115 @@
# ROLAC — 需求稽核報告 (Requirements Review)
**稽核日期:** 2026-05-24
**稽核基準:** 原始需求清單 + 後續對話確認的所有決策
---
## 稽核結果總覽
| 狀態 | 數量 |
|------|------|
| ✅ 已完整涵蓋 | 16 |
| ⚠️ 已涵蓋但細節不足(不影響開工) | 5 |
| ⏳ 暫緩(未來再評估) | 2 |
| ❌ 缺漏 | 0 |
| 🆕 新需求(本輪新) | 1 |
---
## 原始需求清單稽核
| # | 需求 | 狀態 | 文件位置 | 備注 |
|---|------|------|----------|------|
| 1 | 教友管理 | ✅ | PLANNING §3.1 | 含家庭單元、標籤、生日提 |
| 2 | 權限控管 | ✅ | PLANNING §3.2 + §4 | RBAC 矩陣完整 |
| 3 | 小組架構 | ✅ | PLANNING §3.3 | 樹狀結構、組長指派、出席 |
| 4 | 服事表 | ✅ | PLANNING §3.4 | Kendo Scheduler,衝突檢查 |
| 5 | 教會首頁 CMS | ✅ | PLANNING §3.5 | 雙語、SEO、草稿/排程 |
| 6 | 奉獻追蹤 | ✅ | PLANNING §3.6 | 現金/支票/Zelle/PayPal 手續費 |
| 7 | 年度收據 | ✅ | PLANNING §3.7 + IRS_RECEIPT.md | EIN 確認,QuestPDF |
| 8 | Audit Log | ✅ | PLANNING §3.8 | 完整欄位,不可刪除 |
| 9 | 多角色權限 | ✅ | PLANNING §3.2 + §4 | 9 個角色 |
| 10 | Ministry Scope | ✅ | PLANNING §3.10 | API Middleware 強制過濾 |
| 11 | 報表 | ✅ | PLANNING §3.9 | 6 種報表,Kendo Charts |
| 12 | 未來 AI 整合 | ✅ | PLANNING §3.11 | Phase 5API 預留擴展點 |
| — | 主日出席記錄 | ✅ | PLANNING §3.3b | 大人/青少年/兒童三欄 |
| — | 雙語 EN/zh-TW | ✅ | PLANNING §6 + UI_ARCH | 全系統,含網站 |
| — | 敬拜歌曲庫 | 🆕 | PLANNING §3.12(待新增) | 本輪新需求 |
---
## ⚠️ 已涵蓋但細節不足(建議補充)
### W1 — 小組出席記錄(個人層級)
- **現況:** §3.3 只提到「出席記錄(每次小組聚會)」,未設計資料模型
- **缺少:** 每次聚會的個別成員出席/缺席記
- **建議補充:**
```
CellGroupMeeting
├── Id
├── CellGroupId
├── MeetingDate
── Topic / Notes
└── Attendances[]
├── MemberId
└── IsPresent (bool)
```
### W2 — 訪客/新人跟進流程(Visitor Follow-up
- **現況:** §3.1 有「訪客」狀態,§3.9 有「新人追蹤報表」
- **少:** 具體的跟進工作流程(誰負責聯絡、記錄跟進次數、轉為會員的流程)
- **建議補充:** 簡單的 CareRecord 模型,組長/牧師可記錄每次跟進
### W3 — 活動報名表單(Event Registration
- **現況:** §3.5 CMS 事件只提到「可連結報名表單」,實際並未
- **缺少:** 系統內的報名表單,或是否只用外部 Google Form / Jotform
- **建議決策:** 初期用外部表單連結即可,Phase 3+ 再考慮內建表單
### W4 — 廣播訊Broadcast Messaging
- **現況:** 通知系統設計了個別觸發通知
- **缺少:** 管理員向「全體」或「特定小組/Ministry」發送群發通知的功能
- **建議補充:** Admin 界面新增「發送廣播」,選擇對象群組,透過 Email + Push + SMS 發送
### W5 — CCLI 版權合規
- **現況:** 沒有提到
- **缺少:** 教會通常需要 CCLI License 才能合法使用/投影/錄製詩歌
- **與新敬拜歌曲庫需求直接相關** — 見 §3.12
---
## ❌ 明確缺漏(需決策)
### M1 ~~— 禱告代禱管理~~ ✅ 已決定:納入 Phase 1
- 4 個可見範圍:Private / CellGroup / AllLeaders / Public
- 詳見 PLANNING §3.13
### M2 — 會員目錄 / 通訊錄(Member Directory
- **說明:** 教友彼此可查看聯絡資訊的「教會通訊錄」App 功能
- **考量:** 隱私問題需要謹慎,需要教友明確 Opt-in 才顯示聯絡資料
- **建議:** 確認是否需要?
### M3 — 兒童/青少年事工特殊欄
- **說明:** 兒童部門常需要:緊聯絡人、過敏資訊、家長同意書、接送授權人
- **現況:** 3.1 教友資料沒有這些欄位
- **建議:** 在 Member 模型加 `ChildProfile` 子記錄,存放兒童特殊欄位
### M4 ~~— 線上奉獻整合~~ ✅ 已決定:Phase 4Stripe + PayPal Checkout
- Stripe Nonprofit 費率 1.5% + $0.30(需申請)
- Stripe Webhook 自動建立 Giving 記錄
- 定期奉獻:Stripe Subscription
- 詳見 PLANNING §3.6b
---
## 🆕 新增需求:敬拜歌曲庫(見 PLANNING §3.12
在本輪加入設計,詳見下方。
---
## 建議下一步
1. **確認 M1M4 四個缺漏** 是否要納入範疇
2. **W1W5 的細節補充** 可在進入該模組開發前再細化
3. **敬拜歌曲庫(§3.12** 本文件已納入規劃
+464
View File
@@ -0,0 +1,464 @@
# ROLAC — UI 架構設計
**文件版本:** v0.1 (2026-05-24)
---
## 目錄
1. [前端整體架構](#1-前端整體架構)
2. [Angular 專案結構](#2-angular-專案結構)
3. [Landing Page — 公開網站設計](#3-landing-page--公開網站設計)
4. [Admin / User Portal — 後台設計](#4-admin--user-portal--後台設計)
5. [Kendo UI 元件對應清單](#5-kendo-ui-元件對應清單)
6. [Angular Material 使用範圍](#6-angular-material-使用範圍)
7. [設計系統 (Design Tokens)](#7-設計系統-design-tokens)
8. [Responsive / Mobile 規範](#8-responsive--mobile-規範)
9. [Kendo UI 授權注意事項](#9-kendo-ui-授權注意事項)
---
## 1. 前端整體架構
```
單一 Angular 專案 (Monorepo — Angular Workspace)
├── 公開路由 / → Landing Page
│ src/app/public/
│ 技術: Tailwind CSS + 自訂元件 + Angular Animations
│ 對象: 訪客、潛在新教友
├── 教友入口 /portal/ → User Portal
│ src/app/portal/
│ 技術: Angular Material + Kendo UI
│ 對象: 一般教友(查看服事、奉獻歷史、個人資料)
└── 後台管理 /admin/ → Admin Dashboard
src/app/admin/
技術: Angular Material + Kendo UI
對象: 管理員、牧師、財務、秘書等
↓ Capacitor 打包
iOS App / Android App
└── 打包 /portal/ 為主入口(App 不含 Landing Page
```
**為什麼用單一 Angular 專案?**
- Capacitor 只能打包一個 Web App
- 共用 Auth service、API service、ngx-translate
- 共用 Design Token(顏色、字型)保持品牌一致性
- 一個 Jenkins pipeline 搞定所有 build
---
## 2. Angular 專案結構
```
src/
├── app/
│ ├── core/ ← 全域服務 (Auth, API, i18n, Error)
│ │ ├── services/
│ │ ├── guards/
│ │ ├── interceptors/
│ │ └── models/
│ │
│ ├── shared/ ← 跨模組共用元件
│ │ ├── components/ (語言切換器、頁頭、頁腳、Loading)
│ │ └── pipes/ (雙語 pipe: {{ item | localizedName }})
│ │
│ ├── public/ ← Landing PageTailwind
│ │ ├── home/
│ │ ├── about/
│ │ ├── events/
│ │ ├── media/
│ │ ├── giving/
│ │ └── contact/
│ │
│ ├── portal/ ← 教友 User PortalMaterial + Kendo
│ │ ├── dashboard/
│ │ ├── my-roster/
│ │ ├── my-giving/
│ │ └── my-profile/
│ │
│ └── admin/ ← 後台管理(Material + Kendo
│ ├── dashboard/
│ ├── members/
│ ├── attendance/
│ ├── groups/
│ ├── roster/
│ ├── giving/
│ ├── cms/
│ ├── reports/
│ ├── audit-log/
│ └── settings/
├── assets/
│ ├── i18n/
│ │ ├── en.json
│ │ └── zh-TW.json
│ └── images/
└── styles/
├── _tokens.scss ← Design Tokens(色彩、字型、間距)
├── _material-theme.scss ← Angular Material 主題
├── _kendo-theme.scss ← Kendo UI 主題覆寫
└── tailwind.css ← Tailwindpublic/ 使用)
```
---
## 3. Landing Page — 公開網站設計
### 設計方向
**目標:** 有設計感、溫暖、現代,反映教會的歡迎文化
**技術:** Tailwind CSS + 自訂 Angular 元件 + Angular Animations
**不使用** Angular Material 或 Kendo UI(避免 Material Design 的企業感)
### 視覺風格建議
| 元素 | 建議 |
|------|------|
| 色調 | 以教會品牌色為主(深藍/金或暖色系),建議 2 主色 + 1 強調色 |
| 字型 | Google Fonts:標題用 serif(如 Playfair Display),內文用 sans-serifInter |
| 圖像 | 真實教會照片優先;輔以 abstract/light 背景插圖 |
| 動畫 | 入場淡入(Angular Animations)、滾動觸發(Intersection Observer|
| 圖示 | Heroicons 或 Phosphor Icons(免費,SVG |
### 各區塊設計
```
rolac.org
├── [Navbar]
│ Logo | 導覽連結 | EN/中 切換 | [Visit Us] CTA 按鈕
├── [Hero Section]
│ 全版背景圖(教會聚會照片)
│ 主標題 + 副標題(雙語動態切換)
│ 兩個 CTA[Join Us] [Watch Online]
│ 滾動指示箭頭
├── [Welcome / About Section]
│ 左側:短文介紹教會異象
│ 右側:牧師照片 + 名字
│ 底部:[Learn More] 連結
├── [Service Times]
│ 卡片式:主日崇拜時間 / 地點 / 停車資訊
│ 嵌入 Google Maps
├── [Announcements / Events]
│ 最新 3 則公告卡片(從 CMS 動態取得)
│ [View All] 連結
├── [Media — Latest Sermon]
│ YouTube Embed 最新一篇講道
│ 標題 + 日期 + 講員
│ [Sermon Archive] 連結
├── [Giving Section]
│ 感召文字 + 奉獻方式說明(現金/支票/Zelle/PayPal
│ 簡潔卡片排版,非強迫式
├── [Connect / Cell Groups]
│ 鼓勵加入小組的呼召
│ [Contact Us] 或 [填寫訪客卡] 按鈕
├── [Contact Section]
│ 地址、電話、Email
│ 聯絡表單
└── [Footer]
Logo | 快速連結 | 社群媒體 | © | 隱私政策
```
### Tailwind 使用策略
```html
<!-- 範例:Hero Section -->
<section class="relative h-screen flex items-center justify-center overflow-hidden">
<div class="absolute inset-0 bg-cover bg-center"
[style.backgroundImage]="'url(' + heroImage + ')'">
<div class="absolute inset-0 bg-black/50"></div>
</div>
<div class="relative z-10 text-center text-white px-4 max-w-4xl mx-auto">
<h1 class="text-5xl md:text-7xl font-serif mb-6 animate-fade-in">
{{ 'home.hero.title' | translate }}
</h1>
<p class="text-xl md:text-2xl mb-10 text-white/90">
{{ 'home.hero.subtitle' | translate }}
</p>
<div class="flex gap-4 justify-center flex-wrap">
<a routerLink="/about"
class="btn-primary px-8 py-4 rounded-full text-lg font-semibold">
{{ 'home.hero.joinUs' | translate }}
</a>
</div>
</div>
</section>
```
### Landing Page 在 Mobile App 中的處理
> Landing Page 僅存在於 **rolac.org 網站****不** 納入 Capacitor App
> App 啟動後直接跳到 Login 畫面或 Portal Dashboard
---
## 4. Admin / User Portal — 後台設計
### 整體 Layout
```
┌──────────────────────────────────────────────────┐
│ [ROLAC Logo] [模組標題] [EN|中] [通知] [頭像] │ ← Top Toolbar (Angular Material MatToolbar)
├──────────┬───────────────────────────────────────┤
│ │ │
│ [側邊 │ Main Content Area │
│ 導覽] │ │
│ │ (Kendo Grid / Form / Chart 等) │
│ Desktop │ │
│ only │ │
│ │ │
└──────────┴───────────────────────────────────────┘
┌──────────────────────────────────────┐
│ [首頁] [服事] [教友] [奉獻] [我的] │ ← Bottom Tab Bar (Mobile only)
└──────────────────────────────────────┘
```
**導覽策略**
- **Desktop (≥ 1024px):** 左側 Side NavAngular Material `MatSidenav`),可折疊
- **Mobile (< 1024px):** 底部 Tab Bar(最多 5 個主要分頁),Side Nav 改為漢堡選單
### 色彩主題(Admin / Portal
使用 Angular Material Custom Theme,與 Tailwind Landing Page 共用 Design Token
```scss
// _material-theme.scss
@use '@angular/material' as mat;
$rolac-primary: mat.define-palette(mat.$indigo-palette, 700);
$rolac-accent: mat.define-palette(mat.$amber-palette, 600);
$rolac-warn: mat.define-palette(mat.$red-palette);
$rolac-theme: mat.define-light-theme((
color: (
primary: $rolac-primary,
accent: $rolac-accent,
warn: $rolac-warn,
),
typography: mat.define-typography-config(
$font-family: 'Inter, sans-serif'
),
));
@include mat.all-component-themes($rolac-theme);
```
---
## 5. Kendo UI 元件對應清單
### 核心模組 → Kendo 元件 對應
| 模組 | Kendo 元件 | 用途 |
|------|-----------|------|
| **教友管理** | `kendo-grid` | 教友列表(排序、篩選、分頁、匯出) |
| **教友管理** | `kendo-upload` | 教友照片上傳 |
| **奉獻記錄** | `kendo-grid` | 奉獻列表(批次輸入、inline edit|
| **服事表** | `kendo-scheduler` | 排班日曆(月/週/日 視圖) |
| **服事表** | `kendo-grid` | 服事同工列表 |
| **出席報表** | `kendo-chart` `(LineChart)` | 主日出席趨勢折線圖 |
| **奉獻報表** | `kendo-chart` `(BarChart)` | 月度奉獻長條圖 |
| **奉獻報表** | `kendo-chart` `(DonutChart)` | 奉獻類型比例 |
| **教友統計** | `kendo-chart` `(PieChart)` | 教友分佈(年齡/性別) |
| **所有篩選** | `kendo-datepicker` `kendo-daterangepicker` | 日期範圍篩選 |
| **所有列表** | `kendo-dropdownlist` | 下拉選單 |
| **通知** | `kendo-notification` | 操作成功/失敗提示 |
| **Audit Log** | `kendo-grid` | 稽核記錄(大量資料、虛擬捲動) |
| **報表匯出** | Kendo Grid 內建 Excel/PDF 匯出 | 一鍵匯出 |
### Kendo Grid 重點設定(教友列表範例)
```typescript
// members-list.component.html
<kendo-grid
[data]="gridData"
[pageSize]="20"
[pageable]="{ buttonCount: 5 }"
[sortable]="true"
[filterable]="'menu'"
[reorderable]="true"
[resizable]="true"
(excelExport)="onExcelExport($event)">
<ng-template kendoGridToolbarTemplate>
<button kendoGridExcelCommand>
{{ 'common.exportExcel' | translate }}
</button>
<button kendoGridPDFCommand>
{{ 'common.exportPDF' | translate }}
</button>
</ng-template>
<kendo-grid-column field="displayName"
[title]="'member.name' | translate" [width]="180">
</kendo-grid-column>
<kendo-grid-column field="email"
[title]="'member.email' | translate" [width]="220">
</kendo-grid-column>
<!-- ... -->
<kendo-grid-excel fileName="members.xlsx"></kendo-grid-excel>
<kendo-grid-pdf fileName="members.pdf"></kendo-grid-pdf>
</kendo-grid>
```
### Kendo Scheduler(服事排班)
```typescript
// service-roster.component.html
<kendo-scheduler
[kendoSchedulerBinding]="events"
[selectedDate]="selectedDate"
[views]="['month', 'week', 'day']"
(slotClick)="onSlotClick($event)"
(eventClick)="onEventClick($event)">
<kendo-scheduler-month-view></kendo-scheduler-month-view>
<kendo-scheduler-week-view></kendo-scheduler-week-view>
<kendo-scheduler-day-view></kendo-scheduler-day-view>
</kendo-scheduler>
```
---
## 6. Angular Material 使用範圍
Angular Material 負責**基礎 UI 骨架**Kendo UI 負責**複雜資料元件**。
| Angular Material 元件 | 用途 |
|----------------------|------|
| `MatToolbar` | 頂部 Header |
| `MatSidenav` / `MatDrawer` | 側邊導覽(Desktop |
| `MatTabGroup` | Portal 底部分頁(Mobile |
| `MatCard` | Dashboard 統計卡片、表單卡片 |
| `MatDialog` | 確認對話框、新增/編輯 Modal |
| `MatFormField` + `MatInput` | 所有一般表單欄位 |
| `MatSelect` | 小型下拉(非大量資料) |
| `MatButton` / `MatIconButton` | 所有按鈕 |
| `MatSnackBar` | 輕量操作回饋(儲存成功等) |
| `MatProgressSpinner` | 載入中動畫 |
| `MatBadge` | 通知數量角標 |
| `MatChip` | 標籤(教友分類、服事類型) |
| `MatIcon` | 系統圖示(搭配 Material Icons |
| `MatDivider` | 分隔線 |
---
## 7. 設計系統 (Design Tokens)
共用 Token 確保 Landing Page 與 Admin 視覺一致:
```scss
// styles/_tokens.scss
// ── 品牌主色 ──
$color-primary-600: #3B3F8C; // 深藍靛(主色)
$color-primary-400: #6366F1; // 亮藍靛(Hover
$color-accent-500: #D97706; // 金黃(強調色)
$color-accent-300: #FCD34D; // 淺金(Hover
// ── 語意色 ──
$color-success: #16A34A;
$color-warning: #D97706;
$color-error: #DC2626;
$color-info: #2563EB;
// ── 中性色 ──
$color-gray-50: #F9FAFB;
$color-gray-100: #F3F4F6;
$color-gray-700: #374151;
$color-gray-900: #111827;
// ── 字型 ──
$font-display: 'Playfair Display', Georgia, serif; // Landing Page 標題
$font-body: 'Inter', -apple-system, sans-serif; // 全域內文
// ── 間距 ──
$spacing-unit: 8px;
// ── 圓角 ──
$radius-sm: 4px;
$radius-md: 8px;
$radius-lg: 16px;
$radius-full: 9999px;
```
> 實際品牌色在開始前與教會確認(教會 Logo 的主色)。
---
## 8. Responsive / Mobile 規範
### Breakpoints
| 名稱 | 寬度 | 描述 |
|------|------|------|
| `xs` | < 480px | 小螢幕手機 |
| `sm` | 480767px | 一般手機 |
| `md` | 7681023px | 平板 |
| `lg` | ≥ 1024px | 桌機 |
### 各頁面 Mobile 適配規則
| 元件 | Desktop | Mobile |
|------|---------|--------|
| 導覽 | 左側 Sidenav(固定展開) | Bottom Tab Bar + 漢堡 |
| Kendo Grid | 全欄顯示 | 隱藏次要欄,固定姓名欄 |
| Kendo Scheduler | 月 / 週 視圖 | 僅「Day / Agenda」視圖 |
| 表單 | 雙欄排版 | 單欄,全寬輸入框 |
| Chart | 正常尺寸 | 可橫向捲動容器 |
| Dialog | 置中 Modal | 底部 Sheet(全寬滑上) |
### Capacitor App 專屬考量
```typescript
// 偵測是否在原生 App 中執行
import { Capacitor } from '@capacitor/core';
const isNativeApp = Capacitor.isNativePlatform();
// 在 App 中隱藏 Landing Page 導覽
// 在 App 中使用原生 Back Button 處理 Android
```
---
## 9. Kendo UI 授權注意事項
> **Kendo UI for Angular 是商業授權產品(Progress/Telerik)。**
| 方案 | 費用 | 適用 |
|------|------|------|
| Developer License | ~$999/開發者/年 | 標準商業授權 |
| **Kendo UI 30-day Trial** | 免費 | 開發評估用 |
| DevCraft Complete | ~$1,999/年 | 含全套 Telerik 產品 |
**Nonprofit 折扣**
- Progress/Telerik **沒有標準 Nonprofit 免費方案**
- 但可以直接寄信至 `sales@telerik.com` 說明是 501(c)(3) 教會,**詢問 Nonprofit Discount**,有時可獲 4060% 折扣
- 建議在 Phase 0 確認授權再開始使用
**替代方案(若 Kendo 費用過高)**
| 替代品 | 費用 | Grid | Chart | Scheduler |
|--------|------|------|-------|-----------|
| **AG Grid Community** | 免費 | ✅ 強大 | ❌ | ❌ |
| **ngx-charts** | 免費 | ❌ | ✅ | ❌ |
| **FullCalendar** | 免費/付費 | ❌ | ❌ | ✅ |
| **PrimeNG** | 免費 (MIT) | ✅ | ✅ | ✅ 基本 |
> **PrimeNG** 是最接近的免費替代品,如授權談不攏可考慮改用。