@@ -18,7 +18,7 @@ struct SecondStepModel {
1818
1919class SecondStepView: UIView {
2020
21− // MARK: - Properties
21+ // MARK: - IBAOutlets
2222
2323 @IBOutlet weak var totalBookingLabel: UILabel!
2424
@@ -32,6 +32,14 @@ class SecondStepView: UIView {
3232
3333 @IBOutlet weak var intervalsStackView: UIStackView!
3434
35+ // MARK: - Peoperties
36+
37+ /// Время начала вертелки.
38+ /// Для клиента это 12:00 смены (надо вызвать метод для получения текущей смены).
39+ /// Для администратора это `t` - 24h
40+ var startDate: Date?
41+
42+ /// Модель вьюшки
3543 var data: ReservationData? {
3644 didSet {
3745 guard let d = data else { return }
@@ -40,6 +48,7 @@ class SecondStepView: UIView {
4048 }
4149 }
4250
51+ /// Модель с которой мы приходим в эту вьюшку
4352 var model: SecondStepModel? {
4453 didSet {
4554 guard let model = model else { return }
@@ -50,12 +59,20 @@ class SecondStepView: UIView {
5059 numberOfGuests: Int(guestSlider.value),
5160 reservedTable: model.table)
5261
53− setUpIntervals(model.startTime)
54− setUpReservedIntervals(model.reservedintervals)
62+ // isAdmin
63+ let isAdmin = DataStorage.standard.getUserModel()?.isAdmin ?? false
64+
65+ let (start, _) = isAdmin ? model.startTime.getAdminStartingAndEndPoint() : model.startTime.getClientStartingAndEndPoint()
66+
67+ startDate = start
68+
69+ setUpIntervals(isAdmin)
70+ setUpReservedIntervals(model.reservedintervals, isAdmin)
5571 setUpBookingPeriod(model.startTime)
5672 }
5773 }
5874
75+ // констрейнты начала и конца интервала
5976 var startLeadingConstraint: NSLayoutConstraint!
6077 var endLeadingConstraint: NSLayoutConstraint!
6178
@@ -70,11 +87,12 @@ class SecondStepView: UIView {
7087 var endPoint: UIImageView = {
7188 var view = UIImageView()
7289 view.isUserInteractionEnabled = true
73− view.image = #imageLiteral(resourceName: "fff")
90+ view.image = #imageLiteral(resourceName: "Group")
7491 view.translatesAutoresizingMaskIntoConstraints = false
7592 return view
7693 }()
7794
95+ /// Интервал
7896 var fillInterval: UIView = {
7997 var view = UIView()
8098 view.backgroundColor = #colorLiteral(red: 0, green: 0.5921568627, blue: 1, alpha: 0.3426262843)
@@ -82,8 +100,6 @@ class SecondStepView: UIView {
82100 return view
83101 }()
84102
85− var duration: Int? = 1
86−
87103 // MARK: - Lifecycle
88104
89105 override func awakeFromNib() {
@@ -114,10 +130,9 @@ class SecondStepView: UIView {
114130
115131 // MARK: - Setup
116132
117− func setUpIntervals(_ stTime: Date) {
118− let isAdmin = DataStorage.standard.getUserModel()?.isAdmin ?? false
119−
120− let (startPoint, _) = isAdmin ? stTime.getAdminStartingAndEndPoint() : stTime.getClientStartingAndEndPoint()
133+ /// Тут происходит установка интервалов. Разное для клиента и админа
134+ func setUpIntervals(_ isAdmin: Bool) {
135+ guard let startPoint = startDate else { return }
121136
122137 let startingPoint = isAdmin ? startPoint.getAdminsStartingPoint() : Constants.clientStartingPoint
123138 let endingPoint = startingPoint + (isAdmin ? Constants.adminDuration : Constants.clientDuration)
@@ -138,9 +153,9 @@ class SecondStepView: UIView {
138153 self.scrollView.addSubview(endPoint)
139154 self.scrollView.addSubview(fillInterval)
140155
141− let startDate = startTime.set(hours: 12, minutes: 0, seconds: 0)!// for client
156+ guard let startDate = startDate else { return }
142157
143− let startConstr = CGFloat(startTime.getMinutesPeriods(fromStart: startDate) * Constants.timepointWidth)
158+ let startConstr = CGFloat(startTime.getMinutesPeriods(fromStart: startDate) * Constants.widthTimePoint)
144159
145160 scrollView.setContentOffset(CGPoint(x: startConstr - 50, y: 0), animated: true)
146161
@@ -148,7 +163,7 @@ class SecondStepView: UIView {
148163 constant: startConstr)
149164
150165 endLeadingConstraint = endPoint.leftAnchor.constraint(equalTo: scrollView.leftAnchor,
151− constant:startConstr + CGFloat(10 * Constants.timepointWidth))
166+ constant:startConstr + Constants.minBookingLength)
152167
153168 NSLayoutConstraint.activate([
154169
@@ -178,8 +193,39 @@ class SecondStepView: UIView {
178193 endPoint.addGestureRecognizer(scrollViewPanEndGesture)
179194 }
180195
181− func setUpReservedIntervals(_ reservations: [ReservationPeriod]) {
196+ func setUpReservedIntervals(_ reservations: [ReservationPeriod], _ isAdmin: Bool) {
197+
198+ for reservation in reservations {
199+ let uiview = UIView(frame: CGRect(x: 0, y: 0, width: Constants.widthTimePoint * reservation.duration, height: Constants.heightIntervals))
200+ uiview.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 0.5)
201+
202+
203+ uiview.translatesAutoresizingMaskIntoConstraints = false
204+ scrollView.addSubview(uiview)
182205
206+ guard let startDate = startDate else { return }
207+
208+ let s = reservation.startTime.getMinutesPeriods(fromStart: startDate) * Constants.widthTimePoint
209+ let d = reservation.duration * Constants.widthTimePoint
210+
211+ let startTime = s < 0 ? 0 : s
212+
213+ let total = (isAdmin ? Constants.adminDuration : Constants.clientDuration) * Constants.widthTimePoint
214+ var duration = 0
215+ if s < 0 {
216+ duration = reservation.endTime.getMinutesPeriods(fromStart: startDate) * Constants.widthTimePoint
217+ } else {
218+ duration = (s + d) > total ? total - s : d
219+ }
220+
221+ NSLayoutConstraint.activate([
222+ uiview.bottomAnchor.constraint(equalToSystemSpacingBelow: scrollView.bottomAnchor, multiplier: 0),
223+ uiview.leftAnchor.constraint(equalTo: scrollView.leftAnchor,
224+ constant: CGFloat(Constants.widthTimePoint / 2 + startTime)),
225+ uiview.widthAnchor.constraint(equalToConstant: CGFloat(duration)),
226+ uiview.heightAnchor.constraint(equalToConstant: CGFloat(Constants.heightIntervals))
227+ ])
228+ }
183229 }
184230
185231 func bind(model: SecondStepModel) {
@@ -193,57 +239,60 @@ class SecondStepView: UIView {
193239 // MARK: - Pan
194240
195241 @objc func handlePanStart(recognizer:UIPanGestureRecognizer) {
196− guard let d = data else { return }
197242
198− let translation = recognizer.translation(in: self.intervalsStackView)
199− if let view = recognizer.view {
243+ let translation = recognizer.translation(in: self.intervalsStackView)
244+ let duration = abs(startLeadingConstraint.constant + translation.x - endLeadingConstraint.constant)
245+
246+ if let view = recognizer.view, duration >= Constants.minBookingLength {
200247 startLeadingConstraint.constant += translation.x
201248
202− let offset = Int(startLeadingConstraint.constant) % Constants.timepointWidth
203− if offset == 0 {
204−
205− let startDate = d.startTime.set(hours: 12, minutes: 0, seconds: 0)!// for client
206− let p = Int(startLeadingConstraint.constant) / Constants.timepointWidth
207− let start = startDate.addPeriods(p)
208−
209− data = ReservationData(establishment: d.establishment,
210− startTime: start,
211− endTime: d.endTime,
212− numberOfGuests: d.numberOfGuests,
213− reservedTable: d.reservedTable)
214− }
249+ changeTime(startLeadingConstraint, .start)
215250
216251 view.setNeedsUpdateConstraints()
217252 }
218253
219−
220− recognizer.setTranslation(CGPoint.zero, in: self.intervalsStackView)
254+ recognizer.setTranslation(CGPoint.zero, in: self.intervalsStackView)
221255 }
222256
223257 @objc func handlePanEnd(recognizer:UIPanGestureRecognizer) {
224− guard let d = data else { return }
225258
226− let translation = recognizer.translation(in: self.intervalsStackView)
227− if let view = recognizer.view {
259+ let translation = recognizer.translation(in: self.intervalsStackView)
260+ let duration = abs(startLeadingConstraint.constant - (endLeadingConstraint.constant + translation.x))
261+
262+ if let view = recognizer.view, duration >= Constants.minBookingLength {
228263 endLeadingConstraint.constant += translation.x
229264
230− let offset = Int(endLeadingConstraint.constant) % Constants.timepointWidth
231− if offset == 0 {
232− let startDate = d.startTime.set(hours: 12, minutes: 0, seconds: 0)!// for client
233− let p = Int(endLeadingConstraint.constant) / Constants.timepointWidth
234− let end = startDate.addPeriods(p)
235−
265+ changeTime(endLeadingConstraint, .end)
266+ view.setNeedsUpdateConstraints()
267+ }
268+
269+ recognizer.setTranslation(CGPoint.zero, in: self.intervalsStackView)
270+ }
271+
272+ func changeTime(_ constraint: NSLayoutConstraint, _ period: Period) {
273+ guard let startDate = startDate, let d = data else { return }
274+
275+ let offset = Int(constraint.constant) % Constants.widthTimePoint
276+
277+ if offset == 0 {
278+ let p = Int(constraint.constant) / Constants.widthTimePoint
279+ let time = startDate.addPeriods(p)
280+
281+ switch period {
282+ case .start:
283+ data = ReservationData(establishment: d.establishment,
284+ startTime: time,
285+ endTime: d.endTime,
286+ numberOfGuests: d.numberOfGuests,
287+ reservedTable: d.reservedTable)
288+ case .end:
236289 data = ReservationData(establishment: d.establishment,
237290 startTime: d.startTime,
238− endTime: end,
291+ endTime: time,
239292 numberOfGuests: d.numberOfGuests,
240293 reservedTable: d.reservedTable)
241294 }
242−
243− view.setNeedsUpdateConstraints()
244− }
245−
246− recognizer.setTranslation(CGPoint.zero, in: self.intervalsStackView)
295+ }
247296 }
248297}
249298
@@ -255,7 +304,7 @@ extension SecondStepView: UIScrollViewDelegate {
255304
256305extension SecondStepView {
257306 enum Constants {
258− static let timepointWidth = 11
307+ static let widthTimePoint = 11
259308
260309 static let adminDuration = 288
261310 static let clientDuration = 90
@@ -263,6 +312,15 @@ extension SecondStepView {
263312 static let clientStartingPoint = 72
264313
265314 static let pointWidth: CGFloat = 19
266− static let pointHeight: CGFloat = 86
315+ static let pointHeight: CGFloat = 85
316+
317+ static let minBookingLength: CGFloat = 132
318+
319+ static let heightIntervals = 85
320+ }
321+
322+ enum Period {
323+ case start
324+ case end
267325 }
268326}