|
|
@@ -0,0 +1,269 @@
|
|
|
+//
|
|
|
+// LNIMChatOrderMessageCell.swift
|
|
|
+// Lanu
|
|
|
+//
|
|
|
+// Created by OneeChan on 2025/12/26.
|
|
|
+//
|
|
|
+
|
|
|
+import Foundation
|
|
|
+import UIKit
|
|
|
+import SnapKit
|
|
|
+
|
|
|
+
|
|
|
+class LNIMChatOrderMessageCell: UITableViewCell {
|
|
|
+ private let statusIc = UIImageView()
|
|
|
+ private let statusLabel = UILabel()
|
|
|
+
|
|
|
+ private let tipsLabel = UILabel()
|
|
|
+
|
|
|
+ private let gameIc = UIImageView()
|
|
|
+ private let billInfoLabel = UILabel()
|
|
|
+
|
|
|
+ private let menuButton = UIButton()
|
|
|
+
|
|
|
+ private var curItem: LNIMMessageData?
|
|
|
+
|
|
|
+ override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
|
|
+ super.init(style: style, reuseIdentifier: reuseIdentifier)
|
|
|
+
|
|
|
+ setupViews()
|
|
|
+ }
|
|
|
+
|
|
|
+ func update(_ data: LNIMMessageData, viewModel: LNIMChatViewModel) {
|
|
|
+ guard let order: LNIMOrderMessage = data.decodeCustomMessage() else { return }
|
|
|
+
|
|
|
+ let isCreator = !data.imMessage.isSelf
|
|
|
+
|
|
|
+ tipsLabel.isHidden = false
|
|
|
+ menuButton.isHidden = true
|
|
|
+
|
|
|
+ gameIc.sd_setImage(with: URL(string: order.categoryIcon))
|
|
|
+ billInfoLabel.text = "\(order.bizCategoryName)x\(order.purchaseQty)\(order.unit)"
|
|
|
+
|
|
|
+ switch order.status {
|
|
|
+ case .created, .waitingForAccept:
|
|
|
+ if isCreator {
|
|
|
+ statusIc.image = .init(named: "ic_im_chat_order_success")
|
|
|
+ statusLabel.text = .init(key: "Order Success")
|
|
|
+ tipsLabel.text = .init(key: "Waiting for the playmate to accept the order. If the playmate does not reply within 1 hour")
|
|
|
+ } else {
|
|
|
+ statusIc.image = .init(named: "ic_im_chat_order_pending")
|
|
|
+ statusLabel.text = .init(key: "Pending Order")
|
|
|
+ tipsLabel.text = .init(key: "Note: %@", order.customerRemark)
|
|
|
+ }
|
|
|
+ case .completed:
|
|
|
+ statusIc.image = .init(named: "ic_im_chat_order_complete")
|
|
|
+ statusLabel.text = .init(key: "Order Complete")
|
|
|
+
|
|
|
+ if isCreator {
|
|
|
+ tipsLabel.text = .init(key: "The playmate has accepted the order. Waiting for the playmate to start serving")
|
|
|
+ } else {
|
|
|
+ tipsLabel.text = .init(key: "The service has been completed and the payment has been sent to your wallet!")
|
|
|
+ }
|
|
|
+ case .refunded:
|
|
|
+ if isCreator {
|
|
|
+ statusIc.image = .init(named: "ic_im_chat_order_success")
|
|
|
+ statusLabel.text = .init(key: "")
|
|
|
+ } else {
|
|
|
+ statusIc.image = .init(named: "ic_im_chat_order_pending")
|
|
|
+ statusLabel.text = .init(key: "")
|
|
|
+ }
|
|
|
+ case .accepted:
|
|
|
+ statusIc.image = .init(named: "ic_im_chat_order_accepted")
|
|
|
+ statusLabel.text = .init(key: "Order Accepted")
|
|
|
+
|
|
|
+ if isCreator {
|
|
|
+ tipsLabel.text = .init(key: "The playmate has accepted the order. Waiting for the playmate to start serving")
|
|
|
+ } else {
|
|
|
+ tipsLabel.isHidden = true
|
|
|
+ menuButton.isHidden = false
|
|
|
+ menuButton.setTitle(.init(key: "Start Service"), for: .normal)
|
|
|
+ }
|
|
|
+ case .rejected:
|
|
|
+ statusIc.image = .init(named: "ic_im_chat_order_cancel")
|
|
|
+ statusLabel.text = .init(key: "Order Rejected")
|
|
|
+
|
|
|
+ if isCreator {
|
|
|
+ tipsLabel.text = .init(key: "The playmate has declined the order. Please place your order here or choose another playmate")
|
|
|
+ } else {
|
|
|
+ tipsLabel.text = .init(key: "You have terminated the order!")
|
|
|
+ }
|
|
|
+ case .servicing:
|
|
|
+ statusIc.image = .init(named: "ic_im_chat_order_processing")
|
|
|
+ statusLabel.text = .init(key: "In Order Service")
|
|
|
+
|
|
|
+ if isCreator {
|
|
|
+ tipsLabel.text = "The playmate has accepted the order. Waiting for the playmate to start serving"
|
|
|
+ } else {
|
|
|
+ tipsLabel.text = "The playmate has accepted the order. Waiting for the playmate to start serving"
|
|
|
+ menuButton.isHidden = false
|
|
|
+ menuButton.setTitle(.init(key: "Service Completion"), for: .normal)
|
|
|
+ }
|
|
|
+ case .serviceDone:
|
|
|
+ statusIc.image = .init(named: "ic_im_chat_order_processing")
|
|
|
+ statusLabel.text = .init(key: "In Order Service")
|
|
|
+
|
|
|
+ if isCreator {
|
|
|
+ tipsLabel.text = "The playmate has accepted the order. Waiting for the playmate to start serving"
|
|
|
+ menuButton.isHidden = false
|
|
|
+ menuButton.setTitle(.init(key: "Service Completion"), for: .normal)
|
|
|
+ } else {
|
|
|
+ tipsLabel.text = "The playmate has accepted the order. Waiting for the playmate to start serving"
|
|
|
+ }
|
|
|
+ case .cancelled:
|
|
|
+ statusIc.image = .init(named: "ic_im_chat_order_success")
|
|
|
+ statusLabel.text = .init(key: "Order Canceled")
|
|
|
+
|
|
|
+ if isCreator {
|
|
|
+ tipsLabel.text = .init(key: "The playmate has declined the order. Please place your order here or choose another playmate")
|
|
|
+ } else {
|
|
|
+ tipsLabel.text = .init(key: "You did not respond to the order within the countdown, and the order will be automatically cancelled !")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ required init?(coder: NSCoder) {
|
|
|
+ fatalError("init(coder:) has not been implemented")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+extension LNIMChatOrderMessageCell {
|
|
|
+ private func setupViews() {
|
|
|
+ backgroundColor = .clear
|
|
|
+
|
|
|
+ let container = UIView()
|
|
|
+ container.backgroundColor = .fill
|
|
|
+ container.layer.cornerRadius = 12
|
|
|
+ contentView.addSubview(container)
|
|
|
+ container.snp.makeConstraints { make in
|
|
|
+ make.directionalHorizontalEdges.equalToSuperview().inset(16)
|
|
|
+ make.verticalEdges.equalToSuperview()
|
|
|
+ }
|
|
|
+
|
|
|
+ let mainStackView = UIStackView()
|
|
|
+ mainStackView.axis = .vertical
|
|
|
+ mainStackView.spacing = 12
|
|
|
+ container.addSubview(mainStackView)
|
|
|
+ mainStackView.snp.makeConstraints { make in
|
|
|
+ make.directionalHorizontalEdges.equalToSuperview().inset(12)
|
|
|
+ make.verticalEdges.equalToSuperview().inset(12)
|
|
|
+ }
|
|
|
+
|
|
|
+ let infoStackView = UIStackView()
|
|
|
+ infoStackView.axis = .vertical
|
|
|
+ infoStackView.spacing = 6
|
|
|
+ infoStackView.onTap { [weak self] in
|
|
|
+ guard let self else { return }
|
|
|
+ guard let order: LNIMOrderMessage = curItem?.decodeCustomMessage() else { return }
|
|
|
+ pushToOrderDetail(orderId: order.orderId)
|
|
|
+ }
|
|
|
+ mainStackView.addArrangedSubview(infoStackView)
|
|
|
+
|
|
|
+ infoStackView.addArrangedSubview(buildStatusView())
|
|
|
+ infoStackView.addArrangedSubview(buildTipsView())
|
|
|
+ infoStackView.addArrangedSubview(buildLine())
|
|
|
+ infoStackView.addArrangedSubview(buildBillInfoView())
|
|
|
+
|
|
|
+ mainStackView.addArrangedSubview(buildMenu())
|
|
|
+ }
|
|
|
+
|
|
|
+ private func buildStatusView() -> UIView {
|
|
|
+ let container = UIView()
|
|
|
+ container.snp.makeConstraints { make in
|
|
|
+ make.height.equalTo(24)
|
|
|
+ }
|
|
|
+
|
|
|
+ container.addSubview(statusIc)
|
|
|
+ statusIc.snp.makeConstraints { make in
|
|
|
+ make.centerY.equalToSuperview()
|
|
|
+ make.leading.equalToSuperview()
|
|
|
+ make.width.height.equalTo(24)
|
|
|
+ }
|
|
|
+
|
|
|
+ statusLabel.font = .heading_h4
|
|
|
+ statusLabel.textColor = .text_5
|
|
|
+ container.addSubview(statusLabel)
|
|
|
+ statusLabel.snp.makeConstraints { make in
|
|
|
+ make.leading.equalTo(statusIc.snp.trailing).offset(6)
|
|
|
+ make.centerY.equalToSuperview()
|
|
|
+ }
|
|
|
+
|
|
|
+ let arrow = UIImageView.arrowImageView(size: 16)
|
|
|
+ arrow.tintColor = .text_4
|
|
|
+ container.addSubview(arrow)
|
|
|
+ arrow.snp.makeConstraints { make in
|
|
|
+ make.centerY.equalToSuperview()
|
|
|
+ make.trailing.equalToSuperview()
|
|
|
+ }
|
|
|
+
|
|
|
+ return container
|
|
|
+ }
|
|
|
+
|
|
|
+ private func buildTipsView() -> UIView {
|
|
|
+ tipsLabel.font = .body_xs
|
|
|
+ tipsLabel.textColor = .text_3
|
|
|
+ tipsLabel.numberOfLines = 0
|
|
|
+
|
|
|
+ return tipsLabel
|
|
|
+ }
|
|
|
+
|
|
|
+ private func buildLine() -> UIView {
|
|
|
+ let line = UIView()
|
|
|
+ line.backgroundColor = .fill_2
|
|
|
+ line.snp.makeConstraints { make in
|
|
|
+ make.height.equalTo(0.5)
|
|
|
+ }
|
|
|
+
|
|
|
+ return line
|
|
|
+ }
|
|
|
+
|
|
|
+ private func buildBillInfoView() -> UIView {
|
|
|
+ let container = UIView()
|
|
|
+ container.snp.makeConstraints { make in
|
|
|
+ make.height.equalTo(20)
|
|
|
+ }
|
|
|
+
|
|
|
+ let backgroundIc = UIImageView()
|
|
|
+ backgroundIc.layer.cornerRadius = 10
|
|
|
+ backgroundIc.image = .primary_7
|
|
|
+ backgroundIc.clipsToBounds = true
|
|
|
+ container.addSubview(backgroundIc)
|
|
|
+ backgroundIc.snp.makeConstraints { make in
|
|
|
+ make.leading.equalToSuperview()
|
|
|
+ make.centerY.equalToSuperview()
|
|
|
+ make.width.height.equalTo(20)
|
|
|
+ }
|
|
|
+
|
|
|
+ gameIc.backgroundColor = .fill
|
|
|
+ gameIc.layer.cornerRadius = 9
|
|
|
+ backgroundIc.addSubview(gameIc)
|
|
|
+ gameIc.snp.makeConstraints { make in
|
|
|
+ make.center.equalToSuperview()
|
|
|
+ make.width.height.equalTo(18)
|
|
|
+ }
|
|
|
+
|
|
|
+ billInfoLabel.font = .body_s
|
|
|
+ billInfoLabel.textColor = .text_4
|
|
|
+ container.addSubview(billInfoLabel)
|
|
|
+ billInfoLabel.snp.makeConstraints { make in
|
|
|
+ make.leading.equalTo(backgroundIc.snp.trailing).offset(6)
|
|
|
+ make.centerY.equalToSuperview()
|
|
|
+ }
|
|
|
+
|
|
|
+ return container
|
|
|
+ }
|
|
|
+
|
|
|
+ private func buildMenu() -> UIView {
|
|
|
+ menuButton.layer.cornerRadius = 20
|
|
|
+ menuButton.setBackgroundImage(.primary_8, for: .normal)
|
|
|
+ menuButton.clipsToBounds = true
|
|
|
+ menuButton.setTitleColor(.text_1, for: .normal)
|
|
|
+ menuButton.titleLabel?.font = .heading_h3
|
|
|
+ menuButton.snp.makeConstraints { make in
|
|
|
+ make.height.equalTo(40)
|
|
|
+ }
|
|
|
+
|
|
|
+ return menuButton
|
|
|
+ }
|
|
|
+}
|
|
|
+
|