diff --git a/Core/Core/Assets.xcassets/authorization.imageset/Contents.json b/Core/Core/Assets.xcassets/authorization.imageset/Contents.json new file mode 100644 index 000000000..01c74b62a --- /dev/null +++ b/Core/Core/Assets.xcassets/authorization.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "authorization.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Core/Core/Assets.xcassets/authorization.imageset/authorization.svg b/Core/Core/Assets.xcassets/authorization.imageset/authorization.svg new file mode 100644 index 000000000..60f8fde65 --- /dev/null +++ b/Core/Core/Assets.xcassets/authorization.imageset/authorization.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Core/Core/SwiftGen/Assets.swift b/Core/Core/SwiftGen/Assets.swift index 89329e99c..7a9abb632 100644 --- a/Core/Core/SwiftGen/Assets.swift +++ b/Core/Core/SwiftGen/Assets.swift @@ -101,6 +101,7 @@ public enum CoreAssets { public static let alarm = ImageAsset(name: "alarm") public static let arrowLeft = ImageAsset(name: "arrowLeft") public static let arrowRight16 = ImageAsset(name: "arrowRight16") + public static let authorization = ImageAsset(name: "authorization") public static let calendarSyncIcon = ImageAsset(name: "calendarSyncIcon") public static let certificate = ImageAsset(name: "certificate") public static let certificateBadge = ImageAsset(name: "certificateBadge") diff --git a/Core/Core/SwiftGen/Strings.swift b/Core/Core/SwiftGen/Strings.swift index a4e441d6c..9f0506af2 100644 --- a/Core/Core/SwiftGen/Strings.swift +++ b/Core/Core/SwiftGen/Strings.swift @@ -45,8 +45,12 @@ public enum CoreLocalization { public static let leave = CoreLocalization.tr("Localizable", "ALERT.LEAVE", fallback: "Leave") /// Log out public static let logout = CoreLocalization.tr("Localizable", "ALERT.LOGOUT", fallback: "Log out") + /// Register + public static let register = CoreLocalization.tr("Localizable", "ALERT.REGISTER", fallback: "Register") /// Remove public static let remove = CoreLocalization.tr("Localizable", "ALERT.REMOVE", fallback: "Remove") + /// Sign in + public static let signIn = CoreLocalization.tr("Localizable", "ALERT.SIGN_IN", fallback: "Sign in") } public enum Courseware { /// Back to outline diff --git a/Core/Core/View/Base/AlertView.swift b/Core/Core/View/Base/AlertView.swift index bcda89a1b..577cad5f9 100644 --- a/Core/Core/View/Base/AlertView.swift +++ b/Core/Core/View/Base/AlertView.swift @@ -13,6 +13,7 @@ public enum AlertViewType: Equatable { case action(String, SwiftUI.Image) case logOut case leaveProfile + case authorization case deleteVideo case deepLink case addCalendar @@ -24,7 +25,15 @@ public enum AlertViewType: Equatable { switch self { case .`default`, .calendarAdded: return 16 - case .action, .logOut, .leaveProfile, .deleteVideo, .deepLink, .addCalendar, .removeCalendar, .updateCalendar: + case .action, + .logOut, + .leaveProfile, + .authorization, + .deleteVideo, + .deepLink, + .addCalendar, + .removeCalendar, + .updateCalendar: return 36 } } @@ -38,6 +47,7 @@ public struct AlertView: View { private var positiveAction: String private var onCloseTapped: (() -> Void) = {} private var okTapped: (() -> Void) = {} + private var secondButtonTapped: (() -> Void) = {} private var nextSectionTapped: (() -> Void) = {} private let type: AlertViewType @@ -49,6 +59,7 @@ public struct AlertView: View { positiveAction: String, onCloseTapped: @escaping () -> Void, okTapped: @escaping () -> Void, + secondButtonTapped: @escaping (() -> Void) = {}, type: AlertViewType ) { self.alertTitle = alertTitle @@ -56,6 +67,7 @@ public struct AlertView: View { self.positiveAction = positiveAction self.onCloseTapped = onCloseTapped self.okTapped = okTapped + self.secondButtonTapped = secondButtonTapped self.type = type } @@ -94,7 +106,7 @@ public struct AlertView: View { ZStack(alignment: .topTrailing) { adaptiveStack( spacing: isHorizontal ? 10 : 20, - isHorizontal: (type == .leaveProfile && isHorizontal) + isHorizontal: ((type == .leaveProfile || type == .authorization) && isHorizontal) ) { titles buttons @@ -147,6 +159,27 @@ public struct AlertView: View { .multilineTextAlignment(.center) .padding(.horizontal, 40) .frame(maxWidth: 250) + case .authorization: + VStack(spacing: 8) { + HStack { + Spacer(minLength: 100) + CoreAssets.authorization.swiftUIImage.renderingMode(.template) + .padding(.top, 54) + .foregroundColor(Theme.Colors.textPrimary) + Spacer(minLength: 100) + } + Text(alertTitle) + .font(Theme.Fonts.titleLarge) + .foregroundColor(Theme.Colors.textPrimary) + .fixedSize(horizontal: false, vertical: true) + Text(alertMessage) + .font(Theme.Fonts.bodyMedium) + .foregroundColor(Theme.Colors.textPrimary) + .multilineTextAlignment(.center) + .padding(.bottom, 36) + } + .padding(.horizontal, 40) + .frame(maxWidth: 250) case .leaveProfile, .deleteVideo, .deepLink, .addCalendar, .removeCalendar, .updateCalendar: VStack(spacing: 20) { switch type { @@ -359,6 +392,68 @@ public struct AlertView: View { .frame(maxWidth: 215) } .padding(.trailing, isHorizontal ? 20 : 0) + case .authorization: + adaptiveStack( + spacing: isHorizontal ? 10 : 20, + isHorizontal: !isHorizontal + ) { + Button(action: { + okTapped() + }, label: { + ZStack { + Text(CoreLocalization.Alert.signIn) + .foregroundColor(Theme.Colors.accentColor) + .font(Theme.Fonts.labelLarge) + .frame(maxWidth: .infinity) + .padding(.horizontal, 16) + } + .frame(maxWidth: 215, minHeight: 48) + }) + .background( + Theme.Shapes.buttonShape + .fill(.clear) + ) + .overlay( + Theme.Shapes.buttonShape + .stroke(style: .init( + lineWidth: 1, + lineCap: .round, + lineJoin: .round, + miterLimit: 1 + )) + .foregroundColor(Theme.Colors.accentColor) + ) + .frame(maxWidth: 215) + .padding(.bottom, isHorizontal ? 16 : 0) + Button(action: { + secondButtonTapped() + }, label: { + ZStack { + Text(CoreLocalization.Alert.register) + .foregroundColor(Theme.Colors.primaryButtonTextColor) + .font(Theme.Fonts.labelLarge) + .frame(maxWidth: .infinity) + .padding(.horizontal, 16) + } + .frame(maxWidth: 215, minHeight: 48) + }) + .background( + Theme.Shapes.buttonShape + .fill(Theme.Colors.accentColor) + ) + .overlay( + Theme.Shapes.buttonShape + .stroke(style: .init( + lineWidth: 1, + lineCap: .round, + lineJoin: .round, + miterLimit: 1 + )) + .foregroundColor(.clear) + ) + .frame(maxWidth: 215) + } + .padding(.horizontal, 40) case .deleteVideo: configure( primaryButtonTitle: CoreLocalization.Alert.delete, diff --git a/Core/Core/View/Base/LogistrationBottomView.swift b/Core/Core/View/Base/LogistrationBottomView.swift index 08b6197bf..ec441dc33 100644 --- a/Core/Core/View/Base/LogistrationBottomView.swift +++ b/Core/Core/View/Base/LogistrationBottomView.swift @@ -51,11 +51,6 @@ public struct LogistrationBottomView: View { public var body: some View { VStack(alignment: .leading) { HStack(spacing: 24) { - StyledButton(CoreLocalization.SignIn.registerBtn) { - action(.register) - } - .accessibilityIdentifier("logistration_register_button") - StyledButton( CoreLocalization.SignIn.logInBtn, action: { @@ -68,6 +63,11 @@ public struct LogistrationBottomView: View { .frame(width: 100) .accessibilityIdentifier("logistration_signin_button") + StyledButton(CoreLocalization.SignIn.registerBtn) { + action(.register) + } + .accessibilityIdentifier("logistration_register_button") + if ssoEnabled { StyledButton( CoreLocalization.SignIn.logInWithSsoBtn, diff --git a/Core/Core/en.lproj/Localizable.strings b/Core/Core/en.lproj/Localizable.strings index 3bf847155..27a9aaaab 100644 --- a/Core/Core/en.lproj/Localizable.strings +++ b/Core/Core/en.lproj/Localizable.strings @@ -65,6 +65,8 @@ "ALERT.CANCEL" = "Cancel"; "ALERT.LOGOUT" = "Log out"; "ALERT.LEAVE" = "Leave"; +"ALERT.SIGN_IN" = "Sign in"; +"ALERT.REGISTER" = "Register"; "ALERT.KEEP_EDITING" = "Keep editing"; "ALERT.DELETE" = "Delete"; "ALERT.ADD" = "Add"; diff --git a/Discovery/Discovery/Data/Model/Data_CourseDetailsResponse.swift b/Discovery/Discovery/Data/Model/Data_CourseDetailsResponse.swift index 9b9e2522b..ef8550be0 100644 --- a/Discovery/Discovery/Data/Model/Data_CourseDetailsResponse.swift +++ b/Discovery/Discovery/Data/Model/Data_CourseDetailsResponse.swift @@ -16,7 +16,7 @@ public extension DataLayer { public let end: String? public let enrollmentStart: String? public let enrollmentEnd: String? - public let isEnrolled: Bool + public let isEnrolled: Bool? public let id: String public let media: Media public let name: String @@ -72,7 +72,7 @@ public extension DataLayer.CourseDetailsResponse { courseEnd: end != nil ? Date(iso8601: end!) : nil, enrollmentStart: enrollmentStart != nil ? Date(iso8601: enrollmentStart!) : nil, enrollmentEnd: enrollmentEnd != nil ? Date(iso8601: enrollmentEnd!) : nil, - isEnrolled: isEnrolled, + isEnrolled: isEnrolled ?? false, overviewHTML: overview, courseBannerURL: imageURL, courseVideoURL: media.courseVideo?.url, diff --git a/Discovery/Discovery/Presentation/NativeDiscovery/CourseDetailsView.swift b/Discovery/Discovery/Presentation/NativeDiscovery/CourseDetailsView.swift index 392edd01f..8cd1c32f0 100644 --- a/Discovery/Discovery/Presentation/NativeDiscovery/CourseDetailsView.swift +++ b/Discovery/Discovery/Presentation/NativeDiscovery/CourseDetailsView.swift @@ -241,11 +241,38 @@ private struct CourseStateView: View { if viewModel.connectivity.isInternetAvaliable { StyledButton(DiscoveryLocalization.Details.enrollNow, action: { if !viewModel.userloggedIn { - viewModel.router.showRegisterScreen( - sourceScreen: .courseDetail( - courseDetails.courseID, - courseDetails.courseTitle) - ) + viewModel.router.presentView( + transitionStyle: .crossDissolve, + animated: true + ) { + AlertView( + alertTitle: DiscoveryLocalization.Alert.authorization, + alertMessage: DiscoveryLocalization.Alert.pleaseEnterTheSystem, + positiveAction: CoreLocalization.Alert.signIn, + onCloseTapped: { + self.viewModel.router.dismiss(animated: true) + }, + okTapped: { + self.viewModel.router.dismiss(animated: false) + viewModel.router.showLoginScreen( + sourceScreen: .courseDetail( + courseDetails.courseID, + viewModel.courseDetails?.courseTitle ?? "" + ) + ) + }, + secondButtonTapped: { + self.viewModel.router.dismiss(animated: false) + viewModel.router.showRegisterScreen( + sourceScreen: .courseDetail( + courseDetails.courseID, + courseDetails.courseTitle) + ) + + }, + type: .authorization + ) + } } else { Task { await viewModel.enrollToCourse(id: courseDetails.courseID) diff --git a/Discovery/Discovery/SwiftGen/Strings.swift b/Discovery/Discovery/SwiftGen/Strings.swift index 987aec582..2e8c02fc5 100644 --- a/Discovery/Discovery/SwiftGen/Strings.swift +++ b/Discovery/Discovery/SwiftGen/Strings.swift @@ -42,10 +42,14 @@ public enum DiscoveryLocalization { /// Why do I need to update? public static let updateWhyNeed = DiscoveryLocalization.tr("Localizable", "UPDATE_WHY_NEED", fallback: "Why do I need to update?") public enum Alert { + /// Authorization + public static let authorization = DiscoveryLocalization.tr("Localizable", "ALERT.AUTHORIZATION", fallback: "Authorization") /// You are now leaving the app and opening a browser public static let leavingAppMessage = DiscoveryLocalization.tr("Localizable", "ALERT.LEAVING_APP_MESSAGE", fallback: "You are now leaving the app and opening a browser") /// Leaving the app public static let leavingAppTitle = DiscoveryLocalization.tr("Localizable", "ALERT.LEAVING_APP_TITLE", fallback: "Leaving the app") + /// Please enter the system to continue with course enrollment. + public static let pleaseEnterTheSystem = DiscoveryLocalization.tr("Localizable", "ALERT.PLEASE_ENTER_THE_SYSTEM", fallback: "Please enter the system to continue with course enrollment.") } public enum Details { /// Enroll now diff --git a/Discovery/Discovery/en.lproj/Localizable.strings b/Discovery/Discovery/en.lproj/Localizable.strings index 8792ba146..bb9877504 100644 --- a/Discovery/Discovery/en.lproj/Localizable.strings +++ b/Discovery/Discovery/en.lproj/Localizable.strings @@ -35,3 +35,6 @@ "DETAILS.ENROLL_NOW" = "Enroll now"; "DETAILS.ENROLLMENT_DATE_IS_OVER" = "You cannot enroll in this course because the enrollment date is over."; "DETAILS.ENROLLMENT_NO_INTERNET" = "To enroll in this course, please make sure you are connected to the internet."; + +"ALERT.AUTHORIZATION" = "Authorization"; +"ALERT.PLEASE_ENTER_THE_SYSTEM" = "Please enter the system to continue with course enrollment."; diff --git a/Podfile.lock b/Podfile.lock index a14c3e35d..2348a40e7 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -36,4 +36,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 231e03216f446b4695e43a4c85a29e2127fd674b -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.2