Commit a3226063b96dac3711cca7a9373184049894b7d7

Authored by Dmitriy Tymofyeyev
1 parent 0d304487

Add project1

Showing 221 changed files with 5519 additions and 3 deletions
  1 +//
  2 +// AppDelegate.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 30.05.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +@main
  11 +class AppDelegate: UIResponder, UIApplicationDelegate {
  12 +
  13 +
  14 +
  15 + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  16 + // Override point for customization after application launch.
  17 + return true
  18 + }
  19 +
  20 + // MARK: UISceneSession Lifecycle
  21 +
  22 + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
  23 + // Called when a new scene session is being created.
  24 + // Use this method to select a configuration to create the new scene with.
  25 + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
  26 + }
  27 +
  28 + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
  29 + // Called when the user discards a scene session.
  30 + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
  31 + // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
  32 + }
  33 +
  34 +
  35 +}
  36 +
... ...
  1 +{
  2 + "colors" : [
  3 + {
  4 + "idiom" : "universal"
  5 + }
  6 + ],
  7 + "info" : {
  8 + "author" : "xcode",
  9 + "version" : 1
  10 + }
  11 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "3Users.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "3 User@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "3 User@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "EmptySquere.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Rectangle 8@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Rectangle 8@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "FullSquere.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Group 33542@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Group 33542@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "iphone",
  5 + "scale" : "2x",
  6 + "size" : "20x20"
  7 + },
  8 + {
  9 + "idiom" : "iphone",
  10 + "scale" : "3x",
  11 + "size" : "20x20"
  12 + },
  13 + {
  14 + "idiom" : "iphone",
  15 + "scale" : "2x",
  16 + "size" : "29x29"
  17 + },
  18 + {
  19 + "idiom" : "iphone",
  20 + "scale" : "3x",
  21 + "size" : "29x29"
  22 + },
  23 + {
  24 + "idiom" : "iphone",
  25 + "scale" : "2x",
  26 + "size" : "40x40"
  27 + },
  28 + {
  29 + "idiom" : "iphone",
  30 + "scale" : "3x",
  31 + "size" : "40x40"
  32 + },
  33 + {
  34 + "idiom" : "iphone",
  35 + "scale" : "2x",
  36 + "size" : "60x60"
  37 + },
  38 + {
  39 + "idiom" : "iphone",
  40 + "scale" : "3x",
  41 + "size" : "60x60"
  42 + },
  43 + {
  44 + "idiom" : "ipad",
  45 + "scale" : "1x",
  46 + "size" : "20x20"
  47 + },
  48 + {
  49 + "idiom" : "ipad",
  50 + "scale" : "2x",
  51 + "size" : "20x20"
  52 + },
  53 + {
  54 + "idiom" : "ipad",
  55 + "scale" : "1x",
  56 + "size" : "29x29"
  57 + },
  58 + {
  59 + "idiom" : "ipad",
  60 + "scale" : "2x",
  61 + "size" : "29x29"
  62 + },
  63 + {
  64 + "idiom" : "ipad",
  65 + "scale" : "1x",
  66 + "size" : "40x40"
  67 + },
  68 + {
  69 + "idiom" : "ipad",
  70 + "scale" : "2x",
  71 + "size" : "40x40"
  72 + },
  73 + {
  74 + "idiom" : "ipad",
  75 + "scale" : "1x",
  76 + "size" : "76x76"
  77 + },
  78 + {
  79 + "idiom" : "ipad",
  80 + "scale" : "2x",
  81 + "size" : "76x76"
  82 + },
  83 + {
  84 + "idiom" : "ipad",
  85 + "scale" : "2x",
  86 + "size" : "83.5x83.5"
  87 + },
  88 + {
  89 + "idiom" : "ios-marketing",
  90 + "scale" : "1x",
  91 + "size" : "1024x1024"
  92 + }
  93 + ],
  94 + "info" : {
  95 + "author" : "xcode",
  96 + "version" : 1
  97 + }
  98 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Apartman.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Group 33613@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Group 33613@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Mask.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Mask Group@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Mask Group@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
1 1 {
2 2 "images" : [
3 3 {
4   - "filename" : "InterQR.png",
  4 + "filename" : "AUS.png",
5 5 "idiom" : "universal",
6 6 "scale" : "1x"
7 7 },
8 8 {
9   - "filename" : "Group 33497-2.png",
10 9 "idiom" : "universal",
11 10 "scale" : "2x"
12 11 },
13 12 {
14   - "filename" : "Group 33497-3.png",
15 13 "idiom" : "universal",
16 14 "scale" : "3x"
17 15 }
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "GB.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "icons8-великобритания-48.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "icons8-великобритания-96.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "USA.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Icons@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Icons@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "BackPointer.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Arrow - Left 2@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Arrow - Left 2@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Close.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Group 33489@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Group 33489@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "FlagPointer.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Stroke 1@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Stroke 1@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "NextPointer.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Stroke 3@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Stroke 3@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Gradient.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Rectangle 6@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Rectangle 6@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Home.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Home@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Home@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "LeftBlue.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Group 33668@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Group 33668@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "RightBlue.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Group 33606@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Group 33606@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "RightYellow.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Group 33607@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Group 33607@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Setting.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Setting@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Setting@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Lock.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Lock@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Lock@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Tick.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Stroke 3@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Stroke 3@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Bin.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Delete@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Delete@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Edit.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Edit@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Edit@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Heart.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Heart@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Heart@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "HeartRed.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Heart@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Heart@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Plus.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Group 33489@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Group 33489@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Gear.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Setting@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Setting@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Notification.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Notification@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Notification@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Password.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Password@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Password@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Profile.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Profile@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Profile@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Volume.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Volume Up@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Volume Up@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
  1 +{
  2 + "colors" : [
  3 + {
  4 + "color" : {
  5 + "color-space" : "srgb",
  6 + "components" : {
  7 + "alpha" : "1.000",
  8 + "blue" : "234",
  9 + "green" : "234",
  10 + "red" : "227"
  11 + }
  12 + },
  13 + "idiom" : "universal"
  14 + },
  15 + {
  16 + "appearances" : [
  17 + {
  18 + "appearance" : "luminosity",
  19 + "value" : "dark"
  20 + }
  21 + ],
  22 + "color" : {
  23 + "color-space" : "srgb",
  24 + "components" : {
  25 + "alpha" : "1.000",
  26 + "blue" : "1.000",
  27 + "green" : "1.000",
  28 + "red" : "1.000"
  29 + }
  30 + },
  31 + "idiom" : "universal"
  32 + }
  33 + ],
  34 + "info" : {
  35 + "author" : "xcode",
  36 + "version" : 1
  37 + }
  38 +}
... ...
  1 +{
  2 + "colors" : [
  3 + {
  4 + "color" : {
  5 + "color-space" : "srgb",
  6 + "components" : {
  7 + "alpha" : "1.000",
  8 + "blue" : "0.180",
  9 + "green" : "0.000",
  10 + "red" : "1.000"
  11 + }
  12 + },
  13 + "idiom" : "universal"
  14 + },
  15 + {
  16 + "appearances" : [
  17 + {
  18 + "appearance" : "luminosity",
  19 + "value" : "dark"
  20 + }
  21 + ],
  22 + "color" : {
  23 + "color-space" : "srgb",
  24 + "components" : {
  25 + "alpha" : "1.000",
  26 + "blue" : "1.000",
  27 + "green" : "1.000",
  28 + "red" : "1.000"
  29 + }
  30 + },
  31 + "idiom" : "universal"
  32 + }
  33 + ],
  34 + "info" : {
  35 + "author" : "xcode",
  36 + "version" : 1
  37 + }
  38 +}
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
  1 +{
  2 + "colors" : [
  3 + {
  4 + "color" : {
  5 + "color-space" : "srgb",
  6 + "components" : {
  7 + "alpha" : "1.000",
  8 + "blue" : "0.545",
  9 + "green" : "0.267",
  10 + "red" : "0.000"
  11 + }
  12 + },
  13 + "idiom" : "universal"
  14 + },
  15 + {
  16 + "appearances" : [
  17 + {
  18 + "appearance" : "luminosity",
  19 + "value" : "dark"
  20 + }
  21 + ],
  22 + "color" : {
  23 + "color-space" : "srgb",
  24 + "components" : {
  25 + "alpha" : "1.000",
  26 + "blue" : "1.000",
  27 + "green" : "1.000",
  28 + "red" : "1.000"
  29 + }
  30 + },
  31 + "idiom" : "universal"
  32 + }
  33 + ],
  34 + "info" : {
  35 + "author" : "xcode",
  36 + "version" : 1
  37 + }
  38 +}
... ...
  1 +{
  2 + "colors" : [
  3 + {
  4 + "color" : {
  5 + "color-space" : "srgb",
  6 + "components" : {
  7 + "alpha" : "1.000",
  8 + "blue" : "0.910",
  9 + "green" : "0.910",
  10 + "red" : "0.882"
  11 + }
  12 + },
  13 + "idiom" : "universal"
  14 + },
  15 + {
  16 + "appearances" : [
  17 + {
  18 + "appearance" : "luminosity",
  19 + "value" : "dark"
  20 + }
  21 + ],
  22 + "color" : {
  23 + "color-space" : "srgb",
  24 + "components" : {
  25 + "alpha" : "1.000",
  26 + "blue" : "1.000",
  27 + "green" : "1.000",
  28 + "red" : "1.000"
  29 + }
  30 + },
  31 + "idiom" : "universal"
  32 + }
  33 + ],
  34 + "info" : {
  35 + "author" : "xcode",
  36 + "version" : 1
  37 + }
  38 +}
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
  1 +{
  2 + "colors" : [
  3 + {
  4 + "color" : {
  5 + "color-space" : "srgb",
  6 + "components" : {
  7 + "alpha" : "1.000",
  8 + "blue" : "0.545",
  9 + "green" : "0.257",
  10 + "red" : "0.000"
  11 + }
  12 + },
  13 + "idiom" : "universal"
  14 + },
  15 + {
  16 + "appearances" : [
  17 + {
  18 + "appearance" : "luminosity",
  19 + "value" : "dark"
  20 + }
  21 + ],
  22 + "color" : {
  23 + "color-space" : "srgb",
  24 + "components" : {
  25 + "alpha" : "1.000",
  26 + "blue" : "1.000",
  27 + "green" : "1.000",
  28 + "red" : "1.000"
  29 + }
  30 + },
  31 + "idiom" : "universal"
  32 + }
  33 + ],
  34 + "info" : {
  35 + "author" : "xcode",
  36 + "version" : 1
  37 + }
  38 +}
... ...
  1 +{
  2 + "colors" : [
  3 + {
  4 + "color" : {
  5 + "color-space" : "srgb",
  6 + "components" : {
  7 + "alpha" : "1.000",
  8 + "blue" : "0.827",
  9 + "green" : "0.561",
  10 + "red" : "0.000"
  11 + }
  12 + },
  13 + "idiom" : "universal"
  14 + },
  15 + {
  16 + "appearances" : [
  17 + {
  18 + "appearance" : "luminosity",
  19 + "value" : "dark"
  20 + }
  21 + ],
  22 + "color" : {
  23 + "color-space" : "srgb",
  24 + "components" : {
  25 + "alpha" : "1.000",
  26 + "blue" : "1.000",
  27 + "green" : "1.000",
  28 + "red" : "1.000"
  29 + }
  30 + },
  31 + "idiom" : "universal"
  32 + }
  33 + ],
  34 + "info" : {
  35 + "author" : "xcode",
  36 + "version" : 1
  37 + }
  38 +}
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
  1 +{
  2 + "colors" : [
  3 + {
  4 + "color" : {
  5 + "color-space" : "srgb",
  6 + "components" : {
  7 + "alpha" : "1.000",
  8 + "blue" : "0.333",
  9 + "green" : "0.216",
  10 + "red" : "0.196"
  11 + }
  12 + },
  13 + "idiom" : "iphone"
  14 + },
  15 + {
  16 + "appearances" : [
  17 + {
  18 + "appearance" : "luminosity",
  19 + "value" : "dark"
  20 + }
  21 + ],
  22 + "color" : {
  23 + "color-space" : "srgb",
  24 + "components" : {
  25 + "alpha" : "1.000",
  26 + "blue" : "1.000",
  27 + "green" : "1.000",
  28 + "red" : "1.000"
  29 + }
  30 + },
  31 + "idiom" : "iphone"
  32 + }
  33 + ],
  34 + "info" : {
  35 + "author" : "xcode",
  36 + "version" : 1
  37 + },
  38 + "properties" : {
  39 + "localizable" : true
  40 + }
  41 +}
... ...
  1 +{
  2 + "colors" : [
  3 + {
  4 + "color" : {
  5 + "color-space" : "srgb",
  6 + "components" : {
  7 + "alpha" : "1.000",
  8 + "blue" : "0.725",
  9 + "green" : "0.725",
  10 + "red" : "0.725"
  11 + }
  12 + },
  13 + "idiom" : "universal"
  14 + },
  15 + {
  16 + "appearances" : [
  17 + {
  18 + "appearance" : "luminosity",
  19 + "value" : "dark"
  20 + }
  21 + ],
  22 + "color" : {
  23 + "color-space" : "srgb",
  24 + "components" : {
  25 + "alpha" : "1.000",
  26 + "blue" : "1.000",
  27 + "green" : "1.000",
  28 + "red" : "1.000"
  29 + }
  30 + },
  31 + "idiom" : "universal"
  32 + }
  33 + ],
  34 + "info" : {
  35 + "author" : "xcode",
  36 + "version" : 1
  37 + }
  38 +}
... ...
  1 +{
  2 + "colors" : [
  3 + {
  4 + "color" : {
  5 + "color-space" : "srgb",
  6 + "components" : {
  7 + "alpha" : "0.980",
  8 + "blue" : "0.180",
  9 + "green" : "0.000",
  10 + "red" : "1.000"
  11 + }
  12 + },
  13 + "idiom" : "universal"
  14 + },
  15 + {
  16 + "appearances" : [
  17 + {
  18 + "appearance" : "luminosity",
  19 + "value" : "dark"
  20 + }
  21 + ],
  22 + "color" : {
  23 + "color-space" : "srgb",
  24 + "components" : {
  25 + "alpha" : "1.000",
  26 + "blue" : "1.000",
  27 + "green" : "1.000",
  28 + "red" : "1.000"
  29 + }
  30 + },
  31 + "idiom" : "universal"
  32 + }
  33 + ],
  34 + "info" : {
  35 + "author" : "xcode",
  36 + "version" : 1
  37 + }
  38 +}
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
  1 +{
  2 + "colors" : [
  3 + {
  4 + "color" : {
  5 + "color-space" : "srgb",
  6 + "components" : {
  7 + "alpha" : "1.000",
  8 + "blue" : "0.942",
  9 + "green" : "0.929",
  10 + "red" : "1.000"
  11 + }
  12 + },
  13 + "idiom" : "universal"
  14 + },
  15 + {
  16 + "appearances" : [
  17 + {
  18 + "appearance" : "luminosity",
  19 + "value" : "dark"
  20 + }
  21 + ],
  22 + "color" : {
  23 + "color-space" : "srgb",
  24 + "components" : {
  25 + "alpha" : "1.000",
  26 + "blue" : "1.000",
  27 + "green" : "1.000",
  28 + "red" : "1.000"
  29 + }
  30 + },
  31 + "idiom" : "universal"
  32 + }
  33 + ],
  34 + "info" : {
  35 + "author" : "xcode",
  36 + "version" : 1
  37 + }
  38 +}
... ...
  1 +{
  2 + "colors" : [
  3 + {
  4 + "color" : {
  5 + "color-space" : "srgb",
  6 + "components" : {
  7 + "alpha" : "1.000",
  8 + "blue" : "0.954",
  9 + "green" : "0.954",
  10 + "red" : "0.954"
  11 + }
  12 + },
  13 + "idiom" : "universal"
  14 + },
  15 + {
  16 + "appearances" : [
  17 + {
  18 + "appearance" : "luminosity",
  19 + "value" : "dark"
  20 + }
  21 + ],
  22 + "color" : {
  23 + "color-space" : "srgb",
  24 + "components" : {
  25 + "alpha" : "1.000",
  26 + "blue" : "1.000",
  27 + "green" : "1.000",
  28 + "red" : "1.000"
  29 + }
  30 + },
  31 + "idiom" : "universal"
  32 + }
  33 + ],
  34 + "info" : {
  35 + "author" : "xcode",
  36 + "version" : 1
  37 + }
  38 +}
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "OffIndicator.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Ellipse 1@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Ellipse 1@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "OnIndicator.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Group 1@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Group 1@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Pointer.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Arrow - Right Circle@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Arrow - Right Circle@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "8D57D412-3800-4D7C-922A-FF392EC0594E_4_5005_c.jpeg",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Rectangle@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Rectangle@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "RectangleWithShadow.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Rectangle@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Rectangle@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Shield.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Mask Group@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Mask Group@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
... ...
  1 +//
  2 +// NetworkManager.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 25.06.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +import Alamofire
  10 +
  11 +class AuthService {
  12 + static let shared = AuthService()
  13 +
  14 + private init() {
  15 + }
  16 +
  17 + var networkToken: String? {
  18 + get {
  19 + return UserDefaults.standard.string(forKey: "NETWORK_TOKEN")
  20 + }
  21 +
  22 + set (newValue) {
  23 + UserDefaults.standard.set(newValue, forKey: "NETWORK_TOKEN")
  24 + }
  25 + }
  26 +
  27 + typealias InitWebServiceResponse = (InitResponseModel) -> Void
  28 + typealias StartWebServiceResponse = (StartResponseModel) -> Void
  29 + typealias VerifyWebServiceResponse = (VerifyResponseModel) -> Void
  30 + typealias LoginWebServiceResponse = (LoginResponseModel) -> Void
  31 + typealias LogoutWebServiceResponse = (LogoutResponseModel) -> Void
  32 +
  33 + typealias FailedHandler = (Error) -> Void
  34 +
  35 + func initRequest(model: InitRequestModel, completion: @escaping InitWebServiceResponse, fail: @escaping FailedHandler) {
  36 +
  37 + let params = ["device_uuid": model.deviceUUID,
  38 + "manufacturer": model.manufacturer,
  39 + "model": model.model,
  40 + "platform": model.platform,
  41 + "os_version": model.osVersion,
  42 + "app_version": model.appVersion] as [String: Any]
  43 +
  44 + AF.request(Constants.baseURL + APIRoutes.initURL.urlString, method: .post, parameters: params, encoding: JSONEncoding.default).responseDecodable(of: InitResponseModel.self ) { response in
  45 +
  46 + if let error = response.error {
  47 + fail(error)
  48 + } else {
  49 + if let res = response.value {
  50 + completion(res)
  51 + }
  52 + }
  53 + }
  54 + }
  55 +
  56 + func startRequest(model: StartRequestModel, completion: @escaping StartWebServiceResponse, fail: @escaping FailedHandler) {
  57 +
  58 + let params = ["email_or_number": model.emailOrNumber] as [String: Any]
  59 +
  60 + AF.request(Constants.baseURL + APIRoutes.startURL.urlString, method: .post, parameters: params, encoding: JSONEncoding.default).responseDecodable(of: StartResponseModel.self ) { response in
  61 +
  62 + if let error = response.error {
  63 + fail(error)
  64 + } else {
  65 + if let res = response.value {
  66 + completion(res)
  67 + }
  68 + }
  69 + }
  70 + }
  71 +
  72 + func verifyRequest(model: VerifyRequestModel, completion: @escaping VerifyWebServiceResponse, fail: @escaping FailedHandler) {
  73 +
  74 + let params = ["email_or_number": model.emailOrNumber,
  75 + "code": model.code,
  76 + "second_auth_token": model.secondAuthToken] as [String: Any]
  77 +
  78 + AF.request(Constants.baseURL + APIRoutes.verifyURL.urlString, method: .post, parameters: params, encoding: JSONEncoding.default).responseDecodable(of: VerifyResponseModel.self ) { response in
  79 +
  80 + if let error = response.error {
  81 + fail(error)
  82 + } else {
  83 + if let res = response.value {
  84 + self.networkToken = res.data.token
  85 + completion(res)
  86 + }
  87 + }
  88 + }
  89 + }
  90 +
  91 + func loginRequest(model: LoginRequestModel, success: @escaping LoginWebServiceResponse, fail: @escaping FailedHandler) {
  92 + let interceptor = InterQrRequestInterceptor()
  93 +
  94 + let params = ["device_uuid": model.deviceUUID] as [String: Any]
  95 +
  96 + AF.request(Constants.baseURL + APIRoutes.loginURL.urlString, method: .post, parameters: params, encoding: JSONEncoding.default, interceptor: interceptor).responseDecodable(of: LoginResponseModel.self ) { response in
  97 +
  98 + switch response.result {
  99 + case .failure(let error) :
  100 + fail(error)
  101 + case .success(let res) :
  102 + success(res)
  103 + }
  104 + }
  105 + }
  106 +
  107 + func logoutRequest(model: LogoutRequestModel, completion: @escaping LogoutWebServiceResponse, fail: @escaping FailedHandler) {
  108 + let interceptor = InterQrRequestInterceptor()
  109 + let params = ["device_uuid": model.deviceUUID] as [String: Any]
  110 +
  111 + AF.request(Constants.baseURL + APIRoutes.logoutURL.urlString, method: .post, parameters: params, encoding: JSONEncoding.default, interceptor: interceptor).responseDecodable(of: LogoutResponseModel.self ) { response in
  112 + guard let successCode = response.response?.statusCode else { return }
  113 + if let error = response.error {
  114 + fail(error)
  115 + } else {
  116 + if successCode == 200 {
  117 + guard let res = response.value else { return }
  118 + completion(res)
  119 + }
  120 + }
  121 + }
  122 + }
  123 +}
  124 +
  125 +class InterQrRequestInterceptor: RequestInterceptor {
  126 + func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
  127 + var urlRequest = urlRequest
  128 +// let headers = ["Authorization": "Bearer \(self.networkToken ?? "")"]
  129 +// let params = ["device_uuid": model.deviceUUID] as [String: Any]
  130 + if let token = AuthService.shared.networkToken {
  131 + urlRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
  132 + }
  133 +// if let deviceUUID =
  134 + completion(.success(urlRequest))
  135 + }
  136 +}
... ...
  1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2 +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
  3 + <dependencies>
  4 + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
  5 + <capability name="Safe area layout guides" minToolsVersion="9.0"/>
  6 + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
  7 + </dependencies>
  8 + <scenes>
  9 + <!--View Controller-->
  10 + <scene sceneID="EHf-IW-A2E">
  11 + <objects>
  12 + <viewController id="01J-lp-oVM" sceneMemberID="viewController">
  13 + <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
  14 + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
  15 + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
  16 + <color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
  17 + <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
  18 + </view>
  19 + </viewController>
  20 + <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
  21 + </objects>
  22 + <point key="canvasLocation" x="53" y="375"/>
  23 + </scene>
  24 + </scenes>
  25 +</document>
... ...
  1 +//
  2 +// Checkbox.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 07.06.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +import UIKit
  10 +class Checkbox: UIButton {
  11 + private let checkboxImageView: UIImageView = {
  12 + let obj = UIImageView()
  13 + return obj
  14 + }()
  15 +
  16 + private let checkBoxLabel: UILabel = {
  17 + let obj = UILabel()
  18 + obj.font = .skModernist(type: .regular, ofSize: 15)
  19 + return obj
  20 + }()
  21 +
  22 + override var isSelected: Bool {
  23 + didSet {
  24 + checkBoxLabel.textColor = isSelected ?
  25 + .TextColor.darkBlue :
  26 + .TextColor.lightGrey
  27 + checkboxImageView.image = isSelected ?
  28 + UIImage(named: .Image.onIndicator) :
  29 + UIImage(named: .Image.offIndicator)
  30 + }
  31 + }
  32 +
  33 + var checkboxTitle: String = "" {
  34 + didSet {
  35 + checkBoxLabel.text = checkboxTitle
  36 + }
  37 + }
  38 +
  39 + override init(frame: CGRect) {
  40 + super.init(frame: frame)
  41 + setup()
  42 + }
  43 +
  44 + required init?(coder: NSCoder) {
  45 + super.init(coder: coder)
  46 + setup()
  47 + }
  48 +
  49 + private func setup() {
  50 + isSelected = false
  51 +
  52 + addSubview(checkboxImageView)
  53 + addSubview(checkBoxLabel)
  54 +
  55 + checkboxImageView.snp.makeConstraints { make in
  56 + make.leading.equalToSuperview()
  57 + make.top.bottom.equalToSuperview()
  58 + }
  59 +
  60 + checkBoxLabel.snp.makeConstraints { make in
  61 + make.top.bottom.equalToSuperview()
  62 + make.trailing.equalToSuperview()
  63 + make.leading.equalTo(checkboxImageView.snp.trailing).offset(5)
  64 + }
  65 + }
  66 +}
... ...
  1 +//
  2 +// SquereCheckBox.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 17.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +class SquereCheckbox: UIButton {
  10 + private let checkboxImageView: UIImageView = {
  11 + let obj = UIImageView()
  12 + return obj
  13 + }()
  14 +
  15 + private let checkBoxLabel: UILabel = {
  16 + let obj = UILabel()
  17 + obj.font = .skModernist(type: .regular, ofSize: 12)
  18 + return obj
  19 + }()
  20 +
  21 + override var isSelected: Bool {
  22 + didSet {
  23 + checkBoxLabel.textColor = isSelected ?
  24 + .TextColor.darkBlue :
  25 + .TextColor.lightGrey
  26 + checkboxImageView.image = isSelected ?
  27 + UIImage(named: .Image.fullSquere) :
  28 + UIImage(named: .Image.emptySquere)
  29 + }
  30 + }
  31 +
  32 + var checkboxTitle: String = "" {
  33 + didSet {
  34 + checkBoxLabel.text = checkboxTitle
  35 + }
  36 + }
  37 +
  38 + override init(frame: CGRect) {
  39 + super.init(frame: frame)
  40 + setup()
  41 + }
  42 +
  43 + required init?(coder: NSCoder) {
  44 + super.init(coder: coder)
  45 + setup()
  46 + }
  47 +
  48 + private func setup() {
  49 + isSelected = false
  50 +
  51 + addSubview(checkboxImageView)
  52 + addSubview(checkBoxLabel)
  53 +
  54 + checkboxImageView.snp.makeConstraints { make in
  55 + make.leading.equalToSuperview()
  56 + make.top.bottom.equalToSuperview()
  57 + }
  58 +
  59 + checkBoxLabel.snp.makeConstraints { make in
  60 + make.top.bottom.equalToSuperview()
  61 + make.trailing.equalToSuperview()
  62 + make.leading.equalTo(checkboxImageView.snp.trailing).offset(10)
  63 + }
  64 + }
  65 +}
... ...
  1 +//
  2 +// TextFieldWithPadding.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 01.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class TextFieldWithPadding: UITextField {
  11 + var textPadding = UIEdgeInsets(
  12 + top: 0,
  13 + left: 0,
  14 + bottom: 0,
  15 + right: 0)
  16 +
  17 + override func textRect(forBounds bounds: CGRect) -> CGRect {
  18 + let rect = super.textRect(forBounds: bounds)
  19 + return rect.inset(by: textPadding)
  20 + }
  21 +
  22 + override func editingRect(forBounds bounds: CGRect) -> CGRect {
  23 + let rect = super.editingRect(forBounds: bounds)
  24 + return rect.inset(by: textPadding)
  25 + }
  26 +}
... ...
  1 +//
  2 +// Constant.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 25.06.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +
  10 +struct Constants {
  11 + static let baseURL = ""
  12 +}
  13 +
  14 +enum APIRoutes {
  15 + case initURL
  16 + case startURL
  17 + case verifyURL
  18 + case loginURL
  19 + case logoutURL
  20 +
  21 + var urlString: String {
  22 + switch self {
  23 +
  24 + case .initURL:
  25 + return ""
  26 + case .startURL:
  27 + return ""
  28 + case .verifyURL:
  29 + return ""
  30 + case .loginURL:
  31 + return ""
  32 + case .logoutURL:
  33 + return ""
  34 + }
  35 + }
  36 +}
  37 +
... ...
  1 +//
  2 +// Colors + extension.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 19.06.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +import UIKit
  10 +
  11 +extension UIColor {
  12 + enum TextColor {
  13 + static let darkBlue = UIColor(named: "DarkBlueText")
  14 + static let lightGrey = UIColor(named: "LightGreyText")
  15 + static let redError = UIColor(named: "RedErrorText")
  16 + }
  17 +
  18 + enum TextFieldColor {
  19 + static let general = UIColor(named: "GeneralTextField")
  20 + static let error = UIColor(named: "ErrorTextField")
  21 + }
  22 +
  23 + enum Background {
  24 + static let lightGrey = UIColor(named: "LightGreyBackground")
  25 + static let lightRed = UIColor(named: "LightRedBackgroud")
  26 + }
  27 +
  28 + enum GradientBlue {
  29 + static let left = UIColor(named: "Left")?.cgColor
  30 + static let right = UIColor(named: "Right")?.cgColor
  31 + }
  32 +
  33 +}
  34 +extension CGColor {
  35 + enum BorderColor {
  36 + static let lightGrey = UIColor(named: "LightGreyBorderColor")?.cgColor
  37 + static let lightBlue = UIColor(named: "LightBlueBorderColor")?.cgColor
  38 + }
  39 +
  40 + enum GradientBlue {
  41 + static let left = UIColor(named: "Left")?.cgColor
  42 + static let right = UIColor(named: "Right")?.cgColor
  43 + }
  44 +}
  45 +
  46 +extension CAGradientLayer {
  47 + enum GradientBlue {
  48 + static let left = UIColor(named: "Left")?.cgColor
  49 + static let right = UIColor(named: "Right")?.cgColor
  50 + }
  51 +}
... ...
  1 +//
  2 +// Strings + Extension.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 02.07.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +import UIKit
  10 +
  11 +extension String {
  12 + enum Text {
  13 + static let addResident = "Add resident"
  14 + static let residentName = "Resident name"
  15 + static let enterResidentName = "Enter resident name"
  16 + static let mobileNumber = "Mobile number"
  17 + static let enterResidentNumber = "Enter resident number"
  18 + static let manager = "Manager"
  19 + static let hidden = "Hidden"
  20 + static let enterYourVerificationCode = "Enter your\nverification code"
  21 + static let pleaseEnterValidCode = "Please, enter valid verification code"
  22 + static let verify = "Verify"
  23 + static let myApartName = "My apart name"
  24 + static let residents = "Residents"
  25 + static let chooseApartment = "Choose\napartman"
  26 + static let settings = "Settings"
  27 + static let logout = "Logout"
  28 + static let yourDisplayName = "Your display name"
  29 + static let nameWillBeDisplay = "This name will be displayed everywhere"
  30 + static let editResidents = "Edit residents"
  31 + static let editResidentsAndInfo = "Edit the residents and their information"
  32 + static let doNotDisturb = "Do not disturb"
  33 + static let youWillNotBeNotified = "You will not be notified of any calls for one day. Auto reset at midnight"
  34 + static let welcome = "Welcome"
  35 + static let myDoors = "My doors"
  36 + static let locked = "Locked"
  37 + static let home = "Home"
  38 + static let frontDoor = "Front Door"
  39 + static let selectYourCountry = "Select your country"
  40 + static let select = "Select"
  41 + static let hello = "Hello"
  42 + static let letsVerifyYourAccount = "Lets verify your \naccount"
  43 + static let chooseWhatToStartWith = "Choose what to start with"
  44 + static let email = "Email"
  45 + static let phoneNumber = "Phone Number"
  46 + static let enterYourEmailAddress = "Enter your email address"
  47 + static let exampleEmail = "Example: john.doe@gmail.com"
  48 + static let plusOne = "+1"
  49 + static let verificationCodeWillBeSentToYourEmail = "Verification code will be sent to your e-mail"
  50 + static let continueText = "Continue"
  51 + static let johnDoe = "John Doe"
  52 + static let userCode = "503331651"
  53 + static let enterYourPhoneNumber = "Enter your phone number"
  54 + static let verificationCodeWillBeSentToYourNumber = "Verification code will be sent to\nyour phone number"
  55 + static let apple = "Apple"
  56 + }
  57 +
  58 + enum Image {
  59 + static let close = "Close"
  60 + static let threeUsers = "3Users"
  61 + static let heart = "Heart"
  62 + static let heartRed = "HeartRed"
  63 + static let backPointer = "BackPointer"
  64 + static let interQR = "InterQR"
  65 + static let lock = "Lock"
  66 + static let RectangleWithShadow = "RectangleWithShadow"
  67 + static let tick = "Tick"
  68 + static let edit = "Edit"
  69 + static let bin = "Bin"
  70 + static let mask = "Mask"
  71 + static let apartman = "Apartman"
  72 + static let nextPointer = "NextPointer"
  73 + static let gear = "Gear"
  74 + static let profile = "Profile"
  75 + static let notification = "Notification"
  76 + static let setting = "Setting"
  77 + static let home = "Home"
  78 + static let gradient = "Gradient"
  79 + static let password = "Password"
  80 + static let rightStatus = "RightBlue"
  81 + static let leftBlue = "LeftBlue"
  82 + static let shield = "Shield"
  83 + static let USA = "USA"
  84 + static let flagPointer = "FlagPointer"
  85 + static let fullSquere = "FullSquere"
  86 + static let emptySquere = "EmptySquere"
  87 + static let pointer = "Pointer"
  88 + static let onIndicator = "OnIndicator"
  89 + static let offIndicator = "OffIndicator"
  90 + }
  91 +}
... ...
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>UIAppFonts</key>
  6 + <array>
  7 + <string>Sk-Modernist-Bold.otf</string>
  8 + <string>Sk-Modernist-Mono.otf</string>
  9 + <string>Sk-Modernist-Regular.otf</string>
  10 + </array>
  11 + <key>UIApplicationSceneManifest</key>
  12 + <dict>
  13 + <key>UIApplicationSupportsMultipleScenes</key>
  14 + <false/>
  15 + <key>UISceneConfigurations</key>
  16 + <dict>
  17 + <key>UIWindowSceneSessionRoleApplication</key>
  18 + <array>
  19 + <dict>
  20 + <key>UISceneConfigurationName</key>
  21 + <string>Default Configuration</string>
  22 + <key>UISceneDelegateClassName</key>
  23 + <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
  24 + </dict>
  25 + </array>
  26 + </dict>
  27 + </dict>
  28 +</dict>
  29 +</plist>
... ...
  1 +//
  2 +// AuthModel.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 25.06.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +
  10 +//MARK: - Init collection
  11 +struct InitRequestModel: Codable {
  12 + var deviceUUID: String
  13 + var manufacturer: String
  14 + var model: String
  15 + var platform: String
  16 + var osVersion: String
  17 + var appVersion: String
  18 +}
  19 +
  20 +struct InitResponseModel: Decodable {
  21 + var message: String
  22 +}
  23 +
  24 +//MARK: - Start2fa collection
  25 +struct StartRequestModel: Codable {
  26 + var emailOrNumber: String
  27 +
  28 + enum CodingKeys: String, CodingKey {
  29 + case emailOrNumber = "email_or_number"
  30 + }
  31 +}
  32 +
  33 +struct StartResponseModel: Decodable {
  34 + var message: String
  35 +}
  36 +
  37 +//MARK: - Verify2fa collection
  38 +struct VerifyRequestModel: Codable {
  39 + var emailOrNumber: String
  40 + var code: String
  41 + var secondAuthToken: String
  42 +
  43 + enum CodingKeys: String, CodingKey {
  44 + case emailOrNumber = "email_or_number"
  45 + case code
  46 + case secondAuthToken = "second_auth_token"
  47 + }
  48 +}
  49 +
  50 +struct VerifyResponseModel: Decodable {
  51 + var data: VerifyData
  52 + var message: String
  53 +}
  54 +
  55 +struct VerifyData: Decodable {
  56 + var token: String
  57 + var uuid: String
  58 +}
  59 +
  60 +//MARK: - Login collection
  61 +struct LoginRequestModel: Codable {
  62 + var deviceUUID: String
  63 +
  64 + enum CodingKeys: String, CodingKey {
  65 + case deviceUUID = "device_uuid"
  66 + }
  67 +}
  68 +
  69 +struct LoginResponseModel: Decodable {
  70 + var message: String?
  71 +}
  72 +
  73 +//MARK: - Logout collection
  74 +
  75 +struct LogoutRequestModel: Codable {
  76 + var deviceUUID: String
  77 +
  78 + enum CodingKeys: String, CodingKey {
  79 + case deviceUUID = "device_uuid"
  80 + }
  81 +}
  82 +
  83 +struct LogoutResponseModel: Decodable {
  84 + var message: String?
  85 +}
... ...
  1 +//
  2 +// PhonePickerModel.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 31.05.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +import UIKit
  10 +
  11 +struct PhonePickerModel {
  12 + let code: String
  13 + let countryCode: String
  14 + let title: String
  15 + let icon: UIImage
  16 +}
... ...
  1 +//
  2 +// ResidentModel.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 18.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +struct ResidentModel {
  11 + var name: String
  12 + var mobileNumber: String
  13 + var manager = false
  14 + var hidden = false
  15 + var heart = false
  16 +}
... ...
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<Workspace
  3 + version = "1.0">
  4 +</Workspace>
... ...
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>IDEDidComputeMac32BitWarning</key>
  6 + <true/>
  7 +</dict>
  8 +</plist>
... ...
  1 +//
  2 +// AddResidentsView.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 14.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class AddResidentsView: UIView {
  11 + var isShow: Bool = false
  12 +
  13 + let blurEffect: UIVisualEffectView = {
  14 + let blur = UIBlurEffect(style: UIBlurEffect.Style.systemMaterialDark)
  15 + let obj = UIVisualEffectView(effect: blur)
  16 + obj.autoresizingMask = [.flexibleWidth, .flexibleHeight]
  17 + obj.alpha = 0.9
  18 + obj.isUserInteractionEnabled = true
  19 + return obj
  20 + }()
  21 +
  22 + let transparentView: UIView = {
  23 + var obj = UIView()
  24 + obj.isUserInteractionEnabled = true
  25 + obj.backgroundColor = .black
  26 + obj.alpha = 0.5
  27 + return obj
  28 + }()
  29 +
  30 + var containerView: UIView = {
  31 + var obj = UIView()
  32 + obj.clipsToBounds = true
  33 + obj.layer.cornerRadius = 15
  34 + obj.backgroundColor = .white
  35 + return obj
  36 + }()
  37 +
  38 + var addResidentLabeL: UILabel = {
  39 + var obj = UILabel()
  40 + obj.text = .Text.addResident
  41 + obj.textColor = .TextColor.darkBlue
  42 + obj.font = .skModernist(type: .bold, ofSize: 24)
  43 + return obj
  44 + }()
  45 +
  46 + var closeButton: UIButton = {
  47 + var obj = UIButton()
  48 + obj.layer.cornerRadius = 13
  49 + obj.layer.borderWidth = 1
  50 + obj.layer.borderColor = .BorderColor.lightGrey
  51 + obj.setImage(UIImage(named: .Image.close), for: .normal)
  52 + return obj
  53 + }()
  54 +
  55 + var dividingLineView: UIView = {
  56 + var view = UIView()
  57 + view.backgroundColor = .Background.lightGrey
  58 + return view
  59 + }()
  60 +
  61 + var residentNameLabel: UILabel = {
  62 + var obj = UILabel()
  63 + obj.text = .Text.residentName
  64 + obj.font = .skModernist(type: .bold, ofSize: 14)
  65 + obj.textColor = .TextColor.darkBlue
  66 + return obj
  67 + }()
  68 +
  69 + var nameTextField: TextFieldWithPadding = {
  70 + var obj = TextFieldWithPadding()
  71 + obj.backgroundColor = .TextFieldColor.general
  72 + obj.textAlignment = .left
  73 + obj.layer.cornerRadius = 15
  74 + obj.placeholder = .Text.enterResidentName
  75 + obj.font = .skModernist(type: .regular, ofSize: 14)
  76 + obj.textPadding = UIEdgeInsets(top: 0, left: 22, bottom: 0, right: 22)
  77 + obj.returnKeyType = .done
  78 + return obj
  79 + }()
  80 +
  81 + var mobileNumberLabel: UILabel = {
  82 + var obj = UILabel()
  83 + obj.text = .Text.mobileNumber
  84 + obj.font = .skModernist(type: .bold, ofSize: 14)
  85 + obj.textColor = .TextColor.darkBlue
  86 + return obj
  87 + }()
  88 +
  89 + var mobileNumberTextField: TextFieldWithPadding = {
  90 + var obj = TextFieldWithPadding()
  91 + obj.backgroundColor = .TextFieldColor.general
  92 + obj.textAlignment = .left
  93 + obj.layer.cornerRadius = 15
  94 + obj.font = .skModernist(type: .regular, ofSize: 14)
  95 + obj.textPadding = UIEdgeInsets(top: 0, left: 22, bottom: 0, right: 45)
  96 + obj.placeholder = .Text.enterResidentNumber
  97 + obj.keyboardType = .phonePad
  98 + return obj
  99 + }()
  100 +
  101 + let contactListButton: UIButton = {
  102 + let obj = UIButton()
  103 + obj.setImage(UIImage(named: .Image.threeUsers), for: .normal)
  104 + return obj
  105 + }()
  106 +
  107 + var managerButton: SquereCheckbox = {
  108 + var obj = SquereCheckbox()
  109 + obj.checkboxTitle = .Text.manager
  110 + return obj
  111 + }()
  112 +
  113 + var hiddenButton: SquereCheckbox = {
  114 + var obj = SquereCheckbox()
  115 + obj.checkboxTitle = .Text.hidden
  116 + return obj
  117 + }()
  118 +
  119 + var heartButton: UIButton = {
  120 + var obj = UIButton()
  121 + obj.setImage(UIImage(named: .Image.heart), for: .normal)
  122 + obj.setImage(UIImage(named: .Image.heartRed), for: .selected)
  123 + return obj
  124 + }()
  125 +
  126 + var gradientBG: CAGradientLayer = {
  127 + let obj = CAGradientLayer()
  128 + var leftColor = CGColor.GradientBlue.left
  129 + var rightColor = CGColor.GradientBlue.right
  130 + obj.colors = [leftColor, rightColor]
  131 + obj.startPoint = CGPoint(x: 0, y: 0.5)
  132 + obj.endPoint = CGPoint(x: 1, y: 0.5)
  133 + return obj
  134 + }()
  135 +
  136 + var addResidentButton: UIButton = {
  137 + var obj = UIButton()
  138 + obj.setTitle(.Text.addResident, for: .normal)
  139 + obj.setTitleColor(.white, for: .normal)
  140 + obj.titleLabel?.font = .skModernist(type: .bold, ofSize: 16)
  141 + obj.clipsToBounds = true
  142 + obj.layer.masksToBounds = true
  143 + return obj
  144 + }()
  145 +
  146 + override init(frame: CGRect) {
  147 + super.init(frame: frame)
  148 + layout()
  149 + backgroundColor = .clear
  150 + }
  151 +
  152 + required init?(coder: NSCoder) {
  153 + fatalError("init(coder:) has not been implemented")
  154 + }
  155 +
  156 + func layout() {
  157 + isUserInteractionEnabled = true
  158 + addResidentButton.layer.insertSublayer(gradientBG, at: 0)
  159 +
  160 + addSubview(transparentView)
  161 + transparentView.addSubview(blurEffect)
  162 +
  163 + addSubview(containerView)
  164 + containerView.addSubview(addResidentLabeL)
  165 + containerView.addSubview(closeButton)
  166 + containerView.addSubview(dividingLineView)
  167 + containerView.addSubview(residentNameLabel)
  168 + containerView.addSubview(nameTextField)
  169 + containerView.addSubview(mobileNumberLabel)
  170 + containerView.addSubview(mobileNumberTextField)
  171 + mobileNumberTextField.addSubview(contactListButton)
  172 +
  173 + containerView.addSubview(managerButton)
  174 + containerView.addSubview(hiddenButton)
  175 + containerView.addSubview(heartButton)
  176 + containerView.addSubview(addResidentButton)
  177 +
  178 + transparentView.snp.makeConstraints {
  179 + $0.leading.top.trailing.bottom.equalToSuperview()
  180 + }
  181 +
  182 + containerView.snp.makeConstraints {
  183 + $0.leading.trailing.equalToSuperview().inset(25)
  184 + $0.centerY.equalTo(transparentView.snp.centerY)
  185 + }
  186 +
  187 + addResidentLabeL.snp.makeConstraints {
  188 + $0.top.equalToSuperview().offset(34)
  189 + $0.leading.equalToSuperview().offset(28)
  190 + }
  191 +
  192 + closeButton.snp.makeConstraints {
  193 + $0.centerY.equalTo(addResidentLabeL)
  194 + $0.trailing.equalToSuperview().offset(-30)
  195 + $0.height.width.equalTo(45)
  196 + }
  197 +
  198 + dividingLineView.snp.makeConstraints {
  199 + $0.trailing.leading.equalToSuperview()
  200 + $0.height.equalTo(1)
  201 + $0.top.equalTo(addResidentLabeL.snp.bottom).offset(34)
  202 + }
  203 +
  204 + residentNameLabel.snp.makeConstraints {
  205 + $0.top.equalTo(dividingLineView.snp.bottom).offset(24)
  206 + $0.leading.equalToSuperview().offset(44)
  207 + }
  208 +
  209 + nameTextField.snp.makeConstraints {
  210 + $0.leading.trailing.equalToSuperview().inset(30)
  211 + $0.top.equalTo(residentNameLabel.snp.bottom).offset(10)
  212 + $0.height.equalTo(47)
  213 + }
  214 +
  215 + mobileNumberLabel.snp.makeConstraints {
  216 + $0.leading.equalTo(residentNameLabel.snp.leading)
  217 + $0.top.equalTo(nameTextField.snp.bottom).offset(15)
  218 + }
  219 +
  220 + mobileNumberTextField.snp.makeConstraints {
  221 + $0.leading.trailing.equalToSuperview().inset(30)
  222 + $0.top.equalTo(mobileNumberLabel.snp.bottom).offset(10)
  223 + $0.height.equalTo(47)
  224 + }
  225 +
  226 + contactListButton.snp.makeConstraints {
  227 + $0.height.width.equalTo(24)
  228 + $0.centerY.equalToSuperview()
  229 + $0.trailing.equalToSuperview().offset(-19)
  230 + }
  231 +
  232 + managerButton.snp.makeConstraints {
  233 + $0.leading.equalToSuperview().offset(29)
  234 + $0.top.equalTo(mobileNumberTextField.snp.bottom).offset(30)
  235 + $0.height.equalTo(20)
  236 + }
  237 +
  238 + hiddenButton.snp.makeConstraints {
  239 + $0.top.equalTo(managerButton)
  240 + $0.leading.equalTo(managerButton.snp.trailing).offset(24)
  241 + $0.height.equalTo(20)
  242 + }
  243 +
  244 + heartButton.snp.makeConstraints {
  245 + $0.top.equalTo(managerButton)
  246 + $0.trailing.equalToSuperview().offset(-32.5)
  247 + }
  248 +
  249 + addResidentButton.snp.makeConstraints {
  250 + $0.top.equalTo(managerButton.snp.bottom).offset(43)
  251 + $0.leading.trailing.bottom.equalToSuperview()
  252 + $0.height.equalTo(64)
  253 + }
  254 + }
  255 +
  256 + override func layoutSubviews() {
  257 + super.layoutSubviews()
  258 + gradientBG.frame = addResidentButton.bounds
  259 + blurEffect.frame = transparentView.bounds
  260 + }
  261 +}
... ...
  1 +//
  2 +// AddResidentViewController.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 14.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +import ContactsUI
  10 +
  11 +class AddResidentsViewController: UIViewController {
  12 + var isKeyboardAppear = false
  13 +
  14 + var mainView = AddResidentsView()
  15 + weak var delegate: ResidentSavable?
  16 + var closeTap: UITapGestureRecognizer?
  17 +
  18 + override func loadView() {
  19 + view = mainView
  20 + }
  21 +
  22 + override func viewDidLoad() {
  23 + super.viewDidLoad()
  24 + initViewController()
  25 + }
  26 +
  27 + func initViewController() {
  28 + self.closeTap = UITapGestureRecognizer(target: self, action: #selector(didTapCloseButton))
  29 + if let closeTap = self.closeTap {
  30 + mainView.transparentView.addGestureRecognizer(closeTap)
  31 + }
  32 + addDoneButtonOnKeyboard()
  33 +
  34 + mainView.nameTextField.delegate = self
  35 + mainView.mobileNumberTextField.delegate = self
  36 +
  37 + mainView.closeButton.addTarget(self, action: #selector(didTapCloseButton), for: .touchUpInside)
  38 + mainView.managerButton.addTarget(self, action: #selector(didTapOnChangeableButtons(_:)), for: .touchUpInside)
  39 + mainView.hiddenButton.addTarget(self, action: #selector(didTapOnChangeableButtons(_:)), for: .touchUpInside)
  40 + mainView.heartButton.addTarget(self, action: #selector(didTapOnChangeableButtons(_:)), for: .touchUpInside)
  41 + mainView.addResidentButton.addTarget(self, action: #selector(didTapResidentButton), for: .touchUpInside)
  42 + mainView.contactListButton.addTarget(self, action: #selector(didTapContactListButton), for: .touchUpInside)
  43 +
  44 + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
  45 + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
  46 + }
  47 +
  48 + deinit {
  49 + NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
  50 + NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
  51 + }
  52 +
  53 + func addDoneButtonOnKeyboard() {
  54 + let doneToolbar: UIToolbar = UIToolbar(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
  55 + doneToolbar.barStyle = .default
  56 +
  57 + let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
  58 + let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(self.doneButtonAction))
  59 +
  60 + let items = [flexSpace, done]
  61 + doneToolbar.items = items
  62 + doneToolbar.sizeToFit()
  63 +
  64 + mainView.mobileNumberTextField.inputAccessoryView = doneToolbar
  65 + }
  66 +
  67 + @objc func doneButtonAction(){
  68 + mainView.mobileNumberTextField.resignFirstResponder()
  69 +
  70 + }
  71 +
  72 + func reloadView() {
  73 + mainView.mobileNumberTextField.reloadInputViews()
  74 + }
  75 +
  76 + @objc private func didTapCloseButton() {
  77 + dismiss(animated: true, completion: nil)
  78 + }
  79 +
  80 + @objc private func didTapResidentButton() {
  81 + if mainView.nameTextField.text == "" {
  82 + let alert = UIAlertController(title: "Enter name field", message: "", preferredStyle: .alert)
  83 + alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
  84 + present(alert, animated: true, completion: nil)
  85 + } else {
  86 + if mainView.mobileNumberTextField.text == "" {
  87 + let alert = UIAlertController(title: "Enter phone number field", message: "", preferredStyle: .alert)
  88 + alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
  89 + present(alert, animated: true, completion: nil)
  90 + } else {
  91 + didReceiveData()
  92 + dismiss(animated: true, completion: nil)
  93 + }
  94 + }
  95 + }
  96 +
  97 + func didReceiveData() {
  98 + guard let name = mainView.nameTextField.text,
  99 + let mobileNumber = mainView.mobileNumberTextField.text
  100 + else {
  101 + return
  102 + }
  103 + let model = ResidentModel(name: name,
  104 + mobileNumber: mobileNumber,
  105 + manager: mainView.managerButton.isSelected,
  106 + hidden: mainView.hiddenButton.isSelected,
  107 + heart: mainView.heartButton.isSelected)
  108 + delegate?.save(model)
  109 + }
  110 +
  111 + @objc private func didTapOnChangeableButtons(_ sender: SquereCheckbox) {
  112 + switch sender {
  113 + case mainView.managerButton :
  114 + if mainView.managerButton.isSelected == true {
  115 + mainView.managerButton.isSelected = false
  116 + } else {
  117 + mainView.managerButton.isSelected = true
  118 + }
  119 + case mainView.hiddenButton :
  120 + if mainView.hiddenButton.isSelected == true {
  121 + mainView.hiddenButton.isSelected = false
  122 + } else {
  123 + mainView.hiddenButton.isSelected = true
  124 + }
  125 + case mainView.heartButton :
  126 + if mainView.heartButton.isSelected == true {
  127 + mainView.heartButton.isSelected = false
  128 + } else {
  129 + mainView.heartButton.isSelected = true
  130 + }
  131 + default:
  132 + return
  133 + }
  134 + }
  135 +
  136 + @objc private func didTapContactListButton() {
  137 + presentContactPickerVC()
  138 + }
  139 +
  140 + func presentContactPickerVC() {
  141 + let viewController = ContactPickerViewController()
  142 + viewController.delegate = self
  143 + present(viewController, animated: true)
  144 + }
  145 +}
  146 +
  147 +//MARK: - Keyboard observer
  148 +extension AddResidentsViewController {
  149 + @objc private func keyboardWillShow(notification: NSNotification) {
  150 + let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double
  151 +
  152 + if !isKeyboardAppear {
  153 +
  154 + UIView.animate(withDuration: duration ?? 0) {
  155 + self.mainView.containerView.snp.updateConstraints { make in
  156 + make.centerY.equalTo(self.mainView.transparentView.snp.centerY).offset(-150)
  157 + }
  158 + self.mainView.layoutIfNeeded()
  159 + }
  160 + isKeyboardAppear = true
  161 + }
  162 + }
  163 +
  164 + @objc private func keyboardWillHide(notification: NSNotification) {
  165 + let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double
  166 +
  167 + if isKeyboardAppear {
  168 +
  169 + UIView.animate(withDuration: duration ?? 0) {
  170 + self.mainView.containerView.snp.updateConstraints { make in
  171 + make.centerY.equalTo(self.mainView.transparentView.snp.centerY)
  172 + }
  173 + self.mainView.layoutIfNeeded()
  174 + }
  175 + isKeyboardAppear = false
  176 + }
  177 + }
  178 +}
  179 +//MARK: - Contact picker delegate
  180 +extension AddResidentsViewController: CNContactPickerDelegate {
  181 + func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) {
  182 + let userPhoneNumbers:[CNLabeledValue<CNPhoneNumber>] = contact.phoneNumbers
  183 + let firstPhoneNumber:CNPhoneNumber = userPhoneNumbers[0].value
  184 +
  185 + mainView.mobileNumberTextField.text = firstPhoneNumber.stringValue
  186 + }
  187 +}
  188 +//MARK: - TextField delegate
  189 +extension AddResidentsViewController: UITextFieldDelegate {
  190 + func textFieldShouldReturn(_ textField: UITextField) -> Bool {
  191 + guard let text = mainView.nameTextField.text else { return true }
  192 + if text.isEmpty{
  193 + let alert = UIAlertController(title: "Enter name field", message: "", preferredStyle: .alert)
  194 + alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
  195 + present(alert, animated: true, completion: nil)
  196 + } else {
  197 + mainView.mobileNumberTextField.becomeFirstResponder()
  198 + }
  199 + return true
  200 + }
  201 +}
... ...
  1 +//
  2 +// ChooseApartmentsTableViewCell.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 14.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class ChooseApartmentsTableViewCell: UITableViewCell {
  11 + static let id = String(describing: ChooseApartmentsTableViewCell.self)
  12 +
  13 + var apartmanImage: UIImageView = {
  14 + var obj = UIImageView()
  15 + obj.image = UIImage(named: .Image.apartman)
  16 + return obj
  17 + }()
  18 +
  19 + var clientNameLabel: UILabel = {
  20 + var obj = UILabel()
  21 + obj.text = "Bares Family"
  22 + obj.textColor = .TextColor.darkBlue
  23 + obj.font = .skModernist(type: .bold, ofSize: 16)
  24 + return obj
  25 + }()
  26 +
  27 + var adressLabel: UILabel = {
  28 + var obj = UILabel()
  29 + obj.text = "200 5th Ave"
  30 + obj.textColor = .TextColor.lightGrey
  31 + obj.font = .skModernist(type: .regular, ofSize: 14)
  32 + return obj
  33 + }()
  34 +
  35 + var nextPointerImage: UIImageView = {
  36 + var obj = UIImageView()
  37 + obj.image = UIImage(named: .Image.nextPointer)
  38 + return obj
  39 + }()
  40 +
  41 + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
  42 + super.init(style: style, reuseIdentifier: reuseIdentifier)
  43 + setup()
  44 + }
  45 +
  46 + required init?(coder: NSCoder) {
  47 + fatalError("init(coder:) has not been implemented")
  48 + }
  49 +
  50 + func setup() {
  51 + selectionStyle = .none
  52 + contentView.addSubview(apartmanImage)
  53 + contentView.addSubview(clientNameLabel)
  54 + contentView.addSubview(adressLabel)
  55 + contentView.addSubview(nextPointerImage)
  56 +
  57 + apartmanImage.snp.makeConstraints {
  58 + $0.top.equalToSuperview().offset(8)
  59 + $0.leading.equalToSuperview()
  60 + }
  61 + clientNameLabel.snp.makeConstraints {
  62 + $0.top.equalToSuperview().offset(20)
  63 + $0.leading.equalTo(apartmanImage.snp.trailing).offset(18)
  64 + }
  65 + adressLabel.snp.makeConstraints {
  66 + $0.top.equalTo(clientNameLabel.snp.bottom).offset(5)
  67 + $0.leading.equalTo(clientNameLabel.snp.leading)
  68 + }
  69 + nextPointerImage.snp.makeConstraints {
  70 + $0.centerY.equalToSuperview()
  71 + $0.trailing.equalToSuperview().offset(-26)
  72 + }
  73 + }
  74 +}
... ...
  1 +//
  2 +// ChooseApartmentsView.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 14.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class ChooseApartmentView: UIView {
  11 +
  12 + var backButton: UIButton = {
  13 + var obj = UIButton()
  14 + obj.setImage(UIImage(named: .Image.backPointer), for: .normal)
  15 + obj.backgroundColor = .white
  16 + obj.layer.borderColor = .BorderColor.lightGrey
  17 + obj.layer.cornerRadius = 13
  18 + obj.layer.borderWidth = 1
  19 + return obj
  20 + }()
  21 +
  22 + var logoImage: UIImageView = {
  23 + var obj = UIImageView()
  24 + obj.image = UIImage(named: .Image.USA)
  25 + return obj
  26 + }()
  27 +
  28 + var tickImage: UIImageView = {
  29 + var obj = UIImageView()
  30 + obj.image = UIImage(named: .Image.mask)
  31 + return obj
  32 + }()
  33 +
  34 + let apartmentsLabel: UILabel = {
  35 + var obj = UILabel()
  36 + obj.font = .skModernist(type: .bold, ofSize: 35)
  37 + obj.text = .Text.chooseApartment
  38 + obj.numberOfLines = 0
  39 + return obj
  40 + }()
  41 +
  42 + var tableView: UITableView = {
  43 + var obj = UITableView()
  44 + obj.showsVerticalScrollIndicator = false
  45 + return obj
  46 + }()
  47 +
  48 + override init(frame: CGRect) {
  49 + super.init(frame: frame)
  50 + backgroundColor = .white
  51 + layout()
  52 + }
  53 +
  54 + required init?(coder: NSCoder) {
  55 + fatalError("init(coder:) has not been implemented")
  56 + }
  57 +
  58 + func layout() {
  59 + addSubview(backButton)
  60 + addSubview(logoImage)
  61 + addSubview(tickImage)
  62 + addSubview(apartmentsLabel)
  63 + addSubview(tableView)
  64 +
  65 + backButton.snp.makeConstraints {
  66 + $0.top.equalTo(snp.top).offset(66)
  67 + $0.leading.equalTo(snp.leading).offset(25)
  68 + $0.height.width.equalTo(45)
  69 + }
  70 + logoImage.snp.makeConstraints {
  71 + $0.leading.equalTo(backButton.snp.trailing).offset(20)
  72 + $0.top.equalTo(snp.top).offset(79)
  73 + }
  74 + tickImage.snp.makeConstraints {
  75 + $0.trailing.equalTo(snp.trailing)
  76 + $0.top.equalTo(snp.top).offset(106)
  77 + }
  78 + apartmentsLabel.snp.makeConstraints {
  79 + $0.leading.equalTo(backButton.snp.leading)
  80 + $0.top.equalTo(backButton.snp.bottom).offset(46)
  81 + }
  82 +
  83 + tableView.snp.makeConstraints { make in
  84 + make.leading.trailing.equalToSuperview()
  85 + make.top.equalTo(apartmentsLabel.snp.bottom).offset(85)
  86 + make.bottom.equalToSuperview()
  87 + }
  88 + }
  89 +}
... ...
  1 +//
  2 +// ChooseApartmentsViewController.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 14.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class ChooseApartmentsViewController: UIViewController {
  11 +
  12 + var mainView = ChooseApartmentView()
  13 +
  14 + override func loadView() {
  15 + view = mainView
  16 + }
  17 +
  18 + override func viewDidLoad() {
  19 + super.viewDidLoad()
  20 + initViewController()
  21 + }
  22 +
  23 + func initViewController() {
  24 + mainView.tableView.delegate = self
  25 + mainView.tableView.dataSource = self
  26 + mainView.backButton.addTarget(self, action: #selector(backToSettingsVC), for: .touchUpInside)
  27 + mainView.tableView.register(ChooseApartmentsTableViewCell.self, forCellReuseIdentifier: ChooseApartmentsTableViewCell.id)
  28 + }
  29 +
  30 + @objc func backToSettingsVC() {
  31 + navigationController?.popViewController(animated: true)
  32 + }
  33 +}
  34 +extension ChooseApartmentsViewController: UITableViewDelegate, UITableViewDataSource {
  35 + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  36 + 3
  37 + }
  38 +
  39 + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  40 + guard let cell = tableView.dequeueReusableCell(withIdentifier: ChooseApartmentsTableViewCell.id, for: indexPath) as? ChooseApartmentsTableViewCell else { return UITableViewCell() }
  41 +// cell.configureWithItem(doors[indexPath.row])
  42 + return cell
  43 + }
  44 +
  45 + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
  46 + 87
  47 + }
  48 +
  49 + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  50 + let vc = ResidentsViewController()
  51 + navigationController?.pushViewController(vc, animated: true)
  52 + }
  53 +}
... ...
  1 +//
  2 +// ContactPickerViewController.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 17.06.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +import UIKit
  10 +import ContactsUI
  11 +
  12 +class ContactPickerViewController: CNContactPickerViewController {
  13 + var phoneNumber = ""
  14 +}
  15 +
  16 +//MARK: - Contact picker delegate
  17 +extension ContactPickerViewController: CNContactPickerDelegate {
  18 + func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) {
  19 + phoneNumber = "\(contact.phoneNumbers)"
  20 +
  21 + }
  22 +}
... ...
  1 +//
  2 +// HomeTableViewCell.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 08.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class HomeTableViewCell: UITableViewCell {
  11 + static let id = String(describing: HomeTableViewCell.self)
  12 +
  13 + var containerView: UIView = {
  14 + var obj = UIView()
  15 + obj.layer.cornerRadius = 15
  16 + obj.layer.borderWidth = 1
  17 + obj.layer.borderColor = .BorderColor.lightGrey
  18 + return obj
  19 + }()
  20 +
  21 + var leftStatusImage: UIImageView = {
  22 + var obj = UIImageView()
  23 + obj.image = UIImage(named: .Image.leftBlue)
  24 + obj.contentMode = .scaleAspectFill
  25 + return obj
  26 + }()
  27 +
  28 + var doorNameLabel: UILabel = {
  29 + var obj = UILabel()
  30 + obj.font = .skModernist(type: .bold, ofSize: 16)
  31 + obj.textColor = .TextColor.darkBlue
  32 + obj.text = .Text.frontDoor
  33 + return obj
  34 + }()
  35 +
  36 + var doorLocationLabel: UILabel = {
  37 + var obj = UILabel()
  38 + obj.textColor = .TextColor.lightGrey
  39 + obj.font = .skModernist(type: .regular, ofSize: 14)
  40 + obj.text = .Text.home
  41 + return obj
  42 + }()
  43 +
  44 + var lockStatusLabel: UILabel = {
  45 + var obj = UILabel()
  46 + obj.textColor = .TextColor.darkBlue
  47 + obj.font = .skModernist(type: .bold, ofSize: 15)
  48 + obj.text = .Text.locked
  49 + return obj
  50 + }()
  51 +
  52 + var rightStatusImage: UIImageView = {
  53 + var obj = UIImageView()
  54 + obj.image = UIImage(named: .Image.rightStatus)
  55 + return obj
  56 + }()
  57 +
  58 + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
  59 + super.init(style: style, reuseIdentifier: reuseIdentifier)
  60 + setup()
  61 + }
  62 +
  63 + required init?(coder: NSCoder) {
  64 + fatalError("init(coder:) has not been implemented")
  65 + }
  66 +
  67 + func setup() {
  68 + selectionStyle = .none
  69 +
  70 + addSubview(containerView)
  71 + containerView.addSubview(leftStatusImage)
  72 + containerView.addSubview(doorNameLabel)
  73 + containerView.addSubview(doorLocationLabel)
  74 + containerView.addSubview(lockStatusLabel)
  75 + containerView.addSubview(rightStatusImage)
  76 +
  77 + containerView.snp.makeConstraints {
  78 + $0.leading.trailing.equalToSuperview()
  79 + $0.bottom.equalToSuperview().offset(-8)
  80 + $0.top.equalToSuperview().offset(8)
  81 + }
  82 +
  83 + leftStatusImage.snp.makeConstraints {
  84 + $0.top.equalTo(containerView.snp.top).offset(19)
  85 + $0.leading.equalTo(containerView.snp.leading).offset(23)
  86 + $0.height.width.equalTo(41)
  87 + }
  88 +
  89 + doorNameLabel.snp.makeConstraints {
  90 + $0.top.equalTo(snp.top).offset(22)
  91 + $0.leading.equalTo(leftStatusImage.snp.trailing).offset(14)
  92 + }
  93 +
  94 + doorLocationLabel.snp.makeConstraints {
  95 + $0.top.equalTo(doorNameLabel.snp.bottom)
  96 + $0.leading.equalTo(doorNameLabel.snp.leading)
  97 + }
  98 +
  99 + lockStatusLabel.snp.makeConstraints {
  100 + $0.bottom.equalTo(snp.bottom).offset(-15)
  101 + $0.centerX.equalTo(snp.centerX)
  102 + }
  103 +
  104 + rightStatusImage.snp.makeConstraints {
  105 + $0.trailing.equalTo(snp.trailing).offset(-16)
  106 + $0.top.equalTo(snp.top).offset(19)
  107 + }
  108 + }
  109 +}
  110 +
... ...
  1 +//
  2 +// HomeView.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 07.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class HomeView: UIView {
  11 + var logoView: UIImageView = {
  12 + var obj = UIImageView()
  13 + obj.image = UIImage(named: .Image.USA)
  14 + return obj
  15 + }()
  16 +
  17 + var settingsButton: UIButton = {
  18 + var obj = UIButton()
  19 + obj.setImage(UIImage(named: .Image.setting), for: .normal)
  20 + obj.layer.borderWidth = 1
  21 + obj.layer.borderColor = .BorderColor.lightGrey
  22 + obj.layer.cornerRadius = 13
  23 + return obj
  24 + }()
  25 +
  26 + var homeImage: UIImageView = {
  27 + var obj = UIImageView()
  28 + obj.image = UIImage(named: .Image.home)
  29 + return obj
  30 + }()
  31 +
  32 + var welcomeLabel: UILabel = {
  33 + var obj = UILabel()
  34 + obj.font = .skModernist(type: .bold, ofSize: 35)
  35 + obj.text = .Text.welcome
  36 + return obj
  37 + }()
  38 +
  39 + var doorsLabel: UILabel = {
  40 + var obj = UILabel()
  41 + obj.font = .skModernist(type: .bold, ofSize: 20)
  42 + obj.text = .Text.myDoors
  43 + return obj
  44 + }()
  45 +
  46 + var tableView: UITableView = {
  47 + var obj = UITableView()
  48 + obj.separatorStyle = .none
  49 + obj.showsVerticalScrollIndicator = false
  50 + return obj
  51 + }()
  52 +
  53 + var gradientView: UIImageView = {
  54 + var obj = UIImageView()
  55 + obj.image = UIImage(named: .Image.gradient)
  56 + return obj
  57 + }()
  58 +
  59 + var passwordButton: UIButton = {
  60 + var obj = UIButton()
  61 + obj.setImage(UIImage(named: .Image.password), for: .normal)
  62 + return obj
  63 + }()
  64 +
  65 + override init(frame: CGRect) {
  66 + super.init(frame: frame)
  67 + backgroundColor = .white
  68 + setup()
  69 + }
  70 +
  71 + required init?(coder: NSCoder) {
  72 + fatalError("init(coder:) has not been implemented")
  73 + }
  74 +
  75 + func setup() {
  76 + addSubview(logoView)
  77 + addSubview(settingsButton)
  78 + addSubview(welcomeLabel)
  79 + addSubview(homeImage)
  80 + addSubview(doorsLabel)
  81 + addSubview(tableView)
  82 + addSubview(gradientView)
  83 + gradientView.addSubview(passwordButton)
  84 +
  85 + logoView.snp.makeConstraints {
  86 + $0.top.equalTo(77)
  87 + $0.leading.equalTo(24)
  88 + }
  89 +
  90 + settingsButton.snp.makeConstraints {
  91 + $0.top.equalTo(snp.top).offset(63)
  92 + $0.trailing.equalTo(snp.trailing).offset(-27)
  93 + $0.height.width.equalTo(45)
  94 + }
  95 +
  96 + welcomeLabel.snp.makeConstraints {
  97 + $0.top.equalTo(logoView.snp.bottom).offset(63)
  98 + $0.leading.equalTo(logoView.snp.leading)
  99 + }
  100 +
  101 + homeImage.snp.makeConstraints {
  102 + $0.top.equalTo(settingsButton.snp.bottom)
  103 + $0.trailing.equalTo(snp.trailing).offset(5)
  104 + }
  105 +
  106 + doorsLabel.snp.makeConstraints {
  107 + $0.top.equalTo(homeImage.snp.bottom).offset(31)
  108 + $0.leading.equalTo(logoView.snp.leading)
  109 + }
  110 +
  111 + tableView.snp.makeConstraints {
  112 + $0.top.equalTo(doorsLabel.snp.bottom).offset(28)
  113 + $0.leading.equalTo(snp.leading).offset(20)
  114 + $0.trailing.equalTo(snp.trailing).offset(-27)
  115 + $0.bottom.equalToSuperview()
  116 + }
  117 +
  118 + gradientView.snp.makeConstraints {
  119 + $0.leading.trailing.bottom.equalToSuperview()
  120 + $0.height.equalTo(75)
  121 + }
  122 +
  123 + passwordButton.snp.makeConstraints {
  124 + $0.trailing.equalTo(gradientView.snp.trailing).offset(-48)
  125 + $0.bottom.equalTo(gradientView.snp.bottom).offset(-18)
  126 + $0.height.width.equalTo(18.5)
  127 + }
  128 + }
  129 +}
... ...
  1 +//
  2 +// HomeViewController.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 07.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class HomeViewController: UIViewController {
  11 + var mainView = HomeView()
  12 +
  13 + override func loadView() {
  14 + view = mainView
  15 + }
  16 +
  17 + override func viewDidLoad() {
  18 + initViewController()
  19 + }
  20 +
  21 + private func initViewController() {
  22 + mainView.tableView.delegate = self
  23 + mainView.tableView.dataSource = self
  24 + mainView.tableView.register(HomeTableViewCell.self, forCellReuseIdentifier: HomeTableViewCell.id)
  25 + mainView.settingsButton.addTarget(self, action: #selector(didShowSettingsVC), for: .touchUpInside)
  26 + }
  27 +}
  28 +
  29 +extension HomeViewController {
  30 + @objc private func didShowSettingsVC() {
  31 + let vc = SettingsViewController()
  32 + navigationController?.pushViewController(vc, animated: true)
  33 + }
  34 +}
  35 +
  36 +extension HomeViewController: UITableViewDelegate, UITableViewDataSource {
  37 +
  38 + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  39 + 5
  40 + }
  41 +
  42 + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  43 + guard let cell = tableView.dequeueReusableCell(withIdentifier: HomeTableViewCell.id, for: indexPath) as? HomeTableViewCell else { return UITableViewCell() }
  44 + return cell
  45 + }
  46 +
  47 + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
  48 + 120
  49 + }
  50 +
  51 + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  52 + print("✅")
  53 + }
  54 +
  55 +
  56 +}
... ...
  1 +//
  2 +// CodeVerificationView.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 03.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class CodeVerificationView: UIView {
  11 + var containerView: UIView = {
  12 + var obj = UIView()
  13 + return obj
  14 + }()
  15 +
  16 + var backButton: UIButton = {
  17 + var obj = UIButton()
  18 + obj.setImage(UIImage(named: .Image.backPointer), for: .normal)
  19 + obj.backgroundColor = .white
  20 + obj.layer.borderColor = .BorderColor.lightGrey
  21 + obj.layer.cornerRadius = 13
  22 + obj.layer.borderWidth = 1
  23 + return obj
  24 + }()
  25 +
  26 + var logoImage: UIImageView = {
  27 + var obj = UIImageView()
  28 + obj.image = UIImage(named: .Image.USA)
  29 + return obj
  30 + }()
  31 +
  32 + var shieldImage: UIImageView = {
  33 + var obj = UIImageView()
  34 + obj.image = UIImage(named: .Image.lock)
  35 + return obj
  36 + }()
  37 +
  38 + var descriptionLabel: UILabel = {
  39 + var obj = UILabel()
  40 + obj.font = .skModernist(type: .bold, ofSize: 35)
  41 + obj.text = .Text.enterYourVerificationCode
  42 + obj.numberOfLines = 2
  43 + return obj
  44 + }()
  45 +
  46 + let otpView: OTPView = {
  47 + let obj = OTPView()
  48 + return obj
  49 + }()
  50 +
  51 + var errorAlertLabel: UILabel = {
  52 + var obj = UILabel()
  53 + obj.text = .Text.pleaseEnterValidCode
  54 + obj.font = .skModernist(type: .regular, ofSize: 14)
  55 + obj.textColor = UIColor(red: 255/255, green: 0/255, blue: 46/255, alpha: 1)
  56 + obj.isHidden = true
  57 + return obj
  58 + }()
  59 +
  60 + var verifyButton: UIButton = {
  61 + var obj = UIButton()
  62 + obj.setImage(UIImage(named: .Image.RectangleWithShadow), for: .normal)
  63 + return obj
  64 + }()
  65 +
  66 + var verifyLabel: UILabel = {
  67 + var obj = UILabel()
  68 + obj.font = UIFont(name: SkModernistFontType.bold.rawValue, size: 16)
  69 + obj.textColor = .white
  70 + obj.text = .Text.verify
  71 + return obj
  72 + }()
  73 +
  74 + var tickImage: UIImageView = {
  75 + var obj = UIImageView()
  76 + obj.image = UIImage(named: .Image.tick)
  77 + return obj
  78 + }()
  79 +
  80 + let spinner: UIActivityIndicatorView = {
  81 + var obj = UIActivityIndicatorView(style: .large)
  82 + obj.hidesWhenStopped = true
  83 + return obj
  84 + }()
  85 +
  86 + let loadingView: UIView = {
  87 + var obj = UIView()
  88 + obj.alpha = 0.25
  89 + obj.backgroundColor = .black
  90 + obj.clipsToBounds = true
  91 + obj.layer.cornerRadius = 13
  92 + return obj
  93 + }()
  94 +
  95 + override init(frame: CGRect) {
  96 + super.init(frame: frame)
  97 + setup()
  98 + }
  99 +
  100 + required init?(coder: NSCoder) {
  101 + fatalError("init(coder:) has not been implemented")
  102 + }
  103 +
  104 + func setup() {
  105 + backgroundColor = .white
  106 +
  107 + addSubview(backButton)
  108 + addSubview(logoImage)
  109 + addSubview(shieldImage)
  110 + addSubview(containerView)
  111 + addSubview(spinner)
  112 + spinner.addSubview(loadingView)
  113 +
  114 + containerView.addSubview(descriptionLabel)
  115 + containerView.addSubview(otpView)
  116 + containerView.addSubview(errorAlertLabel)
  117 +
  118 + containerView.addSubview(verifyButton)
  119 + verifyButton.addSubview(verifyLabel)
  120 + verifyButton.addSubview(tickImage)
  121 +
  122 + backButton.snp.makeConstraints {
  123 + $0.top.equalTo(snp.top).offset(66)
  124 + $0.leading.equalTo(snp.leading).offset(22)
  125 + $0.height.width.equalTo(45)
  126 + }
  127 +
  128 + logoImage.snp.makeConstraints {
  129 + $0.leading.equalTo(backButton.snp.trailing).offset(20)
  130 + $0.centerY.equalTo(backButton)
  131 + }
  132 +
  133 + shieldImage.snp.makeConstraints {
  134 + $0.top.equalTo(backButton.snp.bottom).offset(25)
  135 + $0.right.equalTo(snp.right).offset(-101)
  136 + }
  137 +
  138 + containerView.snp.makeConstraints {
  139 + $0.top.equalTo(backButton.snp.bottom).offset(227)
  140 + $0.leading.trailing.equalToSuperview()
  141 + $0.height.equalTo(300)
  142 + }
  143 +
  144 + descriptionLabel.snp.makeConstraints {
  145 + $0.leading.equalTo(containerView.snp.leading).offset(20)
  146 + $0.top.equalTo(containerView.snp.top)
  147 + }
  148 +
  149 + otpView.snp.makeConstraints { make in
  150 + make.leading.trailing.equalToSuperview().inset(25)
  151 + make.top.equalTo(descriptionLabel.snp.bottom).offset(28)
  152 + make.height.equalTo(55)
  153 + }
  154 +
  155 + errorAlertLabel.snp.makeConstraints {
  156 + $0.top.equalTo(otpView.snp.bottom).offset(8)
  157 + $0.leading.equalTo(otpView.snp.leading)
  158 + }
  159 +
  160 + verifyButton.snp.makeConstraints {
  161 + $0.top.equalTo(otpView.snp.bottom).offset(67)
  162 + $0.left.right.equalToSuperview()
  163 + }
  164 +
  165 + verifyLabel.snp.makeConstraints {
  166 + $0.left.equalToSuperview().offset(49)
  167 + $0.top.equalToSuperview().offset(22)
  168 + }
  169 +
  170 + tickImage.snp.makeConstraints {
  171 + $0.right.equalToSuperview().offset(-47)
  172 + $0.centerY.equalTo(verifyLabel)
  173 + }
  174 + spinner.snp.makeConstraints { make in
  175 + make.centerX.centerY.equalToSuperview()
  176 + }
  177 + loadingView.snp.makeConstraints { make in
  178 + make.edges.equalTo(snp.edges)
  179 + }
  180 + }
  181 +}
  182 +
... ...
  1 +//
  2 +// OTPView.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 02.07.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +import UIKit
  10 +protocol OTPViewDelegate: AnyObject {
  11 + func didFullCodeCompletion(_ otpView: OTPView)
  12 +}
  13 +
  14 +class OTPView: UIView {
  15 + weak var delegate: OTPViewDelegate?
  16 +
  17 + var digitViews: [UILabel] = []
  18 +
  19 + var code: String? {
  20 + return textField.text
  21 + }
  22 +
  23 + var isError: Bool = false {
  24 + didSet {
  25 + handleErrorUI(isError)
  26 + }
  27 + }
  28 +
  29 + let textField: UITextField = {
  30 + let obj = UITextField()
  31 + obj.isHidden = true
  32 + obj.keyboardType = .numberPad
  33 + return obj
  34 + }()
  35 +
  36 + private lazy var stackView: UIStackView = {
  37 + let obj = UIStackView(arrangedSubviews: digitViews)
  38 + obj.axis = .horizontal
  39 + obj.spacing = 11
  40 + obj.distribution = .fillEqually
  41 + obj.semanticContentAttribute = .forceLeftToRight
  42 + return obj
  43 + }()
  44 +
  45 + override init(frame: CGRect) {
  46 + super.init(frame: frame)
  47 + initDigits()
  48 + setup()
  49 + }
  50 +
  51 + required init?(coder: NSCoder) {
  52 + super.init(coder: coder)
  53 + setup()
  54 + }
  55 +
  56 + private func initDigits() {
  57 + for i in 0...3 {
  58 + digitViews.append(initLabel())
  59 + }
  60 + }
  61 +
  62 + private func initLabel() -> UILabel {
  63 + let obj = UILabel()
  64 + obj.font = .skModernist(type: .bold, ofSize: 16)
  65 + obj.textColor = .black
  66 + obj.textAlignment = .center
  67 + obj.backgroundColor = .TextFieldColor.general
  68 + obj.layer.cornerRadius = 15
  69 + obj.clipsToBounds = true
  70 + return obj
  71 + }
  72 +
  73 + private func setup() {
  74 + addSubview(textField)
  75 + addSubview(stackView)
  76 +
  77 + stackView.snp.makeConstraints { make in
  78 + make.edges.equalToSuperview()
  79 + }
  80 +
  81 + textField.addTarget(self, action: #selector(didTextFieldChanged(_:)), for: .editingChanged)
  82 + }
  83 +
  84 + override func addSubview(_ view: UIView) {
  85 + super.addSubview(view)
  86 + textField.becomeFirstResponder()
  87 + }
  88 +
  89 + @objc func didTextFieldChanged(_ sender: UITextField) {
  90 + guard var code = sender.text else {
  91 + return
  92 + }
  93 + if code.count == 0 {
  94 + delegate?.didFullCodeCompletion(self)
  95 + } else if code.count > 4 {
  96 + code.removeLast()
  97 + } else {
  98 + if code.count == 4 {
  99 + delegate?.didFullCodeCompletion(self)
  100 + textField.resignFirstResponder()
  101 + }
  102 + }
  103 + digitViews.enumerated().forEach { index, item in
  104 + item.text = (code.count-1 >= index ? String(code[code.index(code.startIndex, offsetBy: index)]) : "")
  105 + }
  106 + }
  107 +
  108 + private func handleErrorUI(_ isError: Bool) {
  109 + colorСhanger()
  110 + }
  111 +
  112 + private func colorСhanger() {
  113 + digitViews.self.forEach { label in
  114 + label.backgroundColor = .TextFieldColor.error
  115 + label.textColor = .TextColor.redError
  116 + }
  117 + }
  118 +}
... ...
  1 +//
  2 +// CodeVerificationViewController.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 03.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class CodeVerificationViewController: UIViewController {
  11 + var isKeyboardAppear = false
  12 + var verifyMessage: String?
  13 + private let mainView = CodeVerificationView()
  14 +
  15 + override func loadView() {
  16 + view = mainView
  17 + }
  18 +
  19 + override func viewDidLoad() {
  20 + initViewController()
  21 + }
  22 +
  23 + private func initViewController() {
  24 + mainView.otpView.delegate = self
  25 + mainView.backButton.addTarget(self, action: #selector(didTapBackButton), for: .touchUpInside)
  26 + mainView.verifyButton.addTarget(self, action: #selector(didTapVerifyButton), for: .touchUpInside)
  27 +
  28 + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
  29 + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
  30 + }
  31 +
  32 + deinit {
  33 + NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
  34 + NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
  35 + }
  36 +
  37 + func verificationRequestProcessing() {
  38 + self.mainView.spinner.startAnimating()
  39 + guard let verifyModel = getVerifyModel() else { return }
  40 + AuthService.shared.verifyRequest(model: verifyModel) { response in
  41 + print("3️⃣✅\(response.data)")
  42 + print("\(response.message)✅")
  43 + self.loginRequestProcessing()
  44 + } fail: { error in
  45 + self.mainView.spinner.stopAnimating()
  46 + print("3️⃣\(error)")
  47 + self.errorProcessing()
  48 + }
  49 + }
  50 +
  51 + func loginRequestProcessing() {
  52 + guard let loginModel = getLoginModel() else { return }
  53 + AuthService.shared.loginRequest(model: loginModel) { response in
  54 + print("4️⃣\(String(describing: response.message))4️⃣")
  55 + self.verifyMessage = response.message
  56 + self.loginDataProcessing()
  57 + } fail: { error in
  58 + self.mainView.spinner.stopAnimating()
  59 + self.errorProcessing()
  60 + print("4️⃣⛔️\(error)⛔️")
  61 + }
  62 + }
  63 +
  64 + func getVerifyModel() -> VerifyRequestModel? {
  65 + let email = ""
  66 + guard let code = mainView.otpView.code else { return nil }
  67 + return VerifyRequestModel(emailOrNumber: email, code: code, secondAuthToken: "asdas")
  68 + }
  69 +
  70 + func getLoginModel() -> LoginRequestModel? {
  71 + guard let deviceUUID = UIDevice.current.identifierForVendor?.uuidString else {
  72 + return nil
  73 + }
  74 + return LoginRequestModel(deviceUUID: deviceUUID)
  75 + }
  76 +}
  77 +//MARK: - Targets
  78 +extension CodeVerificationViewController {
  79 + @objc private func didTapVerifyButton() {
  80 + verificationRequestProcessing()
  81 + }
  82 +
  83 + private func showHomeVC() {
  84 + let viewController = HomeViewController()
  85 + navigationController?.pushViewController(viewController, animated: true)
  86 + }
  87 +
  88 + private func loginDataProcessing() {
  89 + self.mainView.spinner.stopAnimating()
  90 + self.showHomeVC()
  91 + }
  92 +
  93 + private func errorProcessing() {
  94 + guard let code = mainView.otpView.code else { return }
  95 +
  96 + if code.count < 4 {
  97 + let alert = UIAlertController(title: "❌", message: "Enter all fields", preferredStyle: .alert)
  98 + alert.addAction(UIAlertAction(title: "Close", style: .cancel, handler: nil))
  99 + present(alert, animated: true, completion: nil)
  100 + } else if verifyMessage != "OK" {
  101 + let alert = UIAlertController(title: "Wrong password", message: "", preferredStyle: .alert)
  102 + alert.addAction(UIAlertAction(title: "Try again", style: .cancel, handler: { action in
  103 + self.mainView.otpView.isError.toggle()
  104 + self.mainView.errorAlertLabel.isHidden = false
  105 + self.mainView.otpView.textField.becomeFirstResponder()
  106 + }))
  107 + present(alert, animated: true, completion: nil)
  108 + } else {
  109 + let alert = UIAlertController(title: "Network technical issues", message: "", preferredStyle: .alert)
  110 + alert.addAction(UIAlertAction(title: "Reload", style: .cancel, handler: { action in
  111 + self.didTapBackButton()
  112 + }))
  113 + present(alert, animated: true, completion: nil)
  114 + }
  115 + }
  116 +
  117 + @objc private func didTapBackButton() {
  118 + navigationController?.popViewController(animated: true)
  119 + }
  120 +
  121 + @objc private func keyboardWillShow(notification: NSNotification) {
  122 + let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double
  123 +
  124 + if !isKeyboardAppear {
  125 + UIView.animate(withDuration: duration ?? 0) {
  126 + self.mainView.containerView.snp.updateConstraints { make in
  127 + make.top.equalTo(self.mainView.backButton.snp.bottom).offset(97)
  128 + }
  129 + self.mainView.shieldImage.snp.updateConstraints {
  130 + $0.right.equalTo(self.mainView.snp.right).offset(-6)
  131 + }
  132 + self.mainView.layoutIfNeeded()
  133 + }
  134 + isKeyboardAppear = true
  135 + }
  136 + }
  137 +
  138 + @objc private func keyboardWillHide(notification: NSNotification) {
  139 + let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double
  140 +
  141 + if isKeyboardAppear {
  142 + UIView.animate(withDuration: duration ?? 0) {
  143 + self.mainView.containerView.snp.updateConstraints { make in
  144 + make.top.equalTo(self.mainView.backButton.snp.bottom).offset(227)
  145 + }
  146 + self.mainView.shieldImage.snp.updateConstraints {
  147 + $0.right.equalTo(self.mainView.snp.right).offset(-101)
  148 + }
  149 + self.mainView.layoutIfNeeded()
  150 + }
  151 + isKeyboardAppear = false
  152 + }
  153 + }
  154 +}
  155 +
  156 +//MARK: - OTPView delegate
  157 +extension CodeVerificationViewController: OTPViewDelegate {
  158 +
  159 + func didFullCodeCompletion(_ otpView: OTPView) {
  160 + print("code -> \(String(describing: otpView.code))")
  161 + }
  162 +}
... ...
  1 +//
  2 +// ResidentTableViewCell.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 17.06.2022.
  6 +//
  7 +
  8 +import Foundation
... ...
  1 +//
  2 +// ResidentTableViewCell.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 21.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +protocol ResidentTableViewCellDelegate: AnyObject {
  11 + func didRemoveButtonTapped(cell: ResidentTableViewCell)
  12 + func didManagerButtonTapped(cell: ResidentTableViewCell)
  13 + func didHiddenButtonTapped(cell: ResidentTableViewCell)
  14 + func didHeardButtonTapped(cell: ResidentTableViewCell)
  15 +}
  16 +
  17 +class ResidentTableViewCell: UITableViewCell {
  18 + var model: ResidentModel? {
  19 + didSet {
  20 + if let model = model {
  21 + nameLabel.text = model.name
  22 + phoneNumberLabel.text = model.mobileNumber
  23 + managerButton.isSelected = model.manager
  24 + hiddenButton.isSelected = model.hidden
  25 + heartButton.isSelected = model.heart
  26 + }
  27 + }
  28 + }
  29 +
  30 + weak var delegate: ResidentTableViewCellDelegate?
  31 +
  32 + static let id = String(describing: ResidentTableViewCell.self)
  33 +
  34 + var containerView: UIView = {
  35 + var obj = UIView()
  36 + obj.layer.cornerRadius = 15
  37 + obj.layer.borderWidth = 1
  38 + obj.layer.borderColor = .BorderColor.lightGrey
  39 + return obj
  40 + }()
  41 +
  42 + var serialNumberView: UIImageView = {
  43 + let obj = UIImageView()
  44 + obj.clipsToBounds = true
  45 + obj.layer.cornerRadius = 21.5
  46 + return obj
  47 + }()
  48 +
  49 + var serialNumberLabel: UILabel = {
  50 + let obj = UILabel()
  51 + obj.font = .skModernist(type: .bold, ofSize: 14)
  52 + obj.textColor = .white
  53 + return obj
  54 + }()
  55 +
  56 + var nameLabel: UILabel = {
  57 + var obj = UILabel()
  58 + obj.textColor = .TextColor.darkBlue
  59 + obj.font = .skModernist(type: .bold, ofSize: 16)
  60 + obj.text = "John Doe"
  61 + return obj
  62 + }()
  63 +
  64 + var phoneNumberLabel: UILabel = {
  65 + var obj = UILabel()
  66 + obj.textColor = .TextColor.lightGrey
  67 + obj.font = .skModernist(type: .regular, ofSize: 14)
  68 + obj.text = "+38095"
  69 + return obj
  70 + }()
  71 +
  72 + var managerButton: SquereCheckbox = {
  73 + var obj = SquereCheckbox()
  74 + obj.checkboxTitle = .Text.manager
  75 + obj.setTitleColor(.TextColor.lightGrey, for: .normal)
  76 + obj.setTitleColor(.TextColor.darkBlue, for: .selected)
  77 + obj.isSelected = false
  78 + return obj
  79 + }()
  80 +
  81 + var hiddenButton: SquereCheckbox = {
  82 + var obj = SquereCheckbox()
  83 + obj.checkboxTitle = .Text.hidden
  84 + obj.setTitleColor(.TextColor.lightGrey, for: .normal)
  85 + obj.setTitleColor(.TextColor.darkBlue, for: .selected)
  86 + obj.isSelected = false
  87 + return obj
  88 + }()
  89 +
  90 + var heartButton: UIButton = {
  91 + var obj = UIButton()
  92 + obj.setImage(UIImage(named: .Image.heart), for: .normal)
  93 + obj.setImage(UIImage(named: .Image.heartRed), for: .selected)
  94 + return obj
  95 + }()
  96 +
  97 + var removeCellButton: UIButton = {
  98 + var obj = UIButton()
  99 + obj.setImage(UIImage(named: .Image.bin), for: .normal)
  100 + return obj
  101 + }()
  102 +
  103 + var gradientBG: CAGradientLayer = {
  104 + let obj = CAGradientLayer()
  105 + var leftColor = UIColor.GradientBlue.left
  106 + var rightColor = UIColor.GradientBlue.right
  107 + obj.colors = [leftColor, rightColor]
  108 + obj.startPoint = CGPoint(x: 0, y: 0.5)
  109 + obj.endPoint = CGPoint(x: 1, y: 0.5)
  110 + return obj
  111 + }()
  112 +
  113 + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
  114 + super.init(style: style, reuseIdentifier: reuseIdentifier)
  115 + setup()
  116 + }
  117 +
  118 + required init?(coder: NSCoder) {
  119 + fatalError("init(coder:) has not been implemented")
  120 + }
  121 +
  122 + func setup() {
  123 + selectionStyle = .none
  124 + serialNumberView.layer.insertSublayer(gradientBG, at: 0)
  125 +
  126 + contentView.addSubview(containerView)
  127 + containerView.addSubview(serialNumberView)
  128 + serialNumberView.addSubview(serialNumberLabel)
  129 +
  130 + containerView.addSubview(nameLabel)
  131 + containerView.addSubview(phoneNumberLabel)
  132 + containerView.addSubview(managerButton)
  133 + containerView.addSubview(hiddenButton)
  134 + containerView.addSubview(heartButton)
  135 + containerView.addSubview(removeCellButton)
  136 +
  137 + containerView.snp.makeConstraints {
  138 + $0.leading.trailing.equalToSuperview().inset(25)
  139 + $0.bottom.top.equalToSuperview().inset(8)
  140 + }
  141 +
  142 + serialNumberView.snp.makeConstraints {
  143 + $0.height.width.equalTo(41)
  144 + $0.leading.equalToSuperview().offset(23)
  145 + $0.top.equalToSuperview().offset(19)
  146 + }
  147 +
  148 + serialNumberLabel.snp.makeConstraints {
  149 + $0.centerX.centerY.equalToSuperview()
  150 + }
  151 +
  152 + nameLabel.snp.makeConstraints {
  153 + $0.leading.equalTo(serialNumberView.snp.trailing).offset(18)
  154 + $0.top.equalToSuperview().offset(22)
  155 + }
  156 +
  157 + removeCellButton.snp.makeConstraints {
  158 + $0.centerY.equalTo(nameLabel.snp.centerY)
  159 + $0.trailing.equalToSuperview().offset(-22.5)
  160 + }
  161 +
  162 + phoneNumberLabel.snp.makeConstraints {
  163 + $0.leading.equalTo(nameLabel.snp.leading)
  164 + $0.top.equalTo(nameLabel.snp.bottom).offset(1)
  165 + }
  166 +
  167 + managerButton.snp.makeConstraints {
  168 + $0.top.equalTo(phoneNumberLabel.snp.bottom).offset(30)
  169 + $0.leading.equalToSuperview().offset(24)
  170 + $0.height.equalTo(20)
  171 + }
  172 +
  173 + hiddenButton.snp.makeConstraints {
  174 + $0.leading.equalTo(managerButton.snp.trailing).offset(23)
  175 + $0.centerY.equalTo(managerButton)
  176 + $0.height.equalTo(20)
  177 + }
  178 +
  179 + heartButton.snp.makeConstraints {
  180 + $0.centerY.equalTo(hiddenButton)
  181 + $0.bottom.equalToSuperview().offset(-18)
  182 + $0.trailing.equalToSuperview().offset(-22)
  183 + }
  184 +
  185 + removeCellButton.addTarget(self, action: #selector(didRemoveButtonTapped(_:)), for: .touchUpInside)
  186 + managerButton.addTarget(self, action: #selector(didManagerButtonTapped(_:)), for: .touchUpInside)
  187 + hiddenButton.addTarget(self, action: #selector(didHiddenButtonTapped(_:)), for: .touchUpInside)
  188 + heartButton.addTarget(self, action: #selector(didHeartButtonTapped(_:)), for: .touchUpInside)
  189 + }
  190 +
  191 + override func layoutSubviews() {
  192 + super.layoutSubviews()
  193 + gradientBG.frame = serialNumberView.bounds
  194 + }
  195 +
  196 +}
  197 +
  198 +//MARK: targets
  199 +extension ResidentTableViewCell {
  200 + @objc private func didRemoveButtonTapped(_ sender: UIButton) {
  201 + delegate?.didRemoveButtonTapped(cell: self)
  202 + }
  203 +
  204 + @objc private func didManagerButtonTapped(_ sender: UIButton) {
  205 + delegate?.didManagerButtonTapped(cell: self)
  206 + }
  207 +
  208 + @objc private func didHiddenButtonTapped(_ sender: UIButton) {
  209 + delegate?.didHiddenButtonTapped(cell: self)
  210 + }
  211 +
  212 + @objc private func didHeartButtonTapped(_ sender: UIButton) {
  213 + delegate?.didHeardButtonTapped(cell: self)
  214 + }
  215 +
  216 +}
... ...
  1 +//
  2 +// ResidentsView.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 14.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class ResidentsView: UIView {
  11 + var backButton: UIButton = {
  12 + var obj = UIButton()
  13 + obj.setImage(UIImage(named: .Image.backPointer), for: .normal)
  14 + obj.backgroundColor = .white
  15 + obj.layer.borderColor = .BorderColor.lightGrey
  16 + obj.layer.cornerRadius = 13
  17 + obj.layer.borderWidth = 1
  18 + return obj
  19 + }()
  20 +
  21 + var logoImage: UIImageView = {
  22 + var obj = UIImageView()
  23 + obj.image = UIImage(named: .Image.USA)
  24 + return obj
  25 + }()
  26 +
  27 + let apartNameLabel: UILabel = {
  28 + var obj = UILabel()
  29 + obj.font = .skModernist(type: .bold, ofSize: 35)
  30 + obj.text = .Text.myApartName
  31 + return obj
  32 + }()
  33 +
  34 + var dividingLineView: UIView = {
  35 + var view = UIView()
  36 + view.backgroundColor = .Background.lightGrey
  37 + return view
  38 + }()
  39 +
  40 + var residentsLabel: UILabel = {
  41 + var obj = UILabel()
  42 + obj.font = .skModernist(type: .bold, ofSize: 20)
  43 + obj.text = .Text.residents
  44 + return obj
  45 + }()
  46 +
  47 + var addResidentsButton: UIButton = {
  48 + var obj = UIButton()
  49 + obj.layer.borderWidth = 1
  50 + obj.layer.borderColor = .BorderColor.lightGrey
  51 + obj.layer.cornerRadius = 13
  52 + obj.setImage(UIImage(named: .Image.edit), for: .normal)
  53 + return obj
  54 + }()
  55 +
  56 + let tableView: UITableView = {
  57 + let obj = UITableView()
  58 + obj.showsVerticalScrollIndicator = false
  59 + obj.separatorStyle = .none
  60 + obj.rowHeight = UITableView.automaticDimension
  61 + return obj
  62 + }()
  63 +
  64 + let addResidentView: AddResidentsView = {
  65 + var obj = AddResidentsView()
  66 + obj.isHidden = true
  67 + return obj
  68 + }()
  69 +
  70 + override init(frame: CGRect) {
  71 + super.init(frame: frame)
  72 + backgroundColor = .white
  73 + setup()
  74 + }
  75 +
  76 + required init?(coder: NSCoder) {
  77 + fatalError("init(coder:) has not been implemented")
  78 + }
  79 +
  80 + func setup() {
  81 +
  82 + addSubview(backButton)
  83 + addSubview(logoImage)
  84 + addSubview(apartNameLabel)
  85 + addSubview(dividingLineView)
  86 + addSubview(residentsLabel)
  87 + addSubview(addResidentsButton)
  88 + addSubview(tableView)
  89 + addSubview(addResidentView)
  90 +
  91 + backButton.snp.makeConstraints {
  92 + $0.top.equalTo(snp.top).offset(66)
  93 + $0.leading.equalTo(snp.leading).offset(25)
  94 + $0.height.width.equalTo(45)
  95 + }
  96 +
  97 + logoImage.snp.makeConstraints {
  98 + $0.leading.equalTo(backButton.snp.trailing).offset(20)
  99 + $0.top.equalTo(snp.top).offset(79)
  100 + }
  101 +
  102 + apartNameLabel.snp.makeConstraints {
  103 + $0.leading.equalTo(backButton.snp.leading)
  104 + $0.top.equalTo(backButton.snp.bottom).offset(46)
  105 + }
  106 +
  107 + dividingLineView.snp.makeConstraints {
  108 + $0.leading.trailing.equalToSuperview()
  109 + $0.height.equalTo(1)
  110 + $0.top.equalTo(apartNameLabel.snp.bottom).offset(42)
  111 + }
  112 +
  113 + residentsLabel.snp.makeConstraints {
  114 + $0.leading.equalToSuperview().offset(24)
  115 + $0.top.equalTo(dividingLineView.snp.bottom).offset(43)
  116 + }
  117 +
  118 + addResidentsButton.snp.makeConstraints {
  119 + $0.height.width.equalTo(45)
  120 + $0.top.equalTo(dividingLineView.snp.bottom).offset(32)
  121 + $0.trailing.equalToSuperview().offset(-29)
  122 + }
  123 +
  124 + tableView.snp.makeConstraints {
  125 + $0.top.equalTo(residentsLabel.snp.bottom).offset(30)
  126 + $0.leading.trailing.equalToSuperview()
  127 + $0.bottom.equalToSuperview()
  128 + }
  129 +
  130 + addResidentView.snp.makeConstraints {
  131 + $0.top.trailing.leading.bottom.equalToSuperview()
  132 + }
  133 + }
  134 +}
... ...
  1 +//
  2 +// ResidentsViewController.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 14.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class ResidentsViewController: UIViewController {
  11 + var mainView = ResidentsView()
  12 + var myData: [ResidentModel] = []
  13 +
  14 + override func loadView() {
  15 + view = mainView
  16 + }
  17 +
  18 + override func viewDidLoad() {
  19 + initViewController()
  20 + }
  21 +
  22 + func initViewController() {
  23 + mainView.tableView.delegate = self
  24 + mainView.tableView.dataSource = self
  25 + mainView.tableView.register(ResidentTableViewCell.self, forCellReuseIdentifier: ResidentTableViewCell.id)
  26 +
  27 + mainView.backButton.addTarget(self, action: #selector(didShowChooseApartVC), for: .touchUpInside)
  28 + mainView.addResidentsButton.addTarget(self, action: #selector(willShowAddResidentVC), for: .touchUpInside)
  29 + }
  30 +
  31 + @objc private func didShowChooseApartVC() {
  32 + navigationController?.popViewController(animated: true)
  33 + }
  34 +
  35 + @objc private func willShowAddResidentVC() {
  36 + let addResidentsVC = AddResidentsViewController()
  37 + addResidentsVC.modalPresentationStyle = .overCurrentContext
  38 + addResidentsVC.modalTransitionStyle = .crossDissolve
  39 + addResidentsVC.delegate = self
  40 + present(addResidentsVC, animated: true)
  41 + }
  42 +}
  43 +
  44 +//MARK: - TableView delegate & data source
  45 +extension ResidentsViewController: UITableViewDelegate, UITableViewDataSource {
  46 + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  47 + myData.count
  48 + }
  49 +
  50 + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  51 + guard let cell = tableView.dequeueReusableCell(withIdentifier: ResidentTableViewCell.id, for: indexPath) as? ResidentTableViewCell else { return UITableViewCell() }
  52 + cell.serialNumberLabel.text = "\(indexPath.row + 1)"
  53 + let data = myData[indexPath.row]
  54 + cell.model = data
  55 + cell.delegate = self
  56 + return cell
  57 + }
  58 +}
  59 +//MARK: - ResidentSavable delegate
  60 +extension ResidentsViewController: ResidentSavable {
  61 + func save(_ data: ResidentModel) {
  62 + self.myData.append(data)
  63 + mainView.tableView.reloadData()
  64 + }
  65 +}
  66 +
  67 +//MARK: residentcell delegate
  68 +extension ResidentsViewController: ResidentTableViewCellDelegate {
  69 + func didButtonsTapped(cell: ResidentTableViewCell) {
  70 + if !cell.managerButton.isSelected {
  71 + cell.managerButton.isSelected = true
  72 + } else {
  73 + cell.managerButton.isSelected = false
  74 + }
  75 + }
  76 +
  77 + func didRemoveButtonTapped(cell: ResidentTableViewCell) {
  78 + guard let model = cell.model else {
  79 + return
  80 + }
  81 + myData.removeAll(where: {$0.name == model.name})
  82 + mainView.tableView.reloadData()
  83 + }
  84 +
  85 + func didManagerButtonTapped(cell: ResidentTableViewCell) {
  86 + if !cell.managerButton.isSelected {
  87 + cell.managerButton.isSelected = true
  88 + } else {
  89 + cell.managerButton.isSelected = false
  90 + }
  91 + }
  92 +
  93 + func didHiddenButtonTapped(cell: ResidentTableViewCell) {
  94 + if !cell.hiddenButton.isSelected {
  95 + cell.hiddenButton.isSelected = true
  96 + } else {
  97 + cell.hiddenButton.isSelected = false
  98 + }
  99 + }
  100 +
  101 + func didHeardButtonTapped(cell: ResidentTableViewCell) {
  102 + if !cell.heartButton.isSelected {
  103 + cell.heartButton.isSelected = true
  104 + } else {
  105 + cell.heartButton.isSelected = false
  106 + }
  107 + }
  108 +}
... ...
  1 +
  2 +//
  3 +// SettingsModel.swift
  4 +// InterQR-Internship
  5 +//
  6 +// Created by Дмитрий Тимофеев on 09.06.2022.
  7 +//
  8 +
  9 +import Foundation
  10 +import UIKit
  11 +enum SettingsModel: CaseIterable {
  12 + case displayName
  13 + case doNotDisturb
  14 + case ringtone
  15 + case editResidents
  16 + case widgetLock
  17 +
  18 + func getTitle() -> String {
  19 + switch self {
  20 + case .displayName :
  21 + return "Your display name"
  22 + case .doNotDisturb :
  23 + return "Do not disturb"
  24 + case .editResidents :
  25 + return "Edit residents"
  26 + case .widgetLock:
  27 + return "Widget lock"
  28 + case .ringtone:
  29 + return "Ringtone"
  30 + }
  31 + }
  32 +
  33 + func getIcon() -> UIImage? {
  34 + switch self {
  35 + case .displayName:
  36 + return UIImage(named: "Profile")
  37 + case .doNotDisturb:
  38 + return UIImage(named: "Notification")
  39 + case .editResidents:
  40 + return UIImage(named: "Password")
  41 + case .widgetLock:
  42 + return UIImage(named: "Profile")
  43 + case .ringtone:
  44 + return UIImage(named: "Volume")
  45 + }
  46 + }
  47 +
  48 + func getDescription() -> String {
  49 + switch self {
  50 + case .displayName :
  51 + return "This name will be dispayed everywhere"
  52 + case .doNotDisturb :
  53 + return "This name will be dispayed everywhere"
  54 + case .editResidents :
  55 + return "This name will be dispayed everywhere"
  56 + case .widgetLock:
  57 + return "This name will be dispayed everywhere"
  58 + case .ringtone:
  59 + return "This name will be dispayed everywhere"
  60 + }
  61 + }
  62 +}
... ...
  1 +//
  2 +// File.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 15.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class DisplayNameCell: UITableViewCell, Reusable {
  11 + var settingsIcon: UIImageView = {
  12 + var obj = UIImageView()
  13 + obj.image = UIImage(named: .Image.profile)
  14 + return obj
  15 + }()
  16 +
  17 + var titleLabel: UILabel = {
  18 + var obj = UILabel()
  19 + obj.text = .Text.yourDisplayName
  20 + obj.font = .skModernist(type: .bold, ofSize: 16)
  21 + obj.textColor = .TextColor.darkBlue
  22 + return obj
  23 + }()
  24 +
  25 + var descriptionLabel: UILabel = {
  26 + var obj = UILabel()
  27 + obj.text = .Text.nameWillBeDisplay
  28 + obj.font = .skModernist(type: .regular, ofSize: 14)
  29 + obj.textColor = .TextColor.lightGrey
  30 + return obj
  31 + }()
  32 +
  33 + var displayNameTextField: TextFieldWithPadding = {
  34 + var obj = TextFieldWithPadding()
  35 + obj.text = .Text.johnDoe
  36 + obj.returnKeyType = .done
  37 + obj.backgroundColor = .TextFieldColor.general
  38 + obj.clipsToBounds = true
  39 + obj.layer.cornerRadius = 15
  40 + obj.textPadding = UIEdgeInsets(top: 0, left: 24, bottom: 0, right: 15)
  41 + return obj
  42 + }()
  43 +
  44 + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
  45 + super.init(style: style, reuseIdentifier: reuseIdentifier)
  46 + setup()
  47 + }
  48 +
  49 + required init?(coder: NSCoder) {
  50 + super.init(coder: coder)
  51 + setup()
  52 + }
  53 +
  54 + private func setup() {
  55 + selectionStyle = .none
  56 + contentView.addSubview(settingsIcon)
  57 + contentView.addSubview(titleLabel)
  58 + contentView.addSubview(descriptionLabel)
  59 + contentView.addSubview(displayNameTextField)
  60 +
  61 + settingsIcon.snp.makeConstraints { make in
  62 + make.top.equalToSuperview()
  63 + make.leading.equalTo(snp.leading).offset(32)
  64 + }
  65 +
  66 + titleLabel.snp.makeConstraints { make in
  67 + make.top.equalTo(settingsIcon.snp.top)
  68 + make.leading.equalTo(settingsIcon.snp.trailing).offset(18)
  69 + }
  70 +
  71 + descriptionLabel.snp.makeConstraints { make in
  72 + make.top.equalTo(titleLabel.snp.bottom).offset(5)
  73 + make.leading.equalTo(titleLabel.snp.leading)
  74 + }
  75 +
  76 + displayNameTextField.snp.makeConstraints { make in
  77 + make.top.equalTo(descriptionLabel.snp.bottom).offset(20)
  78 + make.leading.equalTo(snp.leading).offset(66)
  79 + make.trailing.equalTo(snp.trailing).offset(-28)
  80 + make.height.equalTo(47)
  81 + make.bottom.equalToSuperview().offset(-30)
  82 + }
  83 + }
  84 +}
  85 +
... ...
  1 +//
  2 +// SettingsSwitchCell.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 15.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class SettingsSwitchCell: UITableViewCell, Reusable {
  11 + var settingsIcon: UIImageView = {
  12 + var obj = UIImageView()
  13 + obj.image = UIImage(named: .Image.notification)
  14 + return obj
  15 + }()
  16 +
  17 + var titleLabel: UILabel = {
  18 + var obj = UILabel()
  19 + obj.text = .Text.doNotDisturb
  20 + obj.textColor = .TextColor.darkBlue
  21 + obj.font = .skModernist(type: .bold, ofSize: 16)
  22 + return obj
  23 + }()
  24 +
  25 + var descriptionLabel: UILabel = {
  26 + var obj = UILabel()
  27 + obj.text = .Text.youWillNotBeNotified
  28 + obj.textColor = .TextColor.lightGrey
  29 + obj.font = .skModernist(type: .regular, ofSize: 14)
  30 + obj.numberOfLines = 0
  31 + return obj
  32 + }()
  33 +
  34 + var notificationSwitch: UISwitch = {
  35 + var obj = UISwitch()
  36 + obj.isOn = false
  37 + obj.clipsToBounds = true
  38 + return obj
  39 + }()
  40 +
  41 + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
  42 + super.init(style: style, reuseIdentifier: reuseIdentifier)
  43 + setup()
  44 + }
  45 +
  46 + required init?(coder: NSCoder) {
  47 + super.init(coder: coder)
  48 + setup()
  49 + }
  50 +
  51 + func setup() {
  52 + selectionStyle = .none
  53 + contentView.addSubview(settingsIcon)
  54 + contentView.addSubview(titleLabel)
  55 + contentView.addSubview(descriptionLabel)
  56 + contentView.addSubview(notificationSwitch)
  57 +
  58 + settingsIcon.snp.makeConstraints { make in
  59 + make.leading.equalToSuperview().offset(31)
  60 + make.top.equalToSuperview().offset(38)
  61 + }
  62 +
  63 + titleLabel.snp.makeConstraints { make in
  64 + make.leading.equalTo(settingsIcon.snp.trailing).offset(17.5)
  65 + make.top.equalToSuperview().offset(38)
  66 + }
  67 +
  68 + descriptionLabel.snp.makeConstraints { make in
  69 + make.top.equalTo(titleLabel.snp.bottom).offset(5)
  70 + make.leading.equalTo(titleLabel.snp.leading)
  71 + make.bottom.equalToSuperview().offset(-22)
  72 + }
  73 +
  74 + notificationSwitch.snp.makeConstraints { make in
  75 + make.top.equalTo(snp.top).offset(36)
  76 + make.trailing.equalTo(snp.trailing).offset(-28)
  77 + }
  78 + }
  79 +}
  80 +
  81 +
... ...
  1 +//
  2 +// SettingsTableViewCell.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 15.06.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +
  10 +import UIKit
  11 +
  12 +class SettingsTableViewCell: UITableViewCell, Reusable {
  13 + var settingsIcon: UIImageView = {
  14 + var obj = UIImageView()
  15 + obj.image = UIImage(named: .Image.edit)
  16 + obj.contentMode = .scaleAspectFill
  17 + return obj
  18 + }()
  19 +
  20 + var titleLabel: UILabel = {
  21 + var obj = UILabel()
  22 + obj.text = .Text.editResidents
  23 + obj.textColor = .TextColor.darkBlue
  24 + obj.font = .skModernist(type: .bold, ofSize: 16)
  25 + return obj
  26 + }()
  27 +
  28 + var descriptionLabel: UILabel = {
  29 + var obj = UILabel()
  30 + obj.text = .Text.editResidentsAndInfo
  31 + obj.textColor = .TextColor.lightGrey
  32 + obj.font = .skModernist(type: .regular, ofSize: 14)
  33 + return obj
  34 + }()
  35 +
  36 + var arrowImageView: UIImageView = {
  37 + var obj = UIImageView()
  38 + obj.image = UIImage(named: .Image.nextPointer)
  39 + return obj
  40 + }()
  41 +
  42 + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
  43 + super.init(style: style, reuseIdentifier: reuseIdentifier)
  44 + setup()
  45 + }
  46 +
  47 + required init?(coder: NSCoder) {
  48 + super.init(coder: coder)
  49 + setup()
  50 + }
  51 +
  52 + func setup() {
  53 + selectionStyle = .none
  54 + contentView.addSubview(settingsIcon)
  55 + contentView.addSubview(titleLabel)
  56 + contentView.addSubview(descriptionLabel)
  57 + contentView.addSubview(arrowImageView)
  58 +
  59 + settingsIcon.snp.makeConstraints { make in
  60 + make.top.equalToSuperview().offset(26)
  61 + make.leading.equalToSuperview().offset(32)
  62 + make.height.width.equalTo(18)
  63 + }
  64 +
  65 + titleLabel.snp.makeConstraints { make in
  66 + make.top.equalToSuperview().offset(26)
  67 + make.leading.equalTo(settingsIcon.snp.trailing).offset(15)
  68 + }
  69 +
  70 + descriptionLabel.snp.makeConstraints { make in
  71 + make.top.equalTo(titleLabel.snp.bottom).offset(5)
  72 + make.leading.equalTo(titleLabel.snp.leading)
  73 + make.bottom.equalToSuperview().offset(-22)
  74 + }
  75 +
  76 + arrowImageView.snp.makeConstraints { make in
  77 + make.centerY.equalToSuperview()
  78 + make.trailing.equalTo(snp.trailing).offset(-28)
  79 + }
  80 + }
  81 +}
  82 +
... ...
  1 +//
  2 +// SettingsView.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 08.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class SettingsView: UIView {
  11 + var backButton: UIButton = {
  12 + var obj = UIButton()
  13 + obj.setImage(UIImage(named: .Image.backPointer), for: .normal)
  14 + obj.backgroundColor = .white
  15 + obj.layer.borderColor = .BorderColor.lightGrey
  16 + obj.layer.cornerRadius = 13
  17 + obj.layer.borderWidth = 1
  18 + return obj
  19 + }()
  20 +
  21 + var logoImage: UIImageView = {
  22 + var obj = UIImageView()
  23 + obj.image = UIImage(named: .Image.USA)
  24 + return obj
  25 + }()
  26 +
  27 + var gearImage: UIImageView = {
  28 + var obj = UIImageView()
  29 + obj.image = UIImage(named: .Image.gear)
  30 + return obj
  31 + }()
  32 +
  33 + let settingsLabel: UILabel = {
  34 + var obj = UILabel()
  35 + obj.font = .skModernist(type: .bold, ofSize: 35)
  36 + obj.text = .Text.settings
  37 + return obj
  38 + }()
  39 +
  40 + let settingsTableView: UITableView = {
  41 + let obj = UITableView()
  42 + return obj
  43 + }()
  44 +
  45 + var logoutButton: UIButton = {
  46 + var obj = UIButton()
  47 + obj.backgroundColor = .Background.lightRed?.withAlphaComponent(0.07)
  48 + obj.setTitle(.Text.logout, for: .normal)
  49 + obj.setTitleColor(.TextColor.redError, for: .normal)
  50 + obj.layer.cornerRadius = 15
  51 + return obj
  52 + }()
  53 +
  54 + override init(frame: CGRect) {
  55 + super.init(frame: frame)
  56 + backgroundColor = .white
  57 + setup()
  58 + }
  59 +
  60 + required init?(coder: NSCoder) {
  61 + fatalError("init(coder:) has not been implemented")
  62 + }
  63 +
  64 + func setup() {
  65 + addSubview(backButton)
  66 + addSubview(logoImage)
  67 + addSubview(gearImage)
  68 + addSubview(settingsLabel)
  69 + addSubview(settingsTableView)
  70 + addSubview(logoutButton)
  71 +
  72 + backButton.snp.makeConstraints {
  73 + $0.top.equalTo(snp.top).offset(66)
  74 + $0.leading.equalTo(snp.leading).offset(25)
  75 + $0.height.width.equalTo(45)
  76 + }
  77 +
  78 + logoImage.snp.makeConstraints {
  79 + $0.leading.equalTo(backButton.snp.trailing).offset(20)
  80 + $0.top.equalTo(snp.top).offset(79)
  81 + }
  82 +
  83 + gearImage.snp.makeConstraints {
  84 + $0.trailing.equalTo(snp.trailing)
  85 + $0.top.equalTo(snp.top).offset(106)
  86 + }
  87 +
  88 + settingsLabel.snp.makeConstraints {
  89 + $0.leading.equalTo(backButton.snp.leading)
  90 + $0.top.equalTo(backButton.snp.bottom).offset(46)
  91 + }
  92 +
  93 + settingsTableView.snp.makeConstraints { make in
  94 + make.leading.trailing.equalToSuperview()
  95 + make.top.equalTo(settingsLabel.snp.bottom).offset(85)
  96 + }
  97 +
  98 + logoutButton.snp.makeConstraints {
  99 + $0.top.equalTo(settingsTableView.snp.bottom).offset(42)
  100 + $0.leading.equalTo(snp.leading).offset(25)
  101 + $0.trailing.equalTo(snp.trailing).offset(-26)
  102 + $0.height.equalTo(56)
  103 + $0.bottom.equalToSuperview().offset(-51)
  104 + }
  105 + }
  106 +}
  107 +
... ...
  1 +//
  2 +// SettingsViewController.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 08.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class SettingsViewController: UIViewController {
  11 + var logoutMessage: String?
  12 + var mainView = SettingsView()
  13 + let settingsModel = SettingsModel.allCases
  14 +
  15 + override func loadView() {
  16 + view = mainView
  17 + }
  18 + override func viewDidLoad() {
  19 + super.viewDidLoad()
  20 + initViewController()
  21 + }
  22 +
  23 + private func initViewController() {
  24 + mainView.settingsTableView.delegate = self
  25 + mainView.settingsTableView.dataSource = self
  26 +
  27 + mainView.settingsTableView.registerReusableCell(DisplayNameCell.self)
  28 + mainView.settingsTableView.registerReusableCell(SettingsSwitchCell.self)
  29 + mainView.settingsTableView.registerReusableCell(SettingsTableViewCell.self)
  30 +
  31 + mainView.backButton.addTarget(self, action: #selector(didShowHomeVC), for: .touchUpInside)
  32 + mainView.logoutButton.addTarget(self, action: #selector(didTapLogoutButton), for: .touchUpInside)
  33 + }
  34 +}
  35 +//MARK: - Delegate
  36 +extension SettingsViewController {
  37 + @objc private func didShowHomeVC() {
  38 + navigationController?.popViewController(animated: true)
  39 + }
  40 +
  41 + @objc private func didTapLogoutButton() {
  42 + logoutRequestProcessing()
  43 +
  44 + }
  45 +
  46 + func logoutRequestProcessing() {
  47 + guard let logoutModel = getLogoutModel() else { return }
  48 + AuthService.shared.logoutRequest(model: logoutModel) { response in
  49 + self.logoutMessage = response.message
  50 + self.logoutDataProcessing()
  51 + print("5️⃣❇️\(response.message ?? "Data not received!")❇️")
  52 + } fail: { error in
  53 + self.logoutErrorProcessing()
  54 + print("5️⃣❗️\(error)❗️")
  55 + }
  56 + }
  57 +
  58 + func getLogoutModel() -> LogoutRequestModel? {
  59 + guard let deviceUUID = UIDevice.current.identifierForVendor?.uuidString else {
  60 + return nil
  61 + }
  62 + return LogoutRequestModel(deviceUUID: deviceUUID)
  63 + }
  64 +
  65 + private func logoutDataProcessing() {
  66 + let alert = UIAlertController(title: "Do you really want to logout?", message: "", preferredStyle: .alert)
  67 + alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { action in
  68 + let vc = VerificationViewController()
  69 + self.navigationController?.pushViewController(vc, animated: true)
  70 + }))
  71 + alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: nil))
  72 + present(alert, animated: true, completion: nil)
  73 + }
  74 +
  75 + private func logoutErrorProcessing() {
  76 + if logoutMessage != "OK" {
  77 + let alert = UIAlertController(title: "Some network problems", message: "", preferredStyle: .alert)
  78 + alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
  79 + present(alert, animated: true, completion: nil)
  80 + } else {
  81 + let vc = VerificationViewController()
  82 + self.navigationController?.pushViewController(vc, animated: true)
  83 + }
  84 + }
  85 +}
  86 +
  87 +//MARK: tableView delegate and datasource
  88 +extension SettingsViewController: UITableViewDelegate, UITableViewDataSource {
  89 + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  90 + return settingsModel.count
  91 + }
  92 +
  93 + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  94 + let row = indexPath.row
  95 + let model: SettingsModel = settingsModel[row]
  96 +
  97 + switch model {
  98 + case .displayName:
  99 + let cell: DisplayNameCell = tableView.dequeueReusableCell(for: indexPath)
  100 + cell.titleLabel.text = model.getTitle()
  101 + cell.descriptionLabel.text = model.getDescription()
  102 + cell.settingsIcon.image = model.getIcon()
  103 + return cell
  104 + case .doNotDisturb, .ringtone:
  105 + let cell: SettingsSwitchCell = tableView.dequeueReusableCell(for: indexPath)
  106 + cell.titleLabel.text = model.getTitle()
  107 + cell.descriptionLabel.text = model.getDescription()
  108 + cell.settingsIcon.image = model.getIcon()
  109 + return cell
  110 + case .editResidents, .widgetLock:
  111 + let cell: SettingsTableViewCell = tableView.dequeueReusableCell(for: indexPath)
  112 + cell.titleLabel.text = model.getTitle()
  113 + cell.descriptionLabel.text = model.getDescription()
  114 + cell.settingsIcon.image = model.getIcon()
  115 + return cell
  116 + }
  117 + }
  118 + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  119 + if indexPath.row == 3 {
  120 + let vc = ChooseApartmentsViewController()
  121 + navigationController?.pushViewController(vc, animated: true)
  122 + }
  123 + }
  124 +}
  125 +
... ...
  1 +//
  2 +// PhoneNumberView.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 31.05.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +import CoreTelephony
  10 +
  11 +class PhoneNumberView: UIView {
  12 + var containerPickerView: UIView = {
  13 + var view = UIView()
  14 + view.backgroundColor = .systemRed
  15 + return view
  16 + }()
  17 +
  18 + var titleButton: UIButton = {
  19 + var obj = UIButton()
  20 + obj.setTitle(.Text.selectYourCountry, for: .normal)
  21 + obj.setTitleColor(.TextColor.darkBlue, for: .normal)
  22 + obj.titleLabel?.font = .skModernist(type: .bold, ofSize: 18)
  23 + obj.titleLabel?.textAlignment = .center
  24 + return obj
  25 + }()
  26 +
  27 + var dividingLineView: UIView = {
  28 + var view = UIView()
  29 + view.backgroundColor = .Background.lightGrey
  30 + return view
  31 + }()
  32 +
  33 + var phoneNumberPicker: UIPickerView = {
  34 + var picker = UIPickerView()
  35 + return picker
  36 + }()
  37 +
  38 + var gradientBG: CAGradientLayer = {
  39 + let obj = CAGradientLayer()
  40 + var leftColor = CGColor.GradientBlue.left
  41 + var rightColor = CGColor.GradientBlue.right
  42 + obj.colors = [leftColor, rightColor]
  43 + obj.startPoint = CGPoint(x: 0, y: 0.5)
  44 + obj.endPoint = CGPoint(x: 1, y: 0.5)
  45 + return obj
  46 + }()
  47 +
  48 + var selectButton: UIButton = {
  49 + var button = UIButton()
  50 + button.clipsToBounds = true
  51 + button.layer.masksToBounds = true
  52 + return button
  53 + }()
  54 +
  55 + var selectLabel: UILabel = {
  56 + var label = UILabel()
  57 + label.text = .Text.select
  58 + label.font = .skModernist(type: .bold, ofSize: 16)
  59 + label.textColor = .white
  60 + return label
  61 + }()
  62 +
  63 + override init(frame: CGRect) {
  64 + super.init(frame: frame)
  65 + layout()
  66 + setup()
  67 + backgroundColor = .white
  68 + }
  69 +
  70 + required init?(coder: NSCoder) {
  71 + fatalError("init(coder:) has not been implemented")
  72 + }
  73 +
  74 + func layout() {
  75 + self.backgroundColor = .white
  76 + addSubview(titleButton)
  77 + addSubview(dividingLineView)
  78 + addSubview(phoneNumberPicker)
  79 + addSubview(selectButton)
  80 +
  81 + selectButton.layer.addSublayer(gradientBG)
  82 + selectButton.addSubview(selectLabel)
  83 +
  84 + titleButton.snp.makeConstraints { make in
  85 + make.top.equalToSuperview().offset(20)
  86 + make.leading.trailing.equalToSuperview()
  87 + }
  88 +
  89 + dividingLineView.snp.makeConstraints {
  90 + $0.left.right.equalToSuperview()
  91 + $0.height.equalTo(1)
  92 + $0.top.equalTo(titleButton.snp.bottom).offset(22)
  93 + }
  94 + phoneNumberPicker.snp.makeConstraints {
  95 + $0.left.right.equalToSuperview().inset(5)
  96 + $0.top.equalTo(dividingLineView.snp.bottom).offset(20)
  97 + }
  98 + selectButton.snp.makeConstraints {
  99 + $0.right.equalToSuperview()
  100 + $0.left.equalToSuperview()
  101 + $0.bottom.equalToSuperview()
  102 + $0.height.equalTo(70)
  103 + $0.top.equalTo(phoneNumberPicker.snp.bottom).offset(20)
  104 + }
  105 + selectLabel.snp.makeConstraints {
  106 + $0.centerX.equalTo(selectButton.snp.centerX)
  107 + $0.top.equalTo(selectButton.snp.top).offset(20)
  108 + }
  109 + }
  110 +
  111 + override func layoutSubviews() {
  112 + super.layoutSubviews()
  113 + gradientBG.frame = selectButton.bounds
  114 + }
  115 +}
  116 +
  117 +extension PhoneNumberView {
  118 + func setup() {
  119 + let countryCode: String
  120 + if let carrier = CTTelephonyNetworkInfo().serviceSubscriberCellularProviders?.first?.value,
  121 + let code = carrier.isoCountryCode?.uppercased() {
  122 + countryCode = code
  123 + } else {
  124 + countryCode = "USA"
  125 + }
  126 + phoneNumberPicker.selectRow(0, inComponent: 0, animated: true)
  127 + phoneNumberPicker.subviews[1].backgroundColor = .clear
  128 + }
  129 +}
  130 +
... ...
  1 +//
  2 +// PickerView.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 01.06.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +final class PickerView: UIView {
  11 +
  12 + private let iconView: UIImageView = {
  13 + var obj = UIImageView()
  14 + obj.contentMode = .scaleAspectFill
  15 + obj.layer.cornerRadius = 10
  16 + return obj
  17 + }()
  18 + private let label: UILabel = {
  19 + var obj = UILabel()
  20 + obj.textColor = .TextColor.darkBlue
  21 + obj.font = .skModernist(type: .bold, ofSize: 15)
  22 + return obj
  23 + }()
  24 + private let countryCode: UILabel = {
  25 + var obj = UILabel()
  26 + obj.textColor = .TextColor.darkBlue
  27 + obj.font = .skModernist(type: .bold, ofSize: 15)
  28 + return obj
  29 + }()
  30 + override init(frame: CGRect) {
  31 + super.init(frame: frame)
  32 + setup()
  33 + }
  34 +
  35 + required init?(coder: NSCoder) {
  36 + super.init(coder: coder)
  37 + setup()
  38 + }
  39 +
  40 + private func setup() {
  41 + addSubview(iconView)
  42 + addSubview(label)
  43 + addSubview(countryCode)
  44 +
  45 + iconView.snp.makeConstraints { make in
  46 + make.leading.equalToSuperview().offset(25)
  47 + make.centerY.equalTo(snp.centerY)
  48 + make.height.width.equalTo(20)
  49 + }
  50 +
  51 + label.snp.makeConstraints { make in
  52 + make.leading.equalTo(iconView.snp.trailing).offset(20)
  53 + make.top.bottom.equalToSuperview()
  54 + }
  55 +
  56 + countryCode.snp.makeConstraints { make in
  57 + make.trailing.equalToSuperview().offset(-25)
  58 + make.top.bottom.equalToSuperview()
  59 + }
  60 + }
  61 +
  62 + static func create(icon: UIImage, title: String, code: String) -> PickerView {
  63 + let numberView = PickerView()
  64 + numberView.iconView.image = icon
  65 + numberView.label.text = title
  66 + numberView.countryCode.text = code
  67 + return numberView
  68 + }
  69 +}
... ...
  1 +//
  2 +// VerificationView.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 30.05.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +import UIKit
  10 +
  11 +class VerificationView: UIView {
  12 + var isShow: Bool = false
  13 +
  14 + var logoImage: UIImageView = {
  15 + var view = UIImageView()
  16 + view.image = UIImage(named: .Image.USA)
  17 + return view
  18 + }()
  19 +
  20 + var greetingsLabel: UILabel = {
  21 + var label = UILabel()
  22 + label.text = .Text.hello
  23 + label.font = .skModernist(type: .bold, ofSize: 35)
  24 + return label
  25 + }()
  26 +
  27 + var verifyLabel: UILabel = {
  28 + var label = UILabel()
  29 + label.text = .Text.letsVerifyYourAccount
  30 + label.numberOfLines = 2
  31 + label.font = .skModernist(type: .regular, ofSize: 28)
  32 + return label
  33 + }()
  34 +
  35 + var shieldImage: UIImageView = {
  36 + var view = UIImageView()
  37 + view.image = UIImage(named: .Image.shield)
  38 + return view
  39 + }()
  40 +
  41 + var chooseLabel: UILabel = {
  42 + var label = UILabel()
  43 + label.text = .Text.chooseWhatToStartWith
  44 + label.font = .skModernist(type: .bold, ofSize: 16)
  45 + return label
  46 + }()
  47 +
  48 + var emailButton: Checkbox = {
  49 + var button = Checkbox()
  50 + button.checkboxTitle = .Text.email
  51 + button.isSelected = true
  52 + return button
  53 + }()
  54 +
  55 + var phoneNumberButton: Checkbox = {
  56 + var button = Checkbox()
  57 + button.checkboxTitle = .Text.phoneNumber
  58 + return button
  59 + }()
  60 +
  61 + var dividingLineView: UIView = {
  62 + var view = UIView()
  63 + view.backgroundColor = .Background.lightGrey
  64 + return view
  65 + }()
  66 +
  67 + var enterChosenAuthenticatorLabel: UILabel = {
  68 + var label = UILabel()
  69 + label.text = .Text.enterYourEmailAddress
  70 + label.font = UIFont(name: SkModernistFontType.bold.rawValue, size: 16)
  71 + return label
  72 + }()
  73 +
  74 + var emailTextField: UITextField = {
  75 + var textField = UITextField()
  76 + textField.backgroundColor = .TextFieldColor.general
  77 + textField.textAlignment = .left
  78 + textField.layer.cornerRadius = 15
  79 + textField.keyboardType = .emailAddress
  80 + textField.placeholder = .Text.exampleEmail
  81 + textField.font = .skModernist(type: .regular, ofSize: 15)
  82 + textField.layer.masksToBounds = true
  83 + textField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 22, height: textField.frame.height))
  84 + textField.leftViewMode = .always
  85 + textField.returnKeyType = .done
  86 + return textField
  87 + }()
  88 +
  89 + var phoneTextField: TextFieldWithPadding = {
  90 + var textField = TextFieldWithPadding()
  91 + textField.backgroundColor = .TextFieldColor.general
  92 + textField.textAlignment = .left
  93 + textField.layer.cornerRadius = 15
  94 + textField.keyboardType = .phonePad
  95 + textField.text = .Text.plusOne
  96 + textField.font = .skModernist(type: .regular, ofSize: 15)
  97 + textField.layer.masksToBounds = true
  98 + textField.isHidden = true
  99 + textField.textPadding = UIEdgeInsets(top: 0, left: 75, bottom: 0, right: 15)
  100 + return textField
  101 + }()
  102 +
  103 + var verificationDescriptionLabel: UILabel = {
  104 + var label = UILabel()
  105 + label.numberOfLines = 0
  106 + label.text = .Text.verificationCodeWillBeSentToYourEmail
  107 + label.font = .skModernist(type: .regular, ofSize: 14)
  108 + return label
  109 + }()
  110 +
  111 + var continueButton: UIButton = {
  112 + var button = UIButton()
  113 + button.setImage(UIImage(named: .Image.RectangleWithShadow), for: .normal)
  114 + button.clipsToBounds = true
  115 + button.contentMode = .scaleAspectFit
  116 + button.layer.cornerRadius = 15
  117 + return button
  118 + }()
  119 +
  120 + var continueLabel: UILabel = {
  121 + var label = UILabel()
  122 + label.text = .Text.continueText
  123 + label.font = .skModernist(type: .bold, ofSize: 16)
  124 + label.textColor = .white
  125 + return label
  126 + }()
  127 +
  128 + var pointerImage: UIImageView = {
  129 + var image = UIImageView()
  130 + image.image = UIImage(named: .Image.pointer)
  131 + return image
  132 + }()
  133 +
  134 + var phonePickerView: PhoneNumberView = {
  135 + var view = PhoneNumberView()
  136 + view.isUserInteractionEnabled = true
  137 + return view
  138 + }()
  139 +
  140 + var showPickerButton: UIButton = {
  141 + var button = UIButton()
  142 + button.isHidden = true
  143 + return button
  144 + }()
  145 +
  146 + var flagPickerView: UIImageView = {
  147 + var image = UIImageView()
  148 + image.image = UIImage(named: .Image.USA)
  149 + image.layer.cornerRadius = 11
  150 + image.contentMode = .scaleAspectFit
  151 + return image
  152 + }()
  153 +
  154 + var flagPointerView: UIImageView = {
  155 + var image = UIImageView()
  156 + image.image = UIImage(named: .Image.flagPointer)
  157 + return image
  158 + }()
  159 +
  160 + override init(frame: CGRect) {
  161 + super.init(frame: frame)
  162 + backgroundColor = .white
  163 + setup()
  164 + }
  165 +
  166 + required init?(coder: NSCoder) {
  167 + fatalError("init(coder:) has not been implemented")
  168 + }
  169 +
  170 + func setup() {
  171 + addSubview(logoImage)
  172 + addSubview(greetingsLabel)
  173 + addSubview(verifyLabel)
  174 + addSubview(shieldImage)
  175 +
  176 + addSubview(chooseLabel)
  177 + addSubview(emailButton)
  178 + addSubview(phoneNumberButton)
  179 + addSubview(dividingLineView)
  180 +
  181 + addSubview(enterChosenAuthenticatorLabel)
  182 + addSubview(emailTextField)
  183 + addSubview(phoneTextField)
  184 + addSubview(verificationDescriptionLabel)
  185 + phoneTextField.addSubview(showPickerButton)
  186 +
  187 + showPickerButton.addSubview(flagPickerView)
  188 + showPickerButton.addSubview(flagPointerView)
  189 +
  190 + addSubview(continueButton)
  191 + continueButton.addSubview(continueLabel)
  192 + continueButton.addSubview(pointerImage)
  193 +
  194 + addSubview(phonePickerView)
  195 +
  196 + logoImage.snp.makeConstraints {
  197 + $0.top.equalTo(snp.top).offset(80)
  198 + $0.left.equalTo(snp.left).offset(27)
  199 + }
  200 +
  201 + greetingsLabel.snp.makeConstraints {
  202 + $0.top.equalTo(logoImage.snp.bottom).offset(42)
  203 + $0.left.equalTo(snp.left).offset(24)
  204 + }
  205 +
  206 + shieldImage.snp.makeConstraints {
  207 + $0.right.equalToSuperview()
  208 + $0.top.equalTo(logoImage.snp.bottom).offset(27)
  209 + }
  210 +
  211 + verifyLabel.snp.makeConstraints {
  212 + $0.left.equalTo(27)
  213 + $0.top.equalTo(greetingsLabel.snp.bottom).offset(10)
  214 + }
  215 +
  216 + chooseLabel.snp.makeConstraints {
  217 + $0.top.equalTo(shieldImage.snp.bottom).offset(52)
  218 + $0.left.equalTo(snp.left).offset(27)
  219 + }
  220 +
  221 + emailButton.snp.makeConstraints {
  222 + $0.left.equalTo(snp.left).offset(27)
  223 + $0.top.equalTo(chooseLabel.snp.bottom).offset(29)
  224 + $0.height.equalTo(20)
  225 + }
  226 +
  227 + phoneNumberButton.snp.makeConstraints {
  228 + $0.top.equalTo(emailButton.snp.top)
  229 + $0.height.equalTo(20)
  230 + $0.left.equalTo(emailButton.snp.right).offset(44)
  231 + }
  232 +
  233 + dividingLineView.snp.makeConstraints {
  234 + $0.left.right.equalToSuperview()
  235 + $0.top.equalTo(emailButton.snp.bottom).offset(41)
  236 + $0.height.equalTo(1)
  237 + }
  238 +
  239 + enterChosenAuthenticatorLabel.snp.makeConstraints {
  240 + $0.top.equalTo(dividingLineView.snp.bottom).offset(39)
  241 + $0.left.equalTo(logoImage.snp.left)
  242 + }
  243 +
  244 + emailTextField.snp.makeConstraints {
  245 + $0.left.equalTo(logoImage.snp.left)
  246 + $0.right.equalTo(snp.right).offset(-27)
  247 + $0.top.equalTo(enterChosenAuthenticatorLabel.snp.bottom).offset(23)
  248 + $0.height.equalTo(57)
  249 + }
  250 +
  251 + phoneTextField.snp.makeConstraints {
  252 + $0.left.equalTo(logoImage.snp.left)
  253 + $0.right.equalTo(snp.right).offset(-27)
  254 + $0.top.equalTo(enterChosenAuthenticatorLabel.snp.bottom).offset(23)
  255 + $0.height.equalTo(57)
  256 + }
  257 +
  258 + verificationDescriptionLabel.snp.makeConstraints {
  259 + $0.top.equalTo(emailTextField.snp.bottom).offset(8)
  260 + $0.left.equalTo(snp.left).offset(46)
  261 + $0.right.equalTo(snp.right).offset(-22)
  262 + }
  263 +
  264 + continueButton.snp.makeConstraints {
  265 + $0.left.equalTo(snp.left)
  266 + $0.right.equalTo(snp.right)
  267 + $0.top.equalTo(emailTextField.snp.bottom).offset(90)
  268 + $0.height.equalTo(125)
  269 + }
  270 +
  271 + continueLabel.snp.makeConstraints {
  272 + $0.left.equalTo(snp.left).offset(48)
  273 + $0.top.equalTo(continueButton.snp.top).offset(33)
  274 + }
  275 +
  276 + pointerImage.snp.makeConstraints {
  277 + $0.top.equalTo(continueButton.snp.top).offset(31)
  278 + $0.right.equalTo(snp.right).offset(-51.5)
  279 + }
  280 +
  281 + phonePickerView.snp.makeConstraints { make in
  282 + make.leading.trailing.equalToSuperview()
  283 + make.height.equalTo(390)
  284 + make.top.equalTo(self.snp.bottom)
  285 + }
  286 +
  287 + showPickerButton.snp.makeConstraints {
  288 + $0.height.equalTo(22)
  289 + $0.width.equalTo(50)
  290 + $0.left.equalTo(emailTextField.snp.left).offset(22)
  291 + $0.top.equalTo(emailTextField.snp.top).offset(18)
  292 + }
  293 +
  294 + flagPickerView.snp.makeConstraints {
  295 + $0.left.equalToSuperview()
  296 + $0.size.equalTo(20)
  297 + $0.centerY.equalTo(showPickerButton.snp.centerY)
  298 + }
  299 +
  300 + flagPointerView.snp.makeConstraints {
  301 + $0.left.equalTo(flagPickerView.snp.right).offset(10)
  302 + $0.centerYWithinMargins.equalTo(flagPickerView.snp.centerYWithinMargins)
  303 + }
  304 + }
  305 +
  306 + func showPickerView() {
  307 + UIView.animate(withDuration: 0.3) {
  308 + self.phonePickerView.snp.updateConstraints { make in
  309 + make.top.equalTo(self.snp.bottom).offset(-390)
  310 + }
  311 + self.layoutIfNeeded()
  312 + }
  313 + }
  314 +
  315 + func hidePickerView() {
  316 + UIView.animate(withDuration: 0.3) {
  317 + self.phonePickerView.snp.updateConstraints { make in
  318 + make.top.equalTo(self.snp.bottom).offset(0)
  319 + }
  320 + self.layoutIfNeeded()
  321 + }
  322 + }
  323 +
  324 + func handleUI(_ isChanged: Bool) {
  325 + emailTextField.isHidden = !isChanged
  326 + phoneTextField.isHidden = isChanged
  327 + verificationDescriptionLabel.text = isChanged ? .Text.verificationCodeWillBeSentToYourEmail : .Text.verificationCodeWillBeSentToYourNumber
  328 + enterChosenAuthenticatorLabel.text = isChanged ? .Text.enterYourEmailAddress : .Text.enterYourPhoneNumber
  329 + emailTextField.text = isChanged ? "" : .Text.plusOne
  330 + showPickerButton.isHidden = isChanged
  331 + }
  332 +}
... ...
  1 +//
  2 +// ViewController.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 30.05.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class VerificationViewController: UIViewController {
  11 + var isKeyboardAppear = false
  12 + var startMessage: String?
  13 + private let mainView = VerificationView()
  14 + var closeTap: UITapGestureRecognizer?
  15 +
  16 + lazy var phonePickerModels: [PhonePickerModel] = {
  17 + var models: [PhonePickerModel] = []
  18 +
  19 + for (code, value) in PhoneService.phones
  20 + {
  21 + models.append(.init(code: code, countryCode: value.1, title: value.0, icon: value.2))
  22 + }
  23 + return models
  24 + }()
  25 +
  26 + deinit {
  27 + NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
  28 + NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
  29 + }
  30 +
  31 + override func loadView() {
  32 + view = mainView
  33 + }
  34 +
  35 + override func viewDidLoad() {
  36 + super.viewDidLoad()
  37 + initViewController()
  38 + }
  39 +
  40 + private func initViewController() {
  41 + addDoneButtonOnKeyboard()
  42 +
  43 + mainView.emailTextField.delegate = self
  44 + mainView.phoneTextField.delegate = self
  45 +
  46 + mainView.phonePickerView.phoneNumberPicker.delegate = self
  47 + mainView.phonePickerView.phoneNumberPicker.dataSource = self
  48 +
  49 + mainView.phoneNumberButton.addTarget(self, action: #selector(didCheckboxTapped(_:)), for: .touchUpInside)
  50 + mainView.emailButton.addTarget(self, action: #selector(didCheckboxTapped(_:)), for: .touchUpInside)
  51 + mainView.showPickerButton.addTarget(self, action: #selector(didshowPickerButtonTapped(_:)), for: .touchUpInside)
  52 + mainView.phonePickerView.selectButton.addTarget(self, action: #selector(didshowPickerButtonTapped(_:)), for: .touchUpInside)
  53 + mainView.phonePickerView.titleButton.addTarget(self, action: #selector(didshowPickerButtonTapped(_:)), for: .touchDragInside)
  54 + mainView.continueButton.addTarget(self, action: #selector(didTapContinueButton), for: .touchUpInside)
  55 +
  56 + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
  57 + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
  58 + }
  59 +
  60 + private func initDevice() {
  61 + guard let model = getInitModel() else {
  62 + return
  63 + }
  64 + AuthService.shared.initRequest(model: model) { result in
  65 + print("1️⃣✅\(result.message)✅")
  66 + self.startRequestProcessing()
  67 + } fail: { error in
  68 + print("1️⃣\(error)")
  69 + let alert = UIAlertController(title: "Error", message: "", preferredStyle: .alert)
  70 + alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
  71 + self.present(alert, animated: true, completion: nil)
  72 + }
  73 + }
  74 +
  75 + func getInitModel() -> InitRequestModel? {
  76 + guard let deviceUUID = UIDevice.current.identifierForVendor?.uuidString else {
  77 + return nil
  78 + }
  79 + guard let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String else {
  80 + return nil
  81 + }
  82 + return InitRequestModel(deviceUUID: deviceUUID,
  83 + manufacturer: .Text.apple,
  84 + model: UIDevice.current.model,
  85 + platform: UIDevice.current.systemName,
  86 + osVersion: UIDevice.current.systemVersion,
  87 + appVersion: appVersion)
  88 + }
  89 +
  90 + private func startRequestProcessing() {
  91 + guard let startModel = startModelFilling() else { return }
  92 + AuthService.shared.startRequest(model: startModel) { response in
  93 + self.startMessage = response.message
  94 + print("2️⃣✅\(response.message)✅")
  95 + self.didShowCodeVerificationVC()
  96 + } fail: { error in
  97 + print("2️⃣❌\(error)❌")
  98 + self.errorProcessing()
  99 + }
  100 + }
  101 +
  102 + func didShowCodeVerificationVC() {
  103 + if startMessage == "SMS successfully sent" {
  104 + let viewController = CodeVerificationViewController()
  105 + viewController.navigationItem.hidesBackButton = true
  106 + navigationController?.pushViewController(viewController, animated: true)
  107 + } else {
  108 + userDoesNotExistNotice()
  109 + }
  110 +
  111 + }
  112 +
  113 + private func userDoesNotExistNotice() {
  114 + let alert = UIAlertController(title: "User does not exist", message: "Try again", preferredStyle: .alert)
  115 + alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
  116 + present(alert, animated: true)
  117 + }
  118 +
  119 + private func errorProcessing() {
  120 + let alert = UIAlertController(title: "Network error", message: "Try again later", preferredStyle: .alert)
  121 + alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
  122 + present(alert, animated: true)
  123 + }
  124 +
  125 + func startModelFilling() -> StartRequestModel? {
  126 + let number = mainView.phoneTextField.text
  127 + let email = mainView.emailTextField.text
  128 + if number == nil {
  129 + return StartRequestModel(emailOrNumber: (String(describing: email)))
  130 + } else {
  131 + return StartRequestModel(emailOrNumber: (String(describing: number)))
  132 + }
  133 + }
  134 +
  135 + private func addDoneButtonOnKeyboard() {
  136 + let doneToolbar: UIToolbar = UIToolbar(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
  137 + doneToolbar.barStyle = .default
  138 +
  139 + let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
  140 + let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(self.doneButtonAction))
  141 +
  142 + let items = [flexSpace, done]
  143 + doneToolbar.items = items
  144 + doneToolbar.sizeToFit()
  145 +
  146 + mainView.phoneTextField.inputAccessoryView = doneToolbar
  147 + }
  148 +
  149 + @objc private func doneButtonAction(){
  150 + mainView.phoneTextField.resignFirstResponder()
  151 + }
  152 +}
  153 +
  154 +//MARK: helpers and handlers
  155 +extension VerificationViewController {
  156 +
  157 +}
  158 +
  159 +//MARK: targets
  160 +extension VerificationViewController {
  161 + @objc private func didCheckboxTapped(_ sender: Checkbox) {
  162 + switch sender {
  163 + case mainView.emailButton :
  164 + sender.isSelected = true
  165 + mainView.phoneNumberButton.isSelected = false
  166 + mainView.handleUI(true)
  167 + mainView.phoneTextField.resignFirstResponder()
  168 + case mainView.phoneNumberButton:
  169 + sender.isSelected = true
  170 + mainView.emailButton.isSelected = false
  171 + mainView.handleUI(false)
  172 + mainView.emailTextField.resignFirstResponder()
  173 + default:
  174 + return
  175 + }
  176 + }
  177 +
  178 + @objc private func didshowPickerButtonTapped(_ sender: UIButton) {
  179 + mainView.isShow ? mainView.showPickerView() : mainView.hidePickerView()
  180 + mainView.isShow.toggle()
  181 + }
  182 +
  183 + @objc private func didTapContinueButton() {
  184 + validatingTheLoginField()
  185 + }
  186 +
  187 + private func validatingTheLoginField() {
  188 + guard let email = mainView.emailTextField.text else { return }
  189 + guard let number = mainView.phoneTextField.text else { return }
  190 +
  191 + if email.isEmpty || number.isEmpty{
  192 + let alert = UIAlertController(title: "Enter email or number fields", message: "", preferredStyle: .alert)
  193 + alert.addAction(UIAlertAction(title: "Ok", style: .cancel, handler: nil))
  194 + present(alert, animated: true)
  195 + } else {
  196 + initDevice()
  197 + }
  198 + }
  199 +
  200 + @objc private func keyboardWillShow(notification: NSNotification) {
  201 + let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double
  202 + if !isKeyboardAppear {
  203 + UIView.animate(withDuration: duration ?? 0) {
  204 + self.mainView.chooseLabel.snp.updateConstraints { make in
  205 + make.top.equalTo(self.mainView.shieldImage.snp.bottom).offset(0)
  206 + }
  207 + self.mainView.dividingLineView.snp.updateConstraints {
  208 + $0.top.equalTo(self.mainView.emailButton.snp.bottom).offset(10)
  209 + }
  210 + self.mainView.enterChosenAuthenticatorLabel.snp.updateConstraints {
  211 + $0.top.equalTo(self.mainView.dividingLineView.snp.bottom).offset(5)
  212 + }
  213 + self.mainView.layoutIfNeeded()
  214 + }
  215 + isKeyboardAppear = true
  216 + }
  217 + }
  218 +
  219 + @objc private func keyboardWillHide(notification: NSNotification) {
  220 + let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double
  221 +
  222 + if isKeyboardAppear {
  223 +
  224 + UIView.animate(withDuration: duration ?? 0) {
  225 + self.mainView.chooseLabel.snp.updateConstraints { make in
  226 + make.top.equalTo(self.mainView.shieldImage.snp.bottom).offset(52)
  227 + }
  228 + self.mainView.dividingLineView.snp.updateConstraints {
  229 + $0.top.equalTo(self.mainView.emailButton.snp.bottom).offset(41)
  230 + }
  231 + self.mainView.enterChosenAuthenticatorLabel.snp.updateConstraints {
  232 + $0.top.equalTo(self.mainView.dividingLineView.snp.bottom).offset(39)
  233 + }
  234 + self.mainView.layoutIfNeeded()
  235 + }
  236 + isKeyboardAppear = false
  237 + }
  238 + }
  239 +}
  240 +//MARK: - PickerView Delegate
  241 +extension VerificationViewController: UIPickerViewDataSource, UIPickerViewDelegate {
  242 + func numberOfComponents(in pickerView: UIPickerView) -> Int {
  243 + return 1
  244 + }
  245 +
  246 + func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
  247 + return phonePickerModels.count
  248 +
  249 + }
  250 +
  251 + func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
  252 + 60
  253 + }
  254 +
  255 + func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
  256 + let model = phonePickerModels[row]
  257 + return PickerView.create(icon: model.icon, title: model.title, code: model.countryCode)
  258 + }
  259 +
  260 + func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
  261 + pickerView.subviews[1].backgroundColor = .clear
  262 + let model = phonePickerModels[row]
  263 + mainView.phoneTextField.text = "\(model.countryCode)"
  264 + mainView.flagPickerView.image = model.icon
  265 + }
  266 +}
  267 +//MARK: - TextField delegate
  268 +extension VerificationViewController: UITextFieldDelegate {
  269 + func textFieldShouldReturn(_ textField: UITextField) -> Bool {
  270 + mainView.emailTextField.resignFirstResponder()
  271 + return true
  272 + }
  273 +}
  274 +
  275 +
... ...
  1 +//
  2 +// PhoneService.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 31.05.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +import UIKit
  10 +
  11 +class PhoneService {
  12 + static var phones: [String: (String, String, UIImage)] = {
  13 + var codes = [String: (String, String, UIImage)] ()
  14 + codes["USA"] = ("United States", "+1", UIImage(named: "USA") ?? UIImage())
  15 + codes["GB"] = ("Great Britain", "+123", UIImage(named: "GB") ?? UIImage())
  16 + codes["AUS"] = ("Australia", "+12", UIImage(named: "AUS") ?? UIImage())
  17 + return codes
  18 + }()
  19 +}
... ...
  1 +//
  2 +// ProtocolDelegare.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 17.06.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +import ContactsUI
  10 +
  11 +protocol ResidentSavable: AnyObject {
  12 + func save(_ data: ResidentModel)
  13 +}
... ...
  1 +//
  2 +// Reusable + Cell.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 19.06.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +import UIKit
  10 +
  11 +protocol Reusable: AnyObject {
  12 + static var reuseIdentifier: String { get }
  13 +}
  14 +
  15 +extension Reusable {
  16 + static var reuseIdentifier: String {
  17 + return String(describing: Self.self)
  18 + }
  19 +}
  20 +
  21 +// swiftlint:disable force_cast
  22 +
  23 +extension UICollectionView {
  24 + func registerReusableCell<T: UICollectionViewCell>(_: T.Type) where T: Reusable {
  25 + self.register(T.self, forCellWithReuseIdentifier: T.reuseIdentifier)
  26 + }
  27 +
  28 + func dequeueReusableCell<T: UICollectionViewCell>(for indexPath: IndexPath) -> T where T: Reusable {
  29 + return self.dequeueReusableCell(withReuseIdentifier: T.reuseIdentifier, for: indexPath) as! T
  30 + }
  31 +
  32 + func registerReusableSupplementaryView<T: UICollectionReusableView>(elementKind: String, _: T.Type) where T: Reusable {
  33 + self.register(T.self, forSupplementaryViewOfKind: elementKind, withReuseIdentifier: T.reuseIdentifier)
  34 + }
  35 +
  36 + func dequeueReusableSupplementaryView<T: UICollectionReusableView>(ofKind elementKind: String, for indexPath: IndexPath) -> T where T: Reusable {
  37 + return self.dequeueReusableSupplementaryView(ofKind: elementKind, withReuseIdentifier: T.reuseIdentifier, for: indexPath) as! T
  38 + }
  39 +}
  40 +
  41 +extension UITableView {
  42 + func registerReusableCell<T: UITableViewCell>(_: T.Type) where T: Reusable {
  43 + self.register(T.self, forCellReuseIdentifier: T.reuseIdentifier)
  44 + }
  45 +
  46 + func registerReusableView<T: UITableViewHeaderFooterView>(_: T.Type) where T: Reusable {
  47 + self.register(T.self, forHeaderFooterViewReuseIdentifier: T.reuseIdentifier)
  48 + }
  49 +
  50 + func dequeueReusableCell<T: UITableViewCell>(for indexPath: IndexPath) -> T where T: Reusable {
  51 + return self.dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as! T
  52 + }
  53 +
  54 + func dequeueReusableView<T: UITableViewHeaderFooterView>() -> T where T: Reusable {
  55 + return self.dequeueReusableHeaderFooterView(withIdentifier: T.reuseIdentifier) as! T
  56 + }
  57 +}
  58 +
... ...
  1 +//
  2 +// SceneDelegate.swift
  3 +// InterQR-Internship
  4 +//
  5 +// Created by Дмитрий Тимофеев on 30.05.2022.
  6 +//
  7 +
  8 +import UIKit
  9 +import SnapKit
  10 +
  11 +class SceneDelegate: UIResponder, UIWindowSceneDelegate {
  12 +
  13 + var window: UIWindow?
  14 +
  15 + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
  16 +
  17 + guard let windowScene = (scene as? UIWindowScene) else { return }
  18 + window = UIWindow(windowScene: windowScene)
  19 + let viewController = VerificationViewController()
  20 + let homeVC = HomeViewController()
  21 + let residentVC = ResidentsViewController()
  22 + let navigation = UINavigationController(rootViewController: viewController)
  23 + navigation.isNavigationBarHidden = true
  24 + window?.rootViewController = navigation
  25 + window?.makeKeyAndVisible()
  26 + }
  27 +}
  28 +
... ...
Please register or login to post a comment