diff --git a/AlloVoisinsSwiftUI/AlloVoisinsSwiftUIApp.swift b/AlloVoisinsSwiftUI/AlloVoisinsSwiftUIApp.swift index a4442c1..e118465 100644 --- a/AlloVoisinsSwiftUI/AlloVoisinsSwiftUIApp.swift +++ b/AlloVoisinsSwiftUI/AlloVoisinsSwiftUIApp.swift @@ -12,7 +12,7 @@ struct AlloVoisinsSwiftUIApp: App { var body: some Scene { WindowGroup { NavigationStack { - ResiliationNavigationScreen(resiliationType: .apProWithTrial) + ResiliationNavigationScreen(viewModel: ResiliationViewModel(resiliationType: .apProWithTrial)) } } } diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/allomoji_sad.imageset/Contents.json b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/allomoji_sad.imageset/Contents.json new file mode 100644 index 0000000..5bddf05 --- /dev/null +++ b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/allomoji_sad.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "allomoji_sad.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/allomoji_sad.imageset/allomoji_sad.pdf b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/allomoji_sad.imageset/allomoji_sad.pdf new file mode 100644 index 0000000..7e3d603 --- /dev/null +++ b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/allomoji_sad.imageset/allomoji_sad.pdf @@ -0,0 +1,365 @@ +%PDF-1.7 + +1 0 obj + << /Length 2 0 R + /Range [ 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 ] + /Domain [ 0.000000 1.000000 ] + /FunctionType 4 + >> +stream +{ 0.436170 exch 0.867448 exch 0.925356 exch dup 0.000000 gt { exch pop exch pop exch pop dup 0.000000 sub -0.217539 mul 0.436170 add exch dup 0.000000 sub -0.193018 mul 0.867448 add exch dup 0.000000 sub 0.074644 mul 0.925356 add exch } if dup 1.000000 gt { exch pop exch pop exch pop 0.218632 exch 0.674430 exch 1.000000 exch } if pop } +endstream +endobj + +2 0 obj + 338 +endobj + +3 0 obj + << /Pattern << /P1 << /Matrix [ -149.568039 -159.712708 159.712708 -149.568039 -64.525940 417.659363 ] + /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] + /ColorSpace /DeviceRGB + /Function 1 0 R + /Domain [ 0.000000 1.000000 ] + /ShadingType 2 + /Extend [ true true ] + >> + /PatternType 2 + /Type /Pattern + >> >> + /ExtGState << /E1 << /ca 0.097959 >> >> + >> +endobj + +4 0 obj + << /Length 5 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +/E1 gs +1.000000 0.000000 -0.000000 1.000000 53.714600 13.998047 cm +0.000000 0.000000 0.000000 scn +90.547752 7.723469 m +90.547752 3.458379 70.278847 0.000010 45.275021 0.000010 c +20.271200 0.000010 0.000000 3.458379 0.000000 7.723469 c +0.000000 11.990851 20.271200 15.449219 45.275021 15.449219 c +70.278847 15.449219 90.547752 11.990851 90.547752 7.723469 c +f* +n +Q +q +1.000000 0.000000 -0.000000 1.000000 20.402832 36.408203 cm +/Pattern cs +/P1 scn +159.382812 78.224625 m +159.217804 88.803696 154.723541 98.578331 147.476791 104.113091 c +90.969528 147.272766 l +82.748749 153.552368 72.391983 153.320892 64.427895 146.681473 c +10.877094 102.034409 l +3.937446 96.247543 -0.158046 86.436234 0.004673 75.974052 c +0.678470 32.376640 l +0.942030 15.355255 12.194895 1.725754 25.815214 1.938904 c +135.868683 3.641724 l +149.488998 3.852570 160.315598 17.821259 160.052032 34.842651 c +159.382812 78.224625 l +h +f* +n +Q +q +1.000000 0.000000 -0.000000 1.000000 115.383301 100.441895 cm +1.000000 1.000000 1.000000 scn +10.930661 0.748501 m +8.290481 0.737041 5.648008 0.723290 3.005536 0.714124 c +1.428762 0.709539 0.074294 1.928792 0.005539 3.503277 c +-0.028838 4.339794 0.094920 5.224439 0.429526 6.143462 c +1.252291 8.403203 3.232426 10.158743 5.595296 10.610232 c +10.013932 11.449041 13.889405 8.100682 13.914616 3.826425 c +13.916907 3.737043 13.914616 3.647662 13.912324 3.558280 c +13.855028 1.981503 12.507436 0.755376 10.930661 0.748501 c +f* +n +Q +q +1.000000 0.000000 -0.000000 1.000000 71.195068 100.230957 cm +1.000000 1.000000 1.000000 scn +0.000070 3.647342 m +0.004654 4.238633 0.087159 4.848259 0.261338 5.476219 c +0.944303 7.923890 2.979445 9.885694 5.468369 10.401355 c +9.937431 11.329544 13.888540 7.958268 13.913751 3.642758 c +13.913751 3.610673 l +13.918334 2.024729 12.522612 0.787143 10.936667 0.784850 c +8.287316 0.782558 5.640256 0.777975 2.990904 0.775683 c +1.384333 0.773392 -0.011389 2.040771 0.000070 3.647342 c +f* +n +Q +q +1.000000 0.000000 -0.000000 1.000000 89.196533 74.000000 cm +1.000000 1.000000 1.000000 scn +3.004584 6.093983 m +5.156945 7.444341 8.546254 8.799805 12.205587 8.799805 c +15.864919 8.799805 19.254234 7.444343 21.406603 6.093986 c +22.428444 5.452901 23.424566 4.657184 23.954453 3.813828 c +24.146761 3.507753 24.766466 2.425399 24.132900 1.254358 c +23.488171 0.062685 22.213228 -0.000194 21.805601 -0.000194 c +20.861500 -0.000194 20.007589 0.226774 19.263977 0.487279 c +18.773603 0.659066 18.232281 0.884323 17.729542 1.093524 c +17.516951 1.181988 17.311260 1.267580 17.119238 1.345045 c +15.740918 1.901081 14.239561 2.399805 12.205587 2.399805 c +10.171617 2.399805 8.670266 1.901080 7.291955 1.345045 c +7.099933 1.267580 6.894242 1.181987 6.681652 1.093523 c +6.178916 0.884323 5.637596 0.659066 5.147226 0.487279 c +4.403615 0.226773 3.549706 -0.000196 2.605604 -0.000196 c +2.197973 -0.000196 0.923040 0.062685 0.278309 1.254348 c +-0.355261 2.425384 0.264434 3.507739 0.456743 3.813818 c +0.986627 4.657178 1.982746 5.452897 3.004584 6.093983 c +h +f* +n +Q +q +1.000000 0.000000 -0.000000 1.000000 112.800293 90.399902 cm +0.168362 0.160503 0.179167 scn +31.999998 16.000000 m +31.999998 7.163446 24.836554 0.000002 15.999999 0.000002 c +7.163444 0.000002 0.000000 7.163446 0.000000 16.000000 c +0.000000 24.836555 7.163444 32.000000 15.999999 32.000000 c +24.836554 32.000000 31.999998 24.836555 31.999998 16.000000 c +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 119.200439 110.399902 cm +1.000000 1.000000 1.000000 scn +8.000000 4.000000 m +8.000000 1.790862 6.209138 0.000000 4.000000 0.000000 c +1.790861 0.000000 0.000000 1.790862 0.000000 4.000000 c +0.000000 6.209139 1.790861 8.000000 4.000000 8.000000 c +6.209138 8.000000 8.000000 6.209139 8.000000 4.000000 c +h +f +n +Q +q +-1.000000 -0.000000 -0.000000 1.000000 130.400391 116.799805 cm +1.000000 1.000000 1.000000 scn +3.200000 1.600195 m +3.200000 0.716540 2.483656 0.000195 1.600000 0.000195 c +0.716344 0.000195 0.000000 0.716540 0.000000 1.600195 c +0.000000 2.483851 0.716344 3.200195 1.600000 3.200195 c +2.483656 3.200195 3.200000 2.483851 3.200000 1.600195 c +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 116.197754 92.000000 cm +0.298039 0.266667 0.341176 scn +0.210692 9.427586 m +0.819494 10.927945 2.263791 11.200195 3.002827 11.200195 c +4.263373 11.200195 5.321895 10.698198 6.093330 10.247780 c +6.611842 9.945037 7.198322 9.538357 7.710639 9.183104 c +7.915307 9.041182 8.108138 8.907468 8.280070 8.791867 c +9.648875 7.871538 10.930213 7.200195 12.602841 7.200195 c +14.275468 7.200195 15.556796 7.871536 16.925592 8.791864 c +17.097525 8.907465 17.290358 9.041180 17.495024 9.183102 c +18.007338 9.538354 18.593817 9.945034 19.112326 10.247778 c +19.883757 10.698196 20.942278 11.200195 22.202826 11.200195 c +22.941864 11.200195 24.386152 10.927944 24.994959 9.427594 c +25.463491 8.272933 25.033445 7.210503 24.829237 6.777150 c +24.329792 5.717262 23.346052 4.650410 22.280838 3.759346 c +20.099072 1.934270 16.546749 0.000196 12.602841 0.000196 c +8.658937 0.000196 5.106606 1.934269 2.924833 3.759343 c +1.859617 4.650406 0.875873 5.717257 0.376423 6.777142 c +0.172215 7.210493 -0.257837 8.272923 0.210692 9.427586 c +h +f* +n +Q +q +-1.000000 -0.000000 -0.000000 1.000000 140.000488 97.600098 cm +1.000000 1.000000 1.000000 scn +4.000000 2.000000 m +4.000000 0.895431 3.104569 0.000000 2.000000 0.000000 c +0.895430 0.000000 0.000000 0.895431 0.000000 2.000000 c +0.000000 3.104569 0.895430 4.000000 2.000000 4.000000 c +3.104569 4.000000 4.000000 3.104569 4.000000 2.000000 c +h +f +n +Q +q +1.000000 -0.000000 0.000000 1.000000 116.197998 88.799805 cm +0.839216 0.941176 1.000000 scn +2.186750 7.132430 m +2.481733 7.187536 2.767972 7.200195 3.002226 7.200195 c +22.202225 7.200195 l +22.436480 7.200195 22.722717 7.187535 23.017700 7.132430 c +23.223743 7.093940 23.849474 6.967839 24.399368 6.459650 c +24.724783 6.158916 25.043146 5.702694 25.159731 5.094691 c +25.273575 4.500982 25.151371 3.990361 25.002514 3.640070 c +24.743748 3.031134 24.310673 2.673494 24.152058 2.547267 c +23.757078 2.232945 23.281164 2.001373 22.906059 1.838783 c +22.485668 1.656564 21.994732 1.478374 21.458691 1.310222 c +19.338472 0.645127 16.070730 0.000196 12.602242 0.000196 c +9.133754 0.000196 5.866003 0.645127 3.745779 1.310222 c +3.209736 1.478374 2.718797 1.656562 2.298405 1.838781 c +1.923299 2.001371 1.447385 2.232941 1.052409 2.547260 c +0.893792 2.673485 0.460720 3.031119 0.201949 3.640047 c +0.053092 3.990332 -0.069120 4.500952 0.044717 5.094664 c +0.161296 5.702672 0.479656 6.158901 0.805074 6.459641 c +1.354972 6.967839 1.980710 7.093940 2.186750 7.132430 c +h +f* +n +Q +q +1.000000 0.000000 -0.000000 1.000000 56.800049 90.399902 cm +0.168362 0.160503 0.179167 scn +31.999998 16.000000 m +31.999998 7.163446 24.836554 0.000002 15.999999 0.000002 c +7.163444 0.000002 0.000000 7.163446 0.000000 16.000000 c +0.000000 24.836555 7.163444 32.000000 15.999999 32.000000 c +24.836554 32.000000 31.999998 24.836555 31.999998 16.000000 c +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 63.200439 110.399902 cm +1.000000 1.000000 1.000000 scn +8.000000 4.000000 m +8.000000 1.790862 6.209138 0.000000 4.000000 0.000000 c +1.790861 0.000000 0.000000 1.790862 0.000000 4.000000 c +0.000000 6.209139 1.790861 8.000000 4.000000 8.000000 c +6.209138 8.000000 8.000000 6.209139 8.000000 4.000000 c +h +f +n +Q +q +-1.000000 -0.000000 -0.000000 1.000000 74.400391 116.799805 cm +1.000000 1.000000 1.000000 scn +3.200000 1.600195 m +3.200000 0.716540 2.483656 0.000195 1.600000 0.000195 c +0.716344 0.000195 0.000000 0.716540 0.000000 1.600195 c +0.000000 2.483851 0.716344 3.200195 1.600000 3.200195 c +2.483656 3.200195 3.200000 2.483851 3.200000 1.600195 c +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 60.197754 92.000000 cm +0.298039 0.266667 0.341176 scn +0.210692 9.427586 m +0.819494 10.927945 2.263791 11.200195 3.002826 11.200195 c +4.263373 11.200195 5.321895 10.698198 6.093330 10.247780 c +6.611842 9.945036 7.198323 9.538356 7.710640 9.183103 c +7.915307 9.041182 8.108138 8.907468 8.280070 8.791867 c +9.648875 7.871538 10.930213 7.200195 12.602841 7.200195 c +14.275467 7.200195 15.556796 7.871536 16.925592 8.791864 c +17.097525 8.907465 17.290358 9.041180 17.495024 9.183101 c +18.007338 9.538354 18.593815 9.945034 19.112326 10.247778 c +19.883757 10.698197 20.942278 11.200195 22.202826 11.200195 c +22.941864 11.200195 24.386152 10.927944 24.994959 9.427594 c +25.463491 8.272934 25.033445 7.210504 24.829237 6.777150 c +24.329792 5.717262 23.346052 4.650410 22.280838 3.759346 c +20.099072 1.934270 16.546749 0.000196 12.602841 0.000196 c +8.658937 0.000196 5.106606 1.934269 2.924833 3.759343 c +1.859617 4.650406 0.875873 5.717257 0.376423 6.777142 c +0.172215 7.210493 -0.257837 8.272923 0.210692 9.427586 c +h +f* +n +Q +q +-1.000000 -0.000000 -0.000000 1.000000 84.000244 97.600098 cm +1.000000 1.000000 1.000000 scn +4.000000 2.000000 m +4.000000 0.895431 3.104569 0.000000 2.000000 0.000000 c +0.895430 0.000000 0.000000 0.895431 0.000000 2.000000 c +0.000000 3.104569 0.895430 4.000000 2.000000 4.000000 c +3.104569 4.000000 4.000000 3.104569 4.000000 2.000000 c +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 60.800049 88.799805 cm +0.839216 0.941176 1.000000 scn +2.186750 7.132430 m +2.481733 7.187536 2.767971 7.200195 3.002226 7.200195 c +22.202225 7.200195 l +22.436480 7.200195 22.722717 7.187535 23.017700 7.132430 c +23.223743 7.093940 23.849474 6.967839 24.399368 6.459650 c +24.724783 6.158916 25.043146 5.702694 25.159731 5.094691 c +25.273575 4.500982 25.151371 3.990361 25.002514 3.640070 c +24.743748 3.031134 24.310673 2.673494 24.152058 2.547267 c +23.757078 2.232945 23.281164 2.001373 22.906059 1.838783 c +22.485668 1.656564 21.994732 1.478374 21.458691 1.310222 c +19.338472 0.645127 16.070730 0.000196 12.602242 0.000196 c +9.133754 0.000196 5.866003 0.645127 3.745779 1.310222 c +3.209736 1.478374 2.718797 1.656562 2.298405 1.838781 c +1.923299 2.001371 1.447385 2.232941 1.052409 2.547260 c +0.893792 2.673485 0.460720 3.031119 0.201949 3.640047 c +0.053092 3.990332 -0.069120 4.500952 0.044717 5.094664 c +0.161295 5.702673 0.479656 6.158901 0.805074 6.459641 c +1.354972 6.967839 1.980710 7.093940 2.186750 7.132430 c +h +f* +n +Q + +endstream +endobj + +5 0 obj + 10051 +endobj + +6 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 200.000000 200.000000 ] + /Resources 3 0 R + /Contents 4 0 R + /Parent 7 0 R + >> +endobj + +7 0 obj + << /Kids [ 6 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +8 0 obj + << /Pages 7 0 R + /Type /Catalog + >> +endobj + +xref +0 9 +0000000000 65535 f +0000000010 00000 n +0000000532 00000 n +0000000554 00000 n +0000001236 00000 n +0000011343 00000 n +0000011367 00000 n +0000011542 00000 n +0000011616 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 8 0 R + /Size 9 +>> +startxref +11675 +%%EOF \ No newline at end of file diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/bfmbfm.imageset/Contents.json b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/bfm.imageset/Contents.json similarity index 100% rename from AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/bfmbfm.imageset/Contents.json rename to AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/bfm.imageset/Contents.json diff --git a/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/bfmbfm.imageset/bfm tv 1.png b/AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/bfm.imageset/bfm tv 1.png similarity index 100% rename from AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/bfmbfm.imageset/bfm tv 1.png rename to AlloVoisinsSwiftUI/Resources/Assets.xcassets/Images/bfm.imageset/bfm tv 1.png diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/AlloVoisinReputationScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/AlloVoisinReputationScreen.swift index 00655e5..fa4750b 100644 --- a/AlloVoisinsSwiftUI/Screens/Resiliation/AlloVoisinReputationScreen.swift +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/AlloVoisinReputationScreen.swift @@ -8,6 +8,8 @@ import SwiftUI struct AlloVoisinReputationScreen: View { + @ObservedObject var viewModel: PromotionalScreenViewModel + @State private var navigateToNext = false var body: some View { VStack(spacing: 16) { @@ -74,7 +76,7 @@ struct AlloVoisinReputationScreen: View { .background(Color.white) .cornerRadius(8) SQButton("Conserver mon abonnement", color: .sqNeutral(100), textColor: .white) { - + navigateToNext = true } } .padding(16) @@ -82,7 +84,14 @@ struct AlloVoisinReputationScreen: View { .cornerRadius(8) SQButton("J’ai compris, mais je souhaite résilier", color: .white, textSize: 13) { - + navigateToNext = true + } + } + .navigationDestination(isPresented: $navigateToNext) { + if let screen = viewModel.nextPromotionalScreen { + viewModel.getPromotionalScreenNew(for: screen) + } else { + ResiliationConfirmationScreen() } } .sqNavigationBar(title: "Ne partez pas !") @@ -90,5 +99,5 @@ struct AlloVoisinReputationScreen: View { } #Preview { - AlloVoisinReputationScreen() + AlloVoisinReputationScreen(viewModel: PromotionalScreenViewModel()) } diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/AskIfWillComeBackScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/AskIfWillComeBackScreen.swift index d48ea48..61b8ad2 100644 --- a/AlloVoisinsSwiftUI/Screens/Resiliation/AskIfWillComeBackScreen.swift +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/AskIfWillComeBackScreen.swift @@ -8,7 +8,10 @@ import SwiftUI struct AskIfWillComeBackScreen: View { + @ObservedObject var viewModel: ResiliationViewModel + @State private var navigateToNext = false @State var selectedIndex: Int? = nil + var body: some View { VStack { SQRadio(title: "Pensez-vous redevenir abonné Premier ?", orientation: .horizontal, options: ["1\nNon,Jamais", "2", "3", "4", "5\nOui, sûrement"], selectedIndex: $selectedIndex) @@ -17,5 +20,5 @@ struct AskIfWillComeBackScreen: View { } #Preview { - AskIfWillComeBackScreen() + AskIfWillComeBackScreen(viewModel: ResiliationViewModel(resiliationType: .apProWithTrial)) } diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/ContinueAsParticularScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/ContinueAsParticularScreen.swift index 7bce276..18768d9 100644 --- a/AlloVoisinsSwiftUI/Screens/Resiliation/ContinueAsParticularScreen.swift +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/ContinueAsParticularScreen.swift @@ -8,6 +8,9 @@ import SwiftUI struct ContinueAsParticularScreen: View { + @ObservedObject var viewModel: PromotionalScreenViewModel + @State private var navigateToNext = false + var body: some View { VStack(spacing: 32) { SQText("Souhaitez-vous poursuivre en tant que particulier ?", size: 18, font: .bold) @@ -16,18 +19,25 @@ struct ContinueAsParticularScreen: View { .multilineTextAlignment(.center) VStack { SQButton("Changer de statut", color: .sqNeutral(100), textColor: .white) { - + navigateToNext = true } SQButton("J’ai compris, mais je souhaite résilier", color: .white) { - + navigateToNext = true } } } + .navigationDestination(isPresented: $navigateToNext) { + if let screen = viewModel.nextPromotionalScreen { + viewModel.getPromotionalScreenNew(for: screen) + } else { + ResiliationConfirmationScreen() + } + } .sqNavigationBar(title: "Ne partez pas !") .padding(16) } } #Preview { - ContinueAsParticularScreen() + ContinueAsParticularScreen(viewModel: PromotionalScreenViewModel()) } diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/GenericResiliationScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/GenericResiliationScreen.swift new file mode 100644 index 0000000..de7b9e8 --- /dev/null +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/GenericResiliationScreen.swift @@ -0,0 +1,163 @@ +// +// GenericResiliationScreen.swift +// AlloVoisinsSwiftUI +// +// Created by Victor on 14/10/2024. +// + +import SwiftUI + +protocol ResiliationContentView: View { + var screenType: ResiliationScreenType { get } +} + +enum ResiliationScreenType { + case alloVoisinReputation + case askIfWillComeBack + case continueAsParticular + case getMoreRatings + case moreTime + case onlyProRequests + case personalizedSupport + case profileCompletion + case resizePerimeter + case softwarePresentation + case statusChange + case webinaire + + var title: String { + switch self { + case .statusChange: return "Changer de statut" + default: return "Ne partez pas !" + } + } + + var mainColor: Color { + switch self { + case .alloVoisinReputation, .moreTime: return Color.sqBlue(10) + case .continueAsParticular, .resizePerimeter, .statusChange: return Color.sqOrange(10) + case .getMoreRatings: return Color.sqGold(10) + case .onlyProRequests, .personalizedSupport, .webinaire: return Color.sqGrape(10) + case .profileCompletion: return Color.sqNeutral(10) + case .softwarePresentation: return Color.white + default: return Color.white + } + } + + var buttonColor: Color { + switch self { + case .alloVoisinReputation, .continueAsParticular, .profileCompletion, .softwarePresentation: + return Color.sqNeutral(100) + case .getMoreRatings: return Color.sqGold(50) + case .moreTime: return Color.sqBlue(50) + case .onlyProRequests, .personalizedSupport, .webinaire: return Color.sqGrape(80) + case .resizePerimeter, .statusChange: return Color.sqOrange(50) + default: return Color.sqNeutral(100) + } + } + + var buttonTitle: String { + switch self { + case .alloVoisinReputation: return "Conserver mon abonnement" + case .continueAsParticular: return "Changer de statut" + case .getMoreRatings: return "Recueillir des avis" + case .moreTime: return "Je prolonge ma période d'essai" + case .onlyProRequests: return "Voir les demandes" + case .personalizedSupport: return "Je souhaite être appelé" + case .profileCompletion: return "Je complète mon profil" + case .resizePerimeter: return "Modifier mon périmètre" + case .softwarePresentation: return "Découvrir le logiciel" + case .statusChange: return "Résilier et changer de statut" + case .webinaire: return "Je m'inscris" + default: return "Continuer" + } + } + + var cancelButtonTitle: String { + switch self { + case .moreTime, .personalizedSupport, .webinaire: + return "Non merci, je souhaite résilier" + default: + return "J'ai compris, mais je souhaite résilier" + } + } +} + +struct GenericResiliationScreen: View { + @ObservedObject var viewModel: PromotionalScreenViewModel + @State private var navigateToNext = false + let content: Content + let buttonAction: () -> Void + + var body: some View { + VStack(spacing: 16) { + VStack(spacing: 32) { + content + .padding(16) + .background(content.screenType.mainColor) + .cornerRadius(8) + + SQButton(content.screenType.buttonTitle, color: content.screenType.buttonColor, textColor: .white, action: buttonAction) + } + + if content.screenType != .statusChange { + SQButton(content.screenType.cancelButtonTitle, color: .white, textSize: 13) { + navigateToNext = true + } + } + } + .navigationDestination(isPresented: $navigateToNext) { + if let screen = viewModel.nextPromotionalScreen { + viewModel.getPromotionalScreenNew(for: screen) + } else { + ResiliationConfirmationScreen() + } + } + .sqNavigationBar(title: content.screenType.title) + .padding() + } +} + +//#Preview { +// GenericResiliationScreen(viewModel: ResiliationViewModel(resiliationType: .apProWithTrial), content: ResiliationContentView) { +// +// } +//} +struct AlloVoisinReputationScreens: View { + @ObservedObject var viewModel: PromotionalScreenViewModel + + var body: some View { + GenericResiliationScreen( + viewModel: viewModel, + content: AlloVoisinReputationContent(), + buttonAction: { + // Handle button action + } + ) + } +} + +#Preview { + AlloVoisinReputationScreens(viewModel: PromotionalScreenViewModel()) +} + +struct AlloVoisinReputationContent: ResiliationContentView { + let screenType: ResiliationScreenType = .alloVoisinReputation + + var body: some View { + VStack(spacing: 32) { + VStack { + SQText("Le saviez-vous ?", size: 20, font: .bold) + SQText("AlloVoisins en France, c'est :", size: 20, font: .bold) + } + VStack { + SQText("4,5 millions", size: 32, font: .bold) + SQText("de membres, partout en France") + } + .padding(16) + .background(Color.white) + .cornerRadius(8) + // ... Rest of the content + } + } +} diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/GetMoreRatingsScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/GetMoreRatingsScreen.swift index 48fe734..cd214b9 100644 --- a/AlloVoisinsSwiftUI/Screens/Resiliation/GetMoreRatingsScreen.swift +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/GetMoreRatingsScreen.swift @@ -8,6 +8,8 @@ import SwiftUI struct GetMoreRatingsScreen: View { + @ObservedObject var viewModel: PromotionalScreenViewModel + @State private var navigateToNext = false var body: some View { VStack(spacing: 16) { @@ -29,7 +31,7 @@ struct GetMoreRatingsScreen: View { .multilineTextAlignment(.center) } SQButton("Recueillir des avis", color: .sqGold(50), textColor: .white) { - + navigateToNext = true } } .padding(16) @@ -37,7 +39,14 @@ struct GetMoreRatingsScreen: View { .cornerRadius(8) SQButton("J’ai compris, mais je souhaite résilier", color: .white, textSize: 13) { - + navigateToNext = true + } + } + .navigationDestination(isPresented: $navigateToNext) { + if let screen = viewModel.nextPromotionalScreen { + viewModel.getPromotionalScreenNew(for: screen) + } else { + ResiliationConfirmationScreen() } } .sqNavigationBar(title: "Ne partez pas !") @@ -46,5 +55,5 @@ struct GetMoreRatingsScreen: View { } #Preview { - GetMoreRatingsScreen() + GetMoreRatingsScreen(viewModel: PromotionalScreenViewModel()) } diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/MoreTimeScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/MoreTimeScreen.swift index 70cc79b..e8b05e8 100644 --- a/AlloVoisinsSwiftUI/Screens/Resiliation/MoreTimeScreen.swift +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/MoreTimeScreen.swift @@ -8,7 +8,9 @@ import SwiftUI struct MoreTimeScreen: View { - + @ObservedObject var viewModel: PromotionalScreenViewModel + @State private var navigateToNext = false + var body: some View { VStack(spacing: 16) { VStack(spacing: 32) { @@ -21,7 +23,7 @@ struct MoreTimeScreen: View { .multilineTextAlignment(.center) } SQButton("Je prolonge ma période d’essai", color: .sqBlue(50), textColor: .white) { - + navigateToNext = true } } .padding(16) @@ -29,7 +31,14 @@ struct MoreTimeScreen: View { .cornerRadius(8) SQButton("Non merci, je souhaite résilier", color: .white, textSize: 13) { - + navigateToNext = true + } + } + .navigationDestination(isPresented: $navigateToNext) { + if let screen = viewModel.nextPromotionalScreen { + viewModel.getPromotionalScreenNew(for: screen) + } else { + ResiliationConfirmationScreen() } } .sqNavigationBar(title: "Ne partez pas !") @@ -38,5 +47,5 @@ struct MoreTimeScreen: View { } #Preview { - MoreTimeScreen() + MoreTimeScreen(viewModel: PromotionalScreenViewModel()) } diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/OnlyProRequestsScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/OnlyProRequestsScreen.swift index 38dba42..2155070 100644 --- a/AlloVoisinsSwiftUI/Screens/Resiliation/OnlyProRequestsScreen.swift +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/OnlyProRequestsScreen.swift @@ -8,7 +8,9 @@ import SwiftUI struct OnlyProRequestsScreen: View { - + @ObservedObject var viewModel: PromotionalScreenViewModel + @State private var navigateToNext = false + var body: some View { VStack(spacing: 16) { VStack(spacing: 32) { @@ -29,7 +31,7 @@ struct OnlyProRequestsScreen: View { .multilineTextAlignment(.center) } SQButton("Voir les demandes", color: .sqGrape(80), textColor: .white) { - + navigateToNext = true } } .padding(16) @@ -37,7 +39,14 @@ struct OnlyProRequestsScreen: View { .cornerRadius(8) SQButton("J’ai compris, mais je souhaite résilier", color: .white, textSize: 13) { - + navigateToNext = true + } + } + .navigationDestination(isPresented: $navigateToNext) { + if let screen = viewModel.nextPromotionalScreen { + viewModel.getPromotionalScreenNew(for: screen) + } else { + ResiliationConfirmationScreen() } } .sqNavigationBar(title: "Ne partez pas !") @@ -46,5 +55,5 @@ struct OnlyProRequestsScreen: View { } #Preview { - OnlyProRequestsScreen() + OnlyProRequestsScreen(viewModel: PromotionalScreenViewModel()) } diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/PersonalizedSupportScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/PersonalizedSupportScreen.swift index 07aec94..5745bea 100644 --- a/AlloVoisinsSwiftUI/Screens/Resiliation/PersonalizedSupportScreen.swift +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/PersonalizedSupportScreen.swift @@ -8,6 +8,8 @@ import SwiftUI struct PersonalizedSupportScreen: View { + @ObservedObject var viewModel: PromotionalScreenViewModel + @State private var navigateToNext = false var body: some View { VStack(spacing: 16) { @@ -24,7 +26,7 @@ struct PersonalizedSupportScreen: View { .multilineTextAlignment(.center) } SQButton("Je souhaite être appelé", color: .sqGrape(80), textColor: .white) { - + navigateToNext = true } } .padding(16) @@ -32,7 +34,14 @@ struct PersonalizedSupportScreen: View { .cornerRadius(8) SQButton("Non merci, je souhaite résilier", color: .white, textSize: 13) { - + navigateToNext = true + } + } + .navigationDestination(isPresented: $navigateToNext) { + if let screen = viewModel.nextPromotionalScreen { + viewModel.getPromotionalScreenNew(for: screen) + } else { + ResiliationConfirmationScreen() } } .sqNavigationBar(title: "Ne partez pas !") @@ -41,5 +50,5 @@ struct PersonalizedSupportScreen: View { } #Preview { - PersonalizedSupportScreen() + PersonalizedSupportScreen(viewModel: PromotionalScreenViewModel()) } diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/ProfileCompletionScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/ProfileCompletionScreen.swift index d6d3b64..d3ce202 100644 --- a/AlloVoisinsSwiftUI/Screens/Resiliation/ProfileCompletionScreen.swift +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/ProfileCompletionScreen.swift @@ -8,6 +8,9 @@ import SwiftUI struct ProfileCompletionScreen: View { + @ObservedObject var viewModel: PromotionalScreenViewModel + @State private var navigateToNext = false + var body: some View { VStack(spacing: 16) { VStack(spacing: 32) { @@ -52,7 +55,7 @@ struct ProfileCompletionScreen: View { SQText("des demandeurs comparent systématiquement les profils des offreurs pour faire leur choix.") .multilineTextAlignment(.center) SQButton("Je complète mon profil", color: .sqNeutral(100), textColor: .white) { - + navigateToNext = true } } .padding(16) @@ -60,7 +63,14 @@ struct ProfileCompletionScreen: View { .cornerRadius(8) SQButton("J’ai compris, mais je souhaite résilier", color: .white, textSize: 13) { - + navigateToNext = true + } + } + .navigationDestination(isPresented: $navigateToNext) { + if let screen = viewModel.nextPromotionalScreen { + viewModel.getPromotionalScreenNew(for: screen) + } else { + ResiliationConfirmationScreen() } } .sqNavigationBar(title: "Ne partez pas !") @@ -69,5 +79,5 @@ struct ProfileCompletionScreen: View { } #Preview { - ProfileCompletionScreen() + ProfileCompletionScreen(viewModel: PromotionalScreenViewModel()) } diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/ResiliationCheckStepsScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/ResiliationCheckStepsScreen.swift index db0a70d..c615e73 100644 --- a/AlloVoisinsSwiftUI/Screens/Resiliation/ResiliationCheckStepsScreen.swift +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/ResiliationCheckStepsScreen.swift @@ -8,9 +8,9 @@ import SwiftUI struct ResiliationCheckStepsScreen: View { - @State var nextStep: Bool = false @StateObject var viewModel: ResiliationViewModel @State private var selectedSteps: Set = [] + @State private var navigateToReasonScreen = false var allStepsSelected: Bool { selectedSteps.count == viewModel.resiliationCheckSteps.count @@ -46,7 +46,7 @@ struct ResiliationCheckStepsScreen: View { } SQButton("Continuer", color: .sqNeutral(100), textColor: .white) { - nextStep.toggle() + navigateToReasonScreen = true } .disabled(!allStepsSelected) } @@ -54,7 +54,7 @@ struct ResiliationCheckStepsScreen: View { } .padding() } - .navigationDestination(isPresented: $nextStep) { + .navigationDestination(isPresented: $navigateToReasonScreen) { ResiliationReasonScreen(viewModel: viewModel) } .sqNavigationBar(title: "Demander la résiliation") diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/ResiliationConfirmationScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/ResiliationConfirmationScreen.swift new file mode 100644 index 0000000..6cff302 --- /dev/null +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/ResiliationConfirmationScreen.swift @@ -0,0 +1,33 @@ +// +// ResiliationConfirmationScreen.swift +// AlloVoisinsSwiftUI +// +// Created by Victor on 15/10/2024. +// + +import SwiftUI + +struct ResiliationConfirmationScreen: View { + @State var navigateToNext: Bool = false + + var body: some View { + VStack(spacing: 8) { + Image("allomoji_sad") + .resizable() + .scaledToFit() + .frame(height: 200) + SQText("Votre résiliation a été prise en compte. Elle sera effective le JJ/MM/AAAA.", size: 18, font: .bold) + SQButton("Terminer", color: .sqNeutral(100), textColor: .white) { + + } + .padding() + Spacer() + } + .padding() + .sqNavigationBar(title: "Demander la résiliation") + } +} + +#Preview { + ResiliationConfirmationScreen() +} diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/ResiliationNavigationScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/ResiliationNavigationScreen.swift index b0b5063..eb18f71 100644 --- a/AlloVoisinsSwiftUI/Screens/Resiliation/ResiliationNavigationScreen.swift +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/ResiliationNavigationScreen.swift @@ -8,16 +8,23 @@ import SwiftUI struct ResiliationNavigationScreen: View { - @StateObject private var viewModel: ResiliationViewModel - - init(resiliationType: ResiliationType) { - self._viewModel = StateObject(wrappedValue: ResiliationViewModel(resiliationType: resiliationType)) - } + @StateObject var viewModel: ResiliationViewModel var body: some View { NavigationStack { ResiliationCheckStepsScreen(viewModel: viewModel) - .navigationBarTitle("Résiliation", displayMode: .inline) + } + } +} + +struct PromotionalScreenWrapper: View { + @ObservedObject var viewModel: ResiliationViewModel + + var body: some View { + if let screen = viewModel.currentPromotionalScreen { + viewModel.getPromotionalScreenNew(for: screen) + } else { + ResiliationConfirmationScreen() } } } diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/ResiliationReasonScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/ResiliationReasonScreen.swift index dcd50da..8909122 100644 --- a/AlloVoisinsSwiftUI/Screens/Resiliation/ResiliationReasonScreen.swift +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/ResiliationReasonScreen.swift @@ -12,6 +12,7 @@ struct ResiliationReasonScreen: View { @ObservedObject var viewModel: ResiliationViewModel @State private var selectedIndex: Int? = nil @State private var resiliationOtherMotif: String = "" + @State private var navigateToPromotionalScreen = false var body: some View { ScrollView { @@ -28,10 +29,10 @@ struct ResiliationReasonScreen: View { dismiss() } SQButton("Continuer", color: .sqNeutral(100), textColor: .white) { - // TODO: Aller au prochain promotional screen if let index = selectedIndex { let selectedReason = viewModel.resiliationReasons[index] viewModel.setSelectedReason(selectedReason) + navigateToPromotionalScreen = true } } .disabled(selectedIndex == nil) @@ -41,9 +42,16 @@ struct ResiliationReasonScreen: View { } .padding() .sqNavigationBar(title: "Demander la résiliation") + .navigationDestination(isPresented: $navigateToPromotionalScreen) { + if viewModel.hasNextPromotionalScreen { + viewModel.getPromotionalScreenNew(for: viewModel.currentPromotionalScreen!) + } else { + ResiliationConfirmationScreen() + } + } } } - #Preview { - ResiliationReasonScreen(viewModel: ResiliationViewModel(resiliationType: .apProWithTrial)) - } +#Preview { + ResiliationReasonScreen(viewModel: ResiliationViewModel(resiliationType: .apProWithTrial)) +} diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/ResizePerimeterScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/ResizePerimeterScreen.swift index 7e2f464..6addfa1 100644 --- a/AlloVoisinsSwiftUI/Screens/Resiliation/ResizePerimeterScreen.swift +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/ResizePerimeterScreen.swift @@ -8,6 +8,9 @@ import SwiftUI struct ResizePerimeterScreen: View { + @ObservedObject var viewModel: PromotionalScreenViewModel + @State private var navigateToNext = false + var body: some View { VStack(spacing: 16) { VStack(spacing: 32) { @@ -23,7 +26,7 @@ struct ResizePerimeterScreen: View { .multilineTextAlignment(.center) } SQButton("Modifier mon périmètre", color: .sqOrange(50), textColor: .white) { - + navigateToNext = true } } .padding(16) @@ -31,7 +34,14 @@ struct ResizePerimeterScreen: View { .cornerRadius(8) SQButton("J’ai compris, mais je souhaite résilier", color: .white, textSize: 13) { - + navigateToNext = true + } + } + .navigationDestination(isPresented: $navigateToNext) { + if let screen = viewModel.nextPromotionalScreen { + viewModel.getPromotionalScreenNew(for: screen) + } else { + ResiliationConfirmationScreen() } } .sqNavigationBar(title: "Ne partez pas !") @@ -39,5 +49,5 @@ struct ResizePerimeterScreen: View { } #Preview { - ResizePerimeterScreen() + ResizePerimeterScreen(viewModel: PromotionalScreenViewModel()) } diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/SoftwarePresentationScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/SoftwarePresentationScreen.swift index e4998f5..3e07d6f 100644 --- a/AlloVoisinsSwiftUI/Screens/Resiliation/SoftwarePresentationScreen.swift +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/SoftwarePresentationScreen.swift @@ -8,6 +8,9 @@ import SwiftUI struct SoftwarePresentationScreen: View { + @ObservedObject var viewModel: PromotionalScreenViewModel + @State private var navigateToNext = false + var body: some View { VStack(spacing: 32) { SQText("Saviez-vous que votre abonnement peut vous offrir bien plus que de nouveaux clients ?", size: 18, font: .bold) @@ -37,18 +40,25 @@ struct SoftwarePresentationScreen: View { } VStack { SQButton("Découvrir le logiciel", color: .sqNeutral(100), textColor: .white) { - + navigateToNext = true } SQButton("J’ai compris, mais je souhaite résilier", color: .white, textSize: 13) { - + navigateToNext = true } } } + .navigationDestination(isPresented: $navigateToNext) { + if let screen = viewModel.nextPromotionalScreen { + viewModel.getPromotionalScreenNew(for: screen) + } else { + ResiliationConfirmationScreen() + } + } .sqNavigationBar(title: "Ne partez pas !") .padding() } } #Preview { - SoftwarePresentationScreen() + SoftwarePresentationScreen(viewModel: PromotionalScreenViewModel()) } diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/StatusChangeScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/StatusChangeScreen.swift index 4c6beac..4015441 100644 --- a/AlloVoisinsSwiftUI/Screens/Resiliation/StatusChangeScreen.swift +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/StatusChangeScreen.swift @@ -8,6 +8,8 @@ import SwiftUI struct StatusChangeScreen: View { + @ObservedObject var viewModel: PromotionalScreenViewModel + @State private var navigateToNext = false var body: some View { VStack { @@ -19,17 +21,26 @@ struct StatusChangeScreen: View { SQText("Si vous le souhaitez, vous pourrez vous abonner à l’abonnement Premier en tant que particulier.") .multilineTextAlignment(.center) } - SQButton("Résilier et changer de statut", color: .sqOrange(50), textColor: .white) {} + SQButton("Résilier et changer de statut", color: .sqOrange(50), textColor: .white) { + navigateToNext = true + } } .padding(16) .background(Color.sqOrange(10)) .cornerRadius(8) } + .navigationDestination(isPresented: $navigateToNext) { + if let screen = viewModel.nextPromotionalScreen { + viewModel.getPromotionalScreenNew(for: screen) + } else { + ResiliationConfirmationScreen() + } + } .sqNavigationBar(title: "Changer de statut") .padding() } } #Preview { - StatusChangeScreen() + StatusChangeScreen(viewModel: PromotionalScreenViewModel()) } diff --git a/AlloVoisinsSwiftUI/Screens/Resiliation/WebinaireScreen.swift b/AlloVoisinsSwiftUI/Screens/Resiliation/WebinaireScreen.swift index c35363b..8173e3c 100644 --- a/AlloVoisinsSwiftUI/Screens/Resiliation/WebinaireScreen.swift +++ b/AlloVoisinsSwiftUI/Screens/Resiliation/WebinaireScreen.swift @@ -8,6 +8,8 @@ import SwiftUI struct WebinaireScreen: View { + @ObservedObject var viewModel: PromotionalScreenViewModel + @State private var navigateToNext = false var body: some View { VStack(spacing: 16) { @@ -24,16 +26,37 @@ struct WebinaireScreen: View { .multilineTextAlignment(.center) SQText("“Augmenter mon chiffre d'affaires.“", size: 18, font: .bold) } - SQButton("Je m’inscris", color: .sqGrape(80), textColor: .white) { - + NavigationLink { + if let screen = viewModel.nextPromotionalScreen { + viewModel.getPromotionalScreenNew(for: screen) + } else { + ResiliationConfirmationScreen() + } + } label: { + SQButton("Je m’inscris", color: .sqGrape(80), textColor: .white) { + } } } .padding(16) .background(Color.sqGrape(10)) .cornerRadius(8) - SQButton("Non merci, je souhaite résilier", color: .white, textSize: 13) { - + NavigationLink { + if let screen = viewModel.nextPromotionalScreen { + viewModel.getPromotionalScreenNew(for: screen) + } else { + ResiliationConfirmationScreen() + } + } label: { + SQButton("Non merci, je souhaite résilier", color: .white, textSize: 13) { + } + } + } + .navigationDestination(isPresented: $navigateToNext) { + if let screen = viewModel.nextPromotionalScreen { + viewModel.getPromotionalScreenNew(for: screen) + } else { + ResiliationConfirmationScreen() } } .sqNavigationBar(title: "Ne partez pas !") @@ -41,5 +64,5 @@ struct WebinaireScreen: View { } #Preview { - WebinaireScreen() + WebinaireScreen(viewModel: PromotionalScreenViewModel()) } diff --git a/AlloVoisinsSwiftUI/ViewModels/PromotionalScreenViewModel.swift b/AlloVoisinsSwiftUI/ViewModels/PromotionalScreenViewModel.swift new file mode 100644 index 0000000..27d1069 --- /dev/null +++ b/AlloVoisinsSwiftUI/ViewModels/PromotionalScreenViewModel.swift @@ -0,0 +1,43 @@ +// +// PromotionalScreenViewModel.swift +// AlloVoisinsSwiftUI +// +// Created by Victor on 15/10/2024. +// + +import Foundation +import SwiftUICore + +class PromotionalScreenViewModel: ObservableObject { + @Published var nextPromotionalScreen: ResiliationPromotionalScreen? + + init(nextPromotionalScreen: ResiliationPromotionalScreen? = nil) { + self.nextPromotionalScreen = nextPromotionalScreen + } + + @ViewBuilder + func getPromotionalScreenNew(for screen: ResiliationPromotionalScreen) -> some View { + switch screen { + case .webinarPresentation: + WebinaireScreen(viewModel: PromotionalScreenViewModel()) + case .profileCompletion: + ProfileCompletionScreen(viewModel: PromotionalScreenViewModel()) + case .editPerimeter: + ResizePerimeterScreen(viewModel: PromotionalScreenViewModel()) + case .onlyProSearches: + OnlyProRequestsScreen(viewModel: PromotionalScreenViewModel()) + case .oneMonthBoosterOffered: + BoosterSubscriptionSelectionScreen() + case .allovoisinsPromotion: + AlloVoisinReputationScreen(viewModel: PromotionalScreenViewModel()) + case .extendMyTrialPeriod: + MoreTimeScreen(viewModel: PromotionalScreenViewModel()) + case .askPartProStatusChangeWithCancellation, .askPartProStatusChange: + StatusChangeScreen(viewModel: PromotionalScreenViewModel()) + case .customerSupportForPro, .customerSupportForPart: + PersonalizedSupportScreen(viewModel: PromotionalScreenViewModel()) + default: + EmptyView() + } + } +} diff --git a/AlloVoisinsSwiftUI/ViewModels/ResiliationViewModel.swift b/AlloVoisinsSwiftUI/ViewModels/ResiliationViewModel.swift index 0c4b2b5..6a52738 100644 --- a/AlloVoisinsSwiftUI/ViewModels/ResiliationViewModel.swift +++ b/AlloVoisinsSwiftUI/ViewModels/ResiliationViewModel.swift @@ -14,13 +14,22 @@ class ResiliationViewModel: ObservableObject { @Published var resiliationReasons: [ResiliationReason] @Published var selectedReason: ResiliationReason? @Published var promotionalScreens: [ResiliationPromotionalScreen] = [] - @Published var currentScreen: Screen = .checkSteps + @Published var currentPromotionalScreenIndex: Int = 0 + @Published var shouldShowConfirmationScreen: Bool = false - enum Screen: Equatable { - case checkSteps - case reason - case promotional(ResiliationPromotionalScreen) - case final + var currentPromotionalScreen: ResiliationPromotionalScreen? { + guard currentPromotionalScreenIndex < promotionalScreens.count else { + return nil + } + return promotionalScreens[currentPromotionalScreenIndex] + } + + var hasNextPromotionalScreen: Bool { + currentPromotionalScreenIndex < promotionalScreens.count + } + + var nextPromotionalScreen: ResiliationPromotionalScreen? { + hasNextPromotionalScreen ? promotionalScreens[currentPromotionalScreenIndex + 1] : nil } init(resiliationType: ResiliationType) { @@ -35,32 +44,19 @@ class ResiliationViewModel: ObservableObject { availablePromotions: getAvailablePromotionalScreens(for: reason), eligibleScreens: getEligiblePromotionalScreens() ) - - if promotionalScreens.isEmpty { - currentScreen = .final - } else { - currentScreen = .promotional(promotionalScreens.removeFirst()) - } - } - - func moveToNextPromotionalScreen() { - if !promotionalScreens.isEmpty { - currentScreen = .promotional(promotionalScreens.removeFirst()) - } else { - currentScreen = .final - } + currentPromotionalScreenIndex = 0 + shouldShowConfirmationScreen = false } + // OK private func selectResiliationPromotions(availablePromotions: [ResiliationPromotionalScreen], eligibleScreens: [ResiliationPromotionalScreen]) -> [ResiliationPromotionalScreen] { - let shuffledArray1 = availablePromotions.shuffled() + let promotionsShuffuled = availablePromotions.shuffled() - let commonPromotions = shuffledArray1.filter { promotion in + let commonPromotions = promotionsShuffuled.filter { promotion in eligibleScreens.contains(promotion) } - let result = commonPromotions.map { $0 } - - return Array(result.prefix(2)) + return Array(commonPromotions.prefix(2)) } private func getAvailablePromotionalScreens(for reason: ResiliationReason) -> [ResiliationPromotionalScreen] { @@ -87,30 +83,30 @@ class ResiliationViewModel: ObservableObject { } private func getEligiblePromotionalScreens() -> [ResiliationPromotionalScreen] { - return [.extendMyTrialPeriod, .profileCompletion, .allovoisinsPromotion] + return [.extendMyTrialPeriod, .profileCompletion, .allovoisinsPromotion, .externalReview, .webinarPresentation, .editPerimeter, .onlyProSearches, .askPartProStatusChange, .customerSupportForPro] } @ViewBuilder func getPromotionalScreenNew(for screen: ResiliationPromotionalScreen) -> some View { switch screen { case .webinarPresentation: - WebinaireScreen() + WebinaireScreen(viewModel: PromotionalScreenViewModel(nextPromotionalScreen: nextPromotionalScreen)) case .profileCompletion: - ProfileCompletionScreen() + ProfileCompletionScreen(viewModel: PromotionalScreenViewModel(nextPromotionalScreen: nextPromotionalScreen)) case .editPerimeter: - ResizePerimeterScreen() + ResizePerimeterScreen(viewModel: PromotionalScreenViewModel(nextPromotionalScreen: nextPromotionalScreen)) case .onlyProSearches: - OnlyProRequestsScreen() + OnlyProRequestsScreen(viewModel: PromotionalScreenViewModel(nextPromotionalScreen: nextPromotionalScreen)) case .oneMonthBoosterOffered: BoosterSubscriptionSelectionScreen() case .allovoisinsPromotion: - AlloVoisinReputationScreen() + AlloVoisinReputationScreen(viewModel: PromotionalScreenViewModel(nextPromotionalScreen: nextPromotionalScreen)) case .extendMyTrialPeriod: - MoreTimeScreen() + MoreTimeScreen(viewModel: PromotionalScreenViewModel(nextPromotionalScreen: nextPromotionalScreen)) case .askPartProStatusChangeWithCancellation, .askPartProStatusChange: - StatusChangeScreen() + StatusChangeScreen(viewModel: PromotionalScreenViewModel(nextPromotionalScreen: nextPromotionalScreen)) case .customerSupportForPro, .customerSupportForPart: - PersonalizedSupportScreen() + PersonalizedSupportScreen(viewModel: PromotionalScreenViewModel(nextPromotionalScreen: nextPromotionalScreen)) default: EmptyView() } diff --git a/AlloVoisinsSwiftUI/Views/Components/SQProgressBar.swift b/AlloVoisinsSwiftUI/Views/Components/SQProgressBar.swift new file mode 100644 index 0000000..85b62c9 --- /dev/null +++ b/AlloVoisinsSwiftUI/Views/Components/SQProgressBar.swift @@ -0,0 +1,37 @@ +// +// SQProgressBar.swift +// AlloVoisinsSwiftUI +// +// Created by Victor on 17/10/2024. +// + +import SwiftUI + +struct SQProgressBar: View { + var progress: Double // Valeur entre 0 et 1 + + var body: some View { + GeometryReader { geometry in + ZStack(alignment: .leading) { + Rectangle() + .foregroundColor(Color.sqNeutral(20)) + .frame(width: geometry.size.width, height: 12) + .cornerRadius(50) + + Rectangle() + .foregroundColor(Color.sqNeutral(60)) // Vous pouvez changer la couleur ici + .frame(width: min(CGFloat(self.progress) * geometry.size.width, geometry.size.width), height: 12) + .cornerRadius(50) + } + } + .frame(height: 12) + .frame(maxWidth: .infinity, alignment: .topLeading) + .background(Color.sqNeutral(20)) + .cornerRadius(12) + } +} + +#Preview { + SQProgressBar(progress: 0.2) + .padding() +}