feat: 计划页对齐 android 并新增提交页
This commit is contained in:
135
IosClientKit/Sources/FeaturePlan/PlanSubmitScreen.swift
Normal file
135
IosClientKit/Sources/FeaturePlan/PlanSubmitScreen.swift
Normal file
@@ -0,0 +1,135 @@
|
||||
import SwiftUI
|
||||
import CoreModel
|
||||
import CoreUI
|
||||
import DesignSystem
|
||||
|
||||
public struct PlanSubmitScreen: View {
|
||||
private let viewModel: PlanSubmitViewModel
|
||||
private let type: PlanType
|
||||
private let periodKey: String
|
||||
|
||||
@State private var content = ""
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
public init(viewModel: PlanSubmitViewModel, type: PlanType, periodKey: String) {
|
||||
self.viewModel = viewModel
|
||||
self.type = type
|
||||
self.periodKey = periodKey
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
contentView
|
||||
.navigationTitle("\(type.label) · \(periodKey)")
|
||||
.task { viewModel.load() }
|
||||
.onChange(of: viewModel.uiState) { _, newState in
|
||||
if case .success(let data) = newState, content.isEmpty, !data.content.isEmpty {
|
||||
content = data.content
|
||||
}
|
||||
}
|
||||
.onChange(of: viewModel.saved) { _, saved in
|
||||
if saved { dismiss() }
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var contentView: some View {
|
||||
switch viewModel.uiState {
|
||||
case .loading:
|
||||
LoadingView()
|
||||
case .error(let message):
|
||||
ErrorView(message: message) { viewModel.load() }
|
||||
case .success(let data):
|
||||
submitContent(data)
|
||||
}
|
||||
}
|
||||
|
||||
private func submitContent(_ data: PlanSubmitData) -> some View {
|
||||
ScrollView {
|
||||
VStack(spacing: DS.Spacing.md) {
|
||||
if !data.canSubmit, let message = data.message {
|
||||
Text(message)
|
||||
.font(.caption)
|
||||
.foregroundStyle(DS.Color.brandMuted)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
|
||||
VStack(alignment: .trailing, spacing: DS.Spacing.xs) {
|
||||
TextEditor(text: $content)
|
||||
.frame(minHeight: 120)
|
||||
.scrollContentBackground(.hidden)
|
||||
.padding(DS.Spacing.sm)
|
||||
.background(data.canSubmit ? DS.Color.brandPaper : DS.Color.brandChip)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
||||
.stroke(DS.Color.disabled, lineWidth: 1)
|
||||
)
|
||||
Text("\(content.count)/1000")
|
||||
.font(.caption)
|
||||
.foregroundStyle(DS.Color.faintText)
|
||||
}
|
||||
|
||||
HStack {
|
||||
Text("+ 添加图片(\(data.attachments.count)/4)")
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(data.canSubmit ? DS.Color.brandGold : DS.Color.disabled)
|
||||
Spacer()
|
||||
}
|
||||
.padding(DS.Spacing.sm)
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(Color.white)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
||||
.stroke(data.canSubmit ? DS.Color.brandGold : DS.Color.disabled, lineWidth: 1)
|
||||
)
|
||||
|
||||
Button(saveTitle(data)) {
|
||||
viewModel.save(content: content)
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
.disabled(!(data.canSubmit && !content.isEmpty && !viewModel.saving))
|
||||
|
||||
HistorySection(history: data.history)
|
||||
}
|
||||
.padding(DS.Spacing.md)
|
||||
}
|
||||
.background(DS.Color.brandPaper)
|
||||
}
|
||||
|
||||
private func saveTitle(_ data: PlanSubmitData) -> String {
|
||||
if !data.canSubmit { return "不可提交" }
|
||||
if data.checked { return "保存修改" }
|
||||
return "保存计划"
|
||||
}
|
||||
}
|
||||
|
||||
private struct HistorySection: View {
|
||||
let history: [MyPlanRecord]
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: DS.Spacing.sm) {
|
||||
Text("历史计划")
|
||||
.font(.subheadline.bold())
|
||||
.foregroundStyle(DS.Color.brandDark)
|
||||
if history.isEmpty {
|
||||
EmptyStateView(title: "暂无历史计划", systemImage: "doc")
|
||||
} else {
|
||||
ForEach(history.indices, id: \.self) { index in
|
||||
let item = history[index]
|
||||
VStack(alignment: .leading, spacing: DS.Spacing.xs) {
|
||||
Text("\(item.submittedTime) · \(item.status)")
|
||||
.font(.caption)
|
||||
.foregroundStyle(DS.Color.brandGold)
|
||||
Text(item.content)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(DS.Color.brandBrown)
|
||||
}
|
||||
.padding(DS.Spacing.md)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.background(Color.white)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user