church-api/FRONTEND_MIGRATION_GUIDE.md
Benjamin Slingo 0c06e159bb Initial commit: Church API Rust implementation
Complete church management system with bulletin management, media processing, live streaming integration, and web interface. Includes authentication, email notifications, database migrations, and comprehensive test suite.
2025-08-19 20:56:41 -04:00

475 lines
10 KiB
Markdown

# Frontend Migration Guide
## Backend API Overview
The backend provides two API versions with smart timezone handling and proper URL generation:
### API Versions
- **V1 API** (`/api/*`): Legacy compatibility, returns EST timezone, existing URL formats
- **V2 API** (`/api/v2/*`): Modern API, returns UTC timestamps, client handles timezone conversion
## Authentication
### Login
```http
POST /api/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "password"
}
```
**Response:**
```json
{
"success": true,
"data": {
"token": "jwt_token_here",
"user": {
"id": "uuid",
"username": "admin"
}
}
}
```
### Protected Routes
- Add header: `Authorization: Bearer {token}`
- Admin routes are under `/api/admin/*`
---
## Bulletins API
### List Bulletins
```http
GET /api/bulletins?page=1&per_page=20&active_only=true
GET /api/v2/bulletins?page=1&per_page=20
```
### Get Current Bulletin (≤ today's date)
```http
GET /api/bulletins/current
GET /api/v2/bulletins/current
```
### Get Next Bulletin (> today's date) - NEW!
```http
GET /api/bulletins/next
GET /api/v2/bulletins/next
```
### Get Bulletin by ID
```http
GET /api/bulletins/{id}
GET /api/v2/bulletins/{id}
```
### Create Bulletin (Admin)
```http
POST /api/admin/bulletins
Authorization: Bearer {token}
Content-Type: application/json
{
"title": "Weekly Bulletin",
"date": "2025-08-02",
"url": "https://example.com",
"cover_image": null,
"sabbath_school": "Elder Smith",
"divine_worship": "Pastor Johnson",
"scripture_reading": "John 3:16",
"sunset": "7:45 PM",
"is_active": true
}
```
### Update Bulletin (Admin)
```http
PUT /api/admin/bulletins/{id}
Authorization: Bearer {token}
Content-Type: application/json
{...same fields as create...}
```
### Delete Bulletin (Admin)
```http
DELETE /api/admin/bulletins/{id}
Authorization: Bearer {token}
```
---
## Events API
### List Events
```http
GET /api/events?page=1&per_page=20
GET /api/v2/events?page=1&per_page=20
```
### Get Upcoming Events
```http
GET /api/events/upcoming?limit=10
GET /api/v2/events/upcoming?limit=10
```
### Get Featured Events
```http
GET /api/events/featured?limit=5
GET /api/v2/events/featured?limit=5
```
### Get Event by ID
```http
GET /api/events/{id}
GET /api/v2/events/{id}
```
### Submit Event (Public)
```http
POST /api/events/submit
Content-Type: application/json
{
"title": "Prayer Meeting",
"description": "Weekly prayer meeting",
"start_time": "2025-08-02T19:00:00",
"end_time": "2025-08-02T20:00:00",
"location": "Fellowship Hall",
"location_url": "https://maps.google.com/...",
"category": "worship",
"is_featured": false,
"recurring_type": "weekly",
"bulletin_week": "2025-08-02",
"submitter_email": "user@example.com"
}
```
### Admin Event Management
```http
POST /api/admin/events # Create event
PUT /api/admin/events/{id} # Update event
DELETE /api/admin/events/{id} # Delete event
GET /api/admin/events/pending # List pending submissions
POST /api/admin/events/pending/{id}/approve # Approve pending
POST /api/admin/events/pending/{id}/reject # Reject pending
DELETE /api/admin/events/pending/{id} # Delete pending
```
### Admin User Management
```http
GET /api/admin/users # List all users
```
---
## File Uploads (Admin)
### Upload Bulletin PDF
```http
POST /api/upload/bulletins/{id}/pdf
Authorization: Bearer {token}
Content-Type: multipart/form-data
file: bulletin.pdf
```
### Upload Bulletin Cover Image
```http
POST /api/upload/bulletins/{id}/cover
Authorization: Bearer {token}
Content-Type: multipart/form-data
file: cover.jpg
```
### Upload Event Image
```http
POST /api/upload/events/{id}/image
Authorization: Bearer {token}
Content-Type: multipart/form-data
file: event.jpg
```
**Upload Response:**
```json
{
"success": true,
"file_path": "uploads/bulletins/uuid.pdf",
"pdf_path": "https://api.rockvilletollandsda.church/uploads/bulletins/uuid.pdf",
"message": "File uploaded successfully"
}
```
**Note:** Files are served at `/uploads/*` path (handled by Caddy, not API)
---
## Scripture Processing
The API now automatically processes scripture references in bulletin fields:
### Automatic Scripture Lookup
- **Input:** Short reference like `"John 3:16 KJV"`
- **Output:** Enhanced with full verse text: `"For God so loved the world... - John 3:16 KJV"`
- **Fallback:** If no match found, returns original text unchanged
- **Smart Detection:** Already long texts (>50 chars) are left unchanged
### How It Works
1. When creating/updating bulletins, `scripture_reading` field is processed
2. Uses existing Bible verse database with fuzzy search
3. Matches on both reference and partial text content
4. Returns best match from database
### Example API Response
```json
{
"success": true,
"data": {
"id": "...",
"title": "Weekly Bulletin",
"scripture_reading": "For God so loved the world, that he gave his only begotten Son, that whosoever believeth in him should not perish, but have everlasting life. - John 3:16 KJV",
...
}
}
```
---
## Other APIs
### Bible Verses
```http
GET /api/bible_verses/random
GET /api/bible_verses?page=1&per_page=20
GET /api/bible_verses/search?q=love&limit=10
GET /api/v2/bible_verses/random
GET /api/v2/bible_verses?page=1&per_page=20
GET /api/v2/bible_verses/search?q=love&limit=10
```
### Contact Form
```http
POST /api/contact
POST /api/v2/contact
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com",
"subject": "Question",
"message": "Hello..."
}
```
### Schedule
```http
GET /api/schedule?date=2025-08-02
GET /api/conference-data
GET /api/v2/schedule?date=2025-08-02
GET /api/v2/conference-data
```
### Admin Schedule Management
```http
POST /api/admin/schedule # Create schedule
PUT /api/admin/schedule/{date} # Update schedule by date
DELETE /api/admin/schedule/{date} # Delete schedule by date
GET /api/admin/schedule # List all schedules
```
### Sermons & Livestreams
```http
GET /api/sermons
GET /api/livestreams
```
### Configuration
```http
GET /api/config # Public config
GET /api/admin/config # Admin config (protected)
```
### Legacy Android App Support
```http
GET /api/collections/rtsda_android/records # Legacy Android app update check
```
### Debug Endpoints
```http
GET /api/debug/jellyfin # Debug Jellyfin connectivity (development only)
```
---
## Response Format
All responses follow this format:
```json
{
"success": true,
"data": {...},
"message": "Optional message"
}
```
**Paginated responses:**
```json
{
"success": true,
"data": {
"items": [...],
"total": 150,
"page": 1,
"per_page": 20,
"total_pages": 8
}
}
```
**Error responses:**
```json
{
"success": false,
"message": "Error description"
}
```
---
## Timezone Handling
### V1 API (Legacy)
- **Input:** Accepts times in any format
- **Output:** Converts all timestamps to EST timezone
- **Use case:** Existing clients that expect EST times
### V2 API (Modern)
- **Input:** Expects UTC timestamps with timezone info when needed
- **Output:** Returns UTC timestamps
- **Client responsibility:** Convert to local timezone for display
**V2 Timezone Example:**
```json
{
"start_time": "2025-08-02T23:00:00Z",
"timezone_info": {
"utc": "2025-08-02T23:00:00Z",
"local_display": "2025-08-02T19:00:00-04:00"
}
}
```
---
## Frontend Migration Strategy
### Phase 1: Update Shared Rust Crate
1. **Add V2 API models** with UTC timestamp handling
2. **Keep V1 models** for backward compatibility
3. **Add timezone conversion utilities**
4. **Update HTTP client** to handle both API versions
### Phase 2: Client-by-Client Migration
1. **Web Admin Panel:** Migrate to V2 API first
2. **Mobile App:** Update to use new bulletin endpoints (`/next`)
3. **Website:** Gradually migrate public endpoints
4. **Keep V1 for old clients** until all are updated
### Phase 3: New Features
1. **Use V2 API only** for new features
2. **Proper UTC handling** from day one
3. **Client-side timezone conversion**
---
## Breaking Changes to Watch For
### URL Structure
- **Old:** Some inconsistent URL patterns
- **New:** Consistent `/api/v2/*` structure
- **Files:** Always served at `/uploads/*` (via Caddy)
### Timestamp Format
- **V1:** Mixed timezone handling, EST output
- **V2:** Consistent UTC timestamps
- **Migration:** Update date parsing/formatting code
### Response Fields
- **V2 may have additional fields** for timezone info
- **V1 fields remain unchanged** for compatibility
- **New endpoints** (like `/next`) available in both versions
### Authentication
- **Same JWT tokens** work for both API versions
- **Admin routes** use same authorization header
- **No changes needed** to auth flow
---
## Implementation Notes
### Error Handling
```rust
// Example error handling in shared crate
match api_client.get_current_bulletin().await {
Ok(response) if response.success => {
// Handle response.data
},
Ok(response) => {
// Handle API error: response.message
},
Err(e) => {
// Handle network/parsing error
}
}
```
### Timezone Conversion (V2)
```rust
// Example timezone handling
fn convert_utc_to_local(utc_time: &str, timezone: &str) -> Result<String> {
let utc = DateTime::parse_from_rfc3339(utc_time)?;
let local_tz: Tz = timezone.parse()?;
Ok(utc.with_timezone(&local_tz).to_string())
}
```
### File Upload
```rust
// Example multipart upload
let form = multipart::Form::new()
.file("file", path_to_file)?;
let response = client
.post(&format!("{}/api/upload/bulletins/{}/pdf", base_url, bulletin_id))
.bearer_auth(&token)
.multipart(form)
.send()
.await?;
```
---
## Testing Endpoints
### Development
- **API Base:** `http://localhost:3002`
- **Files:** `http://localhost:3002/uploads/*`
### Production
- **API Base:** `https://api.rockvilletollandsda.church`
- **Files:** `https://api.rockvilletollandsda.church/uploads/*`
### Health Check
```http
GET /api/config
```
Should return basic configuration without authentication.