Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat] #51 - Add Schedule View 구현 #54

Open
wants to merge 40 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
cc5574c
[Feat] #51 - Add event title 뷰 모델 구현
rafa-e1 Jan 18, 2025
2ba94ad
[Feat] #51 - Add event title 뷰 구현
rafa-e1 Jan 18, 2025
b3f54d3
[Feat] #51 - PickerButtonType 모델 구현
rafa-e1 Jan 18, 2025
9f2fc52
[Add] #51 - Add Presentable protocol to manage presentation state
rafa-e1 Jan 18, 2025
b874a82
[Feat] #51 - BasePickerViewModel 구현
rafa-e1 Jan 18, 2025
166cc28
[Feat] #51 - PickerButtonViewModel 구현
rafa-e1 Jan 18, 2025
c8bb81c
[Feat] #51 - PickerButton component 구현
rafa-e1 Jan 18, 2025
fe057d5
[Add] #51 - Add DateTimeSelection model for schedule feature
rafa-e1 Jan 18, 2025
e63da50
[Feat] #51 - DateTimeProtocols 구현
rafa-e1 Jan 18, 2025
977c0bc
[Feat] #51 - Set locale for date formatting in Date extension
rafa-e1 Jan 18, 2025
a617d46
[Feat] #51 - DateTimePickerViewModel 구현
rafa-e1 Jan 18, 2025
22a04ef
[Feat] #51 - DateTimeSectionType 모델 구현
rafa-e1 Jan 18, 2025
0ae5536
[Add] #51 - 화면 크기에 따라 동적으로 시트 높이를 조절하는 유틸리티 추가
rafa-e1 Jan 18, 2025
427b9e9
[Refactor] #51 - DateTimeSectionType 파일명 수정 및 섹션 추가
rafa-e1 Jan 18, 2025
c9542b1
[Remove] #51 - 미사용 파일 제거
rafa-e1 Jan 18, 2025
36b6342
[Feat] #51 - 반복 주기 종류 모델 구현
rafa-e1 Jan 18, 2025
62e62ee
[Feat] #51 - 태그 모델 구현
rafa-e1 Jan 18, 2025
983a98e
[Feat] #51 - 반복 종료 타입 추가
rafa-e1 Jan 18, 2025
c85b58f
[Feat] #51 - 로직 추가
rafa-e1 Jan 18, 2025
b02aba9
[Feat] #51 - 공통 바텀 시트 컴포넌트 구현
rafa-e1 Jan 18, 2025
858f06c
[Refactor] #51 - 공통 바텀 시트 컴포넌트 Sheet 폴더로 분리
rafa-e1 Jan 18, 2025
6d5f60c
[Refactor] #51 - 바텀 시트 종류마다 Detent 값을 동적으로 설정하도록 수정
rafa-e1 Jan 18, 2025
fb92eb1
[Feat] #51 - BaseSheetView 구현
rafa-e1 Jan 18, 2025
5052ce3
[Add] #51 - 임시 뷰 추가
rafa-e1 Jan 18, 2025
7959f50
[Feat] #51 - DateTimePickerSectionView 구현
rafa-e1 Jan 18, 2025
b8293ee
[Feat] #51 - All day 버튼 컴포넌트 구현
rafa-e1 Jan 18, 2025
0d622a2
[Feat] #51 - DateTimeView 구현
rafa-e1 Jan 18, 2025
ab2ef65
[Feat] #51 - Enter 버튼 추가 및 뷰 모델 연결
rafa-e1 Jan 18, 2025
559550e
[Feat] #51 - 반복 타입 선택을 위한 RepeatTypeListView 구현
rafa-e1 Jan 18, 2025
4fceaff
[Feat] #51 - RepeatPickerView 구현
rafa-e1 Jan 18, 2025
4ab2403
[Feat] #51 - 태그 개수에 따라 동적 시트 동작을 위한 뷰 확장 메서드 구현
rafa-e1 Jan 18, 2025
7a28ec9
[Refactor] #51 - 함수명 더 명확하게 수정 및 퀵 헬프 주석 추가
rafa-e1 Jan 18, 2025
97efe53
[Feat] #51 - 태그 바텀 시트 뷰 구현
rafa-e1 Jan 18, 2025
5c78980
[Feat] #51 - TagView 구현
rafa-e1 Jan 18, 2025
89f0611
[Refactor] #51 - 코드 줄 정렬 및 애니메이션 제거
rafa-e1 Jan 18, 2025
b5cdbe6
[Refactor] #51 - updateRepeatType 메서드에서 변경 여부를 확인해 불필요한 업데이트 방지
rafa-e1 Jan 18, 2025
0f83baf
[Refactor] #51 - DateTimePickerView와 RepeatPickerView의 상태 공유 버그 수정
rafa-e1 Jan 18, 2025
35555ab
[Feat] #51 - 이벤트 케이스에 AddScheduleView를 SegmentedMenuView에 추가
rafa-e1 Jan 18, 2025
76fd6be
[Remove] #51 - 미사용 코드 제거
rafa-e1 Jan 18, 2025
1d67717
[Merge] #51 - 디벨롭 충돌 해결
rafa-e1 Jan 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions Memento-iOS/Memento-iOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,47 @@
Source/Component/NeonAnimationView.swift,
Source/Data/MCalendarEventList.swift,
Source/Data/MEventDataSource.swift,
Source/Presentation/Add/AddSchedule/Model/DateTimeSelection.swift,
Source/Presentation/Add/AddSchedule/Model/RepeatType.swift,
Source/Presentation/Add/AddSchedule/View/AddEventTitleView.swift,
Source/Presentation/Add/AddSchedule/View/AddScheduleView.swift,
Source/Presentation/Add/AddSchedule/View/AllDayCheckBoxButton.swift,
Source/Presentation/Add/AddSchedule/View/DateTimePickerSectionView.swift,
Source/Presentation/Add/AddSchedule/View/DateTimePickerView.swift,
Source/Presentation/Add/AddSchedule/View/RepeatPickerView.swift,
Source/Presentation/Add/AddSchedule/View/RepeatTypeListView.swift,
Source/Presentation/Add/AddSchedule/ViewModel/AddEventTitleViewModel.swift,
Source/Presentation/Add/Common/PickerButton/Model/PickerButtonType.swift,
Source/Presentation/Add/Common/PickerButton/View/PickerButton.swift,
Source/Presentation/Add/Common/PickerButton/ViewModel/BasePickerViewModel.swift,
Source/Presentation/Add/Common/PickerButton/ViewModel/PickerButtonViewModel.swift,
Source/Presentation/Add/Common/Protocols/Presentable.swift,
Source/Presentation/Add/Common/SegmentedMenu/Model/SegmentedMenuType.swift,
Source/Presentation/Add/Common/SegmentedMenu/View/SegmentedMenuView.swift,
Source/Presentation/Add/Common/SegmentedMenu/ViewModel/SegmentedMenuViewModel.swift,
Source/Presentation/Add/Common/Sheet/BaseSheetView.swift,
Source/Presentation/Add/Common/Sheet/SheetContainer.swift,
Source/Presentation/Add/Common/Sheet/SheetHeaderView.swift,
Source/Presentation/Add/Common/Tag/Model/Tag.swift,
Source/Presentation/Add/Common/Tag/View/TagPickerSheetView.swift,
Source/Presentation/Add/Common/Tag/View/TagView.swift,
"Source/Presentation/Onboarding/View/Launch Screen.storyboard",
Source/Presentation/Onboarding/ViewModel/AuthViewModel.swift,
Source/Presentation/Onboarding/ViewModel/OnboardingViewModel.swift,
Source/Presentation/Today/Model/AllDayDataModel.swift,
Source/Presentation/Today/Model/ScheduleDataModel.swift,
Source/Presentation/Today/Model/TodayItemDataModel.swift,
Source/Presentation/Today/Model/TodoDataModel.swift,
Source/Presentation/Today/View/AllDayListView.swift,
Source/Presentation/Today/View/ArrowListCell.swift,
Source/Presentation/Today/View/EmptyView.swift,
Source/Presentation/Today/View/OffsetObservableScrollView.swift,
Source/Presentation/Today/View/ReusableView/WakeUpHeaderView.swift,
Source/Presentation/Today/View/ReusableView/WindDownFooterView.swift,
Source/Presentation/Today/View/WeeklyCalendarView.swift,
Source/Presentation/Today/ViewModel/WeeklyCalendarViewModel.swift,
Source/Presentation/ToDoList/View/ToDoListView.swift,
Source/Utils/DynamicPresentationDetent.swift,
);
target = 830F3C552D2A73BD00254FDE /* Memento-iOS */;
};
Expand Down
1 change: 1 addition & 0 deletions Memento-iOS/Memento-iOS/Source/Extension/Date+.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ extension Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
dateFormatter.timeZone = timeZone
dateFormatter.locale = Locale(identifier: "en_US")
return dateFormatter.string(from: self)
}

Expand Down
25 changes: 25 additions & 0 deletions Memento-iOS/Memento-iOS/Source/Extension/View+.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,29 @@ extension View {
UINavigationBar.appearance().largeTitleTextAttributes = [.foregroundColor: uiColor ]
return self
}

/// 태그 개수에 따라 시트의 동작과 크기를 동적으로 조정하는 메서드
///
/// - 태그 개수가 4개를 초과하면 시트는 스크롤이 가능하며 두 가지 높이(`0.33`, `0.99`)로 조정
/// - 태그 개수가 4개 이하일 경우, 고정된 높이(`0.33`)로만 표시되며 스크롤 비활성화
///
/// 사용 예시:
/// ```
/// ExampleView()
/// .applyDynamicSheetForTagCount()
/// ```
///
/// - Returns: 동적으로 동작하는 시트 반환
@ViewBuilder
func applyDynamicSheetForTagCount() -> some View {
if Tag.mockData.count > 4 {
self
.presentationContentInteraction(.scrolls)
.scrollIndicators(.hidden)
.presentationDetents([.fraction(0.33), .fraction(0.99)])
} else {
self
.presentationDetents([.fraction(0.33)])
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// AddScheduleSectionType.swift
// Memento-iOS
//
// Created by RAFA on 1/18/25.
//

import Foundation

enum AddScheduleSectionType {
case start, end, `repeat`, endRepeat
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// DateTimeSelection.swift
// Memento-iOS
//
// Created by RAFA on 1/18/25.
//

import Foundation

struct DateTimeSelection: Equatable {
var startsDate: Date
var endsDate: Date
var isAllDay: Bool
var selectedStartTime: Date
var selectedEndTime: Date
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// RepeatType.swift
// Memento-iOS
//
// Created by RAFA on 1/18/25.
//

import Foundation

enum RepeatType: CaseIterable {
case none, everyDay, everyWeek, everyMonth, everyYear

var title: String {
switch self {
case .none: return "None"
case .everyDay: return "Every Day"
case .everyWeek: return "Every Week"
case .everyMonth: return "Every Month"
case .everyYear: return "Every Year"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// AddEventTitleView.swift
// Memento-iOS
//
// Created by RAFA on 1/18/25.
//

import SwiftUI

import MDSKit

struct AddEventTitleView: View {

// MARK: - Properties

@ObservedObject var viewModel: AddEventTitleViewModel

// MARK: - Body

var body: some View {
VStack {
ZStack(alignment: .leading) {
if viewModel.isTitleEmpty {
Text("Add your event")
.foregroundColor(.gray07)
.applyFont(.body_b_18)
.padding(.vertical, 11)
}

TextField("", text: $viewModel.title)
.tint(Color.mementoLightGreen)
.foregroundColor(.grayWhite)
.applyFont(.body_b_18)
.padding(.vertical, 11)
}
.frame(height: 27)
.padding(.vertical, 11)

Divider()
.frame(height: 2)
.background(Color.gray08)
.padding(.bottom, 24)
}
}
}

// MARK: - Preview

#Preview {
ZStack {
Color.gray10
.ignoresSafeArea()

AddEventTitleView(viewModel: AddEventTitleViewModel())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// AddScheduleView.swift
// Memento-iOS
//
// Created by RAFA on 1/18/25.
//

import SwiftUI

import MDSKit

struct AddScheduleView: View {

// MARK: - Properties

@StateObject private var eventTitleViewModel = AddEventTitleViewModel()
@StateObject private var pickerViewModel = PickerButtonViewModel()

// MARK: - Body

var body: some View {
ZStack {
Color.gray10.ignoresSafeArea()

VStack {
AddEventTitleView(viewModel: eventTitleViewModel)
DateTimePickerView(viewModel: pickerViewModel)
RepeatPickerView(viewModel: pickerViewModel)
TagView()
Spacer()
enterButton
}
.padding(.horizontal)
}
}

// MARK: - UI Components

private var enterButton: some View {
HStack {
Spacer()
Button(action: {
}) {
Image(
eventTitleViewModel.isTitleEmpty
? .btn_enter_disabled
: .btn_enter_active
)
}
.frame(width: 42, height: 42)
.clipShape(Circle())
.disabled(eventTitleViewModel.isTitleEmpty)
.padding(.bottom, 20)
}
}
}

// MARK: - Preview

#Preview {
AddScheduleView()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// AllDayCheckBoxButton.swift
// Memento-iOS
//
// Created by RAFA on 1/18/25.
//

import SwiftUI

import MDSKit

struct AllDayCheckBoxButton: View {

// MARK: - Properties

@ObservedObject var viewModel: PickerButtonViewModel

// MARK: - Body

var body: some View {
HStack {
Spacer()
Button(action: toggleAllDay) {
HStack {
Image(
viewModel.isAllDay
? .btn_check_selected_square
: .btn_check_unselected_square)
Text("All-day")
.applyFont(.body_r_14)
.foregroundColor(Color.gray05)
}
}
.padding(.top, 12)
}
}

// MARK: - Helpers

private func toggleAllDay() {
viewModel.isAllDay.toggle()
}
}
Loading