git.iko.soy/dashared/hookah-tau
on develop help sign in
Второй шаг бронирования
commit228f35a8d6aa2c9065b200707faa36adc776ff55 authorDarya Rednikina <rednikina.com@yandex.ru> dateThu 21 Nov 2019, 23:04 (7 years ago) parent7e9dd45
25 files changed+1243−225
Hookah Tau.xcodeproj/project.pbxproj+40−8 Hookah Tau/Components/BlackButtonStyle.swift+8 Hookah Tau/Components/Button.swift+16 Hookah Tau/Components/TableButton.swift+54 Hookah Tau/Components/TableButtonStyle.swift+87 Hookah Tau/Controllers/Client/Reservations/Adress of reservation/AddresViewController.swift+6 Hookah Tau/Controllers/Client/Reservations/Adress of reservation/AddressCoordinator.swift+1−1 Hookah Tau/Controllers/Client/Reservations/Maps/MapView.swift+53−3 Hookah Tau/Controllers/Client/Reservations/Maps/MapView1.swift+89−50 Hookah Tau/Controllers/Client/Reservations/Maps/MapView1.xib+41−25 Hookah Tau/Controllers/Client/Reservations/Reservation.storyboard+35−3 Hookah Tau/Controllers/Client/Reservations/ReservationCoordinator.swift−34 Hookah Tau/Controllers/Client/Reservations/SecondStepReservationViewController.swift+89 Hookah Tau/Controllers/Client/Reservations/Steps/First/DateView.swift+2−2 Hookah Tau/Controllers/Client/Reservations/Steps/First/FirstStepView.swift+84−30 Hookah Tau/Controllers/Client/Reservations/Steps/First/FirstStepView.xib+25−1 Hookah Tau/Controllers/Client/Reservations/Steps/First/TimePointView.swift+2 Hookah Tau/Controllers/Client/Reservations/Steps/First/TimePointView.xib+2−2 Hookah Tau/Controllers/Client/Reservations/Steps/FirstStepReservationCoordinator.swift+53 Hookah Tau/Controllers/Client/Reservations/ReservationViewController.swift → Hookah Tau/Controllers/Client/Reservations/Steps/FirstStepReservationViewController.swift+61−31 Hookah Tau/Controllers/Client/Reservations/Steps/Second/SecondStepView.swift+189 Hookah Tau/Controllers/Client/Reservations/Steps/Second/SecondStepView.xib+154 Hookah Tau/Controllers/Client/Reservations/Steps/SecondStepReservationCoordinator.swift+38 Hookah Tau/Extensions+Date.swift+83−33 Hookah Tau/Models/AllReservations.swift+31−2
Hookah Tau.xcodeproj/project.pbxproj+40−8
@@ -31,10 +31,10 @@
3131 12838EB4236779C700CEF108 /* ApiResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12838EB3236779C700CEF108 /* ApiResolver.swift */; };
3232 12838EB623677FB900CEF108 /* ApiRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12838EB523677FB900CEF108 /* ApiRequest.swift */; };
3333 12838EB82367834900CEF108 /* MyCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12838EB72367834900CEF108 /* MyCodable.swift */; };
34− 12A075F72373535C00D749BB /* ReservationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12A075F62373535C00D749BB /* ReservationViewController.swift */; };
34+ 12A075F72373535C00D749BB /* FirstStepReservationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12A075F62373535C00D749BB /* FirstStepReservationViewController.swift */; };
3535 12A075F9237353F500D749BB /* MapView1.xib in Resources */ = {isa = PBXBuildFile; fileRef = 12A075F8237353F500D749BB /* MapView1.xib */; };
3636 12A075FB2373561A00D749BB /* Reservation.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 12A075FA2373561A00D749BB /* Reservation.storyboard */; };
37− 12A075FD237357E900D749BB /* ReservationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12A075FC237357E900D749BB /* ReservationCoordinator.swift */; };
37+ 12A075FD237357E900D749BB /* FirstStepReservationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12A075FC237357E900D749BB /* FirstStepReservationCoordinator.swift */; };
3838 12A075FF237358F200D749BB /* MapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12A075FE237358F200D749BB /* MapView.swift */; };
3939 12A07601237359BB00D749BB /* MapView1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12A07600237359BB00D749BB /* MapView1.swift */; };
4040 12B6A60F235B857A00898B31 /* ProfileChangeCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12B6A60E235B857A00898B31 /* ProfileChangeCoordinator.swift */; };
@@ -60,6 +60,12 @@
6060 12EB698123661CB300E4D1CE /* AddressCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12EB698023661CB300E4D1CE /* AddressCell.swift */; };
6161 12EE4A76234BB8FE005B4D1A /* CodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12EE4A75234BB8FE005B4D1A /* CodeView.swift */; };
6262 12F73B022357AD7B007D4476 /* ProfileChangeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12F73B012357AD7B007D4476 /* ProfileChangeViewController.swift */; };
63+ 12F9652723868DA300FCA696 /* SecondStepReservationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12F9652623868DA300FCA696 /* SecondStepReservationViewController.swift */; };
64+ 12F9652A23868E6000FCA696 /* SecondStepView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 12F9652923868E6000FCA696 /* SecondStepView.xib */; };
65+ 12F9652C23868E7200FCA696 /* SecondStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12F9652B23868E7200FCA696 /* SecondStepView.swift */; };
66+ 12F9652E23869F3100FCA696 /* SecondStepReservationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12F9652D23869F3100FCA696 /* SecondStepReservationCoordinator.swift */; };
67+ 12FC40382382C93D00AB593B /* TableButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12FC40372382C93C00AB593B /* TableButtonStyle.swift */; };
68+ 12FC403A2382CB6F00AB593B /* TableButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12FC40392382CB6F00AB593B /* TableButton.swift */; };
6369 12FE4042236B8B050012391E /* DataStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12FE4041236B8B050012391E /* DataStorage.swift */; };
6470 F30369B5233679EA00A8EA84 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F30369B4233679EA00A8EA84 /* LaunchScreen.storyboard */; };
6571 F30369BE2336924D00A8EA84 /* ClientTabbarCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F30369BD2336924D00A8EA84 /* ClientTabbarCoordinator.swift */; };
@@ -132,10 +138,10 @@
132138 12838EB3236779C700CEF108 /* ApiResolver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiResolver.swift; sourceTree = "<group>"; };
133139 12838EB523677FB900CEF108 /* ApiRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiRequest.swift; sourceTree = "<group>"; };
134140 12838EB72367834900CEF108 /* MyCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyCodable.swift; sourceTree = "<group>"; };
135− 12A075F62373535C00D749BB /* ReservationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReservationViewController.swift; sourceTree = "<group>"; };
141+ 12A075F62373535C00D749BB /* FirstStepReservationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstStepReservationViewController.swift; sourceTree = "<group>"; };
136142 12A075F8237353F500D749BB /* MapView1.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MapView1.xib; sourceTree = "<group>"; };
137143 12A075FA2373561A00D749BB /* Reservation.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Reservation.storyboard; sourceTree = "<group>"; };
138− 12A075FC237357E900D749BB /* ReservationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReservationCoordinator.swift; sourceTree = "<group>"; };
144+ 12A075FC237357E900D749BB /* FirstStepReservationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstStepReservationCoordinator.swift; sourceTree = "<group>"; };
139145 12A075FE237358F200D749BB /* MapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapView.swift; sourceTree = "<group>"; };
140146 12A07600237359BB00D749BB /* MapView1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapView1.swift; sourceTree = "<group>"; };
141147 12B6A60E235B857A00898B31 /* ProfileChangeCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileChangeCoordinator.swift; sourceTree = "<group>"; };
@@ -161,6 +167,12 @@
161167 12EB698023661CB300E4D1CE /* AddressCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressCell.swift; sourceTree = "<group>"; };
162168 12EE4A75234BB8FE005B4D1A /* CodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeView.swift; sourceTree = "<group>"; };
163169 12F73B012357AD7B007D4476 /* ProfileChangeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileChangeViewController.swift; sourceTree = "<group>"; };
170+ 12F9652623868DA300FCA696 /* SecondStepReservationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SecondStepReservationViewController.swift; path = "Hookah Tau/Controllers/Client/Reservations/SecondStepReservationViewController.swift"; sourceTree = SOURCE_ROOT; };
171+ 12F9652923868E6000FCA696 /* SecondStepView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SecondStepView.xib; sourceTree = "<group>"; };
172+ 12F9652B23868E7200FCA696 /* SecondStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondStepView.swift; sourceTree = "<group>"; };
173+ 12F9652D23869F3100FCA696 /* SecondStepReservationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondStepReservationCoordinator.swift; sourceTree = "<group>"; };
174+ 12FC40372382C93C00AB593B /* TableButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableButtonStyle.swift; sourceTree = "<group>"; };
175+ 12FC40392382CB6F00AB593B /* TableButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableButton.swift; sourceTree = "<group>"; };
164176 12FE4041236B8B050012391E /* DataStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataStorage.swift; sourceTree = SOURCE_ROOT; };
165177 F30369B4233679EA00A8EA84 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
166178 F30369BD2336924D00A8EA84 /* ClientTabbarCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientTabbarCoordinator.swift; sourceTree = "<group>"; };
@@ -260,8 +272,6 @@
260272 children = (
261273 12BD95AE237EBE52009614D8 /* Maps */,
262274 12BD95B3237EC231009614D8 /* Steps */,
263− 12A075FC237357E900D749BB /* ReservationCoordinator.swift */,
264− 12A075F62373535C00D749BB /* ReservationViewController.swift */,
265275 12A075FA2373561A00D749BB /* Reservation.storyboard */,
266276 1246B721235CDFC2004CBFA1 /* Cells */,
267277 1246B71A235CD4C5004CBFA1 /* Views */,
@@ -344,6 +354,11 @@
344354 12BD95B3237EC231009614D8 /* Steps */ = {
345355 isa = PBXGroup;
346356 children = (
357+ 12F9652623868DA300FCA696 /* SecondStepReservationViewController.swift */,
358+ 12F9652D23869F3100FCA696 /* SecondStepReservationCoordinator.swift */,
359+ 12A075F62373535C00D749BB /* FirstStepReservationViewController.swift */,
360+ 12A075FC237357E900D749BB /* FirstStepReservationCoordinator.swift */,
361+ 12F9652823868E4900FCA696 /* Second */,
347362 12BD95B4237EC23A009614D8 /* First */,
348363 );
349364 path = Steps;
@@ -419,6 +434,15 @@
419434 path = Code;
420435 sourceTree = "<group>";
421436 };
437+ 12F9652823868E4900FCA696 /* Second */ = {
438+ isa = PBXGroup;
439+ children = (
440+ 12F9652923868E6000FCA696 /* SecondStepView.xib */,
441+ 12F9652B23868E7200FCA696 /* SecondStepView.swift */,
442+ );
443+ path = Second;
444+ sourceTree = "<group>";
445+ };
422446 F30369B623367B2300A8EA84 /* Supporting Files */ = {
423447 isa = PBXGroup;
424448 children = (
@@ -458,6 +482,8 @@
458482 F3DC5A00233E896300B5E751 /* ButtonStyle.swift */,
459483 F3895F52233D5EEB00FA6A37 /* BlackButtonStyle.swift */,
460484 F3DC5A04233E89D500B5E751 /* Button.swift */,
485+ 12FC40372382C93C00AB593B /* TableButtonStyle.swift */,
486+ 12FC40392382CB6F00AB593B /* TableButton.swift */,
461487 );
462488 path = Components;
463489 sourceTree = "<group>";
@@ -729,6 +755,7 @@
729755 12387337234BB98700D1F1AB /* CodeView.xib in Resources */,
730756 12B6A615235BB36C00898B31 /* ChangeView.xib in Resources */,
731757 F3851B2C2340A280009EE0B6 /* TitleTextView.xib in Resources */,
758+ 12F9652A23868E6000FCA696 /* SecondStepView.xib in Resources */,
732759 1246B71E235CDF8A004CBFA1 /* ReservationView.xib in Resources */,
733760 12BD95B6237ED8AC009614D8 /* TimePointView.xib in Resources */,
734761 12A075F9237353F500D749BB /* MapView1.xib in Resources */,
@@ -780,6 +807,7 @@
780807 12838EB82367834900CEF108 /* MyCodable.swift in Sources */,
781808 F3DC5A05233E89D500B5E751 /* Button.swift in Sources */,
782809 F3FC7DFB2315C25D0080D851 /* ApplicationCoordinator.swift in Sources */,
810+ 12FC403A2382CB6F00AB593B /* TableButton.swift in Sources */,
783811 12EB698123661CB300E4D1CE /* AddressCell.swift in Sources */,
784812 F3895F48233D2EEA00FA6A37 /* CodeSmsViewController.swift in Sources */,
785813 12219CEF2353A63F0057DDEE /* ReservationsCoordinator.swift in Sources */,
@@ -787,14 +815,15 @@
787815 12BD95B8237EDB01009614D8 /* TimePointView.swift in Sources */,
788816 12838EB2236779A000CEF108 /* AuthResolver.swift in Sources */,
789817 12FE4042236B8B050012391E /* DataStorage.swift in Sources */,
790− 12A075F72373535C00D749BB /* ReservationViewController.swift in Sources */,
818+ 12A075F72373535C00D749BB /* FirstStepReservationViewController.swift in Sources */,
791819 1246B71C235CDF3A004CBFA1 /* ReservationCell.swift in Sources */,
792− 12A075FD237357E900D749BB /* ReservationCoordinator.swift in Sources */,
820+ 12A075FD237357E900D749BB /* FirstStepReservationCoordinator.swift in Sources */,
793821 124D0081237222C900AE76B9 /* ReservationsService.swift in Sources */,
794822 1246B720235CDF9E004CBFA1 /* ReservationView.swift in Sources */,
795823 12050569238048CE00801618 /* Extensions+Date.swift in Sources */,
796824 124D007C23721FD400AE76B9 /* Reservation.swift in Sources */,
797825 12D8FA2F237F00E200305F57 /* DateView.swift in Sources */,
826+ 12F9652E23869F3100FCA696 /* SecondStepReservationCoordinator.swift in Sources */,
798827 F3895F4E233D348B00FA6A37 /* PhoneCoordinator.swift in Sources */,
799828 12B6A617235BB37D00898B31 /* ChangeView.swift in Sources */,
800829 F3FC7DCD2315BE610080D851 /* AppDelegate.swift in Sources */,
@@ -804,6 +833,8 @@
804833 F3FC7DFD2315C4710080D851 /* BaseCoordinator.swift in Sources */,
805834 F3DC59FF233E893400B5E751 /* Extensions+UIFont.swift in Sources */,
806835 F3895F53233D5EEB00FA6A37 /* BlackButtonStyle.swift in Sources */,
836+ 12F9652723868DA300FCA696 /* SecondStepReservationViewController.swift in Sources */,
837+ 12F9652C23868E7200FCA696 /* SecondStepView.swift in Sources */,
807838 12118B9C23682022006BAEE3 /* RegistrationResolver.swift in Sources */,
808839 F30369C02336925800A8EA84 /* ClientTabbarController.swift in Sources */,
809840 F31E20C72348DDB900BEA215 /* Extensions+UIView.swift in Sources */,
@@ -824,6 +855,7 @@
824855 12C72EE3235380EB00AD7004 /* ReservationsViewController.swift in Sources */,
825856 12B6A611235B8EC500898B31 /* User.swift in Sources */,
826857 12B6A60F235B857A00898B31 /* ProfileChangeCoordinator.swift in Sources */,
858+ 12FC40382382C93D00AB593B /* TableButtonStyle.swift in Sources */,
827859 12D8FA31237F08C700305F57 /* AllReservations.swift in Sources */,
828860 12838EB0236777D400CEF108 /* ServerError.swift in Sources */,
829861 );
Hookah Tau/Components/BlackButtonStyle.swift+8
@@ -39,6 +39,14 @@ class BlackButtonStyle: NSObject {
3939 button.addSubviewThatFills(view)
4040 }
4141
42+ func changeToBookedState(button: Button) {
43+ TableStyle.setStripes(for: button)
44+ }
45+
46+ func changeToAvailiableState(button: Button) {
47+ button.layer.sublayers?.removeAll()
48+ }
49+
4250 func backToNormalStyle(button: Button) {
4351 subviewLayer?.removeFromSuperview()
4452 }
Hookah Tau/Components/Button.swift+16
@@ -26,6 +26,12 @@ class Button: UIButton {
2626 }
2727 }
2828
29+ public var availiable = true {
30+ willSet {
31+ willUpdateBookingState(newValue: availiable)
32+ }
33+ }
34+
2935 // MARK: - Init
3036
3137 override func awakeFromNib() {
@@ -43,4 +49,14 @@ class Button: UIButton {
4349 style?.backToNormalStyle(button: self)
4450 }
4551 }
52+
53+ private func willUpdateBookingState(newValue avaliable: Bool) {
54+ isEnabled = !avaliable
55+
56+ if availiable {
57+ style?.changeToAvailiableState(button: self)
58+ } else {
59+ style?.changeToBookedState(button: self)
60+ }
61+ }
4662}
Hookah Tau/Components/TableButton.swiftnew file+54
@@ -0,0 +1,54 @@
1+//
2+// TableButton.swift
3+// Hookah Tau
4+//
5+// Created by cstore on 18/11/2019.
6+// Copyright © 2019 Daria Rednikina. All rights reserved.
7+//
8+
9+import UIKit
10+
11+class TableButton: UIButton {
12+
13+ var style: TableButtonStyle?
14+
15+ var isChosen: Bool = false {
16+ didSet {
17+ if isChosen {
18+ style?.setSelected(button: self)
19+ } else {
20+ style?.setUnselected(button: self)
21+ }
22+ }
23+ }
24+
25+ var isBooked: Bool = false {
26+ didSet {
27+ if !isBooked {
28+ style?.setAvaliable(button: self)
29+ } else {
30+ style?.setBooked(button: self)
31+ }
32+ }
33+ }
34+
35+ override func awakeFromNib() {
36+ super.awakeFromNib()
37+ }
38+
39+ func select() {
40+ isChosen = true
41+ }
42+
43+ func active() {
44+ isBooked = false
45+ }
46+
47+ func inactive() {
48+ isBooked = true
49+ }
50+
51+ func unselect() {
52+ isChosen = false
53+ }
54+}
Hookah Tau/Components/TableButtonStyle.swiftnew file+87
@@ -0,0 +1,87 @@
1+//
2+// MapButtonStyle.swift
3+// Hookah Tau
4+//
5+// Created by cstore on 18/11/2019.
6+// Copyright © 2019 Daria Rednikina. All rights reserved.
7+//
8+
9+import UIKit
10+
11+class TableStyle {
12+
13+ static func setStripes(for view: UIView) {
14+ let replicationLayer = createReplicatorLayer()
15+ replicationLayer.frame = view.bounds
16+ replicationLayer.frame.origin.x = -100
17+
18+ view.layer.masksToBounds = true
19+ view.layer.addSublayer(replicationLayer)
20+ }
21+
22+ private static func createReplicatorLayer() -> CAReplicatorLayer {
23+ let replicatorLayer = CAReplicatorLayer()
24+
25+ let stripe = CALayer()
26+
27+ stripe.frame = CGRect(x: 0, y: -10, width: 2, height: 500)
28+ stripe.backgroundColor = UIColor.black.cgColor
29+ stripe.transform = CATransform3DMakeRotation(0.52, 0, 0, 1.0)
30+
31+ replicatorLayer.instanceCount = 60
32+ replicatorLayer.instanceTransform = CATransform3DMakeTranslation(20, 0, 0)
33+ replicatorLayer.addSublayer(stripe)
34+
35+ return replicatorLayer
36+ }
37+
38+}
39+
40+
41+class TableButtonStyle {
42+ enum Constants {
43+ static let cornerRadius: CGFloat = 8
44+ static let clearColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 0)
45+ }
46+
47+ enum Selection {
48+ static let borderColor: CGColor = #colorLiteral(red: 0.2901960784, green: 0.5647058824, blue: 0.8862745098, alpha: 1)
49+ static let borderWidth: CGFloat = 3
50+ static let fillColor = #colorLiteral(red: 0.2078431373, green: 0.5215686275, blue: 0.8862745098, alpha: 0.5)
51+ }
52+
53+ enum Booked {
54+ static let fillColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 0.5)
55+ }
56+
57+ func setSelected(button: TableButton) {
58+ button.layer.borderWidth = Selection.borderWidth
59+ button.layer.borderColor = Selection.borderColor
60+ button.backgroundColor = Selection.fillColor
61+ }
62+
63+ func setBooked(button: TableButton) {
64+ TableStyle.setStripes(for: button)
65+ }
66+
67+ func setAvaliable(button: TableButton) {
68+ button.layer.sublayers?.removeAll()
69+ button.backgroundColor = button.isChosen ? Selection.fillColor : Constants.clearColor
70+ }
71+
72+ func setUnselected(button: TableButton) {
73+ button.layer.borderWidth = 0
74+ button.backgroundColor = button.isBooked ? Booked.fillColor : Constants.clearColor
75+ }
76+}
77+
78+// MARK: - ButtonStyle
79+
80+extension TableButtonStyle {
81+
82+ func apply(to button: TableButton?) {
83+ button?.layer.cornerRadius = Constants.cornerRadius
84+ button?.style = self
85+ }
86+
87+}
Hookah Tau/Controllers/Client/Reservations/Adress of reservation/AddresViewController.swift+6
@@ -27,6 +27,12 @@ class AddresViewController: BaseViewController {
2727 setUpTableView()
2828 }
2929
30+ override func viewWillAppear(_ animated: Bool) {
31+ super.viewWillAppear(animated)
32+
33+ tabBarController?.tabBar.isHidden = false
34+ }
35+
3036 // MARK: - Setup
3137
3238 func setUpTableView() {
Hookah Tau/Controllers/Client/Reservations/Adress of reservation/AddressCoordinator.swift+1−1
@@ -30,7 +30,7 @@ class AddressCoordinator: BaseCoordinator {
3030 /// continue with reservation
3131 /// TODO: pass some data
3232 func chooseTableAndTime(inEstablishment id: Int) {
33− let reservationCoordinator = ReservationCoordinator(navigationController: navigationController)
33+ let reservationCoordinator = FirstStepReservationCoordinator(navigationController: navigationController)
3434 addDependency(reservationCoordinator)
3535 reservationCoordinator.didFinish = { [weak self] in
3636 self?.removeDependency(reservationCoordinator)
Hookah Tau/Controllers/Client/Reservations/Maps/MapView.swift+53−3
@@ -10,8 +10,58 @@ import UIKit
1010
1111
1212class MapImageScroll: UIView {
13+
14+ weak var handler: MapHandler?
15+
1316 var scrollViewParent: UIScrollView!
14− var tables: [Int: UIButton] = [:]
17+
18+ var tables: [Int: TableButton] = [:]
19+
20+ func scrollToTable(table: Int) { }
21+
22+ var img: UIImageView!
23+
24+ func configureFor(_ imageSize: CGSize) {
25+ self.scrollViewParent.contentSize = imageSize
26+ setMaxMinZoomScaleForCurrentBounds()
27+ }
28+
29+ func setMaxMinZoomScaleForCurrentBounds() {
30+ let boundsSize = self.scrollViewParent.bounds.size
31+ let imageSize = img.bounds.size
32+
33+ //1. calculate minimumZoomscale
34+ let xScale = boundsSize.width / imageSize.width
35+ let yScale = boundsSize.height / imageSize.height
36+ var minScale = min(xScale, yScale)
37+
38+ //2. calculate maximumZoomscale
39+ var maxScale: CGFloat = 1.0
40+ if minScale < 0.1 {
41+ maxScale = 0.3
42+ }
43+ if minScale >= 0.1 && minScale < 0.5 {
44+ maxScale = 0.7
45+ }
46+ if minScale >= 0.5 {
47+ maxScale = max(1.0, minScale)
48+ }
49+
50+ if img.frame.width < frame.width {
51+ let scaleW = frame.width / img.frame.width
52+ minScale = scaleW
53+ }
54+
55+ if img.frame.height < frame.height {
56+ let scaleH = frame.height / img.frame.height
57+ maxScale = scaleH
58+ }
59+
60+ img.transform = CGAffineTransform(scaleX: minScale, y: minScale)
61+
62+ self.scrollViewParent.maximumZoomScale = maxScale
63+ self.scrollViewParent.minimumZoomScale = minScale
64+ }
1565}
1666
1767extension MapImageScroll {
@@ -19,7 +69,7 @@ extension MapImageScroll {
1969 func performUpdate(inactive: [Int]) {
2070
2171 let active = Set(tables.keys).subtracting(inactive)
22− active.forEach { ind in tables[ind]?.backgroundColor = #colorLiteral(red: 0, green: 1, blue: 1, alpha: 0.3711205051) }
23− inactive.forEach { ind in tables[ind]?.backgroundColor = #colorLiteral(red: 1, green: 0, blue: 0.7170844332, alpha: 0.3711205051) }
72+ active.forEach { ind in tables[ind]?.active() }
73+ inactive.forEach { ind in tables[ind]?.inactive() }
2474 }
2575}
Hookah Tau/Controllers/Client/Reservations/Maps/MapView1.swift+89−50
@@ -8,7 +8,7 @@
88
99import UIKit
1010
11−protocol MapHandler {
11+protocol MapHandler: class {
1212 func handleTap(withId id: Int)
1313}
1414
@@ -16,35 +16,75 @@ class MapView1: MapImageScroll, UIScrollViewDelegate {
1616
1717 // MARK: - Properties
1818
19− var handler: MapHandler?
20−
2119 @IBOutlet weak var scrollView: UIScrollView! {
2220 didSet {
2321 super.scrollViewParent = scrollView
2422 }
2523 }
2624
27− @IBOutlet weak var image: UIImageView!
25+ @IBOutlet weak var image: UIImageView! {
26+ didSet {
27+ super.img = image
28+ }
29+ }
2830
29− @IBOutlet weak var firstTable: UIButton! {
31+ @IBOutlet weak var firstTable: TableButton! {
3032 didSet {
33+ let style = TableButtonStyle()
34+ style.apply(to: firstTable)
3135 firstTable.transform = CGAffineTransform(rotationAngle: CGFloat(-Double.pi / 4));
36+ firstTable.select()
3237 }
3338 }
3439
35− @IBOutlet weak var secondTable: UIButton!
40+ @IBOutlet weak var secondTable: TableButton! {
41+ didSet {
42+ let style = TableButtonStyle()
43+ style.apply(to: secondTable)
44+ }
45+ }
3646
37− @IBOutlet weak var trirdTable: UIButton!
47+ @IBOutlet weak var trirdTable: TableButton! {
48+ didSet {
49+ let style = TableButtonStyle()
50+ style.apply(to: trirdTable)
51+ }
52+ }
3853
39− @IBOutlet weak var forthTable: UIButton!
54+ @IBOutlet weak var forthTable: TableButton! {
55+ didSet {
56+ let style = TableButtonStyle()
57+ style.apply(to: forthTable)
58+ }
59+ }
4060
41− @IBOutlet weak var fifthTable: UIButton!
61+ @IBOutlet weak var fifthTable: TableButton! {
62+ didSet {
63+ let style = TableButtonStyle()
64+ style.apply(to: fifthTable)
65+ }
66+ }
4267
43− @IBOutlet weak var sixthTable: UIButton!
68+ @IBOutlet weak var sixthTable: TableButton! {
69+ didSet {
70+ let style = TableButtonStyle()
71+ style.apply(to: sixthTable)
72+ }
73+ }
4474
45− @IBOutlet weak var seventhTable: UIButton!
75+ @IBOutlet weak var seventhTable: TableButton! {
76+ didSet {
77+ let style = TableButtonStyle()
78+ style.apply(to: seventhTable)
79+ }
80+ }
4681
47− @IBOutlet weak var eighthTable: UIButton!
82+ @IBOutlet weak var eighthTable: TableButton! {
83+ didSet {
84+ let style = TableButtonStyle()
85+ style.apply(to: eighthTable)
86+ }
87+ }
4888
4989 // MARK: - Lifecycle
5090
@@ -52,6 +92,7 @@ class MapView1: MapImageScroll, UIScrollViewDelegate {
5292 super.awakeFromNib()
5393
5494 self.scrollView.delegate = self
95+ self.scrollView.delaysContentTouches = false
5596
5697 image.addSubview(firstTable)
5798 image.addSubview(secondTable)
@@ -74,55 +115,53 @@ class MapView1: MapImageScroll, UIScrollViewDelegate {
74115 configureFor(image.frame.size)
75116 }
76117
77− @IBAction func chooseSecondTable(_ sender: UIButton) {
118+ @IBAction func chooseSecondTable(_ sender: TableButton) {
119+ tables.values.forEach { $0.unselect() }
120+ secondTable.select()
78121 handler?.handleTap(withId: 2)
79122 }
80123
81− // MARK: - Scroll view
124+ @IBAction func chooseFifthTable(_ sender: TableButton) {
125+ tables.values.forEach { $0.unselect() }
126+ fifthTable.select()
127+ handler?.handleTap(withId: 5)
128+ }
129+
130+ @IBAction func choseSeventhTable(_ sender: TableButton) {
131+ }
82132
83− func configureFor(_ imageSize: CGSize) {
84− self.scrollView.contentSize = imageSize
85− setMaxMinZoomScaleForCurrentBounds()
133+ @IBAction func chooseFirstTable(_ sender: TableButton) {
134+ tables.values.forEach { $0.unselect() }
135+ firstTable.select()
136+ handler?.handleTap(withId: 1)
86137 }
87138
139+ @IBAction func chooseThirdTable(_ sender: TableButton) {
140+ }
141+
142+ @IBAction func choose4thTable(_ sender: TableButton) {
143+ }
144+
145+ @IBAction func choose6thTable(_ sender: TableButton) {
146+ }
147+
148+ @IBAction func choose8thTable(_ sender: TableButton) {
149+ }
150+
151+
152+ // MARK: - Scroll view
153+
88154 func viewForZooming(in scrollView: UIScrollView) -> UIView? {
89155 self.image
90156 }
91157
92− func setMaxMinZoomScaleForCurrentBounds() {
93− let boundsSize = self.scrollView.bounds.size
94− let imageSize = image.bounds.size
95−
96− //1. calculate minimumZoomscale
97− let xScale = boundsSize.width / imageSize.width
98− let yScale = boundsSize.height / imageSize.height
99− var minScale = min(xScale, yScale)
100−
101− //2. calculate maximumZoomscale
102− var maxScale: CGFloat = 1.0
103− if minScale < 0.1 {
104− maxScale = 0.3
105− }
106− if minScale >= 0.1 && minScale < 0.5 {
107− maxScale = 0.7
108− }
109− if minScale >= 0.5 {
110− maxScale = max(1.0, minScale)
111− }
112−
113− if image.frame.width < frame.width {
114− let scaleW = frame.width / image.frame.width
115− minScale = scaleW
116− }
117−
118− if image.frame.height < frame.height {
119− let scaleH = frame.height / image.frame.height
120− maxScale = scaleH
121− }
158+
159+ override func scrollToTable(table: Int) {
160+ guard let tableButton = tables[table] else { return }
122161
123− image.transform = CGAffineTransform(scaleX: minScale, y: minScale)
162+ scrollView.setZoomScale(1.2, animated: true)
163+ scrollView.setContentOffset(tableButton.frame.origin, animated: true)
124164
125− self.scrollView.maximumZoomScale = maxScale
126− self.scrollView.minimumZoomScale = minScale
165+ scrollView.scrollRectToVisible(tableButton.frame, animated: true)
127166 }
128167}
Hookah Tau/Controllers/Client/Reservations/Maps/MapView1.xib+41−25
@@ -17,80 +17,96 @@
1717 <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="FuE-LV-NBR">
1818 <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
1919 <subviews>
20− <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="map_1" translatesAutoresizingMaskIntoConstraints="NO" id="btD-Wl-3P6">
20+ <imageView clipsSubviews="YES" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="map_1" translatesAutoresizingMaskIntoConstraints="NO" id="btD-Wl-3P6">
2121 <rect key="frame" x="0.0" y="0.0" width="536" height="639"/>
2222 </imageView>
23− <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xsw-fJ-8cN">
23+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xsw-fJ-8cN" customClass="TableButton" customModule="Hookah_Tau" customModuleProvider="target">
2424 <rect key="frame" x="209" y="116" width="131" height="119"/>
25− <color key="backgroundColor" red="0.8027878853" green="0.39771511129999998" blue="0.73183326199999998" alpha="0.19301155819999999" colorSpace="calibratedRGB"/>
25+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
2626 <constraints>
2727 <constraint firstAttribute="width" constant="131" id="2xi-Oz-ceC"/>
2828 <constraint firstAttribute="height" constant="119" id="xPD-fh-9Zg"/>
2929 </constraints>
30− <state key="normal" title="Button"/>
30+ <connections>
31+ <action selector="chooseSecondTable:" destination="iN0-l3-epB" eventType="touchUpInside" id="5XE-gZ-DyJ"/>
32+ </connections>
3133 </button>
32− <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="onR-hl-Q2x">
34+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="onR-hl-Q2x" customClass="TableButton" customModule="Hookah_Tau" customModuleProvider="target">
3335 <rect key="frame" x="60" y="213" width="102" height="119"/>
34− <color key="backgroundColor" red="0.8027878853" green="0.39771511129999998" blue="0.73183326199999998" alpha="0.19301155819999999" colorSpace="calibratedRGB"/>
36+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
3537 <constraints>
3638 <constraint firstAttribute="height" constant="119" id="JWf-x8-7CB"/>
3739 <constraint firstAttribute="width" constant="102" id="LZN-1O-mIP"/>
3840 </constraints>
39− <state key="normal" title="Button"/>
41+ <connections>
42+ <action selector="choose6thTable:" destination="iN0-l3-epB" eventType="touchUpInside" id="gA4-cd-CZo"/>
43+ </connections>
4044 </button>
41− <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Fw9-l6-N8a">
45+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Fw9-l6-N8a" customClass="TableButton" customModule="Hookah_Tau" customModuleProvider="target">
4246 <rect key="frame" x="60" y="353" width="102" height="118"/>
43− <color key="backgroundColor" red="0.8027878853" green="0.39771511129999998" blue="0.73183326199999998" alpha="0.19301155819999999" colorSpace="calibratedRGB"/>
47+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
4448 <constraints>
4549 <constraint firstAttribute="height" constant="118" id="2Vp-Ip-7cO"/>
4650 <constraint firstAttribute="width" constant="102" id="2hI-75-UCM"/>
4751 </constraints>
48− <state key="normal" title="Button"/>
52+ <connections>
53+ <action selector="choseSeventhTable:" destination="iN0-l3-epB" eventType="touchUpInside" id="94e-DE-SAJ"/>
54+ </connections>
4955 </button>
50− <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KJZ-Nl-7hH">
56+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KJZ-Nl-7hH" customClass="TableButton" customModule="Hookah_Tau" customModuleProvider="target">
5157 <rect key="frame" x="222" y="275" width="104" height="119"/>
52− <color key="backgroundColor" red="0.8027878853" green="0.39771511129999998" blue="0.73183326199999998" alpha="0.19301155819999999" colorSpace="calibratedRGB"/>
58+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
5359 <constraints>
5460 <constraint firstAttribute="height" constant="119" id="Ifu-kd-YHH"/>
5561 <constraint firstAttribute="width" constant="104" id="phm-aP-6dx"/>
5662 </constraints>
57− <state key="normal" title="Button"/>
63+ <connections>
64+ <action selector="chooseFifthTable:" destination="iN0-l3-epB" eventType="touchUpInside" id="Tc2-ir-tPU"/>
65+ </connections>
5866 </button>
59− <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mUw-im-1BC">
67+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mUw-im-1BC" customClass="TableButton" customModule="Hookah_Tau" customModuleProvider="target">
6068 <rect key="frame" x="222" y="434" width="92" height="67"/>
61− <color key="backgroundColor" red="0.8027878853" green="0.39771511129999998" blue="0.73183326199999998" alpha="0.19301155819999999" colorSpace="calibratedRGB"/>
69+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
6270 <constraints>
6371 <constraint firstAttribute="width" constant="92" id="AJ6-ku-4R3"/>
6472 <constraint firstAttribute="height" constant="67" id="jVI-uI-YDT"/>
6573 </constraints>
66− <state key="normal" title="Button"/>
74+ <connections>
75+ <action selector="choose8thTable:" destination="iN0-l3-epB" eventType="touchUpInside" id="C8U-7T-Bsc"/>
76+ </connections>
6777 </button>
68− <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Bns-fd-Wv4">
78+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Bns-fd-Wv4" customClass="TableButton" customModule="Hookah_Tau" customModuleProvider="target">
6979 <rect key="frame" x="44" y="43" width="102" height="125"/>
70− <color key="backgroundColor" red="0.8027878853" green="0.39771511129999998" blue="0.73183326199999998" alpha="0.19301155819999999" colorSpace="calibratedRGB"/>
80+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
7181 <constraints>
7282 <constraint firstAttribute="width" constant="102" id="l7h-tW-FfX"/>
7383 <constraint firstAttribute="height" constant="125" id="nDu-wc-Ll7"/>
7484 </constraints>
75− <state key="normal" title="Button"/>
85+ <connections>
86+ <action selector="chooseFirstTable:" destination="iN0-l3-epB" eventType="touchUpInside" id="uc3-Si-PiX"/>
87+ </connections>
7688 </button>
77− <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aIM-Qn-Uhl">
89+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aIM-Qn-Uhl" customClass="TableButton" customModule="Hookah_Tau" customModuleProvider="target">
7890 <rect key="frame" x="386" y="116" width="130" height="119"/>
79− <color key="backgroundColor" red="0.8027878853" green="0.39771511129999998" blue="0.73183326199999998" alpha="0.19301155819999999" colorSpace="calibratedRGB"/>
91+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
8092 <constraints>
8193 <constraint firstAttribute="width" constant="130" id="Lhq-jM-PQ0"/>
8294 <constraint firstAttribute="height" constant="119" id="vsx-u8-L6o"/>
8395 </constraints>
84− <state key="normal" title="Button"/>
96+ <connections>
97+ <action selector="chooseThirdTable:" destination="iN0-l3-epB" eventType="touchUpInside" id="eQS-Wo-hTf"/>
98+ </connections>
8599 </button>
86− <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="wpi-6E-c5p">
100+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="wpi-6E-c5p" customClass="TableButton" customModule="Hookah_Tau" customModuleProvider="target">
87101 <rect key="frame" x="399" y="275" width="104" height="119"/>
88− <color key="backgroundColor" red="0.8027878853" green="0.39771511129999998" blue="0.73183326199999998" alpha="0.19301155819999999" colorSpace="calibratedRGB"/>
102+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
89103 <constraints>
90104 <constraint firstAttribute="height" constant="119" id="Lib-3b-h8b"/>
91105 <constraint firstAttribute="width" constant="104" id="nch-5L-cRo"/>
92106 </constraints>
93− <state key="normal" title="Button"/>
107+ <connections>
108+ <action selector="choose4thTable:" destination="iN0-l3-epB" eventType="touchUpInside" id="U5p-In-FEa"/>
109+ </connections>
94110 </button>
95111 </subviews>
96112 <constraints>
Hookah Tau/Controllers/Client/Reservations/Reservation.storyboard+35−3
@@ -8,17 +8,17 @@
88 <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
99 </dependencies>
1010 <scenes>
11− <!--Reservation View Controller-->
11+ <!--First Step Reservation View Controller-->
1212 <scene sceneID="EKz-nU-dQ1">
1313 <objects>
14− <viewController storyboardIdentifier="ReservationViewController" id="Fha-pE-okd" customClass="ReservationViewController" customModule="Hookah_Tau" customModuleProvider="target" sceneMemberID="viewController">
14+ <viewController storyboardIdentifier="ReservationViewController" id="Fha-pE-okd" customClass="FirstStepReservationViewController" customModule="Hookah_Tau" customModuleProvider="target" sceneMemberID="viewController">
1515 <view key="view" contentMode="scaleToFill" id="cwG-Fa-gXD">
1616 <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
1717 <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
1818 <subviews>
1919 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="RRF-jh-Xme">
2020 <rect key="frame" x="0.0" y="671" width="414" height="225"/>
21− <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
21+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
2222 <constraints>
2323 <constraint firstAttribute="height" constant="225" id="43Q-xl-4hv"/>
2424 </constraints>
@@ -40,5 +40,37 @@
4040 </objects>
4141 <point key="canvasLocation" x="-140.57971014492756" y="-38.169642857142854"/>
4242 </scene>
43+ <!--Second Step Reservation View Controller-->
44+ <scene sceneID="NON-tn-ls5">
45+ <objects>
46+ <viewController storyboardIdentifier="SecondStepReservationViewController" id="OAC-Ui-1o4" customClass="SecondStepReservationViewController" customModule="Hookah_Tau" customModuleProvider="target" sceneMemberID="viewController">
47+ <view key="view" contentMode="scaleToFill" id="dZe-8U-Rs6">
48+ <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
49+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
50+ <subviews>
51+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NBJ-7w-vpV">
52+ <rect key="frame" x="0.0" y="502" width="414" height="394"/>
53+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
54+ <constraints>
55+ <constraint firstAttribute="height" constant="394" id="KKm-d5-Srx"/>
56+ </constraints>
57+ </view>
58+ </subviews>
59+ <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
60+ <constraints>
61+ <constraint firstItem="NBJ-7w-vpV" firstAttribute="leading" secondItem="YKO-1X-SYz" secondAttribute="leading" id="ZCK-Y0-Dnb"/>
62+ <constraint firstItem="NBJ-7w-vpV" firstAttribute="trailing" secondItem="YKO-1X-SYz" secondAttribute="trailing" id="ulb-DD-Mmh"/>
63+ <constraint firstAttribute="bottom" secondItem="NBJ-7w-vpV" secondAttribute="bottom" id="zEI-rl-4r7"/>
64+ </constraints>
65+ <viewLayoutGuide key="safeArea" id="YKO-1X-SYz"/>
66+ </view>
67+ <connections>
68+ <outlet property="childContentView" destination="NBJ-7w-vpV" id="aa6-nY-PUA"/>
69+ </connections>
70+ </viewController>
71+ <placeholder placeholderIdentifier="IBFirstResponder" id="rVf-H4-jP0" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
72+ </objects>
73+ <point key="canvasLocation" x="706" y="-38"/>
74+ </scene>
4375 </scenes>
4476</document>
Hookah Tau/Controllers/Client/Reservations/ReservationCoordinator.swiftdeleted−34
@@ -1,34 +0,0 @@
1−//
2−// ReservationCoordinator.swift
3−// Hookah Tau
4−//
5−// Created by cstore on 06/11/2019.
6−// Copyright © 2019 Daria Rednikina. All rights reserved.
7−//
8−
9−import UIKit
10−
11−class ReservationCoordinator: BaseCoordinator {
12−
13− // MARK: - Properties
14−
15− var didFinish: (() -> Void)?
16−
17− // MARK: - Lifecycle
18−
19− override func start() {
20− let storyboard = UIStoryboard(name: "Reservation", bundle: nil)
21− let reservationVC = storyboard.instantiateViewController(withIdentifier: "ReservationViewController") as! ReservationViewController
22−
23− navigationController?.pushViewController(reservationVC, animated: true)
24− }
25−
26− func callAdmin() {
27−
28− }
29−
30− // TODO: with parameters
31− func makeReservation() {
32−
33− }
34−}
Hookah Tau/Controllers/Client/Reservations/SecondStepReservationViewController.swiftnew file+89
@@ -0,0 +1,89 @@
1+//
2+// SecondStepReservationViewController.swift
3+// Hookah Tau
4+//
5+// Created by cstore on 21/11/2019.
6+// Copyright © 2019 Daria Rednikina. All rights reserved.
7+//
8+
9+import UIKit
10+
11+class SecondStepReservationViewController: BaseViewController {
12+
13+ // MARK: - Properties
14+
15+ weak var coordinator: SecondStepReservationCoordinator?
16+
17+ @IBOutlet weak var childContentView: UIView!
18+
19+ var secondStepView: SecondStepView?
20+
21+ /// map view from the previous screen
22+ var mapView: MapImageScroll?
23+
24+ var model: SecondStepModel?
25+
26+ /// booked periods for this table for this date
27+ var bookedPeriods: [ReservationPeriod] = [] {
28+ didSet {
29+ secondStepView?.setUpReservedIntervals(bookedPeriods)
30+ }
31+ }
32+
33+ let confirmButton: Button = {
34+ let button = Button()
35+ let style = BlackButtonStyle()
36+ style.apply(to: button, withTitle: "ПОДТВЕРДИТЬ")
37+ //button.addTarget(self, action: #selector(doneChanging), for: .touchUpInside)
38+ return button
39+ }()
40+
41+ let cancelButton: Button = {
42+ let button = Button()
43+ let style = BlackButtonStyle()
44+ style.apply(to: button, withTitle: "ОТМЕНИТЬ")
45+ return button
46+ }()
47+
48+ // MARK: - Lifecycle
49+
50+ override func viewDidLoad() {
51+ super.viewDidLoad()
52+
53+ setupMap()
54+ setupChildContainer()
55+ setupButtons()
56+
57+ }
58+
59+ // MARK: - Setup
60+
61+ func setupChildContainer() {
62+
63+ secondStepView = SecondStepView.loadFromNib()
64+ childContentView.addSubviewThatFills(secondStepView)
65+ guard let model = model else { return }
66+ secondStepView?.bind(model: model)
67+ }
68+
69+ func setupMap() {
70+ view.addSubviewThatFills(mapView)
71+
72+ mapView?.isUserInteractionEnabled = false
73+ mapView?.scrollToTable(table: model?.table ?? 0)
74+
75+ guard let map = mapView else { return }
76+ view.sendSubviewToBack(map)
77+ }
78+
79+ func setupButtons() {
80+ addStackViewWithButtons(leftBtn: cancelButton,
81+ rightBtn: confirmButton,
82+ constant: -childContentView.frame.height - 20)
83+ cancelButton.addTarget(self, action: #selector(cancelChange), for: .touchUpInside)
84+ }
85+
86+ @objc func cancelChange() {
87+ coordinator?.cancel(mapView)
88+ }
89+}
Hookah Tau/Controllers/Client/Reservations/Steps/First/DateView.swift+2−2
@@ -12,7 +12,7 @@ class DateView: UIView {
1212
1313 @IBOutlet weak var dateLabel: UILabel!
1414
15− func setUp(with date: IntervalDate) {
16− dateLabel.text = "\(date.day)"
15+ func setUp(with date: Date) {
16+ dateLabel.text = "\(date.getDay())"
1717 }
1818}
Hookah Tau/Controllers/Client/Reservations/Steps/First/FirstStepView.swift+84−30
@@ -9,7 +9,7 @@
99import UIKit
1010
1111protocol MapUpdater: class {
12− func update(_ date: IntervalDate)
12+ func update(_ date: Date)
1313}
1414
1515class FirstStepView: UIView {
@@ -18,21 +18,44 @@ class FirstStepView: UIView {
1818
1919 var chosenPoint: Int? = 0 {
2020 didSet {
21− guard let point = chosenPoint, let date = chosenDate else { return }
22− let newIntervalDate = IntervalDate(day: date.day,
23− month: date.month,
24− year: date.year,
25− minutes: point)
26− mapUpdater?.update(newIntervalDate)
21+ guard
22+ let periods = chosenPoint,
23+ let dateInt = date,
24+ let newDate = Date.getDateFromCurrent(days: dateInt, periods: periods)
25+ else { return }
26+ fullDate = newDate
2727 }
2828 }
2929
30− var chosenDate: IntervalDate? = Date.getDateFromCurrent() {
30+ var fullDate: Date? = Date.getDateFromCurrent() {
3131 didSet {
32− guard let date = chosenDate, let _ = chosenPoint else { return }
32+ guard let date = fullDate, let _ = chosenPoint else { return }
3333 mapUpdater?.update(date)
3434 }
3535 }
36+
37+ var date: Int? {
38+ didSet {
39+ guard
40+ let dateInt = date,
41+ let periods = chosenPoint,
42+ let newDate = Date.getDateFromCurrent(days: dateInt, periods: periods)
43+ else { return }
44+ fullDate = newDate
45+
46+ guard
47+ let date = fullDate?.getDMY()
48+ else { return }
49+ setUpBookingsForIntervals(reservations: bookingsForDates[date] ?? [])
50+ }
51+ }
52+
53+ var bookingsForDates: [Date: [ReservationPeriod]] = [:] {
54+ didSet {
55+ guard let date = fullDate?.getDMY(), let reservPeriods = bookingsForDates[date] else { return }
56+ setUpBookingsForIntervals(reservations: reservPeriods)
57+ }
58+ }
3659
3760 @IBOutlet weak var scrollViewIntervals: UIScrollView!
3861
@@ -42,12 +65,19 @@ class FirstStepView: UIView {
4265
4366 @IBOutlet weak var datesScrollView: UIScrollView!
4467
68+ @IBOutlet weak var earlierThan12Label: UILabel!
69+
70+ @IBOutlet weak var laterThan3Label: UILabel!
71+
72+
73+ var bookingsViewsForDate: [UIView] = []
74+
4575
4676 override func awakeFromNib() {
4777 super.awakeFromNib()
4878
49− self.scrollViewIntervals.delegate = self
50− self.datesScrollView.delegate = self
79+ scrollViewIntervals.delegate = self
80+ datesScrollView.delegate = self
5181
5282 scrollViewIntervals.showsHorizontalScrollIndicator = false
5383 datesScrollView.showsHorizontalScrollIndicator = false
@@ -67,26 +97,53 @@ class FirstStepView: UIView {
6797 }
6898 }
6999
70− func addBusyPeriods() {
100+ func setUpBookingsForIntervals(reservations: [ReservationPeriod]) {
101+ bookingsViewsForDate.forEach { $0.removeFromSuperview() }
102+ bookingsViewsForDate = []
71103
104+ for reservation in reservations {
105+ let uiview = UIView(frame: CGRect(x: 0, y: 0, width: Constants.widthTimePoint * reservation.duration, height: 71))
106+ uiview.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 0.5)
107+
108+ uiview.translatesAutoresizingMaskIntoConstraints = false
109+ scrollViewIntervals.addSubview(uiview)
110+
111+ guard let date = date else { return }
112+ let startDate = Date.getDateFromCurrent(days: date)!.set(hours: 12, minutes: 0, seconds: 0)!
113+
114+ NSLayoutConstraint.activate([
115+ uiview.topAnchor.constraint(equalToSystemSpacingBelow: scrollViewIntervals.topAnchor, multiplier: 0),
116+ uiview.bottomAnchor.constraint(equalToSystemSpacingBelow: scrollViewIntervals.bottomAnchor, multiplier: 0),
117+ uiview.leftAnchor.constraint(equalTo: scrollViewIntervals.leftAnchor,
118+ constant: CGFloat(Constants.widthTimePoint / 2 + Constants.widthTimePoint * reservation.startTime.getMinutesPeriods(fromStart: startDate))),
119+ uiview.widthAnchor.constraint(equalToConstant: CGFloat(Constants.widthTimePoint * reservation.duration))
120+ ])
121+
122+ bookingsViewsForDate.append(uiview)
123+ }
72124 }
73125
74126 func setContent() {
75127 scrollViewIntervals.contentSize = stackViewIntervals.frame.size
76128 datesScrollView.contentSize = datesStackView.frame.size
77129
78− let edges = UIEdgeInsets(top: 0, left: self.frame.size.width / 2, bottom: 0, right: self.frame.size.width / 2)
130+ let halfWidth = frame.size.width / 2
131+ let edges = UIEdgeInsets(top: 0, left: halfWidth, bottom: 0, right: halfWidth)
132+
79133 scrollViewIntervals.contentInset = edges
80134 datesScrollView.contentInset = edges
81135
82− datesScrollView.setContentOffset(CGPoint(x: abs(Constants.widthDate * Constants.daysCount / 2 - Int(edges.left)), y: 0), animated: true)
83− scrollViewIntervals.setContentOffset(CGPoint(x: abs(Constants.widthTimePoint * Constants.day10MinPeriods / 2 - Int(edges.left)), y: 0), animated: true)
136+ datesScrollView.setContentOffset(CGPoint(x: abs(Constants.widthDate * Constants.daysCount / 2 - Int(edges.left)) + 8, y: 0),
137+ animated: true)
138+ scrollViewIntervals.setContentOffset(CGPoint(x: abs(Constants.widthTimePoint * Constants.day10MinPeriods / 2 - Int(edges.left)) + 5, y: 0),
139+ animated: true)
84140 }
85141
86− func setUp(_ data: AllReservations) {
87− //let sortedDates = data.intervals.keys.sorted()
88−
89− // setUpDateStackView()
142+
143+ /// Method for setting up `stackViewIntervals` with appropriate busy intervals of chosen table
144+ /// - Parameter data: Map of booked periods by key - date - is provided
145+ func setUp(_ data: [Date: [ReservationPeriod]]) {
146+ bookingsForDates = data
90147 }
91148
92149 func setUpDateStackView() {
@@ -115,21 +172,18 @@ extension FirstStepView: UIScrollViewDelegate {
115172 }
116173
117174 func intervalsDidScroll() {
175+ let inset = scrollViewIntervals.contentInset.left
176+ let alpha12 = 1 / (abs(inset + scrollViewIntervals.contentOffset.x) / inset)
177+ let alpha3 = 1 / (abs(inset + scrollViewIntervals.contentOffset.x - stackViewIntervals.frame.width) / inset)
178+
179+ earlierThan12Label.textColor = earlierThan12Label.textColor.withAlphaComponent(alpha12)
180+ laterThan3Label.textColor = laterThan3Label.textColor.withAlphaComponent(alpha3)
181+
118182 for (index, stack) in stackViewIntervals.subviews.enumerated() {
119183 if let intervalStack = stack.subviews[0] as? TimePointView {
120184 let positionToSelf = intervalStack.convert(intervalStack.frame, to: self)
121−
122−// var isBusy = false
123−// let positionToScrollView = intervalStack.convert(intervalStack.frame, to: self.scrollViewIntervals)
124−
125−// for busyView in busyViews {
126−// if busyView.frame.contains(positionToScrollView) {
127−// isBusy = true
128−// }
129−// }
130185
131186 if abs((positionToSelf.minX + positionToSelf.maxX) / 2 - frame.size.width / 2) < 5.5
132− //,!isBusy
133187 {
134188 intervalStack.timePoint.backgroundColor = .darkGray
135189 chosenPoint = index
@@ -147,7 +201,7 @@ extension FirstStepView: UIScrollViewDelegate {
147201
148202 if abs((positionToSelf.minX + positionToSelf.maxX) / 2 - frame.size.width / 2) < 15.5 {
149203 dateView.dateLabel.textColor = .black
150− chosenDate = Date.getDateFromCurrent(days: Int((datesScrollView.contentInset.left + datesScrollView.contentOffset.x) / 31), period: chosenPoint)
204+ date = Int(datesScrollView.contentInset.left + datesScrollView.contentOffset.x) / 31
151205 } else {
152206 dateView.dateLabel.textColor = .lightGray
153207 }
Hookah Tau/Controllers/Client/Reservations/Steps/First/FirstStepView.xib+25−1
@@ -5,6 +5,7 @@
55 <deployment identifier="iOS"/>
66 <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14824"/>
77 <capability name="Safe area layout guides" minToolsVersion="9.0"/>
8+ <capability name="Stack View standard spacing" minToolsVersion="9.0"/>
89 <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
910 </dependencies>
1011 <objects>
@@ -55,6 +56,23 @@
5556 <constraint firstAttribute="height" constant="1" id="me1-hs-aWn"/>
5657 </constraints>
5758 </view>
59+ <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacingType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="kS7-N4-kdg">
60+ <rect key="frame" x="16" y="9" width="382" height="53"/>
61+ <subviews>
62+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Для брони времени раньше 12:00 свяжитесь с администратором" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="6DK-77-Npa">
63+ <rect key="frame" x="0.0" y="0.0" width="187" height="53"/>
64+ <fontDescription key="fontDescription" type="system" pointSize="13"/>
65+ <color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
66+ <nil key="highlightedColor"/>
67+ </label>
68+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Для брони времени позже 3:00 свяжитесь с администратором" textAlignment="right" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qz5-ce-S3I">
69+ <rect key="frame" x="195" y="0.0" width="187" height="53"/>
70+ <fontDescription key="fontDescription" type="system" pointSize="13"/>
71+ <color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
72+ <nil key="highlightedColor"/>
73+ </label>
74+ </subviews>
75+ </stackView>
5876 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="zqK-OT-P26">
5977 <rect key="frame" x="0.0" y="70" width="414" height="1"/>
6078 <color key="backgroundColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
@@ -64,12 +82,16 @@
6482 </constraints>
6583 </view>
6684 </subviews>
67− <color key="backgroundColor" red="0.8901960784313725" green="0.8901960784313725" blue="0.8901960784313725" alpha="0.70716502568493156" colorSpace="custom" customColorSpace="calibratedRGB"/>
85+ <color key="backgroundColor" red="0.8901960784313725" green="0.8901960784313725" blue="0.8901960784313725" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
6886 <constraints>
6987 <constraint firstItem="nqq-Xp-Lig" firstAttribute="top" secondItem="dh5-kt-LFH" secondAttribute="top" id="6xZ-TR-tvC"/>
7088 <constraint firstAttribute="trailing" secondItem="zqK-OT-P26" secondAttribute="trailing" id="SeY-dj-8cT"/>
7189 <constraint firstAttribute="trailing" secondItem="nqq-Xp-Lig" secondAttribute="trailing" id="XtL-jd-AZH"/>
90+ <constraint firstItem="kS7-N4-kdg" firstAttribute="leading" secondItem="dh5-kt-LFH" secondAttribute="leading" constant="16" id="d0b-bx-btq"/>
91+ <constraint firstItem="zqK-OT-P26" firstAttribute="top" secondItem="kS7-N4-kdg" secondAttribute="bottom" constant="8" id="eNz-f4-nlO"/>
7292 <constraint firstAttribute="bottom" secondItem="zqK-OT-P26" secondAttribute="bottom" id="m0O-4r-wfZ"/>
93+ <constraint firstItem="kS7-N4-kdg" firstAttribute="top" secondItem="nqq-Xp-Lig" secondAttribute="bottom" constant="8" id="o6k-wD-gGp"/>
94+ <constraint firstAttribute="trailing" secondItem="kS7-N4-kdg" secondAttribute="trailing" constant="16" id="qfN-XY-Uqq"/>
7395 <constraint firstItem="nqq-Xp-Lig" firstAttribute="leading" secondItem="dh5-kt-LFH" secondAttribute="leading" id="qr9-52-TNC"/>
7496 <constraint firstAttribute="height" constant="71" id="tcS-2U-ecA"/>
7597 <constraint firstItem="zqK-OT-P26" firstAttribute="leading" secondItem="dh5-kt-LFH" secondAttribute="leading" id="yUf-Cj-HmN"/>
@@ -178,6 +200,8 @@
178200 <connections>
179201 <outlet property="datesScrollView" destination="Y9G-UI-WV7" id="dbT-BM-Ckq"/>
180202 <outlet property="datesStackView" destination="52e-LM-cF6" id="6Ni-IN-sm4"/>
203+ <outlet property="earlierThan12Label" destination="6DK-77-Npa" id="ftP-Jz-gzw"/>
204+ <outlet property="laterThan3Label" destination="qz5-ce-S3I" id="dzR-7k-uDq"/>
181205 <outlet property="scrollViewIntervals" destination="a6N-9A-8y5" id="uDW-QY-gNF"/>
182206 <outlet property="stackViewIntervals" destination="z9p-OK-tL7" id="0Mj-wX-kq7"/>
183207 </connections>
Hookah Tau/Controllers/Client/Reservations/Steps/First/TimePointView.swift+2
@@ -20,6 +20,8 @@ class TimePointView: UIView {
2020
2121 @IBOutlet weak var heightTimePoint: NSLayoutConstraint!
2222
23+
24+
2325 @IBOutlet weak var timePointContainer: UIView! {
2426 didSet {
2527 timePointContainer.layer.masksToBounds = false
Hookah Tau/Controllers/Client/Reservations/Steps/First/TimePointView.xib+2−2
@@ -40,9 +40,8 @@
4040 </constraints>
4141 </view>
4242 </subviews>
43− <color key="backgroundColor" red="0.8901960784313725" green="0.8901960784313725" blue="0.8901960784313725" alpha="0.14999999999999999" colorSpace="custom" customColorSpace="calibratedRGB"/>
43+ <color key="backgroundColor" red="0.8901960784313725" green="0.8901960784313725" blue="0.8901960784313725" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
4444 <constraints>
45− <constraint firstAttribute="height" constant="71" id="1YF-9X-fzU"/>
4645 <constraint firstItem="yHi-OK-OdD" firstAttribute="leading" secondItem="pWD-hx-gp6" secondAttribute="leading" id="B0T-9H-BtD"/>
4746 <constraint firstItem="yHi-OK-OdD" firstAttribute="top" secondItem="pWD-hx-gp6" secondAttribute="top" id="RNc-ds-Sgr"/>
4847 <constraint firstAttribute="trailing" secondItem="xmA-Sn-VW1" secondAttribute="trailing" id="UwV-GZ-ZJm"/>
@@ -68,6 +67,7 @@
6867 <constraint firstItem="pWD-hx-gp6" firstAttribute="trailing" secondItem="vUN-kp-3ea" secondAttribute="trailing" id="KBo-cb-dAz"/>
6968 <constraint firstItem="pWD-hx-gp6" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="NHW-lH-rza"/>
7069 <constraint firstItem="iIa-WK-OHd" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" id="Pfd-58-VXn"/>
70+ <constraint firstItem="pWD-hx-gp6" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" constant="21" id="Wpp-se-wxM"/>
7171 </constraints>
7272 <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
7373 <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
Hookah Tau/Controllers/Client/Reservations/Steps/FirstStepReservationCoordinator.swiftnew file+53
@@ -0,0 +1,53 @@
1+//
2+// ReservationCoordinator.swift
3+// Hookah Tau
4+//
5+// Created by cstore on 06/11/2019.
6+// Copyright © 2019 Daria Rednikina. All rights reserved.
7+//
8+
9+import UIKit
10+
11+class FirstStepReservationCoordinator: BaseCoordinator {
12+
13+ // MARK: - Properties
14+
15+ var didFinish: (() -> Void)?
16+
17+ // MARK: - Lifecycle
18+
19+ override func start() {
20+ let storyboard = UIStoryboard(name: "Reservation", bundle: nil)
21+ let reservationVC = storyboard.instantiateViewController(withIdentifier: "ReservationViewController") as! FirstStepReservationViewController
22+
23+ reservationVC.coordinator = self
24+ navigationController?.pushViewController(reservationVC, animated: true)
25+ }
26+
27+ func callAdmin() {
28+
29+ }
30+
31+ func makeReservation(model: SecondStepModel,
32+ mapView: MapImageScroll?) {
33+
34+ let reservationCoordinator =
35+ SecondStepReservationCoordinator(navigationController: navigationController)
36+
37+ reservationCoordinator.model = model
38+ reservationCoordinator.mapView = mapView
39+
40+ addDependency(reservationCoordinator)
41+
42+ reservationCoordinator.didFinish = { [weak self] mapView in
43+
44+ self?.navigationController?.popViewController(animated: false)
45+ self?.removeDependency(reservationCoordinator)
46+ if let vv = self?.navigationController?.topViewController as? FirstStepReservationViewController {
47+ vv.mapView = mapView
48+ }
49+ }
50+
51+ reservationCoordinator.start()
52+ }
53+}
Hookah Tau/Controllers/Client/Reservations/ReservationViewController.swift → Hookah Tau/Controllers/Client/Reservations/Steps/FirstStepReservationViewController.swiftrenamed+61−31
@@ -9,25 +9,41 @@
99import UIKit
1010
1111
12−class ReservationViewController: BaseViewController {
12+class FirstStepReservationViewController: BaseViewController {
1313
1414 // MARK: - Properties
1515
16+ weak var coordinator: FirstStepReservationCoordinator?
17+
1618 @IBOutlet weak var childContentView: UIView!
1719
1820 var firstStepView: FirstStepView?
1921
22+ var tableId: Int = 1
23+
2024 var reservationsService: ReservationsService?
2125
22− var mapView: MapImageScroll?
26+ var mapView: MapImageScroll? {
27+ didSet {
28+ view.addSubviewThatFills(mapView)
29+ guard let map = mapView else { return }
30+ map.scrollViewParent.contentInset = UIEdgeInsets(top: 0,
31+ left: 0,
32+ bottom: childContentView.frame.height,
33+ right: 0)
34+ map.isUserInteractionEnabled = true
35+ map.scrollViewParent.setZoomScale(0.5, animated: true)
36+ view.sendSubviewToBack(map)
37+ }
38+ }
2339
2440 var allReservations: AllReservations? {
2541 didSet {
26− guard let reservations = allReservations else {
42+ guard let _ = allReservations else {
2743 return
2844 }
2945
30− self.firstStepView?.setUp(reservations)
46+ updateChildViewControllerWithChosenId(tableId)
3147 }
3248 }
3349
@@ -35,7 +51,6 @@ class ReservationViewController: BaseViewController {
3551 let button = Button()
3652 let style = BlackButtonStyle()
3753 style.apply(to: button, withTitle: "ЗАБРОНИРОВАТЬ")
38− //button.addTarget(self, action: #selector(doneChanging), for: .touchUpInside)
3954 return button
4055 }()
4156
@@ -48,7 +63,6 @@ class ReservationViewController: BaseViewController {
4863 }()
4964
5065 var establishmentId: Int = 1
51− var step: Int = 1
5266
5367 // MARK: - Lifecycle
5468
@@ -56,14 +70,23 @@ class ReservationViewController: BaseViewController {
5670 super.viewDidLoad()
5771
5872 configureMap()
59− configureStep()
73+ setupChildContainer()
74+
75+ setupButtons()
6076
61− addStackViewWithButtons(leftBtn: callButton, rightBtn: continueButton, constant: -childContentView.frame.height - 20)
6277 reservationsService = ReservationsService(apiClient: APIClient.shared)
6378
6479 performUpdate()
6580 }
6681
82+ func setupButtons() {
83+ addStackViewWithButtons(leftBtn: callButton,
84+ rightBtn: continueButton,
85+ constant: -childContentView.frame.height - 20)
86+
87+ continueButton.addTarget(self, action: #selector(continueBooking), for: .touchUpInside)
88+ }
89+
6790 func performUpdate() {
6891 reservationsService?.getAllReservations(establishmentID: establishmentId, completion: { [weak self] result in
6992 switch result {
@@ -87,47 +110,54 @@ class ReservationViewController: BaseViewController {
87110 tabBarController?.tabBar.isHidden = true
88111 }
89112
90− override func viewWillDisappear(_ animated: Bool) {
91− super.viewWillDisappear(animated)
92−
93− tabBarController?.tabBar.isHidden = false
94− }
95−
96113 func configureMap() {
97114 if establishmentId == 1 {
98115 mapView = MapView1.loadFromNib()
99− view.addSubviewThatFills(mapView)
116+ mapView?.handler = self
100117 } else {
101118 // mapView = MapView2.loadFromNib()
102119 }
103−
104− guard let map = mapView else { return }
105− map.scrollViewParent.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: childContentView.frame.height, right: 0)
106− view.sendSubviewToBack(map)
107120 }
108121
109− func configureStep() {
110− if step == 1 {
111− firstStepView = FirstStepView.loadFromNib()
112− firstStepView?.mapUpdater = self
113− childContentView.addSubviewThatFills(firstStepView)
114− }
122+ func setupChildContainer() {
123+ firstStepView = FirstStepView.loadFromNib()
124+ firstStepView?.mapUpdater = self
125+ childContentView.addSubviewThatFills(firstStepView)
115126 }
116127
117128 func updateChildViewControllerWithChosenId(_ id: Int) {
118− print("Chosen \(id) table")
129+ let reservationsForTable = allReservations?.reservations[id] ?? [:]
130+ firstStepView?.setUp(reservationsForTable)
131+ }
132+
133+ // MARK: - button handlers
134+
135+ @objc func continueBooking() {
136+ let map = mapView
137+
138+ guard let startTime = firstStepView?.fullDate else { return }
139+
140+ let reservPeriods = allReservations?.reservations[tableId]?[startTime.getDMY()] ?? []
141+
142+ let model = SecondStepModel(table: tableId,
143+ startTime: startTime,
144+ reservedintervals: reservPeriods)
145+
146+ coordinator?.makeReservation(model: model,
147+ mapView: map)
119148 }
120149}
121150
122−extension ReservationViewController: MapHandler {
151+extension FirstStepReservationViewController: MapHandler {
123152 func handleTap(withId id: Int) {
153+ tableId = id
124154 updateChildViewControllerWithChosenId(id)
125155 }
126156}
127157
128−extension ReservationViewController: MapUpdater {
129− func update(_ date: IntervalDate) {
130− //let areBooked = allReservations?.intervals[date.getDateString()]?[date.getFullString()] ?? []
131− //mapView?.performUpdate(inactive: areBooked)
158+extension FirstStepReservationViewController: MapUpdater {
159+ func update(_ date: Date) {
160+ let areBooked = allReservations?.intervals[date.getDMY()]?[date] ?? []
161+ mapView?.performUpdate(inactive: areBooked)
132162 }
133163}
Hookah Tau/Controllers/Client/Reservations/Steps/Second/SecondStepView.swiftnew file+189
@@ -0,0 +1,189 @@
1+//
2+// SecondStepView.swift
3+// Hookah Tau
4+//
5+// Created by cstore on 21/11/2019.
6+// Copyright © 2019 Daria Rednikina. All rights reserved.
7+//
8+
9+import UIKit
10+
11+struct SecondStepModel {
12+ var table: Int
13+ var startTime: Date
14+ var reservedintervals: [ReservationPeriod]
15+}
16+
17+class SecondStepView: UIView {
18+
19+ // MARK: - Properties
20+
21+ @IBOutlet weak var totalBookingLabel: UILabel!
22+
23+ @IBOutlet weak var infoLabel: UILabel!
24+
25+ @IBOutlet weak var numberOfGuestsLabel: UILabel!
26+
27+ @IBOutlet weak var guestSlider: UISlider!
28+
29+ @IBOutlet weak var scrollView: UIScrollView!
30+
31+ @IBOutlet weak var intervalsStackView: UIStackView!
32+
33+ var model: SecondStepModel? {
34+ didSet {
35+ guard let model = model else { return }
36+ totalBookingLabel.text = "Забронировать \(model.table) столик на \(Int(guestSlider.value)) человека \(model.startTime)?"
37+
38+ setUpReservedIntervals(model.reservedintervals)
39+ setUpBookingPeriod(model.startTime)
40+ }
41+ }
42+
43+ var startLeadingConstraint: NSLayoutConstraint!
44+ var endLeadingConstraint: NSLayoutConstraint!
45+
46+ var startPoint: UIView = {
47+ var view = UIView()
48+ view.backgroundColor = .blue
49+ view.translatesAutoresizingMaskIntoConstraints = false
50+ return view
51+ }()
52+
53+ var endPoint: UIView = {
54+ var view = UIView()
55+ view.backgroundColor = .red
56+ view.translatesAutoresizingMaskIntoConstraints = false
57+ return view
58+ }()
59+
60+ var fillInterval: UIView = {
61+ var view = UIView()
62+ view.backgroundColor = #colorLiteral(red: 0.476841867, green: 0.5048075914, blue: 1, alpha: 0.604880137)
63+ view.translatesAutoresizingMaskIntoConstraints = false
64+ return view
65+ }()
66+
67+ var duration: Int? = 1
68+
69+ // MARK: - Lifecycle
70+
71+ override func awakeFromNib() {
72+ super.awakeFromNib()
73+
74+ scrollView.delegate = self
75+
76+ scrollView.showsHorizontalScrollIndicator = false
77+
78+ setUpIntervals()
79+ }
80+
81+ @IBAction func sliderValueChanged(_ sender: UISlider) {
82+ let value = Int(sender.value)
83+ numberOfGuestsLabel.text = "Количество гостей: \(value)"
84+ infoLabel.text = getNumberOfCalians(value)
85+ totalBookingLabel.text = "Забронировать \(model?.table ?? 0) столик на \(value) человека 29 марта с 3:00 до 5:30?"
86+ }
87+
88+ func getNumberOfCalians(_ sliderValue: Int) -> String {
89+ return "Минимальное количество кальянов: \(sliderValue > 6 ? 2 : 1)"
90+ }
91+
92+ // MARK: - Setup
93+
94+ func setUpIntervals() {
95+ for period in 0...Constants.day10MinPeriods {
96+ let timePointView = TimePointView.loadFromNib()
97+ timePointView?.setUp(withTimePoint: period)
98+ let view = UIView(frame: CGRect(x: 0, y: 0, width: 35, height: 106))
99+ view.addSubviewThatFills(timePointView)
100+ intervalsStackView.addArrangedSubview(view)
101+ }
102+ }
103+
104+ private func setUpBookingPeriod(_ startTime: Date) {
105+ self.scrollView.addSubview(startPoint)
106+ self.scrollView.addSubview(endPoint)
107+ self.scrollView.addSubview(fillInterval)
108+
109+ let startDate = startTime.set(hours: 12, minutes: 0, seconds: 0)!
110+
111+ let startConstr = CGFloat(startDate.getMinutesPeriods(fromStart: startTime) * Constants.timepointWidth)
112+
113+ scrollView.setContentOffset(CGPoint(x: startConstr, y: 0), animated: true)
114+
115+ startLeadingConstraint = startPoint.leftAnchor.constraint(equalTo: scrollView.leftAnchor,
116+ constant: startConstr)
117+ endLeadingConstraint = endPoint.leftAnchor.constraint(equalTo: scrollView.leftAnchor,
118+ constant:startConstr + CGFloat(10 * Constants.timepointWidth))
119+
120+ NSLayoutConstraint.activate([
121+ startPoint.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0),
122+ endPoint.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0),
123+
124+ startPoint.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0),
125+ endPoint.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0),
126+
127+ startPoint.widthAnchor.constraint(equalToConstant: 7),
128+ endPoint.widthAnchor.constraint(equalToConstant: 7),
129+
130+ startLeadingConstraint,
131+ endLeadingConstraint,
132+
133+ fillInterval.leftAnchor.constraint(equalTo: startPoint.rightAnchor, constant: 0),
134+ fillInterval.rightAnchor.constraint(equalTo: endPoint.leftAnchor, constant: 0),
135+
136+ fillInterval.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0),
137+ fillInterval.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0)
138+ ])
139+
140+ let scrollViewPanStartGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanStart(recognizer:)))
141+ startPoint.addGestureRecognizer(scrollViewPanStartGesture)
142+
143+ let scrollViewPanEndGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanEnd(recognizer:)))
144+ endPoint.addGestureRecognizer(scrollViewPanEndGesture)
145+ }
146+
147+ func setUpReservedIntervals(_ reservations: [ReservationPeriod]) {
148+
149+ }
150+
151+ func bind(model: SecondStepModel) {
152+ self.model = model
153+ }
154+
155+ // MARK: - Pan
156+
157+ @objc func handlePanStart(recognizer:UIPanGestureRecognizer) {
158+ let translation = recognizer.translation(in: self.intervalsStackView)
159+ if let view = recognizer.view {
160+ startLeadingConstraint.constant += translation.x
161+ view.setNeedsUpdateConstraints()
162+ }
163+
164+ recognizer.setTranslation(CGPoint.zero, in: self.intervalsStackView)
165+ }
166+
167+ @objc func handlePanEnd(recognizer:UIPanGestureRecognizer) {
168+ let translation = recognizer.translation(in: self.intervalsStackView)
169+ if let view = recognizer.view {
170+ endLeadingConstraint.constant += translation.x
171+ view.setNeedsUpdateConstraints()
172+ }
173+
174+ recognizer.setTranslation(CGPoint.zero, in: self.intervalsStackView)
175+ }
176+}
177+
178+extension SecondStepView: UIScrollViewDelegate {
179+
180+}
181+
182+// MARK: - Nested types
183+
184+extension SecondStepView {
185+ enum Constants {
186+ static let day10MinPeriods = 90
187+ static let timepointWidth = 11
188+ }
189+}
Hookah Tau/Controllers/Client/Reservations/Steps/Second/SecondStepView.xibnew file+154
@@ -0,0 +1,154 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14868" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
3+ <device id="retina4_7" orientation="portrait" appearance="light"/>
4+ <dependencies>
5+ <deployment identifier="iOS"/>
6+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14824"/>
7+ <capability name="Safe area layout guides" minToolsVersion="9.0"/>
8+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
9+ </dependencies>
10+ <objects>
11+ <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
12+ <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
13+ <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="SecondStepView" customModule="Hookah_Tau" customModuleProvider="target">
14+ <rect key="frame" x="0.0" y="0.0" width="414" height="394"/>
15+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
16+ <subviews>
17+ <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="bJ1-1q-VXq">
18+ <rect key="frame" x="20" y="20" width="374" height="121.5"/>
19+ <subviews>
20+ <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" alignment="center" spacing="21" translatesAutoresizingMaskIntoConstraints="NO" id="Dkh-B7-3Dl">
21+ <rect key="frame" x="16.5" y="0.0" width="341.5" height="82.5"/>
22+ <subviews>
23+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Забронировать 7 столик на 3 человека 29 марта с 3:00 до 5:30?" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="7M9-lI-egu">
24+ <rect key="frame" x="0.0" y="0.0" width="341.5" height="41"/>
25+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
26+ <nil key="textColor"/>
27+ <nil key="highlightedColor"/>
28+ </label>
29+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Минимальное количество кальянов: 2" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zMP-Wa-N6b">
30+ <rect key="frame" x="11" y="62" width="319" height="20.5"/>
31+ <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="17"/>
32+ <nil key="textColor"/>
33+ <nil key="highlightedColor"/>
34+ </label>
35+ </subviews>
36+ </stackView>
37+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PHb-Nt-9I2">
38+ <rect key="frame" x="47" y="92.5" width="280.5" height="29"/>
39+ <string key="text">Если Вам нужно что-то особенное, Вы можете
40+связаться с администратором.</string>
41+ <fontDescription key="fontDescription" type="system" pointSize="12"/>
42+ <color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
43+ <nil key="highlightedColor"/>
44+ </label>
45+ </subviews>
46+ </stackView>
47+ <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="9c7-IZ-n2p">
48+ <rect key="frame" x="20" y="171.5" width="373.5" height="60.5"/>
49+ <subviews>
50+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Количество гостей: 3" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QuY-68-2ax">
51+ <rect key="frame" x="0.0" y="0.0" width="373.5" height="20.5"/>
52+ <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="17"/>
53+ <nil key="textColor"/>
54+ <nil key="highlightedColor"/>
55+ </label>
56+ <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="3" minValue="1" maxValue="10" translatesAutoresizingMaskIntoConstraints="NO" id="TrY-MC-Ty0">
57+ <rect key="frame" x="-2" y="30.5" width="377.5" height="31"/>
58+ <connections>
59+ <action selector="sliderValueChanged:" destination="iN0-l3-epB" eventType="valueChanged" id="ekZ-3h-EeB"/>
60+ </connections>
61+ </slider>
62+ </subviews>
63+ </stackView>
64+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="RJE-Hk-KNh">
65+ <rect key="frame" x="0.0" y="268" width="414" height="106"/>
66+ <subviews>
67+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dmc-2e-y3T">
68+ <rect key="frame" x="0.0" y="20" width="414" height="86"/>
69+ <subviews>
70+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lBc-2o-oni">
71+ <rect key="frame" x="0.0" y="0.0" width="414" height="1"/>
72+ <color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
73+ <constraints>
74+ <constraint firstAttribute="height" constant="1" id="dFH-fE-V61"/>
75+ </constraints>
76+ </view>
77+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7Du-Fg-z1t">
78+ <rect key="frame" x="0.0" y="85" width="414" height="1"/>
79+ <color key="backgroundColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
80+ <constraints>
81+ <constraint firstAttribute="height" constant="1" id="hal-Zc-mvq"/>
82+ <constraint firstAttribute="height" relation="greaterThanOrEqual" constant="1" id="mCA-jf-NGh"/>
83+ </constraints>
84+ </view>
85+ </subviews>
86+ <color key="backgroundColor" red="0.89019607840000003" green="0.89019607840000003" blue="0.89019607840000003" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
87+ <constraints>
88+ <constraint firstAttribute="trailing" secondItem="7Du-Fg-z1t" secondAttribute="trailing" id="5fu-5i-psO"/>
89+ <constraint firstAttribute="trailing" secondItem="lBc-2o-oni" secondAttribute="trailing" id="7eP-jA-V9V"/>
90+ <constraint firstItem="lBc-2o-oni" firstAttribute="leading" secondItem="dmc-2e-y3T" secondAttribute="leading" id="CA6-4b-6ZK"/>
91+ <constraint firstItem="7Du-Fg-z1t" firstAttribute="leading" secondItem="dmc-2e-y3T" secondAttribute="leading" id="YwH-ns-ecE"/>
92+ <constraint firstItem="lBc-2o-oni" firstAttribute="top" secondItem="dmc-2e-y3T" secondAttribute="top" id="ja1-YQ-A2D"/>
93+ <constraint firstAttribute="height" constant="86" id="rbN-al-oWi"/>
94+ <constraint firstAttribute="bottom" secondItem="7Du-Fg-z1t" secondAttribute="bottom" id="wa8-GY-qKm"/>
95+ </constraints>
96+ </view>
97+ <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="zk1-3E-2kS">
98+ <rect key="frame" x="0.0" y="0.0" width="414" height="106"/>
99+ <subviews>
100+ <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IIO-je-eBt">
101+ <rect key="frame" x="10" y="0.0" width="414" height="106"/>
102+ </stackView>
103+ </subviews>
104+ <constraints>
105+ <constraint firstAttribute="bottom" secondItem="IIO-je-eBt" secondAttribute="bottom" id="FFo-Gu-FQi"/>
106+ <constraint firstItem="IIO-je-eBt" firstAttribute="top" secondItem="zk1-3E-2kS" secondAttribute="top" id="GCb-A1-Nm9"/>
107+ <constraint firstItem="IIO-je-eBt" firstAttribute="width" secondItem="zk1-3E-2kS" secondAttribute="width" priority="250" id="NNQ-JX-gov"/>
108+ <constraint firstItem="IIO-je-eBt" firstAttribute="leading" secondItem="zk1-3E-2kS" secondAttribute="leading" constant="10" id="SFN-at-Ckn"/>
109+ <constraint firstItem="IIO-je-eBt" firstAttribute="height" secondItem="zk1-3E-2kS" secondAttribute="height" id="rPM-R0-lcb"/>
110+ <constraint firstAttribute="trailing" secondItem="IIO-je-eBt" secondAttribute="trailing" constant="10" id="xBZ-av-Hao"/>
111+ </constraints>
112+ <viewLayoutGuide key="contentLayoutGuide" id="AEC-Ih-oKP"/>
113+ <viewLayoutGuide key="frameLayoutGuide" id="ciz-kC-nwk"/>
114+ </scrollView>
115+ </subviews>
116+ <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
117+ <constraints>
118+ <constraint firstAttribute="height" constant="106" id="DIa-m5-0fc"/>
119+ <constraint firstItem="zk1-3E-2kS" firstAttribute="top" secondItem="RJE-Hk-KNh" secondAttribute="top" id="gWD-k8-Ycq"/>
120+ <constraint firstAttribute="trailing" secondItem="zk1-3E-2kS" secondAttribute="trailing" id="iuc-Gd-ZUo"/>
121+ <constraint firstAttribute="bottom" secondItem="dmc-2e-y3T" secondAttribute="bottom" id="k3O-Eo-mm5"/>
122+ <constraint firstItem="zk1-3E-2kS" firstAttribute="leading" secondItem="RJE-Hk-KNh" secondAttribute="leading" id="qT5-vh-S0P"/>
123+ <constraint firstAttribute="trailing" secondItem="dmc-2e-y3T" secondAttribute="trailing" id="tTC-4l-vfe"/>
124+ <constraint firstAttribute="bottom" secondItem="zk1-3E-2kS" secondAttribute="bottom" id="whX-aj-8o9"/>
125+ <constraint firstItem="dmc-2e-y3T" firstAttribute="leading" secondItem="RJE-Hk-KNh" secondAttribute="leading" id="ymc-Tp-Lqg"/>
126+ </constraints>
127+ </view>
128+ </subviews>
129+ <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
130+ <constraints>
131+ <constraint firstItem="9c7-IZ-n2p" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="20" id="94y-7J-ksb"/>
132+ <constraint firstItem="9c7-IZ-n2p" firstAttribute="top" secondItem="bJ1-1q-VXq" secondAttribute="bottom" constant="30" id="9TT-vO-7PZ"/>
133+ <constraint firstItem="RJE-Hk-KNh" firstAttribute="trailing" secondItem="vUN-kp-3ea" secondAttribute="trailing" id="AgS-kP-UNE"/>
134+ <constraint firstItem="RJE-Hk-KNh" firstAttribute="top" secondItem="9c7-IZ-n2p" secondAttribute="bottom" constant="36" id="FAI-xj-uWk"/>
135+ <constraint firstAttribute="trailing" secondItem="bJ1-1q-VXq" secondAttribute="trailing" constant="20" id="OCH-eC-kP5"/>
136+ <constraint firstItem="bJ1-1q-VXq" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="20" id="PCm-nY-M6p"/>
137+ <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="9c7-IZ-n2p" secondAttribute="trailing" constant="20.5" id="Rh7-V2-v2u"/>
138+ <constraint firstItem="bJ1-1q-VXq" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" constant="20" id="SnG-Cy-hHq"/>
139+ <constraint firstItem="RJE-Hk-KNh" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="fW0-Tt-MpN"/>
140+ </constraints>
141+ <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
142+ <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
143+ <connections>
144+ <outlet property="guestSlider" destination="TrY-MC-Ty0" id="mR0-wv-AM7"/>
145+ <outlet property="infoLabel" destination="zMP-Wa-N6b" id="htu-ql-T0O"/>
146+ <outlet property="intervalsStackView" destination="IIO-je-eBt" id="gaP-LX-Xed"/>
147+ <outlet property="numberOfGuestsLabel" destination="QuY-68-2ax" id="DvK-dr-c3J"/>
148+ <outlet property="scrollView" destination="zk1-3E-2kS" id="b8R-jY-2Q3"/>
149+ <outlet property="totalBookingLabel" destination="7M9-lI-egu" id="7YU-yI-Gm4"/>
150+ </connections>
151+ <point key="canvasLocation" x="137.59999999999999" y="70.164917541229386"/>
152+ </view>
153+ </objects>
154+</document>
Hookah Tau/Controllers/Client/Reservations/Steps/SecondStepReservationCoordinator.swiftnew file+38
@@ -0,0 +1,38 @@
1+//
2+// SecondStepReservationCoordinator.swift
3+// Hookah Tau
4+//
5+// Created by cstore on 21/11/2019.
6+// Copyright © 2019 Daria Rednikina. All rights reserved.
7+//
8+
9+import UIKit
10+
11+
12+class SecondStepReservationCoordinator: BaseCoordinator {
13+
14+ // MARK: - Properties
15+
16+ var didFinish: ((MapImageScroll?) -> Void)?
17+
18+ var model: SecondStepModel?
19+
20+ var mapView: MapImageScroll?
21+
22+ // MARK: - Lifecycle
23+
24+ override func start() {
25+ let storyboard = UIStoryboard(name: "Reservation", bundle: nil)
26+ let reservationVC = storyboard.instantiateViewController(withIdentifier: "SecondStepReservationViewController") as! SecondStepReservationViewController
27+
28+ reservationVC.model = model
29+ reservationVC.mapView = mapView
30+ reservationVC.coordinator = self
31+
32+ navigationController?.pushViewController(reservationVC, animated: false)
33+ }
34+
35+ func cancel(_ mapView: MapImageScroll?) {
36+ didFinish?(mapView)
37+ }
38+}
Hookah Tau/Extensions+Date.swift+83−33
@@ -16,42 +16,32 @@ struct IntervalDate {
1616 var minutes: Int? = nil
1717}
1818
19−extension IntervalDate {
20− func getFullString() -> String {
21− var result = getDateString()
22− if let min = minutes {
23− result += "T\(min * 10 / 60 + 12):\(min * 10 % 60):00Z"
24− }
25− return result
26− }
27−
28− func getDateString() -> String {
29− return "\(year)-\(month)-\(day)"
30− }
31−}
32−
3319extension DateFormatter {
34− static let iso8601Full: DateFormatter = {
35− let formatter = DateFormatter()
36− formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
37− formatter.timeZone = TimeZone(abbreviation: "UTC")
38− return formatter
39− }()
20+ static let iso8601Full: DateFormatter = {
21+ let formatter = DateFormatter()
22+ formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
23+ formatter.timeZone = TimeZone(abbreviation: "UTC")
24+ return formatter
25+ }()
26+
27+ static let dmy: DateFormatter = {
28+ let formatter = DateFormatter()
29+ formatter.dateFormat = "yyyy-MM-dd"
30+ formatter.timeZone = TimeZone(abbreviation: "UTC")
31+ return formatter
32+ }()
4033}
4134
4235
4336extension Date {
44− static func getNext(days: Int) -> [IntervalDate] {
45− var result = [IntervalDate]()
37+ static func getNext(days: Int) -> [Date] {
38+ var result = [Date]()
4639
4740 var date = Date()
4841 let calendar = Calendar.current
4942
5043 for _ in 1...days {
51− let appendingResult = IntervalDate(day: calendar.component(.day, from: date),
52− month: calendar.component(.month, from: date),
53− year: calendar.component(.year, from: date))
54− result.append(appendingResult)
44+ result.append(date)
5545
5646 let newDate = calendar.date(byAdding: .day, value: 1, to: date)
5747 guard let nextDate = newDate else { break }
@@ -61,16 +51,76 @@ extension Date {
6151 return result
6252 }
6353
64− static func getDateFromCurrent(days: Int = 0, period: Int? = nil) -> IntervalDate? {
54+ static func getDateFromCurrent(days: Int = 0, periods: Int? = nil) -> Date? {
6555 let date = Date()
6656 let calendar = Calendar.current
6757
68− let newDate = calendar.date(byAdding: .day, value: days, to: date)
69− guard let nextDate = newDate else { return nil }
58+ let day = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: date)
59+
60+ var dateCalendars = DateComponents()
61+ dateCalendars.hour = day.hour!
62+ dateCalendars.minute = day.minute!
63+ dateCalendars.day = day.day!
64+ dateCalendars.month = day.month!
65+ dateCalendars.year = day.year!
66+ dateCalendars.timeZone = TimeZone(abbreviation: "GMT")
67+
68+ let utcDate = Calendar.current.date(from: dateCalendars)!
69+
70+ let newDate = calendar.date(byAdding: .day, value: days, to: utcDate)
71+
72+ // case if periods are important
73+ if let minutes = periods, let date = newDate {
74+ return date.changeTime(periods: minutes)
75+ }
76+
7077
71− return IntervalDate(day: calendar.component(.day, from: nextDate),
72− month: calendar.component(.month, from: nextDate),
73− year: calendar.component(.year, from: nextDate),
74− minutes: period)
78+ return newDate
79+ }
80+
81+ func changeTime(periods: Int) -> Date? {
82+ let hours = (periods * 10 / 60 + 12) % 24
83+ let min = (periods * 10) % 60
84+
85+ let day = Calendar.current.dateComponents([.year, .month, .day], from: self)
86+
87+ var dateCalendars = DateComponents()
88+ dateCalendars.hour = hours
89+ dateCalendars.minute = min
90+ dateCalendars.day = day.day!
91+ dateCalendars.month = day.month!
92+ dateCalendars.year = day.year!
93+ dateCalendars.timeZone = TimeZone(abbreviation: "GMT")
94+
95+ return Calendar.current.date(from: dateCalendars)
96+ }
97+
98+ func getDay() -> Int {
99+ let day = Calendar.current.dateComponents([.day], from: self)
100+ return day.day ?? 0
101+ }
102+
103+ func getDMY() -> Date {
104+ return set(hours: 0, minutes: 0, seconds: 0)!
105+ }
106+
107+ func set(hours: Int, minutes: Int, seconds: Int) -> Date? {
108+
109+ let dateFormatter = DateFormatter()
110+ dateFormatter.calendar = Calendar.current
111+ dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
112+ dateFormatter.dateFormat = "yyyy-MM-dd"
113+
114+ let newDateString = "\(dateFormatter.string(from: self)) \(hours):\(minutes):\(seconds)"
115+
116+ dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
117+
118+ return dateFormatter.date(from: newDateString)
119+ }
120+
121+ func getMinutesPeriods(fromStart startDate: Date) -> Int {
122+ let diffInMins = Calendar.current.dateComponents([.minute], from: self, to: startDate).minute!
123+ let periods = diffInMins / 10
124+ return periods
75125 }
76126}
Hookah Tau/Models/AllReservations.swift+31−2
@@ -10,10 +10,39 @@ import Foundation
1010
1111struct AllReservations: MyCodable {
1212 var reservations: [Int: [Date: [ReservationPeriod]]]
13− var intervals: [String: [Date: [Int]]]
13+ var intervals: [Date: [Date: [Int]]]
14+
15+ enum CodingKeys: CodingKey {
16+ case reservations
17+ case intervals
18+ }
19+
20+ init(from decoder: Decoder) throws {
21+ let container = try decoder.container(keyedBy: CodingKeys.self)
22+
23+ let intervalsWithStr = try container.decode([String: [String: [Int]]].self, forKey: .intervals)
24+ let reservationWithStr = try container.decode([String: [String: [ReservationPeriod]]].self, forKey: .reservations)
25+
26+ let resArray = reservationWithStr.map { (element) -> (Int, [Date: [ReservationPeriod]]) in
27+ let key = Int(element.key) ?? 0
28+ let valArr = element.value.compactMap { (DateFormatter.dmy.date(from: $0.0)!, $0.1) }
29+ let val = Dictionary(uniqueKeysWithValues: valArr)
30+ return (key, val)
31+ }
32+
33+ let intervArray = intervalsWithStr.map { (element) -> (Date, [Date: [Int]]) in
34+ let key = DateFormatter.dmy.date(from: element.key)!
35+ let arr = element.value.compactMap { (DateFormatter.iso8601Full.date(from: $0.0)!, $0.1) }
36+ let val = Dictionary(uniqueKeysWithValues: arr)
37+ return (key, val)
38+ }
39+
40+ intervals = Dictionary(uniqueKeysWithValues: intervArray)
41+ reservations = Dictionary(uniqueKeysWithValues: resArray)
42+ }
1443}
1544
1645struct ReservationPeriod: MyCodable {
17− var startTime: String
46+ var startTime: Date
1847 var duration: Int
1948}