premium: configurar días y comidas de una semana concreta
Hasta ahora includeWeekends y activeMealTypes vivían solo en AppSettings y aplicaban a todo el calendario. WeekPlan puede ahora sobreescribirlos para su semana (includeWeekendsOverride / mealTypesOverrideRaw) y WeekSchedule resuelve qué manda en cada semana: su override si lo tiene, los ajustes globales si no. Todo lo que pintaba días y comidas —planificador, exports, compartir texto, widget, watch— pasa por settings.schedule(for:), así que una semana con fin de semana añadido o con desayuno activo se ve igual en todas partes. Crear o editar el override es premium; los ya guardados se respetan aunque la suscripción caduque, para no borrar comidas ya planificadas. La hoja avisa y pide confirmación cuando quitar un día o una comida se lleva por delante algo ya planificado. Refs #32 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013su1ttRiMeMYxkZJ1Y3246
This commit is contained in:
@@ -12,6 +12,13 @@ final class WeekPlan {
|
||||
var updatedAt: Date = Date()
|
||||
var userRating: Int = 0 // 0 = unrated, 1 = liked, -1 = disliked
|
||||
|
||||
/// Per-week overrides of the global schedule (2.1.1, premium). nil = follow
|
||||
/// `AppSettings`. Optional so existing stores lightweight-migrate and
|
||||
/// CloudKit accepts the new attributes.
|
||||
var includeWeekendsOverride: Bool?
|
||||
/// Comma-separated MealType raw values, chronological. nil = follow settings.
|
||||
var mealTypesOverrideRaw: String?
|
||||
|
||||
@Relationship(deleteRule: .cascade)
|
||||
var slots: [MealSlot]? = []
|
||||
|
||||
@@ -21,6 +28,36 @@ final class WeekPlan {
|
||||
set { slots = newValue }
|
||||
}
|
||||
|
||||
/// The meal types this week overrides the global setting with, or nil when
|
||||
/// it follows `AppSettings.activeMealTypes`.
|
||||
var mealTypesOverride: [MealType]? {
|
||||
get {
|
||||
guard let raw = mealTypesOverrideRaw else { return nil }
|
||||
let types = raw.split(separator: ",").compactMap { MealType(rawValue: String($0)) }
|
||||
guard !types.isEmpty else { return nil }
|
||||
return MealType.allCases.filter { types.contains($0) }
|
||||
}
|
||||
set {
|
||||
guard let newValue else {
|
||||
mealTypesOverrideRaw = nil
|
||||
return
|
||||
}
|
||||
let ordered = MealType.allCases.filter { newValue.contains($0) }
|
||||
// An empty selection would leave the week with no slots at all;
|
||||
// treat it as "no override" instead.
|
||||
mealTypesOverrideRaw = ordered.isEmpty ? nil : ordered.map(\.rawValue).joined(separator: ",")
|
||||
}
|
||||
}
|
||||
|
||||
var hasScheduleOverride: Bool {
|
||||
includeWeekendsOverride != nil || mealTypesOverrideRaw != nil
|
||||
}
|
||||
|
||||
func clearScheduleOverride() {
|
||||
includeWeekendsOverride = nil
|
||||
mealTypesOverrideRaw = nil
|
||||
}
|
||||
|
||||
init(
|
||||
id: UUID = UUID(),
|
||||
weekStartDate: Date,
|
||||
|
||||
Reference in New Issue
Block a user