Implemented the TaskListItem view in the app target.
This commit is contained in:
@@ -121,6 +121,39 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
"view.task-list-item.placeholder.completed" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Tap to complete or not your task"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"view.task-list-item.placeholder.note" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Add extra notes to your task (if needed)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"view.task-list-item.placeholder.title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Give a title to your task"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
"version" : "1.1"
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
import SwiftUI
|
||||
|
||||
extension TaskListView {
|
||||
|
||||
/// A view that displays a single editable todo task in a list.
|
||||
///
|
||||
/// This view provides a comprehensive interface for viewing and editing task information,
|
||||
/// including:
|
||||
/// - A completion toggle using a circular checkbox design
|
||||
/// - An editable title field with multi-line support
|
||||
/// - An optional note field that appears when the task has notes
|
||||
/// - A date picker for selecting the task's due date
|
||||
///
|
||||
/// The view automatically adjusts its appearance based on completion state, dimming
|
||||
/// completed tasks to provide visual feedback. All text fields support automatic
|
||||
/// capitalization and keyboard correction for improved user experience.
|
||||
struct Item: View {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// The todo task to display.
|
||||
@Bindable
|
||||
private var item: Todo
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Creates a new task list item view for the specified todo.
|
||||
///
|
||||
/// The item is wrapped in a `@Bindable` property wrapper to enable two-way
|
||||
/// data binding for editing task properties directly within the view.
|
||||
///
|
||||
/// - Parameter item: The todo task to display and edit.
|
||||
init(_ item: Todo) {
|
||||
_item = Bindable(item)
|
||||
}
|
||||
|
||||
// MARK: Body
|
||||
|
||||
/// The content and behavior of the view.
|
||||
///
|
||||
/// Renders an editable task list item with a completion toggle, title field,
|
||||
/// optional note field, and date picker. The view's foreground color automatically
|
||||
/// adjusts based on completion state, and changes animate smoothly.
|
||||
var body: some View {
|
||||
HStack(
|
||||
alignment: .top,
|
||||
spacing: 16
|
||||
) {
|
||||
Toggle(
|
||||
"view.task-list-item.placeholder.completed",
|
||||
isOn: isCompleted
|
||||
)
|
||||
.toggleStyle(.completion)
|
||||
|
||||
VStack(
|
||||
alignment: .leading,
|
||||
spacing: 8
|
||||
) {
|
||||
TextField(
|
||||
"view.task-list-item.placeholder.title",
|
||||
text: $item.title,
|
||||
axis: .vertical
|
||||
)
|
||||
.font(.headline)
|
||||
|
||||
if showNote {
|
||||
TextField(
|
||||
"view.task-list-item.placeholder.note",
|
||||
text: note,
|
||||
axis: .vertical
|
||||
)
|
||||
.font(.subheadline)
|
||||
}
|
||||
|
||||
DatePicker(selection: $item.due, displayedComponents: .date) {
|
||||
Image(systemName: "calendar")
|
||||
}
|
||||
.frame(width: 160)
|
||||
.disabled(isCompleted.wrappedValue)
|
||||
}
|
||||
.autocapitalization(.sentences)
|
||||
.autocorrectionDisabled(false)
|
||||
.foregroundStyle(foregroundColor)
|
||||
.keyboardType(.asciiCapable)
|
||||
}
|
||||
.animation(
|
||||
.easeInOut,
|
||||
value: item.completed
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private extension TaskListView.Item {
|
||||
|
||||
// MARK: Bindings
|
||||
|
||||
var isCompleted: Binding<Bool> {
|
||||
.init {
|
||||
item.completed != nil
|
||||
} set: {
|
||||
item.completed = $0 ? .now : nil
|
||||
}
|
||||
}
|
||||
|
||||
var note: Binding<String> {
|
||||
.init {
|
||||
item.note ?? ""
|
||||
} set: {
|
||||
item.note = $0.isEmpty ? nil : $0
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Computed
|
||||
|
||||
var foregroundColor: Color {
|
||||
item.completed == nil ? .primary : .secondary
|
||||
}
|
||||
|
||||
var showNote: Bool {
|
||||
guard let note = item.note else {
|
||||
return false
|
||||
}
|
||||
|
||||
return note.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
#Preview("Task list item") {
|
||||
@Previewable
|
||||
var todo: Todo = .init(
|
||||
title: "Complete project documentation",
|
||||
note: "Add detailed comments and README",
|
||||
due: .now,
|
||||
completed: nil
|
||||
)
|
||||
|
||||
List {
|
||||
TaskListView.Item(todo)
|
||||
}
|
||||
.listStyle(.grouped)
|
||||
}
|
||||
Reference in New Issue
Block a user