export: revision UX de estilos, 2 estilos nuevos y copia como texto

- Header elegante: logo fijado a la izquierda y titulo centrado de verdad
  (ZStack), fecha a la derecha
- School transpuesto: dias como columnas y comidas como filas — antes con
  1-2 comidas quedaba media pagina A4 apaisada en blanco
- Default: las celdas del grid se expanden para llenar la pagina (mismo
  sintoma de hueco que el school)
- Estilo nuevo "Story" (9:16, 2160x3840) para stories de IG/WhatsApp y
  "Minimal (imprimir)" en A4 con lineas finas sin fondos (ahorro tinta)
- Picker del preview pasa de segmentado a chips desplazables (5 estilos)
- WeekPlanTextExporter + boton "Copiar como texto (WhatsApp)" en el
  preview: menu semanal con *negritas* y emojis listo para pegar en
  WhatsApp/Telegram (evento analytics format=text)
- Harness de render en tests: genera PNG de los 5 estilos con datos de
  ejemplo en /tmp/mealmood-export-previews para revisar el diseno
- Nombres de estilos en espanol corregidos (estaban en ingles)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013H6bXqGX1ygwib1Dm3n3UG
This commit is contained in:
alexandrev-tibco
2026-09-01 16:04:07 +02:00
parent dc1a76275b
commit 715dd4ec5e
10 changed files with 455 additions and 65 deletions
+37 -5
View File
@@ -1406,6 +1406,7 @@ private struct WeekExportPreviewSheet: View {
@State private var selectedStyle: WeekExportStyle
@State private var previews: [WeekExportStyle: UIImage] = [:]
@State private var shareFile: ShareFile?
@State private var didCopyText: Bool = false
private struct ShareFile: Identifiable {
let url: URL
@@ -1423,13 +1424,25 @@ private struct WeekExportPreviewSheet: View {
var body: some View {
NavigationStack {
VStack(spacing: 14) {
Picker("share_export_style_picker_title", selection: $selectedStyle) {
ForEach(WeekExportStyle.allCases, id: \.self) { style in
Text(LocalizedStringKey(style.localizedKey)).tag(style)
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 8) {
ForEach(WeekExportStyle.allCases, id: \.self) { style in
Button {
selectedStyle = style
} label: {
Text(LocalizedStringKey(style.localizedKey))
.font(.mealMoodSmall.weight(.semibold))
.foregroundColor(selectedStyle == style ? .white : .mealMoodTextPrimary)
.padding(.horizontal, 14)
.padding(.vertical, 8)
.background(selectedStyle == style ? Color.mealMoodCoral : Color.mealMoodSurface)
.clipShape(Capsule())
}
.buttonStyle(.plain)
}
}
.padding(.horizontal, 16)
}
.pickerStyle(.segmented)
.padding(.horizontal, 16)
.padding(.top, 10)
Group {
@@ -1461,6 +1474,15 @@ private struct WeekExportPreviewSheet: View {
isEnabled: previews[selectedStyle] != nil
)
.padding(.horizontal, 16)
Button(action: copyAsText) {
Label(
String(localized: didCopyText ? "share_text_copied" : "share_export_copy_text"),
systemImage: didCopyText ? "checkmark.circle.fill" : "doc.on.doc"
)
.font(.mealMoodBodyBold)
.foregroundColor(didCopyText ? .mealMoodSuccess : .mealMoodCoral)
}
.padding(.bottom, 12)
}
.background(Color.mealMoodBackground.ignoresSafeArea())
@@ -1508,6 +1530,16 @@ private struct WeekExportPreviewSheet: View {
AnalyticsService.logWeekPlanShared(format: selectedStyle.rawValue)
shareFile = ShareFile(url: url)
}
private func copyAsText() {
UIPasteboard.general.string = WeekPlanTextExporter.text(plan: plan, settings: settings, dishes: dishes)
AnalyticsService.logWeekPlanShared(format: "text")
HapticManager.shared.notification(type: .success)
withAnimation { didCopyText = true }
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
withAnimation { didCopyText = false }
}
}
}