diff --git a/AlloVoisinsSwiftUI/Core/Views/Sequoia/Components/SQCheckbox.swift b/AlloVoisinsSwiftUI/Core/Views/Sequoia/Components/SQCheckbox.swift new file mode 100644 index 0000000..494d3e5 --- /dev/null +++ b/AlloVoisinsSwiftUI/Core/Views/Sequoia/Components/SQCheckbox.swift @@ -0,0 +1,54 @@ +// +// SQCheckbox.swift +// AlloVoisinsSwiftUI +// +// Created by Victor on 25/11/2024. +// + +import SwiftUI + +struct SQCheckbox: View { + var text: String + @Binding var isChecked: Bool + var errorText: String? + @Binding var isInError: Bool + + init(_ text: String, isChecked: Binding, errorText: String? = nil, isInError: Binding = .constant(false)) { + self.text = text + self._isChecked = isChecked + self.errorText = errorText + self._isInError = isInError + } + + var body: some View { + VStack(alignment: .leading, spacing: 4) { + HStack(alignment: .top) { + if isChecked { + SQImage("checked_neutral", height: 20) + } else if isInError { + SQImage("checkbox_unchecked_error", height: 20) + } else { + SQImage("checkbox_unchecked", height: 20) + } + SQText(text) + } + .onTapGesture { + isChecked.toggle() + + if isInError && isChecked { + isInError = false + } + } + + HStack { + SQIcon(.circle_exclamation, customSize: 13, type: .solid, color: .sqSemanticRed) + SQText("Cette condition est obligatoire.", size: 12, font: .demiBold, textColor: .sqSemanticRed) + } + .isHidden(hidden: !isInError) + } + } +} + +#Preview { + SQCheckbox("Je comprends que j’engage ma responsabilité sur l’exhaustivité et l’authenticité des informations renseignées ci-dessus.", isChecked: .constant(false)) +} diff --git a/AlloVoisinsSwiftUI/Core/Views/Sequoia/Components/SQImagePicker.swift b/AlloVoisinsSwiftUI/Core/Views/Sequoia/Components/SQImagePicker.swift new file mode 100644 index 0000000..3d9f57d --- /dev/null +++ b/AlloVoisinsSwiftUI/Core/Views/Sequoia/Components/SQImagePicker.swift @@ -0,0 +1,141 @@ +// +// SQImagePicker.swift +// AlloVoisinsSwiftUI +// +// Created by Victor on 27/11/2024. +// + +import SwiftUI + +struct SQImagePicker: View { + let nbOfImages: Int = 4 + var images: [Image] = [] + + private let itemSpacing: CGFloat = 8 + private var columns: [GridItem] { + [ + GridItem(.fixed(160), spacing: itemSpacing), + GridItem(.fixed(160), spacing: itemSpacing) + ] + } + + var body: some View { + VStack(alignment: .leading) { + SQText("Images", font: .demiBold) + + LazyVGrid(columns: columns, alignment: .leading) { + ForEach(0 ..< nbOfImages) { _ in + SQImagePickerView() + } + } + } + } +} + +struct SQImagePickerView: View { + var image: Image? + @State var showSelection: Bool = false + + var body: some View { + VStack { + if let image = image { + image + .frame(width: 160, height: 160) + .background( + RoundedRectangle(cornerRadius: 8) + .fill(Color.sqNeutral(10))) + } else { + HStack { + SQIcon(.camera, size: .xl) + } + .frame(width: 160, height: 160) + .background( + RoundedRectangle(cornerRadius: 8) + .fill(Color.sqNeutral(10))) + } + } + .onTapGesture { + showSelection = true + } + .sheet(isPresented: $showSelection) { + SQImagePickerSelectorSheet() + } + } +} + +struct SQImagePickerSelectorSheet: View { + @Environment(\.dismiss) var dismiss + + var categoriesImages: [CategoriesImages] = [ + CategoriesImages(name: "Entretien - Réparation autres véhicules", pictures: [ + "square.and.arrow.up.fill", + "paperplane.circle.fill", + "tray.fill" + ]), + CategoriesImages(name: "Plomberie - Installation sanitaire", pictures: [ + "xmark.bin.circle.fill" + ]), + CategoriesImages(name: "Carrelage", pictures: [ + "document.on.document", + "richtext.page.fill.he" + ]) + ] + + private let itemSpacing: CGFloat = 8 + private var columns: [GridItem] { + [ + GridItem(.fixed(160), spacing: itemSpacing), + GridItem(.fixed(160), spacing: itemSpacing) + ] + } + + var body: some View { + VStack(spacing: 0) { + HStack { + Button { + dismiss() + } label: { + SQIcon(.xmark, size: .l) + } + + SQText("Sélectionner une photo", size: 19, font: .bold) + .frame(maxWidth: .infinity) + Spacer() + } + .padding() + ScrollView { + ForEach(categoriesImages, id: \.name) { category in + VStack { + VStack(alignment: .leading) { + SQText(category.name) + LazyVGrid(columns: columns, alignment: .leading) { + ForEach(category.pictures, id: \.self) { picture in + Image(systemName: picture) + .frame(width: 160, height: 120) + .background( + RoundedRectangle(cornerRadius: 8) + .fill(Color.sqNeutral(10))) + } + } + } + .padding() + + Rectangle() + .frame(height: 16) + .foregroundColor(Color.sqNeutral(10)) + } + } + } + } + } +} + +#Preview { + SQImagePicker() + .padding() +} + +struct CategoriesImages { + var name: String + var pictures: [String] +} diff --git a/AlloVoisinsSwiftUI/Core/Views/Sequoia/Components/SQTextEditor.swift b/AlloVoisinsSwiftUI/Core/Views/Sequoia/Components/SQTextEditor.swift new file mode 100644 index 0000000..bfcc982 --- /dev/null +++ b/AlloVoisinsSwiftUI/Core/Views/Sequoia/Components/SQTextEditor.swift @@ -0,0 +1,96 @@ +// +// SQTextEditor.swift +// AlloVoisinsSwiftUI +// +// Created by Victor on 27/11/2024. +// + +import SwiftUI + +struct SQTextEditor: View { + var label: String + var placeholder: String + var type: SQTextFieldType = .text + var errorText: String + var icon: SQIcon? + var isDisabled: Bool = false + var isOptional: Bool = false + var tooltipText: String? + @Binding var isInError: Bool + var minCharacters: Int? + var maxCharacters: Int? + @Binding var text: String + @FocusState private var isFocused: Bool + @State private var showTooltip = false + let infoAction: (() -> Void)? + let iconAction: (() -> Void)? + + private var accentColor: Color = .sqNeutral(80) + + init(_ label: String, + placeholder: String, + type: SQTextFieldType = .text, + errorText: String = "", + text: Binding, + icon: SQIcon? = nil, + isDisabled: Bool = false, + isOptional: Bool = false, + tooltipText: String? = nil, + isInError: Binding = .constant(false), + minCharacters: Int? = nil, + maxCharacters: Int? = nil, + infoAction: (() -> Void)? = nil, + iconAction: (() -> Void)? = nil) + { + self.label = label + self.placeholder = placeholder + self.type = type + self.errorText = errorText + self._text = text + self.icon = icon + self.isDisabled = isDisabled + self.isOptional = isOptional + self.tooltipText = tooltipText + self._isInError = isInError + self.minCharacters = minCharacters + self.maxCharacters = maxCharacters + self.infoAction = infoAction + self.iconAction = iconAction + } + + var body: some View { + VStack(alignment: .leading, spacing: 4) { + HStack(spacing: 8) { + SQText(label) + Spacer() + if isOptional { + SQText("Optionnel", size: 12, textColor: .sqNeutral(50)) + } + } + TextEditor(text: Binding( + get: { self.text }, + set: { self.text = String($0.prefix(self.maxCharacters ?? Int.max)) } + )) + .onChange(of: self.text, perform: { _ in + self.isInError = false + }) + .font(.sq(.medium)) + .foregroundStyle(Color.sqNeutral(100)) + .tint(accentColor) + .frame(height: 108) + .foregroundStyle(Color.sqNeutral()) + .background(isDisabled ? Color.sqNeutral(10) : .clear) + .padding(16) + .overlay( + RoundedRectangle(cornerRadius: 8) + .inset(by: 0.5) + .stroke(isInError ? .sqSemanticRed : isFocused ? accentColor : isDisabled ? Color.sqNeutral(20) : Color.sqNeutral(30), lineWidth: 1) + ) + } + } +} + +#Preview { + SQTextEditor("Zone de texte", placeholder: "Ex : Pro Solutions propose une gamme de services complète pour tout type de dépannage électroménager. Bénéficiez de nos 10 ans d’expérience ! Devis gratuit", text: .constant("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")) + .padding() +} diff --git a/AlloVoisinsSwiftUI/Core/Views/Sequoia/Components/SQTextField.swift b/AlloVoisinsSwiftUI/Core/Views/Sequoia/Components/SQTextField.swift index 3275c38..b402e42 100644 --- a/AlloVoisinsSwiftUI/Core/Views/Sequoia/Components/SQTextField.swift +++ b/AlloVoisinsSwiftUI/Core/Views/Sequoia/Components/SQTextField.swift @@ -8,8 +8,8 @@ import SwiftUI enum SQTextFieldType { - case text - case phoneNumber + case text + case phoneNumber } struct SQTextField: View { @@ -20,17 +20,33 @@ struct SQTextField: View { var icon: SQIcon? var isDisabled: Bool = false var isOptional: Bool = false + var tooltipText: String? @Binding var isInError: Bool var minCharacters: Int? var maxCharacters: Int? @Binding var text: String @FocusState private var isFocused: Bool + @State private var showTooltip = false let infoAction: (() -> Void)? let iconAction: (() -> Void)? private var accentColor: Color = .sqNeutral(80) - init(_ label: String, placeholder: String, type: SQTextFieldType = .text, errorText: String = "", text: Binding, icon: SQIcon? = nil, isDisabled: Bool = false, isOptional: Bool = false, isInError: Binding = .constant(false), minCharacters: Int? = nil, maxCharacters: Int? = nil, infoAction: (() -> Void)? = nil, iconAction: (() -> Void)? = nil) { + init(_ label: String, + placeholder: String, + type: SQTextFieldType = .text, + errorText: String = "", + text: Binding, + icon: SQIcon? = nil, + isDisabled: Bool = false, + isOptional: Bool = false, + tooltipText: String? = nil, + isInError: Binding = .constant(false), + minCharacters: Int? = nil, + maxCharacters: Int? = nil, + infoAction: (() -> Void)? = nil, + iconAction: (() -> Void)? = nil) + { self.label = label self.placeholder = placeholder self.type = type @@ -39,6 +55,7 @@ struct SQTextField: View { self.icon = icon self.isDisabled = isDisabled self.isOptional = isOptional + self.tooltipText = tooltipText self._isInError = isInError self.minCharacters = minCharacters self.maxCharacters = maxCharacters @@ -50,7 +67,23 @@ struct SQTextField: View { VStack(alignment: .leading, spacing: 4) { HStack(spacing: 8) { SQText(label) - if let infoAction = infoAction { + if let tooltipText = tooltipText { + Button { + withAnimation { + showTooltip.toggle() + } + } label: { + SQIcon(.circle_info, color: .sqNeutral(80)) + } + .overlay( + Group { + if showTooltip { + SQTooltip(text: tooltipText, isVisible: $showTooltip) + .fixedSize() + } + } + ) + } else if let infoAction = infoAction { Button { infoAction() } label: { @@ -125,6 +158,18 @@ struct SQTextField: View { } } } + .overlay( + Group { + if showTooltip { + Color.black.opacity(0.001) + .onTapGesture { + withAnimation { + showTooltip = false + } + } + } + } + ) } private var characterCountText: String { @@ -164,6 +209,13 @@ struct SQTextField: View { SQTextField("Label name", placeholder: "Placeholder", text: .constant(""), isDisabled: true) SQTextField("Label name", placeholder: "Placeholder", errorText: "Champ invalide", text: .constant(""), isInError: .constant(true)) SQTextField("Téléphone", placeholder: "01 23 45 67 89", type: .phoneNumber, text: .constant("")) + SQTextField( + "Numéro de RCS", + placeholder: "RCS VILLE B 123456789", + text: .constant(""), + isOptional: true, + tooltipText: "Vous pouvez trouver votre numéro RCS sur l'extrait Kbis de votre entreprise ou votre extrait K, si vous êtes un entrepreneur individuel.\n\nLe numéro RCS se compose tout d'abord de la mention RCS, puis du numéro d'immatriculation de la ville dans laquelle a été créée la société, d'une lettre et enfin du numéro SIREN à 9 chiffres." + ) } .padding() } diff --git a/AlloVoisinsSwiftUI/Core/Views/Sequoia/Components/SQTooltip.swift b/AlloVoisinsSwiftUI/Core/Views/Sequoia/Components/SQTooltip.swift new file mode 100644 index 0000000..55272b5 --- /dev/null +++ b/AlloVoisinsSwiftUI/Core/Views/Sequoia/Components/SQTooltip.swift @@ -0,0 +1,43 @@ +// +// SQTooltip.swift +// AlloVoisinsSwiftUI +// +// Created by Victor on 25/11/2024. +// + +import SwiftUI + +struct SQTooltip: View { + let text: String + @Binding var isVisible: Bool + @State private var tooltipHeight: CGFloat = 0 + + private struct Constants { + static let cornerRadius: CGFloat = 8 + static let padding: CGFloat = 16 + static let maxWidth: CGFloat = 300 + static let spacing: CGFloat = 4 + } + + var body: some View { + VStack(alignment: .leading, spacing: 0) { + SQText(text, textColor: .white) + .fixedSize(horizontal: false, vertical: true) + .padding(Constants.padding) + .background( + GeometryReader { geo in + Color.sqNeutral(100) + .clipShape(RoundedRectangle(cornerRadius: Constants.cornerRadius)) + .onAppear { + tooltipHeight = geo.size.height + } + } + ) + .frame(maxWidth: Constants.maxWidth) + } + .position(x: 210, y: 0) + .offset(y: -(tooltipHeight/2 + Constants.spacing)) + .opacity(isVisible ? 1 : 0) + .animation(.easeInOut(duration: 0.2), value: isVisible) + } +} diff --git a/AlloVoisinsSwiftUI/Extensions/Extension+View.swift b/AlloVoisinsSwiftUI/Extensions/Extension+View.swift index aa5e67e..14d3926 100644 --- a/AlloVoisinsSwiftUI/Extensions/Extension+View.swift +++ b/AlloVoisinsSwiftUI/Extensions/Extension+View.swift @@ -39,3 +39,28 @@ extension Font { .custom(font.rawValue, size: size) } } + +extension View { + func isHidden(hidden: Bool = false, remove: Bool = false) -> some View { + modifier( + IsHidden( + hidden: hidden, + remove: remove + )) + } +} + +struct IsHidden: ViewModifier { + var hidden = false + var remove = false + func body(content: Content) -> some View { + if hidden { + if remove { + } else { + content.hidden() + } + } else { + content + } + } +} diff --git a/AlloVoisinsSwiftUI/Features/Marketing/Views/Flyers/FlyerColorSelectionView.swift b/AlloVoisinsSwiftUI/Features/Marketing/Views/Flyers/FlyerColorSelectionView.swift new file mode 100644 index 0000000..e1cb123 --- /dev/null +++ b/AlloVoisinsSwiftUI/Features/Marketing/Views/Flyers/FlyerColorSelectionView.swift @@ -0,0 +1,51 @@ +// +// FlyerColorSelectionView.swift +// AlloVoisinsSwiftUI +// +// Created by Victor on 25/11/2024. +// + +import SwiftUI + +struct FlyerColorSelectionView: View { + @State var goToNext: Bool = false + @State private var applyToAll: Bool = true + @State private var selectedColor: Color = .sqNeutral() + var selectedTemplate: FlyerTemplate + + var body: some View { + VStack { + VStack(alignment: .leading, spacing: 32) { + VStack(alignment: .leading, spacing: 16) { + SQColorPicker("Couleur principale", selectedColor: $selectedColor, subtitle: "Choisissez la couleur qui sera appliquée sur vos prospectus.") + SQText("Aperçu", size: 18, font: .bold) + selectedTemplate.imageColorTemplate(isLight: selectedColor.isLight) + .background(selectedColor) + .frame(maxWidth: .infinity) + } + VStack(alignment: .leading) { + Toggle(isOn: $applyToAll) { + SQText("Appliquer cette couleur sur mes cartes de visite, mes devis et mes factures") + } + .tint(Color.sqNeutral(100)) + SQText("Nous vous recommandons d’appliquer la même couleur sur tous vos documents.", size: 12) + } + Spacer() + } + .padding() + SQFooter { + SQButton("Continuer", color: .sqNeutral(100), textColor: .white) { + self.goToNext.toggle() + } + } + } + .sqNavigationBar(title: "Choix de la couleur ") + .navigationDestination(isPresented: $goToNext) { + CardFormView() + } + } +} + +#Preview { + FlyerColorSelectionView(selectedTemplate: .template4) +} diff --git a/AlloVoisinsSwiftUI/Features/Marketing/Views/Flyers/FlyerFormView.swift b/AlloVoisinsSwiftUI/Features/Marketing/Views/Flyers/FlyerFormView.swift new file mode 100644 index 0000000..fcb28bc --- /dev/null +++ b/AlloVoisinsSwiftUI/Features/Marketing/Views/Flyers/FlyerFormView.swift @@ -0,0 +1,171 @@ +// +// FlyerFormView.swift +// AlloVoisinsSwiftUI +// +// Created by Victor on 25/11/2024. +// + +import SwiftUI +import _PhotosUI_SwiftUI + +struct FlyerFormView: View { + @State var title: String = "" + @State var subtitle: String = "" + @State var job: String = "" + @State var showRating: Bool = true + @State var phoneNumber: String = "" + @State var address: String = "" + @State var selectedPicture: PhotosPickerItem? + @State private var image: Image? + @State private var showImagePicker = false + @State private var showPhotoPicker = false + @State private var showActionSheet = false + @State private var useCamera = false + @State private var authentConfirm: Bool = false + @State private var confirmIsInError: Bool = false + + var body: some View { + VStack { + ScrollView { + VStack { + VStack(alignment: .leading, spacing: 16) { + VStack(alignment: .leading) { + SQText("Informations", size: 24, font: .bold) + SQText("Les modifications apportées sur votre prospectus ne seront pas reportées sur votre profil.") + } + VStack(alignment: .leading) { + SQText("Image", font: .demiBold) + + ZStack(alignment: .bottomTrailing) { + Button(action: { showActionSheet = true }) { + if let image = image { + image + .resizable() + .scaledToFill() + .frame(width: 160, height: 160) + .clipShape(Circle()) + } else { + SQIcon(.camera, customSize: 40) + .frame(width: 160, height: 160) + .background(Color.sqNeutral(10)) + .clipShape(Circle()) + } + } + + if image != nil { + SQIcon(.pen_to_square, size: .m) + .padding(8) + .background(Circle().fill(Color.sqNeutral(15))) + .shadow(color: .sqNeutral(100).opacity(0.1), radius: 4, x: 0, y: 2) + .offset(x: -8, y: -8) + } + } + .frame(maxWidth: .infinity) + } + SQTextField("Titre", placeholder: "Ex : Pro Solutions", errorText: "", text: $title) + SQTextField("Sous-titre", placeholder: "Ex : Martin Dupont", errorText: "", text: $subtitle, isOptional: true) + SQTextField("Métier", placeholder: "Ex : Dépannage électroménager", errorText: "", text: $job, isOptional: true) + VStack(alignment: .leading, spacing: 0) { + Toggle(isOn: $showRating) { + SQText("Afficher ma note AlloVoisins", font: .demiBold) + } + .tint(Color.sqNeutral(100)) + HStack(spacing: 4) { + SQIcon(.star, type: .solid, color: .sqGold(50)) + SQText("4,7/5 sur", size: 12, font: .demiBold) + SQImage("logo", height: 14) + } + } + .padding(.horizontal, 2) + } + .padding() + + Rectangle() + .frame(height: 16) + .foregroundColor(Color.sqNeutral(10)) + + VStack(alignment: .leading, spacing: 16) { + SQTextEditor("Zone de text", placeholder: "Ex : Pro Solutions propose une gamme de services complète pour tout type de dépannage électroménager. Bénéficiez de nos 10 ans d’expérience ! Devis gratuit", text: .constant("")) + + SQTextField("Prestation 1", placeholder: "Ex : Réparation lave-vaisselle", errorText: "", text: $job, isOptional: true) + SQTextField("Prestation 2", placeholder: "Ex : Réparation machine à laver", errorText: "", text: $job, isOptional: true) + SQTextField("Prestation 3", placeholder: "Ex : Réparation four", errorText: "", text: $job, isOptional: true) + SQTextField("Prestation 4", placeholder: "Ex : Réparation outillage", errorText: "", text: $job, isOptional: true) + SQTextField("Prestation 5", placeholder: "Ex : Dépannage électroménager", errorText: "", text: $job, isOptional: true) + } + .padding() + + Rectangle() + .frame(height: 16) + .foregroundColor(Color.sqNeutral(10)) + + VStack(alignment: .leading, spacing: 16) { + SQTextField("Numéro de téléphone", placeholder: "Ex : 06 12 34 56 78", errorText: "", text: $phoneNumber) + SQTextField("Adresse complète", placeholder: "Ex : 1 rue de la gare, 67000 Strasbourg", errorText: "", text: $address) + } + .padding() + + Rectangle() + .frame(height: 16) + .foregroundColor(Color.sqNeutral(10)) + + VStack(alignment: .leading, spacing: 16) { + SQText("Mentions légales obligatoires", size: 18, font: .bold) + + SQTextField("Dénomination sociale", placeholder: "Ex : Pro solutions", errorText: "", text: $job, isOptional: true) + SQTextField("Adresse du siège social", placeholder: "Ex : 16 rue de la Redoute, 67500 Haguenau", errorText: "", text: $job, isOptional: true) + VStack(spacing: 0) { + SQTextField("Numéro SIRET", placeholder: "Ex : 12345678901234", errorText: "", text: $job, isOptional: true) + SQText("Le numéro SIRET se compose de 14 chiffres : les 9 chiffres du SIREN + 5 chiffres propres à chaque établissement (NIC).", size: 12, textColor: .sqNeutral(50)) + } + SQTextField("Numéro de RCS", placeholder: "Ex : RCS STRASBOURG B 123456789", errorText: "", text: $job, isOptional: true) + SQTextField("Statut juridique", placeholder: "Ex : SARL", errorText: "", text: $job, isOptional: true) + SQTextField("Montant du capital social (€)", placeholder: "Ex : 1 000,00", errorText: "", text: $job, isOptional: true) + SQTextField("Autre champ relatif à votre activité", placeholder: "Ex : Pour votre santé, mangez 5 fruits et légumes par jour", errorText: "", text: $job, isOptional: true) + SQCheckbox("Je comprends que j’engage ma responsabilité sur l’exhaustivité et l’authenticité des informations renseignées ci-dessus.", isChecked: $authentConfirm, isInError: $confirmIsInError) + } + .padding() + } + } + SQFooter { + SQButton("Aperçu", color: .sqNeutral(100), textColor: .sqNeutral(100), icon: SQIcon(.eye, color: .sqNeutral(100)), isFull: false) {} + .sqStyle() + SQButton("Imprimer", color: .sqNeutral(100), textColor: .white, icon: SQIcon(.print, color: .white)) { + if authentConfirm == false { + self.confirmIsInError = true + } + } + .sqStyle() + } + } + .confirmationDialog("Choisir une image", isPresented: $showActionSheet, actions: { + Button("Appareil photo") { + useCamera = true + showImagePicker = true + } + + Button("Galerie") { + useCamera = false + showPhotoPicker = true + } + + Button("Annuler", role: .cancel) {} + }) + .photosPicker(isPresented: $showPhotoPicker, selection: $selectedPicture) + .sheet(isPresented: $showImagePicker) { + if useCamera { + ImagePicker(image: $image, sourceType: .camera) + } + } + .task(id: selectedPicture) { + if let data = try? await selectedPicture?.loadTransferable(type: Image.self) { + image = data + } + } + .sqNavigationBar(title: "Mon prospectus") + } +} + +#Preview { + FlyerFormView() +} diff --git a/AlloVoisinsSwiftUI/Features/Marketing/Views/Flyers/FlyerPrintView.swift b/AlloVoisinsSwiftUI/Features/Marketing/Views/Flyers/FlyerPrintView.swift new file mode 100644 index 0000000..39fb5fd --- /dev/null +++ b/AlloVoisinsSwiftUI/Features/Marketing/Views/Flyers/FlyerPrintView.swift @@ -0,0 +1,18 @@ +// +// FlyerPrintView.swift +// AlloVoisinsSwiftUI +// +// Created by Victor on 25/11/2024. +// + +import SwiftUI + +struct FlyerPrintView: View { + var body: some View { + Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + } +} + +#Preview { + FlyerPrintView() +} diff --git a/AlloVoisinsSwiftUI/Features/Marketing/Views/Flyers/FlyerTemplateSelectionView.swift b/AlloVoisinsSwiftUI/Features/Marketing/Views/Flyers/FlyerTemplateSelectionView.swift new file mode 100644 index 0000000..2e7a8a8 --- /dev/null +++ b/AlloVoisinsSwiftUI/Features/Marketing/Views/Flyers/FlyerTemplateSelectionView.swift @@ -0,0 +1,108 @@ +// +// FlyerTemplateSelectionView.swift +// AlloVoisinsSwiftUI +// +// Created by Victor on 25/11/2024. +// + +import SwiftUI + +enum FlyerTemplate: String, CaseIterable { + case template1 + case template2 + case template3 + case template4 + + var image: SQImage { + switch self { + case .template1: + SQImage("flyer_template_1", height: 284) + case .template2: + SQImage("flyer_template_2", height: 284) + case .template3: + SQImage("flyer_template_3", height: 284) + case .template4: + SQImage("flyer_template_4", height: 284) + } + } + + var nbOfPictures: Int { + switch self { + case .template1: + 1 + case .template2: + 3 + case .template3: + 4 + case .template4: + 2 + } + } + + func imageColorTemplate(isLight: Bool) -> SQImage { + switch self { + case .template1: + if isLight { + return SQImage("flyer_color_template_1_black", height: 284) + } else { + return SQImage("flyer_color_template_1_white", height: 284) + } + case .template2: + return SQImage("flyer_color_template_2", height: 284) + case .template3: + if isLight { + return SQImage("flyer_color_template_3_black", height: 284) + } else { + return SQImage("flyer_color_template_3_white", height: 284) + } + case .template4: + if isLight { + return SQImage("flyer_color_template_4_black", height: 284) + } else { + return SQImage("flyer_color_template_4_white", height: 284) + } + } + } +} + +struct FlyerTemplateSelectionView: View { + @State var goToNext: Bool = false + @State var selectedTemplate: FlyerTemplate? + + var body: some View { + VStack { + ScrollView { + LazyVStack(spacing: 16) { + ForEach(FlyerTemplate.allCases, id: \.self) { template in + template.image + .overlay( + Rectangle() + .inset(by: selectedTemplate == template ? 1 : 0.5) + .stroke(selectedTemplate == template ? Color.sqNeutral(100) : Color.sqNeutral(20), lineWidth: selectedTemplate == template ? 2 : 1) + ) + .opacity(selectedTemplate != nil ? selectedTemplate == template ? 1 : 0.5 : 1) + .onTapGesture { + selectedTemplate = template + } + } + } + } + SQFooter { + SQButton("Continuer", color: .sqNeutral(100), textColor: .white) { + if selectedTemplate != nil { + goToNext.toggle() + } + } + .disabled(selectedTemplate == nil) + } + } + .sqNavigationBar(title: "Choix du modèle") + .navigationDestination(isPresented: $goToNext) { +// FlyerColorSelectionView(selectedTemplate: selectedTemplate ?? FlyerTemplate.template1) + } + } +} + +#Preview { + FlyerTemplateSelectionView() +} diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Icons/AVCheckboxButton/checkbox_unchecked_error.imageset/Contents.json b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Icons/AVCheckboxButton/checkbox_unchecked_error.imageset/Contents.json new file mode 100644 index 0000000..37accc5 --- /dev/null +++ b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Icons/AVCheckboxButton/checkbox_unchecked_error.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "check.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Icons/AVCheckboxButton/checkbox_unchecked_error.imageset/check.pdf b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Icons/AVCheckboxButton/checkbox_unchecked_error.imageset/check.pdf new file mode 100644 index 0000000..5864905 Binary files /dev/null and b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Icons/AVCheckboxButton/checkbox_unchecked_error.imageset/check.pdf differ diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/Contents.json b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_1_black.imageset/Contents.json b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_1_black.imageset/Contents.json new file mode 100644 index 0000000..2f8b7b0 --- /dev/null +++ b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_1_black.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "flyer_color_template_1_black.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_1_black.imageset/flyer_color_template_1_black.pdf b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_1_black.imageset/flyer_color_template_1_black.pdf new file mode 100644 index 0000000..ad6701d Binary files /dev/null and b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_1_black.imageset/flyer_color_template_1_black.pdf differ diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_1_white.imageset/Contents.json b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_1_white.imageset/Contents.json new file mode 100644 index 0000000..4939d62 --- /dev/null +++ b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_1_white.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "flyer_color_template_1.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_1_white.imageset/flyer_color_template_1.pdf b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_1_white.imageset/flyer_color_template_1.pdf new file mode 100644 index 0000000..12fde27 Binary files /dev/null and b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_1_white.imageset/flyer_color_template_1.pdf differ diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_2.imageset/Contents.json b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_2.imageset/Contents.json new file mode 100644 index 0000000..9c296c7 --- /dev/null +++ b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_2.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "flyer_color_template_2.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_2.imageset/flyer_color_template_2.pdf b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_2.imageset/flyer_color_template_2.pdf new file mode 100644 index 0000000..c28693f Binary files /dev/null and b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_2.imageset/flyer_color_template_2.pdf differ diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_3_black.imageset/Contents.json b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_3_black.imageset/Contents.json new file mode 100644 index 0000000..8164835 --- /dev/null +++ b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_3_black.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "flyer_color_template_3_black.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_3_black.imageset/flyer_color_template_3_black.pdf b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_3_black.imageset/flyer_color_template_3_black.pdf new file mode 100644 index 0000000..12f6ff2 Binary files /dev/null and b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_3_black.imageset/flyer_color_template_3_black.pdf differ diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_3_white.imageset/Contents.json b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_3_white.imageset/Contents.json new file mode 100644 index 0000000..ddb6784 --- /dev/null +++ b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_3_white.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "flyer_color_template_3.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_3_white.imageset/flyer_color_template_3.pdf b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_3_white.imageset/flyer_color_template_3.pdf new file mode 100644 index 0000000..465c653 Binary files /dev/null and b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_3_white.imageset/flyer_color_template_3.pdf differ diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_4_black.imageset/Contents.json b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_4_black.imageset/Contents.json new file mode 100644 index 0000000..e14c384 --- /dev/null +++ b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_4_black.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "flyer_color_template_4_black.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_4_black.imageset/flyer_color_template_4_black.pdf b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_4_black.imageset/flyer_color_template_4_black.pdf new file mode 100644 index 0000000..f833078 Binary files /dev/null and b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_4_black.imageset/flyer_color_template_4_black.pdf differ diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_4_white.imageset/Contents.json b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_4_white.imageset/Contents.json new file mode 100644 index 0000000..60cb4ba --- /dev/null +++ b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_4_white.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "flyer_color_template_4.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_4_white.imageset/flyer_color_template_4.pdf b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_4_white.imageset/flyer_color_template_4.pdf new file mode 100644 index 0000000..4c5c431 Binary files /dev/null and b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_color_template_4_white.imageset/flyer_color_template_4.pdf differ diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_1.imageset/Contents.json b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_1.imageset/Contents.json new file mode 100644 index 0000000..f2870c9 --- /dev/null +++ b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_1.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "prospectus 1.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_1.imageset/prospectus 1.png b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_1.imageset/prospectus 1.png new file mode 100644 index 0000000..c6e219f Binary files /dev/null and b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_1.imageset/prospectus 1.png differ diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_2.imageset/Contents.json b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_2.imageset/Contents.json new file mode 100644 index 0000000..e42a99c --- /dev/null +++ b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_2.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "prospectus 2.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_2.imageset/prospectus 2.png b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_2.imageset/prospectus 2.png new file mode 100644 index 0000000..6f950ee Binary files /dev/null and b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_2.imageset/prospectus 2.png differ diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_3.imageset/Contents.json b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_3.imageset/Contents.json new file mode 100644 index 0000000..fda7e10 --- /dev/null +++ b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_3.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "prospectus 3.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_3.imageset/prospectus 3.png b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_3.imageset/prospectus 3.png new file mode 100644 index 0000000..e338d7f Binary files /dev/null and b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_3.imageset/prospectus 3.png differ diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_4.imageset/Contents.json b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_4.imageset/Contents.json new file mode 100644 index 0000000..4c91a90 --- /dev/null +++ b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_4.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "prospectus 4.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_4.imageset/prospectus 4.png b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_4.imageset/prospectus 4.png new file mode 100644 index 0000000..f82cb64 Binary files /dev/null and b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyer/flyer_template_4.imageset/prospectus 4.png differ diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyers.imageset/Contents.json b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyers.imageset/Contents.json index 32d9bc6..d114ab7 100644 --- a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyers.imageset/Contents.json +++ b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyers.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "image (1).png", + "filename" : "image.png", "idiom" : "universal" } ], diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyers.imageset/image (1).png b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyers.imageset/image (1).png deleted file mode 100644 index bb135a8..0000000 Binary files a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyers.imageset/image (1).png and /dev/null differ diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyers.imageset/image.png b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyers.imageset/image.png new file mode 100644 index 0000000..94fc8ff Binary files /dev/null and b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/flyers.imageset/image.png differ