diff --git a/Swift Code Challenge.xcodeproj/project.pbxproj b/Swift Code Challenge.xcodeproj/project.pbxproj index 6663a69..c36b35d 100644 --- a/Swift Code Challenge.xcodeproj/project.pbxproj +++ b/Swift Code Challenge.xcodeproj/project.pbxproj @@ -14,6 +14,11 @@ 1E05E8E02868F16400B12456 /* Swift_Code_ChallengeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E05E8DF2868F16400B12456 /* Swift_Code_ChallengeTests.swift */; }; 1E05E8EA2868F16400B12456 /* Swift_Code_ChallengeUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E05E8E92868F16400B12456 /* Swift_Code_ChallengeUITests.swift */; }; 1E05E8EC2868F16400B12456 /* Swift_Code_ChallengeUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E05E8EB2868F16400B12456 /* Swift_Code_ChallengeUITestsLaunchTests.swift */; }; + 384EB99B286D00F200A2FE3C /* UsersListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 384EB99A286D00F200A2FE3C /* UsersListView.swift */; }; + 384EB99F286DC53A00A2FE3C /* UserDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 384EB99E286DC53A00A2FE3C /* UserDetailsView.swift */; }; + 384EB9A6286DC5EB00A2FE3C /* CircleImageComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 384EB9A5286DC5EB00A2FE3C /* CircleImageComponent.swift */; }; + 388650AE286CEF6E009A16EA /* UserModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 388650AD286CEF6E009A16EA /* UserModel.swift */; }; + 38FD67102886212B00B15515 /* UsersListComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38FD670F2886212B00B15515 /* UsersListComponent.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -45,6 +50,12 @@ 1E05E8E92868F16400B12456 /* Swift_Code_ChallengeUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Swift_Code_ChallengeUITests.swift; sourceTree = ""; }; 1E05E8EB2868F16400B12456 /* Swift_Code_ChallengeUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Swift_Code_ChallengeUITestsLaunchTests.swift; sourceTree = ""; }; 1E05E8F82868F24600B12456 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + 384EB99A286D00F200A2FE3C /* UsersListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsersListView.swift; sourceTree = ""; }; + 384EB99E286DC53A00A2FE3C /* UserDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDetailsView.swift; sourceTree = ""; }; + 384EB9A5286DC5EB00A2FE3C /* CircleImageComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleImageComponent.swift; sourceTree = ""; }; + 384EB9A7286DCA4C00A2FE3C /* Swift-Code-Challenge-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Swift-Code-Challenge-Info.plist"; sourceTree = SOURCE_ROOT; }; + 388650AD286CEF6E009A16EA /* UserModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserModel.swift; sourceTree = ""; }; + 38FD670F2886212B00B15515 /* UsersListComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsersListComponent.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -96,6 +107,9 @@ 1E05E8CD2868F16300B12456 /* Swift Code Challenge */ = { isa = PBXGroup; children = ( + 384EB9A7286DCA4C00A2FE3C /* Swift-Code-Challenge-Info.plist */, + 388650B0286CEF89009A16EA /* Views */, + 388650AF286CEF83009A16EA /* Models */, 1E05E8CE2868F16300B12456 /* Swift_Code_ChallengeApp.swift */, 1E05E8D02868F16300B12456 /* ContentView.swift */, 1E05E8D22868F16400B12456 /* Assets.xcassets */, @@ -129,6 +143,33 @@ path = "Swift Code ChallengeUITests"; sourceTree = ""; }; + 384EB9A2286DC59B00A2FE3C /* Components */ = { + isa = PBXGroup; + children = ( + 384EB9A5286DC5EB00A2FE3C /* CircleImageComponent.swift */, + 38FD670F2886212B00B15515 /* UsersListComponent.swift */, + ); + path = Components; + sourceTree = ""; + }; + 388650AF286CEF83009A16EA /* Models */ = { + isa = PBXGroup; + children = ( + 388650AD286CEF6E009A16EA /* UserModel.swift */, + ); + path = Models; + sourceTree = ""; + }; + 388650B0286CEF89009A16EA /* Views */ = { + isa = PBXGroup; + children = ( + 384EB9A2286DC59B00A2FE3C /* Components */, + 384EB99A286D00F200A2FE3C /* UsersListView.swift */, + 384EB99E286DC53A00A2FE3C /* UserDetailsView.swift */, + ); + path = Views; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -259,7 +300,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 384EB99F286DC53A00A2FE3C /* UserDetailsView.swift in Sources */, + 384EB9A6286DC5EB00A2FE3C /* CircleImageComponent.swift in Sources */, 1E05E8D12868F16300B12456 /* ContentView.swift in Sources */, + 388650AE286CEF6E009A16EA /* UserModel.swift in Sources */, + 384EB99B286D00F200A2FE3C /* UsersListView.swift in Sources */, + 38FD67102886212B00B15515 /* UsersListComponent.swift in Sources */, 1E05E8CF2868F16300B12456 /* Swift_Code_ChallengeApp.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -419,12 +465,12 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"Swift Code Challenge/Preview Content\""; - DEVELOPMENT_TEAM = Q6CQVYDYZ4; + DEVELOPMENT_TEAM = YM283LC5H4; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "Swift-Code-Challenge-Info.plist"; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; LD_RUNPATH_SEARCH_PATHS = ( @@ -448,12 +494,12 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"Swift Code Challenge/Preview Content\""; - DEVELOPMENT_TEAM = Q6CQVYDYZ4; + DEVELOPMENT_TEAM = YM283LC5H4; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "Swift-Code-Challenge-Info.plist"; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/Swift Code Challenge.xcodeproj/project.xcworkspace/xcuserdata/luizeduardomr.xcuserdatad/UserInterfaceState.xcuserstate b/Swift Code Challenge.xcodeproj/project.xcworkspace/xcuserdata/luizeduardomr.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..0cb47e4 Binary files /dev/null and b/Swift Code Challenge.xcodeproj/project.xcworkspace/xcuserdata/luizeduardomr.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Swift Code Challenge.xcodeproj/xcuserdata/luizeduardomr.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Swift Code Challenge.xcodeproj/xcuserdata/luizeduardomr.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..0c2131b --- /dev/null +++ b/Swift Code Challenge.xcodeproj/xcuserdata/luizeduardomr.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,6 @@ + + + diff --git a/Swift Code Challenge.xcodeproj/xcuserdata/luizeduardomr.xcuserdatad/xcschemes/xcschememanagement.plist b/Swift Code Challenge.xcodeproj/xcuserdata/luizeduardomr.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..9a1d4ab --- /dev/null +++ b/Swift Code Challenge.xcodeproj/xcuserdata/luizeduardomr.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + Swift Code Challenge.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/100.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/100.png new file mode 100644 index 0000000..15c4015 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/100.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/1024.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/1024.png new file mode 100644 index 0000000..bfe8ab8 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/1024.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/114.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/114.png new file mode 100644 index 0000000..351fcf0 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/114.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/120.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/120.png new file mode 100644 index 0000000..5d49ca8 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/120.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/128.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/128.png new file mode 100644 index 0000000..cfc656f Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/128.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/144.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/144.png new file mode 100644 index 0000000..5ee4d14 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/144.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/152.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/152.png new file mode 100644 index 0000000..1d59121 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/152.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/16.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/16.png new file mode 100644 index 0000000..c66926f Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/16.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/167.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/167.png new file mode 100644 index 0000000..146c74e Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/167.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/172.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/172.png new file mode 100644 index 0000000..6c5ea2e Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/172.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/180.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/180.png new file mode 100644 index 0000000..5665d31 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/180.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/196.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/196.png new file mode 100644 index 0000000..70fdd1c Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/196.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/20.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/20.png new file mode 100644 index 0000000..d842e08 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/20.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/216.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/216.png new file mode 100644 index 0000000..2a1b5e1 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/216.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/256.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/256.png new file mode 100644 index 0000000..874b7e4 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/256.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/29.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/29.png new file mode 100644 index 0000000..7c98cbb Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/29.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/32.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/32.png new file mode 100644 index 0000000..e63a1c3 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/32.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/40.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/40.png new file mode 100644 index 0000000..bd60f10 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/40.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/48.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/48.png new file mode 100644 index 0000000..9251b11 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/48.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/50.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/50.png new file mode 100644 index 0000000..2c4e83d Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/50.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/512.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/512.png new file mode 100644 index 0000000..51c618a Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/512.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/55.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/55.png new file mode 100644 index 0000000..fc7a0be Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/55.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/57.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/57.png new file mode 100644 index 0000000..6fd36b8 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/57.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/58.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/58.png new file mode 100644 index 0000000..0c44f6c Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/58.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/60.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/60.png new file mode 100644 index 0000000..a6c8bb2 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/60.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/64.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/64.png new file mode 100644 index 0000000..6b341ec Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/64.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/72.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/72.png new file mode 100644 index 0000000..02b4834 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/72.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/76.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/76.png new file mode 100644 index 0000000..d12799d Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/76.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/80.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/80.png new file mode 100644 index 0000000..1886a34 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/80.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/87.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/87.png new file mode 100644 index 0000000..d4b9595 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/87.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/88.png b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/88.png new file mode 100644 index 0000000..c49d9a7 Binary files /dev/null and b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/88.png differ diff --git a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/Contents.json b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/Contents.json index 9221b9b..04de9d4 100644 --- a/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Swift Code Challenge/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,94 +1,326 @@ { "images" : [ { + "filename" : "40.png", "idiom" : "iphone", "scale" : "2x", "size" : "20x20" }, { + "filename" : "60.png", "idiom" : "iphone", "scale" : "3x", "size" : "20x20" }, { + "filename" : "29.png", + "idiom" : "iphone", + "scale" : "1x", + "size" : "29x29" + }, + { + "filename" : "58.png", "idiom" : "iphone", "scale" : "2x", "size" : "29x29" }, { + "filename" : "87.png", "idiom" : "iphone", "scale" : "3x", "size" : "29x29" }, { + "filename" : "80.png", "idiom" : "iphone", "scale" : "2x", "size" : "40x40" }, { + "filename" : "120.png", "idiom" : "iphone", "scale" : "3x", "size" : "40x40" }, { + "filename" : "57.png", + "idiom" : "iphone", + "scale" : "1x", + "size" : "57x57" + }, + { + "filename" : "114.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "57x57" + }, + { + "filename" : "120.png", "idiom" : "iphone", "scale" : "2x", "size" : "60x60" }, { + "filename" : "180.png", "idiom" : "iphone", "scale" : "3x", "size" : "60x60" }, { + "filename" : "20.png", "idiom" : "ipad", "scale" : "1x", "size" : "20x20" }, { + "filename" : "40.png", "idiom" : "ipad", "scale" : "2x", "size" : "20x20" }, { + "filename" : "29.png", "idiom" : "ipad", "scale" : "1x", "size" : "29x29" }, { + "filename" : "58.png", "idiom" : "ipad", "scale" : "2x", "size" : "29x29" }, { + "filename" : "40.png", "idiom" : "ipad", "scale" : "1x", "size" : "40x40" }, { + "filename" : "80.png", "idiom" : "ipad", "scale" : "2x", "size" : "40x40" }, { + "filename" : "50.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "50x50" + }, + { + "filename" : "100.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "50x50" + }, + { + "filename" : "72.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "72x72" + }, + { + "filename" : "144.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "72x72" + }, + { + "filename" : "76.png", "idiom" : "ipad", "scale" : "1x", "size" : "76x76" }, { + "filename" : "152.png", "idiom" : "ipad", "scale" : "2x", "size" : "76x76" }, { + "filename" : "167.png", "idiom" : "ipad", "scale" : "2x", "size" : "83.5x83.5" }, { + "filename" : "1024.png", "idiom" : "ios-marketing", "scale" : "1x", "size" : "1024x1024" + }, + { + "filename" : "48.png", + "idiom" : "watch", + "role" : "notificationCenter", + "scale" : "2x", + "size" : "24x24", + "subtype" : "38mm" + }, + { + "filename" : "55.png", + "idiom" : "watch", + "role" : "notificationCenter", + "scale" : "2x", + "size" : "27.5x27.5", + "subtype" : "42mm" + }, + { + "filename" : "58.png", + "idiom" : "watch", + "role" : "companionSettings", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "87.png", + "idiom" : "watch", + "role" : "companionSettings", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "watch", + "role" : "notificationCenter", + "scale" : "2x", + "size" : "33x33", + "subtype" : "45mm" + }, + { + "filename" : "80.png", + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "40x40", + "subtype" : "38mm" + }, + { + "filename" : "88.png", + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "44x44", + "subtype" : "40mm" + }, + { + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "46x46", + "subtype" : "41mm" + }, + { + "filename" : "100.png", + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "50x50", + "subtype" : "44mm" + }, + { + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "51x51", + "subtype" : "45mm" + }, + { + "filename" : "172.png", + "idiom" : "watch", + "role" : "quickLook", + "scale" : "2x", + "size" : "86x86", + "subtype" : "38mm" + }, + { + "filename" : "196.png", + "idiom" : "watch", + "role" : "quickLook", + "scale" : "2x", + "size" : "98x98", + "subtype" : "42mm" + }, + { + "filename" : "216.png", + "idiom" : "watch", + "role" : "quickLook", + "scale" : "2x", + "size" : "108x108", + "subtype" : "44mm" + }, + { + "idiom" : "watch", + "role" : "quickLook", + "scale" : "2x", + "size" : "117x117", + "subtype" : "45mm" + }, + { + "filename" : "1024.png", + "idiom" : "watch-marketing", + "scale" : "1x", + "size" : "1024x1024" + }, + { + "filename" : "16.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "filename" : "32.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "filename" : "32.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "filename" : "64.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "filename" : "128.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "filename" : "256.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "filename" : "256.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "filename" : "512.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "filename" : "512.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "filename" : "1024.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" } ], "info" : { diff --git a/Swift Code Challenge/ContentView.swift b/Swift Code Challenge/ContentView.swift index e93e548..271258f 100644 --- a/Swift Code Challenge/ContentView.swift +++ b/Swift Code Challenge/ContentView.swift @@ -9,13 +9,6 @@ import SwiftUI struct ContentView: View { var body: some View { - Text("Hello, world!") - .padding() - } -} - -struct ContentView_Previews: PreviewProvider { - static var previews: some View { - ContentView() + UsersListView() } } diff --git a/Swift Code Challenge/Models/UserModel.swift b/Swift Code Challenge/Models/UserModel.swift new file mode 100644 index 0000000..ee0fae8 --- /dev/null +++ b/Swift Code Challenge/Models/UserModel.swift @@ -0,0 +1,64 @@ +// +// UserModel.swift +// Swift Code Challenge +// +// Created by Luiz Eduardo Mello dos Reis on 29/06/22. +// + +import Foundation + +struct PeopleResponse: Codable { + let results: [Person] + let info: Info +} + +struct Info: Codable { + let seed: String + let results, page: Int + let version: String +} + + +struct ID: Equatable, Hashable, Decodable, Encodable { + let value: String? +} + +struct Name: Equatable, Decodable, Hashable, Encodable { + let first: String? + let last: String? +} + +struct Picture: Equatable, Decodable, Hashable, Encodable { + let large: String? + let medium: String? + let thumbnail: String? +} + +struct coordinates: Equatable, Decodable, Hashable, Encodable { + let latitude: String? + let longitude: String? +} + +struct location: Equatable, Decodable, Hashable, Encodable { + let street: street? + let city: String? + let state: String? + let country: String? + let coordinates: coordinates? +} + +struct street: Equatable, Decodable, Encodable, Hashable { + let number: Int? + let name: String? +} + + +struct Person: Identifiable, Equatable, Decodable, Encodable, Hashable { + let id: ID + let name: Name + let picture: Picture + let email: String + let phone: String + let location: location + +} diff --git a/Swift Code Challenge/Views/Components/CircleImageComponent.swift b/Swift Code Challenge/Views/Components/CircleImageComponent.swift new file mode 100644 index 0000000..4b56208 --- /dev/null +++ b/Swift Code Challenge/Views/Components/CircleImageComponent.swift @@ -0,0 +1,18 @@ +// +// CircleImageComponent.swift +// Swift Code Challenge +// +// Created by Luiz Eduardo Mello dos Reis on 30/06/22. +// + +import SwiftUI + +struct CircleImage: View { + var userImage: String + var body: some View { + AsyncImage(url: URL(string: userImage)) + .aspectRatio(contentMode: .fit) + .clipShape(Circle()) + .shadow(radius: 10) + } +} diff --git a/Swift Code Challenge/Views/Components/UsersListComponent.swift b/Swift Code Challenge/Views/Components/UsersListComponent.swift new file mode 100644 index 0000000..6ad00ab --- /dev/null +++ b/Swift Code Challenge/Views/Components/UsersListComponent.swift @@ -0,0 +1,42 @@ +// +// UsersListComponent.swift +// Swift Code Challenge +// +// Created by Luiz Eduardo Mello dos Reis on 18/07/22. +// + +import SwiftUI + +struct UsersListComponent: View { + @ObservedObject private var coordinator = UsersListView.Coordinator() + var body: some View { + List { + ForEach(self.coordinator.dataModel.people, id: \.self) { user in + NavigationLink(destination: UserDetailsView(user: user)) { + HStack { + AsyncImage(url: URL(string: user.picture.thumbnail ?? "")) + .frame(width: 40, height: 40) + .scaledToFill() + .clipShape(Circle()).padding(.horizontal) + Text("\(user.name.first ?? "Luiz") \(user.name.last ?? "Mello")") + } + } + .navigationTitle("Users") + } + .onDelete(perform: removeRows) + .onMove(perform: move) + } + .refreshable { + await self.coordinator.refreshPeople() + } + } + func move(from source: IndexSet, to destination: Int) { + self.coordinator.dataModel.people.move(fromOffsets: source, toOffset: destination) + self.coordinator.dataChanged.toggle() + } + + func removeRows(at offsets: IndexSet) { + self.coordinator.dataModel.people.remove(atOffsets: offsets) + self.coordinator.dataChanged.toggle() + } +} diff --git a/Swift Code Challenge/Views/UserDetailsView.swift b/Swift Code Challenge/Views/UserDetailsView.swift new file mode 100644 index 0000000..a583ee5 --- /dev/null +++ b/Swift Code Challenge/Views/UserDetailsView.swift @@ -0,0 +1,46 @@ +// +// UserDetailsView.swift +// Swift Code Challenge +// +// Created by Luiz Eduardo Mello dos Reis on 30/06/22. +// +import SwiftUI +struct UserDetailsView: View { + @State var user: Person + var body: some View { + VStack { + CircleImage(userImage: user.picture.large ?? "") + .frame(width: 128, height: 128) + contentBody(user: user) + } + Spacer() + } +} +struct contentBody: View { + var user: Person + var body: some View { + VStack(spacing: 5) { + Text("\(user.name.first ?? "Luiz") \(user.name.last ?? "Mello")") + .bold() + .font(.title) + HStack { + Text("\(user.location.street?.name ?? "Street not found"),") + .font(.body) + .foregroundColor(.secondary) + Text("\(user.location.city ?? "City not found") - \(user.location.country ?? "Country not found")") + .font(.body) + .bold() + .foregroundColor(.secondary) + } + .padding(.bottom, 70) + Text("Email").bold() + Text(user.email) + .padding(.vertical, 10) + Text("Phone number").bold() + Text(user.phone) + } + } +} + + + diff --git a/Swift Code Challenge/Views/UsersListView.swift b/Swift Code Challenge/Views/UsersListView.swift new file mode 100644 index 0000000..05d1c3c --- /dev/null +++ b/Swift Code Challenge/Views/UsersListView.swift @@ -0,0 +1,69 @@ +// +// UsersListView.swift +// Swift Code Challenge +// +// Created by Luiz Eduardo Mello dos Reis on 29/06/22. +// +import SwiftUI +import Combine +struct UsersListView: View { + @ObservedObject private var coordinator = Self.Coordinator() + var body: some View { + ZStack { + NavigationView { + if (self.coordinator.dataModel.people.isEmpty) { + ProgressView() + .progressViewStyle(CircularProgressViewStyle()) + } else { + UsersListComponent() + .toolbar { + EditButton() + } + } + } + .navigationViewStyle(StackNavigationViewStyle()) + } + } +} + +extension UsersListView { + @MainActor + final class Coordinator: ObservableObject { + @Published var dataModel = DataModel() + @Published var fetchService = FetchService() + @Published var dataChanged: Bool = false + init() { + Task(priority: .userInitiated) { + do { + let newPeople = try await self.fetchService.refreshPeople() + self.dataModel.people = newPeople + self.dataChanged.toggle() + } catch { + print(error) + } + } + } + func refreshPeople() async { + Task { + if let newPeople = try? await self.fetchService.refreshPeople() { + self.dataModel.people = newPeople + self.dataChanged.toggle() + } + } + } + } + final class DataModel: ObservableObject { + @Published var people = [Person]() + } + actor FetchService { + func refreshPeople() async throws -> [Person] { + return try await self.refreshPeopleFromAPI() + } + func refreshPeopleFromAPI() async throws -> [Person] { + guard let url = URL(string: "https://randomuser.me/api/?results=100") else { return [] } + let request = URLRequest(url: url) + let (data, _) = try await URLSession.shared.data(for: request) + return try JSONDecoder().decode(PeopleResponse.self, from: data).results + } + } +} diff --git a/Swift-Code-Challenge-Info.plist b/Swift-Code-Challenge-Info.plist new file mode 100644 index 0000000..2f43c53 --- /dev/null +++ b/Swift-Code-Challenge-Info.plist @@ -0,0 +1,8 @@ + + + + + UILaunchScreen + + +