// // CalendarDateCollectionViewCell.swift // VDS // // Created by Kanamarlapudi, Vasavi on 24/04/24. // import Foundation import UIKit import VDSTokens /// Calendar collection view cell final class CalendarDateCollectionViewCell: UICollectionViewCell { ///Identifier for the Calendar Date Cell static let identifier: String = String(describing: CalendarDateCollectionViewCell.self) private lazy var dateView = DateView() override init(frame: CGRect) { super.init(frame: frame) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func configure(with indicators: [CalendarBase.CalendarIndicatorModel], text: String) { addSubview(dateView) dateView.dateIndicators = indicators dateView.numberLabel.text = text } override func layoutSubviews() { super.layoutSubviews() } } /// Date view to show Date number and indicator if applies private class DateView : View { //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- required public init() { super.init(frame: .zero) } public override init(frame: CGRect) { super.init(frame: .zero) } public required init?(coder: NSCoder) { super.init(coder: coder) } //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- open var dateIndicators: [CalendarBase.CalendarIndicatorModel] = [] { didSet { setNeedsUpdate() } } open var numberLabel = Label().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.textAlignment = .center $0.textStyle = .bodySmall //isCurrentDate: .boldBodySmall } //-------------------------------------------------- // 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.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) //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- open override func initialSetup() { super.initialSetup() } open override func setup() { super.setup() isAccessibilityElement = false addSubview(containerView) containerView .pinTop() .pinBottom() .pinLeadingGreaterThanOrEqualTo() .pinTrailingLessThanOrEqualTo() .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() } } open override func updateView() { super.updateView() } override open func layoutSubviews() { super.layoutSubviews() } open override func reset() { super.reset() } //-------------------------------------------------- // 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 self.layoutIfNeeded() legendIndicator.layer.cornerRadius = legendIndicator.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 path = UIBezierPath() path.move(to: center) path.addArc(withCenter: center, radius: center.x, startAngle: 2 * .pi, endAngle: .pi, clockwise: true) path.close() shapeLayer.path = path.cgPath shapeLayer.fillColor = color.cgColor guard legendIndicator.layer.sublayers?.contains(shapeLayer) ?? true else { return } legendIndicator.layer.addSublayer(shapeLayer) } }