Rev 17 | AutorÃa | Comparar con el anterior | Ultima modificación | Ver Log |
//
// CommentAndRatingView.swift
// twogetskills
//
// Created by Efrain Yanez Recanatini on 7/28/22.
//
import SwiftUI
import AudioToolbox
import Network
import Alamofire
import SwiftyJSON
import TTGSnackbar
struct CommentAndRatingView: View {
@EnvironmentObject private var networkMonitor : NetworkMonitor
@EnvironmentObject private var appNavigation : AppNavigation
@State private var capsuleTitle : String = ""
@ObservedObject var commentsViewModel : CommentAndRatingCommentsViewModel = CommentAndRatingCommentsViewModel()
@ObservedObject var capsuleViewModel : CommentAndRatingCapsuleViewModel = CommentAndRatingCapsuleViewModel()
@State var refreshListComment : Bool = true
@State var rating : Double = 5.0
@State var comment : String = "" {
didSet {
if comment.count > 128 {
comment = String(comment.prefix(128))
AudioServicesPlayAlertSoundWithCompletion(SystemSoundID(kSystemSoundID_Vibrate)) { return }
}
}
}
@State private var selectedType: CommentAndRatingPickerType = .introduction
@State private var presentAlert : Bool = false
@State private var titleAlert : String = ""
@State private var messageAlert : String = ""
@State private var showProgressView : Bool = false
private var appData = Environment(\.appData).wrappedValue
var body: some View {
VStack(spacing: 0)
{
HStack {
Button(action: {
withAnimation {
appNavigation.subpageActive = .mycapsules
}
}, label: {
Image(systemName: "chevron.backward")
.frame(width: 32, height: 32, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
.aspectRatio(contentMode: .fit)
.foregroundColor(networkMonitor.status == .disconnected ? Color("color_network_disconnected_foreground") : Color("color_app_bar_foreground"))
})
.padding(.leading, 16)
Text(networkMonitor.status == .disconnected ? Config.LANG_ERROR_NETWORK_MESSAGE_SHORT : capsuleTitle)
.font(Font.custom(Config.FONT_NAME_REGULAR, size: Config.FONT_SIZE_APP_BAR_HEAD1 ))
.foregroundColor(networkMonitor.status == .disconnected ? Color("color_network_disconnected_foreground") : Color("color_app_bar_foreground"))
.padding(.leading, 4)
Spacer()
}
.edgesIgnoringSafeArea(.top)
.frame(height: 50)
.background(networkMonitor.status == .disconnected ? Color("color_network_disconnected_background") : Color("color_app_bar_background"))
Divider().background(networkMonitor.status == .disconnected ? Color("color_network_disconnected_background") : Color("color_app_bar_background"))
CommentAndRatingImageView(capsuleModel: self.capsuleViewModel.capsule)
CommentAndRatingPickerView(capsuleModel: self.capsuleViewModel.capsule, selectedType: self.$selectedType).frame(height: 48)
switch self.selectedType
{
case .introduction :
CommentAndRatingIntroductionView(capsuleModel: self.capsuleViewModel.capsule).padding(5)
case .comments :
if self.commentsViewModel.comments.count == 0 {
CommentAndRatingCommentListEmptyView()
} else {
ScrollView {
LazyVStack {
//ForEach(0..<self.comments.count) { index in
ForEach(self.commentsViewModel.comments) { commentItem in
CommentAndRatingCommentListItemView(comment: commentItem) {
deleteComment(id: commentItem.id, linkDelete: commentItem.link_delete )
}
}
}
}
}
// CommentAndRatingCommentListView(comments: self.commentsViewModel.comments, showProgressView: self.$showProgressView).border(Color.blue, width: 1)
default :
CommentAndRatingPostCommentView(
capsuleModel: self.capsuleViewModel.capsule, comment: self.$comment, rating: self.$rating) {
sendPostComment()
}
}
Spacer()
Button(action: {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
appData.topicUuidActive = self.capsuleViewModel.capsule.topicUuid
appData.capsuleUuidActive = self.capsuleViewModel.capsule.uuid
appData.slideUuidActive = ""
appData.save()
appNavigation.subPageSource = .mycapsules
withAnimation {
appNavigation.subpageActive = .slides
}
}
}, label: {
Text(Config.LANG_COMMON_NEXT)
.font(Font.custom(Config.FONT_NAME_REGULAR, size: 16))
.frame(width: UIScreen.main.bounds.width - 32, height: 35)
.foregroundColor(Color("color_button_dark_foreground"))
.background(Color("color_button_dark_background"))
.border(Color( "color_button_dark_border"), width: Config.BUTTON_BORDER_SIZE)
.cornerRadius(Config.BUTTON_BORDER_RADIUS)
})
.padding(.top, 16)
.padding(.leading, 16)
.padding(.trailing, 16)
}
.background(Color("color_picker_background"))
.onAppear {
self.capsuleViewModel.fetch(capsuleUuid: appData.capsuleUuidActive, userUuid: appData.userUuid)
if self.capsuleViewModel.capsule.name.count > Constants.APP_BAR_TITLE_MAX_LENGTH {
self.capsuleTitle = String(Array(self.capsuleViewModel.capsule.name)[0...Constants.APP_BAR_TITLE_MAX_LENGTH]) + "..."
} else {
self.capsuleTitle = self.capsuleViewModel.capsule.name
}
self.reloadComments()
} .alert(isPresented: $presentAlert) {
Alert(
title: Text(self.titleAlert),
message: Text(self.messageAlert),
dismissButton: .default(Text(Config.LANG_COMMON_OK))
)
}
}
func reloadComments()
{
self.commentsViewModel.comments.removeAll()
if !self.capsuleViewModel.capsule.linkComments.isEmpty && networkMonitor.status == .connected {
let headerSecurity : HeaderSecurity = HeaderSecurity()
let headers: HTTPHeaders = [
.init(name: Constants.HTTP_HEADER_SECURITY_TOKEN, value: appData.deviceUuid),
.init(name: Constants.HTTP_HEADER_SECURITY_SECRET, value: headerSecurity.secret),
.init(name: Constants.HTTP_HEADER_SECURITY_CREATED, value: String(headerSecurity.created)),
.init(name: Constants.HTTP_HEADER_SECURITY_RAND, value: String(headerSecurity.rand)),
.accept(Constants.HTTP_HEADER_ACCEPT)
]
//print("URL Comments: \(self.capsuleViewModel.capsule.linkComments)")
commentsViewModel.comments.removeAll()
AF.request(self.capsuleViewModel.capsule.linkComments, method: .get, headers: headers).responseJSON{(response) in
self.showProgressView = false
switch response.result {
case .success:
let json = try? JSON(data: response.data!)
// print("json : \(json)")
if json?["success"] ?? "" != false {
if json?["data"]["capsule"] != nil {
let sTotalComments = json?["data"]["capsule"]["total_comments"].string ?? ""
let sTotalRating = json?["data"]["capsule"]["total_rating"].string ?? ""
capsuleViewModel.capsule.totalComments = Int(sTotalComments) ?? 0
capsuleViewModel.capsule.totalRating = Decimal(Double(sTotalRating) ?? 0)
let capsuleDao = CapsuleDao()
capsuleDao.update(capsule: capsuleViewModel.capsule)
}
if json?["data"]["comments"] != nil {
var newComment : CommentAndRatingComment
for jcomment in json!["data"]["comments"]
{
newComment = CommentAndRatingComment()
newComment.date = jcomment.1["date"].string ?? ""
newComment.rating = Decimal(Double(jcomment.1["rating"].string ?? "") ?? 0)
newComment.fullname = jcomment.1["fullname"].string ?? ""
newComment.comment = jcomment.1["comment"].string ?? ""
newComment.image = jcomment.1["image"].string ?? ""
newComment.link_delete = jcomment.1["link_delete"].string ?? ""
let sDate = jcomment.1["date"].string ?? ""
let formatterService = DateFormatter()
formatterService.dateFormat = Constants.FORMAT_DATETIME_SERVICE
if let date = formatterService.date(from: sDate) {
let dateFormatterUser = DateFormatter()
dateFormatterUser.dateFormat = Constants.FORMAT_DATE_TIME_24
newComment.date = dateFormatterUser.string(from: date)
}
commentsViewModel.comments.append(newComment)
}
}
} else {
let message = json?["data"].string ?? ""
if !message.isEmpty {
self.titleAlert = Config.LANG_ERROR_GENERIC_TITLE
self.messageAlert = message
self.presentAlert = true
}
}
return
case .failure :
self.titleAlert = Config.LANG_ERROR_COMMUNICATION_TITLE
self.messageAlert = Config.LANG_ERROR_COMMUNICATION_MESSAGE
self.presentAlert = true
return
}
}
}
}
func sendPostComment() {
let now = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = Constants.FORMAT_DATETIME_SERVICE
let dateOn = dateFormatter.string(from: now)
showProgressView = true
let parameters = [
Constants.POST_COMMENT_FIELD_COMMENT: comment,
Constants.POST_COMMENT_FIELD_RATING: "\(Int(rating))",
Constants.POST_COMMENT_FIELD_ADDED_ON: dateOn
]
let headerSecurity : HeaderSecurity = HeaderSecurity()
let headers: HTTPHeaders = [
.init(name: Constants.HTTP_HEADER_SECURITY_TOKEN, value: appData.deviceUuid),
.init(name: Constants.HTTP_HEADER_SECURITY_SECRET, value: headerSecurity.secret),
.init(name: Constants.HTTP_HEADER_SECURITY_CREATED, value: String(headerSecurity.created)),
.init(name: Constants.HTTP_HEADER_SECURITY_RAND, value: String(headerSecurity.rand)),
.accept(Constants.HTTP_HEADER_ACCEPT)
]
// print("URL POST COMMENT : \(capsuleViewModel.capsule.linkComments)")
self.showProgressView = true
AF.request(capsuleViewModel.capsule.linkCommentAdd, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).responseJSON{(response) in
self.showProgressView = false
switch response.result {
case .success:
let json = try? JSON(data: response.data!)
print("json : \(json)")
if json?["success"] ?? "" != false {
if json?["data"]["comment"] != nil {
let now = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = Constants.FORMAT_DATETIME_SERVICE
let dateOn = dateFormatter.string(from: now)
let link_delete = json?["data"]["comment"]["link_delete"].string ?? ""
var newComment = CommentAndRatingComment()
newComment.date = dateOn
newComment.image = appData.userImage
newComment.fullname = "\(appData.userFirstname) \(appData.userLastname)"
newComment.rating = Decimal(rating)
newComment.comment = comment
newComment.link_delete = link_delete
commentsViewModel.prepend(newComment: newComment)
self.comment = ""
self.rating = 5
self.selectedType = .comments
}
if json?["data"]["capsule"] != nil {
let sTotalComments = json?["data"]["capsule"]["total_comments"].string ?? ""
let sTotalRating = json?["data"]["capsule"]["total_rating"].string ?? ""
capsuleViewModel.capsule.totalComments = Int(sTotalComments) ?? 0
capsuleViewModel.capsule.totalRating = Decimal(Double(sTotalRating) ?? 0)
let capsuleDao = CapsuleDao()
capsuleDao.update(capsule: capsuleViewModel.capsule)
}
if json?["data"]["message"] != nil {
let snackbar = TTGSnackbar(message: json?["data"]["message"].string ?? "", duration: .long)
snackbar.show()
}
} else {
let message = json?["data"].string ?? ""
if !message.isEmpty {
self.titleAlert = Config.LANG_ERROR_GENERIC_TITLE
self.messageAlert = message
self.presentAlert = true
}
}
return
case .failure :
self.titleAlert = Config.LANG_ERROR_COMMUNICATION_TITLE
self.messageAlert = Config.LANG_ERROR_COMMUNICATION_MESSAGE
self.presentAlert = true
return
}
}
}
func deleteComment(id : String, linkDelete : String) {
showProgressView = true
let headerSecurity : HeaderSecurity = HeaderSecurity()
let headers: HTTPHeaders = [
.init(name: Constants.HTTP_HEADER_SECURITY_TOKEN, value: appData.deviceUuid),
.init(name: Constants.HTTP_HEADER_SECURITY_SECRET, value: headerSecurity.secret),
.init(name: Constants.HTTP_HEADER_SECURITY_CREATED, value: String(headerSecurity.created)),
.init(name: Constants.HTTP_HEADER_SECURITY_RAND, value: String(headerSecurity.rand)),
.accept(Constants.HTTP_HEADER_ACCEPT)
]
self.showProgressView = true
AF.request(linkDelete, method: .post, encoding: URLEncoding.default, headers: headers).responseJSON{(response) in
self.showProgressView = false
switch response.result {
case .success:
let json = try? JSON(data: response.data!)
// print("json : \(json)")
if json?["success"] ?? "" != false {
if json?["data"]["capsule"] != nil {
let sTotalComments = json?["data"]["capsule"]["total_comments"].string ?? ""
let sTotalRating = json?["data"]["capsule"]["total_rating"].string ?? ""
capsuleViewModel.capsule.totalComments = Int(sTotalComments) ?? 0
capsuleViewModel.capsule.totalRating = Decimal(Double(sTotalRating) ?? 0)
let capsuleDao = CapsuleDao()
capsuleDao.update(capsule: capsuleViewModel.capsule)
}
if json?["data"]["message"] != nil {
let snackbar = TTGSnackbar(message: json?["data"]["message"].string ?? "", duration: .long)
snackbar.show()
}
self.commentsViewModel.removeItem(id: id)
} else {
let message = json?["data"].string ?? ""
if !message.isEmpty {
self.titleAlert = Config.LANG_ERROR_GENERIC_TITLE
self.messageAlert = message
self.presentAlert = true
}
}
return
case .failure :
self.titleAlert = Config.LANG_ERROR_COMMUNICATION_TITLE
self.messageAlert = Config.LANG_ERROR_COMMUNICATION_MESSAGE
self.presentAlert = true
return
}
}
}
}
struct CommentAndRatingView_Previews: PreviewProvider {
static var previews: some View {
CommentAndRatingView()
}
}