feat(onboarding): actionable empty state on the main tab
첫 실행의 빈 모음 탭이 안내 문구뿐이던 것을 개선: - 도메인 개념 한 줄 소개 + '첫 행동 만들기'(행동 추가 시트 직행) - '예시 행동으로 시작해 보기' — 즉시 써 볼 수 있는 예시 세트 (꼬리표 생활·건강 + 독서/운동/물 마시기) 생성. 행동 추가와 같은 경로(LocalPrefs 배치 등록 + DataChange.commit)를 쓰며 언제든 수정·삭제 가능 깨끗한 설치 상태 스크린샷으로 확인. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
This commit is contained in:
parent
d7b602f08b
commit
f22aea0f95
@ -43,6 +43,7 @@ struct MainView: View {
|
||||
#endif
|
||||
}()
|
||||
@State private var draggingAction: Action?
|
||||
@State private var showingAddAction = false
|
||||
@State private var settingsEditingAction: Action?
|
||||
@State private var recordsAction: Action?
|
||||
@State private var deletingAction: Action?
|
||||
@ -94,6 +95,9 @@ struct MainView: View {
|
||||
.sheet(item: $settingsEditingAction) { action in
|
||||
ActionEditorView(action: action)
|
||||
}
|
||||
.sheet(isPresented: $showingAddAction) {
|
||||
ActionEditorView(action: nil)
|
||||
}
|
||||
.sheet(item: $recordsAction) { action in
|
||||
ActionRecordsSheet(action: action, startWithAdd: true)
|
||||
}
|
||||
@ -348,14 +352,60 @@ struct MainView: View {
|
||||
.foregroundStyle(.tertiary)
|
||||
Text("아직 등록된 행동이 없어요")
|
||||
.font(.headline)
|
||||
Text("행동 탭에서 추적할 행동을 추가해 보세요.")
|
||||
Text("습관이나 할 일을 '행동'으로 등록하면\n버튼 한 번으로 시간과 횟수를 기록할 수 있어요.")
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
.multilineTextAlignment(.center)
|
||||
VStack(spacing: 10) {
|
||||
Button {
|
||||
showingAddAction = true
|
||||
} label: {
|
||||
Label("첫 행동 만들기", systemImage: "plus")
|
||||
.padding(.horizontal, 10)
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
.buttonBorderShape(.capsule)
|
||||
.tint(AppTheme.green)
|
||||
Button {
|
||||
createStarterPack()
|
||||
} label: {
|
||||
Text("예시 행동으로 시작해 보기")
|
||||
.font(.subheadline)
|
||||
}
|
||||
.tint(AppTheme.green)
|
||||
}
|
||||
.padding(.top, 8)
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 60)
|
||||
}
|
||||
|
||||
/// 빈 상태에서 바로 써 볼 수 있는 예시 세트 (실사용 가능한 구성 — 언제든 수정·삭제 가능)
|
||||
private func createStarterPack() {
|
||||
guard actions.isEmpty else { return }
|
||||
let life = Tag(name: String(localized: "생활"), colorHex: "#2F6B4F")
|
||||
let health = Tag(name: String(localized: "건강"), colorHex: "#4A7A9D")
|
||||
life.sortOrder = 0
|
||||
health.sortOrder = 1
|
||||
context.insert(life)
|
||||
context.insert(health)
|
||||
|
||||
let reading = Action(name: String(localized: "독서"), symbolName: "book.fill",
|
||||
trackingType: .time, sortOrder: 0)
|
||||
reading.tags = [life]
|
||||
let workout = Action(name: String(localized: "운동"), symbolName: "figure.run",
|
||||
trackingType: .time, sortOrder: 1)
|
||||
workout.tags = [health]
|
||||
let water = Action(name: String(localized: "물 마시기"), symbolName: "drop.fill",
|
||||
trackingType: .count, sortOrder: 2)
|
||||
water.tags = [health]
|
||||
for action in [reading, workout, water] {
|
||||
context.insert(action)
|
||||
LocalPrefs.appendActionToOrder(action.uuid)
|
||||
}
|
||||
DataChange.commit(context: context)
|
||||
}
|
||||
|
||||
// MARK: 동작
|
||||
|
||||
private func handleTap(_ action: Action) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user