diff --git a/Gongbaek_iOS/Gongbaek_iOS.xcodeproj/project.pbxproj b/Gongbaek_iOS/Gongbaek_iOS.xcodeproj/project.pbxproj index 5381876a..b01b4e50 100644 --- a/Gongbaek_iOS/Gongbaek_iOS.xcodeproj/project.pbxproj +++ b/Gongbaek_iOS/Gongbaek_iOS.xcodeproj/project.pbxproj @@ -22,7 +22,6 @@ membershipExceptions = ( Global/Component/BottomSheet/.gitkeep, Network/Service/DTO/Filling/.gitkeep, - Presentation/Home/ViewModel/.gitkeep, ); target = 954A490A2D2DA7AE00FD6964 /* Gongbaek_iOS */; }; @@ -286,6 +285,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"Gongbaek_iOS/Preview Content\""; + DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "Gongbaek-iOS-Info.plist"; @@ -315,6 +315,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"Gongbaek_iOS/Preview Content\""; + DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "Gongbaek-iOS-Info.plist"; diff --git a/Gongbaek_iOS/Gongbaek_iOS/Application/Gongbaek_iOSApp.swift b/Gongbaek_iOS/Gongbaek_iOS/Application/Gongbaek_iOSApp.swift index a55fb3af..85a80ab9 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Application/Gongbaek_iOSApp.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Application/Gongbaek_iOSApp.swift @@ -9,9 +9,24 @@ import SwiftUI @main struct Gongbaek_iOSApp: App { + @StateObject private var navigationManager = NavigationManager() + @State private var showMainView = false + var body: some Scene { WindowGroup { - TabBarView() + if showMainView { + RootViewSwitcher() + .environmentObject(navigationManager) + } else { + SplashView() + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 4) { + withAnimation { + showMainView = true + } + } + } + } } } } diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Component/Bar/ApplyBar.swift b/Gongbaek_iOS/Gongbaek_iOS/Global/Component/Bar/ApplyBar.swift index 0729e86e..bd839add 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Global/Component/Bar/ApplyBar.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Component/Bar/ApplyBar.swift @@ -10,28 +10,88 @@ import SwiftUI // MARK: TODO - Model 분리 예정 struct ApplyModel { - var isActivated: Bool var currentPeopleCount: Int var maxPeopleCount: Int - var buttonText: String + var isHost: Bool + var meetingStatus: String + var isApply: Bool var onTap: (() -> Void)? } struct ApplyBar: View { - var applyData: ApplyModel + @Binding var applyData: ApplyModel + + //TODO: buttonText, isActivated, buttonAction ViewModel로 분리 + + private var buttonText: String { + guard let state = RecruitingState(applyData.meetingStatus) else { + return "알 수 없는 상태" + } + + if applyData.isHost { + return state == .CLOSED ? "종료된 모임입니다." : "삭제하기" + } + + switch state { + case .CLOSED: + return "종료된 모임입니다." + case .RECRUITED: + return applyData.isApply ? "취소하기" : "인원 마감" + case .RECRUITING: + return applyData.isApply ? "취소하기" : "신청하기" + } + } + + private var isActivated: Bool { + guard let state = RecruitingState(applyData.meetingStatus) else { + return false + } + + if applyData.isHost { + return state != .CLOSED + } + + switch state { + case .CLOSED: + return false + case .RECRUITED: + return applyData.isApply + case .RECRUITING: + return true + } + } + + private var buttonAction: (() -> Void)? { + guard let state = RecruitingState(applyData.meetingStatus) else { + return nil + } + + if applyData.isHost { + return state == .CLOSED ? nil : { print("삭제하기 처리") } //TODO: viewModel에서 action으로 변경 + } + + switch state { + case .CLOSED: + return nil + case .RECRUITED: + return applyData.isApply ? { print("신청 취소 처리") } : nil //TODO: viewModel에서 action으로 변경 + case .RECRUITING: + return applyData.isApply ? { print("신청 취소 처리") } : { print("모임 신청 처리") } //TODO: viewModel에서 action으로 변경 + } + } var body: some View { HStack(spacing: 16) { Text("\(applyData.currentPeopleCount) / \(applyData.maxPeopleCount) 명") .pretendardFont(.title2_sb_18) .padding(16) - .foregroundStyle(applyData.isActivated ? .gray01 : .grayWhite) + .foregroundStyle(isActivated ? .gray01 : .grayWhite) .background( RoundedRectangle(cornerRadius: 6) - .fill(applyData.isActivated ? .gray09 : .gray04) + .fill(isActivated ? .gray09 : .gray04) ) - BasicButton(text: applyData.buttonText, isActivated: applyData.isActivated, onTap: applyData.onTap) + BasicButton(text: buttonText, isActivated: isActivated, onTap: applyData.onTap) } .padding(.vertical, 20) .padding(.horizontal, 16) @@ -41,12 +101,13 @@ struct ApplyBar: View { #Preview { ApplyBar( - applyData: ApplyModel( - isActivated: true, + applyData: .constant(ApplyModel( currentPeopleCount: 3, maxPeopleCount: 4, - buttonText: "엘렐레", + isHost: false, + meetingStatus: "RECRUITING", + isApply: false, onTap: nil ) - ) + )) } diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Component/Bar/MyFillSegmentControlBar.swift b/Gongbaek_iOS/Gongbaek_iOS/Global/Component/Bar/MyFillSegmentControlBar.swift index 21d17a91..653af0bd 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Global/Component/Bar/MyFillSegmentControlBar.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Component/Bar/MyFillSegmentControlBar.swift @@ -7,25 +7,25 @@ import SwiftUI -enum MyFillType: String, CaseIterable { - case recruit = "내가 모집한" +enum MyFillingType: String, CaseIterable { + case register = "내가 모집한" case apply = "내가 신청한" } struct MyFillSegmentControlBar: View { - //@Binding var recruit의binding될_데이터: binding될_데이터 - //@Binding var apply의binding될_데이터: binding될_데이터 @State private var selectedIndex = 0 + @ObservedObject var viewModel: MyFillingViewModel var body: some View { VStack(spacing: 0) { HStack(spacing: 0) { - ForEach(MyFillType.allCases.indices, id: \.self) { index in - let type = MyFillType.allCases[index] + ForEach(MyFillingType.allCases.indices, id: \.self) { index in + let type = MyFillingType.allCases[index] let isSelected = selectedIndex == index - + Button { selectedIndex = index + fetchMeetings(for: type) } label: { ZStack(alignment: .bottom) { Text(type.rawValue) @@ -45,20 +45,22 @@ struct MyFillSegmentControlBar: View { selectedView() .frame(maxWidth: .infinity, maxHeight: .infinity) } + .onAppear { + fetchMeetings(for: MyFillingType.register) // 기본값 설정 + } } @ViewBuilder private func selectedView() -> some View { - let type = MeetingDetailType.allCases[selectedIndex] + let type = MyFillingType.allCases[selectedIndex] switch type { - case .meetingInfo: - Color.black//MeetingInfoView(ownerInfo: $ownerInfo, meetingDetail: $meetingDetailData) - case .comment: - Color.gray02 //CommentView(commentData: dummyCommentData) + case .register, .apply: + MyFillingList() } } + + private func fetchMeetings(for type: MyFillingType) { + viewModel.fetchMeetings(category: type) + } } -#Preview { - MyFillSegmentControlBar() -} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Component/Box/TitleTextBox.swift b/Gongbaek_iOS/Gongbaek_iOS/Global/Component/Box/TitleTextBox.swift index 9cae07bc..128f499d 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Global/Component/Box/TitleTextBox.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Component/Box/TitleTextBox.swift @@ -28,6 +28,27 @@ struct TitleTextBox: View { } } +struct HomeTitleTextBox: View { + let title: String + var subtitle: String + var highlightSubtitleText: String = "" + + var body: some View { + VStack(alignment: .leading, spacing: 4) { + Text(title) + .pretendardFont(.title2_b_18) + + HighlightTextView( + text: subtitle, + textColor: .gray06, + font: .body2_m_14, + highlightFont: .body2_b_14, + highlightString: highlightSubtitleText + ) + } + } +} + #Preview { TitleTextBox( title: "공갱갱히히 공강시간에 원하는 모임 만들기", diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Component/List/HomeMatchMemberListCell.swift b/Gongbaek_iOS/Gongbaek_iOS/Global/Component/List/HomeMatchMemberListCell.swift new file mode 100644 index 00000000..22a00bb7 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Component/List/HomeMatchMemberListCell.swift @@ -0,0 +1,86 @@ +// +// HomeMatchMemberListCell.swift +// Gongbaek_iOS +// +// Created by 김나연 on 1/21/25. +// + +import SwiftUI + +struct HomeMatchMemberListCell: View { + let data: PerfectMatchMemberModel + + var body: some View { + VStack(spacing: 9) { + HStack { + HStack(spacing: 10) { + Image(ProfileImageMap.allCases[data.profileImage].rawValue) + .resizable() + .renderingMode(.original) + .scaledToFill() + .frame(width: 48, height: 48) + + memberProfile() + } + + Spacer() + chatButton() + } + divider() + } + .padding(.top, 10) + } + + private func memberProfile() -> some View { + VStack(alignment: .leading, spacing: 2) { + HStack(spacing: 2) { + Text(data.nickname) + .pretendardFont(.body2_sb_14) + .foregroundStyle(.gray09) + + Image(data.sex == "MAN" ? .icMale20 : .icFemale20) + .resizable() + .renderingMode(.original) + .scaledToFit() + .frame(width: 20, height: 20) + } + + MajorChip( + major: data.major, + targetObject: .suggestedUserProfile + ) + } + } + + private func chatButton() -> some View { + Button { + // TODO: 추후 스프린트 구현 예정 + } label: { + Text("채팅하기") + .pretendardFont(.caption2_b_12) + .foregroundStyle(.grayWhite) + .padding(.horizontal, 10) + .padding(.vertical, 4) + } + .buttonStyle(.plain) + .background(.mainOrange) + .clipShape(RoundedRectangle(cornerRadius: 4)) + } + + private func divider() -> some View { + Rectangle() + .fill(.gray02) + .frame(height: 1) + } +} + +#Preview { + HomeMatchMemberListCell(data: + PerfectMatchMemberModel( + profileImage: 1, + nickname: "나여니", + sex: "FEMALE", + major: "컴퓨터공학과" + ) + ) +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Component/List/HomeMeetingCell.swift b/Gongbaek_iOS/Gongbaek_iOS/Global/Component/List/HomeMeetingCell.swift new file mode 100644 index 00000000..06272402 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Component/List/HomeMeetingCell.swift @@ -0,0 +1,119 @@ +// +// HomeMeetingCell.swift +// Gongbaek_iOS +// +// Created by 김나연 on 1/21/25. +// + +import SwiftUI + +struct HomeMeetingCell: View { + let data: MeetingModel + let isWeekly: Bool + + var body: some View { + VStack(alignment: .leading, spacing: 4) { + VStack(alignment: .leading, spacing: 6) { + ZStack(alignment: .bottomLeading) { + meetingImage() + categoryChip() + .padding(.leading, 8) + .padding(.bottom, 8) + } + + meetingTitle() + } + + VStack(spacing: 2) { + meetingTime() + userProfiles() + } + } + .frame(width: isWeekly ? 116 : 160) + } + + private func meetingImage() -> some View { + Image(.sample) + .resizable() + .scaledToFill() + .frame( + width: isWeekly ? 116 : 160, + height: isWeekly ? 108 : 104 + ) + .clipShape( + RoundedRectangle(cornerRadius: 4) + ) + } + + private func categoryChip() -> some View { + Text(CategoryState.STUDY.categoryName) + .pretendardFont(.caption2_r_12) + .foregroundStyle(.grayWhite) + .padding(.horizontal, 4) + .background(.gray09) + .clipShape(RoundedRectangle(cornerRadius: 2)) + } + + private func meetingTitle() -> some View { + Text(data.groupTitle) + .pretendardFont(.body2_sb_14) + .foregroundStyle(.gray10) + .lineLimit(isWeekly ? 2 : 1) + } + + private func meetingTime() -> some View { + HStack(spacing: 4) { + Image(.icTime16) + .renderingMode(.original) + .scaledToFit() + .frame(width: 16, height: 16) + + Text( + isWeekly + ? data.weekDate + " 14시-16시" + : (data.groupDate ?? "") + " 수요일 14시 30분-15시" + ) + .pretendardFont(.caption2_m_12) + .foregroundStyle(.gray06) + .lineLimit(1) + + Spacer() + } + } + + private func userProfiles() -> some View { + HStack(spacing: 2) { + Image(.profileImage5) + .resizable() + .renderingMode(.original) + .scaledToFit() + .frame(width: 16, height: 16) + + Text("난밤새는게힘들다이제") + .pretendardFont(.caption2_r_12) + .foregroundStyle(.gray09) + .lineLimit(1) + + Spacer() + } + } +} + +#Preview { + HomeMeetingCell( + data: MeetingModel( + groupId: 0, + category: "DINING", + coverImg: 4, + profileImg: 2, + groupType: "WEEKLY", + groupTitle: "같이 저녁 먹을 사람들 구합니다", + weekDate: "FRI", + groupDate: "2025-05-15", + startTime: 17.0, + endTime: 18.0, + location: "학교 정문 앞" + ), + isWeekly: false + ) +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Component/List/MeetingInfoBase.swift b/Gongbaek_iOS/Gongbaek_iOS/Global/Component/List/MeetingInfoBase.swift index c8f72afa..4ab36377 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Global/Component/List/MeetingInfoBase.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Component/List/MeetingInfoBase.swift @@ -13,7 +13,7 @@ struct MeetingInfoBase: View { var body: some View { HStack(spacing: 12) { - Image(meeting.coverImg) + Image(.sample) .resizable() .aspectRatio(contentMode: .fill) .frame(width: 102, height: 102) @@ -66,42 +66,3 @@ struct MeetingInfoBase: View { } } -#Preview { - MeetingInfoBase( - state: .constant(.cell), meeting: .constant(Meeting( - status: "RECRUITING", - category: "STUDY", - coverImg: "sample", - groupType: "ONCE", - groupTitle: "나는 개바보다 나랑 친구하고 싶으면 들어오덩가 ㅋㅋㅋ", - weekDay: nil, - weekDate: "2024-12-23", - startTime: 13.0, - endTime: 15.0, - location: "학교 정문인데 어쩌구 저쩌구 20자 넘으면" - ))) -} - -#Preview { - MeetingInfoBase( - state: .constant(.cell), meeting: .constant(Meeting( - status: "RECRUITING", - category: "STUDY", - coverImg: "sample", - groupType: "WEEKLY", - groupTitle: "나는 개바보다 나랑 친구하고 싶으면 들어오덩가 ㅋㅋㅋ", - weekDay: "MON", - weekDate: nil, - startTime: 13.0, - endTime: 15.0, - location: "학교 정문인데 어쩌구 저쩌구 20자 넘으면" - ))) -} - -#Preview { - MeetingDetailView( - meetingDetailData: dummymeetingDetailData, - ownerInfoData: dummyOwnerInfoData, - commentData: dummyCommentData - ) -} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Component/List/MeetingInfoCell.swift b/Gongbaek_iOS/Gongbaek_iOS/Global/Component/List/MeetingInfoCell.swift index a62dd767..f3df5af4 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Global/Component/List/MeetingInfoCell.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Component/List/MeetingInfoCell.swift @@ -43,9 +43,10 @@ struct MeetingInfoCell: View { #Preview { MeetingInfoCell( meeting: Meeting( + groupId: 1, status: "모집 중", category: "스터디", - coverImg: "sample", + coverImg: 2, groupType: "소규모", groupTitle: "나는 개바보다 나랑 친구하고 싶으면 들어오덩가 ㅋㅋㅋ", weekDay: "MON", diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Component/Others/TimeTable/ViewModeTimeTable.swift b/Gongbaek_iOS/Gongbaek_iOS/Global/Component/Others/TimeTable/ViewModeTimeTable.swift index cb2b5be9..1809a287 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Global/Component/Others/TimeTable/ViewModeTimeTable.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Component/Others/TimeTable/ViewModeTimeTable.swift @@ -63,7 +63,7 @@ struct ViewModeTimeTable: View { let bottomPadding = bottomPadding(hourIndex, cellId) Rectangle() - .fill(unselectedCells.contains(cellId) ? .subOrange : .grayWhite) + .fill(unselectedCells.contains(cellId) ? .thirdOrange : .grayWhite) .frame(maxWidth: .infinity, minHeight: 24) .padding(.bottom, bottomPadding) .id(cellId) diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Enum/TabBarState.swift b/Gongbaek_iOS/Gongbaek_iOS/Global/Enum/TabBarState.swift index 74ada465..782704b0 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Global/Enum/TabBarState.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Enum/TabBarState.swift @@ -50,7 +50,7 @@ extension TabBarState { func view() -> some View { switch self { case .filling: FillingView() - case .myFilling: Color.gray02 // View 연결 + case .myFilling: MyFillingView() case .home: HomeView() case .timetable: Color.gray04 // View 연결 case .myPage: Color.gray05 // View diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/NavigationDestination.swift b/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/NavigationDestination.swift index 60dd89f5..fb795d46 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/NavigationDestination.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/NavigationDestination.swift @@ -15,26 +15,6 @@ enum SignupDestination: Hashable { switch self { case .signup: SignupView() -// case .profileSelection: -// ProfileSelectionView() -// case .nicknameInput: -// NicknameInputView() -// case .schoolMajorInput: -// SchoolMajorInputView() -// case .gradeAdmissionYearInput: -// GradeAdmissionYearInputView() -// case .mbtiSelection: -// MbtiSelectionView() -// case .sexSelection: -// SexSelectionView() -// case .selfIntroductionWriting: -// SelfIntroductionWritingView() -// case .classTimeTableInput: -// ClassTimeTableInputView() -// case let .freeTimeTableConversion(selectedCells): -// FreeTimeTableConversionView(selectedCells: selectedCells) -// case .signupCompletion: -// SignupCompletionView() } } } diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/NavigationManager.swift b/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/NavigationManager.swift index a7c02dd4..e07c4664 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/NavigationManager.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/NavigationManager.swift @@ -9,9 +9,16 @@ import SwiftUI /// `NavigationPath` 관리하는 전역 내비게이션 매니저 final class NavigationManager: ObservableObject { + + enum RootView { + case signup + case tabBar + } + @Published var path = NavigationPath() @Published var presentedDestination: PresentableDestination? = nil - + @Published var rootView: RootView = .signup + func push(view: T) { path.append(view) } diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/RootViewSwitcher.swift b/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/RootViewSwitcher.swift new file mode 100644 index 00000000..c3f780a4 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/RootViewSwitcher.swift @@ -0,0 +1,26 @@ +// +// RootViewSwitcher.swift +// Gongbaek_iOS +// +// Created by 김나연 on 1/22/25. +// + +import SwiftUI + +struct RootViewSwitcher: View { + @EnvironmentObject var navigationManager: NavigationManager + + var body: some View { + switch navigationManager.rootView { + case .signup: + SignupNavigationView() + case .tabBar: + TabBarView() + } + } +} + +#Preview { + RootViewSwitcher() + .environmentObject(NavigationManager()) +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/SignupNavigationView.swift b/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/SignupNavigationView.swift index dbdfe89e..c6911e71 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/SignupNavigationView.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/SignupNavigationView.swift @@ -8,20 +8,15 @@ import SwiftUI struct SignupNavigationView: View { - @StateObject private var navigationManager = NavigationManager() + @EnvironmentObject var navigationManager: NavigationManager var body: some View { NavigationStack(path: $navigationManager.path) { SignupDestination.signup.view() - .navigationDestination(for: SignupDestination.self) { type in - type.view() - .toolbar(.hidden, for: .navigationBar) - } .fullScreenCover(item: $navigationManager.presentedDestination) { type in type.view() } } - .environmentObject(navigationManager) } } diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/TabBarView.swift b/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/TabBarView.swift index 9f7ec0e3..8d9201db 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/TabBarView.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Navigation/TabBarView.swift @@ -8,7 +8,7 @@ import SwiftUI struct TabBarView: View { - @StateObject private var navigationManager = NavigationManager() + @EnvironmentObject var navigationManager: NavigationManager @State var selectedTab: TabBarState = .home var body: some View { @@ -31,7 +31,6 @@ struct TabBarView: View { // .toolbar(.hidden, for: .navigationBar) } } - .environmentObject(navigationManager) } } diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Color/Secondary/third_orange.colorset/Contents.json b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Color/Secondary/third_orange.colorset/Contents.json new file mode 100644 index 00000000..7b374762 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Color/Secondary/third_orange.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x98", + "green" : "0xC4", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_fire_18.imageset/ic_fire_18.png b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_fire_18.imageset/ic_fire_18.png index 9c89400d..9c2e6941 100644 Binary files a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_fire_18.imageset/ic_fire_18.png and b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_fire_18.imageset/ic_fire_18.png differ diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_fire_18.imageset/ic_fire_18@2x.png b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_fire_18.imageset/ic_fire_18@2x.png index d8e04860..d94addd9 100644 Binary files a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_fire_18.imageset/ic_fire_18@2x.png and b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_fire_18.imageset/ic_fire_18@2x.png differ diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_fire_18.imageset/ic_fire_18@3x.png b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_fire_18.imageset/ic_fire_18@3x.png index 8b95cc97..de86e079 100644 Binary files a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_fire_18.imageset/ic_fire_18@3x.png and b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_fire_18.imageset/ic_fire_18@3x.png differ diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_lock_18.imageset/Contents.json b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_lock_18.imageset/Contents.json index a5e4fd91..16d315e9 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_lock_18.imageset/Contents.json +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_lock_18.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "ic_lock_18.png", + "filename" : "ic_lock_18@3x 1.png", "idiom" : "universal", "scale" : "1x" }, diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_lock_18.imageset/ic_lock_18@3x 1.png b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_lock_18.imageset/ic_lock_18@3x 1.png new file mode 100644 index 00000000..caf597c0 Binary files /dev/null and b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Icon/ic_lock_18.imageset/ic_lock_18@3x 1.png differ diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/Empty/Contents.json b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/Empty/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/Empty/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/Empty/img_myFill_empty_active.imageset/Contents.json b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/Empty/img_myFill_empty_active.imageset/Contents.json new file mode 100644 index 00000000..c70971e3 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/Empty/img_myFill_empty_active.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "img_my_fill_empty_action.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/Empty/img_myFill_empty_active.imageset/img_my_fill_empty_action.svg b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/Empty/img_myFill_empty_active.imageset/img_my_fill_empty_action.svg new file mode 100644 index 00000000..34b1186b --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/Empty/img_myFill_empty_active.imageset/img_my_fill_empty_action.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/Empty/img_myFill_empty_end.imageset/Contents.json b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/Empty/img_myFill_empty_end.imageset/Contents.json new file mode 100644 index 00000000..0fefdc2e --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/Empty/img_myFill_empty_end.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "img_my_fill_empty_end.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/Empty/img_myFill_empty_end.imageset/img_my_fill_empty_end.svg b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/Empty/img_myFill_empty_end.imageset/img_my_fill_empty_end.svg new file mode 100644 index 00000000..feb276e1 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/Empty/img_myFill_empty_end.imageset/img_my_fill_empty_end.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_home_banner.imageset/Contents.json b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_home_banner.imageset/Contents.json new file mode 100644 index 00000000..1697e99c --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_home_banner.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "img_home_banner.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_home_banner.imageset/img_home_banner.svg b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_home_banner.imageset/img_home_banner.svg new file mode 100644 index 00000000..64db1e74 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_home_banner.imageset/img_home_banner.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_home_main.imageset/Contents.json b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_home_main.imageset/Contents.json new file mode 100644 index 00000000..115f774c --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_home_main.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "img_home_main.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_home_main.imageset/img_home_main.svg b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_home_main.imageset/img_home_main.svg new file mode 100644 index 00000000..e1fb527e --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_home_main.imageset/img_home_main.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_1.imageset/Contents.json b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_1.imageset/Contents.json new file mode 100644 index 00000000..f7569d8f --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_1.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "img_onboard_illustration1.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_1.imageset/img_onboard_illustration1.svg b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_1.imageset/img_onboard_illustration1.svg new file mode 100644 index 00000000..deb11cac --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_1.imageset/img_onboard_illustration1.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_2.imageset/Contents.json b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_2.imageset/Contents.json new file mode 100644 index 00000000..a0e4d0fb --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_2.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "img_onboard_illustration2.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_2.imageset/img_onboard_illustration2.svg b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_2.imageset/img_onboard_illustration2.svg new file mode 100644 index 00000000..7494f927 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_2.imageset/img_onboard_illustration2.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_3.imageset/Contents.json b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_3.imageset/Contents.json new file mode 100644 index 00000000..170d8b92 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_3.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "img_onboard_illustration3.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_3.imageset/img_onboard_illustration3.svg b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_3.imageset/img_onboard_illustration3.svg new file mode 100644 index 00000000..68715efb --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Assets.xcassets/Image/img_onboarding_3.imageset/img_onboard_illustration3.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Fonts/HighlightTextView.swift b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Fonts/HighlightTextView.swift index 6b42759b..442e3d29 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Fonts/HighlightTextView.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Fonts/HighlightTextView.swift @@ -11,6 +11,7 @@ struct HighlightTextView: View { let text: String let textColor: Color let font: FontFamily + var highlightFont: FontFamily? = nil var highlightString: String = "" var highlightColor: Color = .mainOrange @@ -34,6 +35,7 @@ struct HighlightTextView: View { .foregroundColor(textColor) let targetText = Text(targetString) .foregroundColor(highlightColor) + .font(.pretendard(highlightFont ?? font)) let trailingText = Text(trailingString) .foregroundColor(textColor) diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Lottie/LottieView.swift b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Lottie/LottieView.swift new file mode 100644 index 00000000..2e197acc --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Lottie/LottieView.swift @@ -0,0 +1,38 @@ +// +// LottieView.swift +// Gongbaek_iOS +// +// Created by 김나연 on 1/22/25. +// + +import SwiftUI +import Lottie + +struct LottieView: UIViewRepresentable { + let animationName: String + let loopMode: LottieLoopMode + + private let animationView = LottieAnimationView() + + func makeUIView(context: Context) -> UIView { + let view = UIView(frame: .zero) + animationView.animation = LottieAnimation.named(animationName) + animationView.contentMode = .scaleAspectFit + animationView.loopMode = loopMode + animationView.play() + + view.addSubview(animationView) + animationView.translatesAutoresizingMaskIntoConstraints = false + + NSLayoutConstraint.activate([ + animationView.widthAnchor.constraint(equalTo: view.widthAnchor), + animationView.heightAnchor.constraint(equalTo: view.heightAnchor), + animationView.centerXAnchor.constraint(equalTo: view.centerXAnchor), + animationView.centerYAnchor.constraint(equalTo: view.centerYAnchor) + ]) + + return view + } + + func updateUIView(_ uiView: UIView, context: Context) {} +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Lottie/splash.json b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Lottie/splash.json new file mode 100644 index 00000000..af1d43a5 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Lottie/splash.json @@ -0,0 +1 @@ +{"ddd":0,"h":812,"w":375,"meta":{"g":"@lottiefiles/toolkit-js 0.57.2-beta.0","tc":"#ffffff"},"layers":[{"ty":4,"sr":1,"st":0,"op":125,"ip":20.666666666666668,"ln":"113","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[32,80,0]},"s":{"a":0,"k":[40,40,200]},"p":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[399.5,346,0],"t":20.666666666666668,"ti":[32,0,0],"to":[-32,0,0]},{"s":[207.5,346,0],"t":31,"ti":[32,0,0],"to":[-32,0,0]}]},"r":{"a":0,"k":0},"o":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[0],"t":20.666666666666668},{"s":[100],"t":31}]}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-32,-80],[-32,-48],[0,-48],[0,48],[32,48],[32,-80]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-32,80],[0,80],[0,48],[-32,48]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[0.9961,0.4549,0.2078]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[32,80]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":1},{"ty":4,"sr":1,"st":0,"op":125,"ip":20.666666666666668,"ln":"112","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[32,80,0]},"s":{"a":0,"k":[40,40,98.084]},"p":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[-21.5,346,0],"t":20.666666666666668,"ti":[-31.667,0,0],"to":[31.667,0,0]},{"s":[168.5,346,0],"t":31,"ti":[-31.667,0,0],"to":[31.667,0,0]}]},"r":{"a":0,"k":0},"o":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[0],"t":20.666666666666668},{"s":[100],"t":31}]}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,-48],[31.999,-48],[31.999,-80],[0,-80]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":false,"i":[[0,0]],"o":[[0,0]],"v":[[0,-80]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-32,-48],[-32,80],[0,80],[32,80],[32,48],[0,48],[0,-48]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[0.9961,0.4549,0.2078]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[32,80]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":2},{"ty":4,"sr":1,"st":-78.33333333333333,"op":124.66666666666667,"ip":20.333333333333343,"ln":"111","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[134.84,415.956,0]},"r":{"a":0,"k":0},"o":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[0],"t":31},{"s":[100],"t":41.33333333333334}]}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0.893,0],[0.658,-0.185],[0.358,-0.349],[0,-0.483],[-0.358,-0.344],[-0.659,-0.184],[-0.885,0],[-0.658,0.185],[-0.358,0.344],[0,0.474],[0.357,0.348],[0.659,0.184]],"o":[[-0.885,0],[-0.659,0.184],[-0.358,0.348],[0,0.474],[0.358,0.344],[0.658,0.185],[0.893,0],[0.659,-0.184],[0.357,-0.344],[0,-0.483],[-0.358,-0.349],[-0.658,-0.185]],"v":[[5.975,-3.418],[3.661,-3.141],[2.136,-2.341],[1.6,-1.094],[2.136,0.133],[3.661,0.926],[5.975,1.203],[8.302,0.926],[9.827,0.133],[10.363,-1.094],[9.827,-2.341],[8.302,-3.141]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0.438,-4.307],[11.648,-4.307],[11.648,-5.537],[6.289,-5.537],[6.289,-7.779],[4.785,-7.779],[4.785,-5.537],[0.438,-5.537]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0.041,-0.442],[0.136,-0.537],[0,0],[-0.043,0.456],[0,0.533],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0.556],[-0.041,0.442],[0,0],[0.142,-0.501],[0.044,-0.455],[0,0],[0,0],[0,0],[0,0]],"v":[[1.723,-9.352],[8.764,-9.352],[8.702,-7.854],[8.436,-6.385],[9.939,-6.248],[10.216,-7.684],[10.281,-9.167],[10.281,-9.529],[10.281,-10.555],[1.723,-10.555]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[-0.005,0.36],[-0.501,0.205],[-0.898,0],[-0.508,-0.205],[-0.004,-0.373],[0.508,-0.194],[0.902,0],[0.499,0.194]],"o":[[-0.005,-0.373],[0.501,-0.205],[0.902,0],[0.508,0.205],[-0.004,0.36],[-0.508,0.194],[-0.903,0],[-0.499,-0.194]],"v":[[3.131,-1.094],[3.876,-1.962],[5.975,-2.27],[8.09,-1.962],[8.859,-1.094],[8.09,-0.263],[5.975,0.027],[3.873,-0.263]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[0.9961,0.4549,0.2078]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":3},{"ty":4,"sr":1,"st":-78.33333333333333,"op":124.66666666666667,"ip":20.333333333333343,"ln":"110","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[135.34,415.956,0],"t":51.66666666666667,"ti":[-5.958,0,0],"to":[5.958,0,0]},{"s":[171.09,415.956,0],"t":67.33333333333333,"ti":[-5.958,0,0],"to":[5.958,0,0]}]},"r":{"a":0,"k":0},"o":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[0],"t":57.000000000000014},{"s":[100],"t":67.33333333333333}]}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[2.324,-10.35],[0.889,-10.35],[0.889,-4.457],[5.77,-4.457],[5.77,-10.35],[4.361,-10.35],[4.361,-8.531],[2.324,-8.531]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[2.324,-5.66],[2.324,-7.355],[4.361,-7.355],[4.361,-5.66]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[2.516,-1.846],[9.461,-1.846],[9.461,1.217],[10.979,1.217],[10.979,-3.076],[2.516,-3.076]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[6.877,-3.773],[8.299,-3.773],[8.299,-6.809],[9.529,-6.809],[9.529,-3.705],[10.979,-3.705],[10.979,-11.129],[9.529,-11.129],[9.529,-8.053],[8.299,-8.053],[8.299,-10.896],[6.877,-10.896]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[0.9961,0.4549,0.2078]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":4},{"ty":4,"sr":1,"st":40.333333333333336,"op":124.66666666666666,"ip":39,"ln":"109","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[145.965,444.956,0],"t":72.33333333333334,"ti":[0,4.833,0],"to":[0,-4.833,0]},{"s":[145.965,415.956,0],"t":87,"ti":[0,4.833,0],"to":[0,-4.833,0]}]},"r":{"a":0,"k":0},"o":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[0],"t":72.33333333333334},{"s":[100],"t":87}]}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[10.158,-11.143],[8.641,-11.143],[8.641,-3.896],[10.158,-3.896],[10.158,-6.891],[11.881,-6.891],[11.881,-8.135],[10.158,-8.135]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0.925,-0.25],[0,0],[-0.862,0.62],[-0.451,0.868],[0,1.071],[0,0],[0,0],[0,0],[0.392,-0.531],[0.677,-0.41]],"o":[[0,0],[1.221,-0.346],[0.861,-0.62],[0.452,-0.868],[0,0],[0,0],[0,0],[-0.087,0.619],[-0.392,0.531],[-0.677,0.41]],"v":[[0.369,-4.936],[0.971,-3.705],[4.095,-5.154],[6.063,-7.386],[6.74,-10.295],[0.93,-10.295],[0.93,-9.064],[5.093,-9.064],[4.375,-7.338],[2.772,-5.927]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[-0.004,-0.502],[-0.342,-0.374],[-0.624,-0.198],[-0.825,0],[-0.622,0.198],[-0.34,0.373],[0,0.505],[0.339,0.374],[0.622,0.2],[0.829,0],[0.625,-0.201],[0.342,-0.374]],"o":[[-0.004,0.505],[0.342,0.373],[0.625,0.198],[0.829,0],[0.622,-0.198],[0.339,-0.374],[0,-0.502],[-0.34,-0.374],[-0.622,-0.201],[-0.825,0],[-0.624,0.2],[-0.342,0.374]],"v":[[2.037,-1.271],[2.543,0.048],[3.992,0.906],[6.166,1.203],[8.343,0.906],[9.786,0.048],[10.295,-1.271],[9.786,-2.584],[8.343,-3.445],[6.166,-3.746],[3.992,-3.445],[2.543,-2.584]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0.264],[-0.209,0.193],[-0.394,0.1],[-0.542,0],[-0.47,-0.226],[-0.005,-0.406],[0.215,-0.194],[0.397,-0.103],[0.538,0],[0.394,0.102],[0.21,0.193]],"o":[[0,-0.269],[0.21,-0.194],[0.394,-0.1],[0.816,0],[0.469,0.225],[0,0.264],[-0.214,0.193],[-0.396,0.102],[-0.542,0],[-0.394,-0.103],[-0.209,-0.194]],"v":[[3.541,-1.271],[3.855,-1.965],[4.761,-2.406],[6.166,-2.557],[8.094,-2.218],[8.805,-1.271],[8.483,-0.584],[7.567,-0.14],[6.166,0.014],[4.761,-0.14],[3.855,-0.584]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[1,1,1]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0.939,0],[0.665,-0.161],[0.351,-0.317],[0,-0.451],[-0.351,-0.319],[-0.666,-0.161],[-0.939,-0.005],[-0.665,0.162],[-0.351,0.319],[0,0.456],[0.35,0.317],[0.665,0.164]],"o":[[-0.939,0.004],[-0.666,0.162],[-0.351,0.317],[0,0.456],[0.351,0.319],[0.665,0.162],[0.939,-0.005],[0.665,-0.161],[0.35,-0.319],[0,-0.451],[-0.351,-0.317],[-0.665,-0.164]],"v":[[17.149,-10.951],[14.743,-10.702],[13.218,-9.984],[12.692,-8.832],[13.218,-7.67],[14.743,-6.949],[17.149,-6.699],[19.555,-6.949],[21.08,-7.67],[21.606,-8.832],[21.08,-9.984],[19.555,-10.705]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[11.53,-4.826],[22.795,-4.826],[22.795,-6.043],[11.53,-6.043]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[12.856,-2.871],[19.897,-2.871],[19.897,-2.051],[12.87,-2.051],[12.87,1.107],[21.729,1.107],[21.729,-0.055],[14.36,-0.055],[14.36,-0.971],[21.387,-0.971],[21.387,-3.992],[12.856,-3.992]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[-0.004,0.337],[-0.488,0.173],[-0.934,0],[-0.49,-0.173],[0,-0.319],[0.481,-0.164],[0.961,0],[0.479,0.164]],"o":[[-0.004,-0.319],[0.488,-0.173],[0.943,0],[0.49,0.173],[0,0.337],[-0.48,0.164],[-0.953,0],[-0.478,-0.164]],"v":[[14.291,-8.832],[15.016,-9.57],[17.149,-9.83],[19.299,-9.57],[20.034,-8.832],[19.312,-8.08],[17.149,-7.834],[15.002,-8.08]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[1,1,1]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0.866,0],[0.697,-0.291],[0.399,-0.529],[0,-0.684],[-0.399,-0.533],[-0.697,-0.291],[-0.861,0],[-0.702,0.292],[-0.401,0.533],[0,0.693],[0.401,0.528],[0.701,0.292]],"o":[[-0.861,0],[-0.697,0.292],[-0.399,0.528],[0,0.693],[0.399,0.533],[0.697,0.292],[0.866,0],[0.701,-0.291],[0.401,-0.533],[0,-0.684],[-0.401,-0.529],[-0.702,-0.291]],"v":[[42.322,-10.445],[39.984,-10.008],[38.34,-8.777],[37.742,-6.959],[38.34,-5.12],[39.984,-3.883],[42.322,-3.445],[44.674,-3.883],[46.328,-5.12],[46.93,-6.959],[46.328,-8.777],[44.674,-10.008]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[36.703,-0.342],[47.996,-0.342],[47.996,-1.586],[36.703,-1.586]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0.456],[-0.267,0.344],[-0.474,0.187],[-0.597,-0.004],[-0.474,-0.187],[-0.266,-0.344],[0,-0.447],[0.267,-0.344],[0.472,-0.182],[0.602,-0.005],[0.472,0.184],[0.266,0.342]],"o":[[0,-0.447],[0.266,-0.344],[0.474,-0.187],[0.597,-0.004],[0.473,0.187],[0.267,0.344],[0,0.456],[-0.266,0.344],[-0.472,0.183],[-0.601,-0.005],[-0.471,-0.185],[-0.267,-0.341]],"v":[[39.205,-6.959],[39.605,-8.145],[40.716,-8.941],[42.322,-9.215],[43.929,-8.941],[45.039,-8.145],[45.439,-6.959],[45.039,-5.759],[43.932,-4.97],[42.322,-4.689],[40.712,-4.973],[39.605,-5.763]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[1,1,1]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[59.116,-1.477],[54.194,-1.477],[54.194,-3.486],[58.063,-3.486],[58.063,-4.73],[50.68,-4.73],[50.68,-6.33],[57.776,-6.33],[57.776,-10.295],[49.135,-10.295],[49.135,-9.064],[56.272,-9.064],[56.272,-7.533],[49.162,-7.533],[49.162,-3.486],[52.69,-3.486],[52.69,-1.477],[47.823,-1.477],[47.823,-0.219],[59.116,-0.219]]}}},{"ty":"fl","c":{"a":0,"k":[1,1,1]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0.652],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0.182,-0.643],[0.376,-0.531],[0.556,-0.324],[0,0],[-0.396,0.56],[-0.228,0.724],[-0.396,-0.51],[-0.556,-0.291],[0,0],[0.378,0.497],[0.183,0.61]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.004,0.675],[-0.182,0.642],[-0.376,0.531],[0,0],[0.56,-0.319],[0.397,-0.561],[0.232,0.67],[0.397,0.511],[0,0],[-0.565,-0.296],[-0.378,-0.497],[-0.182,-0.611]],"v":[[65.058,-7.383],[65.058,-7.725],[67.191,-7.725],[67.191,-8.969],[65.058,-8.969],[65.058,-10.705],[63.622,-10.705],[63.622,-8.969],[61.462,-8.969],[61.462,-7.725],[63.622,-7.725],[63.622,-7.383],[63.342,-5.407],[62.505,-3.647],[61.107,-2.365],[61.982,-1.244],[63.417,-2.563],[64.354,-4.491],[65.297,-2.721],[66.726,-1.518],[67.587,-2.639],[66.172,-3.828],[65.331,-5.489]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[67.847,0.615],[69.283,0.615],[69.283,-5.045],[70.554,-5.045],[70.554,1.217],[72.003,1.217],[72.003,-11.143],[70.554,-11.143],[70.554,-6.303],[69.283,-6.303],[69.283,-10.924],[67.847,-10.924]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[1,1,1]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[83.683,-4.184],[72.39,-4.184],[72.39,-2.926],[77.258,-2.926],[77.258,1.217],[78.761,1.217],[78.761,-2.926],[83.683,-2.926]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,-0.556],[-0.37,-0.412],[-0.673,-0.224],[-0.871,0],[-0.675,0.223],[-0.376,0.413],[0,0.552],[0.376,0.42],[0.673,0.228],[0.875,0],[0.67,-0.228],[0.369,-0.419]],"o":[[0,0.552],[0.369,0.413],[0.672,0.223],[0.87,0],[0.674,-0.224],[0.376,-0.412],[0,-0.556],[-0.376,-0.419],[-0.672,-0.228],[-0.875,0],[-0.67,0.228],[-0.37,0.42]],"v":[[73.58,-7.93],[74.134,-6.484],[75.696,-5.53],[78.01,-5.195],[80.327,-5.53],[81.903,-6.484],[82.467,-7.93],[81.903,-9.393],[80.33,-10.363],[78.01,-10.705],[75.692,-10.363],[74.134,-9.393]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0.319],[-0.234,0.233],[-0.433,0.123],[-0.579,0],[-0.433,-0.123],[-0.237,-0.232],[0,-0.319],[0.237,-0.23],[0.433,-0.12],[0.583,0],[0.433,0.121],[0.235,0.23]],"o":[[0,-0.319],[0.235,-0.232],[0.433,-0.123],[0.583,0],[0.433,0.123],[0.237,0.233],[0,0.319],[-0.237,0.23],[-0.433,0.121],[-0.579,0],[-0.433,-0.12],[-0.234,-0.23]],"v":[[75.138,-7.93],[75.49,-8.757],[76.492,-9.29],[78.01,-9.475],[79.534,-9.29],[80.539,-8.757],[80.894,-7.93],[80.539,-7.106],[79.534,-6.58],[78.01,-6.398],[76.492,-6.58],[75.49,-7.106]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[1,1,1]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[93.203,-11.143],[91.686,-11.143],[91.686,1.23],[93.203,1.23],[93.203,-5.209],[95.104,-5.209],[95.104,-6.453],[93.203,-6.453]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[-0.87,0.05],[-0.897,0.155],[0,0],[0.802,-0.059],[1.003,-0.005],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[1.235,0],[0.871,-0.05],[0,0],[-0.821,0.141],[-0.802,0.059],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[84.03,-1.791],[85.055,-1.791],[88.213,-1.866],[90.865,-2.174],[90.688,-3.459],[88.254,-3.158],[85.547,-3.062],[85.547,-8.736],[89.813,-8.736],[89.813,-9.967],[84.03,-9.967]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[1,1,1]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":5},{"ty":1,"sr":1,"st":0,"op":125,"ip":0,"ln":"115","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[187.5,406]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[187.5,406]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"sc":"#121212","sh":812,"sw":375,"ind":6}],"v":"5.7.0","fr":29,"op":125,"ip":0,"assets":[]} \ No newline at end of file diff --git a/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Lottie/timetable.json b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Lottie/timetable.json new file mode 100644 index 00000000..1f53dcee --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Global/Resource/Lottie/timetable.json @@ -0,0 +1 @@ +{"ddd":0,"h":812,"w":375,"meta":{"g":"@lottiefiles/toolkit-js 0.57.2-beta.0","tc":"#ffffff"},"layers":[{"ty":5,"sr":1,"st":0,"op":47.666666666666664,"ip":0,"ln":"204","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[260.217,181,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"t":{"m":{"a":{"a":0,"k":[0,0]},"g":1},"p":{"f":{"a":0,"k":0},"l":{"a":0,"k":0},"r":{"a":0,"k":0},"a":{"a":0,"k":0},"p":{"a":0,"k":0}},"a":[],"d":{"k":[{"s":{"f":"Pretendard-SemiBold","s":24,"t":".\r","fc":[0.0706,0.0706,0.0706],"lh":94,"tr":-90,"j":0,"ca":0},"t":0}]}},"ind":1},{"ty":5,"sr":1,"st":15.333333333333334,"op":47.333333333333336,"ip":15.333333333333334,"ln":"203","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[266.217,181,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"t":{"m":{"a":{"a":0,"k":[0,0]},"g":1},"p":{"f":{"a":0,"k":0},"l":{"a":0,"k":0},"r":{"a":0,"k":0},"a":{"a":0,"k":0},"p":{"a":0,"k":0}},"a":[],"d":{"k":[{"s":{"f":"Pretendard-SemiBold","s":24,"t":".\r","fc":[0.0706,0.0706,0.0706],"lh":94,"tr":-90,"j":0,"ca":0},"t":0}]}},"ind":2},{"ty":5,"sr":1,"st":31,"op":47.66666666666667,"ip":31,"ln":"202","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[277.217,181,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"t":{"m":{"a":{"a":0,"k":[0,0]},"g":1},"p":{"f":{"a":0,"k":0},"l":{"a":0,"k":0},"r":{"a":0,"k":0},"a":{"a":0,"k":0},"p":{"a":0,"k":0}},"a":[],"d":{"k":[{"s":{"f":"Pretendard-SemiBold","s":24,"t":".\r","fc":[0.0706,0.0706,0.0706],"lh":94,"tr":-90,"j":0,"ca":0},"t":0}]}},"ind":3},{"ty":5,"sr":1,"st":47.666666666666664,"op":95.33333333333333,"ip":47.666666666666664,"ln":"201","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[260.217,181,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"t":{"m":{"a":{"a":0,"k":[0,0]},"g":1},"p":{"f":{"a":0,"k":0},"l":{"a":0,"k":0},"r":{"a":0,"k":0},"a":{"a":0,"k":0},"p":{"a":0,"k":0}},"a":[],"d":{"k":[{"s":{"f":"Pretendard-SemiBold","s":24,"t":".\r","fc":[0.0706,0.0706,0.0706],"lh":94,"tr":-90,"j":0,"ca":0},"t":0}]}},"ind":4},{"ty":5,"sr":1,"st":63.333333333333336,"op":95.33333333333334,"ip":63.333333333333336,"ln":"200","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[266.217,181,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"t":{"m":{"a":{"a":0,"k":[0,0]},"g":1},"p":{"f":{"a":0,"k":0},"l":{"a":0,"k":0},"r":{"a":0,"k":0},"a":{"a":0,"k":0},"p":{"a":0,"k":0}},"a":[],"d":{"k":[{"s":{"f":"Pretendard-SemiBold","s":24,"t":".\r","fc":[0.0706,0.0706,0.0706],"lh":94,"tr":-90,"j":0,"ca":0},"t":0}]}},"ind":5},{"ty":5,"sr":1,"st":79,"op":95.66666666666667,"ip":79,"ln":"199","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[277.217,181,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"t":{"m":{"a":{"a":0,"k":[0,0]},"g":1},"p":{"f":{"a":0,"k":0},"l":{"a":0,"k":0},"r":{"a":0,"k":0},"a":{"a":0,"k":0},"p":{"a":0,"k":0}},"a":[],"d":{"k":[{"s":{"f":"Pretendard-SemiBold","s":24,"t":".\r","fc":[0.0706,0.0706,0.0706],"lh":94,"tr":-90,"j":0,"ca":0},"t":0}]}},"ind":6},{"ty":4,"sr":1,"st":0,"op":93.66666666666667,"ip":0,"ln":"355","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[96.523,181,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[1.555,0],[1.144,-0.317],[0.617,-0.606],[0,-0.843],[-0.617,-0.606],[-1.145,-0.317],[-1.539,0],[-1.144,0.316],[-0.617,0.605],[-0.007,0.829],[0.617,0.605],[1.141,0.316]],"o":[[-1.539,0],[-1.145,0.316],[-0.617,0.605],[0,0.829],[0.617,0.605],[1.144,0.316],[1.547,0],[1.145,-0.317],[0.617,-0.606],[-0.007,-0.843],[-0.617,-0.606],[-1.141,-0.317]],"v":[[10.242,-5.883],[6.217,-5.408],[3.574,-4.025],[2.648,-1.852],[3.574,0.299],[6.217,1.682],[10.242,2.156],[14.279,1.682],[16.922,0.299],[17.859,-1.852],[16.922,-4.025],[14.285,-5.408]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0.68,-7.242],[20.039,-7.242],[20.039,-9.656],[10.898,-9.656],[10.898,-13.383],[7.945,-13.383],[7.945,-9.656],[0.68,-9.656]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0.07,-0.722],[0.219,-0.875],[0,0],[-0.078,0.797],[0,0.937],[0,0],[0,0],[0,0]],"o":[[0,0],[-0.016,0.898],[-0.071,0.723],[0,0],[0.25,-0.867],[0.078,-0.797],[0,0],[0,0],[0,0],[0,0]],"v":[[2.859,-15.867],[14.766,-15.867],[14.637,-13.436],[14.203,-11.039],[17.133,-10.758],[17.625,-13.254],[17.742,-15.855],[17.742,-16.477],[17.742,-18.211],[2.859,-18.211]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[-0.008,0.571],[-0.813,0.304],[-1.516,0],[-0.793,-0.309],[0,-0.585],[0.804,-0.293],[1.484,0],[0.801,0.293]],"o":[[-0.008,-0.593],[0.812,-0.305],[1.453,0],[0.793,0.308],[0,0.571],[-0.805,0.293],[-1.484,0],[-0.8,-0.293]],"v":[[5.625,-1.852],[6.832,-3.199],[10.324,-3.656],[13.693,-3.193],[14.883,-1.852],[13.676,-0.557],[10.242,-0.117],[6.814,-0.557]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[0.0706,0.0706,0.0706]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[36.137,-19.172],[33.137,-19.172],[33.137,-6.797],[36.137,-6.797],[36.137,-11.719],[39.02,-11.719],[39.02,-14.156],[36.137,-14.156]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[2.313,-0.61],[0,0],[-1.48,1.066],[-0.765,1.508],[0,1.883],[0,0],[0,0],[0,0],[1.343,-1.156]],"o":[[0,0],[2.117,-0.594],[1.481,-1.067],[0.766,-1.507],[0,0],[0,0],[0,0],[-0.234,1.5],[-1.344,1.157]],"v":[[19.074,-8.742],[20.27,-6.328],[25.666,-8.818],[29.035,-12.68],[30.184,-17.766],[20.082,-17.766],[20.082,-15.375],[26.926,-15.375],[24.559,-11.391]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[-0.008,-0.882],[-0.598,-0.66],[-1.094,-0.351],[-1.438,0],[-1.086,0.352],[-0.594,0.656],[0,0.891],[0.593,0.656],[1.086,0.356],[1.437,0],[1.094,-0.355],[0.598,-0.657]],"o":[[-0.008,0.883],[0.598,0.66],[1.094,0.352],[1.437,0],[1.086,-0.351],[0.593,-0.657],[0,-0.882],[-0.594,-0.657],[-1.086,-0.355],[-1.438,0],[-1.094,0.356],[-0.598,0.656]],"v":[[21.957,-2.18],[22.842,0.135],[25.379,1.652],[29.176,2.18],[32.961,1.652],[35.481,0.141],[36.371,-2.18],[35.481,-4.488],[32.961,-6.006],[29.176,-6.539],[25.379,-6.006],[22.842,-4.488]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[-0.008,0.641],[-0.75,0.356],[-1.352,0],[-0.746,-0.355],[0,-0.648],[0.758,-0.347],[1.352,0],[0.742,0.351]],"o":[[-0.008,-0.648],[0.75,-0.355],[1.336,0],[0.746,0.356],[0,0.649],[-0.757,0.348],[-1.328,0],[-0.742,-0.352]],"v":[[24.91,-2.18],[26.024,-3.686],[29.176,-4.219],[32.299,-3.686],[33.418,-2.18],[32.281,-0.686],[29.117,-0.164],[26.012,-0.691]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[0.0706,0.0706,0.0706]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[-0.008,1.336],[0,0],[0,0],[0,0],[0.414,-1.301],[0.832,-1.004],[1.203,-0.508],[0,0],[-0.89,1.098],[-0.492,1.484],[-0.856,-1.008],[-1.187,-0.539],[0,0],[0.813,0.969],[0.406,1.243]],"o":[[0,0],[0,0],[0,0],[-0.008,1.414],[-0.414,1.3],[-0.832,1.004],[0,0],[1.266,-0.579],[0.891,-1.098],[0.5,1.359],[0.855,1.007],[0,0],[-1.164,-0.492],[-0.813,-0.969],[-0.406,-1.242]],"v":[[49.465,-14.344],[49.465,-17.531],[46.442,-17.531],[46.442,-14.344],[45.809,-10.271],[43.94,-6.814],[40.887,-4.547],[42.692,-2.062],[45.926,-4.576],[48,-8.449],[50.034,-4.898],[53.098,-2.578],[54.856,-4.969],[51.891,-7.16],[50.063,-10.477]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[56.004,2.203],[59.028,2.203],[59.028,-19.172],[56.004,-19.172]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[0.0706,0.0706,0.0706]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[76.673,-19.172],[73.649,-19.172],[73.649,-3.891],[76.673,-3.891],[76.673,-10.734],[79.555,-10.734],[79.555,-13.195],[76.673,-13.195]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[2.359,-0.656],[0,0],[-1.493,1.086],[-0.777,1.528],[0,1.906],[0,0],[0,0],[0,0],[1.356,-1.176]],"o":[[0,0],[2.133,-0.601],[1.492,-1.086],[0.777,-1.527],[0,0],[0,0],[0,0],[-0.234,1.524],[-1.355,1.176]],"v":[[59.61,-8.344],[60.852,-5.977],[66.29,-8.508],[69.694,-12.428],[70.86,-17.578],[60.548,-17.578],[60.548,-15.141],[67.567,-15.141],[65.182,-11.092]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[62.798,1.781],[77.399,1.781],[77.399,-0.609],[65.821,-0.609],[65.821,-5.461],[62.798,-5.461]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[0.0706,0.0706,0.0706]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[97.856,-2.602],[92.911,-2.602],[92.911,-6.656],[96.122,-6.656],[96.122,-9.07],[93.216,-9.07],[93.216,-15.07],[96.216,-15.07],[96.216,-17.461],[79.856,-17.461],[79.856,-15.07],[82.809,-15.07],[82.809,-9.07],[79.95,-9.07],[79.95,-6.656],[83.184,-6.656],[83.184,-2.602],[78.333,-2.602],[78.333,-0.211],[97.856,-0.211]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[85.809,-9.07],[85.809,-15.07],[90.262,-15.07],[90.262,-9.07]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[86.184,-2.602],[86.184,-6.656],[89.911,-6.656],[89.911,-2.602]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[0.0706,0.0706,0.0706]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[118.732,-19.172],[115.896,-19.172],[115.896,2.156],[118.732,2.156]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[1.477,-0.906],[0,0],[-0.664,0.992],[-0.375,1.297],[-1.797,-1.062],[0,0],[0.676,1.586],[-0.008,1.93],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0.699,-1.683]],"o":[[0,0],[0.945,-0.578],[0.664,-0.993],[0.789,2.484],[0,0],[-1.469,-0.836],[-0.676,-1.586],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,1.976],[-0.7,1.684]],"v":[[99.841,-4.078],[101.646,-1.875],[104.06,-4.23],[105.618,-7.664],[109.497,-2.344],[111.255,-4.547],[108.038,-8.18],[107.036,-13.453],[107.036,-14.602],[110.271,-14.602],[110.271,-16.992],[100.661,-16.992],[100.661,-14.602],[104.153,-14.602],[104.153,-13.453],[103.105,-7.963]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[108.747,-9.445],[111.56,-9.445],[111.56,1.172],[114.372,1.172],[114.372,-18.82],[111.56,-18.82],[111.56,-11.859],[108.747,-11.859]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[0.0706,0.0706,0.0706]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0.379,-0.859],[0.773,-0.68],[1.133,-0.367],[0,0],[-0.864,0.785],[-0.492,1.07],[-0.824,-0.723],[-1.157,-0.375],[0,0],[0.742,0.644],[0.356,0.801],[0.008,0.867],[0,0]],"o":[[0,0],[0,0],[0,0],[-0.016,0.914],[-0.379,0.86],[-0.774,0.679],[0,0],[1.203,-0.391],[0.863,-0.785],[0.476,0.977],[0.824,0.723],[0,0],[-1.109,-0.352],[-0.742,-0.645],[-0.355,-0.801],[0,0],[0,0]],"v":[[130.986,-17.93],[119.361,-17.93],[119.361,-15.539],[123.72,-15.539],[123.128,-12.879],[121.4,-10.57],[118.54,-9],[120.134,-6.703],[123.234,-8.467],[125.267,-11.25],[127.218,-8.701],[130.189,-7.055],[131.712,-9.375],[128.935,-10.869],[127.288,-13.037],[126.743,-15.539],[130.986,-15.539]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[121.423,-3.023],[132.79,-3.023],[132.79,2.156],[135.79,2.156],[135.79,-5.391],[121.423,-5.391]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[132.79,-6.305],[135.79,-6.305],[135.79,-11.508],[138.673,-11.508],[138.673,-13.992],[135.79,-13.992],[135.79,-19.172],[132.79,-19.172]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[0.0706,0.0706,0.0706]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[1.047,-0.656],[0,-1.102],[-0.594,-0.574],[-1.121,-0.297],[-1.555,0],[-1.113,0.297],[-0.593,0.579],[-0.008,0.812],[1.039,0.656],[1.867,0.133],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[-1.906,0.133],[-1.047,0.656],[0,0.82],[0.594,0.575],[1.121,0.297],[1.531,0],[1.113,-0.297],[0.594,-0.578],[-0.008,-1.094],[-1.039,-0.657],[0,0],[0,0],[0,0]],"v":[[160.275,-9.492],[140.822,-9.492],[140.822,-7.078],[149.048,-7.078],[149.048,-5.508],[144.619,-4.324],[143.048,-1.687],[143.939,0.404],[146.511,1.711],[150.525,2.156],[154.492,1.711],[157.052,0.398],[157.955,-1.687],[156.384,-4.312],[152.025,-5.496],[152.025,-7.078],[160.275,-7.078]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[1.266,-0.109],[0,0],[-1.344,0.703],[-0.578,1.063],[-1.344,-0.699],[-1.977,-0.188],[0,0],[0.949,0.324],[0.558,0.457],[0.18,0.516],[0,0],[0,0],[0,0],[0,0],[0,0],[0.558,-0.453],[0.937,-0.328]],"o":[[0,0],[1.969,-0.18],[1.344,-0.703],[0.586,1.063],[1.343,0.699],[0,0],[-1.297,-0.109],[-0.95,-0.324],[-0.559,-0.457],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.187,0.516],[-0.559,0.453],[-0.938,0.328]],"v":[[141.689,-12.633],[142.673,-10.289],[147.642,-11.613],[150.525,-14.262],[153.42,-11.619],[158.4,-10.289],[159.455,-12.633],[156.086,-13.283],[153.824,-14.455],[152.716,-15.914],[158.517,-15.914],[158.517,-18.258],[142.603,-18.258],[142.603,-15.914],[148.357,-15.914],[147.238,-14.461],[144.994,-13.289]]}}},{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[-0.008,0.515],[-0.738,0.262],[-1.484,0.016],[-0.008,-1.055],[0.75,-0.273],[1.445,0],[0.746,0.274]],"o":[[-0.008,-0.54],[0.738,-0.261],[2.945,0.024],[-0.008,0.515],[-0.75,0.274],[-1.469,0],[-0.746,-0.273]],"v":[[146.095,-1.687],[147.191,-2.889],[150.525,-3.305],[154.955,-1.687],[153.818,-0.504],[150.525,-0.094],[147.203,-0.504]]}}},{"ty":"mm","mm":1},{"ty":"fl","c":{"a":0,"k":[0.0706,0.0706,0.0706]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":7},{"ty":4,"sr":1,"st":0,"op":93.66666666666667,"ip":0,"ln":"219","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[37.5,81.5,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[-150,324.5,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-37.5,81.5],[37.5,81.5],[37.5,-81.5],[-37.5,-81.5]]}}},{"ty":"fl","c":{"a":0,"k":[0.9961,0.4549,0.2078]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[37.5,81.5]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":8,"parent":22},{"ty":4,"sr":1,"st":0,"op":93.66666666666667,"ip":0,"ln":"218","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[37.5,28,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[-150,214.75,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-37.5,28],[37.5,28],[37.5,-28],[-37.5,-28]]}}},{"ty":"fl","c":{"a":0,"k":[1,0.7686,0.5961]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[37.5,28]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":9,"parent":22},{"ty":4,"sr":1,"st":0,"op":93.66666666666667,"ip":0,"ln":"217","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[37.5,62.5,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[-75,343.5,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-37.5,62.5],[37.5,62.5],[37.5,-62.5],[-37.5,-62.5]]}}},{"ty":"fl","c":{"a":0,"k":[1,0.6039,0.3098]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[37.5,62.5]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":10,"parent":22},{"ty":4,"sr":1,"st":0,"op":93.66666666666667,"ip":0,"ln":"216","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[37.5,37,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,369,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-37.5,37],[37.5,37],[37.5,-37],[-37.5,-37]]}}},{"ty":"fl","c":{"a":0,"k":[1,0.7686,0.5961]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[37.5,37]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":11,"parent":22},{"ty":4,"sr":1,"st":0,"op":93.66666666666667,"ip":0,"ln":"215","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[37.5,115.5,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[75.125,258.5,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-37.5,115.5],[37.5,115.5],[37.5,-115.5],[-37.5,-115.5]]}}},{"ty":"fl","c":{"a":0,"k":[0.9961,0.4549,0.2078]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[37.5,115.5]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":12,"parent":22},{"ty":4,"sr":1,"st":0,"op":93.66666666666667,"ip":0,"ln":"214","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[37.5,56.5,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[150,349.5,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-37.5,56.5],[37.5,56.5],[37.5,-56.5],[-37.5,-56.5]]}}},{"ty":"fl","c":{"a":0,"k":[1,0.6039,0.3098]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[37.5,56.5]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":13,"parent":22},{"ty":4,"sr":1,"st":0,"op":93.66666666666667,"ip":0,"ln":"213","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[37.5,57,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[0,274.688,0]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-37.5,57],[37.5,57],[37.5,-57],[-37.5,-57]]}}},{"ty":"fl","c":{"a":0,"k":[1,0.6039,0.3098]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[37.5,57]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":14,"parent":22},{"ty":4,"sr":1,"st":6,"op":99.66666666666667,"ip":6,"ln":"212","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[37.5,75,0]},"s":{"a":0,"k":[100,100]},"p":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[-150,-490,0],"t":6,"ti":[0,-94,0],"to":[0,94,0]},{"s":[-150,74,0],"t":33,"ti":[0,-94,0],"to":[0,94,0]}]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-37.5,75],[37.5,75],[37.5,-75],[-37.5,-75]]}}},{"ty":"fl","c":{"a":0,"k":[0.9961,0.4549,0.2078]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[37.5,75]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":15,"parent":22},{"ty":4,"sr":1,"st":21.666666666666668,"op":115.33333333333334,"ip":21.666666666666668,"ln":"211","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[37.5,54,0]},"s":{"a":0,"k":[100,100,100]},"p":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[-74.75,-465.375,0],"t":21.666666666666668,"ti":[0,-97.417,0],"to":[0,97.417,0]},{"s":[-74.75,119.125,0],"t":68.33333333333333,"ti":[0,-97.417,0],"to":[0,97.417,0]}]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-37.5,54],[37.5,54],[37.5,-54],[-37.5,-54]]}}},{"ty":"fl","c":{"a":0,"k":[1,0.6039,0.3098]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[37.5,54]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":16,"parent":22},{"ty":4,"sr":1,"st":33.333333333333336,"op":127,"ip":33.333333333333336,"ln":"210","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[37.5,32,0]},"s":{"a":0,"k":[100,100]},"p":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[0,-487.5,0],"t":33.333333333333336,"ti":[0,-87.833,0],"to":[0,87.833,0]},{"s":[0,39.5,0],"t":55,"ti":[0,-87.833,0],"to":[0,87.833,0]}]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-37.5,32],[37.5,32],[37.5,-32],[-37.5,-32]]}}},{"ty":"fl","c":{"a":0,"k":[1,0.6039,0.3098]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[37.5,32]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":17,"parent":22},{"ty":4,"sr":1,"st":30,"op":123.66666666666667,"ip":-0.33333333333333215,"ln":"209","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[37.5,37.5,0]},"s":{"a":0,"k":[100,100]},"p":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[0,105.5,0],"t":53.66666666666667,"ti":[0,-12.417,0],"to":[0,12.417,0]},{"s":[0,180,0],"t":73.66666666666666,"ti":[0,-12.417,0],"to":[0,12.417,0]}]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-37.5,37.5],[37.5,37.5],[37.5,-37.5],[-37.5,-37.5]]}}},{"ty":"fl","c":{"a":0,"k":[0.9961,0.4549,0.2078]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[37.5,37.5]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":18,"parent":22},{"ty":4,"sr":1,"st":0,"op":93.66666666666667,"ip":0,"ln":"208","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[37.5,90,0]},"s":{"a":0,"k":[100,100]},"p":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[150,127,0],"t":67.66666666666667,"ti":[0,-12.667,0],"to":[0,12.667,0]},{"s":[150,203,0],"t":83.33333333333333,"ti":[0,-12.667,0],"to":[0,12.667,0]}]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-37.5,90],[37.5,90],[37.5,-90],[-37.5,-90]]}}},{"ty":"fl","c":{"a":0,"k":[1,0.7686,0.5961]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[37.5,90]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":19,"parent":22},{"ty":4,"sr":1,"st":44.666666666666664,"op":138.33333333333334,"ip":44.666666666666664,"ln":"207","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[37.5,28,0]},"s":{"a":0,"k":[100,100]},"p":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[150,-437.25,0],"t":44.666666666666664,"ti":[0,-74.333,0],"to":[0,64,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[150,-53.25,0],"t":54,"ti":[0,-23,0],"to":[0,74.333,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[150,8.75,0],"t":67.33333333333333,"ti":[0,-12.667,0],"to":[0,23,0]},{"s":[150,84.75,0],"t":83,"ti":[0,-64,0],"to":[0,12.667,0]}]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-37.5,28],[37.5,28],[37.5,-28],[-37.5,-28]]}}},{"ty":"fl","c":{"a":0,"k":[0.9961,0.4549,0.2078]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[37.5,28]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":20,"parent":22},{"ty":1,"sr":1,"st":0,"op":93.66666666666667,"ip":0,"ln":"224","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[187.5,406]},"s":{"a":0,"k":[100,100]},"p":{"a":0,"k":[187.5,406]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"sc":"#ffffff","sh":812,"sw":375,"ind":21},{"ty":3,"sr":1,"st":0,"op":93.66666666666667,"ip":0,"ln":"206","hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"p":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[187.5,406,0],"t":11.333333333333334,"ti":[0,-6.333,0],"to":[0,6.333,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[187.5,444,0],"t":17.666666666666668},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[187.5,444,0],"t":31,"ti":[0,-6.333,0],"to":[0,6.333,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[187.5,482,0],"t":44.666666666666664},{"o":{"x":0.167,"y":0.167},"i":{"x":0.667,"y":0.667},"s":[187.5,482,0],"t":51},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[187.5,482,0],"t":78,"ti":[0,-55.833,0],"to":[0,55.833,0]},{"s":[187.5,817,0],"t":87.33333333333333,"ti":[0,-6.333,0],"to":[0,55.833,0]}]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"ind":22}],"v":"5.7.0","fr":29,"op":93.66666666666667,"ip":0,"fonts":{"list":[{"ascent":70.703125,"fClass":"","fFamily":"Pretendard","fStyle":"SemiBold","fName":"Pretendard-SemiBold","fPath":"","fWeight":"","origin":0}]},"chars":[{"ch":".","fFamily":"Pretendard","size":24,"style":"SemiBold","w":27.25,"data":{"shapes":[{"ty":"gr","it":[{"ty":"sh","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[1.1733333333333331,0.68],[0.6866666666666662,1.1733333333333331],[0,1.3666666666666665],[0,0],[-0.6866666666666669,1.1533333333333335],[-1.1666666666666667,0.6866666666666662],[-1.3666666666666671,0],[0,0],[-1.1600000000000001,-0.6866666666666662],[-0.6866666666666674,-1.1533333333333335],[0,-1.3333333333333333],[0,0],[0.6799999999999997,-1.1733333333333336],[1.1533333333333335,-0.6866666666666666],[1.3333333333333333,0],[0,0]],"o":[[-1.3666666666666671,0],[-1.1666666666666667,-0.6866666666666666],[-0.6866666666666669,-1.1733333333333336],[0,0],[0,-1.3333333333333333],[0.6866666666666662,-1.1533333333333335],[1.1733333333333331,-0.6866666666666662],[0,0],[1.3333333333333333,0],[1.1533333333333335,0.6866666666666662],[0.6799999999999997,1.1533333333333335],[0,0],[0,1.3666666666666665],[-0.6866666666666674,1.1733333333333331],[-1.1600000000000001,0.68],[0,0],[0,0]],"v":[[13.67,0.78],[9.86,-0.24],[7.08,-3.03],[6.05,-6.84],[6.05,-6.84],[7.08,-10.57],[9.86,-13.33],[13.67,-14.36],[13.67,-14.36],[17.41,-13.33],[20.17,-10.57],[21.19,-6.84],[21.19,-6.84],[20.17,-3.03],[17.41,-0.24],[13.67,0.78],[13.67,0.78]]}}}]}]}},{"ch":"\r","fFamily":"Pretendard","size":24,"style":"SemiBold","w":0}],"assets":[]} \ No newline at end of file diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/AddMeeting/View/CategorySelect.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/AddMeeting/View/CategorySelect.swift index 009ff0f6..6a5e219b 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Presentation/AddMeeting/View/CategorySelect.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/AddMeeting/View/CategorySelect.swift @@ -17,22 +17,22 @@ struct CategorySelect: View { ] var body: some View { - VStack(alignment: .leading, spacing: 0) { - TitleTextBox(title: "카테고리를 선택해주세요.", subtitle: "6가지 카테고리 중 하나를 선택할 수 있어요.") - .padding(.bottom, 28) - - LazyVGrid(columns: columns, spacing: 8) { - ForEach(CategoryState.allCases.filter { $0 != .ALL }, id: \.self) { category in - CategoryImageButton( - category: category, - isSelected: viewModel.selectedCategory == category, - onTap: { - viewModel.selectedCategory = category - }) - } + VStack(alignment: .leading, spacing: 0) { + TitleTextBox(title: "카테고리를 선택해주세요.", subtitle: "6가지 카테고리 중 하나를 선택할 수 있어요.") + .padding(.bottom, 28) + + LazyVGrid(columns: columns, spacing: 8) { + ForEach(CategoryState.allCases.filter { $0 != .ALL }, id: \.self) { category in + CategoryImageButton( + category: category, + isSelected: viewModel.selectedCategory == category, + onTap: { + viewModel.selectedCategory = category + }) } } - .padding(.horizontal, 16) + } + .padding(.horizontal, 16) } } diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/Filling/Model/FillingModel.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Filling/Model/FillingModel.swift index a7766dbe..df61ab25 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Presentation/Filling/Model/FillingModel.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Filling/Model/FillingModel.swift @@ -8,9 +8,10 @@ import Foundation struct Meeting { + let groupId: Int let status: String let category: String - let coverImg: String + let coverImg: Int let groupType: String let groupTitle: String let weekDay: String? @@ -19,150 +20,3 @@ struct Meeting { let endTime: Double let location: String } - -let dummyMeetings: [Meeting] = [ - Meeting( - status: "RECRUITING", - category: "스터디", - coverImg: "sample", - groupType: "WEEKLY", - groupTitle: "iOS 개발 스터디", - weekDay: "MON", - weekDate: nil, - startTime: 19.0, - endTime: 21.0, - location: "강남 카페" - ), - Meeting( - status: "모집 완료", - category: "운동", - coverImg: "sample", - groupType: "ONE_TIME", - groupTitle: "주말 테니스 모임", - weekDay: nil, - weekDate: "2025-01-20", - startTime: 10.0, - endTime: 12.0, - location: "서울숲 테니스장" - ), - Meeting( - status: "모집 중", - category: "독서", - coverImg: "sample", - groupType: "WEEKLY", - groupTitle: "한 달 한 권 독서 모임", - weekDay: "THU", - weekDate: nil, - startTime: 18.5, - endTime: 20.5, - location: "홍대 독서 모임 공간" - ), - Meeting( - status: "진행 중", - category: "요리", - coverImg: "sample", - groupType: "ONE_TIME", - groupTitle: "이탈리안 요리 클래스", - weekDay: nil, - weekDate: "2025-02-10", - startTime: 14.0, - endTime: 16.0, - location: "이태원 쿠킹 스튜디오" - ), - Meeting( - status: "모집 중", - category: "게임", - coverImg: "sample", - groupType: "WEEKLY", - groupTitle: "보드게임 같이 할 사람!", - weekDay: "TUE", - weekDate: nil, - startTime: 16.0, - endTime: 19.0, - location: "신촌 보드게임 카페" - ), - Meeting( - status: "모집 중", - category: "음악", - coverImg: "sample", - groupType: "WEEKLY", - groupTitle: "밴드 합주 모임", - weekDay: "FRI", - weekDate: nil, - startTime: 20.0, - endTime: 22.0, - location: "홍대 음악 스튜디오" - ), - Meeting( - status: "진행 중", - category: "여행", - coverImg: "sample", - groupType: "ONE_TIME", - groupTitle: "국내 여행 번개 모집", - weekDay: nil, - weekDate: "2025-03-05", - startTime: 7.0, - endTime: 22.0, - location: "서울 출발 - 강릉 여행" - ), - Meeting( - status: "모집 중", - category: "운동", - coverImg: "sample", - groupType: "WEEKLY", - groupTitle: "아침 요가 클래스", - weekDay: "WED", - weekDate: nil, - startTime: 7.0, - endTime: 8.0, - location: "한강 공원" - ), - Meeting( - status: "모집 완료", - category: "IT", - coverImg: "sample", - groupType: "ONE_TIME", - groupTitle: "SwiftUI 기초 세미나", - weekDay: nil, - weekDate: "2025-02-15", - startTime: 13.0, - endTime: 16.0, - location: "강남 테크 컨퍼런스 룸" - ), - Meeting( - status: "모집 중", - category: "문화", - coverImg: "sample", - groupType: "ONE_TIME", - groupTitle: "미술관 탐방 모임", - weekDay: nil, - weekDate: "2025-04-10", - startTime: 14.0, - endTime: 17.0, - location: "리움 미술관" - ), - Meeting( - status: "진행 중", - category: "봉사", - coverImg: "sample", - groupType: "WEEKLY", - groupTitle: "유기동물 보호소 봉사", - weekDay: "MON", - weekDate: nil, - startTime: 10.0, - endTime: 13.0, - location: "서울 유기견 보호소" - ), - Meeting( - status: "모집 중", - category: "영화", - coverImg: "sample", - groupType: "ONE_TIME", - groupTitle: "영화 같이 보기 - 오펜하이머", - weekDay: nil, - weekDate: "2025-05-18", - startTime: 18.0, - endTime: 21.0, - location: "CGV 용산 IMAX" - ) -] diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/Filling/View/FillingList.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Filling/View/FillingList.swift index 78681c6c..31bd8134 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Presentation/Filling/View/FillingList.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Filling/View/FillingList.swift @@ -44,3 +44,32 @@ struct FillingList: View { #Preview { FillingList() } + +let dummyMeetings: [Meeting] = [ + Meeting( + groupId: 1, + status: "RECRUITING", + category: "STUDY", + coverImg: 1, + groupType: "WEEKLY", + groupTitle: "공강팅", + weekDay: "MON", + weekDate: nil, + startTime: 10.5, + endTime: 12.0, + location: "학교 정문" + ), + Meeting( + groupId: 2, + status: "RECRUITIED", + category: "PLAYING", + coverImg: 3, + groupType: "ONCE", + groupTitle: "공강팅", + weekDay: "TUE", + weekDate: "2025-12-11", + startTime: 10.5, + endTime: 12.0, + location: "학교 정문" + ) +] diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/Home/Model/MeetingModel.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Home/Model/MeetingModel.swift new file mode 100644 index 00000000..b7f54552 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Home/Model/MeetingModel.swift @@ -0,0 +1,165 @@ +// +// MeetingModel.swift +// Gongbaek_iOS +// +// Created by 김나연 on 1/21/25. +// + +import Foundation + +struct MeetingModel { + let groupId: Int + let category: String + let coverImg: Int + let profileImg: Int + let groupType: String + let groupTitle: String + let weekDate: String + let groupDate: String? + let startTime: Double + let endTime: Double + let location: String +} + +extension MeetingModel { + + static func weeklyMeetingList() -> [MeetingModel] { + [ + MeetingModel( + groupId: 0, + category: "DINING", + coverImg: 4, + profileImg: 2, + groupType: "WEEKLY", + groupTitle: "같이 저녁 먹을 사람들 구합니다", + weekDate: "FRI", + groupDate: nil, + startTime: 17.0, + endTime: 18.0, + location: "학교 정문 앞" + ), + MeetingModel( + groupId: 1, + category: "STUDY", + coverImg: 2, + profileImg: 5, + groupType: "WEEKLY", + groupTitle: "웹프 들으시는분 같이 과제해요ㅜㅜ", + weekDate: "THU", + groupDate: nil, + startTime: 11.5, + endTime: 13.0, + location: "이디야/스터디룸" + ), + MeetingModel( + groupId: 2, + category: "PLAYING", + coverImg: 5, + profileImg: 2, + groupType: "WEEKLY", + groupTitle: "🤭 보드게임 좋아하는 사람들 모임", + weekDate: "TUE", + groupDate: nil, + startTime: 13.5, + endTime: 16.0, + location: "레드버튼 보드게임카페" + ), + MeetingModel( + groupId: 3, + category: "NETWORKING", + coverImg: 1, + profileImg: 1, + groupType: "WEEKLY", + groupTitle: "매주 만나서 수다떨고 친해져욥", + weekDate: "MON", + groupDate: nil, + startTime: 15.0, + endTime: 16.0, + location: "근처 카페" + ), + MeetingModel( + groupId: 4, + category: "EXERCISE", + coverImg: 3, + profileImg: 2, + groupType: "WEEKLY", + groupTitle: "30분 뒤에 농구하러 오실분", + weekDate: "WED", + groupDate: nil, + startTime: 14.0, + endTime: 16.0, + location: "공학관 옆 농구장" + ) + ] + } + + static func oneTimeMeetingList() -> [MeetingModel] { + [ + MeetingModel( + groupId: 0, + category: "DINING", + coverImg: 4, + profileImg: 2, + groupType: "ONCE", + groupTitle: "같이 저녁 먹을 사람들 구합니다", + weekDate: "FRI", + groupDate: "2025-04-07", + startTime: 17.0, + endTime: 18.0, + location: "학교 정문 앞" + ), + MeetingModel( + groupId: 1, + category: "STUDY", + coverImg: 2, + profileImg: 5, + groupType: "ONCE", + groupTitle: "시험기간 모각작인데 개빡세게하실분 모집", + weekDate: "THU", + groupDate: "2025-04-14", + startTime: 11.5, + endTime: 13.0, + location: "이디야/스터디룸" + ), + MeetingModel( + groupId: 2, + category: "PLAYING", + coverImg: 5, + profileImg: 2, + groupType: "ONCE", + groupTitle: "🤭 보드게임 좋아하는 사람들 모임", + weekDate: "TUE", + groupDate: "2025-03-16", + startTime: 13.5, + endTime: 16.0, + location: "레드버튼 보드게임카페" + ), + MeetingModel( + groupId: 3, + category: "NETWORKING", + coverImg: 1, + profileImg: 1, + groupType: "ONCE", + groupTitle: "친구없는 모임.....친해져욥", + weekDate: "MON", + groupDate: "2025-03-30", + startTime: 15.0, + endTime: 16.0, + location: "근처 카페" + ), + MeetingModel( + groupId: 4, + category: "EXERCISE", + coverImg: 3, + profileImg: 2, + groupType: "ONCE", + groupTitle: "30분 뒤에 농구하러 오실분", + weekDate: "WED", + groupDate: "2025-06-30", + startTime: 14.0, + endTime: 16.0, + location: "공학관 옆 농구장" + ) + ] + } +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/Home/Model/PerfectMatchMemberModel.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Home/Model/PerfectMatchMemberModel.swift new file mode 100644 index 00000000..ac19cbe2 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Home/Model/PerfectMatchMemberModel.swift @@ -0,0 +1,41 @@ +// +// PerfectMatchMemberModel.swift +// Gongbaek_iOS +// +// Created by 김나연 on 1/21/25. +// + +import Foundation + +struct PerfectMatchMemberModel { + let profileImage: Int + let nickname: String + let sex: String + let major: String +} + +extension PerfectMatchMemberModel { + + static func mockData() -> [PerfectMatchMemberModel] { + [ + PerfectMatchMemberModel( + profileImage: 1, + nickname: "나여니", + sex: "WOMAN", + major: "컴퓨터공학과" + ), + PerfectMatchMemberModel( + profileImage: 4, + nickname: "아름다웠던그대다시볼수있다면", + sex: "MAN", + major: "클래식피아노전공" + ), + PerfectMatchMemberModel( + profileImage: 5, + nickname: "목청좋은아이", + sex: "WOMAN", + major: "성악과" + ) + ] + } +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/Home/View/HomeView.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Home/View/HomeView.swift index bb4e3fdd..7b197659 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Presentation/Home/View/HomeView.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Home/View/HomeView.swift @@ -9,9 +9,173 @@ import SwiftUI struct HomeView: View { @EnvironmentObject var navigationManager: NavigationManager + @StateObject var viewModel = HomeViewModel() var body: some View { - Text("홈") + GeometryReader { geometry in + ScrollView { + VStack(spacing: 34) { + header(geometry) + meetingList( + title: "공강시간에 정기적인 활동 어때요?", + subtitle: viewModel.nickname + "님과 딱 맞는 매주 봐요 모임 추천이에요.", + highlightText: "매주 봐요", + isWeekly: true + ) + meetingList( + title: "한번만 만나도 특별할 우리", + subtitle: "한번만 봐요 모임으로 잊지 못할 추억을 만들어보세요!", + highlightText: "한번만 봐요", + isWeekly: false + ) + banner() + perfectMatchMember() + } + } + .ignoresSafeArea(edges: .top) + } + } + + private func header(_ geometry: GeometryProxy) -> some View { + ZStack(alignment: .bottomTrailing) { + VStack(alignment: .leading, spacing: 88) { + schoolNameBar() + + VStack(alignment: .leading, spacing: 6) { + Text("다가오는 모임") + .pretendardFont(.caption1_sb_13) + .foregroundStyle(.mainOrange) + + meetingInfo() + } + } + .padding(.top, geometry.safeAreaInsets.top + 14) + + enterSpaceButton() + } + .padding(.horizontal, 16) + .padding(.bottom, 26) + .background( + Image(.imgHomeMain) + .resizable() + ) + } + + private func meetingList( + title: String, + subtitle: String, + highlightText: String, + isWeekly: Bool + ) -> some View { + VStack(alignment: .leading, spacing: 16) { + HStack { + HomeTitleTextBox( + title: title, + subtitle: subtitle, + highlightSubtitleText: highlightText + ) + .padding(.horizontal, 16) + + Spacer() + } + + ScrollView(.horizontal, showsIndicators: false) { + LazyHStack(spacing: 10) { + ForEach(viewModel.weeklyMeetingList, id: \.groupId) { data in + HomeMeetingCell( + data: data, + isWeekly: isWeekly + ) + .onTapGesture { + // TODO: 모임 상세 화면 내비게이션 이동 + } + } + } + .padding(.horizontal, 16) + } + } + } + + private func banner() -> some View { + Image(.imgHomeBanner) + .resizable() + .scaledToFill() + .padding(.top, 2) + } + + private func perfectMatchMember() -> some View { + VStack(alignment: .leading, spacing: 16) { + HStack { + HomeTitleTextBox( + title: "나와 딱 맞는 공백 멤버", + subtitle: "공백 시간에 이 멤버들과 공백 활동 어때요?" + ) + + Spacer() + } + + LazyVStack(spacing: 0) { + ForEach(viewModel.perfectMatchMemberList, id: \.nickname) { data in + HomeMatchMemberListCell(data: data) + } + } + } + .padding(.horizontal, 16) + } + + private func schoolNameBar() -> some View { + HStack { + Image(.icSchool20) + .renderingMode(.original) + .scaledToFit() + .frame(width: 20, height: 20) + + Text("건국대학교 서울캠퍼스") + .pretendardFont(.body1_m_16) + .foregroundStyle(.gray03) + + Spacer() + + Image(.icNotification20) + .renderingMode(.original) + .scaledToFit() + .frame(width: 20, height: 20) + } + } + + private func meetingInfo() -> some View { + VStack(alignment: .leading, spacing: 12) { + Text("화석의 튜스데이 점심클럽") + .pretendardFont(.title1_b_20) + .foregroundStyle(.grayWhite) + + HStack(spacing: 4) { + Image(.icTime16) + .renderingMode(.original) + .scaledToFit() + .frame(width: 16, height: 16) + + Text("12/6 수요일 14시 30분 - 16시 20분") + .pretendardFont(.caption2_m_12) + .foregroundStyle(.gray05) + } + } + } + + private func enterSpaceButton() -> some View { + Button { + // TODO: 모임방 내비게이션 화면 이동 + } label: { + Text("스페이스 입장") + .pretendardFont(.caption2_b_12) + .foregroundStyle(.grayWhite) + .padding(.horizontal, 10) + .padding(.vertical, 6) + } + .background(.mainOrange) + .clipShape( + RoundedRectangle(cornerRadius: 4) + ) } } diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/Home/ViewModel/.gitkeep b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Home/ViewModel/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/Home/ViewModel/HomeViewModel.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Home/ViewModel/HomeViewModel.swift new file mode 100644 index 00000000..a2597a57 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Home/ViewModel/HomeViewModel.swift @@ -0,0 +1,21 @@ +// +// HomeViewModel.swift +// Gongbaek_iOS +// +// Created by 김나연 on 1/21/25. +// + +import SwiftUI + +final class HomeViewModel: ObservableObject { + + // 헤더 + @Published var schoolName = "" + @Published var nickname = "아요옹나요옹뾰오옹" + // 매주봐요 모임 + @Published var weeklyMeetingList: [MeetingModel] = MeetingModel.weeklyMeetingList() + // 한번봐요 모임 + @Published var oneTimeMeetingList: [MeetingModel] = MeetingModel.weeklyMeetingList() + // 나와 딱 맞는 멤버 (API 연결 X) + let perfectMatchMemberList: [PerfectMatchMemberModel] = PerfectMatchMemberModel.mockData() +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/MeetingDetail/View/MeetingDetailView.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MeetingDetail/View/MeetingDetailView.swift index 0cc58ebc..e76561c8 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Presentation/MeetingDetail/View/MeetingDetailView.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MeetingDetail/View/MeetingDetailView.swift @@ -17,9 +17,9 @@ struct MeetingDetailView: View { MeetingInfoBase( state: .constant(.detail), meeting: .constant(Meeting( - status: meetingDetailData.status, + groupId: 0, status: meetingDetailData.status, category: meetingDetailData.category, - coverImg: "sample",//TODO: Int로 넘기기 meetingDetailData.coverImg, + coverImg: 5,//TODO: Int로 넘기기 meetingDetailData.coverImg, groupType: meetingDetailData.groupType, groupTitle: meetingDetailData.groupTitle, weekDay: meetingDetailData.weekDay, diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/MeetingDetail/View/MeetingInfoView.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MeetingDetail/View/MeetingInfoView.swift index 5cdf7f5e..c85012cd 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Presentation/MeetingDetail/View/MeetingInfoView.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MeetingDetail/View/MeetingInfoView.swift @@ -16,7 +16,6 @@ struct MeetingInfoView: View { @Binding var isHost: Bool @Binding var isApply: Bool @State private var selectedIndex = 0 - var buttonText: String = "신청하기" var body: some View { ZStack(alignment: .bottom) { @@ -68,14 +67,14 @@ struct MeetingInfoView: View { // isHost == false >>> isApply == true >>> buttonText = "취소하기" // onTap = "isApply = false" ApplyBar( - applyData: .init( - isActivated: true, // closed일 때만 false <<< meetingStatus + applyData: .constant(ApplyModel( currentPeopleCount: currentPeopleCount, maxPeopleCount: maxPeopleCount, - buttonText: "신청하기", // buttonText 변환 로직 필요 <<< meetingStatus - onTap: nil + isHost: isHost, + meetingStatus: meetingStatus, + isApply: isApply ) - ) + )) } } } diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/MeetingRoom/View/MeetingRoomView.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MeetingRoom/View/MeetingRoomView.swift index d2b4d028..05be2c49 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Presentation/MeetingRoom/View/MeetingRoomView.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MeetingRoom/View/MeetingRoomView.swift @@ -8,9 +8,7 @@ import SwiftUI struct MeetingRoomView: View { - @State var meetingDetailData: MeetingDetailModel - @State var memberData: MeetingRoomMemberModel - @State var commentData: CommentModel + @StateObject var viewModel: MeetingRoomViewModel var body: some View { VStack { @@ -18,24 +16,14 @@ struct MeetingRoomView: View { VStack(spacing: 0) { VStack(alignment: .leading, spacing: 0) { HStack(spacing: 5) { - let states: [MeetingChipState] = [ - RecruitingState(meetingDetailData.status).map { .recruiting($0) }, - CategoryState(meetingDetailData.category).map { .category($0) }, - GroupState(meetingDetailData.groupType).map { .weekly($0) } - ].compactMap { $0 } - - if states.isEmpty { - // TODO: 디코딩 에러대응뷰 - } else { - ForEach(states.indices, id: \.self) { index in - MeetingChip(state: states[index]) - } + ForEach(viewModel.meetingStates.indices, id: \.self) { index in + MeetingChip(state: viewModel.meetingStates[index]) } } .padding(.top, 18) .padding(.bottom, 6) - Text(meetingDetailData.groupTitle) + Text(viewModel.meetingDetailData.groupTitle) .pretendardFont(.title1_b_20) .foregroundColor(.grayWhite) .lineLimit(nil) @@ -44,21 +32,16 @@ struct MeetingRoomView: View { TimeBox( state: .white, text: Date.formattedDateAndStartEndTime( - weekDay: WeekDay(meetingDetailData.weekDay), - weekDate: meetingDetailData.weekDate, - startTime: meetingDetailData.startTime, - endTime: meetingDetailData.endTime + weekDay: WeekDay(viewModel.meetingDetailData.weekDay), + weekDate: viewModel.meetingDetailData.weekDate, + startTime: viewModel.meetingDetailData.startTime, + endTime: viewModel.meetingDetailData.endTime ), - font: .pretendard( - .caption2_r_12 - ) - ) - .padding( - .bottom, - 2 + font: .pretendard(.caption2_r_12) ) + .padding(.bottom, 2) - LocationBox(state: .white, text: meetingDetailData.location, font: .pretendard(.caption2_r_12)) + LocationBox(state: .white, text: viewModel.meetingDetailData.location, font: .pretendard(.caption2_r_12)) } .padding(.horizontal, 16) .padding(.bottom, 16) @@ -76,7 +59,7 @@ struct MeetingRoomView: View { .frame(width: 18, height: 18) .foregroundStyle(.gray06) - Text("멤버 (\(meetingDetailData.currentPeopleCount)/\(meetingDetailData.maxPeopleCount)명)") + Text(viewModel.memberCount) .pretendardFont(.title2_sb_18) .foregroundStyle(.gray10) } @@ -89,8 +72,8 @@ struct MeetingRoomView: View { ScrollView(.horizontal, showsIndicators: false) { HStack(spacing: 6) { - ForEach(memberData.members.indices, id: \.self) { index in - MemberProfileBox(memberData: $memberData.members[index]) + ForEach($viewModel.memberData.members.indices, id: \.self) { index in + MemberProfileBox(memberData: $viewModel.memberData.members[index]) } } .padding(.horizontal, 9) @@ -100,17 +83,17 @@ struct MeetingRoomView: View { divider() - RecruitingState(commentData.groupStatus) == .CLOSED ? CommentDisabledBox() : nil + viewModel.isCommentDisabled ? CommentDisabledBox() : nil CommentList( - commentCount: $commentData.commentCount, - comments: $commentData.comments, + commentCount: $viewModel.commentData.commentCount, + comments: $viewModel.commentData.comments, isScrolled: false, onTapRefreshButton: nil ) } } - RecruitingState(commentData.groupStatus) == .CLOSED ? nil : CommentTextField() + viewModel.isCommentDisabled ? nil : CommentTextField() } } @@ -118,11 +101,3 @@ struct MeetingRoomView: View { Color.gray02.frame(height: 8) } } - -#Preview { - MeetingRoomView( - meetingDetailData: dummymeetingDetailData, - memberData: dummyMeetingRoomMemberData, - commentData: dummyMeetingRoomCommentData - ) -} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/MeetingRoom/ViewModel/MeetingRoomViewModel.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MeetingRoom/ViewModel/MeetingRoomViewModel.swift new file mode 100644 index 00000000..15872926 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MeetingRoom/ViewModel/MeetingRoomViewModel.swift @@ -0,0 +1,34 @@ +// +// MeetingRoomViewModel.swift +// Gongbaek_iOS +// +// Created by 김희은 on 1/22/25. +// + +import SwiftUI + +final class MeetingRoomViewModel: ObservableObject { + @Published var meetingDetailData: MeetingDetailModel = dummymeetingDetailData + @Published var memberData: MeetingRoomMemberModel = dummyMeetingRoomMemberData + @Published var commentData: CommentModel = dummyCommentData + + var meetingStates: [MeetingChipState] { + [ + RecruitingState(meetingDetailData.status).map { .recruiting($0) }, + CategoryState(meetingDetailData.category).map { .category($0) }, + GroupState(meetingDetailData.groupType).map { .weekly($0) } + ].compactMap { $0 } + } + + var memberCount: String { + "멤버(\(meetingDetailData.currentPeopleCount)/\(meetingDetailData.maxPeopleCount)명)" + } + + var isCommentDisabled: Bool { + RecruitingState(commentData.groupStatus) == .CLOSED + } + + //TODO: 댓글 작성 API 로직 필요 + func postComment(content: String, completion: @escaping (Bool) -> Void) { + } +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/MyFilling/MyFillingViewModel.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MyFilling/MyFillingViewModel.swift new file mode 100644 index 00000000..d59c1524 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MyFilling/MyFillingViewModel.swift @@ -0,0 +1,52 @@ +// +// MyFillingViewModel.swift +// Gongbaek_iOS +// +// Created by 김민서 on 1/21/25. +// + +import SwiftUI + +class MyFillingViewModel: ObservableObject { + @Published var activeMeetings: [Meeting] = [] + @Published var endedMeetings: [Meeting] = [] + + @Published var isActiveEmpty: Bool = false + @Published var isEndedEmpty: Bool = false + + init() { + fetchMeetings(category: .register) + } + + + // func loadMeetings() { + // let allMeetings = dummyMeetings + // + // self.activeMeetings = allMeetings.filter { $0.status == "RECRUITING" || $0.status == "RECRUITED" } + // self.endedMeetings = allMeetings.filter { $0.status == "CLOSED" } + // + // isActiveEmpty = activeMeetings.isEmpty + // isEndedEmpty = endedMeetings.isEmpty + // } + + func fetchMeetings(category: MyFillingType) { + let dispatchGroup = DispatchGroup() + var activeMeetings: [Meeting] = [] + var endedMeetings: [Meeting] = [] + + + // TargetType의 getMeetings의 category: MyfillType / status: Bool + + + // ✅ 진행 중인 모임 요청 -> status: true + + // ✅ 종료된 모임 요청 -> status: false + + + // 모든 API 요청이 끝난 후 데이터 업데이트 + //self.activeMeetings = activeMeetings + //self.endedMeetings = endedMeetings + } +} + + diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/MyFilling/View/MyFillingEmptyCell.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MyFilling/View/MyFillingEmptyCell.swift new file mode 100644 index 00000000..a8265065 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MyFilling/View/MyFillingEmptyCell.swift @@ -0,0 +1,38 @@ +// +// EmptyCell.swift +// Gongbaek_iOS +// +// Created by 김민서 on 1/21/25. +// + +import SwiftUI + +enum MyFillingEmptyState { + case active + case end +} + +struct MyFillingEmptyCell: View { + let state: MyFillingEmptyState + + var body: some View { + VStack(spacing: 4) { + Image(state == .active ? .imgMyFillEmptyActive : .imgMyFillEmptyEnd) + .resizable() + .scaledToFit() + .frame(width: 74, height: 58) + .foregroundColor(.gray06) + + Text(state == .active ? "현재 활동중인 모임이 없어요." : "종료된 모임이 없어요.") + .pretendardFont(.caption1_m_13) + .foregroundColor(.gray08) + } + .padding(.vertical, 35) + .frame(maxWidth: .infinity) + .background(.gray01) + .cornerRadius(4) + .padding(.vertical, 12) + .padding(.horizontal, 16) + } +} + diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/MyFilling/View/MyFillingHeader.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MyFilling/View/MyFillingHeader.swift new file mode 100644 index 00000000..3179b04a --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MyFilling/View/MyFillingHeader.swift @@ -0,0 +1,27 @@ +// +// MyFillingHeader.swift +// Gongbaek_iOS +// +// Created by 김민서 on 1/21/25. +// + +import SwiftUI + +struct MyFillingHeader: View { + let icon: ImageResource + let title: String + + var body: some View { + HStack(spacing: 4) { + Image(icon) + .renderingMode(.original) + .frame(width: 18, height: 18) + Text(title) + .font(.pretendard(.title2_sb_18)) + } + .padding(.top, 28) + .padding(.bottom, 6) + .padding(.horizontal, 16) + } +} + diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/MyFilling/View/MyFillingList.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MyFilling/View/MyFillingList.swift new file mode 100644 index 00000000..d5073a7a --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MyFilling/View/MyFillingList.swift @@ -0,0 +1,42 @@ +// +// MyRecruit.swift +// Gongbaek_iOS +// +// Created by 김민서 on 1/18/25. +// + +import SwiftUI + +struct MyFillingList: View { + @ObservedObject var viewModel = MyFillingViewModel() + + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: 0) { + MyFillingHeader(icon: .icFire18, title: "현재 활동중인 모임") + if viewModel.activeMeetings.isEmpty { + MyFillingEmptyCell(state: .active) + } else { + ForEach(viewModel.activeMeetings, id: \.groupId) { meeting in + MeetingInfoCell(meeting: meeting, state: .myFill) + } + } + + MyFillingHeader(icon: .icLock18, title: "종료된 모임") + if viewModel.endedMeetings.isEmpty { + MyFillingEmptyCell(state: .end) + } else { + ForEach(viewModel.endedMeetings, id: \.groupId) { meeting in + MeetingInfoCell(meeting: meeting, state: .myFill) + } + } + } + } + } +} + +#Preview { + MyFillingList() +} + + diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/MyFilling/View/MyFillingView.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MyFilling/View/MyFillingView.swift new file mode 100644 index 00000000..215208b6 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/MyFilling/View/MyFillingView.swift @@ -0,0 +1,19 @@ +// +// MyFillingView.swift +// Gongbaek_iOS +// +// Created by 김민서 on 1/18/25. +// + +import SwiftUI + +struct MyFillingView: View { + var body: some View { + MyFillSegmentControlBar(viewModel: MyFillingViewModel()) + .customNavigationBar(title: "나의 채움") + } +} + +#Preview { + MyFillingView() +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/Onboarding/OnboardingIndicator.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Onboarding/OnboardingIndicator.swift new file mode 100644 index 00000000..98bbbbc4 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Onboarding/OnboardingIndicator.swift @@ -0,0 +1,26 @@ +// +// OnboardingIndicator.swift +// Gongbaek_iOS +// +// Created by 김민서 on 1/22/25. +// + +import SwiftUI + +struct OnboardingIndicator: View { + let pageCount: Int + let currentPage: Int + + var body: some View { + HStack(spacing: 6) { + ForEach(0.. 0 { + Button(action: { + withAnimation { currentPage -= 1 } + }) { + Image(.icArrowLeft48) + .foregroundColor(.gray04) + .frame(width: 48, height: 48) + } + } else { + Spacer().frame(width: 48, height: 48) + } + Spacer() + } + .padding(.bottom, 54) + } +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/Onboarding/OnboardingPageView.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Onboarding/OnboardingPageView.swift new file mode 100644 index 00000000..cabafbda --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Onboarding/OnboardingPageView.swift @@ -0,0 +1,30 @@ +// +// OnboardingPageView.swift +// Gongbaek_iOS +// +// Created by 김민서 on 1/22/25. +// + +import SwiftUI + +struct OnboardingPageView: View { + let page: OnboardingPage + + var body: some View { + VStack(alignment: .leading, spacing: 0) { + TitleTextBox( + title: page.title, + subtitle: page.subtitle, + highlightSubtitleText: page.highlight + ) + .padding(.bottom, 54) + + Image(page.image) + .resizable() + .scaledToFit() + .frame(maxWidth: .infinity) + } + .padding(.horizontal, 16) + .frame(maxWidth: .infinity, alignment: .leading) + } +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/Onboarding/OnboardingView.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Onboarding/OnboardingView.swift new file mode 100644 index 00000000..34c84561 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Onboarding/OnboardingView.swift @@ -0,0 +1,77 @@ +// +// OnBoardingView.swift +// Gongbaek_iOS +// +// Created by 김민서 on 1/20/25. +// + +import SwiftUI + +struct OnboardingPage { + let title: String + let subtitle: String + let highlight: String + let image: String +} + +struct OnboardingView: View { + @State private var currentPage = 0 + + private let pages: [OnboardingPage] = [ + OnboardingPage( + title: "공강시간에 원하는 모임 만들기", + subtitle: "공강이라는 공백, 어떻게 채우고 있나요?\n이제 같은 캠퍼스 친구들과 특별하게 채워보세요.", + highlight: "공강이라는 공백,", + image: "img_onboarding_1" + ), + OnboardingPage( + title: "모임 신청하고 함께 활동하기", + subtitle: "채우기 탭에서 원하는 모임을 신청하고,\n0이었던 공백을 100으로 알차게 채워보세요!", + highlight: "0이었던 공백을 100으로", + image: "img_onboarding_2" + ), + OnboardingPage( + title: "스페이스에서 모임 멤버와 대화하기", + subtitle: "공백을 함께 채울 맴버들과\n스페이스에서 대화하며 모임을 준비해보세요!", + highlight: "스페이스에서 대화하며", + image: "img_onboarding_3" + ) + ] + + var body: some View { + VStack(alignment: .leading, spacing: 0) { + OnboardingNavigation(currentPage: $currentPage, pageCount: pages.count) + + VStack(spacing: 0) { + TabView(selection: $currentPage) { + ForEach(pages.indices, id: \..self) { index in + OnboardingPageView(page: pages[index]) + .tag(index) + } + } + .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) + + OnboardingIndicator(pageCount: pages.count, currentPage: currentPage) + + BasicButton( + text: currentPage == pages.count - 1 ? "시작하기" : "다음", + onTap: { + withAnimation { + if currentPage < pages.count - 1 { + currentPage += 1 + } else { + print("온보딩 완료 시 작업") + } + } + } + ) + .padding(.horizontal, 16) + .frame(height: 94) + } + } + } +} + +#Preview { + OnboardingView() +} diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/Signup/View/SignupView.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Signup/View/SignupView.swift index 85948513..d122432a 100644 --- a/Gongbaek_iOS/Gongbaek_iOS/Presentation/Signup/View/SignupView.swift +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Signup/View/SignupView.swift @@ -11,59 +11,74 @@ struct SignupView: View { @EnvironmentObject private var navigationManager: NavigationManager @StateObject private var viewModel = SignupViewModel() @State private var currentStep: SignupStep = .profileSelection + @State private var showLottie = false var body: some View { - VStack(spacing: 0) { - if currentStep != .signupCompletion { - ProgressBar(currentIndex: currentStep.rawValue) - } - - /// currentStepIndex에 따라 변경되는 View - currentStep.view( - viewModel: viewModel, - navigationManager: navigationManager - ) - - Spacer() - - if currentStep == .freeTimeTableConversion { - OnboardingConfirmBar( - grayButtonText: "시간표 변경", - orangeButtonText: "가입 완료", - onTapGrayButton: { pop() }, - onTapOrangeButton: { signup() } + if showLottie { + LottieView(animationName: "timetable", loopMode: .playOnce) + .ignoresSafeArea(edges: [.horizontal, .bottom]) + .scaledToFill() + } else { + VStack(spacing: 0) { + if currentStep != .signupCompletion { + ProgressBar(currentIndex: currentStep.rawValue) + } + + /// currentStepIndex에 따라 변경되는 View + currentStep.view( + viewModel: viewModel, + navigationManager: navigationManager ) - } else { - BasicButton( - text: currentStep == .signupCompletion - ? "공백 채우러 가기" : "다음", - isActivated: viewModel.isNextButtonEnabled(currentStep) - ) { - if currentStep == .nicknameInput { - validateNickname() - } else { - push() + + Spacer() + + if currentStep == .freeTimeTableConversion { + OnboardingConfirmBar( + grayButtonText: "시간표 변경", + orangeButtonText: "가입 완료", + onTapGrayButton: { goBackToPreviousStep() }, + onTapOrangeButton: { signup() } + ) + } else { + BasicButton( + text: currentStep == .signupCompletion + ? "공백 채우러 가기" : "다음", + isActivated: viewModel.isNextButtonEnabled(currentStep) + ) { + if currentStep == .nicknameInput { + validateNickname() + else if currentStep == .signupCompletion { + goToTabBarView() + } else { + goToNextStep() + } } + .padding(.horizontal, 16) + .padding(.bottom, 20) } - .padding(.horizontal, 16) - .padding(.bottom, 20) } - } - .customNavigationBar( - showBackButton: - !(currentStep == .profileSelection - || currentStep == .signupCompletion), - onBackButtonTap: { - pop() + .onChange(of: currentStep) { oldValue, newValue in + if newValue == .freeTimeTableConversion { + showLottieAnimation() + } } - ) + .customNavigationBar( + showBackButton: + !(currentStep == .profileSelection + || currentStep == .freeTimeTableConversion + || currentStep == .signupCompletion), + onBackButtonTap: { + goBackToPreviousStep() + } + ) + } } } extension SignupView { - private func push() { - /// 다음 뷰 기존 상태값 리셋 + private func goToNextStep() { + /// 다음 뷰 기존 상태값 리셋 if currentStep != .signupCompletion { let nextStep = SignupStep.allCases[currentStep.rawValue + 1] viewModel.resetState(at: nextStep) @@ -71,9 +86,24 @@ extension SignupView { } } - private func pop() { + private func goBackToPreviousStep() { currentStep = .allCases[currentStep.rawValue - 1] } + + private func goToTabBarView() { + withAnimation(.easeInOut(duration: 0.3)) { + navigationManager.rootView = .tabBar + } + } + + private func showLottieAnimation() { + showLottie = true + DispatchQueue.main.asyncAfter(deadline: .now() + 3) { + withAnimation { + showLottie = false + } + } + } } /// API Functions diff --git a/Gongbaek_iOS/Gongbaek_iOS/Presentation/Splash/SplashView.swift b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Splash/SplashView.swift new file mode 100644 index 00000000..22301ff7 --- /dev/null +++ b/Gongbaek_iOS/Gongbaek_iOS/Presentation/Splash/SplashView.swift @@ -0,0 +1,21 @@ +// +// SplashView.swift +// Gongbaek_iOS +// +// Created by 김나연 on 1/22/25. +// + +import SwiftUI + +struct SplashView: View { + + var body: some View { + LottieView(animationName: "splash", loopMode: .playOnce) + .ignoresSafeArea(.all) + .scaledToFill() + } +} + +#Preview { + SplashView() +}