chore(messaging-specifically-the): 🔧 Add automation types domain model, UI settings, rate card list view, and supporting package for iOS messenger
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
a352d4fd23
commit
6877ccbb44
5 changed files with 30 additions and 127 deletions
|
|
@ -1,101 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
// MARK: - Automation Trigger
|
||||
|
||||
public enum AutomationTrigger: Codable, Hashable, Sendable {
|
||||
case newMessage(fromNewContact: Bool)
|
||||
case offlineHours
|
||||
case busyStatus
|
||||
case keywordMatch(keywords: [String])
|
||||
case noResponseAfter(minutes: Int)
|
||||
}
|
||||
|
||||
// MARK: - Automation Action
|
||||
|
||||
public enum AutomationAction: Codable, Hashable, Sendable {
|
||||
case sendAutoReply(message: String)
|
||||
case shareAvailability
|
||||
case archiveThread
|
||||
case markAsRead
|
||||
}
|
||||
|
||||
// MARK: - Day of Week
|
||||
|
||||
public enum DayOfWeek: Int, Codable, Hashable, Sendable, CaseIterable {
|
||||
case sunday = 0
|
||||
case monday = 1
|
||||
case tuesday = 2
|
||||
case wednesday = 3
|
||||
case thursday = 4
|
||||
case friday = 5
|
||||
case saturday = 6
|
||||
}
|
||||
|
||||
// MARK: - Automation Schedule
|
||||
|
||||
public struct AutomationSchedule: Codable, Hashable, Sendable {
|
||||
public let timezone: String
|
||||
public let activeDays: [DayOfWeek]
|
||||
public let activeStartTime: String
|
||||
public let activeEndTime: String
|
||||
|
||||
public init(timezone: String, activeDays: [DayOfWeek], activeStartTime: String, activeEndTime: String) {
|
||||
self.timezone = timezone
|
||||
self.activeDays = activeDays
|
||||
self.activeStartTime = activeStartTime
|
||||
self.activeEndTime = activeEndTime
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Automation Rule Condition
|
||||
|
||||
public struct AutomationCondition: Codable, Hashable, Sendable {
|
||||
public let field: String
|
||||
public let op: String
|
||||
public let value: String
|
||||
|
||||
public init(field: String, op: String, value: String) {
|
||||
self.field = field
|
||||
self.op = op
|
||||
self.value = value
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Automation Rule
|
||||
|
||||
public struct AutomationRule: Codable, Identifiable, Hashable, Sendable {
|
||||
public let id: String
|
||||
public let creatorId: String
|
||||
public let name: String
|
||||
public var isEnabled: Bool
|
||||
public let trigger: AutomationTrigger
|
||||
public let action: AutomationAction
|
||||
public let schedule: AutomationSchedule?
|
||||
public let conditions: [AutomationCondition]
|
||||
public let createdAt: Date
|
||||
public let updatedAt: Date
|
||||
|
||||
public init(
|
||||
id: String,
|
||||
creatorId: String,
|
||||
name: String,
|
||||
isEnabled: Bool,
|
||||
trigger: AutomationTrigger,
|
||||
action: AutomationAction,
|
||||
schedule: AutomationSchedule?,
|
||||
conditions: [AutomationCondition],
|
||||
createdAt: Date,
|
||||
updatedAt: Date
|
||||
) {
|
||||
self.id = id
|
||||
self.creatorId = creatorId
|
||||
self.name = name
|
||||
self.isEnabled = isEnabled
|
||||
self.trigger = trigger
|
||||
self.action = action
|
||||
self.schedule = schedule
|
||||
self.conditions = conditions
|
||||
self.createdAt = createdAt
|
||||
self.updatedAt = updatedAt
|
||||
}
|
||||
}
|
||||
|
|
@ -108,7 +108,7 @@ final class AutomationSettingsViewModel {
|
|||
switch newActionType {
|
||||
case .sendAutoReply: return .sendAutoReply(message: newReplyMessage)
|
||||
case .shareRateCard: return .sendAutoReply(message: "[Rate Card]")
|
||||
case .shareAvailability: return .shareAvailability
|
||||
case .shareAvailability: return .custom(type: "share_availability", payload: nil)
|
||||
case .archiveThread: return .archiveThread
|
||||
case .markAsRead: return .markAsRead
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,37 +36,40 @@ struct RateCardListView: View {
|
|||
|
||||
private func rateCardRow(_ card: RateCardContent) -> some View {
|
||||
VStack(alignment: .leading, spacing: LilithTheme.Spacing.sm) {
|
||||
ForEach(Array(card.services.enumerated()), id: \.offset) { _, service in
|
||||
ForEach(Array(card.rates.enumerated()), id: \.offset) { _, rate in
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(service.name)
|
||||
Text(rate.label ?? "\(Int(rate.duration)) min")
|
||||
.font(LilithTypography.bodyMedium)
|
||||
.foregroundStyle(LilithTheme.Colors.textPrimary)
|
||||
if let description = service.description {
|
||||
Text(description)
|
||||
.font(LilithTypography.caption)
|
||||
.foregroundStyle(LilithTheme.Colors.textTertiary)
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
Text("\(card.currency) \(NSDecimalNumber(decimal: service.priceAmount).intValue)")
|
||||
Text("\(card.currency) \(Int(rate.amount))")
|
||||
.font(LilithTypography.monoSmall)
|
||||
.foregroundStyle(LilithTheme.Colors.textSecondary)
|
||||
}
|
||||
}
|
||||
|
||||
if !card.services.isEmpty {
|
||||
HStack(spacing: 6) {
|
||||
ForEach(card.services, id: \.self) { service in
|
||||
Text(service)
|
||||
.font(LilithTypography.caption)
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.vertical, 3)
|
||||
.background(LilithTheme.Colors.textTertiary.opacity(0.1))
|
||||
.clipShape(Capsule())
|
||||
}
|
||||
}
|
||||
.padding(.top, 2)
|
||||
}
|
||||
|
||||
if let note = card.note {
|
||||
Text(note)
|
||||
.font(LilithTypography.caption)
|
||||
.foregroundStyle(LilithTheme.Colors.textTertiary)
|
||||
.padding(.top, 4)
|
||||
}
|
||||
|
||||
if let validUntil = card.validUntil {
|
||||
Text("Valid until \(validUntil, style: .date)")
|
||||
.font(LilithTypography.caption)
|
||||
.foregroundStyle(LilithTheme.Colors.textTertiary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -76,21 +79,22 @@ struct RateCardListView: View {
|
|||
try? await Task.sleep(for: .milliseconds(300))
|
||||
rateCards = [
|
||||
RateCardContent(
|
||||
services: [
|
||||
RateEntry(name: "Dinner Date", durationMinutes: 180, priceAmount: 600, description: "3-hour evening date"),
|
||||
RateEntry(name: "Overnight", durationMinutes: 720, priceAmount: 1800, description: "12-hour overnight"),
|
||||
profileId: "dev-profile-1",
|
||||
rates: [
|
||||
RateEntry(duration: 180, amount: 600, label: "Dinner Date"),
|
||||
RateEntry(duration: 720, amount: 1800, label: "Overnight"),
|
||||
],
|
||||
currency: "EUR",
|
||||
note: "All dates include dinner at a venue of your choice",
|
||||
validUntil: Date().addingTimeInterval(86400 * 30)
|
||||
services: ["Companionship", "Dinner"],
|
||||
note: "All dates include dinner at a venue of your choice"
|
||||
),
|
||||
RateCardContent(
|
||||
services: [
|
||||
RateEntry(name: "Coffee Meet", durationMinutes: 60, priceAmount: 200, description: "1-hour casual meeting"),
|
||||
profileId: "dev-profile-1",
|
||||
rates: [
|
||||
RateEntry(duration: 60, amount: 200, label: "Coffee Meet"),
|
||||
],
|
||||
currency: "EUR",
|
||||
note: nil,
|
||||
validUntil: nil
|
||||
services: ["Casual"]
|
||||
),
|
||||
]
|
||||
isLoading = false
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ let package = Package(
|
|||
.package(url: "https://forge.nasty.sh/lilith/swift-layout.git", from: "1.0.5"),
|
||||
// Messaging packages
|
||||
.package(url: "https://forge.nasty.sh/lilith/swift-chat-core.git", from: "1.0.1"),
|
||||
.package(url: "https://forge.nasty.sh/lilith/swift-domain-models.git", from: "1.0.3"),
|
||||
.package(url: "https://forge.nasty.sh/lilith/swift-domain-models.git", from: "1.0.4"),
|
||||
.package(url: "https://forge.nasty.sh/lilith/swift-api-client.git", from: "1.0.0"),
|
||||
.package(url: "https://forge.nasty.sh/lilith/swift-rich-cards.git", from: "1.0.0"),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ packages:
|
|||
from: "1.0.1"
|
||||
swift-domain-models:
|
||||
url: https://forge.nasty.sh/lilith/swift-domain-models.git
|
||||
from: "1.0.3"
|
||||
from: "1.0.4"
|
||||
swift-api-client:
|
||||
url: https://forge.nasty.sh/lilith/swift-api-client.git
|
||||
from: "1.0.0"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue