Manos Chorianopoulos

MyRewardsProfileInfoTableViewCell redesign

......@@ -13,107 +13,144 @@ protocol MyRewardsProfileInfoTableViewCellDelegate: AnyObject {
@objc(MyRewardsProfileInfoTableViewCell)
public class MyRewardsProfileInfoTableViewCell: UITableViewCell {
@IBOutlet weak var tagView1: UIView!
@IBOutlet weak var tagLabel1: UILabel!
@IBOutlet weak var tagView2: UIView!
@IBOutlet weak var tagLabel2: UILabel!
@IBOutlet weak var profileImage: UIImageView!
// MARK: - IBOutlets
/// Bold "Rewards" title label (top-left)
@IBOutlet weak var titleLabel: UILabel!
/// Horizontally scrollable container for tag pills
@IBOutlet weak var tagsScrollView: UIScrollView!
/// Horizontal stack view inside the scroll view; tag pill views are added here dynamically
@IBOutlet weak var tagsStackView: UIStackView!
/// Settings / gear button (top-right)
@IBOutlet weak var profileButton: UIButton!
// MARK: - Delegate
weak var delegate: MyRewardsProfileInfoTableViewCellDelegate?
// MARK: - Properties
// MARK: - Private
private var profileModel: ProfileModel?
// MARK: - Lifecycle
public override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
profileImage.image = UIImage(named: "profile_pic_default", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
selectionStyle = .none
profileButton.addTarget(self, action: #selector(profileButtonTapped), for: .touchUpInside)
// Title
titleLabel.font = UIFont(name: "PingLCG-Bold", size: 26)
?? UIFont.boldSystemFont(ofSize: 26)
titleLabel.textColor = UIColor(rgb: 0x1D2023)
titleLabel.text = "Rewards"
tagView1.backgroundColor = UIColor(rgb: 0x09914E)
tagView1.layer.cornerRadius = 4.0
tagLabel1.font = UIFont(name: "PingLCG-Regular", size: 17)
tagLabel1.textColor = UIColor(rgb: 0xFFFFFF)
// Gear button: render image as-is (no tint) so the gray circle style is preserved
let gearImage = UIImage(named: "settings_circle", in: Bundle.frameworkResourceBundle, compatibleWith: nil)?
.withRenderingMode(.alwaysOriginal)
profileButton.setImage(gearImage, for: .normal)
profileButton.setTitle("", for: .normal)
profileButton.addTarget(self, action: #selector(profileButtonTapped), for: .touchUpInside)
tagView2.backgroundColor = UIColor(rgb: 0xFC9F25)
tagView2.layer.cornerRadius = 4.0
tagLabel2.font = UIFont(name: "PingLCG-Regular", size: 17)
tagLabel2.textColor = UIColor(rgb: 0xFFFFFF)
// Tags scroll view
tagsScrollView.showsHorizontalScrollIndicator = false
tagsScrollView.showsVerticalScrollIndicator = false
// Tags stack view
tagsStackView.axis = .horizontal
tagsStackView.spacing = 9
tagsStackView.alignment = .center
tagsStackView.distribution = .fill
}
public override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
// Configure the view for the selected state
public override func prepareForReuse() {
super.prepareForReuse()
clearTags()
}
// MARK: - Actions
@objc private func profileButtonTapped() {
delegate?.didTapProfileButton()
}
// MARK: - Configuration Methods
// MARK: - Configuration
public func configureCell(data: SectionModel?) {
guard let data = data,
let itemType = data.itemType,
itemType == .profile else {
data.sectionType == .myRewardsProfileInfo else {
configureDefaultState()
return
}
// Check if we have real profile data
if let metadata = data.metadata,
let profile = metadata["profile"] as? ProfileModel {
// Configure with real profile data
configureCell(profile: profile)
} else {
// Configure with default state (no profile data)
configureDefaultState()
}
}
public func configureCell(profile: ProfileModel) {
self.profileModel = profile
// TODO: Configure tag labels with profile data
// We need to determine what data should populate tagView1 and tagView2
// Possible options from ProfileModel:
// - _user_points (loyalty points)
// - _badge (user badge/tier)
// - _verified (verification status)
// - Custom business logic based on profile data
// For now, keep tags visible with current static styling
tagView1.isHidden = false
tagView2.isHidden = false
// Load profile image if available
if !profile._image_url.isEmpty {
loadProfileImage(from: profile._image_url)
} else {
profileImage.image = UIImage(named: "profile_pic_default", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
}
populateTags(segments: profile._user_segments)
}
private func configureDefaultState() {
// Default state: no profile data available
self.profileModel = nil
clearTags()
}
// Keep tags visible even in default state
tagView1.isHidden = false
tagView2.isHidden = false
// MARK: - Tag Helpers
profileImage.image = UIImage(named: "profile_pic_default", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
/// Removes all tag pill views from the stack view.
private func clearTags() {
tagsStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
}
private func loadProfileImage(from urlString: String) {
// For now, use default image - can be enhanced later with URL loading
profileImage.image = UIImage(named: "profile_pic_default", in: Bundle.frameworkResourceBundle, compatibleWith: nil)
/// Creates one pill view per segment string and adds them to the stack view.
private func populateTags(segments: [String]) {
clearTags()
for segment in segments where !segment.isEmpty {
let pill = makePillView(text: segment)
tagsStackView.addArrangedSubview(pill)
}
}
// TODO: Add dynamic profile picture and tags
/// Builds a rounded pill view with the given text.
private func makePillView(text: String) -> UIView {
let container = UIView()
container.backgroundColor = UIColor(rgb: 0xF1F2F4)
container.layer.cornerRadius = 13
container.clipsToBounds = true
let label = UILabel()
label.text = text
label.font = UIFont(name: "PingLCG-Regular", size: 12)
?? UIFont.systemFont(ofSize: 12)
label.textColor = UIColor(rgb: 0x00111B)
label.numberOfLines = 1
label.translatesAutoresizingMaskIntoConstraints = false
container.addSubview(label)
container.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
label.topAnchor.constraint(equalTo: container.topAnchor, constant: 6),
label.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: -6),
label.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 8),
label.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -8)
])
return container
}
}
......