소스 검색

Added profile view, localizations, connection with member.php

Hector Carrion 3 년 전
부모
커밋
8c25391de4

+ 37
- 4
Comedores Sociales.xcodeproj/project.pbxproj 파일 보기

23
 		356533A525449C3900F2F0DE /* Comedores_SocialesUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 356533A425449C3900F2F0DE /* Comedores_SocialesUITests.swift */; };
23
 		356533A525449C3900F2F0DE /* Comedores_SocialesUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 356533A425449C3900F2F0DE /* Comedores_SocialesUITests.swift */; };
24
 		356533B92544A1AF00F2F0DE /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 356533B82544A1AF00F2F0DE /* LoginView.swift */; };
24
 		356533B92544A1AF00F2F0DE /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 356533B82544A1AF00F2F0DE /* LoginView.swift */; };
25
 		356533C42544B1FF00F2F0DE /* RegisterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 356533C32544B1FF00F2F0DE /* RegisterView.swift */; };
25
 		356533C42544B1FF00F2F0DE /* RegisterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 356533C32544B1FF00F2F0DE /* RegisterView.swift */; };
26
+		3580269E258A5A2E00CDE7AE /* ProfileSummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3580269D258A5A2E00CDE7AE /* ProfileSummary.swift */; };
27
+		358026A6258A5BB700CDE7AE /* ProfileModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 358026A5258A5BB700CDE7AE /* ProfileModel.swift */; };
28
+		358026AB258A5DA600CDE7AE /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 358026AA258A5DA600CDE7AE /* ProfileView.swift */; };
26
 		358E94702558AC130074E928 /* NetworkingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 358E946F2558AC130074E928 /* NetworkingModel.swift */; };
29
 		358E94702558AC130074E928 /* NetworkingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 358E946F2558AC130074E928 /* NetworkingModel.swift */; };
30
+		35CAE51C258B9B7800FC27A6 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 35CAE51E258B9B7800FC27A6 /* Localizable.strings */; };
27
 /* End PBXBuildFile section */
31
 /* End PBXBuildFile section */
28
 
32
 
29
 /* Begin PBXContainerItemProxy section */
33
 /* Begin PBXContainerItemProxy section */
66
 		356533A625449C3900F2F0DE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
70
 		356533A625449C3900F2F0DE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
67
 		356533B82544A1AF00F2F0DE /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = "<group>"; };
71
 		356533B82544A1AF00F2F0DE /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = "<group>"; };
68
 		356533C32544B1FF00F2F0DE /* RegisterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegisterView.swift; sourceTree = "<group>"; };
72
 		356533C32544B1FF00F2F0DE /* RegisterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegisterView.swift; sourceTree = "<group>"; };
73
+		3580269D258A5A2E00CDE7AE /* ProfileSummary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileSummary.swift; sourceTree = "<group>"; };
74
+		358026A5258A5BB700CDE7AE /* ProfileModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileModel.swift; sourceTree = "<group>"; };
75
+		358026AA258A5DA600CDE7AE /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = "<group>"; };
69
 		358E946F2558AC130074E928 /* NetworkingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkingModel.swift; sourceTree = "<group>"; };
76
 		358E946F2558AC130074E928 /* NetworkingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkingModel.swift; sourceTree = "<group>"; };
77
+		35CAE51D258B9B7800FC27A6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
78
+		35CAE51F258B9BC600FC27A6 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
79
+		35CAE520258B9C2A00FC27A6 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/Localizable.strings"; sourceTree = "<group>"; };
70
 /* End PBXFileReference section */
80
 /* End PBXFileReference section */
71
 
81
 
72
 /* Begin PBXFrameworksBuildPhase section */
82
 /* Begin PBXFrameworksBuildPhase section */
97
 		350E75972575672F006B17CC /* View */ = {
107
 		350E75972575672F006B17CC /* View */ = {
98
 			isa = PBXGroup;
108
 			isa = PBXGroup;
99
 			children = (
109
 			children = (
110
+				350E75BB257576BD006B17CC /* CustomNavigationView.swift */,
100
 				350E75B325757572006B17CC /* FoodCardView.swift */,
111
 				350E75B325757572006B17CC /* FoodCardView.swift */,
112
+				3580269D258A5A2E00CDE7AE /* ProfileSummary.swift */,
113
+				358026AA258A5DA600CDE7AE /* ProfileView.swift */,
101
 				350E759D257567F2006B17CC /* Search */,
114
 				350E759D257567F2006B17CC /* Search */,
102
-				350E759C257567E4006B17CC /* Login */,
103
-				350E75BB257576BD006B17CC /* CustomNavigationView.swift */,
115
+				350E759C257567E4006B17CC /* Auth */,
104
 			);
116
 			);
105
 			path = View;
117
 			path = View;
106
 			sourceTree = "<group>";
118
 			sourceTree = "<group>";
112
 				3565338B25449C3800F2F0DE /* Persistence.swift */,
124
 				3565338B25449C3800F2F0DE /* Persistence.swift */,
113
 				350E75AE2575687C006B17CC /* FoodItem.swift */,
125
 				350E75AE2575687C006B17CC /* FoodItem.swift */,
114
 				350E75CC25758D92006B17CC /* UserSettings.swift */,
126
 				350E75CC25758D92006B17CC /* UserSettings.swift */,
127
+				358026A5258A5BB700CDE7AE /* ProfileModel.swift */,
115
 			);
128
 			);
116
 			path = Model;
129
 			path = Model;
117
 			sourceTree = "<group>";
130
 			sourceTree = "<group>";
118
 		};
131
 		};
119
-		350E759C257567E4006B17CC /* Login */ = {
132
+		350E759C257567E4006B17CC /* Auth */ = {
120
 			isa = PBXGroup;
133
 			isa = PBXGroup;
121
 			children = (
134
 			children = (
122
 				356533B82544A1AF00F2F0DE /* LoginView.swift */,
135
 				356533B82544A1AF00F2F0DE /* LoginView.swift */,
123
 				356533C32544B1FF00F2F0DE /* RegisterView.swift */,
136
 				356533C32544B1FF00F2F0DE /* RegisterView.swift */,
124
 			);
137
 			);
125
-			path = Login;
138
+			path = Auth;
126
 			sourceTree = "<group>";
139
 			sourceTree = "<group>";
127
 		};
140
 		};
128
 		350E759D257567F2006B17CC /* Search */ = {
141
 		350E759D257567F2006B17CC /* Search */ = {
137
 		3565337625449C3600F2F0DE = {
150
 		3565337625449C3600F2F0DE = {
138
 			isa = PBXGroup;
151
 			isa = PBXGroup;
139
 			children = (
152
 			children = (
153
+				35CAE51E258B9B7800FC27A6 /* Localizable.strings */,
140
 				3565338125449C3600F2F0DE /* Comedores Sociales */,
154
 				3565338125449C3600F2F0DE /* Comedores Sociales */,
141
 				3565339825449C3800F2F0DE /* Comedores SocialesTests */,
155
 				3565339825449C3800F2F0DE /* Comedores SocialesTests */,
142
 				356533A325449C3900F2F0DE /* Comedores SocialesUITests */,
156
 				356533A325449C3900F2F0DE /* Comedores SocialesUITests */,
280
 			knownRegions = (
294
 			knownRegions = (
281
 				en,
295
 				en,
282
 				Base,
296
 				Base,
297
+				es,
298
+				"es-419",
283
 			);
299
 			);
284
 			mainGroup = 3565337625449C3600F2F0DE;
300
 			mainGroup = 3565337625449C3600F2F0DE;
285
 			productRefGroup = 3565338025449C3600F2F0DE /* Products */;
301
 			productRefGroup = 3565338025449C3600F2F0DE /* Products */;
299
 			buildActionMask = 2147483647;
315
 			buildActionMask = 2147483647;
300
 			files = (
316
 			files = (
301
 				3565338A25449C3800F2F0DE /* Preview Assets.xcassets in Resources */,
317
 				3565338A25449C3800F2F0DE /* Preview Assets.xcassets in Resources */,
318
+				35CAE51C258B9B7800FC27A6 /* Localizable.strings in Resources */,
302
 				3565338725449C3800F2F0DE /* Assets.xcassets in Resources */,
319
 				3565338725449C3800F2F0DE /* Assets.xcassets in Resources */,
303
 			);
320
 			);
304
 			runOnlyForDeploymentPostprocessing = 0;
321
 			runOnlyForDeploymentPostprocessing = 0;
324
 			isa = PBXSourcesBuildPhase;
341
 			isa = PBXSourcesBuildPhase;
325
 			buildActionMask = 2147483647;
342
 			buildActionMask = 2147483647;
326
 			files = (
343
 			files = (
344
+				358026A6258A5BB700CDE7AE /* ProfileModel.swift in Sources */,
327
 				358E94702558AC130074E928 /* NetworkingModel.swift in Sources */,
345
 				358E94702558AC130074E928 /* NetworkingModel.swift in Sources */,
328
 				356533B92544A1AF00F2F0DE /* LoginView.swift in Sources */,
346
 				356533B92544A1AF00F2F0DE /* LoginView.swift in Sources */,
329
 				3565338C25449C3800F2F0DE /* Persistence.swift in Sources */,
347
 				3565338C25449C3800F2F0DE /* Persistence.swift in Sources */,
331
 				350E75CD25758D92006B17CC /* UserSettings.swift in Sources */,
349
 				350E75CD25758D92006B17CC /* UserSettings.swift in Sources */,
332
 				350E75AF2575687C006B17CC /* FoodItem.swift in Sources */,
350
 				350E75AF2575687C006B17CC /* FoodItem.swift in Sources */,
333
 				350E75C125757B24006B17CC /* SearchContainer.swift in Sources */,
351
 				350E75C125757B24006B17CC /* SearchContainer.swift in Sources */,
352
+				358026AB258A5DA600CDE7AE /* ProfileView.swift in Sources */,
334
 				356533C42544B1FF00F2F0DE /* RegisterView.swift in Sources */,
353
 				356533C42544B1FF00F2F0DE /* RegisterView.swift in Sources */,
335
 				350E75AA25756829006B17CC /* Search.swift in Sources */,
354
 				350E75AA25756829006B17CC /* Search.swift in Sources */,
336
 				3565338F25449C3800F2F0DE /* Comedores_Sociales.xcdatamodeld in Sources */,
355
 				3565338F25449C3800F2F0DE /* Comedores_Sociales.xcdatamodeld in Sources */,
337
 				350E75BC257576BD006B17CC /* CustomNavigationView.swift in Sources */,
356
 				350E75BC257576BD006B17CC /* CustomNavigationView.swift in Sources */,
338
 				350E75B425757572006B17CC /* FoodCardView.swift in Sources */,
357
 				350E75B425757572006B17CC /* FoodCardView.swift in Sources */,
358
+				3580269E258A5A2E00CDE7AE /* ProfileSummary.swift in Sources */,
339
 				3565338325449C3600F2F0DE /* Comedores_SocialesApp.swift in Sources */,
359
 				3565338325449C3600F2F0DE /* Comedores_SocialesApp.swift in Sources */,
340
 			);
360
 			);
341
 			runOnlyForDeploymentPostprocessing = 0;
361
 			runOnlyForDeploymentPostprocessing = 0;
371
 		};
391
 		};
372
 /* End PBXTargetDependency section */
392
 /* End PBXTargetDependency section */
373
 
393
 
394
+/* Begin PBXVariantGroup section */
395
+		35CAE51E258B9B7800FC27A6 /* Localizable.strings */ = {
396
+			isa = PBXVariantGroup;
397
+			children = (
398
+				35CAE51D258B9B7800FC27A6 /* en */,
399
+				35CAE51F258B9BC600FC27A6 /* es */,
400
+				35CAE520258B9C2A00FC27A6 /* es-419 */,
401
+			);
402
+			name = Localizable.strings;
403
+			sourceTree = "<group>";
404
+		};
405
+/* End PBXVariantGroup section */
406
+
374
 /* Begin XCBuildConfiguration section */
407
 /* Begin XCBuildConfiguration section */
375
 		356533A725449C3900F2F0DE /* Debug */ = {
408
 		356533A725449C3900F2F0DE /* Debug */ = {
376
 			isa = XCBuildConfiguration;
409
 			isa = XCBuildConfiguration;

+ 3
- 1
Comedores Sociales/ContentView.swift 파일 보기

10
 struct ContentView: View {
10
 struct ContentView: View {
11
     @StateObject var lvm = LoginViewModel()
11
     @StateObject var lvm = LoginViewModel()
12
     @StateObject var rvm = RegisterViewModel()
12
     @StateObject var rvm = RegisterViewModel()
13
+    @StateObject var pvm = ProfileViewModel()
13
 
14
 
14
     var body: some View {
15
     var body: some View {
15
-        if lvm.response ?? false || rvm.response ?? false {
16
+        if lvm.response == .success || rvm.response == .success || UserDefaults.standard.bool(forKey: "logged-in") {
16
             SearchContainer()
17
             SearchContainer()
18
+                .environmentObject(pvm)
17
         } else {
19
         } else {
18
             LoginView()
20
             LoginView()
19
                 .environmentObject(lvm)
21
                 .environmentObject(lvm)

+ 159
- 9
Comedores Sociales/Model/NetworkingModel.swift 파일 보기

10
 let serverAddress: String = "http://161.35.60.201/"
10
 let serverAddress: String = "http://161.35.60.201/"
11
 
11
 
12
 class Authentication: Codable {
12
 class Authentication: Codable {
13
-    var username: String
13
+    var correo: String
14
     var password: String
14
     var password: String
15
     
15
     
16
     init(email: String, password: String) {
16
     init(email: String, password: String) {
17
-        self.username = email
17
+        self.correo = email
18
         self.password = password
18
         self.password = password
19
     }
19
     }
20
     
20
     
21
     func isComplete() -> Bool {
21
     func isComplete() -> Bool {
22
-        if username != "" && password != "" {
22
+        if correo != "" && password != "" {
23
             return true
23
             return true
24
         } else {
24
         } else {
25
             return false
25
             return false
78
     }
78
     }
79
 }
79
 }
80
 
80
 
81
+enum Response {
82
+    case success
83
+    case failure
84
+    case loading
85
+    case unfetched
86
+}
87
+
88
+struct UserToken: Codable {
89
+    let token: String
90
+}
91
+
92
+func getToken(input: String) -> UserToken {
93
+    let JSONData = input.data(using: .utf8)!
94
+    let token: UserToken = try! JSONDecoder().decode(UserToken.self, from: JSONData)
95
+    return token
96
+}
97
+
98
+struct UserDetails: Codable {
99
+    let correo: String
100
+    let nombre: String
101
+    let organizacion: String?
102
+    let puesto: String?
103
+    let calle: String
104
+    let pueblo: String
105
+    let cpostal: String
106
+    let telefono: String
107
+    let membresia: String?
108
+    let vigencia: String?
109
+    let horas_trabajadas: String?
110
+}
111
+
112
+func getUserDetails(input: String) -> UserDetails {
113
+    let JSONData = input.data(using: .utf8)!
114
+    let info: UserDetails = try! JSONDecoder().decode(UserDetails.self, from: JSONData)
115
+    return info
116
+}
81
 
117
 
82
 class LoginViewModel: ObservableObject {
118
 class LoginViewModel: ObservableObject {
83
-    @Published var response: Bool?
119
+    @Published var response: Response = .unfetched
84
     
120
     
85
     func changeResponse(response: Bool) {
121
     func changeResponse(response: Bool) {
86
-        self.response = response
122
+        if response == true {
123
+            self.response = .success
124
+        } else {
125
+            self.response = .failure
126
+        }
87
     }
127
     }
88
     
128
     
89
     func login(data: Authentication) {
129
     func login(data: Authentication) {
130
+        self.response = .loading
90
         
131
         
91
-        let service = "login.php"
132
+        let service = "api/login.php"
92
         guard let encodedData = try? JSONEncoder().encode(data)
133
         guard let encodedData = try? JSONEncoder().encode(data)
93
         else {
134
         else {
94
             print("Failed to encode login request")
135
             print("Failed to encode login request")
119
                 DispatchQueue.main.async {
160
                 DispatchQueue.main.async {
120
                     if httpResponse.statusCode == 200 {
161
                     if httpResponse.statusCode == 200 {
121
                         self.changeResponse(response: true)
162
                         self.changeResponse(response: true)
163
+                        // MARK: JSON Decoding
164
+                        let dataString = NSString(data: data, encoding: String.Encoding.utf8.rawValue)! as String
165
+                        let json = getToken(input: dataString)
166
+                        
167
+                        let defaults = UserDefaults.standard
168
+                        defaults.set(json.token, forKey: "token")
169
+                        defaults.set(true, forKey: "logged-in")
122
                     } else {
170
                     } else {
123
                         self.changeResponse(response: false)
171
                         self.changeResponse(response: false)
124
                     }
172
                     }
131
 }
179
 }
132
 
180
 
133
 class RegisterViewModel: ObservableObject {
181
 class RegisterViewModel: ObservableObject {
134
-    @Published var response: Bool?
182
+    @Published var response: Response = .unfetched
135
     
183
     
136
     func changeResponse(response: Bool) {
184
     func changeResponse(response: Bool) {
137
-        self.response = response
185
+        if response == true {
186
+            self.response = .success
187
+        } else {
188
+            self.response = .failure
189
+        }
138
     }
190
     }
139
     
191
     
140
     func register(data: Registration) {
192
     func register(data: Registration) {
193
+        self.response = .loading
141
         
194
         
142
         let service = "signup.php"
195
         let service = "signup.php"
143
         guard let encodedData = try? JSONEncoder().encode(data)
196
         guard let encodedData = try? JSONEncoder().encode(data)
146
             return
199
             return
147
         }
200
         }
148
         
201
         
149
-        print("Reg JSON to send:", String(data: encodedData, encoding: .utf8)!)
202
+        //print("Reg JSON to send:", String(data: encodedData, encoding: .utf8)!)
150
         
203
         
151
         let url = URL(string: serverAddress + service)!
204
         let url = URL(string: serverAddress + service)!
152
         var request = URLRequest(url: url)
205
         var request = URLRequest(url: url)
178
         }.resume()
231
         }.resume()
179
     }
232
     }
180
 }
233
 }
234
+
235
+
236
+class ProfileViewModel: ObservableObject {
237
+    @Published var profile: Profile = .default
238
+    @Published var response: Response = .unfetched
239
+    
240
+    func changeResponse(response: Bool) {
241
+        if response == true {
242
+            self.response = .success
243
+        } else {
244
+            self.response = .failure
245
+        }
246
+    }
247
+    
248
+    func changeProfile(data: UserDetails) {
249
+        self.profile.name = data.nombre
250
+        self.profile.email = data.correo
251
+        self.profile.phone = addDashes(phone: data.telefono)
252
+        
253
+        if data.membresia != "" {
254
+            self.profile.membership = data.membresia ?? "No memebership recieved from server"
255
+        }
256
+        if (data.vigencia != nil) {
257
+            self.profile.membershipStatus = .valid
258
+        } else {
259
+            self.profile.membershipStatus = .expired
260
+        }
261
+        
262
+        if let hours = data.horas_trabajadas {
263
+            self.profile.hoursWorked = Int(hours) ?? 0
264
+        }
265
+        
266
+    }
267
+    
268
+    func fetchMember(token: UserToken) {
269
+        self.response = .loading
270
+        
271
+        let service = "api/member.php"
272
+        guard let encodedData = try? JSONEncoder().encode(token)
273
+        else {
274
+            print("Failed to encode login request")
275
+            return
276
+        }
277
+        
278
+        //print("JSON to send:", String(data: encodedData, encoding: .utf8)!)
279
+        
280
+        let url = URL(string: serverAddress + service)!
281
+        var request = URLRequest(url: url)
282
+        request.setValue("appmember/json", forHTTPHeaderField: "Content-Type")
283
+        request.httpMethod = "POST"
284
+        request.httpBody = encodedData
285
+        
286
+        URLSession.shared.dataTask(with: request) {data, response, error in
287
+            
288
+            //handle result here
289
+            guard let data = data
290
+            else {
291
+                print("No data in response: \(error?.localizedDescription ?? "Unknown error").")
292
+                return
293
+            }
294
+            print(response ?? "No response")
295
+            print("Recieved data:", data)
296
+            print(error ?? "No error")
297
+            
298
+            
299
+            if let httpResponse = response as? HTTPURLResponse {
300
+                DispatchQueue.main.async {
301
+                    if httpResponse.statusCode == 200 {
302
+                        // MARK: JSON Decoding
303
+                        let dataString = NSString(data: data, encoding: String.Encoding.utf8.rawValue)! as String
304
+                        let json = getUserDetails(input: dataString)
305
+                        //print(json)
306
+                        self.changeResponse(response: true)
307
+                        self.changeProfile(data: json)
308
+                    } else {
309
+                        self.changeResponse(response: false)
310
+                    }
311
+                    
312
+                }
313
+            }
314
+            
315
+        }.resume()
316
+    }
317
+}
318
+
319
+func addDashes(phone: String) -> String {
320
+    var prettyPhone: String = ""
321
+    var i = 0
322
+    for number in phone {
323
+        prettyPhone.append(number)
324
+        if i == 2 || i == 5 {
325
+            prettyPhone.append("-")
326
+        }
327
+        i += 1
328
+    }
329
+    return prettyPhone
330
+}

+ 25
- 0
Comedores Sociales/Model/ProfileModel.swift 파일 보기

1
+//
2
+//  ProfileModel.swift
3
+//  Comedores Sociales
4
+//
5
+//  Created by Hector Carrion on 12/16/20.
6
+//
7
+
8
+import Foundation
9
+
10
+struct Profile {
11
+    var name: String
12
+    var email: String
13
+    var phone: String
14
+    var membership: String
15
+    var membershipStatus = membership.undetermined
16
+    var hoursWorked: Int = 0
17
+
18
+    static let `default` = Profile(name: "Comedores Sociales", email: "user@comedores.com", phone: "787-555-5555", membership: "Loading...", membershipStatus: membership.undetermined, hoursWorked: 0)
19
+    
20
+    enum membership: String {
21
+        case valid = "Valid"
22
+        case expired = "Expired"
23
+        case undetermined = "Unknown"
24
+    }
25
+}

Comedores Sociales/View/Login/LoginView.swift → Comedores Sociales/View/Auth/LoginView.swift 파일 보기

22
             EmailField(email: $email)
22
             EmailField(email: $email)
23
             PasswordField(password: $password)
23
             PasswordField(password: $password)
24
             
24
             
25
-            if loginVM.response == false {
26
-                Text("Information incorrect, please try again")
25
+            if loginVM.response == .failure {
26
+                Text(NSLocalizedString("incorrect", comment:""))
27
                     .offset(y: -10)
27
                     .offset(y: -10)
28
                     .foregroundColor(.red)
28
                     .foregroundColor(.red)
29
-            } else if loginVM.response == true {
29
+            } else if loginVM.response == .success {
30
                 Text("Login successful 🎉")
30
                 Text("Login successful 🎉")
31
                     .offset(y: -10)
31
                     .offset(y: -10)
32
                     .foregroundColor(.green)
32
                     .foregroundColor(.green)
33
+            } else if loginVM.response == .loading {
34
+                ProgressView("Loading…")
35
+                    .padding()
33
             }
36
             }
34
             
37
             
35
             Button(action: {
38
             Button(action: {
50
             }
53
             }
51
             .sheet(isPresented: $showingRegister, content: {RegisterView()})
54
             .sheet(isPresented: $showingRegister, content: {RegisterView()})
52
             .alert(isPresented: $showingAlert) {
55
             .alert(isPresented: $showingAlert) {
53
-                Alert(title: Text("Fields incomplete"), message: Text("Please enter a valid email and password"), dismissButton: .default(Text("OK")))
56
+                Alert(title: Text(NSLocalizedString("incomplete", comment:"")), message: Text(NSLocalizedString("enter_valid", comment:"")), dismissButton: .default(Text("OK")))
54
                 
57
                 
55
             }
58
             }
56
         }
59
         }
82
 
85
 
83
 struct LoginText: View {
86
 struct LoginText: View {
84
     var body: some View {
87
     var body: some View {
85
-        Text("Login")
88
+        Text(NSLocalizedString("login", comment:""))
86
             .font(.headline)
89
             .font(.headline)
87
             .foregroundColor(.white)
90
             .foregroundColor(.white)
88
             .padding()
91
             .padding()
95
 
98
 
96
 struct RegisterText: View {
99
 struct RegisterText: View {
97
     var body: some View {
100
     var body: some View {
98
-        Text("Don't have an account? Register")
101
+        Text(NSLocalizedString("register", comment:""))
99
             .font(.headline)
102
             .font(.headline)
100
             .foregroundColor(.gray)
103
             .foregroundColor(.gray)
101
             .padding()
104
             .padding()
110
     @Environment(\.colorScheme) var colorScheme
113
     @Environment(\.colorScheme) var colorScheme
111
     var body: some View {
114
     var body: some View {
112
         TextField("Email", text: $email)
115
         TextField("Email", text: $email)
116
+            .disableAutocorrection(true)
113
             .autocapitalization(.none)
117
             .autocapitalization(.none)
114
             .padding()
118
             .padding()
115
             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
119
             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)

Comedores Sociales/View/Login/RegisterView.swift → Comedores Sociales/View/Auth/RegisterView.swift 파일 보기

28
     
28
     
29
     var body: some View {
29
     var body: some View {
30
         VStack {
30
         VStack {
31
-            Text("Details")
31
+            Text(NSLocalizedString("details", comment:""))
32
                 .font(.largeTitle)
32
                 .font(.largeTitle)
33
                 .fontWeight(.semibold)
33
                 .fontWeight(.semibold)
34
                 .frame(width: 350, height: 25, alignment: .topLeading)
34
                 .frame(width: 350, height: 25, alignment: .topLeading)
37
             ScrollView {
37
             ScrollView {
38
                 Group {
38
                 Group {
39
                     Group {
39
                     Group {
40
-                        TextField("Full Name", text: $name)
40
+                        TextField(NSLocalizedString("full_name", comment:""), text: $name)
41
                             .autocapitalization(.words)
41
                             .autocapitalization(.words)
42
                             .padding()
42
                             .padding()
43
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
43
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
56
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
56
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
57
                             .cornerRadius(5.0)
57
                             .cornerRadius(5.0)
58
                             .padding(.bottom, 5)
58
                             .padding(.bottom, 5)
59
-                        SecureField("Password (confirmation)", text: $passwordConf)
59
+                        SecureField(NSLocalizedString("pass_conf", comment:""), text: $passwordConf)
60
                             .autocapitalization(.none)
60
                             .autocapitalization(.none)
61
                             .padding()
61
                             .padding()
62
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
62
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
63
                             .cornerRadius(5.0)
63
                             .cornerRadius(5.0)
64
                             .padding(.bottom, 5)
64
                             .padding(.bottom, 5)
65
                     }
65
                     }
66
-                        TextField("Phone Number", text: $phoneNumber)
66
+                        TextField(NSLocalizedString("phone", comment:""), text: $phoneNumber)
67
                             .keyboardType(.numberPad)
67
                             .keyboardType(.numberPad)
68
                             .padding()
68
                             .padding()
69
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
69
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
70
                             .cornerRadius(5.0)
70
                             .cornerRadius(5.0)
71
                             .padding(.bottom, 5)
71
                             .padding(.bottom, 5)
72
-                        TextField("Urbanization", text: $urb)
72
+                        TextField(NSLocalizedString("urb", comment:""), text: $urb)
73
                             .padding()
73
                             .padding()
74
                             .autocapitalization(.words)
74
                             .autocapitalization(.words)
75
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
75
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
76
                             .cornerRadius(5.0)
76
                             .cornerRadius(5.0)
77
                             .padding(.bottom, 5)
77
                             .padding(.bottom, 5)
78
-                        TextField("Street", text: $street)
78
+                        TextField(NSLocalizedString("street", comment:""), text: $street)
79
                             .autocapitalization(.words)
79
                             .autocapitalization(.words)
80
                             .padding()
80
                             .padding()
81
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
81
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
82
                             .cornerRadius(5.0)
82
                             .cornerRadius(5.0)
83
                             .padding(.bottom, 5)
83
                             .padding(.bottom, 5)
84
-                        TextField("City", text: $city)
84
+                        TextField(NSLocalizedString("city", comment:""), text: $city)
85
                             .autocapitalization(.words)
85
                             .autocapitalization(.words)
86
                             .padding()
86
                             .padding()
87
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
87
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
88
                             .cornerRadius(5.0)
88
                             .cornerRadius(5.0)
89
                             .padding(.bottom, 5)
89
                             .padding(.bottom, 5)
90
-                        TextField("Zip Code", text: $zip)
90
+                        TextField(NSLocalizedString("zip", comment:""), text: $zip)
91
                             .keyboardType(.numberPad)
91
                             .keyboardType(.numberPad)
92
                             .padding()
92
                             .padding()
93
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
93
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
94
                             .cornerRadius(5.0)
94
                             .cornerRadius(5.0)
95
                             .padding(.bottom, 5)
95
                             .padding(.bottom, 5)
96
-                        TextField("Organization (optional)", text: $org)
96
+                        TextField(NSLocalizedString("org", comment:""), text: $org)
97
                             .autocapitalization(.words)
97
                             .autocapitalization(.words)
98
                             .padding()
98
                             .padding()
99
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
99
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
100
                             .cornerRadius(5.0)
100
                             .cornerRadius(5.0)
101
                             .padding(.bottom, 5)
101
                             .padding(.bottom, 5)
102
-                        TextField("Position (optional)", text: $position)
102
+                        TextField(NSLocalizedString("pos", comment:""), text: $position)
103
                             .padding()
103
                             .padding()
104
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
104
                             .background(colorScheme == .dark ? darkGreyColor : lightGreyColor)
105
                             .cornerRadius(5.0)
105
                             .cornerRadius(5.0)
108
                 }.padding(5)
108
                 }.padding(5)
109
             }
109
             }
110
             
110
             
111
-            if registerVM.response == false {
112
-                Text("Registration failed, please try again")
111
+            if registerVM.response == .failure {
112
+                Text(NSLocalizedString("reg_fail", comment:""))
113
                     //.offset(y: -5)
113
                     //.offset(y: -5)
114
                     .foregroundColor(.red)
114
                     .foregroundColor(.red)
115
-            } else if registerVM.response == true {
115
+            } else if registerVM.response == .loading {
116
+                ProgressView("Loading…")
117
+                    .padding()
118
+            } else if registerVM.response == .success {
116
                 Text("Registration successful 🎉")
119
                 Text("Registration successful 🎉")
117
                     //.offset(y: -5)
120
                     //.offset(y: -5)
118
                     .foregroundColor(.green)
121
                     .foregroundColor(.green)
138
                 
141
                 
139
                 
142
                 
140
             }) {
143
             }) {
141
-                Text("Register")
144
+                Text(NSLocalizedString("reg", comment:""))
142
                     .font(.headline)
145
                     .font(.headline)
143
                     .foregroundColor(.white)
146
                     .foregroundColor(.white)
144
                     .padding()
147
                     .padding()
150
             
153
             
151
             
154
             
152
         }.alert(isPresented: $showingAlert) {
155
         }.alert(isPresented: $showingAlert) {
153
-            Alert(title: Text("Fields incomplete"), message: Text("Please enter a all required information"), dismissButton: .default(Text("OK")))}
156
+            Alert(title: Text(NSLocalizedString("incomplete", comment:"")), message: Text(NSLocalizedString("enter_all", comment:"")), dismissButton: .default(Text("OK")))}
154
         .alert(isPresented: $passwordsAlert) {
157
         .alert(isPresented: $passwordsAlert) {
155
-            Alert(title: Text("Passwords do not match"), message: Text("Please retype your password and try again"), dismissButton: .default(Text("OK")))}
158
+            Alert(title: Text(NSLocalizedString("pass_missmatch", comment:"")), message: Text(NSLocalizedString("pass_retype", comment:"")), dismissButton: .default(Text("OK")))}
156
         .padding()
159
         .padding()
157
     }
160
     }
158
 }
161
 }

+ 8
- 4
Comedores Sociales/View/CustomNavigationView.swift 파일 보기

14
         return CustomNavigationView.Coordinator(parent: self)
14
         return CustomNavigationView.Coordinator(parent: self)
15
     }
15
     }
16
     
16
     
17
-    // Just Change Your View That Requires Search Bar...
18
     var view: AnyView
17
     var view: AnyView
19
     
18
     
20
     // Ease Of Use.....
19
     // Ease Of Use.....
21
-    
22
     var largeTitle: Bool
20
     var largeTitle: Bool
23
     var title: String
21
     var title: String
24
     var placeHolder: String
22
     var placeHolder: String
26
     // onSearch And OnCancel Closures....
24
     // onSearch And OnCancel Closures....
27
     var onSearch: (String)->()
25
     var onSearch: (String)->()
28
     var onCancel: ()->()
26
     var onCancel: ()->()
27
+    var onClick: ()->()
29
     
28
     
30
     // requre closure on Call...
29
     // requre closure on Call...
31
     
30
     
32
-    init(view: AnyView,placeHolder: String? = "Search",largeTitle: Bool? = true,title: String,onSearch: @escaping (String)->(),onCancel: @escaping ()->()) {
31
+    init(view: AnyView, placeHolder: String? = NSLocalizedString("search", comment:""), largeTitle: Bool? = true, title: String, onSearch: @escaping (String)->(), onCancel: @escaping ()->(), onClick: @escaping ()->()) {
33
       
32
       
34
-        self.title = title
33
+        self.title = title // Inventory
35
         self.largeTitle = largeTitle!
34
         self.largeTitle = largeTitle!
36
         self.placeHolder = placeHolder!
35
         self.placeHolder = placeHolder!
37
         self.view = view
36
         self.view = view
38
         self.onSearch = onSearch
37
         self.onSearch = onSearch
39
         self.onCancel = onCancel
38
         self.onCancel = onCancel
39
+        self.onClick = onClick
40
     }
40
     }
41
     
41
     
42
     // Integrating UIKit Navigation Controller With SwiftUI View...
42
     // Integrating UIKit Navigation Controller With SwiftUI View...
89
         init(parent: CustomNavigationView) {
89
         init(parent: CustomNavigationView) {
90
             self.parent = parent
90
             self.parent = parent
91
         }
91
         }
92
+        func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
93
+            self.parent.onClick()
94
+            
95
+        }
92
         
96
         
93
         func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
97
         func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
94
             // when text changes....
98
             // when text changes....

+ 3
- 3
Comedores Sociales/View/FoodCardView.swift 파일 보기

26
                     
26
                     
27
                     VStack(alignment: .leading, spacing: 5) {
27
                     VStack(alignment: .leading, spacing: 5) {
28
                         
28
                         
29
-                        Text(item.name)
29
+                        Text(NSLocalizedString(item.name, comment:""))
30
                             .font(.title2)
30
                             .font(.title2)
31
                         
31
                         
32
                         Text(item.cuantity)
32
                         Text(item.cuantity)
40
                         
40
                         
41
                         Button(action: {show.toggle()}) {
41
                         Button(action: {show.toggle()}) {
42
                             
42
                             
43
-                            Text(show ? "Added" : "$" + String(item.priceLocal))
43
+                            Text(show ? NSLocalizedString("added", comment:"") : "$" + String(item.priceLocal))
44
                                 .fontWeight(.heavy)
44
                                 .fontWeight(.heavy)
45
                                 .padding(.vertical,8)
45
                                 .padding(.vertical,8)
46
                                 .padding(.horizontal,20)
46
                                 .padding(.horizontal,20)
48
                                 .clipShape(Capsule())
48
                                 .clipShape(Capsule())
49
                         }
49
                         }
50
                         
50
                         
51
-                        Text("Savings of $" + String(item.savings))
51
+                        Text(NSLocalizedString("savings", comment:"") + String(item.savings))
52
                             .font(.caption2)
52
                             .font(.caption2)
53
                             .foregroundColor(.green)
53
                             .foregroundColor(.green)
54
                     }
54
                     }

+ 91
- 0
Comedores Sociales/View/ProfileSummary.swift 파일 보기

1
+//
2
+//  ProfileView.swift
3
+//  Comedores Sociales
4
+//
5
+//  Created by Hector Carrion on 12/16/20.
6
+//
7
+
8
+import SwiftUI
9
+
10
+struct ProfileSummary: View {
11
+    @State var profile: Profile
12
+
13
+    var body: some View {
14
+        VStack(alignment: .leading, spacing: 10) {
15
+            HStack {
16
+                Image(systemName: "person.crop.circle")
17
+                    .font(.system(size: 100))
18
+                VStack(alignment: .leading, spacing: 5) {
19
+                    Text(profile.name)
20
+                        .bold()
21
+                        .font(.title)
22
+                    Text(profile.membership)
23
+                        .font(.headline)
24
+                    
25
+                }
26
+                
27
+            }.padding()
28
+            .frame(width: 350, height: 125, alignment: .topLeading)
29
+            .offset(x: -10, y: 10.0)
30
+            
31
+            HStack {
32
+                Image(systemName: "envelope")
33
+                    .font(.system(size: 20))
34
+                    .foregroundColor(.gray)
35
+                Text(profile.email)
36
+                    .font(.headline)
37
+                    .foregroundColor(.gray)
38
+            }.padding()
39
+            .offset(x: 0, y: 10.0)
40
+            HStack {
41
+                Image(systemName: "phone")
42
+                    .font(.system(size: 20))
43
+                    .foregroundColor(.gray)
44
+                Text(profile.phone)
45
+                    .font(.headline)
46
+                    .foregroundColor(.gray)
47
+            }.padding()
48
+            
49
+            HStack() {
50
+                VStack {
51
+                    Text(String(profile.hoursWorked))
52
+                        .font(.title)
53
+                        .fontWeight(/*@START_MENU_TOKEN@*/.bold/*@END_MENU_TOKEN@*/)
54
+                    Text(NSLocalizedString("hours_donated", comment:""))
55
+                        .foregroundColor(.gray)
56
+                }.padding()
57
+                
58
+                Spacer()
59
+                VStack {
60
+                    if profile.membershipStatus == .expired {
61
+                        Text(NSLocalizedString("expired", comment:""))
62
+                            .font(.title)
63
+                            .fontWeight(/*@START_MENU_TOKEN@*/.bold/*@END_MENU_TOKEN@*/)
64
+                            .foregroundColor(.red)
65
+                    } else if profile.membershipStatus == .valid {
66
+                        Text(NSLocalizedString("valid", comment:""))
67
+                            .font(.title)
68
+                            .fontWeight(/*@START_MENU_TOKEN@*/.bold/*@END_MENU_TOKEN@*/)
69
+                            .foregroundColor(.green)
70
+                    } else {
71
+                        Text(NSLocalizedString("unknown", comment:""))
72
+                            .font(.title)
73
+                            .fontWeight(/*@START_MENU_TOKEN@*/.bold/*@END_MENU_TOKEN@*/)
74
+                            .foregroundColor(.orange)
75
+                    }
76
+                    
77
+                    Text(NSLocalizedString("membership", comment:""))
78
+                        .foregroundColor(.gray)
79
+                }.padding()
80
+            }.padding()
81
+            .offset(x: 0, y: -10)
82
+            Spacer()
83
+        }
84
+    }
85
+}
86
+
87
+struct ProfileSummary_Previews: PreviewProvider {
88
+    static var previews: some View {
89
+        ProfileSummary(profile: Profile.default)
90
+    }
91
+}

+ 30
- 0
Comedores Sociales/View/ProfileView.swift 파일 보기

1
+//
2
+//  ProfileView.swift
3
+//  Comedores Sociales
4
+//
5
+//  Created by Hector Carrion on 12/16/20.
6
+//
7
+
8
+import SwiftUI
9
+
10
+struct ProfileView: View {
11
+    
12
+    @EnvironmentObject var profileVM: ProfileViewModel
13
+    
14
+    var body: some View {
15
+            VStack(alignment: .leading, spacing: 20) {
16
+                if profileVM.response == .unfetched {
17
+                    ProfileSummary(profile: Profile.default)
18
+                } else if profileVM.response == .success {
19
+                    ProfileSummary(profile: profileVM.profile)
20
+                }
21
+            }
22
+            .padding()
23
+        }
24
+}
25
+
26
+struct ProfileView_Previews: PreviewProvider {
27
+    static var previews: some View {
28
+        ProfileView()
29
+    }
30
+}

+ 39
- 17
Comedores Sociales/View/Search/SearchContainer.swift 파일 보기

9
 
9
 
10
 struct SearchContainer: View {
10
 struct SearchContainer: View {
11
     @State var filteredItems = foods
11
     @State var filteredItems = foods
12
+    @State var showingProfile: Bool = false
13
+    @EnvironmentObject var profileVM: ProfileViewModel
14
+    @State var hideButton = false
15
+    @State var disableButton = false
12
     
16
     
13
     var body: some View {
17
     var body: some View {
14
-
15
-        CustomNavigationView(view: AnyView(Search(filteredItems: $filteredItems)), placeHolder: "Search", largeTitle: true, title: "Inventory",
16
-                             
17
-            onSearch: { (txt) in
18
-
19
-            // filterting Data...
20
-            if txt != ""{
21
-                self.filteredItems = foods.filter{$0.name.lowercased().contains(txt.lowercased())}
22
-            }
23
-            else{
18
+        ZStack(alignment: .topTrailing) {
19
+            CustomNavigationView(view: AnyView(Search(filteredItems: $filteredItems)), placeHolder: NSLocalizedString("search", comment:""), largeTitle: true, title: NSLocalizedString("inventory", comment:""),
20
+                
21
+                onSearch: { (txt) in
22
+                // filterting Data...
23
+                if txt != ""{
24
+                    self.filteredItems = foods.filter{$0.name.lowercased().contains(txt.lowercased())}
25
+                }
26
+                else{
27
+                    self.filteredItems = foods
28
+                }
29
+                
30
+            }, onCancel: {
31
+                // Do Your Own Code When Search And Canceled....
24
                 self.filteredItems = foods
32
                 self.filteredItems = foods
25
-            }
26
-            
27
-        }, onCancel: {
28
-            // Do Your Own Code When Search And Canceled....
29
-            self.filteredItems = foods
33
+                self.hideButton = false
34
+                self.disableButton = false
35
+                
36
+            }, onClick: {
37
+                self.hideButton = true
38
+                self.disableButton = true
39
+            })
40
+            .ignoresSafeArea()
30
             
41
             
31
-        })
32
-        .ignoresSafeArea()
42
+            Button(action: {
43
+                self.showingProfile.toggle()
44
+                let token = UserToken(token: UserDefaults.standard.string(forKey: "token")!)
45
+                profileVM.fetchMember(token: token)
46
+            }) {
47
+                Image(systemName: "person.crop.circle")
48
+                    .font(.system(size: 30))
49
+                    .opacity(hideButton ? 0 : 1)
50
+            }.disabled(disableButton)
51
+            .offset(x: 0, y: -10)
52
+            .padding()
53
+            .sheet(isPresented: $showingProfile, content: {ProfileView()})
54
+        }
33
     }
55
     }
34
 }
56
 }
35
 
57
 

+ 53
- 0
en.lproj/Localizable.strings 파일 보기

1
+/* 
2
+  Localizable.strings
3
+  Comedores Sociales
4
+
5
+  Created by Hector Carrion on 12/17/20.
6
+  
7
+*/
8
+
9
+"hello_world" = "Hello, world!";
10
+"search" = "Search";
11
+"incorrect" = "Information incorrect, please try again";
12
+"incomplete" = "Fields incomplete";
13
+"enter_valid" = "Please enter a valid email and password";
14
+"login" = "Login";
15
+"register" = "Don't have an account? Register";
16
+"details" = "Details";
17
+"full_name" = "Full Name";
18
+"pass_conf" = "Password (confirmation)";
19
+"phone" = "Phone Number";
20
+"urb" = "Address";
21
+"street" = "Address (apt, suite, etc)";
22
+"city" = "City";
23
+"zip" = "Zip Code";
24
+"org" = "Company or Organization (optional)";
25
+"pos" = "Position (optional)";
26
+"reg_fail" = "Registration failed, please double-check all fields and try again";
27
+"reg" = "Register";
28
+"enter_all" = "Please enter a all required information";
29
+"pass_missmatch" = "Passwords do not match";
30
+"pass_retype" = "Please retype your password and try again";
31
+"inventory" = "Inventory";
32
+"hours_donated" = "Hours Donated";
33
+"membership" = "Membership";
34
+"added" = "Added";
35
+"savings" = "Savings of $";
36
+"valid" = "Valid";
37
+"expired" = "Expired";
38
+"unknown" = "Unknown";
39
+"Beans" = "Beans";
40
+"Carrots" = "Carrots";
41
+"Eggs" = "Eggs";
42
+"Malanga" = "Malanga";
43
+"Oatmeal" = "Oatmeal";
44
+"Pasta" = "Pasta";
45
+"Green Peppers" = "Green Peppers";
46
+"Pineapple" = "Pineapple";
47
+"Potatoes" = "Potatoes";
48
+"Rice" = "Rice";
49
+"Sausages" = "Sausages";
50
+"Vegetable Oil" = "Vegetable Oil";
51
+"Yellow Onions" = "Yellow Onions";
52
+"Yuca" = "Yuca";
53
+"Crackers" = "Crackers";

+ 53
- 0
es-419.lproj/Localizable.strings 파일 보기

1
+/* 
2
+  Localizable.strings
3
+  Comedores Sociales
4
+
5
+  Created by Hector Carrion on 12/17/20.
6
+  
7
+*/
8
+
9
+"hello_world" = "Hola mundo!";
10
+"search" = "Buscar";
11
+"incorrect" = "Información incorrecta, trate nuevamente";
12
+"incomplete" = "Campos incompletos";
13
+"enter_valid" = "Porfavor entre email y password válidos";
14
+"login" = "Entrar";
15
+"register" = "¿No tiene cuenta? Regístrese";
16
+"details" = "Detalles";
17
+"full_name" = "Nombre Completo";
18
+"pass_conf" = "Password (confirmación)";
19
+"phone" = "Número de Teléfono";
20
+"urb" = "Urbanización";
21
+"street" = "Calle";
22
+"city" = "Ciudad";
23
+"zip" = "Código Zip";
24
+"org" = "Compañía o Organización (opcional)";
25
+"pos" = "Posición (optional)";
26
+"reg_fail" = "Error al registrar, verifique todos los campos y trate nuevamente";
27
+"reg" = "Registrarme";
28
+"enter_all" = "Porfavor complete todos los campos requeridos";
29
+"pass_missmatch" = "Passwords no coinciden";
30
+"pass_retype" = "Porfavor reescriba su password y trate nuevamente";
31
+"inventory" = "Inventario";
32
+"hours_donated" = "Horas Donadas";
33
+"membership" = "Membresía";
34
+"added" = "Añadido";
35
+"savings" = "Ahorros de $";
36
+"valid" = "Válida";
37
+"expired" = "Expirada";
38
+"unknown" = "Desconocida";
39
+"Beans" = "Habichuelas";
40
+"Carrots" = "Zanahorias";
41
+"Eggs" = "Huevos";
42
+"Malanga" = "Malanga";
43
+"Oatmeal" = "Avena";
44
+"Pasta" = "Pasta";
45
+"Green Peppers" = "Pimiento Verde";
46
+"Pineapple" = "Piña";
47
+"Potatoes" = "Papas";
48
+"Rice" = "Arroz";
49
+"Sausages" = "Salchichas";
50
+"Vegetable Oil" = "Aceite Vegetal";
51
+"Yellow Onions" = "Cebolla Amarilla";
52
+"Yuca" = "Yuca";
53
+"Crackers" = "Galletas";

+ 53
- 0
es.lproj/Localizable.strings 파일 보기

1
+/* 
2
+  Localizable.strings
3
+  Comedores Sociales
4
+
5
+  Created by Hector Carrion on 12/17/20.
6
+  
7
+*/
8
+
9
+"hello_world" = "Hola mundo!";
10
+"search" = "Buscar";
11
+"incorrect" = "Información incorrecta, trate nuevamente";
12
+"incomplete" = "Campos incompletos";
13
+"enter_valid" = "Porfavor entre email y password válidos";
14
+"login" = "Entrar";
15
+"register" = "¿No tiene cuenta? Regístrese";
16
+"details" = "Detalles";
17
+"full_name" = "Nombre Completo";
18
+"pass_conf" = "Password (confirmación)";
19
+"phone" = "Número de Teléfono";
20
+"urb" = "Urbanización";
21
+"street" = "Calle";
22
+"city" = "Ciudad";
23
+"zip" = "Código Zip";
24
+"org" = "Compañía o Organización (opcional)";
25
+"pos" = "Posición (optional)";
26
+"reg_fail" = "Error al registrar, verifique todos los campos y trate nuevamente";
27
+"reg" = "Registrarme";
28
+"enter_all" = "Porfavor complete todos los campos requeridos";
29
+"pass_missmatch" = "Passwords no coinciden";
30
+"pass_retype" = "Porfavor reescriba su password y trate nuevamente";
31
+"inventory" = "Inventario";
32
+"hours_donated" = "Horas Donadas";
33
+"membership" = "Membresía";
34
+"added" = "Añadido";
35
+"savings" = "Ahorros de $";
36
+"valid" = "Válida";
37
+"expired" = "Expirada";
38
+"unknown" = "Desconocida";
39
+"Beans" = "Habichuelas";
40
+"Carrots" = "Zanahorias";
41
+"Eggs" = "Huevos";
42
+"Malanga" = "Malanga";
43
+"Oatmeal" = "Avena";
44
+"Pasta" = "Pasta";
45
+"Green Peppers" = "Pimiento Verde";
46
+"Pineapple" = "Piña";
47
+"Potatoes" = "Papas";
48
+"Rice" = "Arroz";
49
+"Sausages" = "Salchichas";
50
+"Vegetable Oil" = "Aceite Vegetal";
51
+"Yellow Onions" = "Cebolla Amarilla";
52
+"Yuca" = "Yuca";
53
+"Crackers" = "Galletas";