Remove admin event creation - force submission form workflow

Streamline admin panel to only handle pending event approvals:
- Remove create_admin_event functions from Rust core
- Remove createAdminEventJson from API bindings
- Update events admin page to focus on pending approvals only
- Maintain edit/delete for approved events via main collection

Enforces cleaner workflow: Submit → Approve → Auto-move to events collection
This commit is contained in:
Benjamin Slingo 2025-08-28 22:14:17 -04:00
parent f91f696334
commit 1013ca0870
8 changed files with 251 additions and 57 deletions

123
CLAUDE.md Normal file
View file

@ -0,0 +1,123 @@
# CLAUDE INSTRUCTIONS - RTSDA CODEBASE
## **CRITICAL ARCHITECTURE UNDERSTANDING**
### **ASTRO IS A THIN UI LAYER ONLY**
- Astro handles routing, SSR, and basic UI rendering
- **NO BUSINESS LOGIC IN FRONTEND**
- **NO DIRECT API CALLS FROM FRONTEND**
- **ALL LOGIC GOES THROUGH `church-core` RUST CRATE**
### **THE RUST CRATE IS THE CORE FOR A FUCKING REASON**
- `church-core/` contains ALL business logic
- `church-core/` handles ALL API communication
- `church-core/` provides unified data models
- `church-core/` has caching, error handling, auth
- **USE THE RUST CRATE, DON'T BYPASS IT**
## ✅ **FIXED VIOLATIONS**
### **Admin Panel (COMPLETED ✅)**
- ~~`public/admin/scripts/main.js` - 1800+ lines of vanilla JS~~ **REMOVED**
- ✅ **NOW:** Proper Astro routes using Rust functions via FFI bindings
- ✅ **FIXED:** Frontend now follows core architecture
## **REMAINING VIOLATIONS TO FIX**
### **Event Submission Direct API Call**
- `src/pages/events/submit.astro:748` - Still uses direct fetch() call
- **SHOULD BE:** Use `submitEventJson()` from bindings.js
- **VIOLATION:** Bypassing the unified client architecture
### **Data Model Mismatches**
- Frontend expects detailed Schedule fields (`song_leader`, `childrens_story`)
- Backend Rust models missing these fields
- **CAUSE:** Frontend developed independently of core models
## **CORRECT ARCHITECTURE FLOW**
```
Frontend (Astro) → bindings.js → Rust FFI → church-core → API
```
**NOT:**
```
Frontend → fetch() → API directly
```
## **HOW TO FIX VIOLATIONS**
### **For Event Submission:**
1. ✅ Admin functions already exist in `church-core/src/client/admin.rs`
2. ✅ Already exposed via FFI in `church-core/src/api.rs`
3. ✅ Already imported in `astro-church-website/src/lib/bindings.js`
4. **TODO:** Replace `fetch()` call with `submitEventJson()` function
### **For Data Models:**
1. Update Schedule models in `church-core/src/models/admin.rs`
2. Add missing fields (`song_leader`, `childrens_story`, etc.)
3. Regenerate FFI bindings
4. Update frontend to use new model structure
## **COMMANDS TO REMEMBER**
### **Build Commands:**
```bash
# Build Rust bindings FIRST
npm run build:native
# Then build Astro
npm run build
# Dev server
npm run dev
```
### **Testing Commands:**
```bash
# Test Rust core
cd church-core && cargo test
# Test API connectivity
cd church-core && cargo run --bin church-core-test
```
## **BEFORE MAKING CHANGES**
1. **Check if Rust function exists** in `church-core/`
2. **If missing, ADD IT TO RUST FIRST**
3. **Then expose via FFI bindings**
4. **Finally update frontend to use it**
## **DO NOT:**
- Add business logic to JavaScript
- Make direct API calls from frontend
- Create data models in frontend
- Bypass the Rust crate architecture
## **THE RUST CRATE EXISTS FOR:**
- Cross-platform consistency (iOS, Android, Web)
- Type safety and error handling
- Unified caching and auth
- Single source of truth for API communication
**RESPECT THE ARCHITECTURE. USE THE RUST CRATE.**
## **CLEANUP PROGRESS TRACKING**
### ✅ **COMPLETED (Aug 29, 2025)**
- **Admin Panel Conversion**: Removed 1843-line vanilla JS file
- **Proper Astro Routes**: Created TypeScript admin routes using Rust functions
- **Thumbnail Field Removal**: Cleaned up event submission form
- **FFI Functions**: Added 12 new admin functions in church-core
- **Architecture Compliance**: Admin panel now follows correct flow
**Commit:** `f91f696` - Convert admin panel to Astro routes and remove thumbnail field
### 🚨 **HIGH PRIORITY NEXT**
1. Fix event submission direct API call (`src/pages/events/submit.astro:748`)
2. Check Schedule model data field mismatches
3. Add missing admin functions (stats, config, users)
**See:** `/NEXT-STEPS.md` for detailed implementation plan

113
NEXT-STEPS.md Normal file
View file

@ -0,0 +1,113 @@
# Next Steps for Architecture Cleanup
## 🚨 Priority 1: Critical Architecture Violations
### 1. Fix Event Submission Direct API Call
**Location:** `astro-church-website/src/pages/events/submit.astro:748`
**Issue:** Still uses `fetch('https://api.rockvilletollandsda.church/api/events/submit')`
**Fix:** Replace with `submitEventJson()` function from bindings
### 2. Data Model Mismatches
**Issue:** Frontend expects Schedule fields that may not exist in Rust models
**Check:** Does `church-core/src/models/admin.rs` Schedule struct have:
- `song_leader`
- `childrens_story`
- `ss_teacher`
- `ss_leader`
- `mission_story`
- `special_notes`
**Fix:** Update Rust Schedule model if fields are missing
## 🧹 Priority 2: Code Cleanup
### 1. Remove Dead Code (Rust Warnings)
```bash
# Fix these warnings from build output:
cargo fix --lib -p church-core
```
**Locations:**
- `church-core/src/models/streaming.rs:1` - unused Serialize/Deserialize
- `church-core/src/utils/formatting.rs:56` - unused FixedOffset
- `church-core/src/client/http.rs:197` - unused delete method
### 2. Missing Admin Functions
**Add to `church-core/src/api.rs`:**
- `fetch_admin_stats_json()` - Dashboard statistics
- `fetch_recurring_types_json()` - Configuration data
- `get_admin_users_json()` - User management
### 3. Upload Functionality
**Issue:** Old admin JS had image upload logic not yet converted
**Add to `church-core/src/api.rs`:**
- `upload_event_image_json()`
- `upload_bulletin_cover_json()`
## 🔄 Priority 3: Enhanced Admin Features
### 1. Add TypeScript Types
**Create:** `astro-church-website/src/types/admin.ts`
- Define admin API response types
- Add type safety for admin operations
### 2. Improve Error Handling
**Replace:** Generic `alert()` calls in admin pages
**With:** Proper error UI components
### 3. Add Loading States
**Add to admin pages:**
- Loading spinners for operations
- Disabled states during API calls
- Better UX feedback
## 🎯 Priority 4: Testing & Validation
### 1. Test New Admin Functionality
- [ ] Login/logout flow
- [ ] Event approval/rejection
- [ ] Bulletin CRUD operations
- [ ] Schedule management
- [ ] Event submission without thumbnail
### 2. Add Form Validation
- [ ] Client-side validation for admin forms
- [ ] Real-time feedback
- [ ] Error message display
## 📝 Implementation Order
1. **Immediate (blocking):** Fix event submission API call
2. **High:** Check/fix Schedule model data mismatches
3. **Medium:** Add missing admin functions
4. **Low:** UI/UX improvements and TypeScript types
## 🔧 Commands to Run
```bash
# Test current state
cd astro-church-website
npm run build
npm run dev
# Fix Rust warnings
cd ../church-core
cargo fix --lib -p church-core
# Rebuild after Rust changes
cd ../astro-church-website
npm run build:native
npm run build
```
## 🏆 Architecture Success Metrics
**✅ ACHIEVED:**
- Removed 1843 lines of direct API call violations
- All admin routes now use Rust core functions
- Proper Astro/TypeScript structure implemented
**🎯 TARGET:**
- Zero direct API calls from frontend
- All business logic in Rust crate
- Complete type safety with TypeScript
- Full test coverage for admin operations

View file

@ -43,7 +43,6 @@ export const {
approvePendingEventJson,
rejectPendingEventJson,
deletePendingEventJson,
createAdminEventJson,
updateAdminEventJson,
deleteAdminEventJson,
// Admin bulletins

View file

@ -1,5 +1,5 @@
import type { APIRoute } from 'astro';
import { fetchPendingEventsJson, createAdminEventJson } from '../../../lib/bindings.js';
import { fetchPendingEventsJson } from '../../../lib/bindings.js';
export const GET: APIRoute = async ({ request }) => {
try {
@ -16,29 +16,4 @@ export const GET: APIRoute = async ({ request }) => {
headers: { 'Content-Type': 'application/json' }
});
}
};
export const POST: APIRoute = async ({ request }) => {
try {
const eventData = await request.json();
const result = createAdminEventJson(JSON.stringify(eventData));
const response = JSON.parse(result);
if (response.success) {
return new Response(JSON.stringify(response), {
status: 201,
headers: { 'Content-Type': 'application/json' }
});
} else {
return new Response(JSON.stringify(response), {
status: 400,
headers: { 'Content-Type': 'application/json' }
});
}
} catch (error) {
return new Response(JSON.stringify({ error: 'Failed to create event' }), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
};

View file

@ -1,23 +1,27 @@
---
import AdminLayout from '../../layouts/AdminLayout.astro';
import { fetchPendingEventsJson } from '../../lib/bindings.js';
import { fetchPendingEventsJson, fetchEventsJson } from '../../lib/bindings.js';
let pendingEvents = [];
let approvedEvents = [];
try {
const eventsJson = fetchPendingEventsJson();
pendingEvents = JSON.parse(eventsJson);
const pendingJson = fetchPendingEventsJson();
pendingEvents = JSON.parse(pendingJson);
const approvedJson = fetchEventsJson();
approvedEvents = JSON.parse(approvedJson);
} catch (error) {
console.error('Error fetching pending events:', error);
console.error('Error fetching events:', error);
}
---
<AdminLayout title="Events">
<div class="max-w-6xl mx-auto">
<div class="flex justify-between items-center mb-6">
<h1 class="text-2xl font-bold">Event Management</h1>
<button id="create-event-btn" class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600">
Create New Event
</button>
<div>
<h1 class="text-2xl font-bold">Event Management</h1>
<p class="text-gray-600 text-sm mt-1">Events must be created via the <a href="/events/submit" class="text-blue-600 hover:underline">public submission form</a></p>
</div>
</div>
<!-- Pending Events Section -->

View file

@ -396,20 +396,6 @@ pub fn delete_pending_event_json(event_id: String) -> String {
}
}
pub fn create_admin_event_json(event_json: String) -> String {
let client = get_client();
let rt = get_runtime();
match serde_json::from_str::<NewEvent>(&event_json) {
Ok(event) => {
match rt.block_on(crate::client::admin::create_admin_event(client, event)) {
Ok(id) => serde_json::to_string(&serde_json::json!({"success": true, "id": id})).unwrap_or_else(|_| "{}".to_string()),
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": e.to_string()})).unwrap_or_else(|_| "{}".to_string()),
}
},
Err(e) => serde_json::to_string(&serde_json::json!({"success": false, "error": format!("Invalid JSON: {}", e)})).unwrap_or_else(|_| "{}".to_string()),
}
}
pub fn update_admin_event_json(event_id: String, update_json: String) -> String {
let client = get_client();

View file

@ -25,9 +25,7 @@ pub async fn delete_bulletin(client: &ChurchApiClient, id: &str) -> Result<()> {
}
// Admin Event Management
pub async fn create_admin_event(client: &ChurchApiClient, event: NewEvent) -> Result<String> {
client.post_api_with_version("/admin/events", &event, ApiVersion::V1).await
}
// Note: Event creation must go through public submission form
pub async fn update_admin_event(client: &ChurchApiClient, id: &str, update: EventUpdate) -> Result<()> {
let path = format!("/admin/events/{}", id);

View file

@ -326,11 +326,7 @@ pub async fn get_livestreams(&self) -> Result<Vec<Sermon>> {
admin::delete_bulletin(self, id).await
}
// Admin Events
pub async fn create_admin_event(&self, event: NewEvent) -> Result<String> {
admin::create_admin_event(self, event).await
}
// Admin Events - Edit/delete allowed, creation via submission form only
pub async fn update_admin_event(&self, id: &str, update: EventUpdate) -> Result<()> {
admin::update_admin_event(self, id, update).await
}