From 890ad97f0a75a9c5023d8a79babfff4727f087f4 Mon Sep 17 00:00:00 2001 From: vasavk Date: Fri, 3 May 2024 18:29:32 +0530 Subject: [PATCH] Digital ACT-191 ONEAPP-7016 story: Displays indicator for day based on the indicators data --- VDS/Components/Calendar/Calendar.swift | 51 +++++--- .../CalendarDateCollectionViewCell.swift | 112 ++++++++++-------- 2 files changed, 95 insertions(+), 68 deletions(-) diff --git a/VDS/Components/Calendar/Calendar.swift b/VDS/Components/Calendar/Calendar.swift index faa1bed4..f9cb16cf 100644 --- a/VDS/Components/Calendar/Calendar.swift +++ b/VDS/Components/Calendar/Calendar.swift @@ -134,7 +134,6 @@ open class CalendarBase: View { open override func setup() { super.setup() isAccessibilityElement = false - addSubview(containerView) containerView .pinTop() @@ -147,19 +146,20 @@ open class CalendarBase: View { containerView.centerXAnchor.constraint(equalTo: centerXAnchor).activate() containerView.layer.borderWidth = VDSFormControls.borderWidth + let spacing = CGFloat(VDSLayout.space2X) //CGFloat(VDSFormControls.spaceInset) // + // Calendar View containerView.addSubview(collectionView) collectionView .pinTop(VDSLayout.space4X) .pinBottom(VDSLayout.space4X) - .pinLeading(VDSFormControls.spaceInset) - .pinTrailing(VDSFormControls.spaceInset) - let width = containerSize.width - (2 * VDSFormControls.spaceInset) + .pinLeading(spacing) + .pinTrailing(spacing) + let width = containerSize.width - (2 * spacing) collectionView.widthAnchor.constraint(equalToConstant: width).activate() let height = containerSize.height - (2 * VDSLayout.space4X) collectionView.heightAnchor.constraint(equalToConstant: height).activate() collectionView.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).activate() - collectionView.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).activate() } open override func updateView() { @@ -177,29 +177,36 @@ open class CalendarBase: View { super.reset() } + //-------------------------------------------------- + // MARK: - Private Methods + //-------------------------------------------------- func fetchDates(with date:Date) { days.removeAll() if let dates = selectedDate?.calendarDisplayDays { self.dates = dates - for day in dates { + for date in dates { // code to be executed - if day.monthInt != selectedDate?.monthInt { + if date.monthInt != selectedDate?.monthInt { days.append("") } else { - if #available(iOS 15.0, *) { - days.append(day.formatted(.dateTime.day())) - } else { - // Fallback on earlier versions - let dateFormatter: DateFormatter = DateFormatter() - dateFormatter.dateFormat = "d" - let dayStr: String = dateFormatter.string(from: day) - days.append(dayStr) - } + days.append(getDay(with: date)) } } -// print("days: \(days)") } } + + func getDay(with date:Date) -> String { + if #available(iOS 15.0, *) { + return date.formatted(.dateTime.day()) + } else { + // Fallback on earlier versions + let dateFormatter: DateFormatter = DateFormatter() + dateFormatter.dateFormat = "d" + let day: String = dateFormatter.string(from: date) + return day + } + } + } extension CalendarBase: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { @@ -212,7 +219,13 @@ extension CalendarBase: UICollectionViewDelegate, UICollectionViewDataSource, UI public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CalendarDateCollectionViewCell.identifier, for: indexPath) as? CalendarDateCollectionViewCell else { return UICollectionViewCell() } - cell.configure(with: indicators, text: days[indexPath.row]) + var indicatorCount = 0 + for x in (0...(self.indicators.count-1)) { + if (self.days[indexPath.row] == self.getDay(with: self.indicators[x].date)) { + indicatorCount += 1 + } + } + cell.configure(with: surface, indicators: indicators, text: days[indexPath.row], indicatorCount: indicatorCount) return cell } @@ -239,7 +252,7 @@ extension CalendarBase: UICollectionViewDelegate, UICollectionViewDataSource, UI public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let date = Calendar.current.date(byAdding: .day, value: 1, to: self.dates[indexPath.row])! - print("selected day: \(days[indexPath.row]), date: \(date)") +// print("selected day: \(days[indexPath.row]), date: \(date)") } public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { diff --git a/VDS/Components/Calendar/CalendarDateCollectionViewCell.swift b/VDS/Components/Calendar/CalendarDateCollectionViewCell.swift index f1c50f15..fd33611b 100644 --- a/VDS/Components/Calendar/CalendarDateCollectionViewCell.swift +++ b/VDS/Components/Calendar/CalendarDateCollectionViewCell.swift @@ -26,10 +26,11 @@ final class CalendarDateCollectionViewCell: UICollectionViewCell { fatalError("init(coder:) has not been implemented") } - func configure(with indicators: [CalendarBase.CalendarIndicatorModel], text: String) { + func configure(with surface: Surface, indicators: [CalendarBase.CalendarIndicatorModel], text: String, indicatorCount: Int) { addSubview(dateView) - dateView.dateIndicators = indicators dateView.numberLabel.text = text + dateView.indicatorCount = indicatorCount + dateView.dateIndicators = indicators } override func layoutSubviews() { @@ -58,8 +59,10 @@ private class DateView : View { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var indicatorCount: Int = 0 + open var dateIndicators: [CalendarBase.CalendarIndicatorModel] = [] { didSet { setNeedsUpdate() } } - + open var numberLabel = Label().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.textAlignment = .center @@ -70,39 +73,26 @@ private class DateView : View { // MARK: - Private Properties //-------------------------------------------------- internal var containerSize: CGSize { CGSize(width: 40, height: 40) } - + internal var containerView = View().with { $0.clipsToBounds = true } - + private lazy var stackView: UIStackView = { return UIStackView().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.axis = .horizontal $0.distribution = .fill $0.alignment = .center - $0.spacing = VDSLayout.space2X + $0.spacing = VDSLayout.space1X $0.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal) $0.setContentHuggingPriority(.defaultHigh, for: .horizontal) } }() -// private lazy var indicatorsView = View().with { -// $0.translatesAutoresizingMaskIntoConstraints = false -// $0.clipsToBounds = true -// $0.backgroundColor = .systemRed -// } - - private var legendIndicator: View = View().with { - $0.translatesAutoresizingMaskIntoConstraints = false - $0.backgroundColor = .clear - $0.layer.borderWidth = 1.0 - } - private lazy var shapeLayer = CAShapeLayer() - - private let indicatorColorConfiguration = SurfaceColorConfiguration(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark) + private let indicatorColorConfiguration = SurfaceColorConfiguration(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark) //-------------------------------------------------- // MARK: - Lifecycle @@ -114,7 +104,6 @@ private class DateView : View { open override func setup() { super.setup() isAccessibilityElement = false - addSubview(containerView) containerView .pinTop() @@ -124,24 +113,33 @@ private class DateView : View { .height(containerSize.height) .width(containerSize.width) containerView.centerXAnchor.constraint(equalTo: centerXAnchor).activate() - + // Number label containerView.addSubview(numberLabel) numberLabel.pinToSuperView() - + // Indicators - if dateIndicators.count > 0 { - containerView.addSubview(stackView) - let topPos = containerSize.height * 0.6 - stackView.pinTop(topPos).pinBottom().pinLeading().pinTrailing().pinCenterY() - stackView.centerXAnchor.constraint(equalTo: centerXAnchor).activate() - let width = (dateIndicators.count * 8) + (8 * (dateIndicators.count - 1)) - stackView.widthAnchor.constraint(equalToConstant: CGFloat(width)).activate() - } + containerView.addSubview(stackView) + let topPos = containerSize.height * 0.6 + stackView.pinTop(topPos).pinBottom().pinTopGreaterThanOrEqualTo().pinTrailingLessThanOrEqualTo().pinCenterY() + stackView.centerXAnchor.constraint(equalTo: centerXAnchor).activate() } open override func updateView() { super.updateView() + numberLabel.surface = surface + numberLabel.isEnabled = isEnabled + + stackView.arrangedSubviews.forEach { $0.removeFromSuperview() } + if indicatorCount > 0 { + let width = (indicatorCount * 8) + (Int(VDSLayout.space1X) * (indicatorCount - 1)) + stackView.widthAnchor.constraint(equalToConstant: CGFloat(width)).activate() + for x in (0...(dateIndicators.count-1)) { + if (self.numberLabel.text == self.getDay(with: dateIndicators[x].date)) { + addIndicator(with: VDSColor.elementsSecondaryOnlight, surface: surface, clearFullCircle: (x == 1), drawSemiCircle: (x == 2)) + } + } + } } override open func layoutSubviews() { @@ -150,30 +148,33 @@ private class DateView : View { open override func reset() { super.reset() + numberLabel.textStyle = .bodySmall } - //-------------------------------------------------- - // MARK: - Private Methods - //-------------------------------------------------- - func configure(with indicators: [CalendarBase.CalendarIndicatorModel]) { - //TO DO: handling indicators - in progress - //show indicator - legendIndicator.pinLeading().pinTrailing().width(8).height(8).pinCenterY() - stackView.addArrangedSubview(legendIndicator) - updateIndicator(with: VDSColor.elementsSecondaryOnlight, surface: surface, clearFullCircle: false, drawSemiCircle: false) - } - - func updateIndicator(with color: UIColor, surface: Surface, clearFullCircle: Bool, drawSemiCircle: Bool){ - legendIndicator.backgroundColor = drawSemiCircle ? .clear : (clearFullCircle ? .clear : color) - legendIndicator.layer.borderColor = indicatorColorConfiguration.getColor(surface).cgColor + //-------------------------------------------------- + // MARK: - Private Methods + //-------------------------------------------------- + func addIndicator(with color: UIColor, surface: Surface, clearFullCircle: Bool, drawSemiCircle: Bool) { + // add indicator + let indicatorView: View = View().with { + $0.translatesAutoresizingMaskIntoConstraints = false + $0.backgroundColor = .clear + $0.layer.borderWidth = 1.0 + } + indicatorView.pinLeading().pinTrailing().width(8).height(8).pinCenterY() + stackView.addArrangedSubview(indicatorView) + + // update indicator + indicatorView.backgroundColor = drawSemiCircle ? .clear : (clearFullCircle ? .clear : color) + indicatorView.layer.borderColor = indicatorColorConfiguration.getColor(surface).cgColor self.layoutIfNeeded() - legendIndicator.layer.cornerRadius = legendIndicator.frame.size.height / 2.0 + indicatorView.layer.cornerRadius = indicatorView.frame.size.height / 2.0 guard drawSemiCircle else { return } - let center = CGPoint(x: legendIndicator.frame.size.width/2, y: legendIndicator.frame.size.height/2) + let center = CGPoint(x: indicatorView.frame.size.width/2, y: indicatorView.frame.size.height/2) let path = UIBezierPath() path.move(to: center) path.addArc(withCenter: center, radius: center.x, startAngle: 2 * .pi, endAngle: .pi, clockwise: true) @@ -181,7 +182,20 @@ private class DateView : View { shapeLayer.path = path.cgPath shapeLayer.fillColor = color.cgColor - guard legendIndicator.layer.sublayers?.contains(shapeLayer) ?? true else { return } - legendIndicator.layer.addSublayer(shapeLayer) + guard indicatorView.layer.sublayers?.contains(shapeLayer) ?? true else { return } + indicatorView.layer.addSublayer(shapeLayer) } + + func getDay(with date:Date) -> String { + if #available(iOS 15.0, *) { + return date.formatted(.dateTime.day()) + } else { + // Fallback on earlier versions + let dateFormatter: DateFormatter = DateFormatter() + dateFormatter.dateFormat = "d" + let day: String = dateFormatter.string(from: date) + return day + } + } + }