Skip to content

Commit

Permalink
πŸ”€ :: (#483) setting page
Browse files Browse the repository at this point in the history
  • Loading branch information
juyeong525 authored May 29, 2023
2 parents 50832d0 + 90f50d6 commit b660811
Show file tree
Hide file tree
Showing 19 changed files with 217 additions and 66 deletions.
3 changes: 2 additions & 1 deletion Application/Sources/Router/XQUARE/XquareRoute.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ enum XquareRoute: ScreenProtocol {
case mealDetail
case notification
case outingPass
case setting

// Schedule
case writeScheudle
Expand All @@ -25,7 +26,7 @@ enum XquareRoute: ScreenProtocol {
var embedInNavigationView: Bool {
switch self {
case .launch, .mealDetail, .notification, .outingPass, .login, .signup,
.writeScheudle, .myPage, .bugReport, .pointHistory, .selfStudyTeacher, .releaseNote:
.writeScheudle, .myPage, .bugReport, .pointHistory, .selfStudyTeacher, .releaseNote, .setting:
return false
default:
return true
Expand Down
9 changes: 9 additions & 0 deletions Application/Sources/Router/XQUARE/XquareRouterFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class XquareRouterFactory: RouterFactory {
let mealDetailView: MealDetailView
let notificationView: NotificationView
let outingPassView: OutingPassView
let settingView: SettingView

let writeScheduleView: WriteScheduleView

Expand Down Expand Up @@ -89,6 +90,10 @@ class XquareRouterFactory: RouterFactory {
let entireViewModel = EntireViewModel(
logoutUseCase: authServiceDependency.logoutUseCase
)
let settingViewModel = SettingViewModel(
activeNotificationCategoryUseCase: notificatoinServiceDependency.activeNotificationCategoryUseCase,
fetchActivatedCategoryListUseCase: notificatoinServiceDependency.fetchActivitedCategoryLiseUseCase
)

self.mainView = MainView(
homeView: .init(viewModel: homeViewModel),
Expand Down Expand Up @@ -116,6 +121,8 @@ class XquareRouterFactory: RouterFactory {
)
self.outingPassView = OutingPassView(viewModel: outingPassViewModel)

self.settingView = SettingView(viewModel: settingViewModel)

let pointHistoryViewModel = PointHistoryViewModel(
fetchPointHistoryUseCase: pointServiceDependency.fetchPointHistoryUseCase
)
Expand Down Expand Up @@ -171,6 +178,8 @@ class XquareRouterFactory: RouterFactory {
notificationView
case .outingPass:
outingPassView
case .setting:
settingView
case .writeScheudle:
writeScheduleView
case .pointHistory:
Expand Down
18 changes: 13 additions & 5 deletions Application/Sources/Scene/Home/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,19 @@ struct HomeView: View, XNavigationAndTabContent {
.padding(.leading, 5)
}
ToolbarItemGroup(placement: .navigationBarTrailing) {
Button {
self.xquareRouter.navigateTo(.notification)
} label: {
Image.bell
.frame(width: 24, height: 24)
HStack {
Button {
self.xquareRouter.navigateTo(.notification)
} label: {
Image.bell
.frame(width: 24, height: 24)
}
Button {
self.xquareRouter.navigateTo(.setting)
} label: {
Image.settingIcon
.frame(width: 24, height: 24)
}
}
}
}
Expand Down
47 changes: 47 additions & 0 deletions Application/Sources/Scene/Setting/SettingView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import SwiftUI
import SemicolonDesign

struct SettingView: View {

@StateObject var viewModel: SettingViewModel

var body: some View {
VStack(alignment: .center) {
Spacer().frame(height: 16)
HStack {
Text("μ„ νƒν•œ μ•Œλ¦Όμ„ λ³΄λ‚΄λ“œλ¦΄κ²Œμš”.\n곡지사항 μ•Œλ¦Όμ€ 꺼도 받을 수 μžˆμ–΄μš”.")
.sdText(type: .body4, textColor: .GrayScale.gray400)
Spacer()
}
.padding(.horizontal, 16)
Spacer().frame(height: 20)
ToggleView(
title: "ν”Όλ“œ μ•Œλ¦Ό",
subTitle: "ν”Όλ“œμ˜ λŒ“κΈ€κ³Ό μ’‹μ•„μš” λ“±μ˜ μ•Œλ¦Όμ„ μ„€μ •ν•΄μš”",
isToggle: $viewModel.isFeedToggle
)
ToggleView(
title: "μ‹ μ²­ μ•Œλ¦Ό",
subTitle: "급식과 μ™ΈμΆœμ‹ μ²­ λ“±μ˜ μ•Œλ¦Όμ„ μ„€μ •ν•΄μš”",
isToggle: $viewModel.isApplicationToggle
)
ToggleView(
title: "μƒλ²Œμ  μ•Œλ¦Ό",
subTitle: "μƒλ²Œμ  λ“±μ˜ μ•Œλ¦Όμ„ μ„€μ •ν•΄μš”",
isToggle: $viewModel.isAllToggle
)
ToggleView(
title: "일정 μ•Œλ¦Ό",
subTitle: "μΌμ •μ˜ μ•Œλ¦Όμ„ μ„€μ •ν•΄μš”",
isToggle: $viewModel.isScheduleToggle
)
Spacer()
}
.navigationTitle("μ„€μ •")
.navigationBarTitleDisplayMode(.inline)
.setNavigationBackButtonWithRouter()
.navigationBarBackButtonHidden()
.onAppear(perform: viewModel.fetchActivatedCategoryList)
.onDisappear(perform: viewModel.activeNotificationCategory)
}
}
51 changes: 51 additions & 0 deletions Application/Sources/Scene/Setting/SettingViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import SwiftUI

import RxSwift
import NotificationService

class SettingViewModel: ObservableObject {
@Published var isFeedToggle: Bool = false
@Published var isApplicationToggle: Bool = false
@Published var isAllToggle: Bool = false
@Published var isScheduleToggle: Bool = false
@Published var isSucceed: Bool = false

private let activeNotificationCategoryUseCase: ActiveNotificationCategoryUseCase
private let fetchActivatedCategoryListUseCase: FetchActivatedCategoryListUseCase

init(
activeNotificationCategoryUseCase: ActiveNotificationCategoryUseCase,
fetchActivatedCategoryListUseCase: FetchActivatedCategoryListUseCase
) {
self.activeNotificationCategoryUseCase = activeNotificationCategoryUseCase
self.fetchActivatedCategoryListUseCase = fetchActivatedCategoryListUseCase
}

private var disposeBag = DisposeBag()

func activeNotificationCategory() {
self.activeNotificationCategoryUseCase.excute(topics: [
.all: isAllToggle,
.application: isApplicationToggle,
.feed: isFeedToggle,
.schedule: isScheduleToggle
])
.subscribe(onCompleted: { self.isSucceed = true })
.disposed(by: disposeBag)
}

func fetchActivatedCategoryList() {
self.fetchActivatedCategoryListUseCase.excute()
.subscribe(onNext: {
$0.forEach {
switch $0.topic {
case .feed: self.isFeedToggle = $0.isActivate
case .application: self.isApplicationToggle = $0.isActivate
case .all: self.isAllToggle = $0.isActivate
case .schedule: self.isScheduleToggle = $0.isActivate
}
}
})
.disposed(by: disposeBag)
}
}
26 changes: 26 additions & 0 deletions Application/Sources/Scene/Setting/ToggleCell/ToggleView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import SwiftUI

import SemicolonDesign

struct ToggleView: View {

var title: String
var subTitle: String
@Binding var isToggle: Bool
var body: some View {
HStack(alignment: .center) {
VStack(alignment: .leading, spacing: 0) {
Text(title)
.sdText(type: .body1, textColor: .GrayScale.gray900)
Text(subTitle)
.sdText(type: .caption, textColor: .GrayScale.gray500)
}
Spacer()
Toggle("", isOn: $isToggle)
.toggleStyle(SwitchToggleStyle(tint: .Primary.purple400))
.labelsHidden()
}
.padding(.horizontal, 16)
.padding(.bottom, 24)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Foundation

import RxSwift

class ReportRepositoryImpl: ReportRepository {

private let remoteDataSource: RemoteReportDataSource

init(remoteDataSource: RemoteReportDataSource) {
self.remoteDataSource = remoteDataSource
}

func postBugReport(
reason: String,
category: BugCategory,
imageUrl: [String]
) -> Completable {
return remoteDataSource.postBugReport(
reason: reason,
category: category,
imageUrl: imageUrl
)
}
func fetchReleaseNote() -> Observable<[ReleaseNoteEntity]> {
return remoteDataSource.fetchReleaseNote().asObservable()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ public struct NotificationServiceDependency {
public let fetchNotificationCategoryListUseCase: FetchNotificationCategoryListUseCase
public let fetchActivitedCategoryLiseUseCase: FetchActivatedCategoryListUseCase
public let activeNotificationCategoryUseCase: ActiveNotificationCategoryUseCase
public let inactiveNotificationCategoryUseCase: InactiveNotifcationCategoryUseCase
public let fetchPostedNotificationListUseCase: FetchPostedNotificationListUseCase
public let checkNotificationUseCase: CheckNotificationUseCase
public let fetchUncheckNotificationCountUseCase: FetchUncheckNotificationCountUseCase
Expand All @@ -27,9 +26,6 @@ extension NotificationServiceDependency {
let activeNotificationCategoryUseCase = ActiveNotificationCategoryUseCase(
repositry: repository
)
let inactiveNotificationCategoryUseCase = InactiveNotifcationCategoryUseCase(
reposiotry: repository
)
let fetchPostedNotificationListUseCase = FetchPostedNotificationListUseCase(
repository: repository
)
Expand All @@ -44,7 +40,6 @@ extension NotificationServiceDependency {
fetchNotificationCategoryListUseCase: fetchNotificationCategoryListUseCase,
fetchActivitedCategoryLiseUseCase: fetchActivitedCategoryListUseCase,
activeNotificationCategoryUseCase: activeNotificationCategoryUseCase,
inactiveNotificationCategoryUseCase: inactiveNotificationCategoryUseCase,
fetchPostedNotificationListUseCase: fetchPostedNotificationListUseCase,
checkNotificationUseCase: checkNotificationUseCase,
fetchUncheckNotificationCountUseCase: fetchUncheckNotificationCountUseCase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import Moya
enum NotificationAPI {
case fetchNotificationCategoryList(defaultActivated: Bool)
case fetchActivatedNotificationCategoryList
case activeNotificationCategory(categoryId: String)
case inactiveNotificationCategory(categoryId: String)
case activeNotificationCategory(topic: String, isActivated: Bool)
case fetchPostedNotificationList
case checkNotification(notificationId: String)
case fetchUncheckNotificationCount
Expand All @@ -24,10 +23,8 @@ extension NotificationAPI: XquareAPI {
switch self {
case .fetchNotificationCategoryList:
return "/categories"
case .fetchActivatedNotificationCategoryList:
case .fetchActivatedNotificationCategoryList, .activeNotificationCategory:
return "/tags"
case .activeNotificationCategory(let categoryId), .inactiveNotificationCategory(let categoryId):
return "/tags/\(categoryId)"
case .checkNotification(let notificationId):
return "/\(notificationId)"
case .fetchUncheckNotificationCount:
Expand All @@ -50,8 +47,6 @@ extension NotificationAPI: XquareAPI {
switch self {
case .activeNotificationCategory:
return .patch
case .inactiveNotificationCategory:
return .delete
case .checkNotification:
return .post
default:
Expand All @@ -68,6 +63,14 @@ extension NotificationAPI: XquareAPI {
],
encoding: URLEncoding.default
)
case .activeNotificationCategory(let topic, let isActivated):
return .requestParameters(
parameters: [
"topic": topic,
"is-activated": isActivated
],
encoding: URLEncoding.queryString
)
default:
return .requestPlain
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import RestApiModule
protocol RemoteNotificationDataSource: RestApiRemoteDataSource<NotificationAPI> {
func fetchNotificationCategoryList(defaultActivated: Bool) -> Single<[CategoryEntity]>
func fetchActivatedNotificationCategoryList() -> Single<[CategoryEntity]>
func activeNotificationCategory(categoryId: String) -> Completable
func inactiveNotificationCategory(categoryId: String) -> Completable
func activeNotificationCategory(topic: NotificationActivateTopic, isActivated: Bool) -> Completable
func fetchPostedNotificationList() -> Single<[NotificationEntity]>
func checkNotification(notificationId: String) -> Completable
func fetchUncheckNotificationCount() -> Single<Int>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,8 @@ class RemoteNotificationDataSourceImpl: RestApiRemoteDataSource<NotificationAPI>
.map { $0.toDomain() }
}

func activeNotificationCategory(categoryId: String) -> Completable {
return request(.activeNotificationCategory(categoryId: categoryId))
.asCompletable()
}

func inactiveNotificationCategory(categoryId: String) -> Completable {
return request(.inactiveNotificationCategory(categoryId: categoryId))
func activeNotificationCategory(topic: NotificationActivateTopic, isActivated: Bool) -> Completable {
return request(.activeNotificationCategory(topic: topic.rawValue, isActivated: isActivated))
.asCompletable()
}

Expand All @@ -43,5 +38,4 @@ class RemoteNotificationDataSourceImpl: RestApiRemoteDataSource<NotificationAPI>
.map(UnreadCountResponse.self)
.map { $0.unreadCount }
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,8 @@ class NotificationRepositoryImpl: NotificationRepository {
.asObservable()
}

func activeNotificationCategory(categoryId: String) -> Completable {
return remoteDataSource.activeNotificationCategory(categoryId: categoryId)
}

func inactiveNotificationCategory(categoryId: String) -> RxSwift.Completable {
return remoteDataSource.inactiveNotificationCategory(categoryId: categoryId)
func activeNotificationCategory(topic: NotificationActivateTopic, isActivated: Bool) -> Completable {
return remoteDataSource.activeNotificationCategory(topic: topic, isActivated: isActivated)
}

func fetchPostedNotificationList() -> Observable<[NotificationEntity]> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import Foundation

struct CategoryListResponse: Decodable {
let categories: [CategoryResponse]
let settings: [CategoryResponse]
}

extension CategoryListResponse {
func toDomain() -> [CategoryEntity] {
return categories.map { $0.toDomain() }
return settings.map { $0.toDomain() }
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import Foundation

struct CategoryResponse: Decodable {
let id: String
let name: String
let destination: String
let topic: String
let isActivate: Bool

enum CodingKeys: String, CodingKey {
case topic
case isActivate = "is_activate"
}
}

extension CategoryResponse {
func toDomain() -> CategoryEntity {
return .init(
id: id,
name: name,
destination: destination
topic: .init(rawValue: topic) ?? .all,
isActivate: isActivate
)
}
}
Loading

0 comments on commit b660811

Please sign in to comment.