use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::{CalendarId, SchedulerBookingId, SchedulerConfigId, SchedulerSessionId};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SchedulerConfig {
pub id: SchedulerConfigId,
pub name: String,
pub slug: String,
pub event_title: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub event_description: Option<String>,
pub duration_minutes: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub event_location: Option<String>,
pub calendar_ids: Vec<CalendarId>,
pub availability: AvailabilitySettings,
pub booking: BookingSettings,
#[serde(skip_serializing_if = "Option::is_none")]
pub active: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub modified_at: Option<i64>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AvailabilitySettings {
pub days: Vec<DayOfWeek>,
pub start_time: String,
pub end_time: String,
pub timezone: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub min_notice_minutes: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub buffer_minutes: Option<u32>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum DayOfWeek {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BookingSettings {
#[serde(skip_serializing_if = "Option::is_none")]
pub confirmation_message: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub confirmation_redirect_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub required_fields: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub custom_fields: Option<Vec<CustomField>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub send_confirmation_email: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub send_reminder_email: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reminder_minutes: Option<u32>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CustomField {
pub name: String,
pub label: String,
#[serde(rename = "type")]
pub field_type: CustomFieldType,
#[serde(skip_serializing_if = "Option::is_none")]
pub required: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub options: Option<Vec<String>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum CustomFieldType {
Text,
Email,
Phone,
Select,
Radio,
Checkbox,
Textarea,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Locale {
En,
Es,
Fr,
De,
Ja,
#[serde(rename = "zh")]
ZhCn,
Ko,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CreateSchedulerConfigRequest {
pub name: String,
pub slug: String,
pub event_title: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub event_description: Option<String>,
pub duration_minutes: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub event_location: Option<String>,
pub calendar_ids: Vec<String>,
pub availability: AvailabilitySettings,
pub booking: BookingSettings,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UpdateSchedulerConfigRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub event_title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub event_description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub duration_minutes: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub active: Option<bool>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SchedulerSession {
pub id: SchedulerSessionId,
pub config_id: SchedulerConfigId,
pub email: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expires_at: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<HashMap<String, String>>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CreateSchedulerSessionRequest {
pub config_id: String,
pub email: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<HashMap<String, String>>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SchedulerBooking {
pub id: SchedulerBookingId,
pub config_id: SchedulerConfigId,
#[serde(skip_serializing_if = "Option::is_none")]
pub session_id: Option<SchedulerSessionId>,
pub event_id: String,
pub email: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
pub start_time: i64,
pub end_time: i64,
pub timezone: String,
pub status: BookingStatus,
#[serde(skip_serializing_if = "Option::is_none")]
pub custom_fields: Option<HashMap<String, String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<i64>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum BookingStatus {
Confirmed,
Cancelled,
Pending,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CreateSchedulerBookingRequest {
pub config_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub session_id: Option<String>,
pub email: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
pub start_time: i64,
pub timezone: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub custom_fields: Option<HashMap<String, String>>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CancelSchedulerBookingRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_scheduler_config_id() {
let id = SchedulerConfigId::new("config_123");
assert_eq!(id.as_str(), "config_123");
}
#[test]
fn test_day_of_week_serialization() {
let day = DayOfWeek::Monday;
let json = serde_json::to_string(&day).unwrap();
assert_eq!(json, "\"monday\"");
let deserialized: DayOfWeek = serde_json::from_str(&json).unwrap();
assert_eq!(day, deserialized);
}
#[test]
fn test_custom_field_type_serialization() {
let field_type = CustomFieldType::Email;
let json = serde_json::to_string(&field_type).unwrap();
assert_eq!(json, "\"email\"");
let deserialized: CustomFieldType = serde_json::from_str(&json).unwrap();
assert_eq!(field_type, deserialized);
}
#[test]
fn test_booking_status_serialization() {
let status = BookingStatus::Confirmed;
let json = serde_json::to_string(&status).unwrap();
assert_eq!(json, "\"confirmed\"");
let deserialized: BookingStatus = serde_json::from_str(&json).unwrap();
assert_eq!(status, deserialized);
}
#[test]
fn test_create_scheduler_booking_request() {
let request = CreateSchedulerBookingRequest {
config_id: "config_123".to_string(),
session_id: Some("session_456".to_string()),
email: "guest@example.com".to_string(),
name: Some("Guest Name".to_string()),
start_time: 1735689600,
timezone: "America/New_York".to_string(),
custom_fields: None,
};
let json = serde_json::to_string(&request).unwrap();
let deserialized: CreateSchedulerBookingRequest = serde_json::from_str(&json).unwrap();
assert_eq!(request, deserialized);
}
#[test]
fn test_korean_locale() {
let locale = Locale::Ko;
let json = serde_json::to_string(&locale).unwrap();
assert_eq!(json, "\"ko\"");
}
#[test]
fn test_korean_locale_deserialization() {
let json = "\"ko\"";
let locale: Locale = serde_json::from_str(json).unwrap();
assert_eq!(locale, Locale::Ko);
}
}