@@ -35,6 +35,45 @@ class AdminReservationView: UIView {
3535
3636 @IBOutlet weak var intervalsContainerView: UIView?
3737
38+ @IBOutlet weak var scrollView: UIScrollView!
39+
40+ @IBOutlet weak var intervalsStackView: UIStackView!
41+
42+ // MARK: - Properties
43+
44+ // констрейнты начала и конца интервала
45+ var startLeadingConstraint: NSLayoutConstraint!
46+ var endLeadingConstraint: NSLayoutConstraint!
47+
48+ var startPoint: UIImageView = {
49+ var view = UIImageView()
50+ view.isUserInteractionEnabled = true
51+ view.image = #imageLiteral(resourceName: "handle_left")
52+ view.translatesAutoresizingMaskIntoConstraints = false
53+ return view
54+ }()
55+
56+ var endPoint: UIImageView = {
57+ var view = UIImageView()
58+ view.isUserInteractionEnabled = true
59+ view.image = #imageLiteral(resourceName: "Group")
60+ view.translatesAutoresizingMaskIntoConstraints = false
61+ return view
62+ }()
63+
64+ /// Интервал
65+ var fillInterval: UIView = {
66+ var view = UIView()
67+ view.backgroundColor = #colorLiteral(red: 0, green: 0.5921568627, blue: 1, alpha: 0.3426262843)
68+ view.translatesAutoresizingMaskIntoConstraints = false
69+ return view
70+ }()
71+
72+ /// Время начала вертелки.
73+ /// Для клиента это 12:00 смены (надо вызвать метод для получения текущей смены).
74+ /// Для администратора это `t` - 24h
75+ var startDate: Date?
76+
3877 // MARK:- Properties
3978
4079 var intervalPickerView: IntervalPickerView?
@@ -64,10 +103,25 @@ class AdminReservationView: UIView {
64103 endTime: model.endTime,
65104 numberOfGuests: model.numberOfGuests,
66105 reservedTable: model.reservedTable)
106+ self.model = model
107+
108+ let (start, _) = model.owner.isAdmin ? model.startTime.getAdminStartingAndEndPoint() : model.startTime.getClientStartingAndEndPoint()
109+
110+ startDate = start
111+
112+ setUpIntervals(model.owner.isAdmin)
113+
114+ guestSlider?.maximumValue = Float((TotalStorage.standard.getTable(establishment: model.establishment, table: model.reservedTable)?.maxGuestNumber ?? 2) + 1)
67115 }
68116
69117 func bind(withIntervals intervals: [ReservationPeriod]) {
118+ guard
119+ let data = data,
120+ let isAdmin = model?.owner.isAdmin
121+ else { return }
70122
123+ setUpReservedIntervals(intervals, isAdmin)
124+ setUpBookingPeriod(data.startTime, data.endTime)
71125 }
72126
73127 func updateDateAndTime(withData d: ReservationData?) {
@@ -77,6 +131,220 @@ class AdminReservationView: UIView {
77131 dateLabel?.text = date
78132 timeLabel?.text = time
79133 }
134+
135+ @IBAction func valueChanged(_ sender: UISlider) {
136+ let value = Int(sender.value)
137+
138+ if sender.value == sender.maximumValue {
139+ numberOfGuestLabel?.text = "Количество гостей: \(Int(value) - 1)+"
140+ } else {
141+ numberOfGuestLabel?.text = "Количество гостей: \(value)"
142+ }
143+
144+ guard let d = data else { return }
145+
146+ data = ReservationData(establishment: d.establishment,
147+ startTime: d.startTime,
148+ endTime: d.endTime,
149+ numberOfGuests: value,
150+ reservedTable: d.reservedTable)
151+ }
152+
153+
154+ func getNumberOfCalians(_ sliderValue: Int) -> String {
155+ return "Минимальное количество кальянов: \(sliderValue > 6 ? 2 : 1)"
156+ }
157+
158+ // MARK: - Setup
159+
160+ /// Тут происходит установка интервалов. Разное для клиента и админа
161+ func setUpIntervals(_ isAdmin: Bool) {
162+ guard let startPoint = startDate else { return }
163+
164+ let startingPoint = isAdmin ? startPoint.getAdminsStartingPoint() : Constants.clientStartingPoint
165+ let endingPoint = startingPoint + (isAdmin ? Constants.adminDuration : Constants.clientDuration)
166+
167+ for period in startingPoint...endingPoint {
168+ let timePointView = TimePointView.loadFromNib()
169+ timePointView?.setUp(withTimePoint: period)
170+ let view = UIView(frame: CGRect(x: 0, y: 0, width: 35, height: 106))
171+ view.addSubviewThatFills(timePointView)
172+ intervalsStackView.addArrangedSubview(view)
173+ }
174+ }
175+
176+
177+ private func setUpBookingPeriod(_ startTime: Date, _ endTime: Date? = nil) {
178+ self.scrollView.addSubview(startPoint)
179+ self.scrollView.addSubview(endPoint)
180+ self.scrollView.addSubview(fillInterval)
181+
182+ guard let startDate = startDate else { return }
183+
184+ let startConstr = CGFloat(startTime.getMinutesPeriods(fromStart: startDate) * Constants.widthTimePoint)
185+
186+ scrollView.setContentOffset(CGPoint(x: startConstr - 50, y: 0), animated: true)
187+
188+ startLeadingConstraint = startPoint.leftAnchor.constraint(equalTo: scrollView.leftAnchor,
189+ constant: startConstr)
190+
191+ if let end = endTime {
192+ let endConstr = CGFloat(end.getMinutesPeriods(fromStart: startDate) * Constants.widthTimePoint)
193+ endLeadingConstraint = endPoint.leftAnchor.constraint(equalTo: scrollView.leftAnchor,
194+ constant: endConstr)
195+ } else {
196+ endLeadingConstraint = endPoint.leftAnchor.constraint(equalTo: scrollView.leftAnchor,
197+ constant:startConstr + Constants.minBookingLength)
198+ }
199+
200+ NSLayoutConstraint.activate([
201+
202+ startPoint.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0),
203+ endPoint.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0),
204+
205+ startPoint.widthAnchor.constraint(equalToConstant: Constants.pointWidth),
206+ endPoint.widthAnchor.constraint(equalToConstant: Constants.pointWidth),
207+
208+ startPoint.heightAnchor.constraint(equalToConstant: Constants.pointHeight),
209+ endPoint.heightAnchor.constraint(equalToConstant: Constants.pointHeight),
210+
211+ startLeadingConstraint,
212+ endLeadingConstraint,
213+
214+ fillInterval.leftAnchor.constraint(equalTo: startPoint.rightAnchor, constant: 0),
215+ fillInterval.rightAnchor.constraint(equalTo: endPoint.leftAnchor, constant: 0),
216+
217+ fillInterval.heightAnchor.constraint(equalToConstant: Constants.pointHeight),
218+ fillInterval.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0)
219+ ])
220+
221+ let scrollViewPanStartGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanStart(recognizer:)))
222+ startPoint.addGestureRecognizer(scrollViewPanStartGesture)
223+
224+ let scrollViewPanEndGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanEnd(recognizer:)))
225+ endPoint.addGestureRecognizer(scrollViewPanEndGesture)
226+ }
227+
228+ func setUpReservedIntervals(_ reservations: [ReservationPeriod], _ isAdmin: Bool) {
229+
230+ for reservation in reservations {
231+ let uiview = UIView(frame: CGRect(x: 0, y: 0, width: Constants.widthTimePoint * reservation.duration, height: Constants.heightIntervals))
232+ uiview.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 0.5)
233+
234+
235+ uiview.translatesAutoresizingMaskIntoConstraints = false
236+ scrollView.addSubview(uiview)
237+
238+ guard let startDate = startDate else { return }
239+
240+ let s = reservation.startTime.getMinutesPeriods(fromStart: startDate) * Constants.widthTimePoint
241+ let d = reservation.duration * Constants.widthTimePoint
242+
243+ let startTime = s < 0 ? 0 : s
244+
245+ let total = (isAdmin ? Constants.adminDuration : Constants.clientDuration) * Constants.widthTimePoint
246+ var duration = 0
247+ if s < 0 {
248+ duration = reservation.endTime.getMinutesPeriods(fromStart: startDate) * Constants.widthTimePoint
249+ } else {
250+ duration = (s + d) > total ? total - s : d
251+ }
252+
253+ NSLayoutConstraint.activate([
254+ uiview.bottomAnchor.constraint(equalToSystemSpacingBelow: scrollView.bottomAnchor, multiplier: 0),
255+ uiview.leftAnchor.constraint(equalTo: scrollView.leftAnchor,
256+ constant: CGFloat(Constants.widthTimePoint / 2 + startTime)),
257+ uiview.widthAnchor.constraint(equalToConstant: CGFloat(duration)),
258+ uiview.heightAnchor.constraint(equalToConstant: CGFloat(Constants.heightIntervals))
259+ ])
260+ }
261+ }
262+
263+ // MARK: - Pan
264+
265+ @objc func handlePanStart(recognizer:UIPanGestureRecognizer) {
266+
267+ let translation = recognizer.translation(in: self.intervalsStackView)
268+ let duration = abs(startLeadingConstraint.constant + translation.x - endLeadingConstraint.constant)
269+
270+ if let view = recognizer.view, duration >= Constants.minBookingLength {
271+ startLeadingConstraint.constant += translation.x
272+
273+ changeTime(startLeadingConstraint, .start)
274+
275+ view.setNeedsUpdateConstraints()
276+ }
277+
278+ recognizer.setTranslation(CGPoint.zero, in: self.intervalsStackView)
279+ }
280+
281+ @objc func handlePanEnd(recognizer:UIPanGestureRecognizer) {
282+
283+ let translation = recognizer.translation(in: self.intervalsStackView)
284+ let duration = abs(startLeadingConstraint.constant - (endLeadingConstraint.constant + translation.x))
285+
286+ if let view = recognizer.view, duration >= Constants.minBookingLength {
287+ endLeadingConstraint.constant += translation.x
288+
289+ changeTime(endLeadingConstraint, .end)
290+ view.setNeedsUpdateConstraints()
291+ }
292+
293+ recognizer.setTranslation(CGPoint.zero, in: self.intervalsStackView)
294+ }
295+
296+ func changeTime(_ constraint: NSLayoutConstraint, _ period: Period) {
297+ guard let startDate = startDate, let d = data else { return }
298+
299+ let offset = Int(constraint.constant) % Constants.widthTimePoint
300+
301+ if offset == 0 {
302+ let p = Int(constraint.constant) / Constants.widthTimePoint
303+ let time = startDate.addPeriods(p)
304+
305+ switch period {
306+ case .start:
307+ data = ReservationData(establishment: d.establishment,
308+ startTime: time,
309+ endTime: d.endTime,
310+ numberOfGuests: d.numberOfGuests,
311+ reservedTable: d.reservedTable)
312+ case .end:
313+ data = ReservationData(establishment: d.establishment,
314+ startTime: d.startTime,
315+ endTime: time,
316+ numberOfGuests: d.numberOfGuests,
317+ reservedTable: d.reservedTable)
318+ }
319+
320+ updateDateAndTime(withData: data)
321+ }
322+ }
323+}
324+
325+// MARK: - Nested types
326+
327+extension AdminReservationView {
328+ enum Constants {
329+ static let widthTimePoint = 11
330+
331+ static let adminDuration = 288
332+ static let clientDuration = 90
333+ // 12:00 = 12 * 6
334+ static let clientStartingPoint = 72
335+
336+ static let pointWidth: CGFloat = 19
337+ static let pointHeight: CGFloat = 85
338+
339+ static let minBookingLength: CGFloat = 132
340+
341+ static let heightIntervals = 85
342+ }
343+
344+ enum Period {
345+ case start
346+ case end
347+ }
80348}
81349
82350