Skip to content

Commit

Permalink
[MBL-971] Submit Report Project View (#1859)
Browse files Browse the repository at this point in the history
  • Loading branch information
scottkicks committed Oct 2, 2023
1 parent 8f40c4c commit 9bda2ba
Show file tree
Hide file tree
Showing 183 changed files with 405 additions and 50 deletions.
Expand Up @@ -383,9 +383,9 @@ public final class ProjectPageViewController: UIViewController, MessageBannerVie

self.viewModel.outputs.goToReportProject
.observeForControllerAction()
.observeValues { [weak self] flagged, projectUrl in
.observeValues { [weak self] flagged, projectID, projectUrl in
guard !flagged else { return }
self?.goToReportProject(projectUrl: projectUrl)
self?.goToReportProject(projectID: projectID, projectUrl: projectUrl)
}

self.viewModel.outputs.goToUpdates
Expand Down Expand Up @@ -659,9 +659,15 @@ public final class ProjectPageViewController: UIViewController, MessageBannerVie
}
}

private func goToReportProject(projectUrl: String) {
private func goToReportProject(projectID: String, projectUrl: String) {
if #available(iOS 15, *) {
let reportProjectInfoView = ReportProjectInfoView(projectUrl: projectUrl)
let reportProjectInfoView = ReportProjectInfoView(
projectID: projectID,
projectUrl: projectUrl,
onSuccessfulSubmit: { [weak self] in
self?.viewModel.inputs.viewDidLoad()
}
)
self.viewModel.inputs.showNavigationBar(false)
self.navigationController?
.pushViewController(UIHostingController(rootView: reportProjectInfoView), animated: true)
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Expand Up @@ -114,11 +114,13 @@ internal final class ProjectPageViewControllerDataSource: ValueCellDataSource {
inSection: Section.overviewSubpages.rawValue
)

self.set(
values: [project.flagging ?? false],
cellClass: ReportProjectCell.self,
inSection: Section.overviewReportProject.rawValue
)
if featureReportThisProjectEnabled(), AppEnvironment.current.currentUser != nil {
self.set(
values: [project.flagging ?? false],
cellClass: ReportProjectCell.self,
inSection: Section.overviewReportProject.rawValue
)
}
case .campaign:
self.set(
values: [HeaderValue.campaign.description],
Expand Down
Expand Up @@ -717,7 +717,7 @@ final class ProjectPageViewControllerDataSourceTests: XCTestCase {
refTag: nil,
isExpandedStates: nil
)
XCTAssertEqual(4, self.dataSource.numberOfSections(in: self.tableView))
XCTAssertEqual(3, self.dataSource.numberOfSections(in: self.tableView))

// overviewCreatorHeader
XCTAssertEqual(
Expand All @@ -737,11 +737,6 @@ final class ProjectPageViewControllerDataSourceTests: XCTestCase {
self.dataSource.tableView(self.tableView, numberOfRowsInSection: self.overviewSubpagesSection)
)

XCTAssertEqual(
1,
self.dataSource.tableView(self.tableView, numberOfRowsInSection: self.overviewReportProject)
)

XCTAssertEqual(
"ProjectPamphletMainCell",
self.dataSource.reusableId(item: 0, section: self.overviewSection)
Expand All @@ -750,11 +745,6 @@ final class ProjectPageViewControllerDataSourceTests: XCTestCase {
"ProjectPamphletSubpageCell",
self.dataSource.reusableId(item: 0, section: self.overviewSubpagesSection)
)

XCTAssertEqual(
"ReportProjectCell",
self.dataSource.reusableId(item: 0, section: self.overviewReportProject)
)
}
}

Expand Down
Expand Up @@ -23,13 +23,17 @@ internal final class ReportProjectCell: UITableViewCell, ValueCell {
// MARK: - Private Methods

private func setupTableViewCellStyle(projectFlagged: Bool) {
let isAccessibilityElement = projectFlagged ? false : true
let accessibilityLabel = projectFlagged ? Strings.Report_this_project_to() : ""
let accessibilityTraits = projectFlagged
? UIAccessibilityTraits.staticText
: UIAccessibilityTraits.button

_ = self
|> baseTableViewCellStyle()
|> ReportProjectCell.lens.accessibilityTraits .~ accessibilityTraits
|> ReportProjectCell.lens.isAccessibilityElement .~ isAccessibilityElement
|> ReportProjectCell.lens.accessibilityLabel .~ accessibilityLabel
}

private func setupReportProjectLabelView(projectFlagged: Bool) {
Expand Down
119 changes: 119 additions & 0 deletions Kickstarter-iOS/Features/ReportProject/ReportProjectFormView.swift
@@ -0,0 +1,119 @@
import KsApi
import Library
import SwiftUI

enum ReportFormFocusField {
case details
}

@available(iOS 15.0, *)
struct ReportProjectFormView: View {
let projectID: String
let projectURL: String
let projectFlaggingKind: GraphAPI.FlaggingKind
@Binding var popToRoot: Bool

@SwiftUI.Environment(\.dismiss) private var dismiss
@ObservedObject private var viewModel = ReportProjectFormViewModel()

@State private var retrievedEmail = ""
@State private var details: String = ""
@State private var saveEnabled: Bool = false
@State private var saveTriggered: Bool = false
@State private var showLoading: Bool = false
@State private var showBannerMessage = false
@State private var submitSuccess = false
@State private var bannerMessage: MessageBannerViewViewModel?
@FocusState private var focusField: ReportFormFocusField?

var body: some View {
GeometryReader { proxy in
Form {
if !retrievedEmail.isEmpty {
SwiftUI.Section(Strings.Email()) {
Text(retrievedEmail)
.font(Font(UIFont.ksr_body()))
.foregroundColor(Color(.ksr_support_400))
.disabled(true)
}
}

SwiftUI.Section(Strings.Project_url()) {
Text(projectURL)
.font(Font(UIFont.ksr_body()))
.foregroundColor(Color(.ksr_support_400))
.disabled(true)
}

SwiftUI.Section {
TextEditor(text: $details)
.frame(minHeight: 75)
.font(Font(UIFont.ksr_body()))
.focused($focusField, equals: .details)
.padding()
} header: {
Text(Strings.Tell_us_more_details())
.padding(.leading, 20)
}
.listRowInsets(EdgeInsets())
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
LoadingBarButtonItem(
saveEnabled: $saveEnabled,
saveTriggered: $saveTriggered,
showLoading: $showLoading,
titleText: Strings.Send()
)
}
}
.onAppear {
focusField = .details
viewModel.inputs.viewDidLoad()
viewModel.projectID.send(self.projectID)
viewModel.projectFlaggingKind.send(self.projectFlaggingKind)
}
.onChange(of: details) { detailsText in
viewModel.detailsText.send(detailsText)
}
.onChange(of: saveTriggered) { triggered in
focusField = nil
showLoading = triggered
viewModel.saveTriggered.send(triggered)
}
.onChange(of: bannerMessage) { newValue in
/// bannerMessage is set to nil when its done presenting. When it is done, and submit was successful, dismiss this view.
if newValue == nil, self.submitSuccess {
dismiss()
popToRoot = true
} else if newValue?.bannerBackgroundColor == Color(.ksr_alert) {
saveEnabled = true
}
}
.onReceive(viewModel.saveButtonEnabled) { newValue in
saveEnabled = newValue
}
.onReceive(viewModel.submitSuccess) { _ in
submitSuccess = true
}
.onReceive(viewModel.retrievedEmail) { email in
retrievedEmail = email
}
.onReceive(viewModel.bannerMessage) { newValue in
showLoading = false
saveEnabled = false
bannerMessage = newValue
}
.overlay(alignment: .bottom) {
MessageBannerView(viewModel: $bannerMessage)
.frame(
minWidth: proxy.size.width,
idealWidth: proxy.size.width,
maxHeight: proxy.size.height / 5,
alignment: .bottom
)
.animation(.easeInOut)
}
}
}
}
60 changes: 40 additions & 20 deletions Kickstarter-iOS/Features/ReportProject/ReportProjectInfoView.swift
Expand Up @@ -21,26 +21,42 @@ enum ReportProjectHyperLinkType: String, CaseIterable {

@available(iOS 15, *)
struct ReportProjectInfoView: View {
let projectID: String
let projectUrl: String
let onSuccessfulSubmit: () -> Void

@SwiftUI.Environment(\.dismiss) private var dismiss
@State private var selection: Set<ReportProjectInfoListItem> = []
@State private var popToRoot = false

var body: some View {
ScrollView {
ForEach(listItems) { item in
RowView(item: item, isExpanded: self.selection.contains(item))
.modifier(ListRowModifier())
.onTapGesture {
withAnimation {
self.selectDeselect(item)
}
RowView(
item: item,
isExpanded: self.selection.contains(item),
projectID: self.projectID,
projectUrl: self.projectUrl,
popToRoot: self.$popToRoot
)
.modifier(ListRowModifier())
.onTapGesture {
withAnimation {
self.selectDeselect(item)
}
.padding(5)
.animation(.linear(duration: 0.3))
}
.padding(5)
.animation(.linear(duration: 0.3))
}
}
.navigationTitle(Strings.Report_this_project())
.navigationBarTitleDisplayMode(.inline)
.onChange(of: popToRoot) { newValue in
if newValue == true {
dismiss()
onSuccessfulSubmit()
}
}
}

private func selectDeselect(_ item: ReportProjectInfoListItem) {
Expand Down Expand Up @@ -95,6 +111,10 @@ private struct BaseRowView: View {
struct RowView: View {
var item: ReportProjectInfoListItem
let isExpanded: Bool
let projectID: String
let projectUrl: String

@Binding var popToRoot: Bool

private let contentSpacing = 10.0
private let contentPadding = 12.0
Expand All @@ -107,9 +127,18 @@ struct RowView: View {
if isExpanded {
ForEach(item.subItems ?? []) { item in
VStack(alignment: .leading, spacing: contentSpacing) {
// TODO: Push Submission Form View In MBL-971(https://kickstarter.atlassian.net/browse/MBL-971)
NavigationLink(destination: { Text("submit report view") }, label: { BaseRowView(item: item) })
.buttonStyle(PlainButtonStyle())
NavigationLink(
destination: {
ReportProjectFormView(
projectID: self.projectID,
projectURL: self.projectUrl,
projectFlaggingKind: item.flaggingKind ?? GraphAPI.FlaggingKind.guidelinesViolation,
popToRoot: $popToRoot
)
},
label: { BaseRowView(item: item) }
)
.buttonStyle(PlainButtonStyle())
}
.padding(.vertical, 5)
.padding(.leading, self.contentPadding)
Expand Down Expand Up @@ -144,12 +173,3 @@ struct ListRowModifier: ViewModifier {
}.offset(x: 20)
}
}

// MARK: - Preview

@available(iOS 15, *)
struct ReportProjectInfoView_Previews: PreviewProvider {
static var previews: some View {
ReportProjectInfoView(projectUrl: "")
}
}

0 comments on commit 9bda2ba

Please sign in to comment.