| 1 | efrain | 1 | //
 | 
        
           |  |  | 2 | //  ProfileView.swift
 | 
        
           |  |  | 3 | //  twogetskills
 | 
        
           |  |  | 4 | //
 | 
        
           |  |  | 5 | //  Created by Efrain Yanez Recanatini on 5/4/22.
 | 
        
           |  |  | 6 | //
 | 
        
           |  |  | 7 |   | 
        
           |  |  | 8 | import Foundation
 | 
        
           |  |  | 9 | import SwiftUI
 | 
        
           |  |  | 10 | import Alamofire
 | 
        
           |  |  | 11 | import TTGSnackbar
 | 
        
           |  |  | 12 |   | 
        
           |  |  | 13 | struct ProfileView: View {
 | 
        
           |  |  | 14 |     @EnvironmentObject private var appNavigation : AppNavigation
 | 
        
           |  |  | 15 |     @EnvironmentObject private var networkMonitor : NetworkMonitor
 | 
        
           |  |  | 16 |   | 
        
           |  |  | 17 |     @State private var showGlobalAlert : Bool = false
 | 
        
           |  |  | 18 |     @State private var titleGlobalAlert : String = ""
 | 
        
           |  |  | 19 |     @State private var messageGlobalAlert : String = ""
 | 
        
           |  |  | 20 |   | 
        
           |  |  | 21 |   | 
        
           |  |  | 22 |     private var userExtendedPointViewModel : UserExtendedPointViewModel = UserExtendedPointViewModel()
 | 
        
           |  |  | 23 |   | 
        
           | 21 | efrain | 24 |     private var appData = Environment(\.appData).wrappedValue
 | 
        
           | 1 | efrain | 25 |   | 
        
           |  |  | 26 |   | 
        
           |  |  | 27 |     var body: some View {
 | 
        
           |  |  | 28 |         GeometryReader { geometry in
 | 
        
           |  |  | 29 |             VStack(spacing: 0) {
 | 
        
           |  |  | 30 |                 HStack {
 | 
        
           |  |  | 31 |                     Image("logo")
 | 
        
           |  |  | 32 |                     .resizable()
 | 
        
           |  |  | 33 |                     .frame(width: 32, height: 32, alignment: .center)
 | 
        
           |  |  | 34 |                     .aspectRatio(contentMode: .fit)
 | 
        
           |  |  | 35 |                         .foregroundColor(networkMonitor.status == .disconnected ? Color("color_network_disconnected_foreground") : Color("color_app_bar_foreground"))
 | 
        
           |  |  | 36 |                     .padding(.leading, 16)
 | 
        
           |  |  | 37 |   | 
        
           |  |  | 38 |   | 
        
           |  |  | 39 |                     Text(networkMonitor.status == .disconnected ? Config.LANG_ERROR_NETWORK_MESSAGE_SHORT :   Config.LANG_TAB_BAR_BUTTON_PROFILE)
 | 
        
           |  |  | 40 |                     .font(Font.custom(Config.FONT_NAME_REGULAR, size: Config.FONT_SIZE_APP_BAR_HEAD1 ))
 | 
        
           |  |  | 41 |                         .foregroundColor(networkMonitor.status == .disconnected ? Color("color_network_disconnected_foreground") : Color("color_app_bar_foreground"))
 | 
        
           |  |  | 42 |                     .padding(.leading, 4)
 | 
        
           |  |  | 43 |   | 
        
           |  |  | 44 |                     Spacer()
 | 
        
           |  |  | 45 |   | 
        
           | 9 | efrain | 46 |                     /*
 | 
        
           | 2 | efrain | 47 |                     Button(action: {
 | 
        
           |  |  | 48 |                         DispatchQueue.main.async() {
 | 
        
           |  |  | 49 |                             appNavigation.subpageActive = AppMainSubPage.deletaccount
 | 
        
           |  |  | 50 |                         }
 | 
        
           |  |  | 51 |   | 
        
           |  |  | 52 |                     }, label: {
 | 
        
           |  |  | 53 |                         Image(uiImage: UIImage(named: "ui_delete") ?? UIImage())
 | 
        
           |  |  | 54 |                         .resizable()
 | 
        
           |  |  | 55 |                         .frame(width: 24, height: 24, alignment: .center)
 | 
        
           |  |  | 56 |                         .aspectRatio(contentMode: .fit)
 | 
        
           |  |  | 57 |                         .foregroundColor(Color("color_network_disconnected_foreground"))
 | 
        
           |  |  | 58 |                         .padding(.trailing, 16)
 | 
        
           | 9 | efrain | 59 |                     })*/
 | 
        
           | 1 | efrain | 60 |   | 
        
           | 2 | efrain | 61 |   | 
        
           | 1 | efrain | 62 |                     Button(action: {
 | 
        
           |  |  | 63 |                         let snackbar = TTGSnackbar(message: Config.LANG_SIGNOUT_MESSAGE, duration: .long)
 | 
        
           |  |  | 64 |   | 
        
           |  |  | 65 |                         // Action 1
 | 
        
           |  |  | 66 |                         snackbar.actionText = Config.LANG_COMMON_YES
 | 
        
           |  |  | 67 |                         snackbar.actionTextColor = UIColor( Color("color_snackbar_button_yes"))
 | 
        
           |  |  | 68 |                         snackbar.actionBlock = { (snackbar) in signout() }
 | 
        
           |  |  | 69 |   | 
        
           |  |  | 70 |   | 
        
           |  |  | 71 |                         snackbar.secondActionText = Config.LANG_COMMON_NO
 | 
        
           |  |  | 72 |                         snackbar.secondActionTextColor = UIColor(Color("color_snackbar_button_no"))
 | 
        
           |  |  | 73 |                         snackbar.secondActionBlock = { (snackbar) in }
 | 
        
           |  |  | 74 |   | 
        
           |  |  | 75 |                         snackbar.show()
 | 
        
           |  |  | 76 |   | 
        
           |  |  | 77 |                     }, label: {
 | 
        
           |  |  | 78 |                         Image(uiImage: UIImage(named: "ui_exit_app") ?? UIImage())
 | 
        
           |  |  | 79 |                         .resizable()
 | 
        
           |  |  | 80 |                         .frame(width: 24, height: 24, alignment: .center)
 | 
        
           |  |  | 81 |                         .aspectRatio(contentMode: .fit)
 | 
        
           |  |  | 82 |                         .foregroundColor(Color("color_network_disconnected_foreground"))
 | 
        
           |  |  | 83 |                         .padding(.trailing, 16)
 | 
        
           |  |  | 84 |                     })
 | 
        
           |  |  | 85 |                 }
 | 
        
           |  |  | 86 |                 .edgesIgnoringSafeArea(.top)
 | 
        
           |  |  | 87 |                 .frame(height: 50)
 | 
        
           |  |  | 88 |                 .background(networkMonitor.status == .disconnected ? Color("color_network_disconnected_background") : Color("color_app_bar_background"))
 | 
        
           |  |  | 89 |   | 
        
           |  |  | 90 |   | 
        
           |  |  | 91 |                 Divider().background(networkMonitor.status == .disconnected ? Color("color_network_disconnected_background") : Color("color_app_bar_background"))
 | 
        
           |  |  | 92 |   | 
        
           |  |  | 93 |             ZStack(alignment: .top) {
 | 
        
           |  |  | 94 |   | 
        
           |  |  | 95 |   | 
        
           |  |  | 96 |                 Rectangle()
 | 
        
           |  |  | 97 |                     .foregroundColor(Color("color_app_bar_background"))
 | 
        
           |  |  | 98 |                     .edgesIgnoringSafeArea(.top)
 | 
        
           |  |  | 99 |                     .frame(height: 70)
 | 
        
           |  |  | 100 |   | 
        
           |  |  | 101 |   | 
        
           |  |  | 102 |                 HStack {
 | 
        
           |  |  | 103 |   | 
        
           | 19 | efrain | 104 |                     if appData.userImage.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
 | 
        
           | 1 | efrain | 105 |                          Image("logo")
 | 
        
           |  |  | 106 |                             .resizable()
 | 
        
           |  |  | 107 |                             .aspectRatio(contentMode: .fit)
 | 
        
           |  |  | 108 |                             .frame(height: Config.PROFILE_IMAGE_SIZE)
 | 
        
           |  |  | 109 |                             .clipShape(Circle())
 | 
        
           |  |  | 110 |                             .overlay(Circle().stroke(Color.white, lineWidth: 4))
 | 
        
           |  |  | 111 |                             .shadow(radius: 10)
 | 
        
           |  |  | 112 |   | 
        
           |  |  | 113 |   | 
        
           |  |  | 114 |   | 
        
           |  |  | 115 |                     } else {
 | 
        
           |  |  | 116 |                         CustomAsyncImageProfile(
 | 
        
           | 19 | efrain | 117 |                             url: URL(string: appData.userImage.trimmingCharacters(in: .whitespacesAndNewlines))!,
 | 
        
           | 1 | efrain | 118 |                             placeholder: { Text(Config.LANG_COMMON_LOADING).font(.footnote).foregroundColor(.black)},
 | 
        
           |  |  | 119 |                             image: {
 | 
        
           |  |  | 120 |                                 Image(uiImage: $0)
 | 
        
           |  |  | 121 |                                     .resizable()
 | 
        
           |  |  | 122 |   | 
        
           |  |  | 123 |                             }
 | 
        
           |  |  | 124 |                         )
 | 
        
           |  |  | 125 |                     }
 | 
        
           |  |  | 126 |                 }.padding(10)
 | 
        
           |  |  | 127 |             }
 | 
        
           |  |  | 128 |             VStack(spacing: 5) {
 | 
        
           |  |  | 129 |                 VStack(spacing: 5) {
 | 
        
           |  |  | 130 |                     Text("\(appData.userFirstname) \(appData.userLastname)" )
 | 
        
           |  |  | 131 |                         .bold()
 | 
        
           |  |  | 132 |                         .font(.title)
 | 
        
           | 19 | efrain | 133 |                         .foregroundColor(Color("color_textview_foreground"))
 | 
        
           |  |  | 134 |   | 
        
           | 1 | efrain | 135 |                     Text("\(appData.userEmail)")
 | 
        
           |  |  | 136 |                         .font(.body)
 | 
        
           |  |  | 137 |                         .foregroundColor(Color("color_textview_foreground"))
 | 
        
           |  |  | 138 |                 }.padding()
 | 
        
           |  |  | 139 |   | 
        
           |  |  | 140 |   | 
        
           |  |  | 141 |             }.background(Color("color_card_view_background"))
 | 
        
           |  |  | 142 |   | 
        
           |  |  | 143 |             ScrollView {
 | 
        
           |  |  | 144 |                 ForEach(0..<self.userExtendedPointViewModel.points.count) { i in
 | 
        
           |  |  | 145 |                     UserExtendedPointView(userExtendedPoint: self.userExtendedPointViewModel.points[i])
 | 
        
           |  |  | 146 |                         .listRowInsets(.init()).frame(width: geometry.size.width, height: 70, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
 | 
        
           |  |  | 147 |                 }
 | 
        
           |  |  | 148 |             }
 | 
        
           |  |  | 149 |             .background(Color("color_card_view_background"))
 | 
        
           | 9 | efrain | 150 |   | 
        
           |  |  | 151 |             Spacer()
 | 
        
           |  |  | 152 |   | 
        
           |  |  | 153 |                 Button(action: {
 | 
        
           |  |  | 154 |                     DispatchQueue.main.async() {
 | 
        
           |  |  | 155 |                         appNavigation.subpageActive = AppMainSubPage.deletaccount
 | 
        
           |  |  | 156 |                     }
 | 
        
           |  |  | 157 |                 }, label: {
 | 
        
           |  |  | 158 |                     Text(Config.LANG_DELETE_ACCOUNT_TITLE)
 | 
        
           |  |  | 159 |                     .font(Font.custom(Config.FONT_NAME_REGULAR, size: 13))
 | 
        
           |  |  | 160 |                     .frame(width: UIScreen.main.bounds.width - 32, height: 35)
 | 
        
           |  |  | 161 |                     .foregroundColor(Color("color_button_foreground"))
 | 
        
           |  |  | 162 |                     .background(Color("color_button_background"))
 | 
        
           |  |  | 163 |                     .border(Color("color_button_border"), width: Config.BUTTON_BORDER_SIZE)
 | 
        
           |  |  | 164 |                     .cornerRadius(Config.BUTTON_BORDER_RADIUS)
 | 
        
           |  |  | 165 |                 })
 | 
        
           |  |  | 166 |                 .padding(.top, 16)
 | 
        
           |  |  | 167 |                 .padding(.leading, 16)
 | 
        
           |  |  | 168 |                 .padding(.trailing, 16)
 | 
        
           | 1 | efrain | 169 |         }.onAppear {
 | 
        
           |  |  | 170 |             userExtendedPointViewModel.loadAll()
 | 
        
           |  |  | 171 |         }.alert(isPresented: $showGlobalAlert) {
 | 
        
           |  |  | 172 |             Alert(
 | 
        
           |  |  | 173 |                 title: Text(self.titleGlobalAlert),
 | 
        
           |  |  | 174 |                 message: Text(self.messageGlobalAlert),
 | 
        
           |  |  | 175 |                 dismissButton: .default(Text(Config.LANG_COMMON_OK))
 | 
        
           |  |  | 176 |             )
 | 
        
           |  |  | 177 |         }
 | 
        
           |  |  | 178 |         }
 | 
        
           |  |  | 179 |     }
 | 
        
           |  |  | 180 |   | 
        
           |  |  | 181 |     private func signout() -> Void {
 | 
        
           |  |  | 182 |   | 
        
           |  |  | 183 |         if networkMonitor.status == .disconnected {
 | 
        
           |  |  | 184 |   | 
        
           |  |  | 185 |             self.titleGlobalAlert = Config.LANG_ERROR_NETWORK_TITLE
 | 
        
           |  |  | 186 |             self.messageGlobalAlert = Config.LANG_ERROR_NETWORK_MESSAGE_LONG
 | 
        
           |  |  | 187 |             self.showGlobalAlert  = true
 | 
        
           |  |  | 188 |         } else {
 | 
        
           |  |  | 189 |             let headerSecurity = HeaderSecurity()
 | 
        
           |  |  | 190 |             let headers: HTTPHeaders = [
 | 
        
           |  |  | 191 |                 .init(name: Constants.HTTP_HEADER_SECURITY_TOKEN, value: appData.deviceUuid),
 | 
        
           |  |  | 192 |                 .init(name: Constants.HTTP_HEADER_SECURITY_SECRET, value: headerSecurity.secret),
 | 
        
           |  |  | 193 |                 .init(name: Constants.HTTP_HEADER_SECURITY_CREATED, value: String(headerSecurity.created)),
 | 
        
           |  |  | 194 |                 .init(name: Constants.HTTP_HEADER_SECURITY_RAND, value: String(headerSecurity.rand)),
 | 
        
           |  |  | 195 |                 .accept(Constants.HTTP_HEADER_ACCEPT)
 | 
        
           |  |  | 196 |             ]
 | 
        
           |  |  | 197 |   | 
        
           |  |  | 198 |             AF.request(Config.URL_SIGNOUT, method: .post, headers: headers).responseJSON{(response) in
 | 
        
           |  |  | 199 |                 switch response.result {
 | 
        
           |  |  | 200 |                     case .success:
 | 
        
           |  |  | 201 |                         let now = Date()
 | 
        
           |  |  | 202 |                         let dateFormatter = DateFormatter()
 | 
        
           |  |  | 203 |                         dateFormatter.dateFormat = Constants.FORMAT_DATETIME_SERVICE
 | 
        
           |  |  | 204 |                         let dateOn = dateFormatter.string(from: now)
 | 
        
           |  |  | 205 |   | 
        
           |  |  | 206 |   | 
        
           |  |  | 207 |                         var userLog = UserLogModel()
 | 
        
           |  |  | 208 |                         userLog.activity = Constants.USER_LOG_ACTIVITY_SIGNOUT
 | 
        
           |  |  | 209 |                         userLog.userUuid = appData.userUuid
 | 
        
           |  |  | 210 |                         userLog.addedOn = dateOn
 | 
        
           |  |  | 211 |   | 
        
           | 17 | efrain | 212 |                         let userLogDao = UserLogDao()
 | 
        
           | 1 | efrain | 213 |                         userLogDao.insert(record: userLog)
 | 
        
           |  |  | 214 |   | 
        
           |  |  | 215 |                         var json : [String: Any] = userLog.toJson()
 | 
        
           |  |  | 216 |                         json[Constants.SYNC_ADAPTER_DATA_TYPE_FIELD_NAME] = Constants.SYNC_ADAPTER_DATA_TYPE_MICROLEARNING_USER_LOG
 | 
        
           |  |  | 217 |   | 
        
           |  |  | 218 |                         var sync = SyncModel();
 | 
        
           |  |  | 219 |                         sync.type = Constants.SYNC_ADAPTER_TYPE_SYNC
 | 
        
           |  |  | 220 |                         if let theJSONData = try?  JSONSerialization.data(withJSONObject: json, options: .prettyPrinted),
 | 
        
           |  |  | 221 |                            let data = String(data: theJSONData, encoding: String.Encoding.ascii) {
 | 
        
           |  |  | 222 |                                 sync.data = data
 | 
        
           |  |  | 223 |                             }
 | 
        
           |  |  | 224 |   | 
        
           | 17 | efrain | 225 |                         let syncDao = SyncDao()
 | 
        
           | 1 | efrain | 226 |                         syncDao.insert(record : sync)
 | 
        
           |  |  | 227 |   | 
        
           |  |  | 228 |                         appData.userEmail = ""
 | 
        
           |  |  | 229 |                         appData.userFirstname = ""
 | 
        
           |  |  | 230 |                         appData.userLastname = ""
 | 
        
           |  |  | 231 |                         appData.userUuid = ""
 | 
        
           |  |  | 232 |                         appData.userImage = ""
 | 
        
           |  |  | 233 |                         appData.save()
 | 
        
           |  |  | 234 |   | 
        
           |  |  | 235 |   | 
        
           |  |  | 236 |                         appNavigation.pageActive = .goodbye
 | 
        
           |  |  | 237 |                         break;
 | 
        
           |  |  | 238 |   | 
        
           |  |  | 239 |                     case .failure:
 | 
        
           |  |  | 240 |                         self.titleGlobalAlert = Config.LANG_ERROR_COMMUNICATION_TITLE
 | 
        
           |  |  | 241 |                         self.messageGlobalAlert = Config.LANG_ERROR_COMMUNICATION_MESSAGE
 | 
        
           |  |  | 242 |                         self.showGlobalAlert = true
 | 
        
           |  |  | 243 |   | 
        
           |  |  | 244 |                         break;
 | 
        
           |  |  | 245 |                 }
 | 
        
           |  |  | 246 |             }
 | 
        
           |  |  | 247 |         }
 | 
        
           |  |  | 248 |     }
 | 
        
           |  |  | 249 | }
 | 
        
           |  |  | 250 |   | 
        
           |  |  | 251 |   | 
        
           |  |  | 252 | struct ProfileView_Previews: PreviewProvider {
 | 
        
           |  |  | 253 |     static var previews: some View {
 | 
        
           |  |  | 254 |         ProfileView()
 | 
        
           |  |  | 255 |     }
 | 
        
           |  |  | 256 | }
 |