Files
David Furman 8631b5fbcc SyncUp tutorial fixes (#3139)
* Fixes for TestingSyncUpForm

* Typo, heirarchy -> hierarchy

* Typo: recursive -> recursively

* Typo: comes -> combines

* Further fixes for TestingSyncUpForm

* Typo: is -> to be

* Typo: add -> we added

* Typo: 3 -> 2

* Adding a note to avoid confusion

* Add more detail to step

* Remove stray whitespace causing a diff to incorrectly display

* Removed step documentation for unused code

* Typo: apart -> a part

* Fix App.Path Equatable conformance

* App -> AppReducer to avoid conflict with SwiftUI.App

* Fix code file link

* Typo: reducer -> reducers

* Add missing mock

* AppReducer -> AppFeature

* Standardize tutorial on `@Shared(.syncUps)`

* Fix mainactor placement

* Fix transcript param not compiling

* Add durationPerAttendee to be usable

* Add a minimal dismiss override to fit with the docs

* Fix commenting out of Tagged discussion

* Fix commenting out of TestingSyncUpDetail discussion

* Undo a whitespace change

* Partial revert of TestingSyncUpForm-02-code-0004.swift

* Undo unintentionally committed code

* Revert "Add missing mock"

This reverts commit 9672ecbd20.

* Revert "Fixes for TestingSyncUpForm"

This reverts commit 5bece14c2a.

* wip

---------

Co-authored-by: Stephen Celis <stephen@stephencelis.com>
2024-06-07 11:35:19 -07:00

99 lines
2.2 KiB
Swift

import ComposableArchitecture
import SwiftUI
@Reducer
struct SyncUpsList {
// ...
}
struct SyncUpsListView: View {
@Bindable var store: StoreOf<SyncUpsList>
var body: some View {
List {
ForEach(store.$syncUps.elements) { $syncUp in
NavigationLink(
state: AppFeature.Path.State.detail(SyncUpDetail.State(syncUp: $syncUp))
) {
CardView(syncUp: syncUp)
}
.listRowBackground(syncUp.theme.mainColor)
}
}
.sheet(item: $store.scope(state: \.addSyncUp, action: \.addSyncUp)) { addSyncUpStore in
NavigationStack {
SyncUpFormView(store: addSyncUpStore)
.navigationTitle("New sync-up")
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Discard") {
store.send(.discardButtonTapped)
}
}
ToolbarItem(placement: .confirmationAction) {
Button("Add") {
store.send(.confirmAddButtonTapped)
}
}
}
}
}
.toolbar {
Button {
store.send(.addSyncUpButtonTapped)
} label: {
Image(systemName: "plus")
}
}
.navigationTitle("Daily Sync-ups")
}
}
struct CardView: View {
let syncUp: SyncUp
var body: some View {
VStack(alignment: .leading) {
Text(syncUp.title)
.font(.headline)
Spacer()
HStack {
Label("\(syncUp.attendees.count)", systemImage: "person.3")
Spacer()
Label(syncUp.duration.formatted(.units()), systemImage: "clock")
.labelStyle(.trailingIcon)
}
.font(.caption)
}
.padding()
.foregroundColor(syncUp.theme.accentColor)
}
}
struct TrailingIconLabelStyle: LabelStyle {
func makeBody(configuration: Configuration) -> some View {
HStack {
configuration.title
configuration.icon
}
}
}
extension LabelStyle where Self == TrailingIconLabelStyle {
static var trailingIcon: Self { Self() }
}
#Preview {
NavigationStack {
SyncUpsListView(
store: Store(
initialState: SyncUpsList.State(
syncUps: [.mock]
)
) {
SyncUpsList()
}
)
}
}