use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Coordinates { pub lat: f64, pub lng: f64, } #[derive(Debug, Serialize, Deserialize, Clone)] pub struct ChurchConfig { pub church_name: Option, pub church_address: Option, pub po_box: Option, pub contact_phone: Option, pub contact_email: Option, pub website_url: Option, pub google_maps_url: Option, pub facebook_url: Option, pub youtube_url: Option, pub instagram_url: Option, pub about_text: Option, pub mission_statement: Option, pub tagline: Option, pub brand_color: Option, pub donation_url: Option, #[serde(skip_serializing_if = "Option::is_none")] pub service_times: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub pastoral_staff: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub ministries: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub app_settings: Option, #[serde(skip_serializing_if = "Option::is_none")] pub emergency_contacts: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub coordinates: Option, } #[derive(Debug, Serialize, Deserialize, Clone)] pub struct ServiceTime { pub day: String, pub service: String, pub time: String, } #[derive(Debug, Serialize, Deserialize, Clone)] pub struct ServiceTimes { pub sabbath_school: Option, pub divine_worship: Option, pub prayer_meeting: Option, pub youth_service: Option, #[serde(skip_serializing_if = "Option::is_none")] pub special_services: Option>, } #[derive(Debug, Serialize, Deserialize, Clone)] pub struct SpecialService { pub name: String, pub time: String, pub frequency: String, #[serde(skip_serializing_if = "Option::is_none")] pub description: Option, } #[derive(Debug, Serialize, Deserialize, Clone)] pub struct StaffMember { pub name: String, pub title: String, #[serde(skip_serializing_if = "Option::is_none")] pub email: Option, #[serde(skip_serializing_if = "Option::is_none")] pub phone: Option, #[serde(skip_serializing_if = "Option::is_none")] pub photo: Option, #[serde(skip_serializing_if = "Option::is_none")] pub bio: Option, #[serde(skip_serializing_if = "Option::is_none")] pub responsibilities: Option>, } #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Ministry { pub name: String, pub description: String, #[serde(skip_serializing_if = "Option::is_none")] pub leader: Option, #[serde(skip_serializing_if = "Option::is_none")] pub contact_email: Option, #[serde(skip_serializing_if = "Option::is_none")] pub contact_phone: Option, #[serde(skip_serializing_if = "Option::is_none")] pub meeting_time: Option, #[serde(skip_serializing_if = "Option::is_none")] pub meeting_location: Option, #[serde(skip_serializing_if = "Option::is_none")] pub website: Option, pub category: MinistryCategory, #[serde(default)] pub is_active: bool, } #[derive(Debug, Serialize, Deserialize, Clone)] pub struct EmergencyContact { pub name: String, pub title: String, pub phone: String, #[serde(skip_serializing_if = "Option::is_none")] pub email: Option, pub priority: u32, #[serde(skip_serializing_if = "Option::is_none")] pub availability: Option, } #[derive(Debug, Serialize, Deserialize, Clone)] pub struct AppSettings { pub enable_notifications: bool, pub enable_calendar_sync: bool, pub enable_offline_mode: bool, pub theme: AppTheme, pub default_language: String, #[serde(skip_serializing_if = "Option::is_none")] pub owncast_server: Option, #[serde(skip_serializing_if = "Option::is_none")] pub bible_version: Option, #[serde(skip_serializing_if = "Option::is_none")] pub hymnal_version: Option, pub cache_duration_minutes: u32, pub auto_refresh_interval_minutes: u32, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] pub enum MinistryCategory { #[serde(rename = "worship")] Worship, #[serde(rename = "education")] Education, #[serde(rename = "youth")] Youth, #[serde(rename = "children")] Children, #[serde(rename = "outreach")] Outreach, #[serde(rename = "health")] Health, #[serde(rename = "music")] Music, #[serde(rename = "fellowship")] Fellowship, #[serde(rename = "prayer")] Prayer, #[serde(rename = "stewardship")] Stewardship, #[serde(rename = "other")] Other, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] pub enum AppTheme { #[serde(rename = "light")] Light, #[serde(rename = "dark")] Dark, #[serde(rename = "system")] System, } impl Default for AppSettings { fn default() -> Self { Self { enable_notifications: true, enable_calendar_sync: true, enable_offline_mode: true, theme: AppTheme::System, default_language: "en".to_string(), owncast_server: None, bible_version: Some("KJV".to_string()), hymnal_version: Some("1985".to_string()), cache_duration_minutes: 60, auto_refresh_interval_minutes: 15, } } } impl ChurchConfig { pub fn get_display_name(&self) -> String { self.church_name .as_ref() .cloned() .unwrap_or_else(|| "Church".to_string()) } pub fn has_social_media(&self) -> bool { self.facebook_url.is_some() || self.youtube_url.is_some() || self.instagram_url.is_some() } pub fn get_contact_info(&self) -> Vec<(String, String)> { let mut contacts = Vec::new(); if let Some(phone) = &self.contact_phone { contacts.push(("Phone".to_string(), phone.clone())); } if let Some(email) = &self.contact_email { contacts.push(("Email".to_string(), email.clone())); } if let Some(address) = &self.church_address { contacts.push(("Address".to_string(), address.clone())); } if let Some(po_box) = &self.po_box { contacts.push(("PO Box".to_string(), po_box.clone())); } contacts } pub fn active_ministries(&self) -> Vec<&Ministry> { self.ministries .as_ref() .map(|ministries| { ministries .iter() .filter(|ministry| ministry.is_active) .collect() }) .unwrap_or_default() } pub fn ministries_by_category(&self, category: MinistryCategory) -> Vec<&Ministry> { self.ministries .as_ref() .map(|ministries| { ministries .iter() .filter(|ministry| ministry.category == category && ministry.is_active) .collect() }) .unwrap_or_default() } pub fn emergency_contacts_by_priority(&self) -> Vec<&EmergencyContact> { self.emergency_contacts .as_ref() .map(|contacts| { let mut sorted = contacts.iter().collect::>(); sorted.sort_by_key(|contact| contact.priority); sorted }) .unwrap_or_default() } }