mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-28 04:06:57 +02:00
Improve PollListItem to support ended polls
This commit is contained in:
@@ -45,10 +45,10 @@ enum MockPollHistoryScreenState: MockScreenState, CaseIterable {
|
||||
pollHistoryMode = .past
|
||||
case .activeEmpty:
|
||||
pollHistoryMode = .active
|
||||
pollService.pollListData = []
|
||||
pollService.activePollsData = []
|
||||
case .pastEmpty:
|
||||
pollHistoryMode = .past
|
||||
pollService.pollListData = []
|
||||
pollService.pastPollsData = []
|
||||
}
|
||||
|
||||
let viewModel = PollHistoryViewModel(mode: pollHistoryMode, pollService: pollService)
|
||||
|
||||
@@ -33,7 +33,7 @@ struct PollHistoryViewBindings {
|
||||
|
||||
struct PollHistoryViewState: BindableState {
|
||||
init(mode: PollHistoryMode) {
|
||||
self.bindings = .init(mode: mode)
|
||||
bindings = .init(mode: mode)
|
||||
}
|
||||
|
||||
var bindings: PollHistoryViewBindings
|
||||
@@ -42,4 +42,5 @@ struct PollHistoryViewState: BindableState {
|
||||
|
||||
enum PollHistoryViewAction {
|
||||
case viewAppeared
|
||||
case segmentDidChange
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ typealias PollHistoryViewModelType = StateStoreViewModel<PollHistoryViewState, P
|
||||
|
||||
final class PollHistoryViewModel: PollHistoryViewModelType, PollHistoryViewModelProtocol {
|
||||
private let pollService: PollHistoryServiceProtocol
|
||||
private var polls: [PollListData] = []
|
||||
private var fetchingTask: Task<Void, Error>? {
|
||||
didSet {
|
||||
oldValue?.cancel()
|
||||
@@ -39,6 +40,8 @@ final class PollHistoryViewModel: PollHistoryViewModelType, PollHistoryViewModel
|
||||
switch viewAction {
|
||||
case .viewAppeared:
|
||||
fetchingTask = fetchPolls()
|
||||
case .segmentDidChange:
|
||||
updatePolls()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,8 +56,22 @@ private extension PollHistoryViewModel {
|
||||
}
|
||||
|
||||
await MainActor.run {
|
||||
state.polls = polls
|
||||
self.polls = polls
|
||||
updatePolls()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updatePolls() {
|
||||
let renderedPolls: [PollListData]
|
||||
|
||||
switch context.mode {
|
||||
case .active:
|
||||
renderedPolls = polls.filter { $0.winningOption == nil }
|
||||
case .past:
|
||||
renderedPolls = polls.filter { $0.winningOption != nil }
|
||||
}
|
||||
|
||||
state.polls = renderedPolls
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,15 +15,30 @@
|
||||
//
|
||||
|
||||
final class MockPollHistoryService: PollHistoryServiceProtocol {
|
||||
var pollListData: [PollListData] = (1..<10)
|
||||
var activePollsData: [PollListData] = (1..<10)
|
||||
.map { index in
|
||||
PollListData(startDate: .init().addingTimeInterval(-CGFloat(index) * 3600), question: "Do you like the poll number \(index)?")
|
||||
}
|
||||
.sorted { poll1, poll2 in
|
||||
poll1.startDate > poll2.startDate
|
||||
PollListData(
|
||||
startDate: .init().addingTimeInterval(-CGFloat(index) * 3600),
|
||||
question: "Do you like the active poll number \(index)?",
|
||||
numberOfVotes: 30,
|
||||
winningOption: nil
|
||||
)
|
||||
}
|
||||
|
||||
var pastPollsData: [PollListData] = (1..<10)
|
||||
.map { index in
|
||||
PollListData(
|
||||
startDate: .init().addingTimeInterval(-CGFloat(index) * 3600),
|
||||
question: "Do you like the past poll number \(index)?",
|
||||
numberOfVotes: 30,
|
||||
winningOption: .init(id: "id", text: "Yes, of course!", count: 20, winner: true, selected: true)
|
||||
)
|
||||
}
|
||||
|
||||
func fetchHistory() async throws -> [PollListData] {
|
||||
pollListData
|
||||
(activePollsData + pastPollsData)
|
||||
.sorted { poll1, poll2 in
|
||||
poll1.startDate > poll2.startDate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,9 @@ struct PollHistory: View {
|
||||
.onAppear {
|
||||
viewModel.send(viewAction: .viewAppeared)
|
||||
}
|
||||
.onChange(of: viewModel.mode) { newValue in
|
||||
viewModel.send(viewAction: .segmentDidChange)
|
||||
}
|
||||
}
|
||||
|
||||
private var pollListView: some View {
|
||||
|
||||
@@ -19,6 +19,8 @@ import SwiftUI
|
||||
struct PollListData {
|
||||
let startDate: Date
|
||||
let question: String
|
||||
let numberOfVotes: UInt
|
||||
let winningOption: TimelinePollAnswerOption?
|
||||
}
|
||||
|
||||
struct PollListItem: View {
|
||||
@@ -36,18 +38,62 @@ struct PollListItem: View {
|
||||
Text(pollData.formattedDate)
|
||||
.foregroundColor(theme.colors.tertiaryContent)
|
||||
.font(theme.fonts.caption1)
|
||||
|
||||
|
||||
HStack(alignment: .firstTextBaseline, spacing: 8) {
|
||||
Image(uiImage: Asset.Images.pollHistory.image)
|
||||
.resizable()
|
||||
.frame(width: imageSize, height: imageSize)
|
||||
|
||||
|
||||
Text(pollData.question)
|
||||
.foregroundColor(theme.colors.primaryContent)
|
||||
.font(theme.fonts.body)
|
||||
.lineLimit(2)
|
||||
.accessibilityLabel("PollListItem.title")
|
||||
}
|
||||
|
||||
if pollData.winningOption != nil {
|
||||
optionView(winningOption: pollData.winningOption!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var clipShape: some Shape {
|
||||
RoundedRectangle(cornerRadius: 4.0)
|
||||
}
|
||||
|
||||
private func optionView(winningOption: TimelinePollAnswerOption) -> some View {
|
||||
VStack(alignment: .leading, spacing: 12.0) {
|
||||
HStack(alignment: .top, spacing: 8.0) {
|
||||
Text(pollData.winningOption!.text)
|
||||
.font(theme.fonts.body)
|
||||
.foregroundColor(theme.colors.primaryContent)
|
||||
|
||||
Spacer()
|
||||
|
||||
votesText(winningOption: winningOption)
|
||||
}
|
||||
|
||||
ProgressView(value: Double(winningOption.count),
|
||||
total: Double(pollData.numberOfVotes))
|
||||
.progressViewStyle(LinearProgressViewStyle())
|
||||
.scaleEffect(x: 1.0, y: 1.2, anchor: .center)
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.horizontal, 8.0)
|
||||
.padding(.top, 12.0)
|
||||
.padding(.bottom, 12.0)
|
||||
.clipShape(clipShape)
|
||||
.overlay(clipShape.stroke(theme.colors.accent, lineWidth: 1.0))
|
||||
.accentColor(theme.colors.accent)
|
||||
}
|
||||
|
||||
private func votesText(winningOption: TimelinePollAnswerOption) -> some View {
|
||||
Label {
|
||||
Text(winningOption.count == 1 ? VectorL10n.pollTimelineOneVote : VectorL10n.pollTimelineVotesCount(Int(winningOption.count)))
|
||||
.font(theme.fonts.footnote)
|
||||
.foregroundColor(theme.colors.accent)
|
||||
} icon: {
|
||||
Image(uiImage: Asset.Images.pollWinnerIcon.image)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,6 +118,24 @@ private extension DateFormatter {
|
||||
|
||||
struct PollListItem_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
PollListItem(pollData: .init(startDate: .init(), question: "Did you like this poll?"))
|
||||
Group {
|
||||
let pollData1 = PollListData(
|
||||
startDate: .init(),
|
||||
question: "Do you like polls?",
|
||||
numberOfVotes: 30,
|
||||
winningOption: .init(id: "id", text: "Yes, of course!", count: 18, winner: true, selected: true)
|
||||
)
|
||||
|
||||
PollListItem(pollData: pollData1)
|
||||
|
||||
let pollData2 = PollListData(
|
||||
startDate: .init(),
|
||||
question: "Do you like polls?",
|
||||
numberOfVotes: 30,
|
||||
winningOption: nil)
|
||||
|
||||
PollListItem(pollData: pollData2)
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user