diff --git a/app-compose/build.gradle.kts b/app-compose/build.gradle.kts index 931090f68..54435a168 100644 --- a/app-compose/build.gradle.kts +++ b/app-compose/build.gradle.kts @@ -25,24 +25,12 @@ dependencies { implementation(projects.remote.openmajor) implementation(projects.remote.timetable) - implementation(projects.remote.lectureevaluation) - implementation(projects.remote.signup) - implementation(projects.remote.notice) - implementation(projects.remote.user) - implementation(projects.remote.login) implementation(projects.local.openmajor) implementation(projects.local.timetable) - implementation(projects.local.user) - implementation(projects.local.login) implementation(projects.data.openmajor) implementation(projects.data.timetable) - implementation(projects.data.lectureevaluation) - implementation(projects.data.user) - implementation(projects.data.notice) - implementation(projects.data.signup) - implementation(projects.data.login) implementation(platform(libs.firebase.bom)) implementation(libs.firebase.crashlytics) diff --git a/data/lectureevaluation/.gitignore b/data/lectureevaluation/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/data/lectureevaluation/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/data/lectureevaluation/build.gradle.kts b/data/lectureevaluation/build.gradle.kts deleted file mode 100644 index c2434f85d..000000000 --- a/data/lectureevaluation/build.gradle.kts +++ /dev/null @@ -1,12 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.data) -} - -android { - namespace = "com.suwiki.data.lectureevaluation" -} - -dependencies { - implementation(projects.domain.lectureevaluation) -} diff --git a/data/lectureevaluation/consumer-rules.pro b/data/lectureevaluation/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/data/lectureevaluation/proguard-rules.pro b/data/lectureevaluation/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/data/lectureevaluation/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/data/lectureevaluation/src/main/AndroidManifest.xml b/data/lectureevaluation/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e68a..000000000 --- a/data/lectureevaluation/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteExamEditorDataSource.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteExamEditorDataSource.kt deleted file mode 100644 index ccdb3948f..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteExamEditorDataSource.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.suwiki.data.lectureevaluation.datasource - -interface RemoteExamEditorDataSource { - - suspend fun postExamEvaluation( - lectureId: Long, - lectureName: String?, - professor: String?, - selectedSemester: String?, - examInfo: String, - examType: String?, - examDifficulty: String, - content: String, - ) - - suspend fun updateExamEvaluation( - lectureId: Long, - selectedSemester: String?, - examInfo: String, - examType: String?, - examDifficulty: String, - content: String, - ) - - suspend fun deleteExamEvaluation(id: Long) -} diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteExamMyDataSource.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteExamMyDataSource.kt deleted file mode 100644 index 5d156e3d3..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteExamMyDataSource.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.suwiki.data.lectureevaluation.datasource - -import com.suwiki.common.model.lectureevaluation.PurchaseHistory -import com.suwiki.common.model.lectureevaluation.exam.MyExamEvaluation - -interface RemoteExamMyDataSource { - - suspend fun getMyExamEvaluationList(page: Int): List - - suspend fun getPurchaseHistory(): List -} diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteExamProviderDataSource.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteExamProviderDataSource.kt deleted file mode 100644 index 9298e5c0e..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteExamProviderDataSource.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.suwiki.data.lectureevaluation.datasource - -import com.suwiki.common.model.lectureevaluation.exam.ExamEvaluationList - -interface RemoteExamProviderDataSource { - suspend fun buyExam(lectureId: Long) - - suspend fun getExamEvaluationList( - lectureId: Long, - page: Int, - ): ExamEvaluationList -} diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteExamReportDataSource.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteExamReportDataSource.kt deleted file mode 100644 index c211c19e9..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteExamReportDataSource.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.suwiki.data.lectureevaluation.datasource - -interface RemoteExamReportDataSource { - - suspend fun reportExam( - examIdx: Long, - content: String = "", - ) -} diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteLectureEditorDataSource.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteLectureEditorDataSource.kt deleted file mode 100644 index 89699e8ff..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteLectureEditorDataSource.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.suwiki.data.lectureevaluation.datasource - -interface RemoteLectureEditorDataSource { - - suspend fun postLectureEvaluation( - lectureId: Long, - lectureName: String, - professor: String, - selectedSemester: String, - satisfaction: Float, - learning: Float, - honey: Float, - team: Int, - difficulty: Int, - homework: Int, - content: String, - ) - - suspend fun updateLectureEvaluation( - lectureId: Long, - selectedSemester: String, - satisfaction: Float, - learning: Float, - honey: Float, - team: Int, - difficulty: Int, - homework: Int, - content: String, - ) - - suspend fun deleteLectureEvaluation(id: Long) -} diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteLectureMyDataSource.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteLectureMyDataSource.kt deleted file mode 100644 index dea5a9647..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteLectureMyDataSource.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.suwiki.data.lectureevaluation.datasource - -import com.suwiki.common.model.lectureevaluation.lecture.MyLectureEvaluation - -interface RemoteLectureMyDataSource { - - suspend fun getMyLectureEvaluationList(page: Int): List -} diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteLectureProviderDataSource.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteLectureProviderDataSource.kt deleted file mode 100644 index 625009bfc..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteLectureProviderDataSource.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.suwiki.data.lectureevaluation.datasource - -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationAverage -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationExtraAverage -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationList - -interface RemoteLectureProviderDataSource { - suspend fun getLectureEvaluationAverageList( - option: String, - page: Int = 1, - majorType: String = "", - ): List - - suspend fun retrieveLectureEvaluationAverageList( - search: String, - option: String, - page: Int, - majorType: String, - ): List - - suspend fun getLectureEvaluationExtraAverage(lectureId: Long): LectureEvaluationExtraAverage - - suspend fun getLectureEvaluationList( - lectureId: Long, - page: Int, - ): LectureEvaluationList -} diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteLectureReportDataSource.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteLectureReportDataSource.kt deleted file mode 100644 index c7dfc797f..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/datasource/RemoteLectureReportDataSource.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.suwiki.data.lectureevaluation.datasource - -interface RemoteLectureReportDataSource { - - suspend fun reportLecture( - evaluateIdx: Long, - content: String = "", - ) -} diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/di/RepositoryModule.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/di/RepositoryModule.kt deleted file mode 100644 index 5bacc12bf..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/di/RepositoryModule.kt +++ /dev/null @@ -1,76 +0,0 @@ -package com.suwiki.data.lectureevaluation.di - -import com.suwiki.data.lectureevaluation.repository.ExamEditorRepositoryImpl -import com.suwiki.data.lectureevaluation.repository.ExamMyRepositoryImpl -import com.suwiki.data.lectureevaluation.repository.ExamProviderRepositoryImpl -import com.suwiki.data.lectureevaluation.repository.ExamReportRepositoryImpl -import com.suwiki.data.lectureevaluation.repository.LectureEditorRepositoryImpl -import com.suwiki.data.lectureevaluation.repository.LectureMyRepositoryImpl -import com.suwiki.data.lectureevaluation.repository.LectureProviderRepositoryImpl -import com.suwiki.data.lectureevaluation.repository.LectureReportRepositoryImpl -import com.suwiki.domain.lectureevaluation.repository.ExamEditorRepository -import com.suwiki.domain.lectureevaluation.repository.ExamMyRepository -import com.suwiki.domain.lectureevaluation.repository.ExamProviderRepository -import com.suwiki.domain.lectureevaluation.repository.ExamReportRepository -import com.suwiki.domain.lectureevaluation.repository.LectureEditorRepository -import com.suwiki.domain.lectureevaluation.repository.LectureMyRepository -import com.suwiki.domain.lectureevaluation.repository.LectureProviderRepository -import com.suwiki.domain.lectureevaluation.repository.LectureReportRepository -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -abstract class RepositoryModule { - - @Singleton - @Binds - abstract fun bindExamEditorRepository( - examEditorRepositoryImpl: ExamEditorRepositoryImpl, - ): ExamEditorRepository - - @Singleton - @Binds - abstract fun bindLectureEditorRepository( - lectureEditorRepositoryImpl: LectureEditorRepositoryImpl, - ): LectureEditorRepository - - @Singleton - @Binds - abstract fun bindExamMyRepository( - examMyRepositoryImpl: ExamMyRepositoryImpl, - ): ExamMyRepository - - @Singleton - @Binds - abstract fun bindLectureMyRepository( - lectureMyRepositoryImpl: LectureMyRepositoryImpl, - ): LectureMyRepository - - @Singleton - @Binds - abstract fun bindExamProviderRepository( - examProviderRepositoryImpl: ExamProviderRepositoryImpl, - ): ExamProviderRepository - - @Singleton - @Binds - abstract fun bindExamReportRepository( - examReportRepositoryImpl: ExamReportRepositoryImpl, - ): ExamReportRepository - - @Singleton - @Binds - abstract fun bindLectureProviderRepository( - lectureProviderRepositoryImpl: LectureProviderRepositoryImpl, - ): LectureProviderRepository - - @Singleton - @Binds - abstract fun bindLectureReportRepository( - lectureReportRepositoryImpl: LectureReportRepositoryImpl, - ): LectureReportRepository -} diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/ExamEditorRepositoryImpl.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/ExamEditorRepositoryImpl.kt deleted file mode 100644 index 725e80a1e..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/ExamEditorRepositoryImpl.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.suwiki.data.lectureevaluation.repository - -import com.suwiki.data.lectureevaluation.datasource.RemoteExamEditorDataSource -import com.suwiki.domain.lectureevaluation.repository.ExamEditorRepository -import javax.inject.Inject - -class ExamEditorRepositoryImpl @Inject constructor( - private val remoteExamEditorDataSource: RemoteExamEditorDataSource, -) : ExamEditorRepository { - override suspend fun postExamEvaluation( - lectureId: Long, - lectureName: String?, - professor: String?, - selectedSemester: String?, - examInfo: String, - examType: String?, - examDifficulty: String, - content: String, - ) { - remoteExamEditorDataSource.postExamEvaluation( - lectureId = lectureId, - lectureName = lectureName, - professor = professor, - selectedSemester = selectedSemester, - examInfo = examInfo, - examType = examType, - examDifficulty = examDifficulty, - content = content, - ) - } - - override suspend fun updateExamEvaluation( - lectureId: Long, - selectedSemester: String?, - examInfo: String, - examType: String?, - examDifficulty: String, - content: String, - ) { - remoteExamEditorDataSource.updateExamEvaluation( - lectureId = lectureId, - selectedSemester = selectedSemester, - examInfo = examInfo, - examType = examType, - examDifficulty = examDifficulty, - content = content, - ) - } - - override suspend fun deleteExamEvaluation(id: Long) { - remoteExamEditorDataSource.deleteExamEvaluation(id = id) - } -} diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/ExamMyRepositoryImpl.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/ExamMyRepositoryImpl.kt deleted file mode 100644 index 191546cf8..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/ExamMyRepositoryImpl.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.suwiki.data.lectureevaluation.repository - -import com.suwiki.common.model.lectureevaluation.PurchaseHistory -import com.suwiki.common.model.lectureevaluation.exam.MyExamEvaluation -import com.suwiki.data.lectureevaluation.datasource.RemoteExamMyDataSource -import com.suwiki.domain.lectureevaluation.repository.ExamMyRepository -import javax.inject.Inject - -class ExamMyRepositoryImpl @Inject constructor( - private val remoteExamMyDataSource: RemoteExamMyDataSource, -) : ExamMyRepository { - override suspend fun getMyExamEvaluationList(page: Int): List { - return remoteExamMyDataSource.getMyExamEvaluationList(page = page) - } - - override suspend fun getPurchaseHistory(): List { - return remoteExamMyDataSource.getPurchaseHistory() - } -} diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/ExamProviderRepositoryImpl.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/ExamProviderRepositoryImpl.kt deleted file mode 100644 index bb11e29c4..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/ExamProviderRepositoryImpl.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.suwiki.data.lectureevaluation.repository - -import com.suwiki.common.model.lectureevaluation.exam.ExamEvaluationList -import com.suwiki.data.lectureevaluation.datasource.RemoteExamProviderDataSource -import com.suwiki.domain.lectureevaluation.repository.ExamProviderRepository -import javax.inject.Inject - -class ExamProviderRepositoryImpl @Inject constructor( - private val remoteExamProviderDataSource: RemoteExamProviderDataSource, -) : ExamProviderRepository { - override suspend fun buyExam(lectureId: Long) { - remoteExamProviderDataSource.buyExam(lectureId = lectureId) - } - - override suspend fun getExamEvaluationList(lectureId: Long, page: Int): ExamEvaluationList { - return remoteExamProviderDataSource.getExamEvaluationList( - lectureId = lectureId, - page = page, - ) - } -} diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/ExamReportRepositoryImpl.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/ExamReportRepositoryImpl.kt deleted file mode 100644 index 63d95fd50..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/ExamReportRepositoryImpl.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.suwiki.data.lectureevaluation.repository - -import com.suwiki.data.lectureevaluation.datasource.RemoteExamReportDataSource -import com.suwiki.domain.lectureevaluation.repository.ExamReportRepository -import javax.inject.Inject - -class ExamReportRepositoryImpl @Inject constructor( - private val remoteExamReportDataSource: RemoteExamReportDataSource, -) : ExamReportRepository { - - override suspend fun reportExam(examIdx: Long, content: String) { - remoteExamReportDataSource.reportExam( - examIdx = examIdx, - content = content, - ) - } -} diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/LectureEditorRepositoryImpl.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/LectureEditorRepositoryImpl.kt deleted file mode 100644 index 4dc6cfab2..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/LectureEditorRepositoryImpl.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.suwiki.data.lectureevaluation.repository - -import com.suwiki.data.lectureevaluation.datasource.RemoteLectureEditorDataSource -import com.suwiki.domain.lectureevaluation.repository.LectureEditorRepository -import javax.inject.Inject - -class LectureEditorRepositoryImpl @Inject constructor( - private val lectureEditorDataSource: RemoteLectureEditorDataSource, -) : LectureEditorRepository { - override suspend fun postLectureEvaluation( - lectureId: Long, - lectureName: String, - professor: String, - selectedSemester: String, - satisfaction: Float, - learning: Float, - honey: Float, - team: Int, - difficulty: Int, - homework: Int, - content: String, - ) { - lectureEditorDataSource.postLectureEvaluation( - lectureId = lectureId, - lectureName = lectureName, - professor = professor, - selectedSemester = selectedSemester, - satisfaction = satisfaction, - learning = learning, - honey = honey, - team = team, - difficulty = difficulty, - homework = homework, - content = content, - ) - } - - override suspend fun updateLectureEvaluation( - lectureId: Long, - selectedSemester: String, - satisfaction: Float, - learning: Float, - honey: Float, - team: Int, - difficulty: Int, - homework: Int, - content: String, - ) { - lectureEditorDataSource.updateLectureEvaluation( - lectureId = lectureId, - selectedSemester = selectedSemester, - satisfaction = satisfaction, - learning = learning, - honey = honey, - team = team, - difficulty = difficulty, - homework = homework, - content = content, - ) - } - - override suspend fun deleteLectureEvaluation(id: Long) { - lectureEditorDataSource.deleteLectureEvaluation(id = id) - } -} diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/LectureMyRepositoryImpl.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/LectureMyRepositoryImpl.kt deleted file mode 100644 index 7d1be4684..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/LectureMyRepositoryImpl.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.suwiki.data.lectureevaluation.repository - -import com.suwiki.common.model.lectureevaluation.lecture.MyLectureEvaluation -import com.suwiki.data.lectureevaluation.datasource.RemoteLectureMyDataSource -import com.suwiki.domain.lectureevaluation.repository.LectureMyRepository -import javax.inject.Inject - -class LectureMyRepositoryImpl @Inject constructor( - private val remoteLectureMyDataSource: RemoteLectureMyDataSource, -) : LectureMyRepository { - override suspend fun getMyLectureEvaluationList(page: Int): List { - return remoteLectureMyDataSource.getMyLectureEvaluationList(page = page) - } -} diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/LectureProviderRepositoryImpl.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/LectureProviderRepositoryImpl.kt deleted file mode 100644 index 62f5b29dc..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/LectureProviderRepositoryImpl.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.suwiki.data.lectureevaluation.repository - -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationAverage -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationExtraAverage -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationList -import com.suwiki.data.lectureevaluation.datasource.RemoteLectureProviderDataSource -import com.suwiki.domain.lectureevaluation.repository.LectureProviderRepository -import javax.inject.Inject - -class LectureProviderRepositoryImpl @Inject constructor( - private val remoteLectureProviderDataSource: RemoteLectureProviderDataSource, -) : LectureProviderRepository { - - override suspend fun getLectureEvaluationList(lectureId: Long, page: Int): LectureEvaluationList { - return remoteLectureProviderDataSource.getLectureEvaluationList( - lectureId = lectureId, - page = page, - ) - } - - override suspend fun getLectureEvaluationAverageList( - option: String, - page: Int, - majorType: String, - ): List { - return remoteLectureProviderDataSource.getLectureEvaluationAverageList( - option = option, - page = page, - majorType = majorType, - ) - } - - override suspend fun retrieveLectureEvaluationAverageList( - search: String, - option: String, - page: Int, - majorType: String, - ): List { - return remoteLectureProviderDataSource.retrieveLectureEvaluationAverageList( - search = search, - option = option, - page = page, - majorType = majorType, - ) - } - - override suspend fun getLectureEvaluationExtraAverage(lectureId: Long): LectureEvaluationExtraAverage { - return remoteLectureProviderDataSource.getLectureEvaluationExtraAverage( - lectureId = lectureId, - ) - } -} diff --git a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/LectureReportRepositoryImpl.kt b/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/LectureReportRepositoryImpl.kt deleted file mode 100644 index 48b7f510e..000000000 --- a/data/lectureevaluation/src/main/java/com/suwiki/data/lectureevaluation/repository/LectureReportRepositoryImpl.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.suwiki.data.lectureevaluation.repository - -import com.suwiki.data.lectureevaluation.datasource.RemoteLectureReportDataSource -import com.suwiki.domain.lectureevaluation.repository.LectureReportRepository -import javax.inject.Inject - -class LectureReportRepositoryImpl @Inject constructor( - private val remoteLectureReportDataSource: RemoteLectureReportDataSource, -) : LectureReportRepository { - - override suspend fun reportLecture(evaluateIdx: Long, content: String) { - remoteLectureReportDataSource.reportLecture( - evaluateIdx = evaluateIdx, - content = content, - ) - } -} diff --git a/data/login/.gitignore b/data/login/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/data/login/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/data/login/build.gradle.kts b/data/login/build.gradle.kts deleted file mode 100644 index 85d851063..000000000 --- a/data/login/build.gradle.kts +++ /dev/null @@ -1,13 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.data) -} - -android { - namespace = "com.suwiki.data.login" -} - -dependencies { - implementation(projects.common.security) - implementation(projects.domain.login) -} diff --git a/data/login/consumer-rules.pro b/data/login/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/data/login/proguard-rules.pro b/data/login/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/data/login/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/data/login/src/main/AndroidManifest.xml b/data/login/src/main/AndroidManifest.xml deleted file mode 100644 index 8bdb7e14b..000000000 --- a/data/login/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/data/login/src/main/java/com/suwiki/data/login/datasource/LocalLoginDataSource.kt b/data/login/src/main/java/com/suwiki/data/login/datasource/LocalLoginDataSource.kt deleted file mode 100644 index 15a26e04d..000000000 --- a/data/login/src/main/java/com/suwiki/data/login/datasource/LocalLoginDataSource.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.suwiki.data.login.datasource - -import com.suwiki.common.model.user.Token - -interface LocalLoginDataSource { - suspend fun setToken( - token: Token, - ) -} diff --git a/data/login/src/main/java/com/suwiki/data/login/datasource/RemoteLoginDataSource.kt b/data/login/src/main/java/com/suwiki/data/login/datasource/RemoteLoginDataSource.kt deleted file mode 100644 index 72a19b47d..000000000 --- a/data/login/src/main/java/com/suwiki/data/login/datasource/RemoteLoginDataSource.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.suwiki.data.login.datasource - -import com.suwiki.common.model.user.Token - -interface RemoteLoginDataSource { - suspend fun findId(email: String) - - suspend fun findPassword( - loginId: String, - email: String, - ) - - suspend fun login( - loginId: String, - password: String, - ): Token -} diff --git a/data/login/src/main/java/com/suwiki/data/login/di/RepositoryModule.kt b/data/login/src/main/java/com/suwiki/data/login/di/RepositoryModule.kt deleted file mode 100644 index 43423c999..000000000 --- a/data/login/src/main/java/com/suwiki/data/login/di/RepositoryModule.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.suwiki.data.login.di - -import com.suwiki.data.login.repository.LoginRepositoryImpl -import com.suwiki.domain.login.repository.LoginRepository -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -abstract class RepositoryModule { - - @Singleton - @Binds - abstract fun bindLoginRepository( - loginRepositoryImpl: LoginRepositoryImpl, - ): LoginRepository -} diff --git a/data/login/src/main/java/com/suwiki/data/login/repository/LoginRepositoryImpl.kt b/data/login/src/main/java/com/suwiki/data/login/repository/LoginRepositoryImpl.kt deleted file mode 100644 index c47ddfbc0..000000000 --- a/data/login/src/main/java/com/suwiki/data/login/repository/LoginRepositoryImpl.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.suwiki.data.login.repository - -import com.suwiki.data.login.datasource.LocalLoginDataSource -import com.suwiki.data.login.datasource.RemoteLoginDataSource -import com.suwiki.domain.login.repository.LoginRepository -import javax.inject.Inject - -class LoginRepositoryImpl @Inject constructor( - private val remoteLoginDataSource: RemoteLoginDataSource, - private val localLoginDataSource: LocalLoginDataSource, -) : LoginRepository { - - override suspend fun findId(email: String) { - remoteLoginDataSource.findId(email = email) - } - - override suspend fun findPassword(loginId: String, email: String) { - remoteLoginDataSource.findPassword( - loginId = loginId, - email = email, - ) - } - - override suspend fun login(loginId: String, password: String) { - val token = remoteLoginDataSource.login( - loginId = loginId, - password = password, - ) - - localLoginDataSource.setToken(token) - } -} diff --git a/data/notice/.gitignore b/data/notice/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/data/notice/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/data/notice/build.gradle.kts b/data/notice/build.gradle.kts deleted file mode 100644 index 1b60d0a51..000000000 --- a/data/notice/build.gradle.kts +++ /dev/null @@ -1,12 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.data) -} - -android { - namespace = "com.suwiki.data.notice" -} - -dependencies { - implementation(projects.domain.notice) -} diff --git a/data/notice/consumer-rules.pro b/data/notice/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/data/notice/proguard-rules.pro b/data/notice/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/data/notice/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/data/notice/src/main/AndroidManifest.xml b/data/notice/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e68a..000000000 --- a/data/notice/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/data/notice/src/main/java/com/suwiki/data/notice/datasource/RemoteNoticeDataSource.kt b/data/notice/src/main/java/com/suwiki/data/notice/datasource/RemoteNoticeDataSource.kt deleted file mode 100644 index 059da9c0b..000000000 --- a/data/notice/src/main/java/com/suwiki/data/notice/datasource/RemoteNoticeDataSource.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.suwiki.data.notice.datasource - -import com.suwiki.common.model.notice.Notice -import com.suwiki.common.model.notice.NoticeDetail - -interface RemoteNoticeDataSource { - - suspend fun getNoticeList(page: Int): List - - suspend fun getNoticeDetail(id: Long): NoticeDetail - - suspend fun checkUpdateMandatory( - versionCode: Long, - ): Boolean -} diff --git a/data/notice/src/main/java/com/suwiki/data/notice/di/RepositoryModule.kt b/data/notice/src/main/java/com/suwiki/data/notice/di/RepositoryModule.kt deleted file mode 100644 index a75f26e89..000000000 --- a/data/notice/src/main/java/com/suwiki/data/notice/di/RepositoryModule.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.suwiki.data.notice.di - -import com.suwiki.data.notice.repository.NoticeRepositoryImpl -import com.suwiki.domain.notice.repository.NoticeRepository -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -abstract class RepositoryModule { - - @Singleton - @Binds - abstract fun bindNoticeRepository( - noticeRepositoryImpl: NoticeRepositoryImpl, - ): NoticeRepository -} diff --git a/data/notice/src/main/java/com/suwiki/data/notice/repository/NoticeRepositoryImpl.kt b/data/notice/src/main/java/com/suwiki/data/notice/repository/NoticeRepositoryImpl.kt deleted file mode 100644 index 4bc95027a..000000000 --- a/data/notice/src/main/java/com/suwiki/data/notice/repository/NoticeRepositoryImpl.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.suwiki.data.notice.repository - -import com.suwiki.common.model.notice.Notice -import com.suwiki.common.model.notice.NoticeDetail -import com.suwiki.data.notice.datasource.RemoteNoticeDataSource -import com.suwiki.domain.notice.repository.NoticeRepository -import javax.inject.Inject - -class NoticeRepositoryImpl @Inject constructor( - private val remoteNoticeDataSource: RemoteNoticeDataSource, -) : NoticeRepository { - override suspend fun getNoticeList(page: Int): List { - return remoteNoticeDataSource.getNoticeList(page) - } - - override suspend fun getNoticeDetail(id: Long): NoticeDetail { - return remoteNoticeDataSource.getNoticeDetail(id) - } - - override suspend fun checkUpdateMandatory(versionCode: Long): Boolean { - return remoteNoticeDataSource.checkUpdateMandatory(versionCode) - } -} diff --git a/data/notice/src/test/java/com/suwiki/data/notice/ExampleUnitTest.kt b/data/notice/src/test/java/com/suwiki/data/notice/ExampleUnitTest.kt deleted file mode 100644 index bd211aae0..000000000 --- a/data/notice/src/test/java/com/suwiki/data/notice/ExampleUnitTest.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.suwiki.data.notice - -import junit.framework.TestCase.assertEquals -import org.junit.Test - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} diff --git a/data/signup/.gitignore b/data/signup/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/data/signup/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/data/signup/build.gradle.kts b/data/signup/build.gradle.kts deleted file mode 100644 index a85c08a87..000000000 --- a/data/signup/build.gradle.kts +++ /dev/null @@ -1,12 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.data) -} - -android { - namespace = "com.suwiki.data.signup" -} - -dependencies { - implementation(projects.domain.signup) -} diff --git a/data/signup/consumer-rules.pro b/data/signup/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/data/signup/proguard-rules.pro b/data/signup/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/data/signup/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/data/signup/src/main/AndroidManifest.xml b/data/signup/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e68a..000000000 --- a/data/signup/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/data/signup/src/main/java/com/suwiki/data/signup/datasource/RemoteSignUpDataSource.kt b/data/signup/src/main/java/com/suwiki/data/signup/datasource/RemoteSignUpDataSource.kt deleted file mode 100644 index 77f82a215..000000000 --- a/data/signup/src/main/java/com/suwiki/data/signup/datasource/RemoteSignUpDataSource.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.suwiki.data.signup.datasource - -interface RemoteSignUpDataSource { - suspend fun signUp( - id: String, - password: String, - email: String, - ) - - suspend fun checkIdOverlap(loginId: String): Boolean - - suspend fun checkEmailOverlap(email: String): Boolean -} diff --git a/data/signup/src/main/java/com/suwiki/data/signup/di/RepositoryModule.kt b/data/signup/src/main/java/com/suwiki/data/signup/di/RepositoryModule.kt deleted file mode 100644 index 22a9da3d6..000000000 --- a/data/signup/src/main/java/com/suwiki/data/signup/di/RepositoryModule.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.suwiki.data.signup.di - -import com.suwiki.data.signup.repository.SignupRepositoryImpl -import com.suwiki.domain.signup.repository.SignupRepository -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -abstract class RepositoryModule { - - @Singleton - @Binds - abstract fun bindSignUpRepository( - signUpRepositoryImpl: SignupRepositoryImpl, - ): SignupRepository -} diff --git a/data/signup/src/main/java/com/suwiki/data/signup/repository/SignupRepositoryImpl.kt b/data/signup/src/main/java/com/suwiki/data/signup/repository/SignupRepositoryImpl.kt deleted file mode 100644 index ca5bd269a..000000000 --- a/data/signup/src/main/java/com/suwiki/data/signup/repository/SignupRepositoryImpl.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.suwiki.data.signup.repository - -import com.suwiki.data.signup.datasource.RemoteSignUpDataSource -import com.suwiki.domain.signup.repository.SignupRepository -import javax.inject.Inject - -class SignupRepositoryImpl @Inject constructor( - private val remoteSignUpDataSource: RemoteSignUpDataSource, -) : SignupRepository { - override suspend fun signUp(id: String, password: String, email: String) { - remoteSignUpDataSource.signUp(id = id, password = password, email = email) - } - - override suspend fun checkIdOverlap(loginId: String): Boolean { - return remoteSignUpDataSource.checkIdOverlap(loginId = loginId) - } - - override suspend fun checkEmailOverlap(email: String): Boolean { - return remoteSignUpDataSource.checkEmailOverlap(email = email) - } -} diff --git a/data/signup/src/test/java/com/suwiki/data/signup/ExampleUnitTest.kt b/data/signup/src/test/java/com/suwiki/data/signup/ExampleUnitTest.kt deleted file mode 100644 index 55aff6294..000000000 --- a/data/signup/src/test/java/com/suwiki/data/signup/ExampleUnitTest.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.suwiki.data.signup - -import junit.framework.TestCase.assertEquals -import org.junit.Test - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} diff --git a/data/user/.gitignore b/data/user/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/data/user/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/data/user/build.gradle.kts b/data/user/build.gradle.kts deleted file mode 100644 index d243021d3..000000000 --- a/data/user/build.gradle.kts +++ /dev/null @@ -1,13 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.data) -} - -android { - namespace = "com.suwiki.data.user" -} - -dependencies { - implementation(projects.common.security) - implementation(projects.domain.user) -} diff --git a/data/user/consumer-rules.pro b/data/user/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/data/user/proguard-rules.pro b/data/user/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/data/user/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/data/user/src/main/AndroidManifest.xml b/data/user/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e68a..000000000 --- a/data/user/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/data/user/src/main/java/com/suwiki/data/user/datasource/LocalUserDataSource.kt b/data/user/src/main/java/com/suwiki/data/user/datasource/LocalUserDataSource.kt deleted file mode 100644 index d2dde3ac3..000000000 --- a/data/user/src/main/java/com/suwiki/data/user/datasource/LocalUserDataSource.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.suwiki.data.user.datasource - -import com.suwiki.common.model.user.User -import kotlinx.coroutines.flow.Flow - -interface LocalUserDataSource { - val user: Flow - - suspend fun setUserInfo( - user: User, - ) - - suspend fun clearUserInfo() -} diff --git a/data/user/src/main/java/com/suwiki/data/user/datasource/RemoteUserDataSource.kt b/data/user/src/main/java/com/suwiki/data/user/datasource/RemoteUserDataSource.kt deleted file mode 100644 index b9b3f358d..000000000 --- a/data/user/src/main/java/com/suwiki/data/user/datasource/RemoteUserDataSource.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.suwiki.data.user.datasource - -import com.suwiki.common.model.user.Suspension -import com.suwiki.common.model.user.User - -interface RemoteUserDataSource { - - suspend fun resetPassword( - currentPassword: String, - newPassword: String, - ) - - suspend fun quit( - id: String, - password: String, - ) - - suspend fun getUserInfo(): User - - suspend fun getBanHistory(): List - - suspend fun getBlackList(): List -} diff --git a/data/user/src/main/java/com/suwiki/data/user/di/RepositoryModule.kt b/data/user/src/main/java/com/suwiki/data/user/di/RepositoryModule.kt deleted file mode 100644 index 67e8bd796..000000000 --- a/data/user/src/main/java/com/suwiki/data/user/di/RepositoryModule.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.suwiki.data.user.di - -import com.suwiki.data.user.repository.UserRepositoryImpl -import com.suwiki.domain.user.repository.UserRepository -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -abstract class RepositoryModule { - - @Singleton - @Binds - abstract fun bindUserRepository( - userRepositoryImpl: UserRepositoryImpl, - ): UserRepository -} diff --git a/data/user/src/main/java/com/suwiki/data/user/repository/UserRepositoryImpl.kt b/data/user/src/main/java/com/suwiki/data/user/repository/UserRepositoryImpl.kt deleted file mode 100644 index f89450e5e..000000000 --- a/data/user/src/main/java/com/suwiki/data/user/repository/UserRepositoryImpl.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.suwiki.data.user.repository - -import com.suwiki.common.model.exception.AuthorizationException -import com.suwiki.common.model.user.Suspension -import com.suwiki.common.model.user.User -import com.suwiki.common.security.SecurityPreferences -import com.suwiki.data.user.datasource.LocalUserDataSource -import com.suwiki.data.user.datasource.RemoteUserDataSource -import com.suwiki.domain.user.repository.UserRepository -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.flow -import javax.inject.Inject - -class UserRepositoryImpl @Inject constructor( - private val localUserDataSource: LocalUserDataSource, - private val remoteUserDataSource: RemoteUserDataSource, - private val securityPreferences: SecurityPreferences, -) : UserRepository { - override suspend fun logout() { - localUserDataSource.clearUserInfo() - securityPreferences.clearAll() - } - - override suspend fun resetPassword(currentPassword: String, newPassword: String) { - remoteUserDataSource.resetPassword( - currentPassword = currentPassword, - newPassword = newPassword, - ) - } - - override suspend fun quit(id: String, password: String) { - remoteUserDataSource.quit( - id = id, - password = password, - ) - logout() - } - - override suspend fun getUserInfo(): Flow = flow { - val localUserInfo = localUserDataSource.user.first() - emit(localUserInfo) - - val remoteUserInfo = runCatching { - remoteUserDataSource.getUserInfo() - }.getOrElse { exception -> - if (exception is AuthorizationException) { - logout() - emit(User()) - return@flow - } else { - throw exception - } - } - - emit(remoteUserInfo) - localUserDataSource.setUserInfo(remoteUserInfo) - } - - override suspend fun getBanHistory(): List { - return remoteUserDataSource.getBanHistory() - } - - override suspend fun getBlackList(): List { - return remoteUserDataSource.getBlackList() - } -} diff --git a/domain/lectureevaluation/build.gradle.kts b/domain/lectureevaluation/build.gradle.kts deleted file mode 100644 index 9372055ea..000000000 --- a/domain/lectureevaluation/build.gradle.kts +++ /dev/null @@ -1,13 +0,0 @@ -@file:Suppress("DSL_SCOPE_VIOLATION") // @file:을 붙인 이유 -> https://github.com/gradle/gradle/issues/20131 - -plugins { - alias(libs.plugins.suwiki.java.library) -} - -dependencies { - implementation(projects.common.model) - implementation(projects.domain.common) - - implementation(libs.kotlinx.coroutines.core) - implementation(libs.hilt.core) -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/ExamEditorRepository.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/ExamEditorRepository.kt deleted file mode 100644 index 264dedaf0..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/ExamEditorRepository.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.suwiki.domain.lectureevaluation.repository - -interface ExamEditorRepository { - - suspend fun postExamEvaluation( - lectureId: Long, - lectureName: String?, - professor: String?, - selectedSemester: String?, - examInfo: String, - examType: String?, - examDifficulty: String, - content: String, - ) - - suspend fun updateExamEvaluation( - lectureId: Long, - selectedSemester: String?, - examInfo: String, - examType: String?, - examDifficulty: String, - content: String, - ) - - suspend fun deleteExamEvaluation(id: Long) -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/ExamMyRepository.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/ExamMyRepository.kt deleted file mode 100644 index ab4d2c601..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/ExamMyRepository.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.suwiki.domain.lectureevaluation.repository - -import com.suwiki.common.model.lectureevaluation.PurchaseHistory -import com.suwiki.common.model.lectureevaluation.exam.MyExamEvaluation - -interface ExamMyRepository { - - suspend fun getMyExamEvaluationList(page: Int): List - - suspend fun getPurchaseHistory(): List -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/ExamProviderRepository.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/ExamProviderRepository.kt deleted file mode 100644 index c84fb3b6a..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/ExamProviderRepository.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.suwiki.domain.lectureevaluation.repository - -import com.suwiki.common.model.lectureevaluation.exam.ExamEvaluationList - -interface ExamProviderRepository { - suspend fun buyExam(lectureId: Long) - - suspend fun getExamEvaluationList( - lectureId: Long, - page: Int, - ): ExamEvaluationList -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/ExamReportRepository.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/ExamReportRepository.kt deleted file mode 100644 index cef4dd555..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/ExamReportRepository.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.suwiki.domain.lectureevaluation.repository - -interface ExamReportRepository { - - suspend fun reportExam( - examIdx: Long, - content: String = "", - ) -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/LectureEditorRepository.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/LectureEditorRepository.kt deleted file mode 100644 index 6edd0f5e8..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/LectureEditorRepository.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.suwiki.domain.lectureevaluation.repository - -interface LectureEditorRepository { - - suspend fun postLectureEvaluation( - lectureId: Long, - lectureName: String, - professor: String, - selectedSemester: String, - satisfaction: Float, - learning: Float, - honey: Float, - team: Int, - difficulty: Int, - homework: Int, - content: String, - ) - - suspend fun updateLectureEvaluation( - lectureId: Long, - selectedSemester: String, - satisfaction: Float, - learning: Float, - honey: Float, - team: Int, - difficulty: Int, - homework: Int, - content: String, - ) - - suspend fun deleteLectureEvaluation(id: Long) -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/LectureMyRepository.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/LectureMyRepository.kt deleted file mode 100644 index b13e91aa6..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/LectureMyRepository.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.suwiki.domain.lectureevaluation.repository - -import com.suwiki.common.model.lectureevaluation.lecture.MyLectureEvaluation - -interface LectureMyRepository { - - suspend fun getMyLectureEvaluationList(page: Int): List -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/LectureProviderRepository.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/LectureProviderRepository.kt deleted file mode 100644 index 310fa79fb..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/LectureProviderRepository.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.suwiki.domain.lectureevaluation.repository - -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationAverage -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationExtraAverage -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationList - -interface LectureProviderRepository { - suspend fun getLectureEvaluationAverageList( - option: String, - page: Int = 1, - majorType: String = "", - ): List - - suspend fun retrieveLectureEvaluationAverageList( - search: String, - option: String, - page: Int, - majorType: String, - ): List - - suspend fun getLectureEvaluationExtraAverage(lectureId: Long): LectureEvaluationExtraAverage - - suspend fun getLectureEvaluationList( - lectureId: Long, - page: Int, - ): LectureEvaluationList -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/LectureReportRepository.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/LectureReportRepository.kt deleted file mode 100644 index 7cf9da2d6..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/repository/LectureReportRepository.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.suwiki.domain.lectureevaluation.repository - -interface LectureReportRepository { - - suspend fun reportLecture( - evaluateIdx: Long, - content: String = "", - ) -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/BuyExamUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/BuyExamUseCase.kt deleted file mode 100644 index 646b8a3fc..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/BuyExamUseCase.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.exam - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.ExamProviderRepository -import javax.inject.Inject - -class BuyExamUseCase @Inject constructor( - private val examProviderRepository: ExamProviderRepository, -) { - suspend operator fun invoke(lectureId: Long): Result = runCatchingIgnoreCancelled { - examProviderRepository.buyExam(lectureId = lectureId) - } -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/DeleteExamEvaluationUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/DeleteExamEvaluationUseCase.kt deleted file mode 100644 index 31ad4b925..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/DeleteExamEvaluationUseCase.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.exam - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.ExamEditorRepository -import javax.inject.Inject - -class DeleteExamEvaluationUseCase @Inject constructor( - private val examEditorRepository: ExamEditorRepository, -) { - suspend operator fun invoke(id: Long): Result = runCatchingIgnoreCancelled { - examEditorRepository.deleteExamEvaluation( - id = id, - ) - } -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/GetExamEvaluationListUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/GetExamEvaluationListUseCase.kt deleted file mode 100644 index d1f5c735d..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/GetExamEvaluationListUseCase.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.exam - -import com.suwiki.common.model.lectureevaluation.exam.ExamEvaluationList -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.ExamProviderRepository -import javax.inject.Inject - -class GetExamEvaluationListUseCase @Inject constructor( - private val examProviderRepository: ExamProviderRepository, -) { - suspend operator fun invoke(param: Param): Result = runCatchingIgnoreCancelled { - param.run { - examProviderRepository.getExamEvaluationList( - lectureId = lectureId, - page = page, - ) - } - } - - data class Param( - val lectureId: Long, - val page: Int, - ) -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/GetMyExamEvaluationListUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/GetMyExamEvaluationListUseCase.kt deleted file mode 100644 index 7e21ec371..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/GetMyExamEvaluationListUseCase.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.exam - -import com.suwiki.common.model.lectureevaluation.exam.MyExamEvaluation -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.ExamMyRepository -import javax.inject.Inject - -class GetMyExamEvaluationListUseCase @Inject constructor( - private val examMyRepository: ExamMyRepository, -) { - suspend operator fun invoke(page: Int): Result> = runCatchingIgnoreCancelled { - examMyRepository.getMyExamEvaluationList(page = page) - } -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/GetPurchaseHistoryUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/GetPurchaseHistoryUseCase.kt deleted file mode 100644 index f954eeb0f..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/GetPurchaseHistoryUseCase.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.exam - -import com.suwiki.common.model.lectureevaluation.PurchaseHistory -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.ExamMyRepository -import javax.inject.Inject - -class GetPurchaseHistoryUseCase @Inject constructor( - private val examMyRepository: ExamMyRepository, -) { - suspend operator fun invoke(): Result> = runCatchingIgnoreCancelled { - examMyRepository.getPurchaseHistory() - } -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/PostExamEvaluationUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/PostExamEvaluationUseCase.kt deleted file mode 100644 index 02474d6b1..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/PostExamEvaluationUseCase.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.exam - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.ExamEditorRepository -import javax.inject.Inject - -class PostExamEvaluationUseCase @Inject constructor( - private val examEditorRepository: ExamEditorRepository, -) { - suspend operator fun invoke(param: Param): Result = runCatchingIgnoreCancelled { - param.run { - examEditorRepository.postExamEvaluation( - lectureId = lectureId, - lectureName = lectureName, - professor = professor, - selectedSemester = selectedSemester, - examInfo = examInfo, - examType = examType, - examDifficulty = examDifficulty, - content = content, - ) - } - } - - data class Param( - val lectureId: Long, - val lectureName: String?, - val professor: String?, - val selectedSemester: String?, - val examInfo: String, - val examType: String?, - val examDifficulty: String, - val content: String, - ) -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/ReportExamUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/ReportExamUseCase.kt deleted file mode 100644 index 0305269bd..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/ReportExamUseCase.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.exam - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.ExamReportRepository -import javax.inject.Inject - -class ReportExamUseCase @Inject constructor( - private val examReportRepository: ExamReportRepository, -) { - suspend operator fun invoke(examIdx: Long): Result = runCatchingIgnoreCancelled { - examReportRepository.reportExam(examIdx = examIdx) - } -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/UpdateExamEvaluationUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/UpdateExamEvaluationUseCase.kt deleted file mode 100644 index 3eb9f009f..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/exam/UpdateExamEvaluationUseCase.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.exam - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.ExamEditorRepository -import javax.inject.Inject - -class UpdateExamEvaluationUseCase @Inject constructor( - private val examEditorRepository: ExamEditorRepository, -) { - suspend operator fun invoke(param: Param): Result = runCatchingIgnoreCancelled { - param.run { - examEditorRepository.updateExamEvaluation( - lectureId = lectureId, - selectedSemester = selectedSemester, - examInfo = examInfo, - examType = examType, - examDifficulty = examDifficulty, - content = content, - ) - } - } - - data class Param( - val lectureId: Long, - val selectedSemester: String?, - val examInfo: String, - val examType: String?, - val examDifficulty: String, - val content: String, - ) -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/DeleteLectureEvaluationUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/DeleteLectureEvaluationUseCase.kt deleted file mode 100644 index 524a93976..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/DeleteLectureEvaluationUseCase.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.lecture - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.LectureEditorRepository -import javax.inject.Inject - -class DeleteLectureEvaluationUseCase @Inject constructor( - private val lectureEditorRepository: LectureEditorRepository, -) { - suspend operator fun invoke(id: Long): Result = runCatchingIgnoreCancelled { - lectureEditorRepository.deleteLectureEvaluation( - id = id, - ) - } -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/GetLectureEvaluationAverageListUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/GetLectureEvaluationAverageListUseCase.kt deleted file mode 100644 index 3d4265312..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/GetLectureEvaluationAverageListUseCase.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.lecture - -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationAverage -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.LectureProviderRepository -import javax.inject.Inject - -class GetLectureEvaluationAverageListUseCase @Inject constructor( - private val lectureProviderRepository: LectureProviderRepository, -) { - suspend operator fun invoke(param: Param): Result> = runCatchingIgnoreCancelled { - param.run { - lectureProviderRepository.getLectureEvaluationAverageList( - option = option, - page = page, - majorType = majorType, - ) - } - } - - data class Param( - val option: String, - val page: Int, - val majorType: String, - ) -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/GetLectureEvaluationExtraAverageUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/GetLectureEvaluationExtraAverageUseCase.kt deleted file mode 100644 index d6d7bc531..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/GetLectureEvaluationExtraAverageUseCase.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.lecture - -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationExtraAverage -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.LectureProviderRepository -import javax.inject.Inject - -class GetLectureEvaluationExtraAverageUseCase @Inject constructor( - private val lectureProviderRepository: LectureProviderRepository, -) { - suspend operator fun invoke(lectureId: Long): Result = runCatchingIgnoreCancelled { - lectureProviderRepository.getLectureEvaluationExtraAverage( - lectureId = lectureId, - ) - } -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/GetLectureEvaluationListUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/GetLectureEvaluationListUseCase.kt deleted file mode 100644 index c811d5c2d..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/GetLectureEvaluationListUseCase.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.lecture - -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationList -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.LectureProviderRepository -import javax.inject.Inject - -class GetLectureEvaluationListUseCase @Inject constructor( - private val lectureProviderRepository: LectureProviderRepository, -) { - suspend operator fun invoke(param: Param): Result = runCatchingIgnoreCancelled { - param.run { - lectureProviderRepository.getLectureEvaluationList( - lectureId = lectureId, - page = page, - ) - } - } - - data class Param( - val lectureId: Long, - val page: Int, - ) -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/GetMyLectureEvaluationListUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/GetMyLectureEvaluationListUseCase.kt deleted file mode 100644 index cbfddc42e..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/GetMyLectureEvaluationListUseCase.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.lecture - -import com.suwiki.common.model.lectureevaluation.lecture.MyLectureEvaluation -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.LectureMyRepository -import javax.inject.Inject - -class GetMyLectureEvaluationListUseCase @Inject constructor( - private val lectureMyRepository: LectureMyRepository, -) { - suspend operator fun invoke(page: Int): Result> = runCatchingIgnoreCancelled { - lectureMyRepository.getMyLectureEvaluationList(page = page) - } -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/PostLectureEvaluationUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/PostLectureEvaluationUseCase.kt deleted file mode 100644 index 0b25142c6..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/PostLectureEvaluationUseCase.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.lecture - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.LectureEditorRepository -import javax.inject.Inject - -class PostLectureEvaluationUseCase @Inject constructor( - private val lectureEditorRepository: LectureEditorRepository, -) { - suspend operator fun invoke(param: Param): Result = runCatchingIgnoreCancelled { - param.run { - lectureEditorRepository.postLectureEvaluation( - lectureId = id, - lectureName = lectureName, - professor = professor, - selectedSemester = selectedSemester, - satisfaction = satisfaction, - learning = learning, - honey = honey, - team = team, - difficulty = difficulty, - homework = homework, - content = content, - ) - } - } - - data class Param( - val id: Long, - val lectureName: String, - val professor: String, - val selectedSemester: String, - val satisfaction: Float, - val learning: Float, - val honey: Float, - val team: Int, - val difficulty: Int, - val homework: Int, - val content: String, - ) -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/ReportLectureUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/ReportLectureUseCase.kt deleted file mode 100644 index 790bec38c..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/ReportLectureUseCase.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.lecture - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.LectureReportRepository -import javax.inject.Inject - -class ReportLectureUseCase @Inject constructor( - private val lectureReportRepository: LectureReportRepository, -) { - suspend operator fun invoke(evaluateIdx: Long): Result = runCatchingIgnoreCancelled { - lectureReportRepository.reportLecture(evaluateIdx = evaluateIdx) - } -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/RetrieveLectureEvaluationAverageListUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/RetrieveLectureEvaluationAverageListUseCase.kt deleted file mode 100644 index 199202851..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/RetrieveLectureEvaluationAverageListUseCase.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.lecture - -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationAverage -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.LectureProviderRepository -import javax.inject.Inject - -class RetrieveLectureEvaluationAverageListUseCase @Inject constructor( - private val lectureProviderRepository: LectureProviderRepository, -) { - suspend operator fun invoke(param: Param): Result> = runCatchingIgnoreCancelled { - param.run { - lectureProviderRepository.retrieveLectureEvaluationAverageList( - search = search, - option = option, - page = page, - majorType = majorType, - ) - } - } - - data class Param( - val search: String, - val option: String, - val page: Int, - val majorType: String, - ) -} diff --git a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/UpdateLectureEvaluationUseCase.kt b/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/UpdateLectureEvaluationUseCase.kt deleted file mode 100644 index 8f12d1003..000000000 --- a/domain/lectureevaluation/src/main/java/com/suwiki/domain/lectureevaluation/usecase/lecture/UpdateLectureEvaluationUseCase.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.suwiki.domain.lectureevaluation.usecase.lecture - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.lectureevaluation.repository.LectureEditorRepository -import javax.inject.Inject - -class UpdateLectureEvaluationUseCase @Inject constructor( - private val lectureEditorRepository: LectureEditorRepository, -) { - suspend operator fun invoke(param: Param): Result = runCatchingIgnoreCancelled { - with(param) { - lectureEditorRepository.updateLectureEvaluation( - lectureId = lectureId, - selectedSemester = selectedSemester, - satisfaction = satisfaction, - learning = learning, - honey = honey, - team = team, - difficulty = difficulty, - homework = homework, - content = content, - ) - } - } - - data class Param( - val lectureId: Long, - val selectedSemester: String, - val satisfaction: Float, - val learning: Float, - val honey: Float, - val team: Int, - val difficulty: Int, - val homework: Int, - val content: String, - ) -} diff --git a/domain/login/.gitignore b/domain/login/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/domain/login/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/domain/login/build.gradle.kts b/domain/login/build.gradle.kts deleted file mode 100644 index 9372055ea..000000000 --- a/domain/login/build.gradle.kts +++ /dev/null @@ -1,13 +0,0 @@ -@file:Suppress("DSL_SCOPE_VIOLATION") // @file:을 붙인 이유 -> https://github.com/gradle/gradle/issues/20131 - -plugins { - alias(libs.plugins.suwiki.java.library) -} - -dependencies { - implementation(projects.common.model) - implementation(projects.domain.common) - - implementation(libs.kotlinx.coroutines.core) - implementation(libs.hilt.core) -} diff --git a/domain/login/src/main/java/com/suwiki/domain/login/repository/LoginRepository.kt b/domain/login/src/main/java/com/suwiki/domain/login/repository/LoginRepository.kt deleted file mode 100644 index f6a1450c2..000000000 --- a/domain/login/src/main/java/com/suwiki/domain/login/repository/LoginRepository.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.suwiki.domain.login.repository - -interface LoginRepository { - - suspend fun findId(email: String) - - suspend fun findPassword( - loginId: String, - email: String, - ) - - suspend fun login( - loginId: String, - password: String, - ) -} diff --git a/domain/login/src/main/java/com/suwiki/domain/login/usecase/FindIdUseCase.kt b/domain/login/src/main/java/com/suwiki/domain/login/usecase/FindIdUseCase.kt deleted file mode 100644 index db45f953f..000000000 --- a/domain/login/src/main/java/com/suwiki/domain/login/usecase/FindIdUseCase.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.suwiki.domain.login.usecase - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.login.repository.LoginRepository -import javax.inject.Inject - -class FindIdUseCase @Inject constructor( - private val loginRepository: LoginRepository, -) { - suspend operator fun invoke(email: String): Result = runCatchingIgnoreCancelled { - loginRepository.findId(email) - } -} diff --git a/domain/login/src/main/java/com/suwiki/domain/login/usecase/FindPasswordUseCase.kt b/domain/login/src/main/java/com/suwiki/domain/login/usecase/FindPasswordUseCase.kt deleted file mode 100644 index 935830166..000000000 --- a/domain/login/src/main/java/com/suwiki/domain/login/usecase/FindPasswordUseCase.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.suwiki.domain.login.usecase - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.login.repository.LoginRepository -import javax.inject.Inject - -class FindPasswordUseCase @Inject constructor( - private val loginRepository: LoginRepository, -) { - suspend operator fun invoke( - loginId: String, - email: String, - ): Result = runCatchingIgnoreCancelled { - loginRepository.findPassword( - loginId = loginId, - email = email, - ) - } -} diff --git a/domain/login/src/main/java/com/suwiki/domain/login/usecase/LoginUseCase.kt b/domain/login/src/main/java/com/suwiki/domain/login/usecase/LoginUseCase.kt deleted file mode 100644 index aa82bbab4..000000000 --- a/domain/login/src/main/java/com/suwiki/domain/login/usecase/LoginUseCase.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.suwiki.domain.login.usecase - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.login.repository.LoginRepository -import javax.inject.Inject - -class LoginUseCase @Inject constructor( - private val loginRepository: LoginRepository, -) { - suspend operator fun invoke( - loginId: String, - password: String, - ): Result = runCatchingIgnoreCancelled { - loginRepository.login( - loginId = loginId, - password = password, - ) - } -} diff --git a/domain/notice/.gitignore b/domain/notice/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/domain/notice/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/domain/notice/build.gradle.kts b/domain/notice/build.gradle.kts deleted file mode 100644 index 9372055ea..000000000 --- a/domain/notice/build.gradle.kts +++ /dev/null @@ -1,13 +0,0 @@ -@file:Suppress("DSL_SCOPE_VIOLATION") // @file:을 붙인 이유 -> https://github.com/gradle/gradle/issues/20131 - -plugins { - alias(libs.plugins.suwiki.java.library) -} - -dependencies { - implementation(projects.common.model) - implementation(projects.domain.common) - - implementation(libs.kotlinx.coroutines.core) - implementation(libs.hilt.core) -} diff --git a/domain/notice/src/main/java/com/suwiki/domain/notice/repository/NoticeRepository.kt b/domain/notice/src/main/java/com/suwiki/domain/notice/repository/NoticeRepository.kt deleted file mode 100644 index cb182c739..000000000 --- a/domain/notice/src/main/java/com/suwiki/domain/notice/repository/NoticeRepository.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.suwiki.domain.notice.repository - -import com.suwiki.common.model.notice.Notice -import com.suwiki.common.model.notice.NoticeDetail - -interface NoticeRepository { - - suspend fun getNoticeList(page: Int): List - - suspend fun getNoticeDetail(id: Long): NoticeDetail - - suspend fun checkUpdateMandatory( - versionCode: Long, - ): Boolean -} diff --git a/domain/notice/src/main/java/com/suwiki/domain/notice/usecase/CheckUpdateMandatoryUseCase.kt b/domain/notice/src/main/java/com/suwiki/domain/notice/usecase/CheckUpdateMandatoryUseCase.kt deleted file mode 100644 index 558c4cafc..000000000 --- a/domain/notice/src/main/java/com/suwiki/domain/notice/usecase/CheckUpdateMandatoryUseCase.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.suwiki.domain.notice.usecase - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.notice.repository.NoticeRepository -import javax.inject.Inject - -class CheckUpdateMandatoryUseCase @Inject constructor( - private val noticeRepository: NoticeRepository, -) { - suspend operator fun invoke(versionCode: Long): Result = runCatchingIgnoreCancelled { - noticeRepository.checkUpdateMandatory(versionCode) - } -} diff --git a/domain/notice/src/main/java/com/suwiki/domain/notice/usecase/GetNoticeDetailUseCase.kt b/domain/notice/src/main/java/com/suwiki/domain/notice/usecase/GetNoticeDetailUseCase.kt deleted file mode 100644 index 1c1fb7d5b..000000000 --- a/domain/notice/src/main/java/com/suwiki/domain/notice/usecase/GetNoticeDetailUseCase.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.suwiki.domain.notice.usecase - -import com.suwiki.common.model.notice.NoticeDetail -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.notice.repository.NoticeRepository -import javax.inject.Inject - -class GetNoticeDetailUseCase @Inject constructor( - private val noticeRepository: NoticeRepository, -) { - suspend operator fun invoke(id: Long): Result = runCatchingIgnoreCancelled { - noticeRepository.getNoticeDetail(id) - } -} diff --git a/domain/notice/src/main/java/com/suwiki/domain/notice/usecase/GetNoticeListUseCase.kt b/domain/notice/src/main/java/com/suwiki/domain/notice/usecase/GetNoticeListUseCase.kt deleted file mode 100644 index fe22405e0..000000000 --- a/domain/notice/src/main/java/com/suwiki/domain/notice/usecase/GetNoticeListUseCase.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.suwiki.domain.notice.usecase - -import com.suwiki.common.model.notice.Notice -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.notice.repository.NoticeRepository -import javax.inject.Inject - -class GetNoticeListUseCase @Inject constructor( - private val noticeRepository: NoticeRepository, -) { - suspend operator fun invoke(page: Int): Result> = runCatchingIgnoreCancelled { - noticeRepository.getNoticeList(page) - } -} diff --git a/domain/signup/.gitignore b/domain/signup/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/domain/signup/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/domain/signup/build.gradle.kts b/domain/signup/build.gradle.kts deleted file mode 100644 index b0b56a2d3..000000000 --- a/domain/signup/build.gradle.kts +++ /dev/null @@ -1,12 +0,0 @@ -@file:Suppress("DSL_SCOPE_VIOLATION") // @file:을 붙인 이유 -> https://github.com/gradle/gradle/issues/20131 - -plugins { - alias(libs.plugins.suwiki.java.library) -} - -dependencies { - implementation(projects.domain.common) - - implementation(libs.kotlinx.coroutines.core) - implementation(libs.hilt.core) -} diff --git a/domain/signup/src/main/java/com/suwiki/domain/signup/repository/SignupRepository.kt b/domain/signup/src/main/java/com/suwiki/domain/signup/repository/SignupRepository.kt deleted file mode 100644 index 00f12b21b..000000000 --- a/domain/signup/src/main/java/com/suwiki/domain/signup/repository/SignupRepository.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.suwiki.domain.signup.repository - -interface SignupRepository { - suspend fun signUp( - id: String, - password: String, - email: String, - ) - - suspend fun checkIdOverlap(loginId: String): Boolean - - suspend fun checkEmailOverlap(email: String): Boolean -} diff --git a/domain/signup/src/main/java/com/suwiki/domain/signup/usecase/CheckEmailOverlapUseCase.kt b/domain/signup/src/main/java/com/suwiki/domain/signup/usecase/CheckEmailOverlapUseCase.kt deleted file mode 100644 index 2ef04b88d..000000000 --- a/domain/signup/src/main/java/com/suwiki/domain/signup/usecase/CheckEmailOverlapUseCase.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.suwiki.domain.signup.usecase - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.signup.repository.SignupRepository -import javax.inject.Inject - -class CheckEmailOverlapUseCase @Inject constructor( - private val signUpRepository: SignupRepository, -) { - suspend operator fun invoke(email: String): Result = runCatchingIgnoreCancelled { - signUpRepository.checkEmailOverlap(email = email) - } -} diff --git a/domain/signup/src/main/java/com/suwiki/domain/signup/usecase/CheckIdOverlapUseCase.kt b/domain/signup/src/main/java/com/suwiki/domain/signup/usecase/CheckIdOverlapUseCase.kt deleted file mode 100644 index d4ef24d4c..000000000 --- a/domain/signup/src/main/java/com/suwiki/domain/signup/usecase/CheckIdOverlapUseCase.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.suwiki.domain.signup.usecase - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.signup.repository.SignupRepository -import javax.inject.Inject - -class CheckIdOverlapUseCase @Inject constructor( - private val signUpRepository: SignupRepository, -) { - suspend operator fun invoke(id: String): Result = runCatchingIgnoreCancelled { - signUpRepository.checkIdOverlap(loginId = id) - } -} diff --git a/domain/signup/src/main/java/com/suwiki/domain/signup/usecase/SignupUseCase.kt b/domain/signup/src/main/java/com/suwiki/domain/signup/usecase/SignupUseCase.kt deleted file mode 100644 index 78b99a605..000000000 --- a/domain/signup/src/main/java/com/suwiki/domain/signup/usecase/SignupUseCase.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.suwiki.domain.signup.usecase - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.signup.repository.SignupRepository -import javax.inject.Inject - -class SignupUseCase @Inject constructor( - private val signupRepository: SignupRepository, -) { - suspend operator fun invoke(param: Param): Result = runCatchingIgnoreCancelled { - signupRepository.signUp( - id = param.id, - password = param.password, - email = param.email, - ) - } - - data class Param( - val id: String, - val password: String, - val email: String, - ) -} diff --git a/domain/user/.gitignore b/domain/user/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/domain/user/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/domain/user/build.gradle.kts b/domain/user/build.gradle.kts deleted file mode 100644 index 9372055ea..000000000 --- a/domain/user/build.gradle.kts +++ /dev/null @@ -1,13 +0,0 @@ -@file:Suppress("DSL_SCOPE_VIOLATION") // @file:을 붙인 이유 -> https://github.com/gradle/gradle/issues/20131 - -plugins { - alias(libs.plugins.suwiki.java.library) -} - -dependencies { - implementation(projects.common.model) - implementation(projects.domain.common) - - implementation(libs.kotlinx.coroutines.core) - implementation(libs.hilt.core) -} diff --git a/domain/user/src/main/java/com/suwiki/domain/user/repository/UserRepository.kt b/domain/user/src/main/java/com/suwiki/domain/user/repository/UserRepository.kt deleted file mode 100644 index b68f7f3db..000000000 --- a/domain/user/src/main/java/com/suwiki/domain/user/repository/UserRepository.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.suwiki.domain.user.repository - -import com.suwiki.common.model.user.Suspension -import com.suwiki.common.model.user.User -import kotlinx.coroutines.flow.Flow - -interface UserRepository { - - suspend fun logout() - - suspend fun resetPassword( - currentPassword: String, - newPassword: String, - ) - - suspend fun quit( - id: String, - password: String, - ) - - suspend fun getUserInfo(): Flow - - suspend fun getBanHistory(): List - suspend fun getBlackList(): List -} diff --git a/domain/user/src/main/java/com/suwiki/domain/user/usecase/GetBanHistoryUseCase.kt b/domain/user/src/main/java/com/suwiki/domain/user/usecase/GetBanHistoryUseCase.kt deleted file mode 100644 index 78b2464cf..000000000 --- a/domain/user/src/main/java/com/suwiki/domain/user/usecase/GetBanHistoryUseCase.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.suwiki.domain.user.usecase - -import com.suwiki.common.model.user.Suspension -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.user.repository.UserRepository -import javax.inject.Inject - -class GetBanHistoryUseCase @Inject constructor( - private val userRepository: UserRepository, -) { - suspend operator fun invoke(): Result> = runCatchingIgnoreCancelled { - userRepository.getBanHistory() - } -} diff --git a/domain/user/src/main/java/com/suwiki/domain/user/usecase/GetBlackListUseCase.kt b/domain/user/src/main/java/com/suwiki/domain/user/usecase/GetBlackListUseCase.kt deleted file mode 100644 index 01eea89e6..000000000 --- a/domain/user/src/main/java/com/suwiki/domain/user/usecase/GetBlackListUseCase.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.suwiki.domain.user.usecase - -import com.suwiki.common.model.user.Suspension -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.user.repository.UserRepository -import javax.inject.Inject - -class GetBlackListUseCase @Inject constructor( - private val userRepository: UserRepository, -) { - suspend operator fun invoke(): Result> = runCatchingIgnoreCancelled { - userRepository.getBlackList() - } -} diff --git a/domain/user/src/main/java/com/suwiki/domain/user/usecase/GetUserInfoUseCase.kt b/domain/user/src/main/java/com/suwiki/domain/user/usecase/GetUserInfoUseCase.kt deleted file mode 100644 index 7628f512b..000000000 --- a/domain/user/src/main/java/com/suwiki/domain/user/usecase/GetUserInfoUseCase.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.suwiki.domain.user.usecase - -import com.suwiki.common.model.user.User -import com.suwiki.domain.user.repository.UserRepository -import kotlinx.coroutines.flow.Flow -import javax.inject.Inject - -class GetUserInfoUseCase @Inject constructor( - private val userRepository: UserRepository, -) { - suspend operator fun invoke(): Flow = userRepository.getUserInfo() -} diff --git a/domain/user/src/main/java/com/suwiki/domain/user/usecase/LogoutUseCase.kt b/domain/user/src/main/java/com/suwiki/domain/user/usecase/LogoutUseCase.kt deleted file mode 100644 index 7785fb1af..000000000 --- a/domain/user/src/main/java/com/suwiki/domain/user/usecase/LogoutUseCase.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.suwiki.domain.user.usecase - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.user.repository.UserRepository -import javax.inject.Inject - -class LogoutUseCase @Inject constructor( - private val userRepository: UserRepository, -) { - suspend operator fun invoke(): Result = runCatchingIgnoreCancelled { - userRepository.logout() - } -} diff --git a/domain/user/src/main/java/com/suwiki/domain/user/usecase/QuitUseCase.kt b/domain/user/src/main/java/com/suwiki/domain/user/usecase/QuitUseCase.kt deleted file mode 100644 index c5374e14f..000000000 --- a/domain/user/src/main/java/com/suwiki/domain/user/usecase/QuitUseCase.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.suwiki.domain.user.usecase - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.user.repository.UserRepository -import javax.inject.Inject - -class QuitUseCase @Inject constructor( - private val userRepository: UserRepository, -) { - suspend operator fun invoke( - id: String, - password: String, - ): Result = runCatchingIgnoreCancelled { - userRepository.quit( - id = id, - password = password, - ) - } -} diff --git a/domain/user/src/main/java/com/suwiki/domain/user/usecase/ResetPasswordUseCase.kt b/domain/user/src/main/java/com/suwiki/domain/user/usecase/ResetPasswordUseCase.kt deleted file mode 100644 index 1c66b497c..000000000 --- a/domain/user/src/main/java/com/suwiki/domain/user/usecase/ResetPasswordUseCase.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.suwiki.domain.user.usecase - -import com.suwiki.domain.common.runCatchingIgnoreCancelled -import com.suwiki.domain.user.repository.UserRepository -import javax.inject.Inject - -class ResetPasswordUseCase @Inject constructor( - private val userRepository: UserRepository, -) { - suspend operator fun invoke( - currentPassword: String, - newPassword: String, - ): Result = runCatchingIgnoreCancelled { - userRepository.resetPassword( - currentPassword = currentPassword, - newPassword = newPassword, - ) - } -} diff --git a/local/login/.gitignore b/local/login/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/local/login/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/local/login/build.gradle.kts b/local/login/build.gradle.kts deleted file mode 100644 index 385227509..000000000 --- a/local/login/build.gradle.kts +++ /dev/null @@ -1,20 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.library) - alias(libs.plugins.suwiki.android.hilt) -} - -android { - namespace = "com.suwiki.local.login" -} - -dependencies { - implementation(projects.common.model) - implementation(projects.data.login) - implementation(projects.common.security) - - implementation(libs.bundles.coroutine) - - testImplementation(libs.junit4) - androidTestImplementation(libs.junit4) -} diff --git a/local/login/consumer-rules.pro b/local/login/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/local/login/proguard-rules.pro b/local/login/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/local/login/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/local/login/src/main/AndroidManifest.xml b/local/login/src/main/AndroidManifest.xml deleted file mode 100644 index 8bdb7e14b..000000000 --- a/local/login/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/local/login/src/main/java/com/suwiki/local/login/datasource/LocalLoginDataSourceImpl.kt b/local/login/src/main/java/com/suwiki/local/login/datasource/LocalLoginDataSourceImpl.kt deleted file mode 100644 index 6adf126ae..000000000 --- a/local/login/src/main/java/com/suwiki/local/login/datasource/LocalLoginDataSourceImpl.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.suwiki.local.login.datasource - -import com.suwiki.common.model.user.Token -import com.suwiki.common.security.SecurityPreferences -import com.suwiki.data.login.datasource.LocalLoginDataSource -import javax.inject.Inject - -class LocalLoginDataSourceImpl @Inject constructor( - private val securityPreferences: SecurityPreferences, -) : LocalLoginDataSource { - - override suspend fun setToken(token: Token) { - token.run { - securityPreferences.setAccessToken(accessToken) - securityPreferences.setRefreshToken(refreshToken) - } - } -} diff --git a/local/login/src/main/java/com/suwiki/local/login/di/LocalDataSourceModule.kt b/local/login/src/main/java/com/suwiki/local/login/di/LocalDataSourceModule.kt deleted file mode 100644 index 9287a674f..000000000 --- a/local/login/src/main/java/com/suwiki/local/login/di/LocalDataSourceModule.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.suwiki.local.login.di - -import com.suwiki.data.login.datasource.LocalLoginDataSource -import com.suwiki.local.login.datasource.LocalLoginDataSourceImpl -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -abstract class LocalDataSourceModule { - - @Singleton - @Binds - abstract fun bindLocalLoginDataSource( - localLoginDataSourceImpl: LocalLoginDataSourceImpl, - ): LocalLoginDataSource -} diff --git a/local/user/.gitignore b/local/user/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/local/user/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/local/user/build.gradle.kts b/local/user/build.gradle.kts deleted file mode 100644 index ed70a24aa..000000000 --- a/local/user/build.gradle.kts +++ /dev/null @@ -1,23 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.library) - alias(libs.plugins.suwiki.android.hilt) -} - -android { - namespace = "com.suwiki.local.user" -} - -dependencies { - implementation(projects.common.model) - implementation(projects.data.user) - implementation(projects.local.common) - - implementation(libs.bundles.coroutine) - implementation(libs.androidx.datastore.core) - implementation(libs.androidx.datastore.preferences) - implementation(libs.protobuf.kotlin.lite) - - testImplementation(libs.junit4) - androidTestImplementation(libs.junit4) -} diff --git a/local/user/consumer-rules.pro b/local/user/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/local/user/proguard-rules.pro b/local/user/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/local/user/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/local/user/src/main/AndroidManifest.xml b/local/user/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e68a..000000000 --- a/local/user/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/local/user/src/main/java/com/suwiki/local/user/datasource/LocalUserDataSourceImpl.kt b/local/user/src/main/java/com/suwiki/local/user/datasource/LocalUserDataSourceImpl.kt deleted file mode 100644 index f18be69d6..000000000 --- a/local/user/src/main/java/com/suwiki/local/user/datasource/LocalUserDataSourceImpl.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.suwiki.local.user.datasource - -import androidx.datastore.core.DataStore -import com.suwiki.common.model.user.DEFAULT_USER_EMAIL -import com.suwiki.common.model.user.DEFAULT_USER_ID -import com.suwiki.common.model.user.DEFAULT_USER_POINT -import com.suwiki.common.model.user.DEFAULT_USER_VIEW_EXAM -import com.suwiki.common.model.user.DEFAULT_USER_WRITTEN_EVALUATION -import com.suwiki.common.model.user.DEFAULT_USER_WRITTEN_EXAM -import com.suwiki.common.model.user.User -import com.suwiki.data.user.datasource.LocalUserDataSource -import com.suwiki.local.common.UserPreference -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map -import javax.inject.Inject - -class LocalUserDataSourceImpl @Inject constructor( - private val dataStore: DataStore, -) : LocalUserDataSource { - - override val user: Flow - get() = dataStore.data.map { - User( - userId = it.userId, - email = it.email, - point = it.point, - writtenEvaluation = it.writtenEvaluation, - writtenExam = it.writtenExam, - viewExam = it.viewExam, - ) - } - - override suspend fun setUserInfo(user: User) { - user.run { - dataStore.updateData { userPref -> - userPref - .toBuilder() - .setUserId(userId) - .setEmail(email) - .setPoint(point) - .setWrittenEvaluation(writtenEvaluation) - .setWrittenExam(writtenExam) - .setViewExam(viewExam) - .build() - } - } - } - - override suspend fun clearUserInfo() { - dataStore.updateData { userPref -> - userPref - .toBuilder() - .setUserId(DEFAULT_USER_ID) - .setEmail(DEFAULT_USER_EMAIL) - .setPoint(DEFAULT_USER_POINT) - .setWrittenEvaluation(DEFAULT_USER_WRITTEN_EVALUATION) - .setWrittenExam(DEFAULT_USER_WRITTEN_EXAM) - .setViewExam(DEFAULT_USER_VIEW_EXAM) - .build() - } - } -} diff --git a/local/user/src/main/java/com/suwiki/local/user/di/LocalDataSourceModule.kt b/local/user/src/main/java/com/suwiki/local/user/di/LocalDataSourceModule.kt deleted file mode 100644 index 05d9daf07..000000000 --- a/local/user/src/main/java/com/suwiki/local/user/di/LocalDataSourceModule.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.suwiki.local.user.di - -import com.suwiki.data.user.datasource.LocalUserDataSource -import com.suwiki.local.user.datasource.LocalUserDataSourceImpl -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -abstract class LocalDataSourceModule { - - @Singleton - @Binds - abstract fun bindLocalUserProviderDataSource( - localUserProviderDataSourceImpl: LocalUserDataSourceImpl, - ): LocalUserDataSource -} diff --git a/presentation/lectureevaluation/.gitignore b/presentation/lectureevaluation/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/presentation/lectureevaluation/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/presentation/lectureevaluation/build.gradle.kts b/presentation/lectureevaluation/build.gradle.kts deleted file mode 100644 index a28e7e068..000000000 --- a/presentation/lectureevaluation/build.gradle.kts +++ /dev/null @@ -1,16 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.presentation.compose) -} - -android { - namespace = "com.suwiki.presentation.lectureevaluation" -} - -dependencies { - implementation(projects.domain.user) - implementation(projects.domain.lectureevaluation) - - implementation(libs.kotlinx.serialization.json) - implementation(libs.compose.toolbar) -} diff --git a/presentation/lectureevaluation/consumer-rules.pro b/presentation/lectureevaluation/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/presentation/lectureevaluation/proguard-rules.pro b/presentation/lectureevaluation/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/presentation/lectureevaluation/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/presentation/lectureevaluation/src/main/AndroidManifest.xml b/presentation/lectureevaluation/src/main/AndroidManifest.xml deleted file mode 100644 index 8bdb7e14b..000000000 --- a/presentation/lectureevaluation/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/examevaluation/ExamEvaluationEditorViewModel.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/examevaluation/ExamEvaluationEditorViewModel.kt deleted file mode 100644 index 2f31306c3..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/examevaluation/ExamEvaluationEditorViewModel.kt +++ /dev/null @@ -1,172 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.examevaluation - -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel -import com.suwiki.common.model.enums.ExamInfo -import com.suwiki.common.model.enums.ExamLevel -import com.suwiki.common.model.enums.ExamType -import com.suwiki.common.model.lectureevaluation.exam.MyExamEvaluation -import com.suwiki.domain.lectureevaluation.usecase.exam.PostExamEvaluationUseCase -import com.suwiki.domain.lectureevaluation.usecase.exam.UpdateExamEvaluationUseCase -import com.suwiki.presentation.common.ui.extension.decodeFromUri -import com.suwiki.presentation.lectureevaluation.navigation.EvaluationEditorRoute -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.collections.immutable.toPersistentList -import kotlinx.serialization.json.Json -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.annotation.OrbitExperimental -import org.orbitmvi.orbit.syntax.simple.blockingIntent -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class ExamEvaluationEditorViewModel @Inject constructor( - savedStateHandle: SavedStateHandle, - val postExamEvaluationUseCase: PostExamEvaluationUseCase, - val updateExamEvaluationUseCase: UpdateExamEvaluationUseCase, -) : ContainerHost, ViewModel() { - override val container: Container = - container(ExamEvaluationEditorState()) - - private val myExamEvaluation = savedStateHandle.get(EvaluationEditorRoute.examEvaluation)!! - private val myExamEvaluationItem: MyExamEvaluation = Json.decodeFromUri(myExamEvaluation) - private val isEditMode = myExamEvaluationItem.content.isNotEmpty() - - suspend fun initData() = intent { - showLoadingScreen() - - with(myExamEvaluationItem) { - reduce { - state.copy( - semesterList = semesterList.toPersistentList(), - selectedSemester = selectedSemester, - selectedExamType = examType, - ) - } - examInfo.forEach { info -> - ExamInfo.entries.forEach { - if (it.value == info) { - updateExamInfo(it) - } - } - } - ExamLevel.entries.forEach { - if (it.value == examDifficulty) { - updateExamLevel(it) - } - } - updateMyExamEvaluationValue(content) - } - hideLoadingScreen() - } - - fun postOrUpdateExamEvaluation() = intent { - if (state.examEvaluation.length < 30) { - postSideEffect(ExamEvaluationEditorSideEffect.ShowInputMoreTextToast) - return@intent - } - - if (state.selectedSemester.isNullOrEmpty()) { - postSideEffect(ExamEvaluationEditorSideEffect.ShowSelectSemesterToast) - return@intent - } - - if (state.selectedExamType.isNullOrEmpty()) { - postSideEffect(ExamEvaluationEditorSideEffect.ShowSelectExamTypeToast) - return@intent - } - - if (isEditMode) { - updateExamEvaluation() - } else { - postExamEvaluation() - } - } - - private fun postExamEvaluation() = intent { - postExamEvaluationUseCase( - PostExamEvaluationUseCase.Param( - lectureId = myExamEvaluationItem.id, - lectureName = myExamEvaluationItem.lectureName, - professor = myExamEvaluationItem.professor, - selectedSemester = state.selectedSemester, - examInfo = state.examInfo.filter { it.isNotBlank() }.joinToString(", "), - examType = state.selectedExamType, - examDifficulty = state.examLevel!!.value, - content = state.examEvaluation, - ), - ) - .onSuccess { - popBackStack() - } - .onFailure { - postSideEffect(ExamEvaluationEditorSideEffect.HandleException(it)) - } - } - - private fun updateExamEvaluation() = intent { - updateExamEvaluationUseCase( - UpdateExamEvaluationUseCase.Param( - lectureId = myExamEvaluationItem.id, - selectedSemester = state.selectedSemester, - examInfo = state.examInfo.filter { it.isNotBlank() }.joinToString(", "), - examType = state.selectedExamType, - examDifficulty = state.examLevel!!.value, - content = state.examEvaluation, - ), - ) - .onSuccess { - popBackStack() - } - .onFailure { - postSideEffect(ExamEvaluationEditorSideEffect.HandleException(it)) - } - } - - fun updateSemester(selectedPosition: Int) = intent { - reduce { state.copy(selectedSemester = state.semesterList[selectedPosition]) } - hideSemesterBottomSheet() - } - - fun updateExamType(selectedPosition: Int) = intent { - ExamType.entries.forEach { examType -> - if (examType.ordinal == selectedPosition) { - reduce { state.copy(selectedExamType = examType.value) } - } - } - hideExamTypeBottomSheet() - } - - fun updateExamLevel(examLevel: ExamLevel) = intent { - reduce { state.copy(examLevel = examLevel) } - } - - fun updateExamInfo(info: ExamInfo) = intent { - val examInfoList = state.examInfo.toMutableList() - - if (info.value in state.examInfo) { - examInfoList.remove(info.value) - } else { - examInfoList.add(info.value) - } - reduce { state.copy(examInfo = examInfoList.toPersistentList()) } - } - - @OptIn(OrbitExperimental::class) - fun updateMyExamEvaluationValue(examEvaluationValue: String) = blockingIntent { - reduce { state.copy(examEvaluation = examEvaluationValue) } - } - - private fun showLoadingScreen() = intent { reduce { state.copy(isLoading = true) } } - private fun hideLoadingScreen() = intent { reduce { state.copy(isLoading = false) } } - fun showSemesterBottomSheet() = intent { reduce { state.copy(showSemesterBottomSheet = true) } } - fun hideSemesterBottomSheet() = intent { reduce { state.copy(showSemesterBottomSheet = false) } } - fun showExamTypeBottomSheet() = intent { reduce { state.copy(showExamTypeBottomSheet = true) } } - fun hideExamTypeBottomSheet() = intent { reduce { state.copy(showExamTypeBottomSheet = false) } } - - fun popBackStack() = intent { postSideEffect(ExamEvaluationEditorSideEffect.PopBackStack) } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/examevaluation/ExamEvalutionEditorContract.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/examevaluation/ExamEvalutionEditorContract.kt deleted file mode 100644 index 7c82e1ecd..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/examevaluation/ExamEvalutionEditorContract.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.examevaluation - -import com.suwiki.common.model.enums.ExamLevel -import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.persistentListOf - -data class ExamEvaluationEditorState( - val isLoading: Boolean = false, - val point: Int = 0, - val semesterList: PersistentList = persistentListOf(""), - val selectedSemester: String? = null, - val selectedExamType: String? = null, - val selectedSemesterPosition: Int? = null, - val selectedExamTypePosition: Int? = null, - val examEvaluation: String = "", - val examLevel: ExamLevel? = null, - val examInfo: PersistentList = persistentListOf(), - val showSemesterBottomSheet: Boolean = false, - val showExamTypeBottomSheet: Boolean = false, -) { - val buttonEnabled = examLevel != null && - examInfo.isNotEmpty() && - examEvaluation.isNotEmpty() -} - -sealed interface ExamEvaluationEditorSideEffect { - data object ShowInputMoreTextToast : ExamEvaluationEditorSideEffect - data object ShowSelectSemesterToast : ExamEvaluationEditorSideEffect - data object ShowSelectExamTypeToast : ExamEvaluationEditorSideEffect - data object PopBackStack : ExamEvaluationEditorSideEffect - data object ShowExamEvaluationDeleteToast : ExamEvaluationEditorSideEffect - data class HandleException(val throwable: Throwable) : ExamEvaluationEditorSideEffect -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/examevaluation/ExamEvalutionEditorScreen.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/examevaluation/ExamEvalutionEditorScreen.kt deleted file mode 100644 index ad66e2703..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/examevaluation/ExamEvalutionEditorScreen.kt +++ /dev/null @@ -1,261 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.examevaluation - -import androidx.compose.foundation.ScrollState -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ExperimentalLayoutApi -import androidx.compose.foundation.layout.FlowRow -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.common.model.enums.ExamInfo -import com.suwiki.common.model.enums.ExamLevel -import com.suwiki.common.model.enums.ExamType -import com.suwiki.presentation.common.designsystem.component.appbar.SuwikiAppBarWithTitle -import com.suwiki.presentation.common.designsystem.component.bottomsheet.SuwikiSelectBottomSheet -import com.suwiki.presentation.common.designsystem.component.button.SuwikiContainedMediumButton -import com.suwiki.presentation.common.designsystem.component.chip.SuwikiOutlinedChip -import com.suwiki.presentation.common.designsystem.component.container.SuwikiSelectionContainer -import com.suwiki.presentation.common.designsystem.component.loading.LoadingScreen -import com.suwiki.presentation.common.designsystem.component.textfield.SuwikiReviewInputBox -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.common.ui.extension.toText -import com.suwiki.presentation.lectureevaluation.R -import kotlinx.collections.immutable.toPersistentList -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect - -@Composable -fun ExamEvaluationEditorRoute( - viewModel: ExamEvaluationEditorViewModel = hiltViewModel(), - popBackStack: () -> Unit = {}, - onShowToast: (String) -> Unit = {}, - handleException: (Throwable) -> Unit, -) { - val context = LocalContext.current - val scrollState = rememberScrollState() - val uiState = viewModel.collectAsState().value - - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - ExamEvaluationEditorSideEffect.PopBackStack -> popBackStack() - ExamEvaluationEditorSideEffect.ShowExamEvaluationDeleteToast -> { - onShowToast(context.getString(R.string.exam_evaluation_delete_toast_msg)) - } - - is ExamEvaluationEditorSideEffect.HandleException -> handleException(sideEffect.throwable) - ExamEvaluationEditorSideEffect.ShowInputMoreTextToast -> onShowToast(context.getString(R.string.toast_need_input_30)) - ExamEvaluationEditorSideEffect.ShowSelectExamTypeToast -> onShowToast(context.getString(R.string.toast_select_exam_type)) - ExamEvaluationEditorSideEffect.ShowSelectSemesterToast -> onShowToast(context.getString(R.string.toast_select_semester)) - } - } - - LaunchedEffect(key1 = Unit) { - viewModel.initData() - } - - ExamEvaluationEditorScreen( - scrollState = scrollState, - uiState = uiState, - popBackStack = viewModel::popBackStack, - onClickSemesterButton = viewModel::showSemesterBottomSheet, - onClickSemesterItem = viewModel::updateSemester, - onSemesterBottomSheetDismissRequest = viewModel::hideSemesterBottomSheet, - onClickExamTypeButton = viewModel::showExamTypeBottomSheet, - onClickExamTypeItem = viewModel::updateExamType, - onExamTypeBottomSheetDismissRequest = viewModel::hideExamTypeBottomSheet, - onClickExamLevelChip = viewModel::updateExamLevel, - onClickExamInfoChip = viewModel::updateExamInfo, - onExamEvaluationValueChange = viewModel::updateMyExamEvaluationValue, - onClickExamEvaluationReviseButton = viewModel::postOrUpdateExamEvaluation, - ) -} - -@OptIn(ExperimentalLayoutApi::class) -@Composable -fun ExamEvaluationEditorScreen( - scrollState: ScrollState, - uiState: ExamEvaluationEditorState, - popBackStack: () -> Unit = {}, - onClickSemesterButton: () -> Unit = {}, - onClickSemesterItem: (Int) -> Unit = {}, - onSemesterBottomSheetDismissRequest: () -> Unit = {}, - onClickExamTypeButton: () -> Unit = {}, - onClickExamTypeItem: (Int) -> Unit = {}, - onExamTypeBottomSheetDismissRequest: () -> Unit = {}, - onClickExamLevelChip: (ExamLevel) -> Unit = {}, - onClickExamInfoChip: (ExamInfo) -> Unit = {}, - onExamEvaluationValueChange: (String) -> Unit = { _ -> }, - - onClickExamEvaluationReviseButton: () -> Unit = {}, -) { - Column( - modifier = Modifier - .background(White) - .fillMaxSize(), - ) { - SuwikiAppBarWithTitle( - title = stringResource(R.string.word_exam_info), - showBackIcon = false, - showCloseIcon = true, - onClickClose = popBackStack, - ) - Column( - modifier = Modifier - .weight(1f) - .padding(horizontal = 24.dp) - .verticalScroll(scrollState), - ) { - Spacer(modifier = Modifier.height(20.dp)) - SuwikiSelectionContainer( - title = uiState.selectedSemester?.ifEmpty { stringResource(R.string.word_choose_semester) } ?: stringResource(R.string.word_choose_semester), - onClick = onClickSemesterButton, - ) - Spacer(modifier = Modifier.height(14.dp)) - - SuwikiSelectionContainer( - title = uiState.selectedExamType?.ifEmpty { stringResource(R.string.word_choose_test_type) } - ?: stringResource(R.string.word_choose_test_type), - onClick = onClickExamTypeButton, - ) - - Spacer(modifier = Modifier.height(16.dp)) - - LectureExamEditContainer( - text = stringResource(R.string.word_difficulty), - verticalAlignment = Alignment.Top, - content = { - Row( - horizontalArrangement = Arrangement.spacedBy(4.dp), - ) { - ExamLevel.entries.forEach { examLevel -> - SuwikiOutlinedChip( - isChecked = uiState.examLevel == examLevel, - text = examLevel.toText(), - onClick = { onClickExamLevelChip(examLevel) }, - ) - } - } - }, - ) - - Spacer(modifier = Modifier.height(16.dp)) - - LectureExamEditContainer( - text = stringResource(R.string.word_test_info), - verticalAlignment = Alignment.Top, - content = { - FlowRow( - verticalArrangement = Arrangement.spacedBy(6.dp), - horizontalArrangement = Arrangement.spacedBy(4.dp), - ) { - ExamInfo.entries.forEach { examInfo -> - SuwikiOutlinedChip( - isChecked = examInfo.value in uiState.examInfo, - text = examInfo.toText(), - onClick = { onClickExamInfoChip(examInfo) }, - ) - } - } - }, - ) - Spacer(modifier = Modifier.height(20.dp)) - SuwikiReviewInputBox( - modifier = Modifier, - value = uiState.examEvaluation, - hint = stringResource(R.string.exam_evaluation_input_box_hint), - onValueChange = onExamEvaluationValueChange, - ) - } - - Box(modifier = Modifier.imePadding()) { - SuwikiContainedMediumButton( - modifier = Modifier - .padding(24.dp) - .fillMaxWidth() - .height(50.dp) - .imePadding(), - text = stringResource(com.suwiki.presentation.common.ui.R.string.word_complete), - enabled = uiState.buttonEnabled, - clickable = uiState.buttonEnabled, - onClick = onClickExamEvaluationReviseButton, - ) - } - } - - SuwikiSelectBottomSheet( - isSheetOpen = uiState.showExamTypeBottomSheet, - onDismissRequest = onExamTypeBottomSheetDismissRequest, - onClickItem = { onClickExamTypeItem(it) }, - itemList = ExamType.entries.map { it.value }.toPersistentList(), - title = stringResource(R.string.word_choose_test_type), - selectedPosition = uiState.selectedExamTypePosition, - ) - - SuwikiSelectBottomSheet( - isSheetOpen = uiState.showSemesterBottomSheet, - onDismissRequest = onSemesterBottomSheetDismissRequest, - onClickItem = { onClickSemesterItem(it) }, - itemList = uiState.semesterList, - title = stringResource(R.string.word_choose_semester), - selectedPosition = uiState.selectedSemesterPosition, - ) - - if (uiState.isLoading) { - LoadingScreen() - } -} - -@Composable -fun LectureExamEditContainer( - text: String, - verticalAlignment: Alignment.Vertical, - content: @Composable RowScope.() -> Unit, -) { - Row( - verticalAlignment = verticalAlignment, - horizontalArrangement = Arrangement.spacedBy(12.dp), - modifier = Modifier.fillMaxWidth(), - ) { - Text( - modifier = Modifier.width(52.dp), - text = text, - style = SuwikiTheme.typography.body4, - ) - content() - } -} - -@Preview -@Composable -fun ExamEvaluationEditorScreenPreview() { - val scrollState = rememberScrollState() - - SuwikiTheme { - ExamEvaluationEditorScreen( - scrollState = scrollState, - uiState = ExamEvaluationEditorState(), - ) - } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/LectureEvaluationEditorContract.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/LectureEvaluationEditorContract.kt deleted file mode 100644 index 3bbcb1dd7..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/LectureEvaluationEditorContract.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.lectureevaluation - -import com.suwiki.common.model.enums.GradeLevel -import com.suwiki.common.model.enums.HomeworkLevel -import com.suwiki.common.model.enums.TeamLevel -import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.persistentListOf - -data class LectureEvaluationEditorState( - val isLoading: Boolean = false, - val semesterList: PersistentList = persistentListOf(""), - val selectedSemester: String = "", - val selectedSemesterPosition: Int? = null, - val totalAvg: Float = 0f, - val honeyRating: Float = 0f, - val learningRating: Float = 0f, - val satisfactionRating: Float = 0f, - val gradeLevel: GradeLevel? = null, - val homeworkLevel: HomeworkLevel? = null, - val teamLevel: TeamLevel? = null, - val lectureEvaluation: String = "", - val showSemesterBottomSheet: Boolean = false, -) { - val buttonEnabled = gradeLevel != null && - homeworkLevel != null && - teamLevel != null && - lectureEvaluation.isNotEmpty() -} - -sealed interface LectureEvaluationEditorSideEffect { - data object ShowInputMoreTextToast : LectureEvaluationEditorSideEffect - data object ShowSelectSemesterToast : LectureEvaluationEditorSideEffect - data object PopBackStack : LectureEvaluationEditorSideEffect - data object ShowLectureEvaluationDeleteToast : LectureEvaluationEditorSideEffect - data class HandleException(val throwable: Throwable) : LectureEvaluationEditorSideEffect -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/LectureEvaluationEditorScreen.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/LectureEvaluationEditorScreen.kt deleted file mode 100644 index 8894ce59d..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/LectureEvaluationEditorScreen.kt +++ /dev/null @@ -1,334 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.lectureevaluation - -import androidx.compose.foundation.ScrollState -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.common.model.enums.GradeLevel -import com.suwiki.common.model.enums.HomeworkLevel -import com.suwiki.common.model.enums.TeamLevel -import com.suwiki.presentation.common.designsystem.component.appbar.SuwikiAppBarWithTitle -import com.suwiki.presentation.common.designsystem.component.bottomsheet.SuwikiSelectBottomSheet -import com.suwiki.presentation.common.designsystem.component.button.SuwikiContainedMediumButton -import com.suwiki.presentation.common.designsystem.component.chip.ChipColor -import com.suwiki.presentation.common.designsystem.component.chip.SuwikiContainedChip -import com.suwiki.presentation.common.designsystem.component.container.SuwikiSelectionContainer -import com.suwiki.presentation.common.designsystem.component.loading.LoadingScreen -import com.suwiki.presentation.common.designsystem.component.ratingbar.SuwikiRatingBar -import com.suwiki.presentation.common.designsystem.component.textfield.SuwikiReviewInputBox -import com.suwiki.presentation.common.designsystem.theme.Primary -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.common.ui.extension.toText -import com.suwiki.presentation.lectureevaluation.R -import com.suwiki.presentation.lectureevaluation.lectureevaluation.component.slider.SuwikiSlider -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect -import java.util.Locale - -@Composable -fun LectureEvaluationEditorRoute( - viewModel: LectureEvaluationEditorViewModel = hiltViewModel(), - popBackStack: () -> Unit = {}, - onShowToast: (String) -> Unit = {}, - handleException: (Throwable) -> Unit, -) { - val context = LocalContext.current - val scrollState = rememberScrollState() - val uiState = viewModel.collectAsState().value - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - LectureEvaluationEditorSideEffect.PopBackStack -> popBackStack() - LectureEvaluationEditorSideEffect.ShowLectureEvaluationDeleteToast -> { - onShowToast(context.getString(R.string.lecture_evaluation_delete_toast_msg)) - } - is LectureEvaluationEditorSideEffect.HandleException -> handleException(sideEffect.throwable) - LectureEvaluationEditorSideEffect.ShowInputMoreTextToast -> onShowToast(context.getString(R.string.toast_need_input_30)) - LectureEvaluationEditorSideEffect.ShowSelectSemesterToast -> onShowToast(context.getString(R.string.toast_select_semester)) - } - } - - LaunchedEffect(key1 = Unit) { - viewModel.initData() - } - - LaunchedEffect( - key1 = uiState.honeyRating, - key2 = uiState.learningRating, - key3 = uiState.satisfactionRating, - ) { - viewModel.updateTotalAvg() - } - - LectureEvaluationEditorScreen( - uiState = uiState, - scrollState = scrollState, - popBackStack = viewModel::popBackStack, - onClickSemesterButton = viewModel::showSemesterBottomSheet, - onClickSemesterItem = viewModel::updateSemester, - onSemesterBottomSheetDismissRequest = viewModel::hideSemesterBottomSheet, - onHoneyRatingValueChange = viewModel::updateHoneyRating, - onLearningRatingValueChange = viewModel::updateLearningRating, - onSatisfactionRatingValueChange = viewModel::updateSatisfactionRating, - onLectureEvaluationValueChange = viewModel::updateMyLectureEvaluationValue, - onClickGradeChip = viewModel::updateGradeLevel, - onClickHomeworkChip = viewModel::updateHomeworkLevel, - onClickTeamChip = viewModel::updateTeamLevel, - onClickLectureEvaluationReviseButton = viewModel::postOrUpdateLectureEvaluation, - ) -} - -@Composable -fun LectureEvaluationEditorScreen( - uiState: LectureEvaluationEditorState, - scrollState: ScrollState, - popBackStack: () -> Unit, - onClickSemesterButton: () -> Unit = {}, - onClickSemesterItem: (Int) -> Unit = {}, - onSemesterBottomSheetDismissRequest: () -> Unit = {}, - onHoneyRatingValueChange: (Float) -> Unit = {}, - onLearningRatingValueChange: (Float) -> Unit = {}, - onSatisfactionRatingValueChange: (Float) -> Unit = {}, - onClickGradeChip: (GradeLevel) -> Unit = {}, - onClickHomeworkChip: (HomeworkLevel) -> Unit = {}, - onClickTeamChip: (TeamLevel) -> Unit = {}, - onLectureEvaluationValueChange: (String) -> Unit = { _ -> }, - onClickLectureEvaluationReviseButton: () -> Unit = {}, -) { - Column( - modifier = Modifier - .background(White) - .fillMaxSize(), - ) { - SuwikiAppBarWithTitle( - title = stringResource(R.string.word_lecture_evaluation), - showBackIcon = false, - showCloseIcon = true, - onClickClose = popBackStack, - ) - - Column( - modifier = Modifier - .weight(1f) - .padding(horizontal = 24.dp) - .verticalScroll(scrollState), - ) { - Spacer(modifier = Modifier.height(20.dp)) - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier - .fillMaxWidth(), - ) { - SuwikiSelectionContainer( - title = uiState.selectedSemester.ifEmpty { stringResource(id = R.string.word_choose_semester) }, - onClick = onClickSemesterButton, - ) - - Row( - modifier = Modifier.wrapContentHeight(), - verticalAlignment = Alignment.CenterVertically, - ) { - SuwikiRatingBar( - rating = uiState.totalAvg, - ) - Text( - text = "%.1f".format(Locale.US, uiState.totalAvg), - style = SuwikiTheme.typography.body4, - color = Primary, - ) - } - } - - LectureEvaluationEditContainer( - text = stringResource(R.string.word_honey_rating), - verticalAlignment = Alignment.Bottom, - content = { - SuwikiSlider( - modifier = Modifier.weight(1f), - value = uiState.honeyRating, - onValueChange = onHoneyRatingValueChange, - ) - }, - ) - LectureEvaluationEditContainer( - text = stringResource(R.string.word_learning_rating), - verticalAlignment = Alignment.Bottom, - content = { - SuwikiSlider( - modifier = Modifier.weight(1f), - value = uiState.learningRating, - onValueChange = onLearningRatingValueChange, - ) - }, - ) - LectureEvaluationEditContainer( - text = stringResource(R.string.word_satisfaction_rating), - verticalAlignment = Alignment.Bottom, - content = { - SuwikiSlider( - modifier = Modifier.weight(1f), - value = uiState.satisfactionRating, - onValueChange = onSatisfactionRatingValueChange, - ) - }, - ) - - Spacer(modifier = Modifier.height(20.dp)) - - Column( - verticalArrangement = Arrangement.spacedBy(20.dp), - ) { - LectureEvaluationEditContainer( - text = stringResource(R.string.word_grade), - verticalAlignment = Alignment.Bottom, - content = { - Row( - horizontalArrangement = Arrangement.spacedBy(4.dp), - ) { - GradeLevel.entries.zip(ChipColor.entries).forEach { (gradeLevel, color) -> - SuwikiContainedChip( - isChecked = uiState.gradeLevel == gradeLevel, - color = color, - text = gradeLevel.toText(), - onClick = { onClickGradeChip(gradeLevel) }, - ) - } - } - }, - ) - - LectureEvaluationEditContainer( - text = stringResource(R.string.word_homework), - verticalAlignment = Alignment.Bottom, - content = { - Row( - horizontalArrangement = Arrangement.spacedBy(4.dp), - ) { - HomeworkLevel.entries.zip(ChipColor.entries).forEach { (homeworkLevel, color) -> - SuwikiContainedChip( - isChecked = uiState.homeworkLevel == homeworkLevel, - color = color, - text = homeworkLevel.toText(), - onClick = { onClickHomeworkChip(homeworkLevel) }, - ) - } - } - }, - ) - - LectureEvaluationEditContainer( - text = stringResource(R.string.word_team), - verticalAlignment = Alignment.Bottom, - content = { - Row( - horizontalArrangement = Arrangement.spacedBy(4.dp), - ) { - TeamLevel.entries.zip(ChipColor.entries.minus(ChipColor.BLUE)).forEach { (teamLevel, color) -> - SuwikiContainedChip( - isChecked = uiState.teamLevel == teamLevel, - color = color, - text = teamLevel.toText(), - onClick = { onClickTeamChip(teamLevel) }, - ) - } - } - }, - ) - } - - Spacer(modifier = Modifier.size(24.dp)) - - SuwikiReviewInputBox( - value = uiState.lectureEvaluation, - hint = stringResource(R.string.lecture_evaluation_input_box_hint), - onValueChange = onLectureEvaluationValueChange, - ) - } - - Box(modifier = Modifier.imePadding()) { - SuwikiContainedMediumButton( - modifier = Modifier - .padding(24.dp) - .fillMaxWidth() - .height(50.dp) - .imePadding(), - text = stringResource(com.suwiki.presentation.common.ui.R.string.word_complete), - enabled = uiState.buttonEnabled, - clickable = uiState.buttonEnabled, - onClick = onClickLectureEvaluationReviseButton, - ) - } - } - - SuwikiSelectBottomSheet( - isSheetOpen = uiState.showSemesterBottomSheet, - onDismissRequest = onSemesterBottomSheetDismissRequest, - onClickItem = { onClickSemesterItem(it) }, - itemList = uiState.semesterList, - title = stringResource(R.string.word_select_semester), - selectedPosition = uiState.selectedSemesterPosition, - ) - - if (uiState.isLoading) { - LoadingScreen() - } -} - -@Composable -fun LectureEvaluationEditContainer( - text: String, - verticalAlignment: Alignment.Vertical, - content: @Composable RowScope.() -> Unit, -) { - Row( - verticalAlignment = verticalAlignment, - horizontalArrangement = Arrangement.spacedBy(12.dp), - modifier = Modifier.fillMaxWidth(), - ) { - Text( - modifier = Modifier.width(52.dp), - text = text, - style = SuwikiTheme.typography.body4, - ) - content() - } -} - -@Preview -@Composable -fun LectureEvaluationEditorPreview() { - SuwikiTheme { - val scrollState = rememberScrollState() - - LectureEvaluationEditorScreen( - uiState = LectureEvaluationEditorState(), - scrollState = scrollState, - popBackStack = {}, - ) - } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/LectureEvaluationEditorViewModel.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/LectureEvaluationEditorViewModel.kt deleted file mode 100644 index c09704212..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/LectureEvaluationEditorViewModel.kt +++ /dev/null @@ -1,177 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.lectureevaluation - -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel -import com.suwiki.common.model.enums.GradeLevel -import com.suwiki.common.model.enums.HomeworkLevel -import com.suwiki.common.model.enums.TeamLevel -import com.suwiki.common.model.lectureevaluation.lecture.MyLectureEvaluation -import com.suwiki.domain.lectureevaluation.usecase.lecture.PostLectureEvaluationUseCase -import com.suwiki.domain.lectureevaluation.usecase.lecture.UpdateLectureEvaluationUseCase -import com.suwiki.presentation.common.ui.extension.decodeFromUri -import com.suwiki.presentation.lectureevaluation.navigation.EvaluationEditorRoute -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.collections.immutable.toPersistentList -import kotlinx.serialization.json.Json -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.annotation.OrbitExperimental -import org.orbitmvi.orbit.syntax.simple.blockingIntent -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class LectureEvaluationEditorViewModel @Inject constructor( - savedStateHandle: SavedStateHandle, - val postLectureEvaluationUseCase: PostLectureEvaluationUseCase, - val updateLectureEvaluationUseCase: UpdateLectureEvaluationUseCase, -) : ContainerHost, ViewModel() { - override val container: Container = - container(LectureEvaluationEditorState()) - - private val myLectureEvaluation = savedStateHandle.get(EvaluationEditorRoute.lectureEvaluation)!! - private val myLectureEvaluationItem: MyLectureEvaluation = Json.decodeFromUri(myLectureEvaluation) - private val isEditMode = myLectureEvaluationItem.content.isNotEmpty() - - suspend fun initData() = intent { - showLoadingScreen() - with(myLectureEvaluationItem) { - reduce { - state.copy( - selectedSemester = selectedSemester, - semesterList = lectureInfo.semesterList.toPersistentList(), - ) - } - updateHoneyRating(honey) - updateLearningRating(learning) - updateSatisfactionRating(satisfaction) - updateTotalAvg() - updateMyLectureEvaluationValue(content) - GradeLevel.entries.forEach { - if (it.value == difficulty) { - updateGradeLevel(it) - } - } - HomeworkLevel.entries.forEach { - if (it.value == homework) { - updateHomeworkLevel(it) - } - } - TeamLevel.entries.forEach { - if (it.value == team) { - updateTeamLevel(it) - } - } - } - hideLoadingScreen() - } - - fun postOrUpdateLectureEvaluation() = intent { - if (state.lectureEvaluation.length < 30) { - postSideEffect(LectureEvaluationEditorSideEffect.ShowInputMoreTextToast) - return@intent - } - - if (state.selectedSemester.isEmpty()) { - postSideEffect(LectureEvaluationEditorSideEffect.ShowSelectSemesterToast) - return@intent - } - - if (isEditMode) { - updateLectureEvaluation() - } else { - postLectureEvaluation() - } - } - - private fun postLectureEvaluation() = intent { - postLectureEvaluationUseCase( - PostLectureEvaluationUseCase.Param( - id = myLectureEvaluationItem.id, - lectureName = myLectureEvaluationItem.lectureInfo.lectureName, - professor = myLectureEvaluationItem.lectureInfo.professor, - selectedSemester = state.selectedSemester, - satisfaction = "%.1f".format(state.satisfactionRating).toFloat(), - learning = "%.1f".format(state.learningRating).toFloat(), - honey = "%.1f".format(state.honeyRating).toFloat(), - team = state.teamLevel!!.value, - difficulty = state.gradeLevel!!.value, - homework = state.homeworkLevel!!.value, - content = state.lectureEvaluation, - ), - ) - .onSuccess { - popBackStack() - } - .onFailure { - postSideEffect(LectureEvaluationEditorSideEffect.HandleException(it)) - } - } - - private fun updateLectureEvaluation() = intent { - updateLectureEvaluationUseCase( - UpdateLectureEvaluationUseCase.Param( - lectureId = myLectureEvaluationItem.id, - selectedSemester = state.selectedSemester, - satisfaction = "%.1f".format(state.satisfactionRating).toFloat(), - learning = "%.1f".format(state.learningRating).toFloat(), - honey = "%.1f".format(state.honeyRating).toFloat(), - team = state.teamLevel!!.value, - difficulty = state.gradeLevel!!.value, - homework = state.homeworkLevel!!.value, - content = state.lectureEvaluation, - ), - ) - .onSuccess { - popBackStack() - } - .onFailure { - postSideEffect(LectureEvaluationEditorSideEffect.HandleException(it)) - } - } - - fun updateSemester(selectedPosition: Int) = intent { - reduce { state.copy(selectedSemester = state.semesterList[selectedPosition]) } - hideSemesterBottomSheet() - } - - fun updateHoneyRating(honeyRating: Float) = intent { - reduce { state.copy(honeyRating = if (honeyRating < 0.5) 0.5F else honeyRating) } - } - - fun updateLearningRating(learningRating: Float) = intent { - reduce { state.copy(learningRating = if (learningRating < 0.5) 0.5F else learningRating) } - } - - fun updateSatisfactionRating(satisfactionRating: Float) = intent { - reduce { state.copy(satisfactionRating = if (satisfactionRating < 0.5) 0.5F else satisfactionRating) } - } - - @OptIn(OrbitExperimental::class) - fun updateMyLectureEvaluationValue(lectureEvaluationValue: String) = blockingIntent { - reduce { state.copy(lectureEvaluation = lectureEvaluationValue) } - } - - fun updateTotalAvg() = intent { - reduce { state.copy(totalAvg = (state.honeyRating + state.learningRating + state.satisfactionRating) / 3) } - } - fun updateGradeLevel(gradeLevel: GradeLevel) = intent { - reduce { state.copy(gradeLevel = gradeLevel) } - } - fun updateHomeworkLevel(homeworkLevel: HomeworkLevel) = intent { - reduce { state.copy(homeworkLevel = homeworkLevel) } - } - fun updateTeamLevel(teamLevel: TeamLevel) = intent { - reduce { state.copy(teamLevel = teamLevel) } - } - - private fun showLoadingScreen() = intent { reduce { state.copy(isLoading = true) } } - private fun hideLoadingScreen() = intent { reduce { state.copy(isLoading = false) } } - fun showSemesterBottomSheet() = intent { reduce { state.copy(showSemesterBottomSheet = true) } } - fun hideSemesterBottomSheet() = intent { reduce { state.copy(showSemesterBottomSheet = false) } } - - fun popBackStack() = intent { postSideEffect(LectureEvaluationEditorSideEffect.PopBackStack) } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/SuwikiSlider.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/SuwikiSlider.kt deleted file mode 100644 index 411a591d1..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/SuwikiSlider.kt +++ /dev/null @@ -1,114 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.lectureevaluation.component.slider - -import androidx.annotation.IntRange -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableFloatStateOf -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.suwiki.presentation.common.designsystem.theme.Primary -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.lectureevaluation.lectureevaluation.component.slider.material.Slider -import kotlin.math.round - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun SuwikiSlider( - modifier: Modifier = Modifier, - value: Float = 2.5f, - onValueChange: (Float) -> Unit = { _ -> }, - @IntRange(from = 0) - steps: Int = 9, - valueRange: ClosedFloatingPointRange = 0f..5f, - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, -) { - var isHovering by rememberSaveable { - mutableStateOf(false) - } - - val label = (round(value * 100) / 100).toString() - - Row( - modifier = modifier - .fillMaxWidth(), - verticalAlignment = Alignment.Bottom, - ) { - Slider( - modifier = Modifier.weight(1f), - value = value, - onValueChange = { - isHovering = true - onValueChange(it) - }, - onValueChangeFinished = { isHovering = false }, - valueRange = valueRange, - steps = steps, - interactionSource = interactionSource, - trackOffset = with(LocalDensity.current) { 16.dp.toPx() }, - thumb = { - Box( - modifier = Modifier.height(57.dp), - contentAlignment = Alignment.BottomCenter, - ) { - if (isHovering) { - SuwikiSliderThumbWithLabel( - label = label, - ) - } else { - SuwikiSliderThumb() - } - } - }, - track = { - SuwikiSliderTrack( - value = value, - valueRange = valueRange, - height = 6.dp, - shape = RoundedCornerShape(4.dp), - ) - }, - ) - - Column { - Text( - text = label, - style = SuwikiTheme.typography.header6, - color = Primary, - ) - Spacer(modifier = Modifier.size(3.dp)) - } - } -} - -@Preview(showBackground = true, backgroundColor = 0xFFFFFF) -@Composable -fun SuwikiSliderPreview() { - SuwikiTheme { - var sliderPosition by rememberSaveable { - mutableFloatStateOf(5f) - } - - SuwikiSlider( - value = sliderPosition, - onValueChange = { sliderPosition = if (it < 0.5) 0.5F else it }, - ) - } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/SuwikiSliderThumb.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/SuwikiSliderThumb.kt deleted file mode 100644 index 2e60c6985..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/SuwikiSliderThumb.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.lectureevaluation.component.slider - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.suwiki.presentation.common.designsystem.theme.Primary -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme - -@Composable -fun SuwikiSliderThumb() { - Box( - modifier = Modifier - .height(26.dp) - .width(28.dp), - contentAlignment = Alignment.Center, - ) { - Spacer( - modifier = Modifier - .size(16.dp) - .clip(CircleShape) - .background(Primary), - ) - } -} - -@Preview -@Composable -fun SuwikiSliderThumbPreview() { - SuwikiTheme { - SuwikiSliderThumb() - } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/SuwikiSliderThumbWithLabel.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/SuwikiSliderThumbWithLabel.kt deleted file mode 100644 index 56e6255f7..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/SuwikiSliderThumbWithLabel.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.lectureevaluation.component.slider - -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.suwiki.presentation.common.designsystem.R -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme - -@Composable -fun SuwikiSliderThumbWithLabel( - modifier: Modifier = Modifier, - label: String, -) { - Box( - modifier = modifier.wrapContentSize(), - ) { - Image( - painter = painterResource(id = R.drawable.ic_slider_thumb_hovered), - contentDescription = "", - ) - - Box( - modifier = Modifier.size(28.dp), - contentAlignment = Alignment.Center, - ) { - Text( - text = label, - textAlign = TextAlign.Center, - color = Color.White, - style = SuwikiTheme.typography.caption1, - ) - } - } -} - -@Preview -@Composable -fun SuwikiSliderThumbWithLabelPreview() { - SuwikiTheme { - SuwikiSliderThumbWithLabel(label = "5.0") - } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/SuwikiSliderTrack.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/SuwikiSliderTrack.kt deleted file mode 100644 index 0159d045d..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/SuwikiSliderTrack.kt +++ /dev/null @@ -1,64 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.lectureevaluation.component.slider - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp -import com.suwiki.presentation.common.designsystem.theme.GrayF6 -import com.suwiki.presentation.common.designsystem.theme.Primary -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme - -@Composable -@ExperimentalMaterial3Api -fun SuwikiSliderTrack( - modifier: Modifier = Modifier, - value: Float, - valueRange: ClosedFloatingPointRange, - height: Dp = 6.dp, - shape: Shape = RoundedCornerShape(4.dp), -) { - SuwikiTheme { - Box( - modifier = modifier - .track(height = height, shape = shape) - .background(GrayF6), - ) { - Box( - modifier = modifier - .progress( - value = value, - valueRange = valueRange, - height = height, - shape = shape, - ) - .background(Primary), - ) - } - } -} - -private fun Modifier.track( - height: Dp = 6.dp, - shape: Shape = CircleShape, -) = fillMaxWidth() - .heightIn(min = height) - .clip(shape) - -private fun Modifier.progress( - value: Float, - valueRange: ClosedFloatingPointRange, - height: Dp = 6.dp, - shape: Shape = CircleShape, -) = - fillMaxWidth(fraction = value / valueRange.endInclusive - valueRange.start) - .heightIn(min = height) - .clip(shape) diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/material/Slider.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/material/Slider.kt deleted file mode 100644 index 1ed696a23..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/material/Slider.kt +++ /dev/null @@ -1,262 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.lectureevaluation.component.slider.material - -import androidx.annotation.IntRange -import androidx.compose.foundation.focusable -import androidx.compose.foundation.gestures.Orientation -import androidx.compose.foundation.gestures.detectTapGestures -import androidx.compose.foundation.gestures.draggable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.requiredSizeIn -import androidx.compose.foundation.progressSemantics -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.minimumInteractiveComponentSize -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.layout.Layout -import androidx.compose.ui.layout.layoutId -import androidx.compose.ui.semantics.disabled -import androidx.compose.ui.semantics.semantics -import androidx.compose.ui.semantics.setProgress -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.offset -import kotlin.math.abs -import kotlin.math.max -import kotlin.math.roundToInt - -/** - * material3에서 제공하는 Slider와 거의 동일합니다. - * 주요 차이점은 trackOffset이 존재합니다. - */ -@Composable -@ExperimentalMaterial3Api -fun Slider( - value: Float, - onValueChange: (Float) -> Unit, - modifier: Modifier = Modifier, - trackOffset: Float, - enabled: Boolean = true, - onValueChangeFinished: (() -> Unit)? = null, - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - @IntRange(from = 0) - steps: Int = 0, - thumb: @Composable (SliderState) -> Unit = { _ -> }, - track: @Composable (SliderState) -> Unit = { _ -> }, - valueRange: ClosedFloatingPointRange = 0f..1f, -) { - val state = remember( - steps, - valueRange, - ) { - SliderState( - value, - onValueChange, - steps, - valueRange, - onValueChangeFinished, - ) - } - - state.value = value - state.onValueChange = onValueChange - state.onValueChangeFinished = onValueChangeFinished - - Slider( - state = state, - modifier = modifier, - enabled = enabled, - interactionSource = interactionSource, - thumb = thumb, - track = track, - trackOffset = trackOffset, - ) -} - -@Composable -@ExperimentalMaterial3Api -fun Slider( - state: SliderState, - modifier: Modifier = Modifier, - trackOffset: Float, - enabled: Boolean = true, - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - thumb: @Composable (SliderState) -> Unit = { - }, - track: @Composable (SliderState) -> Unit = { sliderState -> - }, -) { - require(state.steps >= 0) { "steps should be >= 0" } - - SliderImpl( - state = state, - modifier = modifier, - enabled = enabled, - interactionSource = interactionSource, - thumb = thumb, - track = track, - trackOffset = trackOffset, - ) -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun SliderImpl( - modifier: Modifier, - state: SliderState, - enabled: Boolean, - interactionSource: MutableInteractionSource, - trackOffset: Float, - thumb: @Composable (SliderState) -> Unit, - track: @Composable (SliderState) -> Unit, -) { - val press = Modifier.sliderTapModifier( - state, - interactionSource, - enabled, - ) - val drag = Modifier.draggable( - orientation = Orientation.Horizontal, - enabled = enabled, - interactionSource = interactionSource, - onDragStopped = { state.gestureEndAction() }, - startDragImmediately = state.isDragging, - state = state, - ) - - Layout( - { - Box(modifier = Modifier.layoutId(SliderComponents.THUMB)) { - thumb(state) - } - Box(modifier = Modifier.layoutId(SliderComponents.TRACK)) { - track(state) - } - }, - modifier = modifier - .minimumInteractiveComponentSize() - .requiredSizeIn( - minWidth = 20.dp, - minHeight = 20.dp, - ) - .sliderSemantics( - state, - enabled, - ) - .focusable(enabled, interactionSource) - .then(press) - .then(drag), - ) { measurables, constraints -> - - val thumbPlaceable = measurables.find { - it.layoutId == SliderComponents.THUMB - }!!.measure(constraints) - - val trackPlaceable = measurables.find { - it.layoutId == SliderComponents.TRACK - }!!.measure( - constraints.offset( - horizontal = -thumbPlaceable.width, - ).copy(minHeight = 0), - ) - - val sliderWidth = thumbPlaceable.width + trackPlaceable.width - val sliderHeight = max(trackPlaceable.height, thumbPlaceable.height) - - state.updateDimensions( - thumbPlaceable.width.toFloat(), - sliderWidth, - ) - - val trackOffsetX = thumbPlaceable.width / 2 - val thumbOffsetX = ((trackPlaceable.width) * state.coercedValueAsFraction).roundToInt() - val trackOffsetY = (sliderHeight - trackPlaceable.height) / 2 + trackOffset.toInt() - val thumbOffsetY = (sliderHeight - thumbPlaceable.height) / 2 - - layout(sliderWidth, sliderHeight) { - trackPlaceable.placeRelative( - trackOffsetX, - trackOffsetY, - ) - thumbPlaceable.placeRelative( - thumbOffsetX, - thumbOffsetY, - ) - } - } -} - -private enum class SliderComponents { - THUMB, - TRACK, -} - -@OptIn(ExperimentalMaterial3Api::class) -private fun Modifier.sliderTapModifier( - state: SliderState, - interactionSource: MutableInteractionSource, - enabled: Boolean, -) = if (enabled) { - pointerInput(state, interactionSource) { - detectTapGestures( - onPress = { with(state) { onPress(it) } }, - onTap = { - state.dispatchRawDelta(0f) - state.gestureEndAction() - }, - ) - } -} else { - this -} - -@OptIn(ExperimentalMaterial3Api::class) -private fun Modifier.sliderSemantics( - state: SliderState, - enabled: Boolean, -): Modifier { - return semantics { - if (!enabled) disabled() - setProgress( - action = { targetValue -> - var newValue = targetValue.coerceIn( - state.valueRange.start, - state.valueRange.endInclusive, - ) - val originalVal = newValue - val resolvedValue = if (state.steps > 0) { - var distance: Float = newValue - for (i in 0..state.steps + 1) { - val stepValue = lerp( - state.valueRange.start, - state.valueRange.endInclusive, - i.toFloat() / (state.steps + 1), - ) - if (abs(stepValue - originalVal) <= distance) { - distance = abs(stepValue - originalVal) - newValue = stepValue - } - } - newValue - } else { - newValue - } - - // This is to keep it consistent with AbsSeekbar.java: return false if no - // change from current. - if (resolvedValue == state.value) { - false - } else { - state.onValueChange(resolvedValue) - state.onValueChangeFinished?.invoke() - true - } - }, - ) - }.progressSemantics( - state.value, - state.valueRange.start..state.valueRange.endInclusive, - state.steps, - ) -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/material/SliderState.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/material/SliderState.kt deleted file mode 100644 index bc1eb8b24..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/lectureevaluation/component/slider/material/SliderState.kt +++ /dev/null @@ -1,165 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.lectureevaluation.component.slider.material - -import androidx.compose.foundation.MutatePriority -import androidx.compose.foundation.MutatorMutex -import androidx.compose.foundation.gestures.DragScope -import androidx.compose.foundation.gestures.DraggableState -import androidx.compose.foundation.gestures.GestureCancellationException -import androidx.compose.foundation.gestures.PressGestureScope -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.runtime.Stable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableFloatStateOf -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.compose.ui.geometry.Offset -import kotlinx.coroutines.coroutineScope -import kotlin.math.abs -import kotlin.math.max -import kotlin.math.min - -/** - * material3에서 제공하는 SliderState와 동일합니다. - */ -@Stable -@ExperimentalMaterial3Api -class SliderState( - initialValue: Float = 0f, - initialOnValueChange: ((Float) -> Unit)? = null, - val steps: Int = 0, - val valueRange: ClosedFloatingPointRange = 0f..1f, - var onValueChangeFinished: (() -> Unit)? = null, -) : DraggableState { - - private var valueState by mutableFloatStateOf(initialValue) - - /** - * [Float] that indicates the current value that the thumb - * currently is in respect to the track. - */ - var value: Float - set(newVal) { - val coercedValue = newVal.coerceIn(valueRange.start, valueRange.endInclusive) - val snappedValue = snapValueToTick( - coercedValue, - tickFractions, - valueRange.start, - valueRange.endInclusive, - ) - valueState = snappedValue - } - get() = valueState - - override suspend fun drag( - dragPriority: MutatePriority, - block: suspend DragScope.() -> Unit, - ): Unit = coroutineScope { - isDragging = true - scrollMutex.mutateWith(dragScope, dragPriority, block) - isDragging = false - } - - override fun dispatchRawDelta(delta: Float) { - val maxPx = max(totalWidth - thumbWidth / 2, 0f) - val minPx = min(thumbWidth / 2, maxPx) - rawOffset = (rawOffset + delta + pressOffset) - pressOffset = 0f - val offsetInTrack = snapValueToTick(rawOffset, tickFractions, minPx, maxPx) - onValueChange(scaleToUserValue(minPx, maxPx, offsetInTrack)) - } - - /** - * callback in which value should be updated - */ - internal var onValueChange: (Float) -> Unit = { - if (it != value) { - initialOnValueChange?.invoke(it) ?: defaultOnValueChange(it) - } - } - - internal val tickFractions = stepsToTickFractions(steps) - internal var totalWidth by mutableIntStateOf(0) - internal var isRtl = false - internal var thumbWidth by mutableFloatStateOf(0f) - - internal val coercedValueAsFraction - get() = calcFraction( - valueRange.start, - valueRange.endInclusive, - value.coerceIn(valueRange.start, valueRange.endInclusive), - ) - - internal var isDragging by mutableStateOf(false) - private set - - internal fun updateDimensions( - newThumbWidth: Float, - newTotalWidth: Int, - ) { - thumbWidth = newThumbWidth - totalWidth = newTotalWidth - } - - internal val gestureEndAction = { - if (!isDragging) { - // check isDragging in case the change is still in progress (touch -> drag case) - onValueChangeFinished?.invoke() - } - } - - internal suspend fun PressGestureScope.onPress(pos: Offset) { - val to = if (isRtl) totalWidth - pos.x else pos.x - pressOffset = to - rawOffset - try { - awaitRelease() - } catch (_: GestureCancellationException) { - pressOffset = 0f - } - } - - private var rawOffset by mutableFloatStateOf(scaleToOffset(0f, 0f, value)) - private var pressOffset by mutableFloatStateOf(0f) - private val dragScope: DragScope = object : DragScope { - override fun dragBy(pixels: Float): Unit = dispatchRawDelta(pixels) - } - - private val scrollMutex = MutatorMutex() - - private fun defaultOnValueChange(newVal: Float) { - value = newVal - } - - private fun scaleToUserValue(minPx: Float, maxPx: Float, offset: Float) = - scale(minPx, maxPx, offset, valueRange.start, valueRange.endInclusive) - - private fun scaleToOffset(minPx: Float, maxPx: Float, userValue: Float) = - scale(valueRange.start, valueRange.endInclusive, userValue, minPx, maxPx) -} - -private fun scale(a1: Float, b1: Float, x1: Float, a2: Float, b2: Float) = - lerp(a2, b2, calcFraction(a1, b1, x1)) - -private fun snapValueToTick( - current: Float, - tickFractions: FloatArray, - minPx: Float, - maxPx: Float, -): Float { - // target is a closest anchor to the `current`, if exists - return tickFractions - .minByOrNull { abs(lerp(minPx, maxPx, it) - current) } - ?.run { lerp(minPx, maxPx, this) } - ?: current -} - -fun lerp(start: Float, stop: Float, amount: Float): Float { - return start + (stop - start) * amount -} - -private fun stepsToTickFractions(steps: Int): FloatArray { - return if (steps == 0) floatArrayOf() else FloatArray(steps + 2) { it.toFloat() / (steps + 1) } -} - -private fun calcFraction(a: Float, b: Float, pos: Float) = - (if (b - a == 0f) 0f else (pos - a) / (b - a)).coerceIn(0f, 1f) diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/my/MyEvaluationContract.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/my/MyEvaluationContract.kt deleted file mode 100644 index 46dd88203..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/my/MyEvaluationContract.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.my - -import com.suwiki.common.model.lectureevaluation.exam.MyExamEvaluation -import com.suwiki.common.model.lectureevaluation.lecture.MyLectureEvaluation -import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.persistentListOf - -data class MyEvaluationState( - val isLoading: Boolean = false, - val point: Int = 0, - val currentTabPage: Int = 0, - val myLectureEvaluationList: PersistentList = persistentListOf(), - val myExamEvaluationList: PersistentList = persistentListOf(), - val showDeleteLectureEvaluationDialog: Boolean = false, - val showDeleteExamEvaluationDialog: Boolean = false, - val showLackPointDialog: Boolean = false, -) { - val showLectureEmptyScreen: Boolean = myLectureEvaluationList.isEmpty() - val showExamEmptyScreen: Boolean = myExamEvaluationList.isEmpty() -} - -sealed interface MyEvaluationSideEffect { - data object PopBackStack : MyEvaluationSideEffect - data class NavigateLectureEvaluationEditor(val lectureEvaluation: String) : MyEvaluationSideEffect - data class NavigateExamEvaluationEditor(val examEvaluation: String) : MyEvaluationSideEffect - data class HandleException(val throwable: Throwable) : MyEvaluationSideEffect -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/my/MyEvaluationScreen.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/my/MyEvaluationScreen.kt deleted file mode 100644 index 6917c7a69..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/my/MyEvaluationScreen.kt +++ /dev/null @@ -1,320 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.my - -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.pager.HorizontalPager -import androidx.compose.foundation.pager.PagerState -import androidx.compose.foundation.pager.rememberPagerState -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.runtime.snapshotFlow -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.common.model.lectureevaluation.exam.MyExamEvaluation -import com.suwiki.common.model.lectureevaluation.lecture.MyLectureEvaluation -import com.suwiki.presentation.common.designsystem.component.appbar.SuwikiAppBarWithTitle -import com.suwiki.presentation.common.designsystem.component.container.SuwikiEditContainer -import com.suwiki.presentation.common.designsystem.component.dialog.SuwikiDialog -import com.suwiki.presentation.common.designsystem.component.loading.LoadingScreen -import com.suwiki.presentation.common.designsystem.component.tabbar.SuwikiTabBar -import com.suwiki.presentation.common.designsystem.component.tabbar.TabTitle -import com.suwiki.presentation.common.designsystem.theme.Gray95 -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.common.ui.enums.LectureEvaluationTab -import com.suwiki.presentation.common.ui.extension.OnBottomReached -import com.suwiki.presentation.common.ui.extension.collectWithLifecycle -import com.suwiki.presentation.common.ui.extension.encodeToUri -import com.suwiki.presentation.lectureevaluation.R -import kotlinx.collections.immutable.PersistentList -import kotlinx.serialization.json.Json -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect - -private val MY_EVALUATION_PAGE_COUNT = LectureEvaluationTab.entries.size - -@OptIn(ExperimentalFoundationApi::class) -@Composable -fun MyEvaluationRoute( - viewModel: MyEvaluationViewModel = hiltViewModel(), - popBackStack: () -> Unit = {}, - navigateLectureEvaluationEditor: (String) -> Unit = {}, - navigateExamEvaluationEditor: (String) -> Unit = {}, - handleException: (Throwable) -> Unit, -) { - val uiState = viewModel.collectAsState().value - val lectureEvaluationListState = rememberLazyListState() - val examEvaluationListState = rememberLazyListState() - - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - MyEvaluationSideEffect.PopBackStack -> popBackStack() - is MyEvaluationSideEffect.NavigateLectureEvaluationEditor -> navigateLectureEvaluationEditor(sideEffect.lectureEvaluation) - is MyEvaluationSideEffect.NavigateExamEvaluationEditor -> navigateExamEvaluationEditor(sideEffect.examEvaluation) - is MyEvaluationSideEffect.HandleException -> handleException(sideEffect.throwable) - } - } - val pagerState = rememberPagerState(pageCount = { MY_EVALUATION_PAGE_COUNT }) - - lectureEvaluationListState.OnBottomReached { - viewModel.getMyLectureEvaluations() - } - - examEvaluationListState.OnBottomReached { - viewModel.getMyExamEvaluations() - } - - LaunchedEffect(key1 = Unit) { - viewModel.initData() - } - - LaunchedEffect(key1 = uiState.currentTabPage) { - pagerState.animateScrollToPage(uiState.currentTabPage) - } - - snapshotFlow { pagerState.currentPage }.collectWithLifecycle { - viewModel.syncPager(it) - } - - MyEvaluationScreen( - uiState = uiState, - pagerState = pagerState, - lectureEvaluationListState = lectureEvaluationListState, - examEvaluationListState = examEvaluationListState, - onClickTab = viewModel::syncPager, - onClickBack = viewModel::popBackStack, - onClickLectureEvaluationEditButton = viewModel::navigateMyLectureEvaluation, - onClickExamEvaluationEditButton = viewModel::navigateMyExamEvaluation, - onClickExamEvaluationDeleteButton = viewModel::showExamDeleteOrLackPointDialog, - onDismissExamEvaluationDelete = viewModel::hideExamEvaluationDeleteDialog, - onDismissLackPoint = viewModel::hideLackPointDialog, - onClickExamEvaluationDeleteConfirm = { - viewModel.deleteExamEvaluation() - viewModel.hideExamEvaluationDeleteDialog() - }, - onClickLectureEvaluationDeleteConfirm = { - viewModel.deleteLectureEvaluation() - viewModel.hideLectureEvaluationDeleteDialog() - }, - onClickLectureEvaluationDeleteButton = viewModel::showLectureDeleteOrLackPointDialog, - ) -} - -@OptIn(ExperimentalFoundationApi::class) -@Composable -fun MyEvaluationScreen( - uiState: MyEvaluationState, - pagerState: PagerState = rememberPagerState(pageCount = { MY_EVALUATION_PAGE_COUNT }), - lectureEvaluationListState: LazyListState = rememberLazyListState(), - examEvaluationListState: LazyListState = rememberLazyListState(), - onClickTab: (Int) -> Unit = {}, - onClickBack: () -> Unit = {}, - onClickLectureEvaluationEditButton: (String) -> Unit = {}, - onClickLectureEvaluationDeleteButton: (Long) -> Unit = {}, - onClickExamEvaluationEditButton: (String) -> Unit = {}, - onDismissExamEvaluationDelete: () -> Unit = {}, - onDismissLackPoint: () -> Unit = {}, - onClickExamEvaluationDeleteConfirm: () -> Unit = {}, - onClickExamEvaluationDeleteButton: (Long) -> Unit = {}, - onClickLectureEvaluationDeleteConfirm: () -> Unit = {}, - onDismissLectureEvaluationDelete: () -> Unit = {}, -) { - Column( - modifier = Modifier - .background(White) - .fillMaxSize(), - ) { - SuwikiAppBarWithTitle( - title = stringResource(R.string.word_manage_my_evaluation), - showCloseIcon = false, - showBackIcon = true, - onClickBack = onClickBack, - ) - SuwikiTabBar( - selectedTabPosition = pagerState.currentPage, - ) { - LectureEvaluationTab.entries.forEach { tab -> - with(tab) { - TabTitle( - title = stringResource(title), - position = position, - selected = pagerState.currentPage == position, - onClick = { onClickTab(position) }, - ) - } - } - } - HorizontalPager( - modifier = Modifier.weight(1f), - state = pagerState, - ) { page -> - when (LectureEvaluationTab.entries[page]) { - LectureEvaluationTab.LECTURE_EVALUATION -> { - if (uiState.showLectureEmptyScreen) { - EmptyScreen() - } else { - MyLectureEvaluationLazyColumn( - itemList = uiState.myLectureEvaluationList, - listState = lectureEvaluationListState, - onClickLectureEditButton = onClickLectureEvaluationEditButton, - onClickDeleteButton = onClickLectureEvaluationDeleteButton, - ) - } - } - - LectureEvaluationTab.EXAM_INFO -> { - if (uiState.showExamEmptyScreen) { - EmptyScreen() - } else { - MyExamEvaluationLazyColumn( - itemList = uiState.myExamEvaluationList, - listState = examEvaluationListState, - onClickExamEditButton = onClickExamEvaluationEditButton, - onClickDeleteButton = onClickExamEvaluationDeleteButton, - ) - } - } - } - } - } - - if (uiState.showDeleteExamEvaluationDialog) { - SuwikiDialog( - headerText = stringResource(R.string.delete_dialog_header), - bodyText = stringResource(R.string.delete_dialog_body, uiState.point), - confirmButtonText = stringResource(R.string.word_delete), - dismissButtonText = stringResource(R.string.word_cancel), - onDismissRequest = onDismissExamEvaluationDelete, - onClickConfirm = onClickExamEvaluationDeleteConfirm, - onClickDismiss = onDismissExamEvaluationDelete, - ) - } - - if (uiState.showLackPointDialog) { - SuwikiDialog( - headerText = stringResource(R.string.lack_point_dialog_header), - bodyText = stringResource(R.string.lack_point_dialog_body, uiState.point), - confirmButtonText = stringResource(R.string.word_confirm), - onDismissRequest = onDismissLackPoint, - onClickConfirm = onDismissLackPoint, - ) - } - - if (uiState.showDeleteLectureEvaluationDialog) { - SuwikiDialog( - headerText = stringResource(R.string.delete_dialog_header), - bodyText = stringResource(R.string.delete_dialog_body, uiState.point), - confirmButtonText = stringResource(R.string.word_delete), - dismissButtonText = stringResource(R.string.word_cancel), - onDismissRequest = onDismissLectureEvaluationDelete, - onClickConfirm = onClickLectureEvaluationDeleteConfirm, - onClickDismiss = onDismissLectureEvaluationDelete, - ) - } - - if (uiState.isLoading) { - LoadingScreen() - } -} - -@Composable -fun MyLectureEvaluationLazyColumn( - modifier: Modifier = Modifier, - itemList: PersistentList, - listState: LazyListState, - onClickLectureEditButton: (String) -> Unit = {}, - onClickDeleteButton: (Long) -> Unit = {}, -) { - LazyColumn( - modifier = modifier.fillMaxSize(), - state = listState, - ) { - items( - items = itemList, - key = { - it.id - }, - ) { item -> - SuwikiEditContainer( - semester = item.selectedSemester, - name = item.lectureInfo.lectureName, - onClickEditButton = { onClickLectureEditButton(Json.encodeToUri(item)) }, - onClickDeleteButton = { onClickDeleteButton(item.id) }, - ) - } - } -} - -@Composable -fun EmptyScreen() { - Text( - modifier = Modifier - .padding(top = 150.dp) - .fillMaxSize(), - text = stringResource(R.string.empty_screen_text), - textAlign = TextAlign.Center, - style = SuwikiTheme.typography.header4, - color = Gray95, - ) -} - -@Composable -fun MyExamEvaluationLazyColumn( - modifier: Modifier = Modifier, - itemList: PersistentList, - listState: LazyListState, - onClickExamEditButton: (String) -> Unit = {}, - onClickDeleteButton: (Long) -> Unit = {}, -) { - LazyColumn( - modifier = modifier.fillMaxSize(), - state = listState, - ) { - items( - items = itemList, - key = { - it.id - }, - ) { item -> - val (examSemester, examName) = item.selectedSemester to item.lectureName - - SuwikiEditContainer( - semester = examSemester, - name = examName, - onClickEditButton = { onClickExamEditButton(Json.encodeToUri(item)) }, - onClickDeleteButton = { onClickDeleteButton(item.id) }, - ) - } - } -} - -@OptIn(ExperimentalFoundationApi::class) -@Preview(showSystemUi = true) -@Composable -fun MyEvaluationPreview() { - var currentPage by remember { mutableIntStateOf(0) } - SuwikiTheme { - MyEvaluationScreen( - uiState = MyEvaluationState( - currentTabPage = currentPage, - ), - onClickTab = { currentPage = it }, - ) - } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/my/MyEvaluationViewModel.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/my/MyEvaluationViewModel.kt deleted file mode 100644 index 447a4949d..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/my/MyEvaluationViewModel.kt +++ /dev/null @@ -1,182 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.my - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.suwiki.common.model.user.User -import com.suwiki.domain.lectureevaluation.usecase.exam.DeleteExamEvaluationUseCase -import com.suwiki.domain.lectureevaluation.usecase.exam.GetMyExamEvaluationListUseCase -import com.suwiki.domain.lectureevaluation.usecase.lecture.DeleteLectureEvaluationUseCase -import com.suwiki.domain.lectureevaluation.usecase.lecture.GetMyLectureEvaluationListUseCase -import com.suwiki.domain.user.usecase.GetUserInfoUseCase -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.toPersistentList -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.joinAll -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class MyEvaluationViewModel @Inject constructor( - private val getUserInfoUseCase: GetUserInfoUseCase, - private val getMyLectureEvaluationListUseCase: GetMyLectureEvaluationListUseCase, - private val getMyExamEvaluationListUseCase: GetMyExamEvaluationListUseCase, - private val deleteExamEvaluationUseCase: DeleteExamEvaluationUseCase, - private val deleteLectureEvaluationUseCase: DeleteLectureEvaluationUseCase, -) : ContainerHost, ViewModel() { - override val container: Container = container(MyEvaluationState()) - - private var lectureEvaluationPage = 1 - private var isLastLectureEvaluation = false - private var examEvaluationPage = 1 - private var isLastExamEvaluation = false - - private var toDeleteExamId: Long = 0 - private var toDeleteLectureId: Long = 0 - - private val mutex: Mutex = Mutex() - - fun getMyLectureEvaluations(needClear: Boolean = false) = intent { - mutex.withLock { - val currentList = if (needClear) { - lectureEvaluationPage = 1 - isLastLectureEvaluation = false - persistentListOf() - } else { - state.myLectureEvaluationList - } - - if (isLastLectureEvaluation) return@intent - - getMyLectureEvaluationListUseCase(lectureEvaluationPage) - .onSuccess { - reduce { - lectureEvaluationPage++ - isLastLectureEvaluation = it.isEmpty() - state.copy(myLectureEvaluationList = currentList.addAll(it).distinctBy { it.id }.toPersistentList()) - } - } - .onFailure { - postSideEffect(MyEvaluationSideEffect.HandleException(it)) - } - } - } - - fun getMyExamEvaluations(needClear: Boolean = false) = intent { - mutex.withLock { - val currentList = if (needClear) { - examEvaluationPage = 1 - isLastExamEvaluation = false - persistentListOf() - } else { - state.myExamEvaluationList - } - - if (isLastExamEvaluation) return@intent - - getMyExamEvaluationListUseCase(examEvaluationPage) - .onSuccess { - reduce { - examEvaluationPage++ - isLastExamEvaluation = it.isEmpty() - state.copy(myExamEvaluationList = currentList.addAll(it).distinctBy { it.id }.toPersistentList()) - } - } - .onFailure { - postSideEffect(MyEvaluationSideEffect.HandleException(it)) - } - } - } - - fun initData() = intent { - showLoadingScreen() - - getUserInfoUseCase() - .onEach(::setPoint) - .catch { postSideEffect(MyEvaluationSideEffect.HandleException(it)) } - .launchIn(viewModelScope) - - joinAll(getMyLectureEvaluations(true), getMyExamEvaluations(true)) - hideLoadingScreen() - } - - fun deleteExamEvaluation() = intent { - deleteExamEvaluationUseCase(toDeleteExamId) - .onSuccess { - reduce { - state.copy( - point = state.point - 30, - myExamEvaluationList = state.myExamEvaluationList.filter { it.id != toDeleteExamId }.toPersistentList(), - ) - } - } - .onFailure { - postSideEffect(MyEvaluationSideEffect.HandleException(it)) - } - } - - fun deleteLectureEvaluation() = intent { - deleteLectureEvaluationUseCase(toDeleteLectureId) - .onSuccess { - reduce { - state.copy( - point = state.point - 30, - myLectureEvaluationList = state.myLectureEvaluationList.filter { it.id != toDeleteLectureId }.toPersistentList(), - ) - } - } - .onFailure { - postSideEffect(MyEvaluationSideEffect.HandleException(it)) - } - } - - private fun setPoint(user: User) = intent { reduce { state.copy(point = user.point) } } - - fun syncPager(currentPage: Int) = intent { reduce { state.copy(currentTabPage = currentPage) } } - - private fun showLoadingScreen() = intent { reduce { state.copy(isLoading = true) } } - private fun hideLoadingScreen() = intent { reduce { state.copy(isLoading = false) } } - - fun popBackStack() = intent { postSideEffect(MyEvaluationSideEffect.PopBackStack) } - fun navigateMyLectureEvaluation(lectureEvaluation: String) = intent { - postSideEffect(MyEvaluationSideEffect.NavigateLectureEvaluationEditor(lectureEvaluation)) - } - - fun navigateMyExamEvaluation(examEvaluation: String) = intent { - postSideEffect(MyEvaluationSideEffect.NavigateExamEvaluationEditor(examEvaluation)) - } - - fun showExamDeleteOrLackPointDialog(id: Long) = intent { - if (state.point >= 30) { - toDeleteExamId = id - showExamEvaluationDeleteDialog() - } else { - showLackPointDialog() - } - } - - fun showLectureDeleteOrLackPointDialog(id: Long) = intent { - if (state.point >= 30) { - toDeleteLectureId = id - showLectureEvaluationDeleteDialog() - } else { - showLackPointDialog() - } - } - - private fun showExamEvaluationDeleteDialog() = intent { reduce { state.copy(showDeleteExamEvaluationDialog = true) } } - fun hideExamEvaluationDeleteDialog() = intent { reduce { state.copy(showDeleteExamEvaluationDialog = false) } } - private fun showLectureEvaluationDeleteDialog() = intent { reduce { state.copy(showDeleteLectureEvaluationDialog = true) } } - fun hideLectureEvaluationDeleteDialog() = intent { reduce { state.copy(showDeleteLectureEvaluationDialog = false) } } - private fun showLackPointDialog() = intent { reduce { state.copy(showLackPointDialog = true) } } - fun hideLackPointDialog() = intent { reduce { state.copy(showLackPointDialog = false) } } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/navigation/EvaluationEditorNavigation.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/navigation/EvaluationEditorNavigation.kt deleted file mode 100644 index 63d5effd4..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/navigation/EvaluationEditorNavigation.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.navigation - -import androidx.navigation.NavController -import androidx.navigation.NavGraphBuilder -import androidx.navigation.NavType -import androidx.navigation.compose.composable -import androidx.navigation.navArgument -import com.suwiki.presentation.lectureevaluation.examevaluation.ExamEvaluationEditorRoute -import com.suwiki.presentation.lectureevaluation.lectureevaluation.LectureEvaluationEditorRoute - -// TODO 리팩토링 -fun NavController.navigateLectureEvaluationEditor(lectureEvaluation: String) { - navigate(EvaluationEditorRoute.lectureEvaluationEditorRoute(lectureEvaluation)) -} - -// TODO 리팩토링 -fun NavController.navigateExamEvaluationEditor(examEvaluation: String) { - navigate(EvaluationEditorRoute.examEvaluationEditorRoute(examEvaluation)) -} - -fun NavGraphBuilder.myEvaluationEditNavGraph( - popBackStack: () -> Unit = {}, - onShowToast: (String) -> Unit = {}, - handleException: (Throwable) -> Unit, -) { - composable( - route = EvaluationEditorRoute.lectureEvaluationEditorRoute("{${EvaluationEditorRoute.lectureEvaluation}}"), - arguments = listOf( - navArgument(EvaluationEditorRoute.lectureEvaluation) { - type = NavType.StringType - }, - ), - ) { - LectureEvaluationEditorRoute( - popBackStack = popBackStack, - onShowToast = onShowToast, - handleException = handleException, - ) - } - composable( - route = EvaluationEditorRoute.examEvaluationEditorRoute("{${EvaluationEditorRoute.examEvaluation}}"), - arguments = listOf( - navArgument(EvaluationEditorRoute.examEvaluation) { - type = NavType.StringType - }, - ), - ) { - ExamEvaluationEditorRoute( - popBackStack = popBackStack, - onShowToast = onShowToast, - handleException = handleException, - ) - } -} - -object EvaluationEditorRoute { - const val lectureEvaluation = "lecture-evaluation" - const val examEvaluation = "exam-evaluation" - fun lectureEvaluationEditorRoute(lectureEvaluation: String) = "lecture-evaluation-editor/$lectureEvaluation" - fun examEvaluationEditorRoute(examEvaluation: String) = "exam-evaluation-editor/$examEvaluation" -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/navigation/LectureEvaluationNavigation.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/navigation/LectureEvaluationNavigation.kt deleted file mode 100644 index e3d23ebbe..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/navigation/LectureEvaluationNavigation.kt +++ /dev/null @@ -1,70 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.navigation - -import androidx.compose.foundation.layout.PaddingValues -import androidx.navigation.NavController -import androidx.navigation.NavGraphBuilder -import androidx.navigation.NavOptions -import androidx.navigation.NavType -import androidx.navigation.compose.composable -import androidx.navigation.navArgument -import com.suwiki.presentation.lectureevaluation.viewerrepoter.LectureEvaluationRoute -import com.suwiki.presentation.lectureevaluation.viewerrepoter.detail.LectureEvaluationDetailRoute - -fun NavController.navigateLectureEvaluation(navOptions: NavOptions) { - navigate(LectureEvaluationRoute.route, navOptions) -} - -fun NavController.navigateLectureEvaluationDetail(id: String) { - navigate(LectureEvaluationRoute.detailRoute(id)) -} - -fun NavGraphBuilder.lectureEvaluationNavGraph( - padding: PaddingValues, - argumentName: String, - popBackStack: () -> Unit, - navigateLogin: () -> Unit, - navigateSignUp: () -> Unit, - navigateOpenMajor: (String) -> Unit, - navigateLectureEvaluationDetail: (String) -> Unit, - navigateLectureEvaluationEditor: (String) -> Unit, - navigateExamEvaluationEditor: (String) -> Unit, - onShowToast: (String) -> Unit, - handleException: (Throwable) -> Unit, -) { - composable(route = LectureEvaluationRoute.route) { navBackStackEntry -> - val selectedOpenMajor = navBackStackEntry.savedStateHandle.get(argumentName) ?: "전체" - LectureEvaluationRoute( - padding = padding, - selectedOpenMajor = selectedOpenMajor, - navigateLogin = navigateLogin, - navigateSignUp = navigateSignUp, - navigateOpenMajor = navigateOpenMajor, - navigateLectureEvaluationDetail = navigateLectureEvaluationDetail, - handleException = handleException, - ) - } - - composable( - route = LectureEvaluationRoute.detailRoute("{${LectureEvaluationRoute.lectureEvaluationDetail}}"), - arguments = listOf( - navArgument(LectureEvaluationRoute.lectureEvaluationDetail) { - type = NavType.StringType - }, - ), - ) { - LectureEvaluationDetailRoute( - navigateLectureEvaluationEditor = navigateLectureEvaluationEditor, - navigateExamEvaluationEditor = navigateExamEvaluationEditor, - popBackStack = popBackStack, - onShowToast = onShowToast, - handleException = handleException, - ) - } -} - -object LectureEvaluationRoute { - const val route = "lecture-evaluation" - const val lectureEvaluationDetail = "lecture-evaluation-detail" - - fun detailRoute(lectureEvaluationDetail: String) = "lecture-evaluation-detail/$lectureEvaluationDetail" -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/navigation/MyEvaluationNavigation.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/navigation/MyEvaluationNavigation.kt deleted file mode 100644 index a707d18a9..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/navigation/MyEvaluationNavigation.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.navigation - -import androidx.navigation.NavController -import androidx.navigation.NavGraphBuilder -import androidx.navigation.compose.composable -import com.suwiki.presentation.lectureevaluation.my.MyEvaluationRoute - -fun NavController.navigateMyEvaluation() { - navigate(MyEvaluationRoute.route) -} - -fun NavGraphBuilder.myEvaluationNavGraph( - popBackStack: () -> Unit = {}, - navigateLectureEvaluationEditor: (String) -> Unit = {}, - navigateExamEvaluationEditor: (String) -> Unit = {}, - handleException: (Throwable) -> Unit, -) { - composable(route = MyEvaluationRoute.route) { navBackStackEntry -> - MyEvaluationRoute( - popBackStack = popBackStack, - navigateLectureEvaluationEditor = navigateLectureEvaluationEditor, - navigateExamEvaluationEditor = navigateExamEvaluationEditor, - handleException = handleException, - ) - } -} - -object MyEvaluationRoute { - const val route = "my-evaluation" -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/LectureEvaluationContract.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/LectureEvaluationContract.kt deleted file mode 100644 index 56060acf2..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/LectureEvaluationContract.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.viewerrepoter - -import com.suwiki.common.model.enums.LectureAlign -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationAverage -import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.persistentListOf - -data class LectureEvaluationState( - val lectureEvaluationList: PersistentList = persistentListOf(), - val showOnboardingBottomSheet: Boolean = false, - val showAgreementBottomSheet: Boolean = false, - val isCheckedTerm: Boolean = false, - val isCheckedPersonalPolicy: Boolean = false, - val showAlignBottomSheet: Boolean = false, - val selectedOpenMajor: String = "전체", - val selectedAlignPosition: Int = 0, - val searchValue: String = "", - val isLoading: Boolean = false, -) { - val alignValue = LectureAlign.entries[selectedAlignPosition] - - val showSearchEmptyResultScreen: Boolean = - searchValue.isNotEmpty() && - selectedOpenMajor.isNotEmpty() && - lectureEvaluationList.isEmpty() && - isLoading.not() - - val isEnabledAgreementButton: Boolean = isCheckedTerm && isCheckedPersonalPolicy -} - -sealed interface LectureEvaluationSideEffect { - data class NavigateOpenMajor(val selectedOpenMajor: String) : LectureEvaluationSideEffect - data object NavigateLogin : LectureEvaluationSideEffect - data object NavigateSignUp : LectureEvaluationSideEffect - data class NavigateLectureEvaluationDetail(val id: String) : LectureEvaluationSideEffect - data object OpenTermWebSite : LectureEvaluationSideEffect - data object OpenPersonalPolicyWebSite : LectureEvaluationSideEffect - data object ScrollToTop : LectureEvaluationSideEffect - data class HandleException(val throwable: Throwable) : LectureEvaluationSideEffect -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/LectureEvaluationScreen.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/LectureEvaluationScreen.kt deleted file mode 100644 index 7d1c70c8f..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/LectureEvaluationScreen.kt +++ /dev/null @@ -1,301 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.viewerrepoter - -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.pager.PagerState -import androidx.compose.foundation.pager.rememberPagerState -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationAverage -import com.suwiki.presentation.common.designsystem.component.bottomsheet.SuwikiAgreementBottomSheet -import com.suwiki.presentation.common.designsystem.component.bottomsheet.SuwikiSelectBottomSheet -import com.suwiki.presentation.common.designsystem.component.loading.LoadingScreen -import com.suwiki.presentation.common.designsystem.theme.Gray95 -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.ui.extension.OnBottomReached -import com.suwiki.presentation.common.ui.extension.lectureAlignList -import com.suwiki.presentation.common.ui.extension.toText -import com.suwiki.presentation.common.ui.util.PRIVACY_POLICY_SITE -import com.suwiki.presentation.common.ui.util.TERMS_SITE -import com.suwiki.presentation.lectureevaluation.R -import com.suwiki.presentation.lectureevaluation.viewerrepoter.component.EvaluationAppBar -import com.suwiki.presentation.lectureevaluation.viewerrepoter.component.EvaluationCard -import com.suwiki.presentation.lectureevaluation.viewerrepoter.component.EvaluationSearchBar -import com.suwiki.presentation.lectureevaluation.viewerrepoter.component.ONBOARDING_PAGE_COUNT -import com.suwiki.presentation.lectureevaluation.viewerrepoter.component.OnboardingBottomSheet -import kotlinx.collections.immutable.PersistentList -import kotlinx.coroutines.android.awaitFrame -import kotlinx.coroutines.launch -import me.onebone.toolbar.CollapsingToolbarScaffold -import me.onebone.toolbar.ScrollStrategy -import me.onebone.toolbar.rememberCollapsingToolbarScaffoldState -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect - -@OptIn(ExperimentalFoundationApi::class) -@Composable -fun LectureEvaluationRoute( - padding: PaddingValues, - viewModel: LectureEvaluationViewModel = hiltViewModel(), - selectedOpenMajor: String, - navigateLogin: () -> Unit, - navigateSignUp: () -> Unit, - navigateLectureEvaluationDetail: (String) -> Unit, - navigateOpenMajor: (String) -> Unit, - handleException: (Throwable) -> Unit, -) { - val uiState = viewModel.collectAsState().value - - val uriHandler = LocalUriHandler.current - - val listState = rememberLazyListState() - val scope = rememberCoroutineScope() - - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - LectureEvaluationSideEffect.NavigateLogin -> navigateLogin() - LectureEvaluationSideEffect.NavigateSignUp -> navigateSignUp() - LectureEvaluationSideEffect.OpenPersonalPolicyWebSite -> uriHandler.openUri(PRIVACY_POLICY_SITE) - LectureEvaluationSideEffect.OpenTermWebSite -> uriHandler.openUri(TERMS_SITE) - LectureEvaluationSideEffect.ScrollToTop -> scope.launch { - awaitFrame() - listState.animateScrollToItem(0) - } - - is LectureEvaluationSideEffect.HandleException -> handleException(sideEffect.throwable) - is LectureEvaluationSideEffect.NavigateOpenMajor -> navigateOpenMajor(sideEffect.selectedOpenMajor) - is LectureEvaluationSideEffect.NavigateLectureEvaluationDetail -> navigateLectureEvaluationDetail(sideEffect.id) - } - } - - val pagerState = rememberPagerState(pageCount = { ONBOARDING_PAGE_COUNT }) - - LaunchedEffect(key1 = viewModel) { - viewModel.initData() - } - - LaunchedEffect(selectedOpenMajor) { - viewModel.updateSelectedOpenMajor(selectedOpenMajor) - } - - listState.OnBottomReached { - viewModel.getLectureEvaluationList(needClear = false) - } - - LectureEvaluationScreen( - padding = padding, - uiState = uiState, - listState = listState, - pagerState = pagerState, - hideOnboardingBottomSheet = viewModel::hideOnboardingBottomSheet, - hideAgreementBottomSheet = viewModel::hideAgreementBottomSheet, - hideAlignBottomSheet = viewModel::hideAlignBottomSheet, - showAlignBottomSheet = { viewModel.showAlignBottomSheet() }, - onClickLoginButton = { - viewModel.hideOnboardingBottomSheet() - viewModel.navigateLogin() - }, - onClickSignupButton = viewModel::showAgreementBottomSheet, - onClickTermCheckIcon = viewModel::toggleTermChecked, - onClickTermArrowIcon = viewModel::openTermWebSite, - onClickPersonalCheckIcon = viewModel::togglePersonalPolicyChecked, - onClickPersonalArrowIcon = viewModel::openPersonalPolicyWebSite, - onClickLectureEvaluationItem = viewModel::navigateLectureEvaluationDetailIfLoggedIn, - onClickAgreementButton = { - viewModel.hideAgreementBottomSheet() - viewModel.hideOnboardingBottomSheet() - viewModel.navigateSignup() - }, - onClickSelectedOpenMajor = viewModel::navigateOpenMajor, - onValueChangeSearchBar = viewModel::updateSearchValue, - onClickSearchButton = viewModel::searchLectureEvaluation, - onClickSearchBarClearButton = { - viewModel.updateSearchValue("") - }, - onClickAlignBottomSelectedItem = { - viewModel.hideAlignBottomSheet() - viewModel.updateAlignItem(it) - }, - ) -} - -@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class) -@Composable -fun LectureEvaluationScreen( - padding: PaddingValues, - uiState: LectureEvaluationState, - listState: LazyListState = rememberLazyListState(), - pagerState: PagerState = rememberPagerState(pageCount = { ONBOARDING_PAGE_COUNT }), - hideOnboardingBottomSheet: () -> Unit = {}, - hideAlignBottomSheet: () -> Unit = {}, - showAlignBottomSheet: () -> Unit = {}, - hideAgreementBottomSheet: () -> Unit = {}, - onClickLoginButton: () -> Unit = {}, - onClickSignupButton: () -> Unit = {}, - onClickAlignBottomSelectedItem: (Int) -> Unit = {}, - onValueChangeSearchBar: (String) -> Unit = {}, - onClickSearchButton: (String) -> Unit = {}, - onClickSearchBarClearButton: () -> Unit = {}, - onClickSelectedOpenMajor: (String) -> Unit = {}, - onClickTermCheckIcon: () -> Unit = {}, - onClickTermArrowIcon: () -> Unit = {}, - onClickPersonalCheckIcon: () -> Unit = {}, - onClickPersonalArrowIcon: () -> Unit = {}, - onClickAgreementButton: () -> Unit = {}, - onClickLectureEvaluationItem: (String) -> Unit = {}, -) { - val state = rememberCollapsingToolbarScaffoldState() - - CollapsingToolbarScaffold( - modifier = Modifier - .fillMaxSize() - .padding(padding), - state = state, - scrollStrategy = ScrollStrategy.EnterAlways, - toolbar = { - Column { - EvaluationAppBar( - title = stringResource(R.string.word_lecture_evaluation), - major = uiState.selectedOpenMajor, - onClickMajor = { onClickSelectedOpenMajor(uiState.selectedOpenMajor) }, - ) - EvaluationSearchBar( - placeHolder = stringResource(R.string.word_search_placeholder), - value = uiState.searchValue, - onValueChange = onValueChangeSearchBar, - onClickClearButton = onClickSearchBarClearButton, - onClickFilterButton = showAlignBottomSheet, - onClickSearchButton = onClickSearchButton, - ) - Text( - modifier = Modifier - .padding(start = 24.dp, top = 10.dp), - text = uiState.alignValue.toText(), - style = SuwikiTheme.typography.body2, - color = Gray95, - ) - } - }, - ) { - if (uiState.showSearchEmptyResultScreen) { - EmptyText(stringResource(R.string.word_empty_search_result)) - } - - LectureEvaluationLazyColumn( - listState = listState, - openLectureEvaluationInfoList = uiState.lectureEvaluationList, - onClickOpenLectureEvaluationDetail = onClickLectureEvaluationItem, - ) - } - - if (uiState.isLoading) { - LoadingScreen() - } - - SuwikiAgreementBottomSheet( - isSheetOpen = uiState.showAgreementBottomSheet, - buttonEnabled = uiState.isEnabledAgreementButton, - isCheckedTerm = uiState.isCheckedTerm, - onClickTermCheckIcon = onClickTermCheckIcon, - onClickTermArrowIcon = onClickTermArrowIcon, - isCheckedPersonalPolicy = uiState.isCheckedPersonalPolicy, - onClickPersonalCheckIcon = onClickPersonalCheckIcon, - onClickPersonalArrowIcon = onClickPersonalArrowIcon, - onClickAgreementButton = onClickAgreementButton, - onDismissRequest = hideAgreementBottomSheet, - ) - - OnboardingBottomSheet( - uiState = uiState, - hideOnboardingBottomSheet = hideOnboardingBottomSheet, - pagerState = pagerState, - onClickLoginButton = onClickLoginButton, - onClickSignupButton = onClickSignupButton, - ) - - SuwikiSelectBottomSheet( - isSheetOpen = uiState.showAlignBottomSheet, - onDismissRequest = hideAlignBottomSheet, - onClickItem = onClickAlignBottomSelectedItem, - itemList = lectureAlignList, - title = stringResource(R.string.word_sort), - selectedPosition = uiState.selectedAlignPosition, - ) -} - -@Composable -private fun LectureEvaluationLazyColumn( - listState: LazyListState, - openLectureEvaluationInfoList: PersistentList, - onClickOpenLectureEvaluationDetail: (String) -> Unit = {}, -) { - LazyColumn( - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 24.dp), - contentPadding = PaddingValues(top = 15.dp, bottom = 24.dp), - state = listState, - verticalArrangement = Arrangement.spacedBy(12.dp), - ) { - items( - items = openLectureEvaluationInfoList, - key = { it!!.id }, - ) { lectureEvaluation -> - with(lectureEvaluation) { - EvaluationCard( - className = this!!.lectureInfo.lectureName, - openMajor = lectureInfo.majorType, - professor = lectureInfo.professor, - rating = lectureTotalAvg, - classType = lectureInfo.lectureType ?: "", - onClick = { onClickOpenLectureEvaluationDetail(id.toString()) }, - ) - } - } - } -} - -@Composable -private fun EmptyText( - text: String = "", -) { - Text( - modifier = Modifier - .padding(52.dp) - .fillMaxSize(), - textAlign = TextAlign.Center, - text = text, - style = SuwikiTheme.typography.header4, - color = Gray95, - ) -} - -@OptIn(ExperimentalFoundationApi::class) -@Preview -@Composable -fun LectureEvaluationScreenPreview() { - SuwikiTheme { - LectureEvaluationScreen( - padding = PaddingValues(0.dp), - uiState = LectureEvaluationState(), - ) - } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/LectureEvaluationViewModel.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/LectureEvaluationViewModel.kt deleted file mode 100644 index 96c9e2652..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/LectureEvaluationViewModel.kt +++ /dev/null @@ -1,172 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.viewerrepoter - -import androidx.lifecycle.ViewModel -import com.suwiki.common.model.enums.LectureAlign -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationAverage -import com.suwiki.domain.lectureevaluation.usecase.lecture.RetrieveLectureEvaluationAverageListUseCase -import com.suwiki.domain.user.usecase.GetUserInfoUseCase -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.collections.immutable.toPersistentList -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.lastOrNull -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.annotation.OrbitExperimental -import org.orbitmvi.orbit.syntax.simple.SimpleSyntax -import org.orbitmvi.orbit.syntax.simple.blockingIntent -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class LectureEvaluationViewModel @Inject constructor( - private val getUserInfoUseCase: GetUserInfoUseCase, - private val getLectureEvaluationListUseCase: RetrieveLectureEvaluationAverageListUseCase, -) : ContainerHost, ViewModel() { - override val container: Container = - container(LectureEvaluationState()) - - private val mutex: Mutex = Mutex() - - private val currentState - get() = container.stateFlow.value - - private var isLoggedIn: Boolean = false - private var isFirstVisit: Boolean = true - private var page: Int = 1 - private var searchQuery: String = "" - - fun searchLectureEvaluation(search: String) { - searchQuery = search - getLectureEvaluationList(search = search, needClear = true) - } - - @OptIn(OrbitExperimental::class) - fun updateSearchValue(searchValue: String) = blockingIntent { - reduce { state.copy(searchValue = searchValue) } - } - - fun updateSelectedOpenMajor(openMajor: String) = intent { - if (openMajor == state.selectedOpenMajor) return@intent - - reduce { - state.copy( - selectedOpenMajor = openMajor, - ) - } - - getLectureEvaluationList( - needClear = true, - ) - } - - fun updateAlignItem(position: Int) = intent { - reduce { - state.copy( - selectedAlignPosition = position, - ) - } - - getLectureEvaluationList( - needClear = true, - ) - } - - fun initData() = intent { - checkLoggedIn() - if (isLoggedIn.not() && isFirstVisit) { - showOnboardingBottomSheet() - } - - if (isFirstVisit) { - reduce { state.copy(isLoading = true) } - getLectureEvaluationList(needClear = false).join() - reduce { state.copy(isLoading = false) } - } - - isFirstVisit = false - } - - fun getLectureEvaluationList( - search: String = searchQuery, - needClear: Boolean, - ) = intent { - mutex.withLock { - val currentList = if (needClear) { - page = 1 - reduce { state.copy(isLoading = true) } - emptyList() - } else { - state.lectureEvaluationList - } - - getLectureEvaluationListUseCase( - RetrieveLectureEvaluationAverageListUseCase.Param( - search = search, - option = LectureAlign.entries[currentState.selectedAlignPosition].query, - page = page, - majorType = currentState.selectedOpenMajor, - ), - ).onSuccess { newList -> - handleGetLectureEvaluationListSuccess( - currentList = currentList, - newList = newList, - ) - }.onFailure { - postSideEffect(LectureEvaluationSideEffect.HandleException(it)) - } - - if (needClear) { - postSideEffect(LectureEvaluationSideEffect.ScrollToTop) - reduce { state.copy(isLoading = false) } - } - } - } - - private suspend fun SimpleSyntax.handleGetLectureEvaluationListSuccess( - currentList: List, - newList: List, - ) = reduce { - page++ - state.copy( - lectureEvaluationList = currentList - .plus(newList) - .distinctBy { it?.id } - .toPersistentList(), - ) - } - - private suspend fun checkLoggedIn() { - isLoggedIn = getUserInfoUseCase().catch { }.lastOrNull()?.isLoggedIn == true - } - - fun navigateOpenMajor(selectedOpenMajor: String) = intent { postSideEffect(LectureEvaluationSideEffect.NavigateOpenMajor(selectedOpenMajor)) } - fun navigateLogin() = intent { postSideEffect(LectureEvaluationSideEffect.NavigateLogin) } - fun navigateSignup() = intent { postSideEffect(LectureEvaluationSideEffect.NavigateSignUp) } - fun navigateLectureEvaluationDetailIfLoggedIn(id: String) = intent { - if (isLoggedIn.not()) { - postSideEffect(LectureEvaluationSideEffect.NavigateLogin) - } else { - postSideEffect(LectureEvaluationSideEffect.NavigateLectureEvaluationDetail(id)) - } - } - - private fun showOnboardingBottomSheet() = intent { reduce { state.copy(showOnboardingBottomSheet = true) } } - fun hideOnboardingBottomSheet() = intent { reduce { state.copy(showOnboardingBottomSheet = false) } } - - fun showAgreementBottomSheet() = intent { reduce { state.copy(showAgreementBottomSheet = true) } } - fun hideAgreementBottomSheet() = intent { reduce { state.copy(showAgreementBottomSheet = false) } } - - fun toggleTermChecked() = intent { reduce { state.copy(isCheckedTerm = !state.isCheckedTerm) } } - fun togglePersonalPolicyChecked() = intent { reduce { state.copy(isCheckedPersonalPolicy = !state.isCheckedPersonalPolicy) } } - - fun openTermWebSite() = intent { postSideEffect(LectureEvaluationSideEffect.OpenTermWebSite) } - fun openPersonalPolicyWebSite() = intent { postSideEffect(LectureEvaluationSideEffect.OpenPersonalPolicyWebSite) } - - fun showAlignBottomSheet() = intent { reduce { state.copy(showAlignBottomSheet = true) } } - fun hideAlignBottomSheet() = intent { reduce { state.copy(showAlignBottomSheet = false) } } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/component/EvaluationAppBar.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/component/EvaluationAppBar.kt deleted file mode 100644 index b2f990b84..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/component/EvaluationAppBar.kt +++ /dev/null @@ -1,90 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.viewerrepoter.component - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.material3.Icon -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Alignment.Companion.CenterVertically -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.suwiki.presentation.common.designsystem.theme.GrayFB -import com.suwiki.presentation.common.designsystem.theme.Primary -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.ui.extension.suwikiClickable -import com.suwiki.presentation.lectureevaluation.R - -@Composable -fun EvaluationAppBar( - modifier: Modifier = Modifier, - title: String, - major: String, - onClickMajor: () -> Unit = {}, -) { - Row( - modifier = modifier - .fillMaxWidth() - .wrapContentHeight() - .background(GrayFB) - .padding(top = 28.dp, bottom = 3.dp, start = 24.dp, end = 24.dp), - ) { - Text( - text = title, - style = SuwikiTheme.typography.header1, - ) - FilterButton( - text = major, - onClick = onClickMajor, - modifier = Modifier - .align(CenterVertically), - ) - } -} - -@Composable -fun FilterButton( - modifier: Modifier = Modifier, - text: String, - onClick: () -> Unit = {}, -) { - Row( - modifier = modifier - .suwikiClickable(onClick = onClick) - .wrapContentHeight() - .padding(vertical = 4.dp, horizontal = 8.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Text( - text = text, - style = SuwikiTheme.typography.header6, - color = Primary, - ) - Icon( - painter = painterResource(id = R.drawable.ic_filter_arrow_down), - contentDescription = "", - tint = Primary, - modifier = Modifier - .size(24.dp) - .padding(vertical = 9.dp, horizontal = 7.dp), - ) - } -} - -@Preview(showSystemUi = true) -@Composable -fun EvaluationAppBarPreview() { - SuwikiTheme { - EvaluationAppBar( - title = "강의평가", - major = "학과명", - onClickMajor = { /*TODO*/ }, - ) - } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/component/EvaluationCard.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/component/EvaluationCard.kt deleted file mode 100644 index b93676f89..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/component/EvaluationCard.kt +++ /dev/null @@ -1,141 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.viewerrepoter.component - -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.IntrinsicSize -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.foundation.layout.wrapContentWidth -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Text -import androidx.compose.material3.VerticalDivider -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.suwiki.presentation.common.designsystem.component.badge.BadgeColor -import com.suwiki.presentation.common.designsystem.component.badge.SuwikiBadge -import com.suwiki.presentation.common.designsystem.shadow.cardShadow -import com.suwiki.presentation.common.designsystem.theme.Black -import com.suwiki.presentation.common.designsystem.theme.Gray6A -import com.suwiki.presentation.common.designsystem.theme.GrayDA -import com.suwiki.presentation.common.designsystem.theme.Primary -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.common.ui.extension.suwikiClickable -import java.util.Locale - -@Composable -fun EvaluationCard( - modifier: Modifier = Modifier, - className: String, - openMajor: String, - professor: String, - rating: Float, - classType: String, - onClick: () -> Unit, -) { - Row( - modifier = modifier - .fillMaxWidth() - .cardShadow() - .clip(RoundedCornerShape(10.dp)) - .suwikiClickable(onClick = onClick) - .background(White) - .padding(horizontal = 16.dp, vertical = 13.dp), - horizontalArrangement = Arrangement.SpaceBetween, - ) { - Column( - modifier = Modifier.weight(1f), - ) { - Text( - modifier = Modifier - .wrapContentHeight(), - maxLines = 1, - overflow = TextOverflow.Ellipsis, - text = className, - style = SuwikiTheme.typography.header3, - color = Black, - ) - Row( - modifier = Modifier - .wrapContentSize() - .height(IntrinsicSize.Min), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(4.dp), - ) { - Text( - text = openMajor, - style = SuwikiTheme.typography.body7, - color = Gray6A, - ) - VerticalDivider( - color = GrayDA, - modifier = Modifier - .fillMaxHeight() - .width(1.dp) - .padding(vertical = 3.dp), - ) - Text( - text = if (professor == "null") stringResource(id = com.suwiki.presentation.common.ui.R.string.word_none) else professor, - style = SuwikiTheme.typography.body7, - color = Gray6A, - ) - } - Spacer(modifier = Modifier.height(3.dp)) - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(2.dp), - modifier = Modifier.wrapContentWidth(), - ) { - Image( - painter = painterResource(id = com.suwiki.presentation.common.ui.R.drawable.ic_star_filled), - contentDescription = null, - ) - Text( - text = "%.1f".format(Locale.US, rating), - style = SuwikiTheme.typography.body1, - color = Primary, - ) - } - } - - SuwikiBadge( - text = classType, - color = BadgeColor.Gray, - ) - } -} - -@Preview -@Composable -fun CardPreview() { - SuwikiTheme { - Box(modifier = Modifier.padding(10.dp)) { - EvaluationCard( - modifier = Modifier, - className = "강의명강의명강의명강의명강의명강의명", - openMajor = "개설학과", - professor = "교수명", - rating = 4.0f, - classType = "강의 유형", - onClick = {}, - ) - } - } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/component/EvaluationSearchBar.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/component/EvaluationSearchBar.kt deleted file mode 100644 index f1b7902ef..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/component/EvaluationSearchBar.kt +++ /dev/null @@ -1,137 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.viewerrepoter.component - -import androidx.compose.foundation.background -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.KeyboardActions -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material3.Icon -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.focus.FocusManager -import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.platform.LocalSoftwareKeyboardController -import androidx.compose.ui.platform.SoftwareKeyboardController -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.suwiki.presentation.common.designsystem.component.searchbar.BasicSearchBar -import com.suwiki.presentation.common.designsystem.shadow.cardShadow -import com.suwiki.presentation.common.designsystem.theme.Gray6A -import com.suwiki.presentation.common.designsystem.theme.GrayCB -import com.suwiki.presentation.common.designsystem.theme.GrayFB -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.common.ui.extension.suwikiClickable -import com.suwiki.presentation.lectureevaluation.R - -@Composable -fun EvaluationSearchBar( - modifier: Modifier = Modifier, - placeHolder: String = "", - value: String = "", - maxLines: Int = 1, - minLines: Int = 1, - onValueChange: (String) -> Unit = { _ -> }, - onClickClearButton: () -> Unit = {}, - onClickFilterButton: () -> Unit = {}, - onClickSearchButton: (String) -> Unit = {}, - keyboardOptions: KeyboardOptions = KeyboardOptions.Default, - keyboardController: SoftwareKeyboardController? = LocalSoftwareKeyboardController.current, - focusRequester: FocusRequester = remember { FocusRequester() }, - focusManager: FocusManager = LocalFocusManager.current, - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, -) { - Row( - modifier - .background(GrayFB) - .padding(vertical = 10.dp, horizontal = 24.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - BasicSearchBar( - modifier = Modifier - .focusRequester(focusRequester) - .weight(1f) - .cardShadow() - .background(White, shape = RoundedCornerShape(10.dp)) - .height(40.dp) - .padding(8.dp), - value = value, - onValueChange = onValueChange, - maxLines = maxLines, - minLines = minLines, - interactionSource = interactionSource, - placeholder = placeHolder, - keyboardOptions = keyboardOptions, - keyboardActions = KeyboardActions( - onDone = { - onClickSearchButton(value) - keyboardController?.hide() - focusManager.clearFocus() - }, - ), - placeholderColor = GrayCB, - onClickClearButton = onClickClearButton, - ) - - Spacer(modifier = Modifier.size(4.dp)) - - SuwikiAlignButton( - onClick = onClickFilterButton, - ) - } -} - -@Composable -fun SuwikiAlignButton( - modifier: Modifier = Modifier, - onClick: () -> Unit = {}, -) { - Icon( - painter = painterResource(id = R.drawable.ic_filter), - contentDescription = "", - modifier = modifier - .cardShadow() - .clip(RoundedCornerShape(10.dp)) - .suwikiClickable(onClick = onClick) - .background(White) - .padding(8.dp), - tint = Gray6A, - ) -} - -@Preview(showBackground = true, backgroundColor = 0xFFFFFF) -@Composable -fun SuwikiSearchBarWithFilterPreview() { - SuwikiTheme { - var normalValue by remember { - mutableStateOf("") - } - - Column( - verticalArrangement = Arrangement.spacedBy(10.dp), - ) { - EvaluationSearchBar( - placeHolder = "Hinted search text", - value = normalValue, - onValueChange = { normalValue = it }, - onClickClearButton = { normalValue = "" }, - ) - } - } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/component/OnboardingBottomSheet.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/component/OnboardingBottomSheet.kt deleted file mode 100644 index e998be226..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/component/OnboardingBottomSheet.kt +++ /dev/null @@ -1,94 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.viewerrepoter.component - -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.pager.PagerState -import androidx.compose.foundation.pager.rememberPagerState -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.rememberModalBottomSheetState -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.suwiki.presentation.common.designsystem.component.bottomsheet.SuwikiBottomSheet -import com.suwiki.presentation.common.designsystem.component.button.SuwikiContainedLargeButton -import com.suwiki.presentation.common.designsystem.component.button.SuwikiOutlinedButton -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.lectureevaluation.R -import com.suwiki.presentation.lectureevaluation.viewerrepoter.LectureEvaluationState - -@Composable -@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) -fun OnboardingBottomSheet( - uiState: LectureEvaluationState, - hideOnboardingBottomSheet: () -> Unit, - pagerState: PagerState, - onClickLoginButton: () -> Unit = {}, - onClickSignupButton: () -> Unit = {}, -) { - SuwikiBottomSheet( - sheetState = rememberModalBottomSheetState( - skipPartiallyExpanded = true, - ), - isSheetOpen = uiState.showOnboardingBottomSheet, - onDismissRequest = hideOnboardingBottomSheet, - ) { - OnboardingBottomSheetContent( - pagerState = pagerState, - onClickLoginButton = onClickLoginButton, - onClickSignupButton = onClickSignupButton, - ) - } -} - -@OptIn(ExperimentalFoundationApi::class) -@Composable -private fun OnboardingBottomSheetContent( - pagerState: PagerState = rememberPagerState(pageCount = { ONBOARDING_PAGE_COUNT }), - onClickLoginButton: () -> Unit = {}, - onClickSignupButton: () -> Unit = {}, -) { - Column( - modifier = Modifier.padding(top = 32.dp, bottom = 32.dp, start = 24.dp, end = 24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Image( - modifier = Modifier.align(Alignment.CenterHorizontally), - painter = painterResource(id = R.drawable.ic_logo), - contentDescription = stringResource(R.string.content_description_logo), - ) - - Spacer(modifier = Modifier.size(64.dp)) - - OnboardingPager(pagerState) - - Spacer(modifier = Modifier.size(28.dp)) - - OnboardingPagerIndicator( - pageCount = ONBOARDING_PAGE_COUNT, - pagerState = pagerState, - ) - - Spacer(modifier = Modifier.size(48.dp)) - - SuwikiContainedLargeButton(text = stringResource(R.string.onboarding_button_signup), onClick = onClickSignupButton) - Spacer(modifier = Modifier.size(12.dp)) - SuwikiOutlinedButton(text = stringResource(R.string.word_login), onClick = onClickLoginButton) - } -} - -@OptIn(ExperimentalFoundationApi::class) -@Preview(showBackground = true) -@Composable -fun OnboardingBottomSheetContentPreview() { - SuwikiTheme { - OnboardingBottomSheetContent() - } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/component/OnboardingPager.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/component/OnboardingPager.kt deleted file mode 100644 index c05dade8b..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/component/OnboardingPager.kt +++ /dev/null @@ -1,107 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.viewerrepoter.component - -import androidx.annotation.DrawableRes -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.pager.HorizontalPager -import androidx.compose.foundation.pager.PagerState -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import com.suwiki.presentation.common.designsystem.theme.Gray6A -import com.suwiki.presentation.common.designsystem.theme.GrayDA -import com.suwiki.presentation.common.designsystem.theme.Primary -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.lectureevaluation.R - -const val ONBOARDING_PAGE_COUNT = 2 - -@Composable -@OptIn(ExperimentalFoundationApi::class) -fun OnboardingPager(pagerState: PagerState) { - HorizontalPager( - state = pagerState, - ) { page -> - when (page) { - 0 -> { - OnboardingPageContent( - title = stringResource(R.string.onboarding_title), - description = stringResource(R.string.onboarding1_description), - icon = R.drawable.ic_onboarding1, - ) - } - - 1 -> { - OnboardingPageContent( - title = stringResource(R.string.onboarding_title), - description = stringResource(R.string.onboarding2_description), - icon = R.drawable.ic_onboarding2, - ) - } - } - } -} - -@Composable -private fun OnboardingPageContent( - title: String, - description: String, - @DrawableRes icon: Int, -) { - Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Image( - modifier = Modifier.size(160.dp), - painter = painterResource(id = icon), - contentDescription = "", - ) - - Spacer(modifier = Modifier.size(42.dp)) - - Text(text = title, style = SuwikiTheme.typography.header2, textAlign = TextAlign.Center) - - Spacer(modifier = Modifier.size(7.dp)) - - Text(text = description, style = SuwikiTheme.typography.body5, color = Gray6A) - } -} - -@OptIn(ExperimentalFoundationApi::class) -@Composable -fun OnboardingPagerIndicator( - pageCount: Int, - pagerState: PagerState, -) { - Row( - horizontalArrangement = Arrangement.Center, - ) { - repeat(pageCount) { iteration -> - val color = if (pagerState.currentPage == iteration) Primary else GrayDA - Box( - modifier = Modifier - .padding(horizontal = 4.dp) - .clip(CircleShape) - .background(color) - .size(5.dp), - ) - } - } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/LectureEvaluationDetailContract.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/LectureEvaluationDetailContract.kt deleted file mode 100644 index b4c8ac52d..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/LectureEvaluationDetailContract.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.viewerrepoter.detail - -import com.suwiki.common.model.lectureevaluation.exam.ExamEvaluation -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluation -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationExtraAverage -import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.persistentListOf - -data class LectureEvaluationDetailState( - val isLoading: Boolean = false, - val currentTabPage: Int = 0, - val lectureEvaluationExtraAverage: LectureEvaluationExtraAverage = LectureEvaluationExtraAverage(), - val lectureEvaluationList: PersistentList = persistentListOf(), - val isLectureEvaluationWritten: Boolean = false, - val examEvaluationList: PersistentList = persistentListOf(), - val needBuyExam: Boolean = false, - val isExamEvaluationWritten: Boolean = false, - val showLectureReportDialog: Boolean = false, - val showExamReportDialog: Boolean = false, -) -sealed interface LectureEvaluationDetailSideEffect { - data class ShowLackPointToast(val msg: String) : LectureEvaluationDetailSideEffect - data object PopBackStack : LectureEvaluationDetailSideEffect - data class HandleException(val throwable: Throwable) : LectureEvaluationDetailSideEffect - data class NavigateLectureEvaluationEditor(val argument: String) : LectureEvaluationDetailSideEffect - data class NavigateExamEvaluationEditor(val argument: String) : LectureEvaluationDetailSideEffect - data object ShowAlreadyWriteToast : LectureEvaluationDetailSideEffect -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/LectureEvaluationDetailScreen.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/LectureEvaluationDetailScreen.kt deleted file mode 100644 index 23548b9e2..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/LectureEvaluationDetailScreen.kt +++ /dev/null @@ -1,366 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.viewerrepoter.detail - -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.pager.HorizontalPager -import androidx.compose.foundation.pager.PagerState -import androidx.compose.foundation.pager.rememberPagerState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Icon -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.runtime.snapshotFlow -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.presentation.common.designsystem.component.appbar.SuwikiAppBarWithTitle -import com.suwiki.presentation.common.designsystem.component.button.SuwikiOutlinedButton -import com.suwiki.presentation.common.designsystem.component.dialog.SuwikiDialog -import com.suwiki.presentation.common.designsystem.component.loading.LoadingScreen -import com.suwiki.presentation.common.designsystem.component.tabbar.SuwikiTabBar -import com.suwiki.presentation.common.designsystem.component.tabbar.TabTitle -import com.suwiki.presentation.common.designsystem.theme.Gray95 -import com.suwiki.presentation.common.designsystem.theme.Primary -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.common.ui.enums.LectureEvaluationTab -import com.suwiki.presentation.common.ui.extension.OnBottomReached -import com.suwiki.presentation.common.ui.extension.collectWithLifecycle -import com.suwiki.presentation.common.ui.extension.suwikiClickable -import com.suwiki.presentation.lectureevaluation.R -import com.suwiki.presentation.lectureevaluation.viewerrepoter.detail.component.ExamEvaluationContainer -import com.suwiki.presentation.lectureevaluation.viewerrepoter.detail.component.LectureEvaluationContainer -import com.suwiki.presentation.lectureevaluation.viewerrepoter.detail.component.SuwikiReviewStatisticsContainer -import me.onebone.toolbar.CollapsingToolbarScaffold -import me.onebone.toolbar.ExperimentalToolbarApi -import me.onebone.toolbar.ScrollStrategy -import me.onebone.toolbar.rememberCollapsingToolbarScaffoldState -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect - -private val LECTURE_EVALUATION_PAGE_COUNT = LectureEvaluationTab.entries.size - -@OptIn(ExperimentalFoundationApi::class) -@Composable -fun LectureEvaluationDetailRoute( - viewModel: LectureEvaluationDetailViewModel = hiltViewModel(), - popBackStack: () -> Unit = {}, - navigateLectureEvaluationEditor: (String) -> Unit = {}, - navigateExamEvaluationEditor: (String) -> Unit = {}, - onShowToast: (String) -> Unit, - handleException: (Throwable) -> Unit = {}, -) { - val uiState = viewModel.collectAsState().value - - val lectureEvaluationListState = rememberLazyListState() - val examEvaluationListState = rememberLazyListState() - - val context = LocalContext.current - - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - is LectureEvaluationDetailSideEffect.PopBackStack -> popBackStack() - is LectureEvaluationDetailSideEffect.HandleException -> handleException(sideEffect.throwable) - is LectureEvaluationDetailSideEffect.ShowLackPointToast -> onShowToast(sideEffect.msg) - is LectureEvaluationDetailSideEffect.NavigateExamEvaluationEditor -> navigateExamEvaluationEditor(sideEffect.argument) - is LectureEvaluationDetailSideEffect.NavigateLectureEvaluationEditor -> navigateLectureEvaluationEditor(sideEffect.argument) - LectureEvaluationDetailSideEffect.ShowAlreadyWriteToast -> onShowToast(context.getString(R.string.toast_already_write)) - } - } - val pagerState = rememberPagerState(pageCount = { LECTURE_EVALUATION_PAGE_COUNT }) - - LaunchedEffect(key1 = Unit) { - viewModel.initData() - } - - lectureEvaluationListState.OnBottomReached { - viewModel.getLectureEvaluationList() - } - - examEvaluationListState.OnBottomReached { - viewModel.getExamEvaluationList() - } - - LaunchedEffect(key1 = uiState.currentTabPage) { - pagerState.animateScrollToPage(uiState.currentTabPage) - } - - snapshotFlow { pagerState.currentPage }.collectWithLifecycle { - viewModel.syncPager(it) - } - - LectureEvaluationDetailScreen( - uiState = uiState, - pagerState = pagerState, - lectureEvaluationListState = lectureEvaluationListState, - examEvaluationListState = examEvaluationListState, - onClickBack = viewModel::popBackStack, - onClickTab = viewModel::syncPager, - onClickBuyExamButton = viewModel::buyExam, - onClickWriteButton = viewModel::navigateEvaluationEditor, - onClickLectureReportButton = viewModel::showLectureReportDialog, - onClickLectureReportConfirm = { - viewModel.hideLectureReportDialog() - viewModel.reportLecture() - }, - onDismissLectureReport = viewModel::hideLectureReportDialog, - onClickExamReportButton = viewModel::showExamReportDialog, - onClickExamReportConfirm = { - viewModel.hideExamReportDialog() - viewModel.reportExam() - }, - onDismissExamReport = viewModel::hideExamReportDialog, - ) -} - -@OptIn(ExperimentalFoundationApi::class, ExperimentalToolbarApi::class) -@Composable -fun LectureEvaluationDetailScreen( - uiState: LectureEvaluationDetailState = LectureEvaluationDetailState(), - pagerState: PagerState = rememberPagerState(pageCount = { LECTURE_EVALUATION_PAGE_COUNT }), - lectureEvaluationListState: LazyListState = rememberLazyListState(), - examEvaluationListState: LazyListState = rememberLazyListState(), - onClickBack: () -> Unit = {}, - onClickTab: (Int) -> Unit = {}, - onClickBuyExamButton: () -> Unit = {}, - onClickWriteButton: () -> Unit = {}, - onClickLectureReportButton: (Long) -> Unit = {}, - onClickLectureReportConfirm: () -> Unit = {}, - onDismissLectureReport: () -> Unit = {}, - onClickExamReportButton: (Long) -> Unit = {}, - onClickExamReportConfirm: () -> Unit = {}, - onDismissExamReport: () -> Unit = {}, -) { - val state = rememberCollapsingToolbarScaffoldState() - - Column { - SuwikiAppBarWithTitle( - showBackIcon = true, - showCloseIcon = false, - onClickBack = onClickBack, - ) - - CollapsingToolbarScaffold( - modifier = Modifier - .fillMaxSize() - .background(White), - state = state, - scrollStrategy = ScrollStrategy.EnterAlwaysCollapsed, - toolbar = { - Column { - SuwikiReviewStatisticsContainer( - data = uiState.lectureEvaluationExtraAverage, - ) - - SuwikiTabBar( - selectedTabPosition = pagerState.currentPage, - ) { - LectureEvaluationTab.entries.forEach { tab -> - with(tab) { - TabTitle( - title = stringResource(title), - position = position, - selected = pagerState.currentPage == position, - onClick = { onClickTab(position) }, - ) - } - } - } - } - }, - ) { - HorizontalPager( - modifier = Modifier.fillMaxSize(), - state = pagerState, - ) { pager -> - when (LectureEvaluationTab.entries[pager]) { - LectureEvaluationTab.LECTURE_EVALUATION -> { - if (uiState.lectureEvaluationList.isEmpty()) { - Text( - modifier = Modifier - .padding(52.dp) - .fillMaxSize(), - textAlign = TextAlign.Center, - text = stringResource(R.string.lecture_evaluation_detail_empty_data), - style = SuwikiTheme.typography.header4, - color = Gray95, - ) - } - - LazyColumn( - modifier = Modifier.fillMaxSize(), - state = lectureEvaluationListState, - contentPadding = PaddingValues(bottom = 100.dp), - ) { - items( - items = uiState.lectureEvaluationList, - key = { it.id }, - ) { - LectureEvaluationContainer( - semester = it.selectedSemester, - content = it.content, - rating = it.totalAvg, - onClickButton = { onClickLectureReportButton(it.id) }, - ) - } - } - } - - LectureEvaluationTab.EXAM_INFO -> { - when { - uiState.needBuyExam -> { - Box(modifier = Modifier.fillMaxSize()) { - SuwikiOutlinedButton( - modifier = Modifier - .padding(52.dp), - text = stringResource(R.string.lecture_evaluation_detail_screen_buy_exam), - onClick = onClickBuyExamButton, - ) - } - } - - uiState.examEvaluationList.isEmpty() -> { - Text( - modifier = Modifier - .padding(52.dp) - .fillMaxSize(), - textAlign = TextAlign.Center, - text = stringResource(R.string.lecture_evaluation_detail_empty_data), - style = SuwikiTheme.typography.header4, - color = Gray95, - ) - } - - else -> { - LazyColumn( - modifier = Modifier.fillMaxSize(), - state = examEvaluationListState, - contentPadding = PaddingValues(bottom = 100.dp), - ) { - items( - items = uiState.examEvaluationList, - key = { - it.id - }, - ) { - ExamEvaluationContainer( - difficulty = it.examDifficulty, - examType = it.examType, - content = it.content, - semester = it.selectedSemester, - examInfo = it.examInfo, - onClickButton = { onClickExamReportButton(it.id) }, - ) - } - } - } - } - } - } - } - - LectureEvaluationWriteButton( - modifier = Modifier - .padding(12.dp) - .align(Alignment.BottomCenter), - onClick = onClickWriteButton, - ) - } - } - - if (uiState.isLoading) { - LoadingScreen( - modifier = Modifier - .padding(top = 50.dp) - .background(Color.White), - ) - } - - if (uiState.showLectureReportDialog) { - SuwikiDialog( - headerText = "강의평가 신고", - bodyText = "허위 신고 시 서비스 이용에 제한을 받을 수 있습니다.", - confirmButtonText = "신고", - onDismissRequest = onDismissLectureReport, - onClickConfirm = onClickLectureReportConfirm, - dismissButtonText = "취소", - onClickDismiss = onDismissLectureReport, - ) - } - - if (uiState.showExamReportDialog) { - SuwikiDialog( - headerText = "시험정보 신고", - bodyText = "허위 신고 시 서비스 이용에 제한을 받을 수 있습니다.", - confirmButtonText = "신고", - onDismissRequest = onDismissExamReport, - onClickConfirm = onClickExamReportConfirm, - dismissButtonText = "취소", - onClickDismiss = onDismissExamReport, - ) - } -} - -@Composable -fun LectureEvaluationWriteButton( - modifier: Modifier = Modifier, - onClick: () -> Unit = {}, -) { - Row( - modifier = modifier - .clip(shape = RoundedCornerShape(10.dp)) - .suwikiClickable(onClick = onClick) - .background(Primary) - .padding(vertical = 8.dp, horizontal = 16.dp), - ) { - Icon( - modifier = Modifier.align(Alignment.CenterVertically), - painter = painterResource(R.drawable.ic_write), - contentDescription = "", - tint = White, - ) - Text( - text = stringResource(R.string.lecture_evaluation_detail_screen_write), - color = White, - style = SuwikiTheme.typography.body2, - ) - } -} - -@OptIn(ExperimentalFoundationApi::class) -@Preview -@Composable -fun LectureEvaluationDetailScreenPreview() { - var currentPage by remember { mutableIntStateOf(0) } - SuwikiTheme { - LectureEvaluationDetailScreen( - uiState = LectureEvaluationDetailState( - currentTabPage = currentPage, - ), - onClickTab = { currentPage = it }, - ) - } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/LectureEvaluationDetailViewModel.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/LectureEvaluationDetailViewModel.kt deleted file mode 100644 index 7be323a68..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/LectureEvaluationDetailViewModel.kt +++ /dev/null @@ -1,235 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.viewerrepoter.detail - -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel -import com.suwiki.common.model.exception.UserPointLackException -import com.suwiki.common.model.lectureevaluation.exam.MyExamEvaluation -import com.suwiki.common.model.lectureevaluation.lecture.MyLectureEvaluation -import com.suwiki.domain.lectureevaluation.usecase.exam.BuyExamUseCase -import com.suwiki.domain.lectureevaluation.usecase.exam.GetExamEvaluationListUseCase -import com.suwiki.domain.lectureevaluation.usecase.exam.ReportExamUseCase -import com.suwiki.domain.lectureevaluation.usecase.lecture.GetLectureEvaluationExtraAverageUseCase -import com.suwiki.domain.lectureevaluation.usecase.lecture.GetLectureEvaluationListUseCase -import com.suwiki.domain.lectureevaluation.usecase.lecture.ReportLectureUseCase -import com.suwiki.presentation.common.ui.enums.LectureEvaluationTab -import com.suwiki.presentation.common.ui.extension.encodeToUri -import com.suwiki.presentation.lectureevaluation.navigation.LectureEvaluationRoute -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.toPersistentList -import kotlinx.coroutines.joinAll -import kotlinx.serialization.json.Json -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class LectureEvaluationDetailViewModel @Inject constructor( - savedStateHandle: SavedStateHandle, - private val getLectureEvaluationExtraAverageUseCase: GetLectureEvaluationExtraAverageUseCase, - private val getLectureEvaluationListUseCase: GetLectureEvaluationListUseCase, - private val getExamEvaluationListUseCase: GetExamEvaluationListUseCase, - private val reportExamUseCase: ReportExamUseCase, - private val reportLectureUseCase: ReportLectureUseCase, - private val buyExamUseCase: BuyExamUseCase, -) : ContainerHost, ViewModel() { - override val container: Container = container( - LectureEvaluationDetailState(), - ) - - private val evaluationId: Long = savedStateHandle.get(LectureEvaluationRoute.lectureEvaluationDetail)!!.toLong() - private var lectureEvaluationPage = 1 - private var isLastLectureEvaluation = false - private var examEvaluationPage = 1 - private var isLastExamEvaluation = false - - private var lectureReportId: Long = 0 - private var examReportId: Long = 0 - - fun showLectureReportDialog(lectureReportId: Long) = intent { - this@LectureEvaluationDetailViewModel.lectureReportId = lectureReportId - reduce { - state.copy( - showLectureReportDialog = true, - ) - } - } - - fun hideLectureReportDialog() = intent { - reduce { - state.copy( - showLectureReportDialog = false, - ) - } - } - - fun showExamReportDialog(examReportId: Long) = intent { - this@LectureEvaluationDetailViewModel.examReportId = examReportId - reduce { - state.copy( - showExamReportDialog = true, - ) - } - } - - fun hideExamReportDialog() = intent { - reduce { - state.copy( - showExamReportDialog = false, - ) - } - } - - fun reportLecture() = intent { - reportLectureUseCase(lectureReportId) - .onFailure { postSideEffect(LectureEvaluationDetailSideEffect.HandleException(it)) } - } - - fun reportExam() = intent { - reportExamUseCase(examReportId) - .onFailure { postSideEffect(LectureEvaluationDetailSideEffect.HandleException(it)) } - } - - fun syncPager(currentPage: Int) = intent { reduce { state.copy(currentTabPage = currentPage) } } - - fun initData() = intent { - reduce { state.copy(isLoading = true) } - - joinAll(getLectureEvaluationDetail(), getLectureEvaluationList(needClear = true), getExamEvaluationList(needClear = true)) - - reduce { state.copy(isLoading = false) } - } - - private fun getLectureEvaluationDetail() = intent { - getLectureEvaluationExtraAverageUseCase(evaluationId) - .onSuccess { lectureEvaluationExtraAverage -> - reduce { - state.copy( - lectureEvaluationExtraAverage = lectureEvaluationExtraAverage, - ) - } - } - .onFailure { - postSideEffect(LectureEvaluationDetailSideEffect.HandleException(it)) - } - } - - fun getLectureEvaluationList(needClear: Boolean = false) = intent { - val currentList = if (needClear) { - lectureEvaluationPage = 1 - isLastLectureEvaluation = false - persistentListOf() - } else { - state.lectureEvaluationList - } - - if (isLastLectureEvaluation) return@intent - - getLectureEvaluationListUseCase( - GetLectureEvaluationListUseCase.Param( - lectureId = evaluationId, - page = lectureEvaluationPage, - ), - ).onSuccess { - reduce { - lectureEvaluationPage++ - isLastLectureEvaluation = it.data.isEmpty() - state.copy( - lectureEvaluationList = currentList.addAll(it.data).distinctBy { it.id }.toPersistentList(), - isLectureEvaluationWritten = it.written, - ) - } - }.onFailure { - postSideEffect(LectureEvaluationDetailSideEffect.HandleException(it)) - } - } - - fun getExamEvaluationList(needClear: Boolean = false) = intent { - val currentList = if (needClear) { - examEvaluationPage = 1 - isLastExamEvaluation = false - persistentListOf() - } else { - state.examEvaluationList - } - - if (isLastExamEvaluation) return@intent - - getExamEvaluationListUseCase( - GetExamEvaluationListUseCase.Param( - lectureId = evaluationId, - page = examEvaluationPage, - ), - ).onSuccess { - reduce { - examEvaluationPage++ - isLastExamEvaluation = it.data.isEmpty() - state.copy( - examEvaluationList = currentList.addAll(it.data).distinctBy { it.id }.toPersistentList(), - needBuyExam = it.needBuyExam, - isExamEvaluationWritten = it.written, - ) - } - }.onFailure { - postSideEffect(LectureEvaluationDetailSideEffect.HandleException(it)) - } - } - - fun buyExam() = intent { - buyExamUseCase(evaluationId) - .onSuccess { - getExamEvaluationList(needClear = true) - } - .onFailure { throwable -> - when (throwable) { - is UserPointLackException -> postSideEffect(LectureEvaluationDetailSideEffect.ShowLackPointToast(throwable.message)) - else -> postSideEffect(LectureEvaluationDetailSideEffect.HandleException(throwable)) - } - } - } - - fun navigateEvaluationEditor() = intent { - if (state.currentTabPage == LectureEvaluationTab.LECTURE_EVALUATION.position) { - if (state.isLectureEvaluationWritten) { - postSideEffect(LectureEvaluationDetailSideEffect.ShowAlreadyWriteToast) - return@intent - } - - postSideEffect( - LectureEvaluationDetailSideEffect.NavigateLectureEvaluationEditor( - Json.encodeToUri( - MyLectureEvaluation( - id = evaluationId, - lectureInfo = state.lectureEvaluationExtraAverage.info, - ), - ), - ), - ) - } else { - if (state.isExamEvaluationWritten) { - postSideEffect(LectureEvaluationDetailSideEffect.ShowAlreadyWriteToast) - return@intent - } - - postSideEffect( - LectureEvaluationDetailSideEffect.NavigateExamEvaluationEditor( - Json.encodeToUri( - MyExamEvaluation( - id = evaluationId, - lectureName = state.lectureEvaluationExtraAverage.info.lectureName, - professor = state.lectureEvaluationExtraAverage.info.professor, - majorType = state.lectureEvaluationExtraAverage.info.majorType, - semesterList = state.lectureEvaluationExtraAverage.info.semesterList, - ), - ), - ), - ) - } - } - - fun popBackStack() = intent { postSideEffect(LectureEvaluationDetailSideEffect.PopBackStack) } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/component/ExamEvaluationContainer.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/component/ExamEvaluationContainer.kt deleted file mode 100644 index f31ed1225..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/component/ExamEvaluationContainer.kt +++ /dev/null @@ -1,139 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.viewerrepoter.detail.component - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.suwiki.presentation.common.designsystem.component.badge.BadgeColor -import com.suwiki.presentation.common.designsystem.component.badge.SuwikiBadge -import com.suwiki.presentation.common.designsystem.component.button.SuwikiContainedSmallButton -import com.suwiki.presentation.common.designsystem.theme.Black -import com.suwiki.presentation.common.designsystem.theme.Gray95 -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White - -@Composable -fun ExamEvaluationContainer( - modifier: Modifier = Modifier, - difficulty: String, - examType: String, - semester: String, - examInfo: String, - content: String, - isAuthor: Boolean = false, - onClickButton: () -> Unit, -) { - val buttonText = if (isAuthor) { - stringResource(id = com.suwiki.presentation.common.ui.R.string.word_edit) - } else { - stringResource( - id = com.suwiki.presentation.common.ui.R.string.word_report, - ) - } - - Column( - modifier = Modifier - .fillMaxWidth() - .background(White) - .padding(24.dp), - ) { - Row( - modifier = Modifier.fillMaxWidth(), - ) { - if (isAuthor) { - SuwikiBadge( - color = BadgeColor.Blue, - text = stringResource(id = com.suwiki.presentation.common.ui.R.string.word_my), - ) - Spacer(modifier = Modifier.width(8.dp)) - } - SuwikiBadge( - color = BadgeColor.Gray, - text = semester, - ) - Spacer(modifier = Modifier.width(6.dp)) - SuwikiBadge( - color = BadgeColor.Gray, - text = examType, - ) - Spacer(modifier = Modifier.weight(1f)) - SuwikiContainedSmallButton(text = buttonText, onClick = onClickButton) - } - Spacer(modifier = Modifier.height(10.dp)) - Row( - modifier = modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(6.dp), - ) { - Text( - text = stringResource(id = com.suwiki.presentation.common.ui.R.string.word_difficulty), - style = SuwikiTheme.typography.caption2, - color = Gray95, - ) - Text( - text = difficulty, - style = SuwikiTheme.typography.caption1, - color = Black, - ) - } - Spacer(modifier = Modifier.height(2.dp)) - Row( - modifier = modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(6.dp), - ) { - Text( - text = stringResource(id = com.suwiki.presentation.common.ui.R.string.word_type_exam), - style = SuwikiTheme.typography.caption2, - color = Gray95, - ) - Text( - text = examInfo, - style = SuwikiTheme.typography.caption1, - color = Black, - ) - } - Spacer(modifier = Modifier.height(10.dp)) - Text( - text = content, - style = SuwikiTheme.typography.body7, - color = Black, - ) - } -} - -@Preview -@Composable -fun ExamEvaluationContainerPreview() { - SuwikiTheme { - Column { - ExamEvaluationContainer( - isAuthor = false, - difficulty = "어려움", - examInfo = "응용,실습,과제,PPT", - content = "거의 한 학기 팀플하시는데... 팀원 잘 만나면 잘 모르겠네요. 굉장히 오픈 마인드시긴해요.", - onClickButton = {}, - examType = "중간고사", - semester = "2023-1", - ) - ExamEvaluationContainer( - isAuthor = true, - difficulty = "어려움", - examType = "중간고사", - content = "거의 한 학기 팀플하시는데... 팀원 잘 만나면 잘 모르겠네요. 굉장히 오픈 마인드시긴해요.", - onClickButton = {}, - semester = "2023-1", - examInfo = "응용,실습,과제,PPT", - ) - } - } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/component/LectureEvaluationContainer.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/component/LectureEvaluationContainer.kt deleted file mode 100644 index b35f66a27..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/component/LectureEvaluationContainer.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.viewerrepoter.detail.component - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.suwiki.presentation.common.designsystem.component.badge.BadgeColor -import com.suwiki.presentation.common.designsystem.component.badge.SuwikiBadge -import com.suwiki.presentation.common.designsystem.component.button.SuwikiContainedSmallButton -import com.suwiki.presentation.common.designsystem.component.ratingbar.SuwikiRatingBar -import com.suwiki.presentation.common.designsystem.theme.Black -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.common.ui.R - -@Composable -fun LectureEvaluationContainer( - modifier: Modifier = Modifier, - content: String, - semester: String, - rating: Float, - isAuthor: Boolean = false, - onClickButton: () -> Unit = {}, -) { - val buttonText = if (isAuthor) stringResource(id = R.string.word_edit) else stringResource(id = R.string.word_report) - Column( - modifier = modifier - .fillMaxWidth() - .background(White) - .padding(24.dp), - verticalArrangement = Arrangement.spacedBy(14.dp), - ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(8.dp), - ) { - if (isAuthor) { - SuwikiBadge( - color = BadgeColor.Blue, - text = stringResource(id = R.string.word_my), - ) - } - SuwikiBadge( - color = BadgeColor.Gray, - text = semester, - ) - Spacer(modifier = Modifier.weight(1f)) - SuwikiContainedSmallButton(text = buttonText, onClick = onClickButton) - } - SuwikiRatingBar(rating = rating) - Text( - text = content, - style = SuwikiTheme.typography.body7, - color = Black, - ) - } -} - -@Preview -@Composable -fun ReviewContainerPreview() { - SuwikiTheme { - Column { - LectureEvaluationContainer( - isAuthor = false, - semester = "2023-1", - rating = 3.0f, - content = "거의 한 학기 팀플하시는데... 팀원 잘 만나면 잘 모르겠네요. 굉장히 오픈 마인드시긴해요.", - ) - LectureEvaluationContainer( - rating = 3.0f, - semester = "2023-1", - isAuthor = true, - content = "거의 한 학기 팀플하시는데... 팀원 잘 만나면 잘 모르겠네요. 굉장히 오픈 마인드시긴해요.", - ) - } - } -} diff --git a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/component/StatisticsContainer.kt b/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/component/StatisticsContainer.kt deleted file mode 100644 index 97ebbf3d3..000000000 --- a/presentation/lectureevaluation/src/main/java/com/suwiki/presentation/lectureevaluation/viewerrepoter/detail/component/StatisticsContainer.kt +++ /dev/null @@ -1,329 +0,0 @@ -package com.suwiki.presentation.lectureevaluation.viewerrepoter.detail.component - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.IntrinsicSize -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.foundation.layout.wrapContentWidth -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.LinearProgressIndicator -import androidx.compose.material3.Text -import androidx.compose.material3.VerticalDivider -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.StrokeCap -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.suwiki.common.model.enums.GradeLevel -import com.suwiki.common.model.enums.HomeworkLevel -import com.suwiki.common.model.enums.TeamLevel -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationExtraAverage -import com.suwiki.common.model.lectureevaluation.lecture.LectureInfo -import com.suwiki.presentation.common.designsystem.component.badge.BadgeColor -import com.suwiki.presentation.common.designsystem.component.badge.SuwikiBadge -import com.suwiki.presentation.common.designsystem.component.ratingbar.SuwikiRatingBar -import com.suwiki.presentation.common.designsystem.shadow.cardShadow -import com.suwiki.presentation.common.designsystem.theme.Black -import com.suwiki.presentation.common.designsystem.theme.Blue10 -import com.suwiki.presentation.common.designsystem.theme.Blue100 -import com.suwiki.presentation.common.designsystem.theme.Gray6A -import com.suwiki.presentation.common.designsystem.theme.GrayDA -import com.suwiki.presentation.common.designsystem.theme.GrayF6 -import com.suwiki.presentation.common.designsystem.theme.GrayFB -import com.suwiki.presentation.common.designsystem.theme.Green10 -import com.suwiki.presentation.common.designsystem.theme.Green100 -import com.suwiki.presentation.common.designsystem.theme.Orange10 -import com.suwiki.presentation.common.designsystem.theme.Orange100 -import com.suwiki.presentation.common.designsystem.theme.Primary -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.common.ui.R -import com.suwiki.presentation.common.ui.extension.toText -import java.util.Locale - -@Composable -fun SuwikiReviewStatisticsContainer( - modifier: Modifier = Modifier, - data: LectureEvaluationExtraAverage, -) { - Column( - modifier = modifier - .fillMaxWidth() - .background(GrayFB) - .padding(top = 14.dp, bottom = 24.dp, start = 24.dp, end = 24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - SuwikiBadge(color = BadgeColor.Gray, text = data.info.lectureType) - Spacer(modifier = Modifier.height(4.dp)) - Text( - text = data.info.lectureName, - style = SuwikiTheme.typography.header3, - color = Black, - ) - Spacer(modifier = Modifier.height(2.dp)) - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .wrapContentWidth() - .height(IntrinsicSize.Min), - horizontalArrangement = Arrangement.spacedBy(4.dp), - ) { - Text( - text = data.info.majorType, - style = SuwikiTheme.typography.body7, - color = Gray6A, - ) - VerticalDivider( - color = GrayDA, - modifier = Modifier - .fillMaxHeight() - .width(1.dp) - .padding(vertical = 3.dp), - ) - Text( - text = if (data.info.professor == "null") stringResource(id = com.suwiki.presentation.common.ui.R.string.word_none) else data.info.professor, - style = SuwikiTheme.typography.body7, - color = Gray6A, - ) - } - - if (data.totalAvg > 0.0f) { - Spacer(modifier = Modifier.height(14.dp)) - Row( - horizontalArrangement = Arrangement.spacedBy(7.dp), - ) { - StatisticsLabel( - color = LabelColor.entries[data.gradeAvg.ordinal], - name = stringResource(R.string.word_grade), - value = data.gradeAvg.toText(), - ) - StatisticsLabel( - color = LabelColor.entries[data.homeworkAvg.ordinal], - name = stringResource(R.string.word_homework), - value = data.homeworkAvg.toText(), - ) - StatisticsLabel( - color = LabelColor.entries.minus(LabelColor.BLUE)[data.teamAvg.ordinal], - name = stringResource(R.string.word_team), - value = data.teamAvg.toText(), - ) - } - } - Spacer(modifier = Modifier.height(23.dp)) - ReviewGradeCard( - rating = data.totalAvg, - honeyRating = data.honeyAvg, - learningRating = data.learningAvg, - satisfactionRating = data.satisfactionAvg, - ) - } -} - -@Composable -fun ReviewGradeCard( - modifier: Modifier = Modifier, - rating: Float, - honeyRating: Float, - learningRating: Float, - satisfactionRating: Float, -) { - val reviewCountColor = if (rating > 0) Primary else GrayDA - val reviewIndicatorColor = if (rating > 0) Black else GrayDA - Row( - modifier = modifier - .fillMaxWidth() - .cardShadow() - .clip(RoundedCornerShape(10.dp)) - .background(White) - .padding(16.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(20.dp), - ) { - Column( - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Text( - text = "%.1f".format(Locale.US, rating), - style = SuwikiTheme.typography.header1, - color = reviewCountColor, - ) - SuwikiRatingBar( - rating = rating, - ) - } - VerticalDivider( - color = GrayF6, - modifier = Modifier - .height(49.dp) - .width(1.dp), - ) - Column( - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally, - ) { - ReviewProgressLine( - name = stringResource(id = com.suwiki.presentation.common.ui.R.string.word_honey_rating), - rating = honeyRating, - textColor = reviewIndicatorColor, - ) - ReviewProgressLine( - name = stringResource(id = R.string.learning_quality), - rating = learningRating, - textColor = reviewIndicatorColor, - ) - ReviewProgressLine( - name = stringResource(id = R.string.satisfaction_quality), - rating = satisfactionRating, - textColor = reviewIndicatorColor, - ) - } - } -} - -@Composable -fun ReviewProgressLine( - name: String, - rating: Float, - textColor: Color, -) { - Row( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - ) { - Text( - text = name, - style = SuwikiTheme.typography.caption5, - color = textColor, - ) - LinearProgressIndicator( - progress = { rating / 5.0f }, - modifier = Modifier - .weight(1f) - .height(6.dp) - .padding(horizontal = 10.dp) - .clip(RoundedCornerShape(4.dp)), - color = Primary, - strokeCap = StrokeCap.Round, - ) - Text( - text = "%.1f".format(Locale.US, rating), - style = SuwikiTheme.typography.caption1, - color = textColor, - ) - } -} - -enum class LabelColor( - val backgroundColor: Color, - val contentColor: Color, -) { - GREEN( - backgroundColor = Green10, - contentColor = Green100, - ), - BLUE( - backgroundColor = Blue10, - contentColor = Blue100, - ), - ORANGE( - backgroundColor = Orange10, - contentColor = Orange100, - ), -} - -@Composable -private fun StatisticsLabel( - modifier: Modifier = Modifier, - color: LabelColor, - name: String, - value: String, -) { - with(color) { - Box( - modifier = modifier - .clip(RoundedCornerShape(5.dp)) - .background(color = backgroundColor) - .wrapContentHeight() - .padding(vertical = 4.dp, horizontal = 6.dp), - ) { - Row( - modifier = Modifier.wrapContentWidth(), - ) { - Text( - text = name, - style = SuwikiTheme.typography.caption2, - color = contentColor, - ) - Spacer(modifier = Modifier.width(2.dp)) - Text( - text = value, - style = SuwikiTheme.typography.caption1, - color = contentColor, - ) - } - } - } -} - -@Preview -@Composable -fun SuwikiReviewStaticsContainerPreview() { - SuwikiTheme { - Column { - SuwikiReviewStatisticsContainer( - data = LectureEvaluationExtraAverage( - id = 0, - info = LectureInfo( - semesterList = listOf(), - professor = "교수", - majorType = "전공", - lectureType = "유형", - lectureName = "이름", - ), - totalAvg = 3.0f, - satisfactionAvg = 3.0f, - honeyAvg = 3.0f, - learningAvg = 3.0f, - teamAvg = TeamLevel.EXIST, - gradeAvg = GradeLevel.DIFFICULT, - homeworkAvg = HomeworkLevel.MANY, - ), - ) - SuwikiReviewStatisticsContainer( - data = LectureEvaluationExtraAverage( - id = 0, - info = LectureInfo( - semesterList = listOf(), - professor = "교수", - majorType = "전공", - lectureType = "유형", - lectureName = "이름", - ), - totalAvg = 0.0f, - satisfactionAvg = 0.0f, - honeyAvg = 0.0f, - learningAvg = 0.0f, - teamAvg = TeamLevel.EXIST, - gradeAvg = GradeLevel.DIFFICULT, - homeworkAvg = HomeworkLevel.MANY, - ), - ) - } - } -} diff --git a/presentation/lectureevaluation/src/main/res/drawable/ic_filter.xml b/presentation/lectureevaluation/src/main/res/drawable/ic_filter.xml deleted file mode 100644 index 2bbadb61b..000000000 --- a/presentation/lectureevaluation/src/main/res/drawable/ic_filter.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/presentation/lectureevaluation/src/main/res/drawable/ic_filter_arrow_down.xml b/presentation/lectureevaluation/src/main/res/drawable/ic_filter_arrow_down.xml deleted file mode 100644 index ff8a84a70..000000000 --- a/presentation/lectureevaluation/src/main/res/drawable/ic_filter_arrow_down.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/presentation/lectureevaluation/src/main/res/drawable/ic_onboarding1.png b/presentation/lectureevaluation/src/main/res/drawable/ic_onboarding1.png deleted file mode 100644 index b35a6a779..000000000 Binary files a/presentation/lectureevaluation/src/main/res/drawable/ic_onboarding1.png and /dev/null differ diff --git a/presentation/lectureevaluation/src/main/res/drawable/ic_onboarding2.png b/presentation/lectureevaluation/src/main/res/drawable/ic_onboarding2.png deleted file mode 100644 index 8fe8800c7..000000000 Binary files a/presentation/lectureevaluation/src/main/res/drawable/ic_onboarding2.png and /dev/null differ diff --git a/presentation/lectureevaluation/src/main/res/drawable/ic_write.xml b/presentation/lectureevaluation/src/main/res/drawable/ic_write.xml deleted file mode 100644 index 950aa35c6..000000000 --- a/presentation/lectureevaluation/src/main/res/drawable/ic_write.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/presentation/lectureevaluation/src/main/res/values/strings.xml b/presentation/lectureevaluation/src/main/res/values/strings.xml deleted file mode 100644 index f57306157..000000000 --- a/presentation/lectureevaluation/src/main/res/values/strings.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - 강의평가를 입력해주세요. - 강의평가가 수정되었습니다. - 강의평가가 삭제되었습니다. - 시험정보를 입력해주세요. - 시험정보가 수정되었습니다. - 시험정보가 삭제되었습니다. - 30자 이상 작성해주세요 - 수강학기를 선택해주세요 - 시험종류을 선택해주세요 - 30포인트가 차감됩니다. - 작성한 평가를 정말로 삭제하시겠습니까?\n현재 보유 포인트 : %dp - 포인트가 부족합니다. - 현재 보유 포인트 : %dp - 등록된 평가가 없어요 - 로고 - 가입하기 - 수원대 학생이라면\n수위키로 한 번에 해결! - 재학생들의 솔직한 강의평가 확인하기 - 나만의 시간표로 손쉬운 일정관리 - - 등록된 평가가 없어요 - 시험 정보 열람 -20p - 작성하기 - 이미 작성한 이력이 있어요 - diff --git a/presentation/login/.gitignore b/presentation/login/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/presentation/login/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/presentation/login/build.gradle.kts b/presentation/login/build.gradle.kts deleted file mode 100644 index 3a9c53ad7..000000000 --- a/presentation/login/build.gradle.kts +++ /dev/null @@ -1,13 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.presentation.compose) -} - -android { - namespace = "com.suwiki.presentation.login" -} - -dependencies { - implementation(projects.domain.login) - implementation(projects.domain.user) -} diff --git a/presentation/login/consumer-rules.pro b/presentation/login/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/presentation/login/proguard-rules.pro b/presentation/login/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/presentation/login/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/presentation/login/src/main/AndroidManifest.xml b/presentation/login/src/main/AndroidManifest.xml deleted file mode 100644 index 8bdb7e14b..000000000 --- a/presentation/login/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/presentation/login/src/main/java/com/suwiki/presentation/login/findid/FindIdContract.kt b/presentation/login/src/main/java/com/suwiki/presentation/login/findid/FindIdContract.kt deleted file mode 100644 index 506285d9a..000000000 --- a/presentation/login/src/main/java/com/suwiki/presentation/login/findid/FindIdContract.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.suwiki.presentation.login.findid - -import com.suwiki.presentation.login.R - -data class FindIdState( - val email: String = "", - val showFindIdButton: Boolean = false, - val showFindIdSuccessDialog: Boolean = false, - private val showEmailNoticeHelperText: Boolean = true, - private val showEmailInvalidHelperText: Boolean = false, - val isLoading: Boolean = false, -) { - val emailHelperTextResId = when { - showEmailNoticeHelperText -> R.string.textfield_email_notice_text - showEmailInvalidHelperText -> R.string.textfield_email_invalid_text - else -> R.string.word_empty - } - - val isErrorEmailTextField = showEmailInvalidHelperText -} - -sealed interface FindIdSideEffect { - data class HandleException(val throwable: Throwable) : FindIdSideEffect - data object PopBackStack : FindIdSideEffect -} diff --git a/presentation/login/src/main/java/com/suwiki/presentation/login/findid/FindIdScreen.kt b/presentation/login/src/main/java/com/suwiki/presentation/login/findid/FindIdScreen.kt deleted file mode 100644 index a7382222a..000000000 --- a/presentation/login/src/main/java/com/suwiki/presentation/login/findid/FindIdScreen.kt +++ /dev/null @@ -1,154 +0,0 @@ -package com.suwiki.presentation.login.findid - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.snapshotFlow -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.presentation.common.designsystem.component.appbar.SuwikiAppBarWithTitle -import com.suwiki.presentation.common.designsystem.component.button.SuwikiContainedLargeButton -import com.suwiki.presentation.common.designsystem.component.dialog.SuwikiDialog -import com.suwiki.presentation.common.designsystem.component.loading.LoadingScreen -import com.suwiki.presentation.common.designsystem.component.textfield.SuwikiRegularTextField -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.common.ui.util.LaunchedEffectWithLifecycle -import com.suwiki.presentation.common.ui.util.TEXT_FIELD_DEBOUNCE -import com.suwiki.presentation.login.R -import kotlinx.coroutines.FlowPreview -import kotlinx.coroutines.flow.debounce -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect - -@OptIn(FlowPreview::class) -@Composable -fun FindIdRoute( - viewModel: FindIdViewModel = hiltViewModel(), - popBackStack: () -> Unit, - handleException: (Throwable) -> Unit, -) { - val uiState = viewModel.collectAsState().value - - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - is FindIdSideEffect.HandleException -> handleException(sideEffect.throwable) - FindIdSideEffect.PopBackStack -> popBackStack() - } - } - - LaunchedEffectWithLifecycle(key1 = uiState.email) { - snapshotFlow { uiState.email } - .debounce(TEXT_FIELD_DEBOUNCE) - .onEach(viewModel::checkEmailInvalid) - .launchIn(this) - } - - FindIdScreen( - uiState = uiState, - onClickBack = viewModel::popBackStack, - onValueChangeEmail = viewModel::updateEmail, - onClickEmailTextFieldClearButton = { viewModel.updateEmail("") }, - onClickFindIdButton = viewModel::findId, - onClickFindIdSuccessDialogConfirmButton = { - viewModel.hideSuccessDialog() - viewModel.popBackStack() - }, - onDismissRequestFindIdSuccessDialog = viewModel::hideSuccessDialog, - ) -} - -@Composable -fun FindIdScreen( - uiState: FindIdState = FindIdState(), - onClickBack: () -> Unit = {}, - onValueChangeEmail: (String) -> Unit = {}, - onClickEmailTextFieldClearButton: () -> Unit = {}, - onClickFindIdButton: () -> Unit = {}, - onClickFindIdSuccessDialogConfirmButton: () -> Unit = {}, - onDismissRequestFindIdSuccessDialog: () -> Unit = {}, -) { - Box( - modifier = Modifier - .fillMaxSize() - .background(White), - ) { - Column { - SuwikiAppBarWithTitle( - showCloseIcon = false, - onClickBack = onClickBack, - ) - Column( - modifier = Modifier - .fillMaxSize() - .padding( - top = 13.dp, - start = 24.dp, - end = 24.dp, - bottom = 20.dp, - ), - ) { - Text( - text = stringResource(id = R.string.word_find_id), - style = SuwikiTheme.typography.header1, - ) - - Spacer(modifier = Modifier.size(26.dp)) - - SuwikiRegularTextField( - label = stringResource(R.string.word_email), - placeholder = stringResource(R.string.textfield_email_placeholder), - value = uiState.email, - onValueChange = onValueChangeEmail, - onClickClearButton = onClickEmailTextFieldClearButton, - helperText = stringResource(id = uiState.emailHelperTextResId), - isError = uiState.isErrorEmailTextField, - ) - - Spacer(modifier = Modifier.weight(1f)) - - if (uiState.showFindIdButton) { - SuwikiContainedLargeButton( - modifier = Modifier.imePadding(), - text = stringResource(R.string.word_find_id), - onClick = onClickFindIdButton, - ) - } - } - } - - if (uiState.showFindIdSuccessDialog) { - SuwikiDialog( - headerText = stringResource(R.string.find_id_screen_dialog_success_title), - bodyText = stringResource(R.string.find_id_screen_dialog_success_body), - confirmButtonText = stringResource(R.string.word_confirm), - onDismissRequest = onDismissRequestFindIdSuccessDialog, - onClickConfirm = onClickFindIdSuccessDialogConfirmButton, - ) - } - - if (uiState.isLoading) { - LoadingScreen() - } - } -} - -@Preview(showBackground = true) -@Composable -fun FindIdScreenPreview() { - SuwikiTheme { - FindIdScreen() - } -} diff --git a/presentation/login/src/main/java/com/suwiki/presentation/login/findid/FindIdViewModel.kt b/presentation/login/src/main/java/com/suwiki/presentation/login/findid/FindIdViewModel.kt deleted file mode 100644 index 6565585c1..000000000 --- a/presentation/login/src/main/java/com/suwiki/presentation/login/findid/FindIdViewModel.kt +++ /dev/null @@ -1,77 +0,0 @@ -package com.suwiki.presentation.login.findid - -import androidx.lifecycle.ViewModel -import com.suwiki.domain.login.usecase.FindIdUseCase -import com.suwiki.presentation.common.ui.util.REGEX -import dagger.hilt.android.lifecycle.HiltViewModel -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.annotation.OrbitExperimental -import org.orbitmvi.orbit.syntax.simple.blockingIntent -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class FindIdViewModel @Inject constructor( - private val findIdUseCase: FindIdUseCase, -) : ContainerHost, ViewModel() { - override val container: Container = container(FindIdState()) - - @OptIn(OrbitExperimental::class) - fun updateEmail(email: String) = blockingIntent { - reduce { - state.copy( - email = email, - showFindIdButton = false, - showEmailNoticeHelperText = true, - showEmailInvalidHelperText = false, - ) - } - } - - fun checkEmailInvalid(email: String) { - when { - email.isEmpty() -> Unit - email.matches(REGEX.EMAIL) -> showFindIdButton() - else -> showEmailInvalidHelperText() - } - } - - private fun showFindIdButton() = intent { - reduce { - state.copy( - showFindIdButton = true, - showEmailNoticeHelperText = false, - showEmailInvalidHelperText = false, - ) - } - } - - private fun showEmailInvalidHelperText() = intent { - reduce { - state.copy( - showFindIdButton = false, - showEmailNoticeHelperText = false, - showEmailInvalidHelperText = true, - ) - } - } - - fun popBackStack() = intent { postSideEffect(FindIdSideEffect.PopBackStack) } - fun findId() = intent { - reduce { state.copy(isLoading = true) } - findIdUseCase(email = state.email) - .onSuccess { - reduce { state.copy(showFindIdSuccessDialog = true) } - } - .onFailure { - postSideEffect(FindIdSideEffect.HandleException(it)) - } - reduce { state.copy(isLoading = false) } - } - - fun hideSuccessDialog() = intent { reduce { state.copy(showFindIdSuccessDialog = false) } } -} diff --git a/presentation/login/src/main/java/com/suwiki/presentation/login/findpassword/FindPasswordContract.kt b/presentation/login/src/main/java/com/suwiki/presentation/login/findpassword/FindPasswordContract.kt deleted file mode 100644 index 69418a1c2..000000000 --- a/presentation/login/src/main/java/com/suwiki/presentation/login/findpassword/FindPasswordContract.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.suwiki.presentation.login.findpassword - -import com.suwiki.presentation.login.R - -data class FindPasswordState( - val email: String = "", - val showFindPasswordButton: Boolean = false, - val showFindPasswordSuccessDialog: Boolean = false, - private val showEmailNoticeHelperText: Boolean = true, - private val showEmailInvalidHelperText: Boolean = false, - val id: String = "", - private val showIdOverlapHelperText: Boolean = false, - private val showIdInvalidHelperText: Boolean = false, - val isLoading: Boolean = false, -) { - val emailHelperTextResId = when { - showEmailNoticeHelperText -> R.string.textfield_email_notice_text - showEmailInvalidHelperText -> R.string.textfield_email_invalid_text - else -> R.string.word_empty - } - - val isErrorEmailTextField = showEmailInvalidHelperText - - val idHelperTextResId = when { - showIdInvalidHelperText -> R.string.textfield_id_invalid_helper_text - showIdOverlapHelperText -> R.string.textfield_id_overlap_helper_text - else -> R.string.word_empty - } - - val isErrorIdTextField = showIdInvalidHelperText || showIdOverlapHelperText -} - -sealed interface FindPasswordSideEffect { - data class HandleException(val throwable: Throwable) : FindPasswordSideEffect - data object PopBackStack : FindPasswordSideEffect -} diff --git a/presentation/login/src/main/java/com/suwiki/presentation/login/findpassword/FindPasswordScreen.kt b/presentation/login/src/main/java/com/suwiki/presentation/login/findpassword/FindPasswordScreen.kt deleted file mode 100644 index 03ad307fe..000000000 --- a/presentation/login/src/main/java/com/suwiki/presentation/login/findpassword/FindPasswordScreen.kt +++ /dev/null @@ -1,177 +0,0 @@ -package com.suwiki.presentation.login.findpassword - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.snapshotFlow -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.presentation.common.designsystem.component.appbar.SuwikiAppBarWithTitle -import com.suwiki.presentation.common.designsystem.component.button.SuwikiContainedLargeButton -import com.suwiki.presentation.common.designsystem.component.dialog.SuwikiDialog -import com.suwiki.presentation.common.designsystem.component.loading.LoadingScreen -import com.suwiki.presentation.common.designsystem.component.textfield.SuwikiRegularTextField -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.common.ui.util.LaunchedEffectWithLifecycle -import com.suwiki.presentation.common.ui.util.TEXT_FIELD_DEBOUNCE -import com.suwiki.presentation.login.R -import kotlinx.coroutines.FlowPreview -import kotlinx.coroutines.flow.debounce -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect - -@OptIn(FlowPreview::class) -@Composable -fun FindPasswordRoute( - viewModel: FindPasswordViewModel = hiltViewModel(), - popBackStack: () -> Unit, - handleException: (Throwable) -> Unit, -) { - val uiState = viewModel.collectAsState().value - - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - is FindPasswordSideEffect.HandleException -> handleException(sideEffect.throwable) - FindPasswordSideEffect.PopBackStack -> popBackStack() - } - } - - LaunchedEffectWithLifecycle(key1 = uiState.id) { - snapshotFlow { uiState.id } - .debounce(TEXT_FIELD_DEBOUNCE) - .onEach(viewModel::checkIdInvalid) - .launchIn(this) - } - - LaunchedEffectWithLifecycle(key1 = uiState.email) { - snapshotFlow { uiState.email } - .debounce(TEXT_FIELD_DEBOUNCE) - .onEach(viewModel::checkEmailInvalid) - .launchIn(this) - } - - FindPasswordScreen( - uiState = uiState, - onClickBack = viewModel::popBackStack, - onValueChangeEmail = viewModel::updateEmail, - onClickEmailTextFieldClearButton = { viewModel.updateEmail("") }, - onValueChangeId = viewModel::updateId, - onClickIdTextFieldClearButton = { viewModel.updateId("") }, - onClickFindPasswordButton = viewModel::findPassword, - onClickFindPasswordSuccessDialogConfirmButton = { - viewModel.hideSuccessDialog() - viewModel.popBackStack() - }, - onDismissRequestFindPasswordSuccessDialog = viewModel::hideSuccessDialog, - ) -} - -@Composable -fun FindPasswordScreen( - uiState: FindPasswordState = FindPasswordState(), - onClickBack: () -> Unit = {}, - onValueChangeEmail: (String) -> Unit = {}, - onClickEmailTextFieldClearButton: () -> Unit = {}, - onValueChangeId: (String) -> Unit = {}, - onClickIdTextFieldClearButton: () -> Unit = {}, - onClickFindPasswordButton: () -> Unit = {}, - onClickFindPasswordSuccessDialogConfirmButton: () -> Unit = {}, - onDismissRequestFindPasswordSuccessDialog: () -> Unit = {}, -) { - Box( - modifier = Modifier - .fillMaxSize() - .background(White), - ) { - Column { - SuwikiAppBarWithTitle( - showCloseIcon = false, - onClickBack = onClickBack, - ) - Column( - modifier = Modifier - .fillMaxSize() - .padding( - top = 13.dp, - start = 24.dp, - end = 24.dp, - bottom = 20.dp, - ), - ) { - Text( - text = stringResource(id = R.string.word_find_password), - style = SuwikiTheme.typography.header1, - ) - - Spacer(modifier = Modifier.size(26.dp)) - - SuwikiRegularTextField( - label = stringResource(R.string.word_id), - placeholder = stringResource(R.string.textfield_id_placeholder), - value = uiState.id, - onValueChange = onValueChangeId, - onClickClearButton = onClickIdTextFieldClearButton, - helperText = stringResource(id = uiState.idHelperTextResId), - isError = uiState.isErrorIdTextField, - ) - - Spacer(modifier = Modifier.size(4.dp)) - - SuwikiRegularTextField( - label = stringResource(R.string.word_email), - placeholder = stringResource(R.string.textfield_email_placeholder), - value = uiState.email, - onValueChange = onValueChangeEmail, - onClickClearButton = onClickEmailTextFieldClearButton, - helperText = stringResource(id = uiState.emailHelperTextResId), - isError = uiState.isErrorEmailTextField, - ) - - Spacer(modifier = Modifier.weight(1f)) - - if (uiState.showFindPasswordButton) { - SuwikiContainedLargeButton( - modifier = Modifier.imePadding(), - text = stringResource(R.string.word_find_password), - onClick = onClickFindPasswordButton, - ) - } - } - } - - if (uiState.showFindPasswordSuccessDialog) { - SuwikiDialog( - headerText = stringResource(R.string.find_password_screen_dialog_success_title), - bodyText = stringResource(R.string.find_password_screen_dialog_success_body), - confirmButtonText = stringResource(R.string.word_confirm), - onDismissRequest = onDismissRequestFindPasswordSuccessDialog, - onClickConfirm = onClickFindPasswordSuccessDialogConfirmButton, - ) - } - - if (uiState.isLoading) { - LoadingScreen() - } - } -} - -@Preview(showBackground = true) -@Composable -fun FindPasswordScreenPreview() { - SuwikiTheme { - FindPasswordScreen() - } -} diff --git a/presentation/login/src/main/java/com/suwiki/presentation/login/findpassword/FindPasswordViewModel.kt b/presentation/login/src/main/java/com/suwiki/presentation/login/findpassword/FindPasswordViewModel.kt deleted file mode 100644 index 6ddce4e76..000000000 --- a/presentation/login/src/main/java/com/suwiki/presentation/login/findpassword/FindPasswordViewModel.kt +++ /dev/null @@ -1,133 +0,0 @@ -package com.suwiki.presentation.login.findpassword - -import androidx.lifecycle.ViewModel -import com.suwiki.domain.login.usecase.FindPasswordUseCase -import com.suwiki.presentation.common.ui.util.REGEX -import dagger.hilt.android.lifecycle.HiltViewModel -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.annotation.OrbitExperimental -import org.orbitmvi.orbit.syntax.simple.blockingIntent -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class FindPasswordViewModel @Inject constructor( - private val findPasswordUseCase: FindPasswordUseCase, -) : ContainerHost, ViewModel() { - override val container: Container = container(FindPasswordState()) - - private var isEmailValid: Boolean = false - private var isIdValid: Boolean = false - - @OptIn(OrbitExperimental::class) - fun updateId(id: String) = blockingIntent { - reduce { - isIdValid = false - state.copy( - id = id, - showIdInvalidHelperText = false, - showIdOverlapHelperText = false, - showFindPasswordButton = false, - ) - } - } - - fun checkIdInvalid(id: String) { - when { - id.isEmpty() -> Unit - id.matches(REGEX.ID) && isEmailValid -> showFindPasswordEmailButton() - id.matches(REGEX.ID) -> hideIdInvalidHelperText() - else -> showIdInvalidHelperText() - } - } - - private fun hideIdInvalidHelperText() = intent { - reduce { - isIdValid = true - state.copy( - showIdInvalidHelperText = false, - ) - } - } - - private fun showIdInvalidHelperText() = intent { - reduce { - state.copy( - showIdInvalidHelperText = true, - ) - } - } - - @OptIn(OrbitExperimental::class) - fun updateEmail(email: String) = blockingIntent { - reduce { - state.copy( - email = email, - showFindPasswordButton = false, - showEmailNoticeHelperText = true, - showEmailInvalidHelperText = false, - ) - } - } - - fun checkEmailInvalid(email: String) { - when { - email.isEmpty() -> Unit - email.matches(REGEX.EMAIL) && isIdValid -> showFindPasswordEmailButton() - email.matches(REGEX.EMAIL) -> hideEmailInvalidHelperText() - else -> showEmailInvalidHelperText() - } - } - - private fun showFindPasswordEmailButton() = intent { - reduce { - isIdValid = true - isEmailValid = true - state.copy( - showFindPasswordButton = true, - showEmailNoticeHelperText = false, - showEmailInvalidHelperText = false, - ) - } - } - - private fun hideEmailInvalidHelperText() = intent { - reduce { - isEmailValid = true - state.copy( - showFindPasswordButton = false, - showEmailNoticeHelperText = false, - showEmailInvalidHelperText = false, - ) - } - } - - private fun showEmailInvalidHelperText() = intent { - reduce { - state.copy( - showFindPasswordButton = false, - showEmailNoticeHelperText = false, - showEmailInvalidHelperText = true, - ) - } - } - - fun popBackStack() = intent { postSideEffect(FindPasswordSideEffect.PopBackStack) } - fun findPassword() = intent { - reduce { state.copy(isLoading = true) } - findPasswordUseCase(loginId = state.id, email = state.email) - .onSuccess { - reduce { state.copy(showFindPasswordSuccessDialog = true) } - } - .onFailure { - postSideEffect(FindPasswordSideEffect.HandleException(it)) - } - reduce { state.copy(isLoading = false) } - } - - fun hideSuccessDialog() = intent { reduce { state.copy(showFindPasswordSuccessDialog = false) } } -} diff --git a/presentation/login/src/main/java/com/suwiki/presentation/login/login/LoginContract.kt b/presentation/login/src/main/java/com/suwiki/presentation/login/login/LoginContract.kt deleted file mode 100644 index dab424e03..000000000 --- a/presentation/login/src/main/java/com/suwiki/presentation/login/login/LoginContract.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.suwiki.presentation.login.login - -data class LoginState( - val showEmailNotAuthDialog: Boolean = false, - val showLoginFailDialog: Boolean = false, - val id: String = "", - val password: String = "", - val showPassword: Boolean = false, - val isLoading: Boolean = false, - val showAgreementBottomSheet: Boolean = false, - val isCheckedTerm: Boolean = false, - val isCheckedPersonalPolicy: Boolean = false, -) { - val loginButtonEnable = id.isNotBlank() && password.isNotBlank() - val isEnabledAgreementButton: Boolean = isCheckedTerm && isCheckedPersonalPolicy -} - -sealed interface LoginSideEffect { - data class HandleException(val throwable: Throwable) : LoginSideEffect - data object PopBackStack : LoginSideEffect - data object NavigateFindId : LoginSideEffect - data object NavigateFindPassword : LoginSideEffect - data object NavigateSignUp : LoginSideEffect - data object OpenTermWebSite : LoginSideEffect - data object OpenPersonalPolicyWebSite : LoginSideEffect -} diff --git a/presentation/login/src/main/java/com/suwiki/presentation/login/login/LoginScreen.kt b/presentation/login/src/main/java/com/suwiki/presentation/login/login/LoginScreen.kt deleted file mode 100644 index 3fe1a388e..000000000 --- a/presentation/login/src/main/java/com/suwiki/presentation/login/login/LoginScreen.kt +++ /dev/null @@ -1,237 +0,0 @@ -package com.suwiki.presentation.login.login - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.IntrinsicSize -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Text -import androidx.compose.material3.VerticalDivider -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.presentation.common.designsystem.component.bottomsheet.SuwikiAgreementBottomSheet -import com.suwiki.presentation.common.designsystem.component.button.SuwikiContainedLargeButton -import com.suwiki.presentation.common.designsystem.component.dialog.SuwikiDialog -import com.suwiki.presentation.common.designsystem.component.loading.LoadingScreen -import com.suwiki.presentation.common.designsystem.component.textfield.SuwikiRegularTextField -import com.suwiki.presentation.common.designsystem.theme.Gray6A -import com.suwiki.presentation.common.designsystem.theme.GrayF6 -import com.suwiki.presentation.common.designsystem.theme.Primary -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.ui.extension.suwikiClickable -import com.suwiki.presentation.common.ui.util.PRIVACY_POLICY_SITE -import com.suwiki.presentation.common.ui.util.TERMS_SITE -import com.suwiki.presentation.login.R -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect - -@Composable -fun LoginRoute( - viewModel: LoginViewModel = hiltViewModel(), - popBackStack: () -> Unit, - navigateFindId: () -> Unit, - navigateFindPassword: () -> Unit, - navigateSignup: () -> Unit, - handleException: (Throwable) -> Unit, -) { - val uiState = viewModel.collectAsState().value - val uriHandler = LocalUriHandler.current - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - is LoginSideEffect.HandleException -> handleException(sideEffect.throwable) - LoginSideEffect.NavigateFindId -> navigateFindId() - LoginSideEffect.NavigateFindPassword -> navigateFindPassword() - LoginSideEffect.NavigateSignUp -> navigateSignup() - LoginSideEffect.PopBackStack -> popBackStack() - LoginSideEffect.OpenPersonalPolicyWebSite -> uriHandler.openUri(PRIVACY_POLICY_SITE) - LoginSideEffect.OpenTermWebSite -> uriHandler.openUri(TERMS_SITE) - } - } - - LoginScreen( - uiState = uiState, - onValueChangeIdTextField = viewModel::updateId, - onValueChangePasswordTextField = viewModel::updatePassword, - onClickIdClearButton = { viewModel.updateId("") }, - onClickPasswordClearButton = { viewModel.updatePassword("") }, - onClickPasswordEyeIcon = viewModel::toggleShowPassword, - onClickFindIdText = viewModel::navigateFindId, - onClickFindPasswordText = viewModel::navigateFindPassword, - onClickSignupText = viewModel::showAgreementBottomSheet, - onClickLoginButton = viewModel::login, - onClickLoginFailDialogButton = viewModel::hideLoginFailDialog, - onClickEmailNotAuthDialogButton = viewModel::hideEmailNotAuthDialog, - onClickTermCheckIcon = viewModel::toggleTermChecked, - onClickTermArrowIcon = viewModel::openTermWebSite, - onClickPersonalCheckIcon = viewModel::togglePersonalPolicyChecked, - onClickPersonalArrowIcon = viewModel::openPersonalPolicyWebSite, - onClickAgreementButton = { - viewModel.hideAgreementBottomSheet() - viewModel.navigateSignup() - }, - hideAgreementBottomSheet = viewModel::hideAgreementBottomSheet, - ) -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun LoginScreen( - uiState: LoginState = LoginState(), - onValueChangeIdTextField: (String) -> Unit = {}, - onValueChangePasswordTextField: (String) -> Unit = {}, - onClickIdClearButton: () -> Unit = {}, - onClickPasswordClearButton: () -> Unit = {}, - onClickPasswordEyeIcon: () -> Unit = {}, - onClickFindIdText: () -> Unit = {}, - onClickFindPasswordText: () -> Unit = {}, - onClickSignupText: () -> Unit = {}, - onClickLoginButton: () -> Unit = {}, - onClickLoginFailDialogButton: () -> Unit = {}, - onClickEmailNotAuthDialogButton: () -> Unit = {}, - hideAgreementBottomSheet: () -> Unit = {}, - onClickTermCheckIcon: () -> Unit = {}, - onClickTermArrowIcon: () -> Unit = {}, - onClickPersonalCheckIcon: () -> Unit = {}, - onClickPersonalArrowIcon: () -> Unit = {}, - onClickAgreementButton: () -> Unit = {}, -) { - Box( - modifier = Modifier - .fillMaxSize() - .padding(top = 63.dp, bottom = 30.dp, start = 24.dp, end = 24.dp), - ) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Text(text = stringResource(com.suwiki.presentation.common.ui.R.string.word_login), style = SuwikiTheme.typography.header1) - - Spacer(modifier = Modifier.size(26.dp)) - - SuwikiRegularTextField( - value = uiState.id, - onValueChange = onValueChangeIdTextField, - onClickClearButton = onClickIdClearButton, - label = stringResource(com.suwiki.presentation.common.ui.R.string.word_id), - placeholder = stringResource(R.string.login_screen_id_textfield_placeholder), - ) - - Spacer(modifier = Modifier.size(20.dp)) - - SuwikiRegularTextField( - value = uiState.password, - onValueChange = onValueChangePasswordTextField, - onClickClearButton = onClickPasswordClearButton, - showEyeIcon = true, - showValue = uiState.showPassword, - onClickEyeIcon = onClickPasswordEyeIcon, - label = stringResource(com.suwiki.presentation.common.ui.R.string.word_password), - placeholder = stringResource(R.string.login_screen_password_textfield_placeholder), - ) - - Spacer(modifier = Modifier.weight(1f)) - - Row( - modifier = Modifier.height(IntrinsicSize.Min), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp), - ) { - Text( - modifier = Modifier.suwikiClickable(onClick = onClickFindIdText), - text = stringResource(com.suwiki.presentation.common.ui.R.string.word_find_id), - style = SuwikiTheme.typography.body5, - color = Gray6A, - ) - VerticalDivider( - modifier = Modifier.padding(vertical = 4.5.dp), - thickness = 1.dp, - color = GrayF6, - ) - Text( - modifier = Modifier.suwikiClickable(onClick = onClickFindPasswordText), - text = stringResource(com.suwiki.presentation.common.ui.R.string.word_find_password), - style = SuwikiTheme.typography.body5, - color = Gray6A, - ) - VerticalDivider( - modifier = Modifier.padding(vertical = 4.5.dp), - thickness = 1.dp, - color = GrayF6, - ) - Text( - modifier = Modifier.suwikiClickable(onClick = onClickSignupText), - text = stringResource(com.suwiki.presentation.common.ui.R.string.word_signup), - style = SuwikiTheme.typography.body4, - color = Primary, - ) - } - - Spacer(modifier = Modifier.size(20.dp)) - - SuwikiContainedLargeButton( - modifier = Modifier.imePadding(), - clickable = uiState.loginButtonEnable, - enabled = uiState.loginButtonEnable, - text = stringResource(com.suwiki.presentation.common.ui.R.string.word_login), - onClick = onClickLoginButton, - ) - } - - if (uiState.showLoginFailDialog) { - SuwikiDialog( - headerText = stringResource(R.string.login_screen_dialog_login_fail_title), - bodyText = stringResource(R.string.login_screen_dialog_login_fail_body), - confirmButtonText = stringResource(com.suwiki.presentation.common.ui.R.string.word_confirm), - onDismissRequest = onClickLoginFailDialogButton, - onClickConfirm = onClickLoginFailDialogButton, - ) - } - - if (uiState.showEmailNotAuthDialog) { - SuwikiDialog( - headerText = stringResource(R.string.login_screen_dialog_email_not_auth_title), - bodyText = stringResource(R.string.login_screen_dialog_email_not_auth_body), - confirmButtonText = stringResource(com.suwiki.presentation.common.ui.R.string.word_confirm), - onDismissRequest = onClickEmailNotAuthDialogButton, - onClickConfirm = onClickEmailNotAuthDialogButton, - ) - } - - if (uiState.isLoading) { - LoadingScreen() - } - - SuwikiAgreementBottomSheet( - isSheetOpen = uiState.showAgreementBottomSheet, - buttonEnabled = uiState.isEnabledAgreementButton, - isCheckedTerm = uiState.isCheckedTerm, - onClickTermCheckIcon = onClickTermCheckIcon, - onClickTermArrowIcon = onClickTermArrowIcon, - isCheckedPersonalPolicy = uiState.isCheckedPersonalPolicy, - onClickPersonalCheckIcon = onClickPersonalCheckIcon, - onClickPersonalArrowIcon = onClickPersonalArrowIcon, - onClickAgreementButton = onClickAgreementButton, - onDismissRequest = hideAgreementBottomSheet, - ) - } -} - -@Preview(showBackground = true) -@Composable -fun LoginScreenPreview() { - SuwikiTheme { - LoginScreen() - } -} diff --git a/presentation/login/src/main/java/com/suwiki/presentation/login/login/LoginViewModel.kt b/presentation/login/src/main/java/com/suwiki/presentation/login/login/LoginViewModel.kt deleted file mode 100644 index 35fb27678..000000000 --- a/presentation/login/src/main/java/com/suwiki/presentation/login/login/LoginViewModel.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.suwiki.presentation.login.login - -import androidx.lifecycle.ViewModel -import com.suwiki.common.model.exception.EmailNotAuthedException -import com.suwiki.common.model.exception.LoginFailedException -import com.suwiki.common.model.exception.PasswordErrorException -import com.suwiki.domain.login.usecase.LoginUseCase -import dagger.hilt.android.lifecycle.HiltViewModel -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.annotation.OrbitExperimental -import org.orbitmvi.orbit.syntax.simple.blockingIntent -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class LoginViewModel @Inject constructor( - private val loginUseCase: LoginUseCase, -) : ContainerHost, ViewModel() { - override val container: Container = container(LoginState()) - - fun login() = intent { - reduce { state.copy(isLoading = true) } - loginUseCase(loginId = state.id, password = state.password) - .onSuccess { - postSideEffect(LoginSideEffect.PopBackStack) - } - .onFailure { - when (it) { - is LoginFailedException -> reduce { state.copy(showLoginFailDialog = true) } - is PasswordErrorException -> reduce { state.copy(showLoginFailDialog = true) } - is EmailNotAuthedException -> reduce { state.copy(showEmailNotAuthDialog = true) } - else -> postSideEffect(LoginSideEffect.HandleException(it)) - } - } - - reduce { state.copy(isLoading = false) } - } - - fun navigateFindId() = intent { postSideEffect(LoginSideEffect.NavigateFindId) } - fun navigateFindPassword() = intent { postSideEffect(LoginSideEffect.NavigateFindPassword) } - fun navigateSignup() = intent { postSideEffect(LoginSideEffect.NavigateSignUp) } - - fun toggleShowPassword() = intent { reduce { state.copy(showPassword = !state.showPassword) } } - - fun hideLoginFailDialog() = intent { reduce { state.copy(showLoginFailDialog = false) } } - - fun hideEmailNotAuthDialog() = intent { reduce { state.copy(showEmailNotAuthDialog = false) } } - - @OptIn(OrbitExperimental::class) - fun updateId(id: String) = blockingIntent { reduce { state.copy(id = id) } } - - @OptIn(OrbitExperimental::class) - fun updatePassword(password: String) = blockingIntent { reduce { state.copy(password = password) } } - - fun showAgreementBottomSheet() = intent { reduce { state.copy(showAgreementBottomSheet = true) } } - fun hideAgreementBottomSheet() = intent { reduce { state.copy(showAgreementBottomSheet = false) } } - - fun toggleTermChecked() = intent { reduce { state.copy(isCheckedTerm = !state.isCheckedTerm) } } - fun togglePersonalPolicyChecked() = intent { reduce { state.copy(isCheckedPersonalPolicy = !state.isCheckedPersonalPolicy) } } - - fun openTermWebSite() = intent { postSideEffect(LoginSideEffect.OpenTermWebSite) } - fun openPersonalPolicyWebSite() = intent { postSideEffect(LoginSideEffect.OpenPersonalPolicyWebSite) } -} diff --git a/presentation/login/src/main/java/com/suwiki/presentation/login/navigation/LoginNavigation.kt b/presentation/login/src/main/java/com/suwiki/presentation/login/navigation/LoginNavigation.kt deleted file mode 100644 index c50178ddb..000000000 --- a/presentation/login/src/main/java/com/suwiki/presentation/login/navigation/LoginNavigation.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.suwiki.presentation.login.navigation - -import androidx.navigation.NavController -import androidx.navigation.NavGraphBuilder -import androidx.navigation.NavOptions -import androidx.navigation.compose.composable -import com.suwiki.presentation.login.findid.FindIdRoute -import com.suwiki.presentation.login.findpassword.FindPasswordRoute -import com.suwiki.presentation.login.login.LoginRoute - -fun NavController.navigateLogin(navOptions: NavOptions? = null) { - navigate( - route = LoginRoute.route, - navOptions = navOptions, - ) -} - -fun NavController.navigateFindId() { - navigate(LoginRoute.findIdRoute) -} - -fun NavController.navigateFindPassword() { - navigate(LoginRoute.findPasswordRoute) -} - -fun NavGraphBuilder.loginNavGraph( - popBackStack: () -> Unit, - navigateFindId: () -> Unit, - navigateFindPassword: () -> Unit, - navigateSignup: () -> Unit, - handleException: (Throwable) -> Unit, -) { - composable(route = LoginRoute.route) { - LoginRoute( - popBackStack = popBackStack, - navigateFindId = navigateFindId, - navigateFindPassword = navigateFindPassword, - navigateSignup = navigateSignup, - handleException = handleException, - ) - } - - composable(route = LoginRoute.findIdRoute) { - FindIdRoute( - popBackStack = popBackStack, - handleException = handleException, - ) - } - - composable(route = LoginRoute.findPasswordRoute) { - FindPasswordRoute( - popBackStack = popBackStack, - handleException = handleException, - ) - } -} - -object LoginRoute { - const val route = "login" - const val findIdRoute = "find-id" - const val findPasswordRoute = "find-password" -} diff --git a/presentation/login/src/main/res/values/strings.xml b/presentation/login/src/main/res/values/strings.xml deleted file mode 100644 index ca2e9d8f2..000000000 --- a/presentation/login/src/main/res/values/strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - 아이디를 입력하세요 - 비밀번호를 입력하세요 - 잘못된 아이디 혹은 비밀번호입니다. - 입력한 내용을 다시 확인해주세요. - 웹메일 인증 절차가 필요합니다. - 학교 웹메일 인증 진행 후 로그인 가능합니다. - 아이디가 발송되었습니다 - 이메일 수신함을 확인해주세요 - 임시 비밀번호가 발송되었습니다 - 이메일 수신함을 확인해주세요 - diff --git a/presentation/myinfo/.gitignore b/presentation/myinfo/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/presentation/myinfo/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/presentation/myinfo/build.gradle.kts b/presentation/myinfo/build.gradle.kts deleted file mode 100644 index 87e5e76c4..000000000 --- a/presentation/myinfo/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.presentation.compose) -} - -android { - namespace = "com.suwiki.presentation.myinfo" -} - -dependencies { - implementation(projects.domain.user) - implementation(projects.domain.lectureevaluation) - - implementation(libs.oss.licenses) -} diff --git a/presentation/myinfo/consumer-rules.pro b/presentation/myinfo/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/presentation/myinfo/proguard-rules.pro b/presentation/myinfo/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/presentation/myinfo/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/presentation/myinfo/src/main/AndroidManifest.xml b/presentation/myinfo/src/main/AndroidManifest.xml deleted file mode 100644 index 6bdfa19dd..000000000 --- a/presentation/myinfo/src/main/AndroidManifest.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/MyInfoContract.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/MyInfoContract.kt deleted file mode 100644 index f4239978d..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/MyInfoContract.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.suwiki.presentation.myinfo - -data class MyInfoState( - val showMyInfoCard: Boolean = false, - val isLoading: Boolean = false, - val loginId: String = "", - val point: Int = 0, -) - -sealed interface MyInfoSideEffect { - data object NavigateNotice : MyInfoSideEffect - data object NavigateLogin : MyInfoSideEffect - data object NavigateMyEvaluation : MyInfoSideEffect - data object NavigateMyAccount : MyInfoSideEffect - data object NavigateMyPoint : MyInfoSideEffect - data object NavigateBanHistory : MyInfoSideEffect - data object ShowNeedLoginToast : MyInfoSideEffect - data object ShowOpenLicenses : MyInfoSideEffect - data class HandleException(val throwable: Throwable) : MyInfoSideEffect - data object OpenPersonalPolicyWebSite : MyInfoSideEffect - data object OpenTermWebSite : MyInfoSideEffect - data object OpenAskWebSite : MyInfoSideEffect - data object OpenFeedbackWebSite : MyInfoSideEffect -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/MyInfoScreen.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/MyInfoScreen.kt deleted file mode 100644 index 3235e6e61..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/MyInfoScreen.kt +++ /dev/null @@ -1,426 +0,0 @@ -package com.suwiki.presentation.myinfo - -import android.content.Intent -import androidx.compose.foundation.Image -import androidx.compose.foundation.ScrollState -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.IntrinsicSize -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.Text -import androidx.compose.material3.VerticalDivider -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.google.android.gms.oss.licenses.OssLicensesMenuActivity -import com.suwiki.presentation.common.designsystem.component.bottomsheet.SuwikiMenuItem -import com.suwiki.presentation.common.designsystem.component.loading.LoadingScreen -import com.suwiki.presentation.common.designsystem.shadow.cardShadow -import com.suwiki.presentation.common.designsystem.theme.Black -import com.suwiki.presentation.common.designsystem.theme.Gray6A -import com.suwiki.presentation.common.designsystem.theme.Gray95 -import com.suwiki.presentation.common.designsystem.theme.GrayF6 -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.common.ui.extension.findActivity -import com.suwiki.presentation.common.ui.extension.suwikiClickable -import com.suwiki.presentation.common.ui.util.ASK_SITE -import com.suwiki.presentation.common.ui.util.FEEDBACK_SITE -import com.suwiki.presentation.common.ui.util.PRIVACY_POLICY_SITE -import com.suwiki.presentation.common.ui.util.TERMS_SITE -import okhttp3.internal.immutableListOf -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect - -data class MyInfoListItem( - val title: String, - val onClick: () -> Unit, -) - -@Composable -fun MyInfoRoute( - padding: PaddingValues, - viewModel: MyInfoViewModel = hiltViewModel(), - navigateNotice: () -> Unit, - navigateMyEvaluation: () -> Unit, - navigateMyAccount: () -> Unit, - navigateMyPoint: () -> Unit, - navigateBanHistory: () -> Unit, - navigateLogin: () -> Unit, - onShowToast: (String) -> Unit = {}, - handleException: (Throwable) -> Unit = {}, -) { - val scrollState = rememberScrollState() - val uiState = viewModel.collectAsState().value - - val uriHandler = LocalUriHandler.current - val context = LocalContext.current - - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - is MyInfoSideEffect.NavigateNotice -> navigateNotice() - is MyInfoSideEffect.NavigateMyEvaluation -> navigateMyEvaluation() - is MyInfoSideEffect.NavigateMyAccount -> navigateMyAccount() - is MyInfoSideEffect.NavigateMyPoint -> navigateMyPoint() - is MyInfoSideEffect.NavigateBanHistory -> navigateBanHistory() - MyInfoSideEffect.ShowNeedLoginToast -> onShowToast(context.getString(R.string.my_info_screen_need_login_toast)) - MyInfoSideEffect.ShowOpenLicenses -> context.startActivity( - Intent( - context.findActivity(), - OssLicensesMenuActivity::class.java, - ), - ) - - is MyInfoSideEffect.HandleException -> handleException(sideEffect.throwable) - MyInfoSideEffect.OpenPersonalPolicyWebSite -> uriHandler.openUri(PRIVACY_POLICY_SITE) - MyInfoSideEffect.OpenTermWebSite -> uriHandler.openUri(TERMS_SITE) - MyInfoSideEffect.OpenAskWebSite -> uriHandler.openUri(ASK_SITE) - MyInfoSideEffect.OpenFeedbackWebSite -> uriHandler.openUri(FEEDBACK_SITE) - MyInfoSideEffect.NavigateLogin -> navigateLogin() - } - } - - LaunchedEffect(key1 = viewModel) { - viewModel.checkLoggedIn() - } - - MyInfoScreen( - padding = padding, - uiState = uiState, - scrollState = scrollState, - onClickNoticeButton = viewModel::navigateNotice, - onClickMyEvaluationButton = viewModel::navigateMyEvaluation, - onClickMyAccountButton = viewModel::navigateMyAccount, - onClickMyPointItem = viewModel::navigateMyPoint, - onClickBanHistoryItem = viewModel::navigateBanHistory, - onClickAskButton = viewModel::openAskSite, - onClickSendFeedback = viewModel::openFeedbackSite, - onClickTerm = viewModel::openTermSite, - onClickPersonalInfoPolicy = viewModel::openPersonalPolicySite, - onClickOpenLicense = viewModel::showOpenLicense, - onClickLogin = viewModel::navigateLogin, - ) -} - -@Composable -fun MyInfoScreen( - padding: PaddingValues, - uiState: MyInfoState, - scrollState: ScrollState, - onClickNoticeButton: () -> Unit, - onClickMyEvaluationButton: () -> Unit, - onClickMyAccountButton: () -> Unit, - onClickMyPointItem: () -> Unit, - onClickBanHistoryItem: () -> Unit, - onClickAskButton: () -> Unit, - onClickSendFeedback: () -> Unit, - onClickTerm: () -> Unit, - onClickPersonalInfoPolicy: () -> Unit, - onClickOpenLicense: () -> Unit, - onClickLogin: () -> Unit, -) { - val myList = immutableListOf( - MyInfoListItem( - title = stringResource(R.string.my_info_point), - onClick = onClickMyPointItem, - ), - MyInfoListItem( - title = stringResource(R.string.my_info_ban_history), - onClick = onClickBanHistoryItem, - ), - ) - val serviceList = immutableListOf( - MyInfoListItem( - title = stringResource(R.string.my_info_send_feedback), - onClick = onClickSendFeedback, - ), - MyInfoListItem( - title = stringResource(R.string.my_info_use_terms), - onClick = onClickTerm, - ), - MyInfoListItem( - title = stringResource(R.string.my_info_privacy_policy), - onClick = onClickPersonalInfoPolicy, - ), - MyInfoListItem( - title = stringResource(R.string.my_info_open_source_library), - onClick = onClickOpenLicense, - ), - ) - Column( - modifier = Modifier - .padding(padding) - .verticalScroll(scrollState), - ) { - Box( - modifier = Modifier.background(if (uiState.showMyInfoCard) GrayF6 else White), - ) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - ) { - with(uiState) { - if (showMyInfoCard) { - LoginMyInfoCard( - userId = loginId, - point = point, - onClickMyEvaluation = onClickMyEvaluationButton, - ) - } else { - LogoutMyInfoCard(onClickLogin) - } - } - Row( - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier - .padding(vertical = 28.dp, horizontal = 41.dp) - .fillMaxWidth() - .height(IntrinsicSize.Min), - ) { - MyInfoMenuItem( - title = stringResource(R.string.my_info_notice), - iconId = R.drawable.ic_my_info_notice, - onClickItem = onClickNoticeButton, - ) - VerticalDivider( - modifier = Modifier - .padding(vertical = 5.dp), - thickness = 1.dp, - color = GrayF6, - ) - MyInfoMenuItem( - title = stringResource(R.string.my_info_contact), - iconId = R.drawable.ic_my_info_comment, - onClickItem = onClickAskButton, - ) - VerticalDivider( - modifier = Modifier - .padding(vertical = 5.dp), - thickness = 1.dp, - color = GrayF6, - ) - MyInfoMenuItem( - title = stringResource(R.string.my_info_account_manage), - iconId = R.drawable.ic_my_info_setting, - onClickItem = onClickMyAccountButton, - ) - } - } - } - Column( - modifier = Modifier - .background(White) - .fillMaxSize(), - ) { - if (uiState.showMyInfoCard) { - SuwikiMenuItem(title = stringResource(R.string.my_info_my)) - - myList.forEach { (title, onClick) -> - MyInfoListItemContainer( - title = title, - onClick = onClick, - ) - } - } - SuwikiMenuItem(title = stringResource(R.string.my_info_service)) - - serviceList.forEach { (title, onClick) -> - MyInfoListItemContainer( - title = title, - onClick = onClick, - ) - } - } - if (uiState.isLoading) { - LoadingScreen() - } - } -} - -@Composable -fun LogoutMyInfoCard( - onClickLogin: () -> Unit = {}, -) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(top = 52.dp, start = 24.dp, end = 24.dp) - .background( - color = GrayF6, - shape = RoundedCornerShape(10.dp), - ), - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .padding(top = 19.dp, start = 16.dp) - .suwikiClickable(onClick = onClickLogin), - ) { - Text( - text = stringResource(R.string.my_info_login), - style = SuwikiTheme.typography.header2, - color = Black, - ) - Image( - painter = painterResource(id = R.drawable.ic_arrow_gray_right), - contentDescription = "", - ) - } - Text( - modifier = Modifier.padding(start = 16.dp, bottom = 19.dp), - text = stringResource(R.string.my_info_check_mine), - style = SuwikiTheme.typography.body4, - color = Gray95, - ) - } -} - -@Composable -fun LoginMyInfoCard( - userId: String, - point: Int, - onClickMyEvaluation: () -> Unit = {}, -) { - Row( - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier - .fillMaxWidth() - .padding(top = 52.dp, start = 24.dp, end = 24.dp) - .cardShadow() - .background( - color = White, - shape = RoundedCornerShape(10.dp), - ), - ) { - Column { - Text( - modifier = Modifier.padding(top = 19.dp, start = 16.dp), - text = userId, - style = SuwikiTheme.typography.header2, - color = Black, - ) - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.padding(start = 16.dp, bottom = 19.dp), - ) { - Image( - modifier = Modifier - .padding(end = 4.dp), - painter = painterResource(id = R.drawable.ic_my_info_point), - contentDescription = "", - ) - Text( - text = point.toString(), - style = SuwikiTheme.typography.body4, - color = Black, - ) - } - } - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .padding(top = 31.dp, end = 6.dp) - .suwikiClickable(onClick = onClickMyEvaluation), - ) { - Text( - text = stringResource(R.string.my_info_my_post), - style = SuwikiTheme.typography.caption1, - color = Black, - ) - Image( - painter = painterResource(id = R.drawable.ic_arrow_gray_right), - contentDescription = "", - ) - } - } -} - -@Composable -private fun MyInfoMenuItem( - title: String = "", - iconId: Int, - onClickItem: () -> Unit = {}, -) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier - .suwikiClickable(onClick = onClickItem), - ) { - Image( - painter = painterResource(id = iconId), - contentDescription = "", - ) - Text( - text = title, - style = SuwikiTheme.typography.caption2, - ) - } -} - -@Composable -private fun MyInfoListItemContainer( - title: String = "", - onClick: () -> Unit = {}, -) { - Box( - modifier = Modifier - .background(White) - .fillMaxWidth() - .wrapContentHeight() - .suwikiClickable( - onClick = onClick, - rippleColor = Gray6A, - ), - ) { - Text( - text = title, - style = SuwikiTheme.typography.body2, - modifier = Modifier - .align(Alignment.CenterStart) - .padding(top = 13.dp, bottom = 14.dp, start = 24.dp, end = 52.dp), - ) - } -} - -@Preview(showSystemUi = true) -@Composable -fun MyInfoScreenScreenPreview() { - val scrollState = rememberScrollState() - - SuwikiTheme { - MyInfoScreen( - padding = PaddingValues(0.dp), - uiState = MyInfoState(true), - scrollState = scrollState, - onClickNoticeButton = {}, - onClickMyEvaluationButton = {}, - onClickMyAccountButton = {}, - onClickMyPointItem = {}, - onClickBanHistoryItem = {}, - onClickSendFeedback = {}, - onClickTerm = {}, - onClickPersonalInfoPolicy = {}, - onClickOpenLicense = {}, - onClickAskButton = {}, - onClickLogin = {}, - ) - } -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/MyInfoViewModel.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/MyInfoViewModel.kt deleted file mode 100644 index a54522367..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/MyInfoViewModel.kt +++ /dev/null @@ -1,69 +0,0 @@ -package com.suwiki.presentation.myinfo - -import androidx.lifecycle.ViewModel -import com.suwiki.common.model.user.User -import com.suwiki.domain.user.usecase.GetUserInfoUseCase -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.catch -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class MyInfoViewModel @Inject constructor( - private val getUserInfoUseCase: GetUserInfoUseCase, -) : ContainerHost, ViewModel() { - override val container: Container = container(MyInfoState()) - - private var isLoggedIn: Boolean = false - - suspend fun checkLoggedIn() { - showLoadingScreen() - /* TODO 에러 처리 */ - getUserInfoUseCase() - .catch { intent { postSideEffect(MyInfoSideEffect.HandleException(it)) } } - .collect(::reduceUser) - hideLoadingScreen() - } - - private fun reduceUser(user: User) = intent { - reduce { - isLoggedIn = user.isLoggedIn - state.copy( - showMyInfoCard = user.isLoggedIn, - loginId = user.userId, - point = user.point, - ) - } - } - - private fun showLoadingScreen() = intent { reduce { state.copy(isLoading = true) } } - private fun hideLoadingScreen() = intent { reduce { state.copy(isLoading = false) } } - - fun navigateNotice() = intent { postSideEffect(MyInfoSideEffect.NavigateNotice) } - fun navigateMyEvaluation() = intent { postSideEffect(MyInfoSideEffect.NavigateMyEvaluation) } - fun navigateMyAccount() = intent { - postSideEffect( - if (isLoggedIn) { - MyInfoSideEffect.NavigateMyAccount - } else { - MyInfoSideEffect.ShowNeedLoginToast - }, - ) - } - fun navigateMyPoint() = intent { postSideEffect(MyInfoSideEffect.NavigateMyPoint) } - fun navigateLogin() = intent { postSideEffect(MyInfoSideEffect.NavigateLogin) } - fun navigateBanHistory() = intent { postSideEffect(MyInfoSideEffect.NavigateBanHistory) } - - fun openTermSite() = intent { postSideEffect(MyInfoSideEffect.OpenTermWebSite) } - fun openPersonalPolicySite() = intent { postSideEffect(MyInfoSideEffect.OpenPersonalPolicyWebSite) } - - fun openAskSite() = intent { postSideEffect(MyInfoSideEffect.OpenAskWebSite) } - fun openFeedbackSite() = intent { postSideEffect(MyInfoSideEffect.OpenFeedbackWebSite) } - - fun showOpenLicense() = intent { postSideEffect(MyInfoSideEffect.ShowOpenLicenses) } -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/banhistory/BanHistoryContract.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/banhistory/BanHistoryContract.kt deleted file mode 100644 index ef2cf01cf..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/banhistory/BanHistoryContract.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.suwiki.presentation.myinfo.banhistory - -import com.suwiki.common.model.user.Suspension -import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.persistentListOf - -data class BanHistoryState( - val isLoading: Boolean = false, - val banHistory: PersistentList = persistentListOf(), - val blackList: PersistentList = persistentListOf(), -) { - val showEmptyScreen = banHistory.isEmpty() && blackList.isEmpty() -} - -sealed interface BanHistorySideEffect { - data object PopBackStack : BanHistorySideEffect - data class HandleException(val throwable: Throwable) : BanHistorySideEffect -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/banhistory/BanHistoryScreen.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/banhistory/BanHistoryScreen.kt deleted file mode 100644 index 238a123f0..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/banhistory/BanHistoryScreen.kt +++ /dev/null @@ -1,103 +0,0 @@ -package com.suwiki.presentation.myinfo.banhistory - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.presentation.common.designsystem.component.appbar.SuwikiAppBarWithTitle -import com.suwiki.presentation.common.designsystem.component.container.SuwikiBoardContainer -import com.suwiki.presentation.common.designsystem.theme.Gray95 -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.myinfo.R -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect - -@Composable -fun BanHistoryRoute( - viewModel: BanHistoryViewModel = hiltViewModel(), - popBackStack: () -> Unit = {}, - handleException: (Throwable) -> Unit, -) { - val uiState = viewModel.collectAsState().value - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - is BanHistorySideEffect.PopBackStack -> popBackStack() - is BanHistorySideEffect.HandleException -> handleException(sideEffect.throwable) - } - } - - LaunchedEffect(key1 = Unit) { - viewModel.initData() - } - - BanHistoryScreen( - uiState = uiState, - popBackStack = viewModel::popBackStack, - ) -} - -@Composable -fun BanHistoryScreen( - uiState: BanHistoryState = BanHistoryState(), - popBackStack: () -> Unit = {}, -) { - Column( - modifier = Modifier - .fillMaxSize() - .background(White), - ) { - SuwikiAppBarWithTitle( - title = stringResource(R.string.my_info_ban_history), - showBackIcon = true, - showCloseIcon = false, - onClickBack = popBackStack, - ) - - if (uiState.showEmptyScreen) { - Text( - modifier = Modifier - .padding(top = 150.dp) - .fillMaxSize(), - textAlign = TextAlign.Center, - text = stringResource(R.string.ban_history_screen_empt), - style = SuwikiTheme.typography.header4, - color = Gray95, - ) - } - - LazyColumn { - items(items = uiState.banHistory) { banHistory -> - SuwikiBoardContainer( - titleText = banHistory.reason, - dateText = banHistory.createdAt.toString(), - ) - } - items(items = uiState.blackList) { blackList -> - SuwikiBoardContainer( - titleText = blackList.reason, - dateText = blackList.createdAt.toString(), - ) - } - } - } -} - -@Preview -@Composable -fun BanHistoryScreenPreview() { - SuwikiTheme { - BanHistoryScreen() - } -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/banhistory/BanHistoryViewModel.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/banhistory/BanHistoryViewModel.kt deleted file mode 100644 index 0d6607855..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/banhistory/BanHistoryViewModel.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.suwiki.presentation.myinfo.banhistory - -import androidx.lifecycle.ViewModel -import com.suwiki.domain.user.usecase.GetBanHistoryUseCase -import com.suwiki.domain.user.usecase.GetBlackListUseCase -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.collections.immutable.toPersistentList -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class BanHistoryViewModel @Inject constructor( - private val getBanHistoryUseCase: GetBanHistoryUseCase, - private val getBlackListUseCase: GetBlackListUseCase, -) : ContainerHost, ViewModel() { - override val container: Container = container(BanHistoryState()) - - fun initData() = intent { - getBanHistoryUseCase() - .onSuccess { - reduce { state.copy(banHistory = it.toPersistentList()) } - } - .onFailure { - postSideEffect(BanHistorySideEffect.HandleException(it)) - } - getBlackListUseCase() - .onSuccess { - reduce { state.copy(blackList = it.toPersistentList()) } - } - .onFailure { - postSideEffect(BanHistorySideEffect.HandleException(it)) - } - } - - fun popBackStack() = intent { postSideEffect(BanHistorySideEffect.PopBackStack) } -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/myaccount/MyAccountContract.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/myaccount/MyAccountContract.kt deleted file mode 100644 index d73f07842..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/myaccount/MyAccountContract.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.suwiki.presentation.myinfo.myaccount - -data class MyAccountState( - val isLoading: Boolean = false, - val userId: String = "", - val userEmail: String = "", -) - -sealed interface MyAccountSideEffect { - data object PopBackStack : MyAccountSideEffect - data object NavigateResetPassword : MyAccountSideEffect - data object NavigateQuit : MyAccountSideEffect - data class HandleException(val throwable: Throwable) : MyAccountSideEffect -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/myaccount/MyAccountScreen.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/myaccount/MyAccountScreen.kt deleted file mode 100644 index 0f28d750c..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/myaccount/MyAccountScreen.kt +++ /dev/null @@ -1,164 +0,0 @@ -package com.suwiki.presentation.myinfo.myaccount - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.presentation.common.designsystem.component.appbar.SuwikiAppBarWithTitle -import com.suwiki.presentation.common.designsystem.theme.Gray95 -import com.suwiki.presentation.common.designsystem.theme.GrayF6 -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.common.ui.extension.suwikiClickable -import com.suwiki.presentation.myinfo.R -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect - -@Composable -fun MyAccountRoute( - viewModel: MyAccountViewModel = hiltViewModel(), - popBackStack: () -> Unit, - navigateResetPassword: () -> Unit = {}, - navigateQuit: () -> Unit = {}, - handleException: (Throwable) -> Unit, -) { - val uiState = viewModel.collectAsState().value - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - MyAccountSideEffect.PopBackStack -> popBackStack() - is MyAccountSideEffect.NavigateResetPassword -> navigateResetPassword() - is MyAccountSideEffect.NavigateQuit -> navigateQuit() - is MyAccountSideEffect.HandleException -> handleException(sideEffect.throwable) - } - } - - LaunchedEffect(key1 = Unit) { - viewModel.initData() - } - - MyAccountScreen( - uiState = uiState, - popBackStack = viewModel::popBackStack, - onClickResetPassword = viewModel::navigateResetPassword, - onClickLogout = viewModel::logout, - onClickQuit = viewModel::navigateQuit, - ) -} - -@Composable -fun MyAccountScreen( - uiState: MyAccountState = MyAccountState(), - popBackStack: () -> Unit = {}, - onClickResetPassword: () -> Unit = {}, - onClickLogout: () -> Unit = {}, - onClickQuit: () -> Unit = {}, -) { - Column( - modifier = Modifier - .fillMaxSize() - .background(White), - ) { - SuwikiAppBarWithTitle( - showBackIcon = true, - showCloseIcon = false, - onClickBack = popBackStack, - ) - Text( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp, vertical = 14.dp), - text = stringResource(R.string.word_my_account), - style = SuwikiTheme.typography.body2, - ) - UserInfoRowContainer( - userInfo = stringResource(R.string.word_login_id), - userInfoValue = uiState.userId, - ) - UserInfoRowContainer( - userInfo = stringResource(R.string.word_authentication_email), - userInfoValue = uiState.userEmail, - ) - Spacer(modifier = Modifier.height(24.dp)) - AlignContainer( - title = stringResource(R.string.word_reset_password), - onClick = onClickResetPassword, - ) - AlignContainer( - title = stringResource(R.string.word_logout), - onClick = onClickLogout, - ) - AlignContainer( - title = stringResource(R.string.word_quit), - onClick = onClickQuit, - ) - } -} - -@Composable -fun AlignContainer( - modifier: Modifier = Modifier, - title: String, - onClick: () -> Unit = {}, -) { - Box( - modifier = modifier - .fillMaxWidth() - .suwikiClickable(onClick = onClick) - .padding(horizontal = 24.dp, vertical = 14.dp), - ) { - Text( - text = title, - style = SuwikiTheme.typography.body2, - ) - } -} - -@Composable -fun UserInfoRowContainer( - modifier: Modifier = Modifier, - userInfo: String, - userInfoValue: String, -) { - Column { - Row( - modifier = modifier - .fillMaxWidth() - .padding(horizontal = 24.dp, vertical = 14.dp), - horizontalArrangement = Arrangement.SpaceBetween, - ) { - Text( - text = userInfo, - style = SuwikiTheme.typography.caption2, - color = Gray95, - ) - Text( - text = userInfoValue, - style = SuwikiTheme.typography.body5, - ) - } - HorizontalDivider(color = GrayF6) - } -} - -@Preview -@Composable -fun MyAccountScreenPreview() { - SuwikiTheme { - MyAccountScreen() - } -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/myaccount/MyAccountViewModel.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/myaccount/MyAccountViewModel.kt deleted file mode 100644 index 798d1d5d9..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/myaccount/MyAccountViewModel.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.suwiki.presentation.myinfo.myaccount - -import androidx.lifecycle.ViewModel -import com.suwiki.common.model.user.User -import com.suwiki.domain.user.usecase.GetUserInfoUseCase -import com.suwiki.domain.user.usecase.LogoutUseCase -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.catch -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class MyAccountViewModel @Inject constructor( - private val getUserInfoUseCase: GetUserInfoUseCase, - private val logoutUseCase: LogoutUseCase, -) : ContainerHost, ViewModel() { - override val container: Container = container(MyAccountState()) - - fun initData() = intent { - getUserInfoUseCase() - .catch { e -> postSideEffect(MyAccountSideEffect.HandleException(e)) } - .collect(::updateUserIdAndEmail) - } - - fun logout() = intent { - logoutUseCase() - .onSuccess { popBackStack() } - .onFailure { postSideEffect(MyAccountSideEffect.HandleException(it)) } - } - - private fun updateUserIdAndEmail(user: User) = intent { - if (user.isLoggedIn.not()) { - popBackStack() - return@intent - } - - reduce { - state.copy( - userId = user.userId, - userEmail = user.email, - ) - } - } - - fun popBackStack() = intent { postSideEffect(MyAccountSideEffect.PopBackStack) } - fun navigateResetPassword() = intent { postSideEffect(MyAccountSideEffect.NavigateResetPassword) } - fun navigateQuit() = intent { postSideEffect(MyAccountSideEffect.NavigateQuit) } -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/mypoint/MyPointContract.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/mypoint/MyPointContract.kt deleted file mode 100644 index 31fbbcdf6..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/mypoint/MyPointContract.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.suwiki.presentation.myinfo.mypoint - -import com.suwiki.common.model.lectureevaluation.PurchaseHistory -import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.persistentListOf - -data class MyPointState( - val isLoading: Boolean = false, - val currentPoint: Int = 0, - val writtenLectureEvaluations: Int = 0, - val writtenExamEvaluations: Int = 0, - val viewExam: Int = 0, - val purchaseHistory: PersistentList = persistentListOf(), -) - -sealed interface MyPointSideEffect { - data object PopBackStack : MyPointSideEffect - data class HandleException(val throwable: Throwable) : MyPointSideEffect -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/mypoint/MyPointScreen.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/mypoint/MyPointScreen.kt deleted file mode 100644 index ba03349e6..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/mypoint/MyPointScreen.kt +++ /dev/null @@ -1,236 +0,0 @@ -package com.suwiki.presentation.myinfo.mypoint - -import androidx.compose.foundation.ScrollState -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.presentation.common.designsystem.component.appbar.SuwikiAppBarWithTitle -import com.suwiki.presentation.common.designsystem.theme.Gray95 -import com.suwiki.presentation.common.designsystem.theme.GrayF6 -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.myinfo.R -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect - -const val WRITE_LECTURE_EVALUATION_POINT = 10 -const val WRITE_EXAM_EVALUATION_POINT = 20 -const val VIEW_EXAM_POINT = 20 - -@Composable -fun MyPointRoute( - viewModel: MyPointViewModel = hiltViewModel(), - popBackStack: () -> Unit, - handleException: (Throwable) -> Unit, -) { - val uiState = viewModel.collectAsState().value - val scrollState = rememberScrollState() - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - is MyPointSideEffect.PopBackStack -> popBackStack() - is MyPointSideEffect.HandleException -> handleException(sideEffect.throwable) - } - } - - LaunchedEffect(key1 = Unit) { - viewModel.initData() - } - - MyPointScreen( - uiState = uiState, - scrollState = scrollState, - popBackStack = viewModel::popBackStack, - ) -} - -@Composable -fun MyPointScreen( - uiState: MyPointState = MyPointState(), - scrollState: ScrollState, - popBackStack: () -> Unit = {}, -) { - Column( - modifier = Modifier - .background(White), - ) { - SuwikiAppBarWithTitle( - title = stringResource(R.string.my_info_point), - showBackIcon = true, - showCloseIcon = false, - onClickBack = popBackStack, - ) - Column( - modifier = Modifier - .fillMaxSize() - .padding(start = 24.dp, end = 24.dp) - .verticalScroll(scrollState), - ) { - TitleContainer(title = stringResource(R.string.word_point_status)) - MyPointRowContainer( - modifier = Modifier.padding(vertical = 14.dp), - title = stringResource(R.string.word_current_point), - point = stringResource(R.string.word_current_point_value, uiState.currentPoint), - verticalAlignment = Alignment.Bottom, - ) - MyPointRowContainer( - modifier = Modifier.padding(vertical = 14.dp), - title = stringResource(R.string.text_written_lecture_evaluation, uiState.writtenLectureEvaluations), - point = stringResource(R.string.word_plus_point_value, uiState.writtenLectureEvaluations * WRITE_LECTURE_EVALUATION_POINT), - verticalAlignment = Alignment.Bottom, - ) - MyPointRowContainer( - modifier = Modifier.padding(vertical = 14.dp), - title = stringResource(R.string.text_written_exam_evaluation, uiState.writtenExamEvaluations * WRITE_EXAM_EVALUATION_POINT), - point = stringResource(R.string.word_plus_point_value, uiState.writtenExamEvaluations * WRITE_EXAM_EVALUATION_POINT), - verticalAlignment = Alignment.Bottom, - ) - MyPointRowContainer( - modifier = Modifier.padding(vertical = 14.dp), - title = stringResource(R.string.text_view_exam, uiState.viewExam), - point = stringResource(R.string.word_minus_point_value, uiState.viewExam * VIEW_EXAM_POINT), - verticalAlignment = Alignment.Bottom, - ) - Spacer(modifier = Modifier.height(12.dp)) - PointPolicyContainer() - Spacer(modifier = Modifier.height(24.dp)) - if (!uiState.purchaseHistory.isEmpty()) { - TitleContainer(title = stringResource(R.string.word_point_use_history)) - } - Column { - uiState.purchaseHistory.forEach { purchaseHistory -> - Row( - verticalAlignment = Alignment.Bottom, - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 17.dp), - ) { - Text( - modifier = Modifier.weight(1f), - maxLines = 1, - text = purchaseHistory.createDate.toString(), - style = SuwikiTheme.typography.body5, - color = Gray95, - ) - Text( - modifier = Modifier.weight(1f), - maxLines = 1, - textAlign = TextAlign.End, - text = purchaseHistory.lectureName, - style = SuwikiTheme.typography.body5, - ) - } - } - } - } - } -} - -@Composable -fun TitleContainer( - title: String, -) { - Text( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 14.dp), - text = title, - style = SuwikiTheme.typography.body2, - ) -} - -@Composable -fun MyPointRowContainer( - modifier: Modifier = Modifier, - title: String, - point: String, - verticalAlignment: Alignment.Vertical, -) { - Column { - Row( - verticalAlignment = verticalAlignment, - horizontalArrangement = Arrangement.spacedBy(48.dp), - modifier = modifier.fillMaxWidth(), - ) { - Text( - modifier = Modifier.width(120.dp), - text = title, - style = SuwikiTheme.typography.body5, - color = Gray95, - ) - Text( - text = point, - style = SuwikiTheme.typography.body5, - ) - } - HorizontalDivider(color = GrayF6) - } -} - -@Composable -fun PointPolicyText( - text: String, -) { - Row( - modifier = Modifier.fillMaxWidth(), - ) { - Text( - text = stringResource(R.string.word_dot), - style = SuwikiTheme.typography.caption4, - ) - Text( - text = text, - style = SuwikiTheme.typography.caption4, - ) - } -} - -@Composable -fun PointPolicyContainer() { - Column( - modifier = Modifier - .padding(vertical = 12.dp), - ) { - PointPolicyText(stringResource(R.string.text_point_policy_first)) - PointPolicyText(stringResource(R.string.text_point_policy_second)) - PointPolicyText(stringResource(R.string.text_point_policy_third)) - PointPolicyText(stringResource(R.string.text_point_policy_fourth)) - Text("") - PointPolicyText(stringResource(R.string.text_point_policy_fifth)) - PointPolicyText(stringResource(R.string.text_point_policy_sixth)) - PointPolicyText(stringResource(R.string.text_point_policy_seventh)) - Text("") - PointPolicyText(stringResource(R.string.text_point_policy_eighth)) - PointPolicyText(stringResource(R.string.text_point_policy_ninth)) - } -} - -@Preview -@Composable -fun MyPointScreenPreview() { - val scrollState = rememberScrollState() - - SuwikiTheme { - MyPointScreen(scrollState = scrollState) - } -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/mypoint/MyPointViewModel.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/mypoint/MyPointViewModel.kt deleted file mode 100644 index 61557110f..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/mypoint/MyPointViewModel.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.suwiki.presentation.myinfo.mypoint - -import androidx.lifecycle.ViewModel -import com.suwiki.common.model.user.User -import com.suwiki.domain.lectureevaluation.usecase.exam.GetPurchaseHistoryUseCase -import com.suwiki.domain.user.usecase.GetUserInfoUseCase -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.collections.immutable.toPersistentList -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class MyPointViewModel @Inject constructor( - private val getUserInfoUseCase: GetUserInfoUseCase, - private val getPurchaseHistoryUseCase: GetPurchaseHistoryUseCase, -) : ContainerHost, ViewModel() { - override val container: Container = container(MyPointState()) - - fun initData() = intent { - showLoadingScreen() - getUserInfoUseCase().collect(::reduceMyPoint) - getPurchaseHistory() - hideLoadingScreen() - } - - private fun reduceMyPoint(user: User) = intent { - reduce { - state.copy( - currentPoint = user.point, - writtenLectureEvaluations = user.writtenEvaluation, - writtenExamEvaluations = user.writtenExam, - viewExam = user.viewExam, - ) - } - } - - private fun getPurchaseHistory() = intent { - getPurchaseHistoryUseCase() - .onSuccess { purchaseHistory -> - reduce { state.copy(purchaseHistory = purchaseHistory.toPersistentList()) } - } - .onFailure { - postSideEffect(MyPointSideEffect.HandleException(it)) - } - } - - private fun showLoadingScreen() = intent { reduce { state.copy(isLoading = true) } } - private fun hideLoadingScreen() = intent { reduce { state.copy(isLoading = false) } } - fun popBackStack() = intent { postSideEffect(MyPointSideEffect.PopBackStack) } -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/navigation/MyInfoNavigation.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/navigation/MyInfoNavigation.kt deleted file mode 100644 index 38acd8e1a..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/navigation/MyInfoNavigation.kt +++ /dev/null @@ -1,120 +0,0 @@ -package com.suwiki.presentation.myinfo.navigation - -import androidx.compose.foundation.layout.PaddingValues -import androidx.navigation.NavController -import androidx.navigation.NavGraphBuilder -import androidx.navigation.NavOptions -import androidx.navigation.compose.composable -import androidx.navigation.navOptions -import com.suwiki.presentation.myinfo.MyInfoRoute -import com.suwiki.presentation.myinfo.banhistory.BanHistoryRoute -import com.suwiki.presentation.myinfo.myaccount.MyAccountRoute -import com.suwiki.presentation.myinfo.mypoint.MyPointRoute -import com.suwiki.presentation.myinfo.quit.QuitRoute -import com.suwiki.presentation.myinfo.resetpassword.ResetPasswordRoute - -fun NavController.navigateMyInfo(navOptions: NavOptions) { - navigate(MyInfoRoute.route, navOptions) -} - -fun NavController.navigateMyAccount() { - navigate(MyInfoRoute.myAccountRoute) -} - -fun NavController.navigateResetPassword() { - navigate(MyInfoRoute.resetPasswordRoute) -} - -fun NavController.navigateQuit() { - navigate(MyInfoRoute.quitRoute) -} - -fun NavController.navigateMyPoint() { - navigate(MyInfoRoute.myPointRoute) -} - -fun NavController.navigateBanHistory() { - navigate(MyInfoRoute.banHistoryRoute) -} - -fun NavGraphBuilder.myInfoNavGraph( - padding: PaddingValues, - popBackStack: () -> Unit = {}, - navigateNotice: () -> Unit = {}, - navigateMyEvaluation: () -> Unit = {}, - navigateMyAccount: () -> Unit = {}, - navigateResetPassword: () -> Unit = {}, - navigateQuit: () -> Unit = {}, - navigateFindPassword: () -> Unit = {}, - navigateMyPoint: () -> Unit = {}, - navigateBanHistory: () -> Unit = {}, - navigateLogin: (NavOptions?) -> Unit = {}, - handleException: (Throwable) -> Unit = {}, - onShowToast: (String) -> Unit = {}, -) { - composable(route = MyInfoRoute.route) { - MyInfoRoute( - padding = padding, - navigateNotice = navigateNotice, - navigateMyEvaluation = navigateMyEvaluation, - navigateMyAccount = navigateMyAccount, - navigateMyPoint = navigateMyPoint, - navigateBanHistory = navigateBanHistory, - navigateLogin = { - navigateLogin(null) - }, - onShowToast = onShowToast, - handleException = handleException, - ) - } - composable(route = MyInfoRoute.myAccountRoute) { - MyAccountRoute( - popBackStack = popBackStack, - navigateResetPassword = navigateResetPassword, - navigateQuit = navigateQuit, - handleException = handleException, - ) - } - composable(route = MyInfoRoute.resetPasswordRoute) { - ResetPasswordRoute( - popBackStack = popBackStack, - navigateFindPassword = navigateFindPassword, - navigateLogin = { - navigateLogin( - navOptions { - popUpTo(MyInfoRoute.route) - }, - ) - }, - handleException = handleException, - ) - } - composable(route = MyInfoRoute.quitRoute) { - QuitRoute( - popBackStack = popBackStack, - handleException = handleException, - onShowToast = onShowToast, - ) - } - composable(route = MyInfoRoute.myPointRoute) { - MyPointRoute( - popBackStack = popBackStack, - handleException = handleException, - ) - } - composable(route = MyInfoRoute.banHistoryRoute) { - BanHistoryRoute( - popBackStack = popBackStack, - handleException = handleException, - ) - } -} - -object MyInfoRoute { - const val route = "my-info" - const val myAccountRoute = "my-account" - const val resetPasswordRoute = "reset-password" - const val quitRoute = "quit" - const val myPointRoute = "my-point" - const val banHistoryRoute = "ban-history" -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/quit/QuitContract.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/quit/QuitContract.kt deleted file mode 100644 index 6ea9c5599..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/quit/QuitContract.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.suwiki.presentation.myinfo.quit - -data class QuitState( - val isLoading: Boolean = false, - val id: String = "", - val password: String = "", - val showPassword: Boolean = false, -) { - val quitButtonEnable = id.isNotBlank() && password.isNotBlank() -} - -sealed interface QuitSideEffect { - data object ShowSuccessQuitToast : QuitSideEffect - data object PopBackStack : QuitSideEffect - data class HandleException(val throwable: Throwable) : QuitSideEffect -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/quit/QuitScreen.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/quit/QuitScreen.kt deleted file mode 100644 index 6ce69526e..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/quit/QuitScreen.kt +++ /dev/null @@ -1,125 +0,0 @@ -package com.suwiki.presentation.myinfo.quit - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.presentation.common.designsystem.component.appbar.SuwikiAppBarWithTitle -import com.suwiki.presentation.common.designsystem.component.button.SuwikiContainedLargeButton -import com.suwiki.presentation.common.designsystem.component.textfield.SuwikiRegularTextField -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.myinfo.R -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect - -@Composable -fun QuitRoute( - viewModel: QuitViewModel = hiltViewModel(), - onShowToast: (String) -> Unit, - popBackStack: () -> Unit, - handleException: (Throwable) -> Unit, -) { - val uiState = viewModel.collectAsState().value - val context = LocalContext.current - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - is QuitSideEffect.PopBackStack -> popBackStack() - is QuitSideEffect.HandleException -> handleException(sideEffect.throwable) - QuitSideEffect.ShowSuccessQuitToast -> onShowToast(context.getString(R.string.quit_screen_quit_success_toast)) - } - } - QuitScreen( - uiState = uiState, - popBackStack = viewModel::popBackStack, - onClickQuitButton = viewModel::quit, - onValueChangeId = viewModel::updateId, - onClickIdTextFieldClearButton = { viewModel.updateId("") }, - onValueChangePassword = viewModel::updatePassword, - onClickPasswordTextFieldClearButton = { viewModel.updatePassword("") }, - onClickPasswordEyeIcon = viewModel::toggleShowPassword, - ) -} - -@Composable -fun QuitScreen( - uiState: QuitState = QuitState(), - popBackStack: () -> Unit = {}, - onClickQuitButton: (String, String) -> Unit = { _, _ -> }, - onValueChangeId: (String) -> Unit = {}, - onClickIdTextFieldClearButton: () -> Unit = {}, - onValueChangePassword: (String) -> Unit = {}, - onClickPasswordTextFieldClearButton: () -> Unit = {}, - onClickPasswordEyeIcon: () -> Unit = {}, -) { - Column( - modifier = Modifier - .fillMaxSize() - .background(White), - ) { - SuwikiAppBarWithTitle( - showBackIcon = true, - showCloseIcon = false, - onClickBack = popBackStack, - ) - Column( - modifier = Modifier.padding(start = 24.dp, end = 24.dp), - ) { - Text( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 14.dp), - text = stringResource(R.string.word_quit), - style = SuwikiTheme.typography.header1, - ) - Spacer(modifier = Modifier.height(12.dp)) - SuwikiRegularTextField( - label = stringResource(R.string.word_id), - placeholder = stringResource(R.string.quit_screen_id_textfield_placeholder), - value = uiState.id, - onValueChange = onValueChangeId, - onClickClearButton = onClickIdTextFieldClearButton, - ) - Spacer(modifier = Modifier.height(12.dp)) - SuwikiRegularTextField( - label = stringResource(R.string.word_password), - placeholder = stringResource(R.string.quit_screen_password_textfield_placeholder), - showEyeIcon = true, - value = uiState.password, - showValue = uiState.showPassword, - onValueChange = onValueChangePassword, - onClickClearButton = onClickPasswordTextFieldClearButton, - onClickEyeIcon = onClickPasswordEyeIcon, - ) - Spacer(modifier = Modifier.weight(1f)) - SuwikiContainedLargeButton( - modifier = Modifier.imePadding(), - text = stringResource(R.string.word_quit), - onClick = { onClickQuitButton(uiState.id, uiState.password) }, - clickable = uiState.quitButtonEnable, - enabled = uiState.quitButtonEnable, - ) - Spacer(modifier = Modifier.height(20.dp)) - } - } -} - -@Preview -@Composable -fun QuitScreenPreview() { - SuwikiTheme { - QuitScreen() - } -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/quit/QuitViewModel.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/quit/QuitViewModel.kt deleted file mode 100644 index 42bbfa33b..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/quit/QuitViewModel.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.suwiki.presentation.myinfo.quit - -import androidx.lifecycle.ViewModel -import com.suwiki.domain.user.usecase.QuitUseCase -import dagger.hilt.android.lifecycle.HiltViewModel -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.annotation.OrbitExperimental -import org.orbitmvi.orbit.syntax.simple.blockingIntent -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class QuitViewModel @Inject constructor( - private val quitUseCase: QuitUseCase, -) : ContainerHost, ViewModel() { - override val container: Container = container(QuitState()) - - @OptIn(OrbitExperimental::class) - fun updateId(id: String) = blockingIntent { - reduce { state.copy(id = id) } - } - - @OptIn(OrbitExperimental::class) - fun updatePassword(password: String) = blockingIntent { - reduce { state.copy(password = password) } - } - - @OptIn(OrbitExperimental::class) - fun quit(id: String, password: String) = blockingIntent { - showLoadingScreen() - quitUseCase( - id = id, - password = password, - ).onSuccess { - postSideEffect(QuitSideEffect.ShowSuccessQuitToast) - popBackStack() - }.onFailure { - postSideEffect(QuitSideEffect.HandleException(it)) - } - hideLoadingScreen() - } - - private fun showLoadingScreen() = intent { reduce { state.copy(isLoading = true) } } - - private fun hideLoadingScreen() = intent { reduce { state.copy(isLoading = false) } } - fun toggleShowPassword() = intent { reduce { state.copy(showPassword = !state.showPassword) } } - fun popBackStack() = intent { postSideEffect(QuitSideEffect.PopBackStack) } -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/resetpassword/ResetPasswordContract.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/resetpassword/ResetPasswordContract.kt deleted file mode 100644 index ec0030158..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/resetpassword/ResetPasswordContract.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.suwiki.presentation.myinfo.resetpassword - -import com.suwiki.presentation.myinfo.R - -data class ResetPasswordState( - val isLoading: Boolean = false, - val currentPassword: String = "", - val newPassword: String = "", - val checkNewPassword: String = "", - val showCurrentPassword: Boolean = false, - val showNewPassword: Boolean = false, - val showCheckNewPassword: Boolean = false, - val showPasswordInvalidErrorText: Boolean = false, - val showPasswordNotMatchErrorText: Boolean = false, - val showResetPasswordDialog: Boolean = false, -) { - val passwordInvalidHelperTextId = - if (showPasswordInvalidErrorText) { - R.string.textfield_password_invalid_helper_text - } else { - R.string.word_empty - } - val passwordMatchHelperTextId = - if (showPasswordNotMatchErrorText) { - R.string.textfield_password_not_same_helper_text - } else { - R.string.word_empty - } - val showResetPasswordButton = (!showPasswordInvalidErrorText && !showPasswordNotMatchErrorText) && - (currentPassword.isNotEmpty() && newPassword.isNotEmpty() && checkNewPassword.isNotEmpty()) -} - -sealed interface ResetPasswordSideEffect { - data object PopBackStack : ResetPasswordSideEffect - data object NavigateFindPassword : ResetPasswordSideEffect - data object NavigateLogin : ResetPasswordSideEffect - data class HandleException(val throwable: Throwable) : ResetPasswordSideEffect -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/resetpassword/ResetPasswordScreen.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/resetpassword/ResetPasswordScreen.kt deleted file mode 100644 index 6abbd5ecf..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/resetpassword/ResetPasswordScreen.kt +++ /dev/null @@ -1,205 +0,0 @@ -package com.suwiki.presentation.myinfo.resetpassword - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.presentation.common.designsystem.component.appbar.SuwikiAppBarWithTitle -import com.suwiki.presentation.common.designsystem.component.button.SuwikiContainedLargeButton -import com.suwiki.presentation.common.designsystem.component.dialog.SuwikiDialog -import com.suwiki.presentation.common.designsystem.component.loading.LoadingScreen -import com.suwiki.presentation.common.designsystem.component.textfield.SuwikiRegularTextField -import com.suwiki.presentation.common.designsystem.theme.Gray6A -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.common.ui.extension.suwikiClickable -import com.suwiki.presentation.common.ui.util.LaunchedEffectWithLifecycle -import com.suwiki.presentation.myinfo.R -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect - -@Composable -fun ResetPasswordRoute( - viewModel: ResetPasswordViewModel = hiltViewModel(), - popBackStack: () -> Unit, - navigateFindPassword: () -> Unit, - navigateLogin: () -> Unit, - handleException: (Throwable) -> Unit, -) { - val uiState = viewModel.collectAsState().value - - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - is ResetPasswordSideEffect.PopBackStack -> popBackStack() - is ResetPasswordSideEffect.NavigateFindPassword -> navigateFindPassword() - is ResetPasswordSideEffect.NavigateLogin -> navigateLogin() - is ResetPasswordSideEffect.HandleException -> handleException(sideEffect.throwable) - } - } - - LaunchedEffectWithLifecycle(key1 = uiState.newPassword, key2 = uiState.checkNewPassword) { - viewModel.checkNewPasswordInvalid(uiState.newPassword) - viewModel.checkNewPasswordMatch(uiState.checkNewPassword) - } - - ResetPasswordScreen( - uiState = uiState, - onClickBack = viewModel::popBackStack, - onValueChangeCurrentPassword = viewModel::updateCurrentPassword, - onClickCurrentPasswordTextFieldClearButton = { viewModel.updateCurrentPassword("") }, - onClickCurrentPasswordEyeIcon = viewModel::toggleShowCurrentPassword, - onValueChangeNewPassword = viewModel::updateNewPassword, - onClickNewPasswordTextFieldClearButton = { viewModel.updateNewPassword("") }, - onClickNewPasswordEyeIcon = viewModel::toggleShowNewPassword, - onValueChangeCheckNewPassword = viewModel::updateCheckNewPassword, - onClickCheckNewPasswordTextFieldClearButton = { viewModel.updateCheckNewPassword("") }, - onClickCheckNewPasswordEyeIcon = viewModel::toggleShowCheckNewPassword, - onClickFindPasswordButton = viewModel::navigateFindPassword, - onClickResetPasswordButton = viewModel::resetPassword, - onDismissResetPasswordDialog = { - viewModel.hideResetPasswordDialog() - viewModel.popBackStack() - }, - onClickResetPasswordDialogConfirm = { - viewModel.hideResetPasswordDialog() - viewModel.navigateLogin() - }, - ) -} - -@Composable -fun ResetPasswordScreen( - uiState: ResetPasswordState = ResetPasswordState(), - onClickBack: () -> Unit = {}, - onValueChangeCurrentPassword: (String) -> Unit = {}, - onClickCurrentPasswordTextFieldClearButton: () -> Unit = {}, - onClickCurrentPasswordEyeIcon: () -> Unit = {}, - onClickNewPasswordEyeIcon: () -> Unit = {}, - onClickCheckNewPasswordEyeIcon: () -> Unit = {}, - onValueChangeNewPassword: (String) -> Unit = {}, - onClickNewPasswordTextFieldClearButton: () -> Unit = {}, - onValueChangeCheckNewPassword: (String) -> Unit = {}, - onClickCheckNewPasswordTextFieldClearButton: () -> Unit = {}, - onClickFindPasswordButton: () -> Unit = {}, - onClickResetPasswordButton: () -> Unit = {}, - onDismissResetPasswordDialog: () -> Unit = {}, - onClickResetPasswordDialogConfirm: () -> Unit = {}, -) { - Column( - modifier = Modifier - .fillMaxSize() - .background(White) - .padding(bottom = 20.dp), - ) { - SuwikiAppBarWithTitle( - showBackIcon = true, - showCloseIcon = false, - onClickBack = onClickBack, - ) - Column( - modifier = Modifier.padding(start = 24.dp, end = 24.dp), - ) { - Text( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 14.dp), - text = stringResource(R.string.word_reset_password), - style = SuwikiTheme.typography.header1, - ) - Spacer(modifier = Modifier.height(12.dp)) - SuwikiRegularTextField( - label = stringResource(R.string.word_current_password), - placeholder = stringResource(R.string.reset_password_screen_current_password_textfield_placeholder), - showEyeIcon = true, - value = uiState.currentPassword, - showValue = uiState.showCurrentPassword, - onValueChange = onValueChangeCurrentPassword, - onClickClearButton = onClickCurrentPasswordTextFieldClearButton, - onClickEyeIcon = onClickCurrentPasswordEyeIcon, - helperText = "", - ) - Spacer(modifier = Modifier.height(12.dp)) - SuwikiRegularTextField( - label = stringResource(R.string.word_new_password), - placeholder = stringResource(R.string.textfield_password_placeholder), - showEyeIcon = true, - value = uiState.newPassword, - showValue = uiState.showNewPassword, - onValueChange = onValueChangeNewPassword, - onClickClearButton = onClickNewPasswordTextFieldClearButton, - onClickEyeIcon = onClickNewPasswordEyeIcon, - helperText = stringResource(uiState.passwordInvalidHelperTextId), - isError = uiState.showPasswordInvalidErrorText, - ) - Spacer(modifier = Modifier.height(12.dp)) - SuwikiRegularTextField( - label = stringResource(R.string.word_new_password_check), - placeholder = stringResource(R.string.reset_password_screen_check_new_password_textfield_placeholder), - showEyeIcon = true, - value = uiState.checkNewPassword, - showValue = uiState.showCheckNewPassword, - onValueChange = onValueChangeCheckNewPassword, - onClickClearButton = onClickCheckNewPasswordTextFieldClearButton, - onClickEyeIcon = onClickCheckNewPasswordEyeIcon, - helperText = stringResource(uiState.passwordMatchHelperTextId), - isError = uiState.showPasswordNotMatchErrorText, - ) - Spacer(modifier = Modifier.weight(1f)) - Column( - modifier = Modifier - .fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Text( - modifier = Modifier - .suwikiClickable(onClick = onClickFindPasswordButton), - text = stringResource(R.string.word_find_password), - style = SuwikiTheme.typography.body5, - color = Gray6A, - ) - Spacer(modifier = Modifier.height(20.dp)) - if (uiState.showResetPasswordButton) { - SuwikiContainedLargeButton( - modifier = Modifier.imePadding(), - text = stringResource(R.string.word_change), - onClick = onClickResetPasswordButton, - ) - } - } - } - } - if (uiState.showResetPasswordDialog) { - SuwikiDialog( - headerText = stringResource(R.string.reset_password_screen_dialog_header), - bodyText = stringResource(R.string.reset_password_screen_dialog_body), - confirmButtonText = stringResource(R.string.word_login), - dismissButtonText = stringResource(R.string.word_cancel), - onDismissRequest = onDismissResetPasswordDialog, - onClickDismiss = onDismissResetPasswordDialog, - onClickConfirm = onClickResetPasswordDialogConfirm, - ) - } - if (uiState.isLoading) { - LoadingScreen() - } -} - -@Preview(showBackground = true) -@Composable -fun ResetPasswordScreenPreview() { - SuwikiTheme { - ResetPasswordScreen() - } -} diff --git a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/resetpassword/ResetPasswordViewModel.kt b/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/resetpassword/ResetPasswordViewModel.kt deleted file mode 100644 index b75c3dcc6..000000000 --- a/presentation/myinfo/src/main/java/com/suwiki/presentation/myinfo/resetpassword/ResetPasswordViewModel.kt +++ /dev/null @@ -1,83 +0,0 @@ -package com.suwiki.presentation.myinfo.resetpassword - -import androidx.lifecycle.ViewModel -import com.suwiki.domain.user.usecase.ResetPasswordUseCase -import com.suwiki.presentation.common.ui.util.REGEX -import dagger.hilt.android.lifecycle.HiltViewModel -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.annotation.OrbitExperimental -import org.orbitmvi.orbit.syntax.simple.blockingIntent -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class ResetPasswordViewModel @Inject constructor( - val resetPasswordUseCase: ResetPasswordUseCase, -) : ContainerHost, ViewModel() { - override val container: Container = container( - ResetPasswordState(), - ) - - fun checkNewPasswordInvalid(password: String) = intent { - reduce { state.copy(showPasswordInvalidErrorText = !(password == "" || password.matches(REGEX.PASSWORD))) } - } - - fun checkNewPasswordMatch(password: String) = intent { - reduce { state.copy(showPasswordNotMatchErrorText = !(password == "" || password == state.newPassword)) } - } - - fun resetPassword() = intent { - showLoadingScreen() - resetPasswordUseCase( - currentPassword = state.currentPassword, - newPassword = state.newPassword, - ).onSuccess { - showResetPasswordDialog() - }.onFailure { - postSideEffect(ResetPasswordSideEffect.HandleException(it)) - } - hideLoadingScreen() - } - - @OptIn(OrbitExperimental::class) - fun updateCurrentPassword(password: String) = blockingIntent { - reduce { - state.copy( - currentPassword = password, - ) - } - } - - @OptIn(OrbitExperimental::class) - fun updateNewPassword(password: String) = blockingIntent { - reduce { - state.copy( - newPassword = password, - ) - } - } - - @OptIn(OrbitExperimental::class) - fun updateCheckNewPassword(password: String) = blockingIntent { - reduce { - state.copy( - checkNewPassword = password, - ) - } - } - - private fun showLoadingScreen() = intent { reduce { state.copy(isLoading = true) } } - private fun hideLoadingScreen() = intent { reduce { state.copy(isLoading = false) } } - private fun showResetPasswordDialog() = intent { reduce { state.copy(showResetPasswordDialog = true) } } - fun hideResetPasswordDialog() = intent { reduce { state.copy(showResetPasswordDialog = false) } } - fun toggleShowCurrentPassword() = intent { reduce { state.copy(showCurrentPassword = !state.showCurrentPassword) } } - fun toggleShowNewPassword() = intent { reduce { state.copy(showNewPassword = !state.showNewPassword) } } - fun toggleShowCheckNewPassword() = intent { reduce { state.copy(showCheckNewPassword = !state.showCheckNewPassword) } } - fun popBackStack() = intent { postSideEffect(ResetPasswordSideEffect.PopBackStack) } - fun navigateFindPassword() = intent { postSideEffect(ResetPasswordSideEffect.NavigateFindPassword) } - fun navigateLogin() = intent { postSideEffect(ResetPasswordSideEffect.NavigateLogin) } -} diff --git a/presentation/myinfo/src/main/res/drawable/ic_my_info_comment.xml b/presentation/myinfo/src/main/res/drawable/ic_my_info_comment.xml deleted file mode 100644 index 0ca3c7910..000000000 --- a/presentation/myinfo/src/main/res/drawable/ic_my_info_comment.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/presentation/myinfo/src/main/res/drawable/ic_my_info_notice.xml b/presentation/myinfo/src/main/res/drawable/ic_my_info_notice.xml deleted file mode 100644 index 6592792f0..000000000 --- a/presentation/myinfo/src/main/res/drawable/ic_my_info_notice.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/presentation/myinfo/src/main/res/drawable/ic_my_info_point.xml b/presentation/myinfo/src/main/res/drawable/ic_my_info_point.xml deleted file mode 100644 index db5ee6c6c..000000000 --- a/presentation/myinfo/src/main/res/drawable/ic_my_info_point.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - diff --git a/presentation/myinfo/src/main/res/drawable/ic_my_info_setting.xml b/presentation/myinfo/src/main/res/drawable/ic_my_info_setting.xml deleted file mode 100644 index 376568e40..000000000 --- a/presentation/myinfo/src/main/res/drawable/ic_my_info_setting.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/presentation/myinfo/src/main/res/values/strings.xml b/presentation/myinfo/src/main/res/values/strings.xml deleted file mode 100644 index 824088dce..000000000 --- a/presentation/myinfo/src/main/res/values/strings.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - 내 포인트 - 이용제한 내역 - 피드백 전송 - 이용약관 - 개인정보처리방침 - 오픈소스 라이선스 - 공지사항 - 문의하기 - 계정관리 - MY - 서비스 - 로그인하세요 - 내 글과 포인트, 구매 내역을 확인해 보세요. - 내 글 관리 - 내 계정 - 로그인 아이디 - 학교 인증 메일 - 비밀번호 변경 - 로그아웃 - 회원 탈퇴 - 현재 비밀번호 - 현재 비밀번호를 입력하세요 - 새로운 비밀번호 - 새로운 비밀번호 확인 - 새로운 비밀번호를 입력하세요 - 변경하기 - 비밀번호가 변경되었습니다. - 새로운 비밀번호로 로그인 하시겠습니까? - 아이디를 입력하세요 - 비밀번호를 입력하세요 - 회원 탈퇴 되었어요 - 먼저 로그인 해주세요 - 포인트 현황 - 현재 포인트 - 작성한 강의평가(%d) - 작성한 시험정보(%d) - 시험정보 열람(%d) - 포인트 사용 내역 - %dp - +%dp - -%dp - 포인트는 강의평가 서비스 내에서만 이용됩니다. - 다른 계정으로 학교 인증 시 해당 계정으로 포인트가 합산 되며, 기존 포인트는 초기화 됩니다. - 포인트 획득을 위해 허위/중복/성의없는 정보를 작성 할 경우 서비스 이용이 제한 될 수 있습니다. - 허위 신고를 남용하는 이용자 또한 서비스 이용에 대한 제재가 가해질 수 있습니다. - 강의평 작성 : 10p 적립 - 시험정보 작성 : 20p 적립 - 신고 보상 : 1p 적립 - 시험정보 조회 : -20p - 강의평가/시험정보 삭제 : -30p - - 이용제한 내역이 없어요 - diff --git a/presentation/navigator/build.gradle.kts b/presentation/navigator/build.gradle.kts index 73e691666..767980955 100644 --- a/presentation/navigator/build.gradle.kts +++ b/presentation/navigator/build.gradle.kts @@ -8,13 +8,7 @@ android { } dependencies { - implementation(projects.domain.notice) - implementation(projects.presentation.lectureevaluation) - implementation(projects.presentation.login) - implementation(projects.presentation.myinfo) - implementation(projects.presentation.notice) implementation(projects.presentation.openmajor) - implementation(projects.presentation.signup) implementation(projects.presentation.timetable) } diff --git a/presentation/navigator/src/main/java/com/suwiki/presentation/navigator/MainNavigator.kt b/presentation/navigator/src/main/java/com/suwiki/presentation/navigator/MainNavigator.kt index da140c5ed..7eca87268 100644 --- a/presentation/navigator/src/main/java/com/suwiki/presentation/navigator/MainNavigator.kt +++ b/presentation/navigator/src/main/java/com/suwiki/presentation/navigator/MainNavigator.kt @@ -2,134 +2,21 @@ package com.suwiki.presentation.navigator import androidx.compose.runtime.Composable import androidx.compose.runtime.remember -import androidx.navigation.NavDestination -import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavHostController -import androidx.navigation.NavOptions -import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController -import androidx.navigation.navOptions -import com.suwiki.presentation.lectureevaluation.navigation.navigateExamEvaluationEditor -import com.suwiki.presentation.lectureevaluation.navigation.navigateLectureEvaluation -import com.suwiki.presentation.lectureevaluation.navigation.navigateLectureEvaluationDetail -import com.suwiki.presentation.lectureevaluation.navigation.navigateLectureEvaluationEditor -import com.suwiki.presentation.lectureevaluation.navigation.navigateMyEvaluation -import com.suwiki.presentation.login.navigation.navigateFindId -import com.suwiki.presentation.login.navigation.navigateFindPassword -import com.suwiki.presentation.login.navigation.navigateLogin -import com.suwiki.presentation.myinfo.navigation.navigateBanHistory -import com.suwiki.presentation.myinfo.navigation.navigateMyAccount -import com.suwiki.presentation.myinfo.navigation.navigateMyInfo -import com.suwiki.presentation.myinfo.navigation.navigateMyPoint -import com.suwiki.presentation.myinfo.navigation.navigateQuit -import com.suwiki.presentation.myinfo.navigation.navigateResetPassword -import com.suwiki.presentation.notice.navigation.navigateNotice -import com.suwiki.presentation.notice.navigation.navigateNoticeDetail import com.suwiki.presentation.openmajor.navigation.navigateOpenMajor -import com.suwiki.presentation.signup.navigation.navigateSignup -import com.suwiki.presentation.signup.navigation.navigateSignupComplete import com.suwiki.presentation.timetable.navigation.TimetableRoute import com.suwiki.presentation.timetable.navigation.argument.CellEditorArgument import com.suwiki.presentation.timetable.navigation.argument.TimetableEditorArgument import com.suwiki.presentation.timetable.navigation.navigateCellEditor import com.suwiki.presentation.timetable.navigation.navigateOpenLecture -import com.suwiki.presentation.timetable.navigation.navigateTimetable import com.suwiki.presentation.timetable.navigation.navigateTimetableEditor import com.suwiki.presentation.timetable.navigation.navigateTimetableList internal class MainNavigator( val navController: NavHostController, ) { - private val currentDestination: NavDestination? - @Composable get() = navController - .currentBackStackEntryAsState().value?.destination - - val startDestination = MainTab.TIMETABLE.route - - val currentTab: MainTab? - @Composable get() = currentDestination - ?.route - ?.let(MainTab::find) - - fun navigate(tab: MainTab) { - val navOptions = navOptions { - popUpTo(navController.graph.findStartDestination().id) { - saveState = true - } - launchSingleTop = true - restoreState = true - } - - when (tab) { - MainTab.TIMETABLE -> navController.navigateTimetable(navOptions) - MainTab.LECTURE_EVALUATION -> navController.navigateLectureEvaluation(navOptions) - MainTab.MY_INFO -> navController.navigateMyInfo(navOptions) - } - } - - fun navigateLogin(navOptions: NavOptions? = null) { - navController.navigateLogin(navOptions) - } - - fun navigateFindId() { - navController.navigateFindId() - } - - fun navigateFindPassword() { - navController.navigateFindPassword() - } - - fun navigateSignup() { - navController.navigateSignup() - } - - fun navigateSignupComplete() { - navController.navigateSignupComplete() - } - - fun navigateLectureEvaluationDetail(id: String) { - navController.navigateLectureEvaluationDetail(id) - } - - fun navigateMyAccount() { - navController.navigateMyAccount() - } - - fun navigateResetPassword() { - navController.navigateResetPassword() - } - - fun navigateQuit() { - navController.navigateQuit() - } - - fun navigateMyPoint() { - navController.navigateMyPoint() - } - - fun navigateBanHistory() { - navController.navigateBanHistory() - } - - fun navigateNotice() { - navController.navigateNotice() - } - - fun navigateNoticeDetail(noticeId: Long) { - navController.navigateNoticeDetail(noticeId) - } - - fun navigateMyEvaluation() { - navController.navigateMyEvaluation() - } - - fun navigateLectureEvaluationEditor(lectureEvaluation: String) { - navController.navigateLectureEvaluationEditor(lectureEvaluation) - } - - fun navigateExamEvaluationEditor(examEvaluation: String) { - navController.navigateExamEvaluationEditor(examEvaluation) - } + val startDestination = TimetableRoute.route fun navigateOpenMajor(selectedOpenMajor: String) { navController.navigateOpenMajor(selectedOpenMajor) @@ -160,11 +47,6 @@ internal class MainNavigator( private fun isSameCurrentDestination(route: String) = navController.currentDestination?.route == route - @Composable - fun shouldShowBottomBar(): Boolean { - val currentRoute = currentDestination?.route ?: return false - return currentRoute in MainTab - } } @Composable diff --git a/presentation/navigator/src/main/java/com/suwiki/presentation/navigator/MainScreen.kt b/presentation/navigator/src/main/java/com/suwiki/presentation/navigator/MainScreen.kt index 2ee57b3ee..f34e480b0 100644 --- a/presentation/navigator/src/main/java/com/suwiki/presentation/navigator/MainScreen.kt +++ b/presentation/navigator/src/main/java/com/suwiki/presentation/navigator/MainScreen.kt @@ -25,32 +25,15 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.IntOffset -import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.compose.NavHost -import androidx.navigation.navOptions import com.suwiki.presentation.common.designsystem.component.dialog.SuwikiDialog -import com.suwiki.presentation.common.designsystem.shadow.bottomNavigationShadow -import com.suwiki.presentation.common.designsystem.theme.GrayDA -import com.suwiki.presentation.common.designsystem.theme.Primary -import com.suwiki.presentation.common.designsystem.theme.White -import com.suwiki.presentation.common.ui.extension.suwikiClickable import com.suwiki.presentation.common.ui.extension.versionCode import com.suwiki.presentation.common.ui.util.PLAY_STORE_SITE -import com.suwiki.presentation.lectureevaluation.navigation.lectureEvaluationNavGraph -import com.suwiki.presentation.lectureevaluation.navigation.myEvaluationEditNavGraph -import com.suwiki.presentation.lectureevaluation.navigation.myEvaluationNavGraph -import com.suwiki.presentation.login.navigation.loginNavGraph -import com.suwiki.presentation.myinfo.navigation.myInfoNavGraph import com.suwiki.presentation.navigator.component.SuwikiToast -import com.suwiki.presentation.notice.navigation.noticeNavGraph import com.suwiki.presentation.openmajor.navigation.OpenMajorRoute import com.suwiki.presentation.openmajor.navigation.openMajorNavGraph -import com.suwiki.presentation.signup.navigation.signupNavGraph import com.suwiki.presentation.timetable.navigation.timetableNavGraph -import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.toImmutableList import org.orbitmvi.orbit.compose.collectAsState import org.orbitmvi.orbit.compose.collectSideEffect @@ -80,26 +63,6 @@ internal fun MainScreen( navController = navigator.navController, startDestination = navigator.startDestination, ) { - loginNavGraph( - popBackStack = navigator::popBackStackIfNotHome, - navigateFindId = navigator::navigateFindId, - navigateFindPassword = navigator::navigateFindPassword, - navigateSignup = navigator::navigateSignup, - handleException = viewModel::handleException, - ) - - signupNavGraph( - popBackStack = navigator::popBackStackIfNotHome, - handleException = viewModel::handleException, - navigateSignupComplete = navigator::navigateSignupComplete, - navigateLogin = { - navigator.navigateLogin( - navOptions { - popUpTo(navigator.startDestination) - }, - ) - }, - ) openMajorNavGraph( popBackStack = navigator::popBackStackIfNotHome, @@ -126,56 +89,6 @@ internal fun MainScreen( navigateOpenMajor = navigator::navigateOpenMajor, navigateCellEditor = navigator::navigateCellEditor, ) - - lectureEvaluationNavGraph( - padding = innerPadding, - argumentName = OpenMajorRoute.ARGUMENT_NAME, - popBackStack = navigator::popBackStackIfNotHome, - navigateLogin = navigator::navigateLogin, - navigateSignUp = navigator::navigateSignup, - navigateLectureEvaluationEditor = navigator::navigateLectureEvaluationEditor, - navigateExamEvaluationEditor = navigator::navigateExamEvaluationEditor, - handleException = viewModel::handleException, - navigateOpenMajor = navigator::navigateOpenMajor, - onShowToast = viewModel::onShowToast, - navigateLectureEvaluationDetail = navigator::navigateLectureEvaluationDetail, - ) - - myEvaluationNavGraph( - popBackStack = navigator::popBackStackIfNotHome, - navigateLectureEvaluationEditor = navigator::navigateLectureEvaluationEditor, - navigateExamEvaluationEditor = navigator::navigateExamEvaluationEditor, - handleException = viewModel::handleException, - ) - - myEvaluationEditNavGraph( - popBackStack = navigator::popBackStackIfNotHome, - onShowToast = viewModel::onShowToast, - handleException = viewModel::handleException, - ) - - myInfoNavGraph( - padding = innerPadding, - popBackStack = navigator::popBackStackIfNotHome, - navigateNotice = navigator::navigateNotice, - navigateMyEvaluation = navigator::navigateMyEvaluation, - navigateMyAccount = navigator::navigateMyAccount, - navigateResetPassword = navigator::navigateResetPassword, - navigateQuit = navigator::navigateQuit, - navigateFindPassword = navigator::navigateFindPassword, - navigateLogin = navigator::navigateLogin, - navigateMyPoint = navigator::navigateMyPoint, - navigateBanHistory = navigator::navigateBanHistory, - handleException = viewModel::handleException, - onShowToast = viewModel::onShowToast, - ) - - noticeNavGraph( - padding = innerPadding, - popBackStack = navigator::popBackStackIfNotHome, - navigateNoticeDetail = navigator::navigateNoticeDetail, - handleException = viewModel::handleException, - ) } if (uiState.showNetworkErrorDialog) { @@ -203,76 +116,5 @@ internal fun MainScreen( message = uiState.toastMessage, ) }, - bottomBar = { - MainBottomBar( - visible = navigator.shouldShowBottomBar(), - tabs = MainTab.entries.toImmutableList(), - currentTab = navigator.currentTab, - onTabSelected = navigator::navigate, - ) - }, ) } - -@Composable -private fun MainBottomBar( - visible: Boolean, - tabs: ImmutableList, - currentTab: MainTab?, - onTabSelected: (MainTab) -> Unit, -) { - AnimatedVisibility( - visible = visible, - enter = fadeIn() + slideIn { IntOffset(0, it.height) }, - exit = fadeOut() + slideOut { IntOffset(0, it.height) }, - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .height(56.dp) - .bottomNavigationShadow() - .background( - color = White, - shape = RoundedCornerShape(topStart = 10.dp, topEnd = 10.dp), - ), - horizontalArrangement = Arrangement.spacedBy(8.dp), - ) { - tabs.forEach { tab -> - MainBottomBarItem( - tab = tab, - selected = tab == currentTab, - onClick = { onTabSelected(tab) }, - ) - } - } - } -} - -@Composable -private fun RowScope.MainBottomBarItem( - tab: MainTab, - selected: Boolean, - onClick: () -> Unit, -) { - Box( - modifier = Modifier - .weight(1f) - .fillMaxHeight() - .suwikiClickable( - rippleEnabled = false, - onClick = onClick, - ), - contentAlignment = Alignment.Center, - ) { - Icon( - painter = painterResource(tab.iconResId), - contentDescription = tab.contentDescription, - tint = if (selected) { - Primary - } else { - GrayDA - }, - modifier = Modifier.size(24.dp), - ) - } -} diff --git a/presentation/navigator/src/main/java/com/suwiki/presentation/navigator/MainTab.kt b/presentation/navigator/src/main/java/com/suwiki/presentation/navigator/MainTab.kt deleted file mode 100644 index a32d77432..000000000 --- a/presentation/navigator/src/main/java/com/suwiki/presentation/navigator/MainTab.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.suwiki.presentation.navigator - -import com.suwiki.presentation.lectureevaluation.navigation.LectureEvaluationRoute -import com.suwiki.presentation.myinfo.navigation.MyInfoRoute -import com.suwiki.presentation.timetable.navigation.TimetableRoute - -internal enum class MainTab( - val iconResId: Int, - internal val contentDescription: String, - val route: String, -) { - TIMETABLE( - iconResId = R.drawable.ic_bottom_navigation_timetable, - contentDescription = "시간표", - route = TimetableRoute.route, - ), - LECTURE_EVALUATION( - iconResId = R.drawable.ic_bottom_navigation_evaluation, - contentDescription = "강의평가", - route = LectureEvaluationRoute.route, - ), - MY_INFO( - iconResId = R.drawable.ic_bottom_navigation_myinfo, - contentDescription = "내 정보", - route = MyInfoRoute.route, - ), - ; - - companion object { - operator fun contains(route: String): Boolean { - return entries.map { it.route }.contains(route) - } - - fun find(route: String): MainTab? { - return entries.find { it.route == route } - } - } -} diff --git a/presentation/navigator/src/main/java/com/suwiki/presentation/navigator/MainViewModel.kt b/presentation/navigator/src/main/java/com/suwiki/presentation/navigator/MainViewModel.kt index 9306c1d22..07120ac23 100644 --- a/presentation/navigator/src/main/java/com/suwiki/presentation/navigator/MainViewModel.kt +++ b/presentation/navigator/src/main/java/com/suwiki/presentation/navigator/MainViewModel.kt @@ -4,7 +4,6 @@ import androidx.lifecycle.ViewModel import com.suwiki.common.android.recordException import com.suwiki.common.model.exception.NetworkException import com.suwiki.common.model.exception.UnknownException -import com.suwiki.domain.notice.usecase.CheckUpdateMandatoryUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.delay import kotlinx.coroutines.sync.Mutex @@ -19,9 +18,7 @@ import java.net.ConnectException import javax.inject.Inject @HiltViewModel -class MainViewModel @Inject constructor( - private val checkUpdateMandatoryUseCase: CheckUpdateMandatoryUseCase, -) : ContainerHost, ViewModel() { +class MainViewModel @Inject constructor() : ContainerHost, ViewModel() { override val container: Container = container(MainState()) private val mutex = Mutex() @@ -29,10 +26,8 @@ class MainViewModel @Inject constructor( fun checkUpdateMandatory(versionCode: Long) = intent { if (isFirstVisit.not()) return@intent - checkUpdateMandatoryUseCase(versionCode) - .onSuccess { updateMandatory -> - reduce { state.copy(showUpdateMandatoryDialog = updateMandatory) } - } + // 앱 버전 확인 하는 동작 수행 + // 최신 아닌 경우 업데이트 팝업 띄우는 상태 업데이트 isFirstVisit = true } diff --git a/presentation/notice/.gitignore b/presentation/notice/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/presentation/notice/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/presentation/notice/build.gradle.kts b/presentation/notice/build.gradle.kts deleted file mode 100644 index fb7517f44..000000000 --- a/presentation/notice/build.gradle.kts +++ /dev/null @@ -1,12 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.presentation.compose) -} - -android { - namespace = "com.suwiki.presentation.notice" -} - -dependencies { - implementation(projects.domain.notice) -} diff --git a/presentation/notice/consumer-rules.pro b/presentation/notice/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/presentation/notice/proguard-rules.pro b/presentation/notice/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/presentation/notice/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/presentation/notice/src/main/AndroidManifest.xml b/presentation/notice/src/main/AndroidManifest.xml deleted file mode 100644 index 8bdb7e14b..000000000 --- a/presentation/notice/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/presentation/notice/src/main/java/com/suwiki/presentation/notice/NoticeContract.kt b/presentation/notice/src/main/java/com/suwiki/presentation/notice/NoticeContract.kt deleted file mode 100644 index d104488b8..000000000 --- a/presentation/notice/src/main/java/com/suwiki/presentation/notice/NoticeContract.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.suwiki.presentation.notice - -import com.suwiki.common.model.notice.Notice -import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.persistentListOf - -data class NoticeState( - val isLoading: Boolean = false, - val noticeList: PersistentList = persistentListOf(), -) - -sealed interface NoticeSideEffect { - data class NavigateNoticeDetail(val noticeId: Long) : NoticeSideEffect - data object PopBackStack : NoticeSideEffect - data class HandleException(val exception: Throwable) : NoticeSideEffect -} diff --git a/presentation/notice/src/main/java/com/suwiki/presentation/notice/NoticeScreen.kt b/presentation/notice/src/main/java/com/suwiki/presentation/notice/NoticeScreen.kt deleted file mode 100644 index 564c69779..000000000 --- a/presentation/notice/src/main/java/com/suwiki/presentation/notice/NoticeScreen.kt +++ /dev/null @@ -1,114 +0,0 @@ -package com.suwiki.presentation.notice - -import android.annotation.SuppressLint -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.common.model.notice.Notice -import com.suwiki.presentation.common.designsystem.component.appbar.SuwikiAppBarWithTitle -import com.suwiki.presentation.common.designsystem.component.container.SuwikiBoardContainer -import com.suwiki.presentation.common.designsystem.component.loading.LoadingScreen -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.toPersistentList -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect -import java.time.LocalDateTime - -@Composable -fun NoticeRoute( - padding: PaddingValues, - viewModel: NoticeViewModel = hiltViewModel(), - navigateNoticeDetail: (Long) -> Unit, - popBackStack: () -> Unit, - handleException: (Throwable) -> Unit, -) { - val uiState = viewModel.collectAsState().value - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - is NoticeSideEffect.NavigateNoticeDetail -> navigateNoticeDetail(sideEffect.noticeId) - NoticeSideEffect.PopBackStack -> popBackStack() - is NoticeSideEffect.HandleException -> handleException(sideEffect.exception) - } - } - - LaunchedEffect(key1 = viewModel) { - viewModel.loadNoticeList() - } - - NoticeScreen( - padding = padding, - noticeList = uiState.noticeList, - uiState = uiState, - navigateNoticeDetail = viewModel::navigateNoticeDetail, - popBackStack = viewModel::popBackStack, - ) -} - -@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") -@Composable -fun NoticeScreen( - padding: PaddingValues, - noticeList: PersistentList, - uiState: NoticeState, - navigateNoticeDetail: (Long) -> Unit, - popBackStack: () -> Unit, -) { - Column( - modifier = Modifier - .padding(padding) - .fillMaxSize() - .background(White), - ) { - SuwikiAppBarWithTitle( - title = stringResource(R.string.notice), - onClickBack = popBackStack, - showBackIcon = true, - showCloseIcon = false, - ) - LazyColumn { - items(items = noticeList, key = { it.id }) { notice -> - SuwikiBoardContainer( - titleText = notice.title, - dateText = notice.date.toString(), - onClick = { navigateNoticeDetail(notice.id) }, - ) - } - } - if (uiState.isLoading) { - LoadingScreen() - } - } -} - -@Preview -@Composable -fun NoticeScreenPreview() { - val sampleNoticeList = listOf( - Notice(id = 1, title = "회원가입 필독", date = LocalDateTime.now()), - Notice(id = 2, title = "2023년 04월 17일 데이터베이스 문제", date = LocalDateTime.now()), - Notice(id = 3, title = "개인정보 처리방침 개정 안내", date = LocalDateTime.now()), - Notice(id = 4, title = "아이폰 유저 시간표 반영 주의사항", date = LocalDateTime.now()), - ) - SuwikiTheme { - NoticeScreen( - padding = PaddingValues(0.dp), - uiState = NoticeState(false), - noticeList = sampleNoticeList.toPersistentList(), - navigateNoticeDetail = {}, - popBackStack = {}, - ) - } -} diff --git a/presentation/notice/src/main/java/com/suwiki/presentation/notice/NoticeViewModel.kt b/presentation/notice/src/main/java/com/suwiki/presentation/notice/NoticeViewModel.kt deleted file mode 100644 index 092a2c1e8..000000000 --- a/presentation/notice/src/main/java/com/suwiki/presentation/notice/NoticeViewModel.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.suwiki.presentation.notice - -import androidx.lifecycle.ViewModel -import com.suwiki.domain.notice.usecase.GetNoticeListUseCase -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.collections.immutable.toPersistentList -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class NoticeViewModel @Inject constructor( - private val getNoticeListUseCase: GetNoticeListUseCase, -) : ContainerHost, ViewModel() { - - override val container: Container = container(NoticeState()) - - fun loadNoticeList() = intent { - showLoadingScreen() - getNoticeListUseCase(1) - .onSuccess { notices -> - reduce { state.copy(noticeList = notices.toPersistentList()) } - } - .onFailure { - postSideEffect(NoticeSideEffect.HandleException(it)) - } - hideLoadingScreen() - } - - private fun showLoadingScreen() = intent { reduce { state.copy(isLoading = true) } } - private fun hideLoadingScreen() = intent { reduce { state.copy(isLoading = false) } } - fun navigateNoticeDetail(noticeId: Long) = intent { postSideEffect(NoticeSideEffect.NavigateNoticeDetail(noticeId)) } - fun popBackStack() = intent { postSideEffect(NoticeSideEffect.PopBackStack) } -} diff --git a/presentation/notice/src/main/java/com/suwiki/presentation/notice/detail/NoticeDetailContract.kt b/presentation/notice/src/main/java/com/suwiki/presentation/notice/detail/NoticeDetailContract.kt deleted file mode 100644 index 5cbc57247..000000000 --- a/presentation/notice/src/main/java/com/suwiki/presentation/notice/detail/NoticeDetailContract.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.suwiki.presentation.notice.detail - -import com.suwiki.common.model.notice.NoticeDetail - -data class NoticeDetailState( - val isLoading: Boolean = false, - val noticeDetail: NoticeDetail = NoticeDetail(), -) - -sealed interface NoticeDetailSideEffect { - data object PopBackStack : NoticeDetailSideEffect - data class HandleException(val exception: Throwable) : NoticeDetailSideEffect -} diff --git a/presentation/notice/src/main/java/com/suwiki/presentation/notice/detail/NoticeDetailScreen.kt b/presentation/notice/src/main/java/com/suwiki/presentation/notice/detail/NoticeDetailScreen.kt deleted file mode 100644 index 9f5828151..000000000 --- a/presentation/notice/src/main/java/com/suwiki/presentation/notice/detail/NoticeDetailScreen.kt +++ /dev/null @@ -1,153 +0,0 @@ -package com.suwiki.presentation.notice.detail - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.common.model.notice.NoticeDetail -import com.suwiki.presentation.common.designsystem.component.appbar.SuwikiAppBarWithTitle -import com.suwiki.presentation.common.designsystem.component.loading.LoadingScreen -import com.suwiki.presentation.common.designsystem.theme.Black -import com.suwiki.presentation.common.designsystem.theme.Gray95 -import com.suwiki.presentation.common.designsystem.theme.GrayF6 -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.designsystem.theme.White -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect -import java.time.LocalDateTime - -@Composable -fun NoticeDetailRoute( - padding: PaddingValues, - viewModel: NoticeDetailViewModel = hiltViewModel(), - popBackStack: () -> Unit = {}, - handleException: (Throwable) -> Unit, -) { - val uiState = viewModel.collectAsState().value - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - NoticeDetailSideEffect.PopBackStack -> popBackStack() - is NoticeDetailSideEffect.HandleException -> handleException(sideEffect.exception) - } - } - - LaunchedEffect(key1 = viewModel) { - viewModel.loadNoticeDetail() - } - - NoticeDetailScreen( - padding = padding, - uiState = uiState, - popBackStack = viewModel::popBackStack, - ) -} - -@Composable -fun NoticeDetailScreen( - padding: PaddingValues, - uiState: NoticeDetailState, - popBackStack: () -> Unit, -) { - Column( - modifier = Modifier - .padding(padding) - .background(White) - .fillMaxSize(), - ) { - SuwikiAppBarWithTitle( - title = "", - onClickBack = popBackStack, - showBackIcon = true, - showCloseIcon = false, - ) - - Column { - NoticeDetailTitleContainer( - title = uiState.noticeDetail.title, - date = uiState.noticeDetail.date?.toString() ?: "", - ) - HorizontalDivider( - thickness = 4.dp, - color = GrayF6, - ) - Spacer(modifier = Modifier.height(24.dp)) - Text( - modifier = Modifier - .padding(24.dp), - text = uiState.noticeDetail.content, - style = SuwikiTheme.typography.body7, - ) - } - } - if (uiState.isLoading) { - LoadingScreen() - } -} - -@Composable -private fun NoticeDetailTitleContainer( - modifier: Modifier = Modifier, - title: String = "", - date: String = "", -) { - Column( - modifier = modifier - .fillMaxWidth() - .background(White) - .padding(24.dp, 15.dp), - ) { - Text( - text = title, - style = SuwikiTheme.typography.header6, - color = Black, - ) - Spacer(modifier = Modifier.height(2.dp)) - Text( - text = date, - style = SuwikiTheme.typography.caption6, - color = Gray95, - ) - } -} - -@Preview -@Composable -fun NoticeDetailScreenPreview() { - val sampleNoticeDetail = NoticeDetail( - title = "2023년 04월 17일 데이터베이스 문제", - date = LocalDateTime.now(), - content = "데이터 베이스의 불문명현 원인으로 인해 특정 되돌리는 풀백을 수행했습니다. \n" + - "\n" + - "이로 인해 회원가입을 진행해주셨으나 회원가입 처리가 \n" + - "되어있지 않는 현상 및 \n" + - "강의평가 시험정보 작성을 하였으나 등록되지 않는 \n" + - "경우가 발생할 수 있습니다\n" + - "\n" + - "양해부탁드립니다. \n" + - "\n" + - "감사합니다.", - ) - SuwikiTheme { - NoticeDetailScreen( - padding = PaddingValues(0.dp), - uiState = NoticeDetailState( - isLoading = false, - noticeDetail = - sampleNoticeDetail, - ), - popBackStack = {}, - ) - } -} diff --git a/presentation/notice/src/main/java/com/suwiki/presentation/notice/detail/NoticeDetailViewModel.kt b/presentation/notice/src/main/java/com/suwiki/presentation/notice/detail/NoticeDetailViewModel.kt deleted file mode 100644 index 3aad96bb8..000000000 --- a/presentation/notice/src/main/java/com/suwiki/presentation/notice/detail/NoticeDetailViewModel.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.suwiki.presentation.notice.detail - -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel -import com.suwiki.domain.notice.usecase.GetNoticeDetailUseCase -import com.suwiki.presentation.notice.navigation.NoticeRoute -import dagger.hilt.android.lifecycle.HiltViewModel -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class NoticeDetailViewModel @Inject constructor( - private val getNoticeDetailUseCase: GetNoticeDetailUseCase, - savedStateHandle: SavedStateHandle, -) : ContainerHost, ViewModel() { - override val container: Container = container(NoticeDetailState()) - - private val noticeId: Long = savedStateHandle.get(NoticeRoute.DETAIL_ARGUMENT_NAME)!!.toLong() - - fun loadNoticeDetail() = intent { - showLoadingScreen() - getNoticeDetailUseCase(noticeId) - .onSuccess { noticeDetail -> - reduce { state.copy(noticeDetail = noticeDetail) } - } - .onFailure { - postSideEffect(NoticeDetailSideEffect.HandleException(it)) - } - hideLoadingScreen() - } - - private fun showLoadingScreen() = intent { reduce { state.copy(isLoading = true) } } - private fun hideLoadingScreen() = intent { reduce { state.copy(isLoading = false) } } - fun popBackStack() = intent { postSideEffect(NoticeDetailSideEffect.PopBackStack) } -} diff --git a/presentation/notice/src/main/java/com/suwiki/presentation/notice/navigation/NoticeNavigation.kt b/presentation/notice/src/main/java/com/suwiki/presentation/notice/navigation/NoticeNavigation.kt deleted file mode 100644 index d141205bb..000000000 --- a/presentation/notice/src/main/java/com/suwiki/presentation/notice/navigation/NoticeNavigation.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.suwiki.presentation.notice.navigation - -import androidx.compose.foundation.layout.PaddingValues -import androidx.navigation.NavController -import androidx.navigation.NavGraphBuilder -import androidx.navigation.NavType -import androidx.navigation.compose.composable -import androidx.navigation.navArgument -import com.suwiki.presentation.notice.NoticeRoute -import com.suwiki.presentation.notice.detail.NoticeDetailRoute - -fun NavController.navigateNotice() { - navigate(NoticeRoute.route) -} - -fun NavController.navigateNoticeDetail(noticeId: Long) { - navigate(NoticeRoute.detailRoute(noticeId.toString())) -} - -fun NavGraphBuilder.noticeNavGraph( - padding: PaddingValues, - popBackStack: () -> Unit = {}, - navigateNoticeDetail: (Long) -> Unit = {}, - handleException: (Throwable) -> Unit, -) { - composable(route = NoticeRoute.route) { - NoticeRoute( - padding = padding, - navigateNoticeDetail = navigateNoticeDetail, - popBackStack = popBackStack, - handleException = handleException, - ) - } - composable( - route = NoticeRoute.detailRoute("{${NoticeRoute.DETAIL_ARGUMENT_NAME}}"), - arguments = listOf( - navArgument(NoticeRoute.DETAIL_ARGUMENT_NAME) { - type = NavType.StringType - }, - ), - ) { - NoticeDetailRoute( - padding = padding, - popBackStack = popBackStack, - handleException = handleException, - ) - } -} - -object NoticeRoute { - const val route = "notice" - const val DETAIL_ARGUMENT_NAME = "noticeId" - - fun detailRoute(noticeId: String) = "notice/detail/$noticeId" -} diff --git a/presentation/notice/src/main/res/values/strings.xml b/presentation/notice/src/main/res/values/strings.xml deleted file mode 100644 index 17ab86898..000000000 --- a/presentation/notice/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - 공지사항 - diff --git a/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/OpenMajorContract.kt b/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/OpenMajorContract.kt index d61cb5401..c817e0e26 100644 --- a/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/OpenMajorContract.kt +++ b/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/OpenMajorContract.kt @@ -13,8 +13,6 @@ data class OpenMajorState( val isLoading: Boolean = false, ) { val showAllOpenMajorEmptySearchResultScreen: Boolean = searchValue.isNotEmpty() && filteredAllOpenMajorList.isEmpty() - val showBookmarkedOpenMajorSearchEmptyResultScreen: Boolean = searchValue.isNotEmpty() && filteredBookmarkedOpenMajorList.isEmpty() - val showBookmarkedOpenMajorEmptyScreen: Boolean = searchValue.isEmpty() && filteredBookmarkedOpenMajorList.isEmpty() } sealed interface OpenMajorSideEffect { diff --git a/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/OpenMajorScreen.kt b/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/OpenMajorScreen.kt index 8020d5ba6..4ede857ec 100644 --- a/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/OpenMajorScreen.kt +++ b/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/OpenMajorScreen.kt @@ -85,7 +85,6 @@ fun OpenMajorRoute( } val allOpenMajorListState = rememberLazyListState() - val bookmarkedOpenMajorListState = rememberLazyListState() val onReachedBottomAllOpenMajor by remember { derivedStateOf { @@ -93,20 +92,11 @@ fun OpenMajorRoute( } } - val onReachedBottomBookmarkedOpenMajor by remember { - derivedStateOf { - bookmarkedOpenMajorListState.isScrolledToEnd() - } - } LaunchedEffect(onReachedBottomAllOpenMajor) { viewModel.changeBottomShadowVisible(!onReachedBottomAllOpenMajor) } - LaunchedEffect(onReachedBottomBookmarkedOpenMajor) { - viewModel.changeBottomShadowVisible(!onReachedBottomBookmarkedOpenMajor) - } - LaunchedEffect(key1 = Unit) { viewModel.initData() } @@ -115,11 +105,9 @@ fun OpenMajorRoute( uiState = uiState, pagerState = pagerState, allOpenMajorListState = allOpenMajorListState, - bookmarkedOpenMajorListState = bookmarkedOpenMajorListState, onClickClose = viewModel::popBackStack, onClickConfirmButton = viewModel::popBackStackWithArgument, onClickOpenMajorContainer = viewModel::updateSelectedOpenMajor, - onClickOpenMajorBookmark = viewModel::toggleBookmark, onClickTab = viewModel::syncPagerState, onValueChangeSearchBar = viewModel::updateSearchValue, onClickSearchBarClearButton = { viewModel.updateSearchValue("") }, @@ -132,11 +120,9 @@ fun OpenMajorScreen( uiState: OpenMajorState = OpenMajorState(), pagerState: PagerState = rememberPagerState(pageCount = { OPEN_MAJOR_PAGE_COUNT }), allOpenMajorListState: LazyListState = rememberLazyListState(), - bookmarkedOpenMajorListState: LazyListState = rememberLazyListState(), onClickClose: () -> Unit = {}, onClickConfirmButton: () -> Unit = {}, onClickOpenMajorContainer: (String) -> Unit = {}, - onClickOpenMajorBookmark: (String) -> Unit = {}, onValueChangeSearchBar: (String) -> Unit = {}, onClickSearchBarClearButton: () -> Unit = {}, onClickTab: (Int) -> Unit = {}, @@ -189,22 +175,6 @@ fun OpenMajorScreen( listState = allOpenMajorListState, openMajorList = uiState.filteredAllOpenMajorList, onClickOpenMajorContainer = onClickOpenMajorContainer, - onClickOpenMajorBookmark = onClickOpenMajorBookmark, - ) - } - } - - OpenMajorTap.BOOKMARK -> { - if (uiState.showBookmarkedOpenMajorSearchEmptyResultScreen) { - EmptyText(stringResource(R.string.open_major_empty_search_result)) - } else if (uiState.showBookmarkedOpenMajorEmptyScreen) { - EmptyText(stringResource(R.string.open_major_empty_bookmark)) - } else { - OpenMajorLazyColumn( - listState = bookmarkedOpenMajorListState, - openMajorList = uiState.filteredBookmarkedOpenMajorList, - onClickOpenMajorContainer = onClickOpenMajorContainer, - onClickOpenMajorBookmark = onClickOpenMajorBookmark, ) } } @@ -252,7 +222,6 @@ private fun OpenMajorLazyColumn( listState: LazyListState, openMajorList: PersistentList, onClickOpenMajorContainer: (String) -> Unit = {}, - onClickOpenMajorBookmark: (String) -> Unit = {}, ) { LazyColumn( modifier = Modifier.fillMaxSize(), @@ -267,9 +236,7 @@ private fun OpenMajorLazyColumn( OpenMajorContainer( text = name, isChecked = isSelected, - isStared = isBookmarked, onClick = { onClickOpenMajorContainer(name) }, - onClickStar = { onClickOpenMajorBookmark(name) }, ) } } diff --git a/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/OpenMajorViewModel.kt b/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/OpenMajorViewModel.kt index c537507a3..9a4961c2e 100644 --- a/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/OpenMajorViewModel.kt +++ b/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/OpenMajorViewModel.kt @@ -87,10 +87,6 @@ class OpenMajorViewModel @Inject constructor( } fun syncPagerState(currentPage: Int) = intent { - if (isLoggedIn.not() && currentPage == OpenMajorTap.BOOKMARK.position) { - postSideEffect(OpenMajorSideEffect.ShowNeedLoginToast) - return@intent - } reduce { state.copy(currentPage = currentPage) } } @@ -120,7 +116,6 @@ class OpenMajorViewModel @Inject constructor( allOpenMajorList.addAll(it) reduceOpenMajorList() }.catch { - postSideEffect(OpenMajorSideEffect.HandleException(it)) }.launchIn(viewModelScope) } @@ -147,7 +142,6 @@ class OpenMajorViewModel @Inject constructor( if (it is AuthorizationException) { isLoggedIn = false } else { - postSideEffect(OpenMajorSideEffect.HandleException(it)) } } } diff --git a/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/component/OpenMajorContainer.kt b/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/component/OpenMajorContainer.kt index b1c4d31ca..4c9999f28 100644 --- a/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/component/OpenMajorContainer.kt +++ b/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/component/OpenMajorContainer.kt @@ -34,9 +34,7 @@ fun OpenMajorContainer( modifier: Modifier = Modifier, text: String, isChecked: Boolean, - isStared: Boolean, onClick: () -> Unit = {}, - onClickStar: () -> Unit = {}, ) { val (textColor, backgroundColor) = if (isChecked) { Primary to Blue5 @@ -56,18 +54,6 @@ fun OpenMajorContainer( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Start, ) { - Icon( - painter = painterResource(id = R.drawable.ic_filter_stared), - contentDescription = "", - modifier = Modifier - .size(24.dp) - .suwikiClickable( - onClick = onClickStar, - rippleEnabled = false, - ), - tint = if (isStared) Primary else GrayDA, - ) - Spacer(modifier = Modifier.width(4.dp)) Text( text = text, style = SuwikiTheme.typography.body2, @@ -80,15 +66,12 @@ fun OpenMajorContainer( @Composable fun OpenMajorContainerPreview() { var isChecked by remember { mutableStateOf(false) } - var isStared by remember { mutableStateOf(false) } SuwikiTheme { OpenMajorContainer( text = "개설학과명", isChecked = isChecked, - isStared = isStared, onClick = { isChecked = !isChecked }, - onClickStar = { isStared = !isStared }, ) } } diff --git a/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/model/OpenMajorTap.kt b/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/model/OpenMajorTap.kt index a62886e31..ec370d2b5 100644 --- a/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/model/OpenMajorTap.kt +++ b/presentation/openmajor/src/main/java/com/suwiki/presentation/openmajor/model/OpenMajorTap.kt @@ -11,8 +11,4 @@ enum class OpenMajorTap( position = 0, titleId = R.string.word_all, ), - BOOKMARK( - position = 1, - titleId = R.string.word_bookmark, - ), } diff --git a/presentation/signup/.gitignore b/presentation/signup/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/presentation/signup/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/presentation/signup/build.gradle.kts b/presentation/signup/build.gradle.kts deleted file mode 100644 index 54ead4d4d..000000000 --- a/presentation/signup/build.gradle.kts +++ /dev/null @@ -1,12 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.presentation.compose) -} - -android { - namespace = "com.suwiki.presentation.signup" -} - -dependencies { - implementation(projects.domain.signup) -} diff --git a/presentation/signup/consumer-rules.pro b/presentation/signup/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/presentation/signup/proguard-rules.pro b/presentation/signup/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/presentation/signup/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/presentation/signup/src/main/AndroidManifest.xml b/presentation/signup/src/main/AndroidManifest.xml deleted file mode 100644 index 8bdb7e14b..000000000 --- a/presentation/signup/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/presentation/signup/src/main/java/com/suwiki/presentation/signup/complete/SignupCompleteContract.kt b/presentation/signup/src/main/java/com/suwiki/presentation/signup/complete/SignupCompleteContract.kt deleted file mode 100644 index a6da81cb3..000000000 --- a/presentation/signup/src/main/java/com/suwiki/presentation/signup/complete/SignupCompleteContract.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.suwiki.presentation.signup.complete - -sealed interface SignupCompleteState { - data object Default : SignupCompleteState -} - -sealed interface SignupCompleteSideEffect { - data object OpenSchoolWebSite : SignupCompleteSideEffect - data object NavigateLogin : SignupCompleteSideEffect -} diff --git a/presentation/signup/src/main/java/com/suwiki/presentation/signup/complete/SignupCompleteScreen.kt b/presentation/signup/src/main/java/com/suwiki/presentation/signup/complete/SignupCompleteScreen.kt deleted file mode 100644 index a9525f51d..000000000 --- a/presentation/signup/src/main/java/com/suwiki/presentation/signup/complete/SignupCompleteScreen.kt +++ /dev/null @@ -1,106 +0,0 @@ -package com.suwiki.presentation.SignupComplete.complete - -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.presentation.common.designsystem.component.button.SuwikiContainedLargeButton -import com.suwiki.presentation.common.designsystem.component.button.SuwikiOutlinedButton -import com.suwiki.presentation.common.designsystem.theme.Gray6A -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.ui.util.SCHOOL_HOMEPAGE -import com.suwiki.presentation.signup.R -import com.suwiki.presentation.signup.complete.SignupCompleteSideEffect -import org.orbitmvi.orbit.compose.collectSideEffect - -@Composable -fun SignupCompleteRoute( - viewModel: SignupCompleteViewModel = hiltViewModel(), - navigateLogin: () -> Unit, -) { - val uriHandler = LocalUriHandler.current - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - SignupCompleteSideEffect.NavigateLogin -> navigateLogin() - SignupCompleteSideEffect.OpenSchoolWebSite -> uriHandler.openUri(SCHOOL_HOMEPAGE) - } - } - - SignupCompleteScreen( - onClickConfirmEmailButton = viewModel::openSchoolWebsite, - onClickLoginButton = viewModel::navigateLogin, - ) -} - -@Composable -fun SignupCompleteScreen( - onClickConfirmEmailButton: () -> Unit = {}, - onClickLoginButton: () -> Unit = {}, -) { - Column( - modifier = Modifier - .padding( - top = 63.dp, - start = 24.dp, - end = 24.dp, - bottom = 107.dp, - ) - .fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Text( - text = "메일로 인증 링크를\n보냈습니다!", - textAlign = TextAlign.Center, - style = SuwikiTheme.typography.header1, - ) - - Spacer(modifier = Modifier.size(34.dp)) - - Image( - modifier = Modifier.size(180.dp), - painter = painterResource(id = R.drawable.ic_signup_complete), - contentDescription = null, - ) - - Spacer(modifier = Modifier.size(22.dp)) - - Text(text = "가입 완료를 위해 이메일을 확인하세요", style = SuwikiTheme.typography.header2) - - Spacer(modifier = Modifier.size(6.dp)) - - Text( - text = "인증 링크를 확인하지 않으면\n서비스 이용이 불가능합니다!", - style = SuwikiTheme.typography.header7, - color = Gray6A, - textAlign = TextAlign.Center, - ) - - Spacer(modifier = Modifier.weight(1f)) - - SuwikiContainedLargeButton(text = "이메일 확인하기", onClick = onClickConfirmEmailButton) - - Spacer(modifier = Modifier.size(12.dp)) - - SuwikiOutlinedButton(text = "로그인", onClick = onClickLoginButton) - } -} - -@Preview(showBackground = true) -@Composable -fun SignupCompleteScreenPreview() { - SuwikiTheme { - SignupCompleteScreen() - } -} diff --git a/presentation/signup/src/main/java/com/suwiki/presentation/signup/complete/SignupCompleteViewModel.kt b/presentation/signup/src/main/java/com/suwiki/presentation/signup/complete/SignupCompleteViewModel.kt deleted file mode 100644 index d5bec5881..000000000 --- a/presentation/signup/src/main/java/com/suwiki/presentation/signup/complete/SignupCompleteViewModel.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.suwiki.presentation.SignupComplete.complete - -import androidx.lifecycle.ViewModel -import com.suwiki.presentation.signup.complete.SignupCompleteSideEffect -import com.suwiki.presentation.signup.complete.SignupCompleteState -import dagger.hilt.android.lifecycle.HiltViewModel -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class SignupCompleteViewModel @Inject constructor() : ContainerHost, ViewModel() { - - override val container: Container = container( - SignupCompleteState.Default, - ) - - fun navigateLogin() = intent { postSideEffect(SignupCompleteSideEffect.NavigateLogin) } - fun openSchoolWebsite() = intent { postSideEffect(SignupCompleteSideEffect.OpenSchoolWebSite) } -} diff --git a/presentation/signup/src/main/java/com/suwiki/presentation/signup/navigation/SignupNavigation.kt b/presentation/signup/src/main/java/com/suwiki/presentation/signup/navigation/SignupNavigation.kt deleted file mode 100644 index 384974091..000000000 --- a/presentation/signup/src/main/java/com/suwiki/presentation/signup/navigation/SignupNavigation.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.suwiki.presentation.signup.navigation - -import androidx.navigation.NavController -import androidx.navigation.NavGraphBuilder -import androidx.navigation.compose.composable -import androidx.navigation.navOptions -import com.suwiki.presentation.SignupComplete.complete.SignupCompleteRoute -import com.suwiki.presentation.signup.signup.SignupRoute - -fun NavController.navigateSignup() { - navigate(SignupRoute.route) -} - -fun NavController.navigateSignupComplete() { - val navOptions = navOptions { - popUpTo(SignupRoute.route) { - inclusive = true - } - } - - navigate( - route = SignupRoute.completeRoute, - navOptions = navOptions, - ) -} - -fun NavGraphBuilder.signupNavGraph( - popBackStack: () -> Unit, - navigateSignupComplete: () -> Unit, - navigateLogin: () -> Unit, - handleException: (Throwable) -> Unit, -) { - composable(route = SignupRoute.route) { - SignupRoute( - popBackStack = popBackStack, - navigateSignupComplete = navigateSignupComplete, - handleException = handleException, - ) - } - - composable(route = SignupRoute.completeRoute) { - SignupCompleteRoute( - navigateLogin = navigateLogin, - ) - } -} - -object SignupRoute { - const val route = "signup" - const val completeRoute = "signup-complete" -} diff --git a/presentation/signup/src/main/java/com/suwiki/presentation/signup/signup/SignupContract.kt b/presentation/signup/src/main/java/com/suwiki/presentation/signup/signup/SignupContract.kt deleted file mode 100644 index f2ed90a66..000000000 --- a/presentation/signup/src/main/java/com/suwiki/presentation/signup/signup/SignupContract.kt +++ /dev/null @@ -1,86 +0,0 @@ -package com.suwiki.presentation.signup.signup - -import com.suwiki.presentation.signup.R - -data class SignupState( - val idState: IdState = IdState(), - val passwordState: PasswordState = PasswordState(), - val emailState: EmailState = EmailState(), - val isLoading: Boolean = false, -) { - val titleResId = when { - emailState.showEmailTextField -> R.string.signup_screen_title_email - passwordState.showPasswordConfirmTextField -> R.string.signup_screen_title_password_confirm - passwordState.showPasswordTextField -> R.string.signup_screen_title_password - idState.showIdTextField -> R.string.signup_screen_title_id - else -> R.string.signup_screen_title_email - } -} - -data class IdState( - val showIdTextField: Boolean = true, - val showIdCheckButton: Boolean = false, - val id: String = "", - private val showIdOverlapHelperText: Boolean = false, - private val showIdInvalidHelperText: Boolean = false, -) { - val idHelperTextResId = when { - showIdInvalidHelperText -> R.string.textfield_id_invalid_helper_text - showIdOverlapHelperText -> R.string.textfield_id_overlap_helper_text - else -> R.string.word_empty - } - - val isErrorIdTextField = showIdInvalidHelperText || showIdOverlapHelperText -} - -data class PasswordState( - val showPasswordTextField: Boolean = false, - val showPasswordConfirmTextField: Boolean = false, - val password: String = "", - val showPasswordValue: Boolean = false, - val passwordConfirm: String = "", - val showPasswordConfirmValue: Boolean = false, - private val showPasswordInvalidHelperText: Boolean = false, - private val showPasswordConfirmInvalidHelperText: Boolean = false, - private val showPasswordConfirmNotSameHelperText: Boolean = false, -) { - val passwordHelperTextResId = when { - showPasswordInvalidHelperText -> R.string.textfield_password_invalid_helper_text - else -> R.string.word_empty - } - - val isErrorPasswordTextField = showPasswordInvalidHelperText - - val passwordConfirmHelperTextResId = when { - showPasswordConfirmInvalidHelperText -> R.string.textfield_password_invalid_helper_text - showPasswordConfirmNotSameHelperText -> R.string.textfield_password_not_same_helper_text - else -> R.string.word_empty - } - - val isErrorPasswordConfirmTextField = showPasswordConfirmInvalidHelperText || showPasswordConfirmNotSameHelperText -} - -data class EmailState( - val showEmailTextField: Boolean = false, - val showSendAuthEmailButton: Boolean = false, - val email: String = "", - private val showEmailNoticeHelperText: Boolean = true, - private val showEmailInvalidHelperText: Boolean = false, -) { - val emailHelperTextResId = when { - showEmailNoticeHelperText -> R.string.textfield_email_notice_text - showEmailInvalidHelperText -> R.string.textfield_email_invalid_text - else -> R.string.word_empty - } - - val isErrorEmailTextField = showEmailInvalidHelperText -} - -sealed interface SignupSideEffect { - data class HandleException(val throwable: Throwable) : SignupSideEffect - data object PopBackStack : SignupSideEffect - data object NavigateSignupComplete : SignupSideEffect - data object FocusPassword : SignupSideEffect - data object FocusPasswordConfirm : SignupSideEffect - data object FocusEmail : SignupSideEffect -} diff --git a/presentation/signup/src/main/java/com/suwiki/presentation/signup/signup/SignupScreen.kt b/presentation/signup/src/main/java/com/suwiki/presentation/signup/signup/SignupScreen.kt deleted file mode 100644 index 915f5c7b3..000000000 --- a/presentation/signup/src/main/java/com/suwiki/presentation/signup/signup/SignupScreen.kt +++ /dev/null @@ -1,257 +0,0 @@ -package com.suwiki.presentation.signup.signup - -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.runtime.snapshotFlow -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.suwiki.presentation.common.designsystem.component.button.SuwikiContainedLargeButton -import com.suwiki.presentation.common.designsystem.component.loading.LoadingScreen -import com.suwiki.presentation.common.designsystem.component.textfield.SuwikiRegularTextField -import com.suwiki.presentation.common.designsystem.theme.SuwikiTheme -import com.suwiki.presentation.common.ui.util.LaunchedEffectWithLifecycle -import com.suwiki.presentation.common.ui.util.TEXT_FIELD_DEBOUNCE -import com.suwiki.presentation.signup.R -import kotlinx.coroutines.FlowPreview -import kotlinx.coroutines.android.awaitFrame -import kotlinx.coroutines.flow.debounce -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import org.orbitmvi.orbit.compose.collectAsState -import org.orbitmvi.orbit.compose.collectSideEffect - -@OptIn(FlowPreview::class) -@Composable -fun SignupRoute( - viewModel: SignupViewModel = hiltViewModel(), - popBackStack: () -> Unit, - navigateSignupComplete: () -> Unit, - handleException: (Throwable) -> Unit, -) { - val uiState = viewModel.collectAsState().value - - val passwordFocusRequester = remember { FocusRequester() } - val passwordConfirmFocusRequester = remember { FocusRequester() } - val emailFocusRequester = remember { FocusRequester() } - - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - is SignupSideEffect.HandleException -> handleException(sideEffect.throwable) - SignupSideEffect.NavigateSignupComplete -> navigateSignupComplete() - SignupSideEffect.PopBackStack -> popBackStack() - SignupSideEffect.FocusEmail -> { - awaitFrame() - emailFocusRequester.requestFocus() - } - - SignupSideEffect.FocusPassword -> { - awaitFrame() - passwordFocusRequester.requestFocus() - } - - SignupSideEffect.FocusPasswordConfirm -> { - awaitFrame() - passwordConfirmFocusRequester.requestFocus() - } - } - } - - LaunchedEffectWithLifecycle(key1 = uiState.idState.id) { - snapshotFlow { uiState.idState.id } - .debounce(TEXT_FIELD_DEBOUNCE) - .onEach(viewModel::checkIdInvalid) - .launchIn(this) - } - - LaunchedEffectWithLifecycle(key1 = uiState.passwordState) { - snapshotFlow { uiState.passwordState } - .debounce(TEXT_FIELD_DEBOUNCE) - .onEach { - viewModel.checkPasswordInvalid(it.password) - viewModel.checkPasswordConfirmInvalid( - password = it.password, - passwordConfirm = it.passwordConfirm, - ) - } - .launchIn(this) - } - - LaunchedEffectWithLifecycle(key1 = uiState.emailState.email) { - snapshotFlow { uiState.emailState.email } - .debounce(TEXT_FIELD_DEBOUNCE) - .onEach(viewModel::checkEmailInvalid) - .launchIn(this) - } - - SignupScreen( - uiState = uiState, - passwordFocusRequester = passwordFocusRequester, - passwordConfirmFocusRequester = passwordConfirmFocusRequester, - emailFocusRequester = emailFocusRequester, - onValueChangeId = viewModel::updateId, - onClickIdTextFieldClearButton = { viewModel.updateId("") }, - onClickIdOverlapButton = viewModel::checkIdOverlap, - onValueChangePassword = viewModel::updatePassword, - onClickPasswordTextFieldClearButton = { viewModel.updatePassword("") }, - onClickPasswordEyeIcon = viewModel::toggleShowPasswordValue, - onValueChangePasswordConfirm = viewModel::updatePasswordConfirm, - onClickPasswordConfirmTextFieldClearButton = { viewModel.updatePasswordConfirm("") }, - onClickPasswordConfirmEyeIcon = viewModel::toggleShowPasswordConfirmValue, - onValueChangeEmail = viewModel::updateEmail, - onClickEmailTextFieldClearButton = { viewModel.updateEmail("") }, - onClickSendEmailAuthButton = viewModel::signup, - ) -} - -@Composable -fun SignupScreen( - uiState: SignupState = SignupState(), - passwordFocusRequester: FocusRequester = remember { FocusRequester() }, - passwordConfirmFocusRequester: FocusRequester = remember { FocusRequester() }, - emailFocusRequester: FocusRequester = remember { FocusRequester() }, - onValueChangeId: (String) -> Unit = {}, - onClickIdTextFieldClearButton: () -> Unit = {}, - onClickIdOverlapButton: () -> Unit = {}, - onValueChangePassword: (String) -> Unit = {}, - onClickPasswordTextFieldClearButton: () -> Unit = {}, - onClickPasswordEyeIcon: () -> Unit = {}, - onValueChangePasswordConfirm: (String) -> Unit = {}, - onClickPasswordConfirmTextFieldClearButton: () -> Unit = {}, - onClickPasswordConfirmEyeIcon: () -> Unit = {}, - onValueChangeEmail: (String) -> Unit = {}, - onClickEmailTextFieldClearButton: () -> Unit = {}, - onClickSendEmailAuthButton: () -> Unit = {}, -) { - Box( - modifier = Modifier - .fillMaxSize() - .padding(top = 63.dp, bottom = 28.dp, start = 24.dp, end = 24.dp), - ) { - Column { - Text( - text = stringResource(id = uiState.titleResId), - style = SuwikiTheme.typography.header1, - ) - - Spacer(modifier = Modifier.size(26.dp)) - - Column( - modifier = Modifier.verticalScroll(state = rememberScrollState()), - verticalArrangement = Arrangement.spacedBy(4.dp), - ) { - with(uiState.emailState) { - AnimatedVisibility(visible = showEmailTextField) { - SuwikiRegularTextField( - modifier = Modifier.focusRequester(emailFocusRequester), - label = stringResource(R.string.word_email), - placeholder = stringResource(R.string.textfield_email_placeholder), - value = email, - onValueChange = onValueChangeEmail, - onClickClearButton = onClickEmailTextFieldClearButton, - helperText = stringResource(id = emailHelperTextResId), - isError = isErrorEmailTextField, - ) - } - } - - with(uiState.passwordState) { - AnimatedVisibility(visible = showPasswordConfirmTextField) { - SuwikiRegularTextField( - modifier = Modifier.focusRequester(passwordConfirmFocusRequester), - label = stringResource(R.string.word_password_confirm), - placeholder = stringResource(R.string.textfield_password_placeholder), - value = passwordConfirm, - onValueChange = onValueChangePasswordConfirm, - onClickClearButton = onClickPasswordConfirmTextFieldClearButton, - helperText = stringResource(id = passwordConfirmHelperTextResId), - isError = isErrorPasswordConfirmTextField, - showEyeIcon = true, - showValue = showPasswordConfirmValue, - onClickEyeIcon = onClickPasswordConfirmEyeIcon, - ) - } - - AnimatedVisibility(visible = showPasswordTextField) { - SuwikiRegularTextField( - modifier = Modifier.focusRequester(passwordFocusRequester), - label = stringResource(R.string.word_password), - placeholder = stringResource(R.string.textfield_password_placeholder), - value = password, - onValueChange = onValueChangePassword, - onClickClearButton = onClickPasswordTextFieldClearButton, - helperText = stringResource(id = passwordHelperTextResId), - isError = isErrorPasswordTextField, - showEyeIcon = true, - showValue = showPasswordValue, - onClickEyeIcon = onClickPasswordEyeIcon, - ) - } - } - - with(uiState.idState) { - AnimatedVisibility(visible = showIdTextField) { - SuwikiRegularTextField( - label = stringResource(R.string.word_id), - placeholder = stringResource(R.string.textfield_id_placeholder), - value = id, - onValueChange = onValueChangeId, - onClickClearButton = onClickIdTextFieldClearButton, - helperText = stringResource(id = idHelperTextResId), - isError = isErrorIdTextField, - ) - } - } - } - } - - if (uiState.emailState.showSendAuthEmailButton) { - SuwikiContainedLargeButton( - modifier = Modifier - .align(Alignment.BottomCenter) - .imePadding(), - text = stringResource(R.string.signup_screen_receive_auth_email), - onClick = onClickSendEmailAuthButton, - ) - } - - if (uiState.idState.showIdCheckButton) { - SuwikiContainedLargeButton( - modifier = Modifier - .align(Alignment.BottomCenter) - .imePadding(), - text = stringResource(R.string.signup_screen_id_overlap), - onClick = onClickIdOverlapButton, - ) - } - - if (uiState.isLoading) { - LoadingScreen() - } - } -} - -@Preview(showBackground = true) -@Composable -fun SignupScreenPreview() { - SuwikiTheme { - SignupScreen() - } -} diff --git a/presentation/signup/src/main/java/com/suwiki/presentation/signup/signup/SignupViewModel.kt b/presentation/signup/src/main/java/com/suwiki/presentation/signup/signup/SignupViewModel.kt deleted file mode 100644 index 4beb3f02b..000000000 --- a/presentation/signup/src/main/java/com/suwiki/presentation/signup/signup/SignupViewModel.kt +++ /dev/null @@ -1,322 +0,0 @@ -package com.suwiki.presentation.signup.signup - -import androidx.lifecycle.ViewModel -import com.suwiki.domain.signup.usecase.CheckIdOverlapUseCase -import com.suwiki.domain.signup.usecase.SignupUseCase -import com.suwiki.presentation.common.ui.util.REGEX -import dagger.hilt.android.lifecycle.HiltViewModel -import org.orbitmvi.orbit.Container -import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.annotation.OrbitExperimental -import org.orbitmvi.orbit.syntax.simple.blockingIntent -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.postSideEffect -import org.orbitmvi.orbit.syntax.simple.reduce -import org.orbitmvi.orbit.viewmodel.container -import javax.inject.Inject - -@HiltViewModel -class SignupViewModel @Inject constructor( - private val checkIdOverlapUseCase: CheckIdOverlapUseCase, - private val signupUseCase: SignupUseCase, -) : ContainerHost, ViewModel() { - override val container: Container = container(SignupState()) - - private val idState - get() = container.stateFlow.value.idState - - private var isIdValid: Boolean = false - - private val passwordState - get() = container.stateFlow.value.passwordState - - private var isPasswordValid: Boolean = false - - private var isPasswordConfirmValid: Boolean = false - - private val emailState - get() = container.stateFlow.value.emailState - - private var passwordFocused = false - private var passwordConfirmFocused = false - private var emailFocused = false - - fun signup() = intent { - reduce { state.copy(isLoading = true) } - signupUseCase( - SignupUseCase.Param( - id = idState.id, - password = passwordState.passwordConfirm, - email = emailState.email, - ), - ) - .onSuccess { - postSideEffect(SignupSideEffect.NavigateSignupComplete) - } - .onFailure { - postSideEffect(SignupSideEffect.HandleException(it)) - } - reduce { state.copy(isLoading = false) } - } - - @OptIn(OrbitExperimental::class) - fun updateEmail(email: String) = blockingIntent { - reduce { - state.copy( - emailState = emailState.copy( - email = email, - showSendAuthEmailButton = false, - showEmailNoticeHelperText = true, - showEmailInvalidHelperText = false, - ), - ) - } - } - - fun checkEmailInvalid(email: String) { - when { - email.isEmpty() -> Unit - email.matches(REGEX.EMAIL) -> showSendAuthEmailButton() - else -> showEmailInvalidHelperText() - } - } - - private fun showSendAuthEmailButton() = intent { - reduce { - state.copy( - emailState = emailState.copy( - showSendAuthEmailButton = true, - showEmailNoticeHelperText = false, - showEmailInvalidHelperText = false, - ), - ) - } - } - - private fun showEmailInvalidHelperText() = intent { - reduce { - state.copy( - emailState = emailState.copy( - showSendAuthEmailButton = false, - showEmailNoticeHelperText = false, - showEmailInvalidHelperText = true, - ), - ) - } - } - - fun toggleShowPasswordValue() = intent { - reduce { - state.copy( - passwordState = passwordState.copy( - showPasswordValue = !passwordState.showPasswordValue, - ), - ) - } - } - - fun toggleShowPasswordConfirmValue() = intent { - reduce { - state.copy( - passwordState = passwordState.copy( - showPasswordConfirmValue = !passwordState.showPasswordConfirmValue, - ), - ) - } - } - - @OptIn(OrbitExperimental::class) - fun updatePasswordConfirm(passwordConfirm: String) = blockingIntent { - reduce { - isPasswordConfirmValid = false - state.copy( - passwordState = passwordState.copy( - passwordConfirm = passwordConfirm, - showPasswordConfirmInvalidHelperText = false, - showPasswordConfirmNotSameHelperText = false, - ), - ) - } - } - - fun checkPasswordConfirmInvalid(password: String, passwordConfirm: String) { - when { - passwordConfirm.isEmpty() -> Unit - passwordConfirm.matches(REGEX.PASSWORD) && passwordConfirm == password -> showEmailTextField() - passwordConfirm != password -> showPasswordConfirmNotSameHelperText() - else -> showPasswordConfirmInvalidHelperText() - } - } - - private fun showEmailTextField() = intent { - reduce { - isPasswordConfirmValid = true - state.copy( - emailState = emailState.copy( - showEmailTextField = true, - ), - passwordState = passwordState.copy( - showPasswordTextField = false, - showPasswordConfirmTextField = false, - showPasswordConfirmNotSameHelperText = false, - showPasswordConfirmInvalidHelperText = false, - ), - idState = idState.copy( - showIdTextField = false, - ), - ) - } - if (emailFocused.not()) { - postSideEffect(SignupSideEffect.FocusEmail) - emailFocused = true - } - } - - private fun showPasswordConfirmNotSameHelperText() = intent { - reduce { - state.copy( - passwordState = passwordState.copy( - showPasswordConfirmNotSameHelperText = true, - ), - ) - } - } - - private fun showPasswordConfirmInvalidHelperText() = intent { - reduce { - state.copy( - passwordState = passwordState.copy( - showPasswordConfirmInvalidHelperText = true, - ), - ) - } - } - - @OptIn(OrbitExperimental::class) - fun updatePassword(password: String) = blockingIntent { - reduce { - isPasswordValid = false - state.copy( - passwordState = passwordState.copy( - password = password, - showPasswordInvalidHelperText = false, - ), - ) - } - } - - fun checkPasswordInvalid(password: String) { - when { - password.isEmpty() -> Unit - password.matches(REGEX.PASSWORD) -> showPasswordConfirmTextField() - else -> showPasswordInvalidHelperText() - } - } - - private fun showPasswordConfirmTextField() = intent { - reduce { - isPasswordValid = true - state.copy( - passwordState = passwordState.copy( - showPasswordConfirmTextField = true, - ), - ) - } - if (passwordConfirmFocused.not()) { - postSideEffect(SignupSideEffect.FocusPasswordConfirm) - passwordConfirmFocused = true - } - } - - private fun showPasswordInvalidHelperText() = intent { - reduce { - state.copy( - passwordState = passwordState.copy( - showPasswordInvalidHelperText = true, - ), - ) - } - } - - fun checkIdOverlap() = intent { - reduce { state.copy(isLoading = true) } - checkIdOverlapUseCase(id = idState.id) - .onSuccess(::handleCheckIdOverlapSuccess) - .onFailure { - postSideEffect(SignupSideEffect.HandleException(it)) - } - reduce { state.copy(isLoading = false) } - } - - private fun handleCheckIdOverlapSuccess(overlap: Boolean) = intent { - if (overlap) { - reduce { state.copy(idState = idState.copy(showIdOverlapHelperText = true)) } - } else { - reduce { - isIdValid = true - state.copy( - passwordState = passwordState.copy(showPasswordTextField = true), - idState = idState.copy(showIdCheckButton = false), - ) - } - if (passwordFocused.not()) { - postSideEffect(SignupSideEffect.FocusPassword) - passwordFocused = true - } - } - } - - @OptIn(OrbitExperimental::class) - fun updateId(id: String) = blockingIntent { - reduce { - isIdValid = false - state.copy( - idState = idState.copy( - id = id, - showIdInvalidHelperText = false, - showIdOverlapHelperText = false, - showIdCheckButton = false, - ), - ) - } - } - - fun checkIdInvalid(id: String) { - when { - id.isEmpty() -> Unit - id.matches(REGEX.ID) && isIdValid.not() -> showIdCheckButton() - isIdValid -> hideIdInvalidHelperText() - else -> showIdInvalidHelperText() - } - } - - private fun showIdCheckButton() = intent { - reduce { - state.copy( - idState = idState.copy( - showIdCheckButton = true, - ), - ) - } - } - - private fun hideIdInvalidHelperText() = intent { - reduce { - state.copy( - idState = idState.copy( - showIdInvalidHelperText = false, - ), - ) - } - } - - private fun showIdInvalidHelperText() = intent { - reduce { - state.copy( - idState = idState.copy( - showIdInvalidHelperText = true, - ), - ) - } - } -} diff --git a/presentation/signup/src/main/res/drawable/ic_signup_complete.png b/presentation/signup/src/main/res/drawable/ic_signup_complete.png deleted file mode 100644 index e1b993d53..000000000 Binary files a/presentation/signup/src/main/res/drawable/ic_signup_complete.png and /dev/null differ diff --git a/presentation/signup/src/main/res/values/strings.xml b/presentation/signup/src/main/res/values/strings.xml deleted file mode 100644 index 56d4201f0..000000000 --- a/presentation/signup/src/main/res/values/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - 아이디를 입력하세요 - 비밀번호를 입력하세요 - 비밀번호를 확인하세요 - 학교 이메일을 입력하세요 - 인증메일 받기 - 아이디 중복확인 - diff --git a/presentation/timetable/src/main/java/com/suwiki/presentation/timetable/navigation/TimetableNavigation.kt b/presentation/timetable/src/main/java/com/suwiki/presentation/timetable/navigation/TimetableNavigation.kt index 9c2cadb07..8b0f0ddfd 100644 --- a/presentation/timetable/src/main/java/com/suwiki/presentation/timetable/navigation/TimetableNavigation.kt +++ b/presentation/timetable/src/main/java/com/suwiki/presentation/timetable/navigation/TimetableNavigation.kt @@ -17,10 +17,6 @@ import com.suwiki.presentation.timetable.timetableeditor.TimetableEditorRoute import com.suwiki.presentation.timetable.timetablelist.TimetableListRoute import kotlinx.serialization.json.Json -fun NavController.navigateTimetable(navOptions: NavOptions) { - navigate(TimetableRoute.route, navOptions) -} - fun NavController.navigateTimetableEditor(argument: TimetableEditorArgument = TimetableEditorArgument()) { navigate(TimetableRoute.timetableEditorRoute(Json.encodeToUri(argument))) } diff --git a/remote/lectureevaluation/.gitignore b/remote/lectureevaluation/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/remote/lectureevaluation/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/remote/lectureevaluation/build.gradle.kts b/remote/lectureevaluation/build.gradle.kts deleted file mode 100644 index 6eb6877fe..000000000 --- a/remote/lectureevaluation/build.gradle.kts +++ /dev/null @@ -1,17 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.remote) - alias(libs.plugins.kotlin.serialization) -} - -android { - namespace = "com.suwiki.remote.lectureevaluation" -} - -dependencies { - implementation(projects.data.lectureevaluation) - - implementation(libs.retrofit.core) - implementation(libs.kotlinx.serialization.json) - implementation(libs.kotlinx.datetime) -} diff --git a/remote/lectureevaluation/consumer-rules.pro b/remote/lectureevaluation/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/remote/lectureevaluation/proguard-rules.pro b/remote/lectureevaluation/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/remote/lectureevaluation/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/remote/lectureevaluation/src/main/AndroidManifest.xml b/remote/lectureevaluation/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e68a..000000000 --- a/remote/lectureevaluation/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/ExamEditorApi.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/ExamEditorApi.kt deleted file mode 100644 index 1f024ba7a..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/ExamEditorApi.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.suwiki.remote.lectureevaluation.api - -import com.suwiki.remote.common.retrofit.ApiResult -import com.suwiki.remote.lectureevaluation.request.PostExamEvaluationRequest -import com.suwiki.remote.lectureevaluation.request.UpdateExamEvaluationRequest -import retrofit2.http.Body -import retrofit2.http.DELETE -import retrofit2.http.POST -import retrofit2.http.PUT -import retrofit2.http.Query - -// TODO : v2 api로 업그레이드 필요. -interface ExamEditorApi { - companion object { - const val EXAM_POSTS: String = "/exam-posts" - const val QUERY_EXAM_IDX = "examIdx" - const val QUERY_LECTURE_ID = "lectureId" - } - - @POST(EXAM_POSTS) - suspend fun postExamEvaluation( - @Query(QUERY_LECTURE_ID) lectureId: Long, - @Body request: PostExamEvaluationRequest, - ): ApiResult - - @PUT(EXAM_POSTS) - suspend fun updateExamEvaluation( - @Query(QUERY_EXAM_IDX) lectureId: Long, - @Body request: UpdateExamEvaluationRequest, - ): ApiResult - - @DELETE(EXAM_POSTS) - suspend fun deleteExamEvaluation(@Query(QUERY_EXAM_IDX) id: Long): ApiResult -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/ExamMyApi.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/ExamMyApi.kt deleted file mode 100644 index a93662f44..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/ExamMyApi.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.suwiki.remote.lectureevaluation.api - -import com.suwiki.remote.common.retrofit.ApiResult -import com.suwiki.remote.lectureevaluation.response.DataResponse -import com.suwiki.remote.lectureevaluation.response.MyExamEvaluationResponse -import com.suwiki.remote.lectureevaluation.response.PurchaseHistoryResponse -import retrofit2.http.GET -import retrofit2.http.Query - -// TODO : v2 api로 업그레이드 필요. -interface ExamMyApi { - companion object { - const val EXAM_POSTS: String = "/exam-posts" - const val QUERY_PAGE = "page" - } - - // 내가 쓴 글 (시험 정보) - @GET("$EXAM_POSTS/written") - suspend fun getMyExamEvaluationList(@Query(QUERY_PAGE) page: Int): ApiResult>> - - // 시험정보 구매 이력 - @GET("$EXAM_POSTS/purchase") - suspend fun getPurchaseHistory(): ApiResult>> -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/ExamReportApi.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/ExamReportApi.kt deleted file mode 100644 index 246df7215..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/ExamReportApi.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.suwiki.remote.lectureevaluation.api - -import com.suwiki.remote.common.retrofit.ApiResult -import com.suwiki.remote.lectureevaluation.api.LectureReportApi.Companion.REPORT -import com.suwiki.remote.lectureevaluation.api.LectureReportApi.Companion.USER -import com.suwiki.remote.lectureevaluation.request.ReportExamRequest -import retrofit2.http.Body -import retrofit2.http.POST - -interface ExamReportApi { - - // 시험 정보 신고하기 - @POST("$USER/$REPORT/exam") - suspend fun reportExam(@Body reportExamRequest: ReportExamRequest): ApiResult -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/ExamViewerApi.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/ExamViewerApi.kt deleted file mode 100644 index eeecc9885..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/ExamViewerApi.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.suwiki.remote.lectureevaluation.api - -import com.suwiki.remote.common.retrofit.ApiResult -import com.suwiki.remote.lectureevaluation.api.LectureViewerApi.Companion.QUERY_LECTURE_ID -import com.suwiki.remote.lectureevaluation.response.ExamEvaluationListResponse -import retrofit2.http.GET -import retrofit2.http.POST -import retrofit2.http.Query - -interface ExamViewerApi { - companion object { - const val EXAM_POSTS: String = "/exam-posts" - const val QUERY_PAGE = "page" - } - - // 검색결과 자세히 보기 (Exam) - @GET(EXAM_POSTS) - suspend fun getExamEvaluationList( - @Query(QUERY_LECTURE_ID) lectureId: Long, - @Query(QUERY_PAGE) page: Int, - ): ApiResult - - // 시험 정보 구매 - @POST("$EXAM_POSTS/purchase/") - suspend fun buyExam(@Query(QUERY_LECTURE_ID) lectureId: Long): ApiResult -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/LectureEditorApi.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/LectureEditorApi.kt deleted file mode 100644 index 047a6b922..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/LectureEditorApi.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.suwiki.remote.lectureevaluation.api - -import com.suwiki.remote.common.retrofit.ApiResult -import com.suwiki.remote.lectureevaluation.request.PostLectureEvaluationRequest -import com.suwiki.remote.lectureevaluation.request.UpdateLectureEvaluationRequest -import retrofit2.http.Body -import retrofit2.http.DELETE -import retrofit2.http.POST -import retrofit2.http.PUT -import retrofit2.http.Query - -interface LectureEditorApi { - companion object { - - const val EVALUATE_POST = "/evaluate-posts" - const val QUERY_EVALUATE_ID = "evaluateIdx" - const val QUERY_LECTURE_ID = "lectureId" - } - - // 강의 평가 쓰기 - @POST(EVALUATE_POST) - suspend fun postLectureEvaluation( - @Query(QUERY_LECTURE_ID) lectureId: Long, - @Body postLectureEvaluationRequest: PostLectureEvaluationRequest, - ): ApiResult - - // 강의 평가 수정 - @PUT(EVALUATE_POST) - suspend fun updateLectureEvaluation( - @Query(QUERY_EVALUATE_ID) lectureId: Long, - @Body updateLectureEvaluationRequest: UpdateLectureEvaluationRequest, - ): ApiResult - - // 강의 평가 삭제 - @DELETE(EVALUATE_POST) - suspend fun deleteLectureEvaluation(@Query(QUERY_EVALUATE_ID) id: Long): ApiResult -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/LectureMyApi.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/LectureMyApi.kt deleted file mode 100644 index 0f97b103c..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/LectureMyApi.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.suwiki.remote.lectureevaluation.api - -import com.suwiki.remote.common.retrofit.ApiResult -import com.suwiki.remote.lectureevaluation.response.DataResponse -import com.suwiki.remote.lectureevaluation.response.MyLectureEvaluationResponse -import retrofit2.http.GET -import retrofit2.http.Query - -// TODO : v2 api로 업그레이드 필요. -interface LectureMyApi { - companion object { - const val QUERY_PAGE = "page" - const val EVALUATE_POST = "/evaluate-posts" - } - - // 내가 쓴 글 (강의평가) - @GET("$EVALUATE_POST/written") - suspend fun getMyLectureEvaluationList(@Query(QUERY_PAGE) page: Int): ApiResult>> -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/LectureReportApi.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/LectureReportApi.kt deleted file mode 100644 index 9c4af3d75..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/LectureReportApi.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.suwiki.remote.lectureevaluation.api - -import com.suwiki.remote.common.retrofit.ApiResult -import com.suwiki.remote.lectureevaluation.request.ReportLectureRequest -import retrofit2.http.Body -import retrofit2.http.POST - -interface LectureReportApi { - companion object { - const val USER = "/user" - const val REPORT = "report" - } - - // 강의 평가 신고하기 - @POST("$USER/$REPORT/evaluate") - suspend fun reportLecture(@Body reportLectureRequest: ReportLectureRequest): ApiResult -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/LectureViewerApi.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/LectureViewerApi.kt deleted file mode 100644 index aec4afd51..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/api/LectureViewerApi.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.suwiki.remote.lectureevaluation.api - -import com.suwiki.remote.common.retrofit.ApiResult -import com.suwiki.remote.lectureevaluation.response.DataResponse -import com.suwiki.remote.lectureevaluation.response.LectureEvaluationAverageResponse -import com.suwiki.remote.lectureevaluation.response.LectureEvaluationExtraAverageResponse -import com.suwiki.remote.lectureevaluation.response.LectureEvaluationListResponse -import retrofit2.http.GET -import retrofit2.http.Query - -interface LectureViewerApi { - companion object { - const val LECTURE: String = "/lecture" - - const val QUERY_SEARCH_VALUE = "searchValue" - const val QUERY_MAJOR_TYPE = "majorType" - const val QUERY_PAGE = "page" - const val QUERY_OPTION = "option" - const val QUERY_LECTURE_ID = "lectureId" - - const val EVALUATE_POST = "/evaluate-posts" - } - - // 메인 페이지 - @GET("$LECTURE/all/") - suspend fun getLectureEvaluationAverageList( - @Query(QUERY_OPTION) option: String, - @Query(QUERY_PAGE) page: Int = 1, - @Query(QUERY_MAJOR_TYPE) majorType: String = "", - ): ApiResult>> - - // 통합 검색 결과 - @GET("$LECTURE/search/") - suspend fun retrieveLectureEvaluationAverageList( - @Query(QUERY_SEARCH_VALUE) searchValue: String, - @Query(QUERY_OPTION) option: String, - @Query(QUERY_PAGE) page: Int, - @Query(QUERY_MAJOR_TYPE) majorType: String, - ): ApiResult>> - - // 검색결과 자세히 보기 (LECTURE) - @GET("$LECTURE/") - suspend fun getLectureEvaluationExtraAverage( - @Query(QUERY_LECTURE_ID) lectureId: Long, - ): ApiResult> - - // 검색 결과 자세히 보기 (Evaluation) - @GET(EVALUATE_POST) - suspend fun getLectureEvaluationList( - @Query(QUERY_LECTURE_ID) lectureId: Long, - @Query(QUERY_PAGE) page: Int, - ): ApiResult -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteExamEditorDataSourceImpl.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteExamEditorDataSourceImpl.kt deleted file mode 100644 index 13ac9e006..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteExamEditorDataSourceImpl.kt +++ /dev/null @@ -1,64 +0,0 @@ -package com.suwiki.remote.lectureevaluation.datasource - -import com.suwiki.data.lectureevaluation.datasource.RemoteExamEditorDataSource -import com.suwiki.remote.lectureevaluation.api.ExamEditorApi -import com.suwiki.remote.lectureevaluation.request.PostExamEvaluationRequest -import com.suwiki.remote.lectureevaluation.request.UpdateExamEvaluationRequest -import javax.inject.Inject - -class RemoteExamEditorDataSourceImpl @Inject constructor( - private val examApi: ExamEditorApi, -) : RemoteExamEditorDataSource { - - override suspend fun postExamEvaluation( - lectureId: Long, - lectureName: String?, - professor: String?, - selectedSemester: String?, - examInfo: String, - examType: String?, - examDifficulty: String, - content: String, - ) { - val request = PostExamEvaluationRequest( - lectureName = lectureName, - professor = professor, - selectedSemester = selectedSemester, - examInfo = examInfo, - examType = examType, - examDifficulty = examDifficulty, - content = content, - ) - - return examApi.postExamEvaluation( - lectureId = lectureId, - request = request, - ).getOrThrow() - } - - override suspend fun updateExamEvaluation( - lectureId: Long, - selectedSemester: String?, - examInfo: String, - examType: String?, - examDifficulty: String, - content: String, - ) { - val request = UpdateExamEvaluationRequest( - selectedSemester = selectedSemester, - examInfo = examInfo, - examType = examType, - examDifficulty = examDifficulty, - content = content, - ) - - return examApi.updateExamEvaluation( - lectureId = lectureId, - request = request, - ).getOrThrow() - } - - override suspend fun deleteExamEvaluation(id: Long) { - return examApi.deleteExamEvaluation(id).getOrThrow() - } -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteExamMyDataSourceImpl.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteExamMyDataSourceImpl.kt deleted file mode 100644 index 83a72f14e..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteExamMyDataSourceImpl.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.suwiki.remote.lectureevaluation.datasource - -import com.suwiki.common.model.lectureevaluation.PurchaseHistory -import com.suwiki.common.model.lectureevaluation.exam.MyExamEvaluation -import com.suwiki.data.lectureevaluation.datasource.RemoteExamMyDataSource -import com.suwiki.remote.lectureevaluation.api.ExamMyApi -import com.suwiki.remote.lectureevaluation.response.toModel -import javax.inject.Inject - -class RemoteExamMyDataSourceImpl @Inject constructor( - private val examApi: ExamMyApi, -) : RemoteExamMyDataSource { - - override suspend fun getMyExamEvaluationList(page: Int): List { - return examApi.getMyExamEvaluationList(page).getOrThrow().data.map { it.toModel() } - } - - override suspend fun getPurchaseHistory(): List { - return examApi.getPurchaseHistory().getOrThrow().data.map { it.toModel() } - } -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteExamProviderDataSourceImpl.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteExamProviderDataSourceImpl.kt deleted file mode 100644 index c847f7b6f..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteExamProviderDataSourceImpl.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.suwiki.remote.lectureevaluation.datasource - -import com.suwiki.common.model.lectureevaluation.exam.ExamEvaluationList -import com.suwiki.data.lectureevaluation.datasource.RemoteExamProviderDataSource -import com.suwiki.remote.lectureevaluation.api.ExamViewerApi -import com.suwiki.remote.lectureevaluation.response.toModel -import javax.inject.Inject - -class RemoteExamProviderDataSourceImpl @Inject constructor( - private val examApi: ExamViewerApi, -) : RemoteExamProviderDataSource { - - override suspend fun getExamEvaluationList( - lectureId: Long, - page: Int, - ): ExamEvaluationList { - return examApi.getExamEvaluationList(lectureId = lectureId, page = page) - .getOrThrow().toModel() - } - - override suspend fun buyExam(lectureId: Long) { - return examApi.buyExam(lectureId).getOrThrow() - } -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteExamReportDataSourceImpl.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteExamReportDataSourceImpl.kt deleted file mode 100644 index ce5a32b54..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteExamReportDataSourceImpl.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.suwiki.remote.lectureevaluation.datasource - -import com.suwiki.data.lectureevaluation.datasource.RemoteExamReportDataSource -import com.suwiki.remote.lectureevaluation.api.ExamReportApi -import com.suwiki.remote.lectureevaluation.request.ReportExamRequest -import javax.inject.Inject - -class RemoteExamReportDataSourceImpl @Inject constructor( - private val examApi: ExamReportApi, -) : RemoteExamReportDataSource { - - override suspend fun reportExam( - examIdx: Long, - content: String, - ) { - return examApi.reportExam( - ReportExamRequest( - examIdx = examIdx, - content = content, - ), - ).getOrThrow() - } -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteLectureEditorDataSourceImpl.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteLectureEditorDataSourceImpl.kt deleted file mode 100644 index a34241a8f..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteLectureEditorDataSourceImpl.kt +++ /dev/null @@ -1,76 +0,0 @@ -package com.suwiki.remote.lectureevaluation.datasource - -import com.suwiki.data.lectureevaluation.datasource.RemoteLectureEditorDataSource -import com.suwiki.remote.lectureevaluation.api.LectureEditorApi -import com.suwiki.remote.lectureevaluation.request.PostLectureEvaluationRequest -import com.suwiki.remote.lectureevaluation.request.UpdateLectureEvaluationRequest -import javax.inject.Inject - -class RemoteLectureEditorDataSourceImpl @Inject constructor( - private val lectureApi: LectureEditorApi, -) : RemoteLectureEditorDataSource { - - override suspend fun postLectureEvaluation( - lectureId: Long, - lectureName: String, - professor: String, - selectedSemester: String, - satisfaction: Float, - learning: Float, - honey: Float, - team: Int, - difficulty: Int, - homework: Int, - content: String, - ) { - val request = PostLectureEvaluationRequest( - lectureName = lectureName, - professor = professor, - selectedSemester = selectedSemester, - satisfaction = satisfaction, - learning = learning, - honey = honey, - team = team, - difficulty = difficulty, - homework = homework, - content = content, - ) - - return lectureApi.postLectureEvaluation( - lectureId, - request, - ).getOrThrow() - } - - override suspend fun updateLectureEvaluation( - lectureId: Long, - selectedSemester: String, - satisfaction: Float, - learning: Float, - honey: Float, - team: Int, - difficulty: Int, - homework: Int, - content: String, - ) { - val request = UpdateLectureEvaluationRequest( - selectedSemester = selectedSemester, - satisfaction = satisfaction, - learning = learning, - honey = honey, - team = team, - difficulty = difficulty, - homework = homework, - content = content, - ) - - return lectureApi.updateLectureEvaluation( - lectureId = lectureId, - updateLectureEvaluationRequest = request, - ).getOrThrow() - } - - override suspend fun deleteLectureEvaluation(id: Long) { - return lectureApi.deleteLectureEvaluation(id = id).getOrThrow() - } -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteLectureMyDataSourceImpl.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteLectureMyDataSourceImpl.kt deleted file mode 100644 index c5be10dc3..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteLectureMyDataSourceImpl.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.suwiki.remote.lectureevaluation.datasource - -import com.suwiki.common.model.lectureevaluation.lecture.MyLectureEvaluation -import com.suwiki.data.lectureevaluation.datasource.RemoteLectureMyDataSource -import com.suwiki.remote.lectureevaluation.api.LectureMyApi -import com.suwiki.remote.lectureevaluation.response.toModel -import javax.inject.Inject - -class RemoteLectureMyDataSourceImpl @Inject constructor( - private val lectureApi: LectureMyApi, -) : RemoteLectureMyDataSource { - override suspend fun getMyLectureEvaluationList(page: Int): List { - return lectureApi.getMyLectureEvaluationList(page).getOrThrow().data.map { it.toModel() } - } -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteLectureProviderDataSourceImpl.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteLectureProviderDataSourceImpl.kt deleted file mode 100644 index 53aabb71d..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteLectureProviderDataSourceImpl.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.suwiki.remote.lectureevaluation.datasource - -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationAverage -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationExtraAverage -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationList -import com.suwiki.data.lectureevaluation.datasource.RemoteLectureProviderDataSource -import com.suwiki.remote.lectureevaluation.api.LectureViewerApi -import com.suwiki.remote.lectureevaluation.response.toModel -import javax.inject.Inject - -class RemoteLectureProviderDataSourceImpl @Inject constructor( - private val lectureApi: LectureViewerApi, -) : RemoteLectureProviderDataSource { - - override suspend fun getLectureEvaluationList( - lectureId: Long, - page: Int, - ): LectureEvaluationList { - return lectureApi.getLectureEvaluationList(lectureId = lectureId, page = page) - .getOrThrow().toModel() - } - - override suspend fun getLectureEvaluationAverageList( - option: String, - page: Int, - majorType: String, - ): List { - return lectureApi.getLectureEvaluationAverageList( - option = option, - page = page, - majorType = majorType, - ).getOrThrow().data.map { it?.toModel() } - } - - override suspend fun retrieveLectureEvaluationAverageList( - search: String, - option: String, - page: Int, - majorType: String, - ): List { - return lectureApi.retrieveLectureEvaluationAverageList( - searchValue = search, - option = option, - page = page, - majorType = majorType, - ).getOrThrow().data.map { it?.toModel() } - } - - override suspend fun getLectureEvaluationExtraAverage(lectureId: Long): LectureEvaluationExtraAverage { - return lectureApi.getLectureEvaluationExtraAverage(lectureId).getOrThrow().data.toModel() - } -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteLectureReportDataSourceImpl.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteLectureReportDataSourceImpl.kt deleted file mode 100644 index 16744d72f..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/datasource/RemoteLectureReportDataSourceImpl.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.suwiki.remote.lectureevaluation.datasource - -import com.suwiki.data.lectureevaluation.datasource.RemoteLectureReportDataSource -import com.suwiki.remote.lectureevaluation.api.LectureReportApi -import com.suwiki.remote.lectureevaluation.request.ReportLectureRequest -import javax.inject.Inject - -class RemoteLectureReportDataSourceImpl @Inject constructor( - private val lectureApi: LectureReportApi, -) : RemoteLectureReportDataSource { - - override suspend fun reportLecture(evaluateIdx: Long, content: String) { - return lectureApi.reportLecture( - ReportLectureRequest( - evaluateIdx = evaluateIdx, - content = content, - ), - ).getOrThrow() - } -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/di/ApiModule.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/di/ApiModule.kt deleted file mode 100644 index 64ac29bb1..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/di/ApiModule.kt +++ /dev/null @@ -1,70 +0,0 @@ -package com.suwiki.remote.lectureevaluation.di - -import com.suwiki.remote.common.di.AuthRetrofit -import com.suwiki.remote.lectureevaluation.api.ExamEditorApi -import com.suwiki.remote.lectureevaluation.api.ExamMyApi -import com.suwiki.remote.lectureevaluation.api.ExamReportApi -import com.suwiki.remote.lectureevaluation.api.ExamViewerApi -import com.suwiki.remote.lectureevaluation.api.LectureEditorApi -import com.suwiki.remote.lectureevaluation.api.LectureMyApi -import com.suwiki.remote.lectureevaluation.api.LectureReportApi -import com.suwiki.remote.lectureevaluation.api.LectureViewerApi -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import retrofit2.Retrofit -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -object ApiModule { - - @Singleton - @Provides - fun provideExamEditorApi(@AuthRetrofit retrofit: Retrofit): ExamEditorApi { - return retrofit.create(ExamEditorApi::class.java) - } - - @Singleton - @Provides - fun provideLectureEditorApi(@AuthRetrofit retrofit: Retrofit): LectureEditorApi { - return retrofit.create(LectureEditorApi::class.java) - } - - @Singleton - @Provides - fun provideExamMyApi(@AuthRetrofit retrofit: Retrofit): ExamMyApi { - return retrofit.create(ExamMyApi::class.java) - } - - @Singleton - @Provides - fun provideLectureMyApi(@AuthRetrofit retrofit: Retrofit): LectureMyApi { - return retrofit.create(LectureMyApi::class.java) - } - - @Singleton - @Provides - fun provideExamReportApi(@AuthRetrofit retrofit: Retrofit): ExamReportApi { - return retrofit.create(ExamReportApi::class.java) - } - - @Singleton - @Provides - fun provideLectureReportApi(@AuthRetrofit retrofit: Retrofit): LectureReportApi { - return retrofit.create(LectureReportApi::class.java) - } - - @Singleton - @Provides - fun provideExamViewerApi(@AuthRetrofit retrofit: Retrofit): ExamViewerApi { - return retrofit.create(ExamViewerApi::class.java) - } - - @Singleton - @Provides - fun provideLectureViewerApi(@AuthRetrofit retrofit: Retrofit): LectureViewerApi { - return retrofit.create(LectureViewerApi::class.java) - } -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/di/RemoteDataSourceModule.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/di/RemoteDataSourceModule.kt deleted file mode 100644 index 2b44c712d..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/di/RemoteDataSourceModule.kt +++ /dev/null @@ -1,76 +0,0 @@ -package com.suwiki.remote.lectureevaluation.di - -import com.suwiki.data.lectureevaluation.datasource.RemoteExamEditorDataSource -import com.suwiki.data.lectureevaluation.datasource.RemoteExamMyDataSource -import com.suwiki.data.lectureevaluation.datasource.RemoteExamProviderDataSource -import com.suwiki.data.lectureevaluation.datasource.RemoteExamReportDataSource -import com.suwiki.data.lectureevaluation.datasource.RemoteLectureEditorDataSource -import com.suwiki.data.lectureevaluation.datasource.RemoteLectureMyDataSource -import com.suwiki.data.lectureevaluation.datasource.RemoteLectureProviderDataSource -import com.suwiki.data.lectureevaluation.datasource.RemoteLectureReportDataSource -import com.suwiki.remote.lectureevaluation.datasource.RemoteExamEditorDataSourceImpl -import com.suwiki.remote.lectureevaluation.datasource.RemoteExamMyDataSourceImpl -import com.suwiki.remote.lectureevaluation.datasource.RemoteExamProviderDataSourceImpl -import com.suwiki.remote.lectureevaluation.datasource.RemoteExamReportDataSourceImpl -import com.suwiki.remote.lectureevaluation.datasource.RemoteLectureEditorDataSourceImpl -import com.suwiki.remote.lectureevaluation.datasource.RemoteLectureMyDataSourceImpl -import com.suwiki.remote.lectureevaluation.datasource.RemoteLectureProviderDataSourceImpl -import com.suwiki.remote.lectureevaluation.datasource.RemoteLectureReportDataSourceImpl -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -abstract class RemoteDataSourceModule { - - @Singleton - @Binds - abstract fun bindRemoteLectureEditorDatasource( - remoteLectureEditorDataSourceImpl: RemoteLectureEditorDataSourceImpl, - ): RemoteLectureEditorDataSource - - @Singleton - @Binds - abstract fun bindRemoteExamEditorDatasource( - remoteExamEditorDataSourceImpl: RemoteExamEditorDataSourceImpl, - ): RemoteExamEditorDataSource - - @Singleton - @Binds - abstract fun bindRemoteExamMyDatasource( - remoteOpenMajorDataSourceImpl: RemoteExamMyDataSourceImpl, - ): RemoteExamMyDataSource - - @Singleton - @Binds - abstract fun bindLectureExamMyDatasource( - remoteOpenMajorDataSourceImpl: RemoteLectureMyDataSourceImpl, - ): RemoteLectureMyDataSource - - @Singleton - @Binds - abstract fun bindRemoteLectureProviderDatasource( - remoteLectureProviderDataSourceImpl: RemoteLectureProviderDataSourceImpl, - ): RemoteLectureProviderDataSource - - @Singleton - @Binds - abstract fun bindRemoteExamProviderDatasource( - remoteExamProviderDataSourceImpl: RemoteExamProviderDataSourceImpl, - ): RemoteExamProviderDataSource - - @Singleton - @Binds - abstract fun bindRemoteExamReportDatasource( - remoteOpenMajorDataSourceImpl: RemoteExamReportDataSourceImpl, - ): RemoteExamReportDataSource - - @Singleton - @Binds - abstract fun bindLectureExamReportDatasource( - remoteOpenMajorDataSourceImpl: RemoteLectureReportDataSourceImpl, - ): RemoteLectureReportDataSource -} diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/PostExamEvaluationRequest.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/PostExamEvaluationRequest.kt deleted file mode 100644 index 449783115..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/PostExamEvaluationRequest.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.suwiki.remote.lectureevaluation.request - -import kotlinx.serialization.Serializable - -@Serializable -data class PostExamEvaluationRequest( - val lectureName: String?, - val professor: String?, - val selectedSemester: String?, - val examInfo: String, - val examType: String?, - val examDifficulty: String, - val content: String, -) diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/PostLectureEvaluationRequest.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/PostLectureEvaluationRequest.kt deleted file mode 100644 index 6ee2836d1..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/PostLectureEvaluationRequest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.suwiki.remote.lectureevaluation.request - -import kotlinx.serialization.Serializable - -@Serializable -data class PostLectureEvaluationRequest( - val lectureName: String, - val professor: String, - val selectedSemester: String, - val satisfaction: Float, - val learning: Float, - val honey: Float, - val team: Int, - val difficulty: Int, - val homework: Int, - val content: String, -) diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/ReportExamRequest.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/ReportExamRequest.kt deleted file mode 100644 index 13d962ce8..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/ReportExamRequest.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.suwiki.remote.lectureevaluation.request - -import kotlinx.serialization.Serializable - -@Serializable -data class ReportExamRequest( - val examIdx: Long, - val content: String = "", -) diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/ReportLectureRequest.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/ReportLectureRequest.kt deleted file mode 100644 index 7dde08d3b..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/ReportLectureRequest.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.suwiki.remote.lectureevaluation.request - -import kotlinx.serialization.Serializable - -@Serializable -data class ReportLectureRequest( - val evaluateIdx: Long, - val content: String = "", -) diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/UpdateExamEvaluationRequest.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/UpdateExamEvaluationRequest.kt deleted file mode 100644 index fe82ad055..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/UpdateExamEvaluationRequest.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.suwiki.remote.lectureevaluation.request - -import kotlinx.serialization.Serializable - -@Serializable -data class UpdateExamEvaluationRequest( - val selectedSemester: String?, - val examInfo: String, - val examType: String?, - val examDifficulty: String, - val content: String, -) diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/UpdateLectureEvaluationRequest.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/UpdateLectureEvaluationRequest.kt deleted file mode 100644 index 82a66ade8..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/request/UpdateLectureEvaluationRequest.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.suwiki.remote.lectureevaluation.request - -import kotlinx.serialization.Serializable - -@Serializable -data class UpdateLectureEvaluationRequest( - val selectedSemester: String, - val satisfaction: Float, - val learning: Float, - val honey: Float, - val team: Int, - val difficulty: Int, - val homework: Int, - val content: String, -) diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/DataResponse.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/DataResponse.kt deleted file mode 100644 index 1efaaa2cb..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/DataResponse.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.suwiki.remote.lectureevaluation.response - -import kotlinx.serialization.Serializable - -@Serializable -data class DataResponse(val data: T) diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/ExamEvaluationListResponse.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/ExamEvaluationListResponse.kt deleted file mode 100644 index f66d7a47e..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/ExamEvaluationListResponse.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.suwiki.remote.lectureevaluation.response - -import com.suwiki.common.model.lectureevaluation.exam.ExamEvaluation -import com.suwiki.common.model.lectureevaluation.exam.ExamEvaluationList -import kotlinx.serialization.Serializable - -@Serializable -data class ExamEvaluationListResponse( - val data: List, - val examDataExist: Boolean, - val written: Boolean, -) - -internal fun ExamEvaluationListResponse.toModel() = ExamEvaluationList( - data = data.map { it.toModel() }, - needBuyExam = examDataExist && data.isEmpty(), - written = written, -) - -@Serializable -data class ExamEvaluationResponse( - val id: Long, - val selectedSemester: String, - val examInfo: String, - val examType: String = "", - val examDifficulty: String, - val content: String, -) - -internal fun ExamEvaluationResponse.toModel() = ExamEvaluation( - id = id, - selectedSemester = selectedSemester, - examInfo = examInfo, - examType = examType, - examDifficulty = examDifficulty, - content = content, -) diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/LectureEvaluationAverageResponse.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/LectureEvaluationAverageResponse.kt deleted file mode 100644 index 32649b445..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/LectureEvaluationAverageResponse.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.suwiki.remote.lectureevaluation.response - -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationAverage -import com.suwiki.common.model.lectureevaluation.lecture.LectureInfo -import kotlinx.serialization.Serializable - -@Serializable -data class LectureEvaluationAverageResponse( - val id: Long, - val semesterList: String, - val professor: String, - val majorType: String, - val lectureType: String, - val lectureName: String, - val lectureTotalAvg: Float, - val lectureSatisfactionAvg: Float, - val lectureHoneyAvg: Float, - val lectureLearningAvg: Float, -) - -internal fun LectureEvaluationAverageResponse.toModel() = LectureEvaluationAverage( - id = id, - lectureInfo = LectureInfo( - semesterList = semesterList.replace(" ", "").split(","), - professor = professor, - majorType = majorType, - lectureType = lectureType, - lectureName = lectureName, - ), - lectureTotalAvg = lectureTotalAvg, - lectureSatisfactionAvg = lectureSatisfactionAvg, - lectureHoneyAvg = lectureHoneyAvg, - lectureLearningAvg = lectureLearningAvg, -) diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/LectureEvaluationExtraAverageResponse.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/LectureEvaluationExtraAverageResponse.kt deleted file mode 100644 index 60b8e97e7..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/LectureEvaluationExtraAverageResponse.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.suwiki.remote.lectureevaluation.response - -import com.suwiki.common.model.enums.GradeLevel -import com.suwiki.common.model.enums.HomeworkLevel -import com.suwiki.common.model.enums.TeamLevel -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationExtraAverage -import com.suwiki.common.model.lectureevaluation.lecture.LectureInfo -import kotlinx.serialization.Serializable -import kotlin.math.roundToInt - -@Serializable -data class LectureEvaluationExtraAverageResponse( - val id: Long, - val semesterList: String, - val professor: String, - val majorType: String, - val lectureType: String, - val lectureName: String, - val lectureTotalAvg: Float, - val lectureSatisfactionAvg: Float, - val lectureHoneyAvg: Float, - val lectureLearningAvg: Float, - val lectureTeamAvg: Float, - val lectureDifficultyAvg: Float, - val lectureHomeworkAvg: Float, -) - -internal fun LectureEvaluationExtraAverageResponse.toModel() = LectureEvaluationExtraAverage( - id = id, - info = LectureInfo( - semesterList = semesterList.replace(" ", "").split(","), - professor = professor, - majorType = majorType, - lectureType = lectureType, - lectureName = lectureName, - ), - totalAvg = lectureTotalAvg, - satisfactionAvg = lectureSatisfactionAvg, - honeyAvg = lectureHoneyAvg, - learningAvg = lectureLearningAvg, - teamAvg = TeamLevel.valueOf(lectureTeamAvg.roundToInt()), - gradeAvg = GradeLevel.valueOf(lectureDifficultyAvg.roundToInt()), - homeworkAvg = HomeworkLevel.valueOf(lectureHomeworkAvg.roundToInt()), -) diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/LectureEvaluationListResponse.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/LectureEvaluationListResponse.kt deleted file mode 100644 index 6a53bd328..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/LectureEvaluationListResponse.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.suwiki.remote.lectureevaluation.response - -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluation -import com.suwiki.common.model.lectureevaluation.lecture.LectureEvaluationList -import kotlinx.serialization.Serializable - -@Serializable -data class LectureEvaluationListResponse( - val data: List, - val written: Boolean, -) - -internal fun LectureEvaluationListResponse.toModel() = - LectureEvaluationList( - data = data.map { it.toModel() }, - written = written, - ) - -@Serializable -data class LectureEvaluationResponse( - val id: Long, - val selectedSemester: String, - val totalAvg: Float, - val satisfaction: Float, - val learning: Float, - val honey: Float, - val team: Int, - val difficulty: Int, - val homework: Int, - val content: String, -) - -internal fun LectureEvaluationResponse.toModel() = - LectureEvaluation( - id = id, - selectedSemester = selectedSemester, - totalAvg = totalAvg, - satisfaction = satisfaction, - learning = learning, - honey = honey, - team = team, - difficulty = difficulty, - homework = homework, - content = content, - ) diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/MyExamEvaluationResponse.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/MyExamEvaluationResponse.kt deleted file mode 100644 index 1d94b8053..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/MyExamEvaluationResponse.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.suwiki.remote.lectureevaluation.response - -import com.suwiki.common.model.lectureevaluation.exam.MyExamEvaluation -import kotlinx.serialization.Serializable - -@Serializable -data class MyExamEvaluationResponse( - val id: Long = -1L, - val lectureName: String = "", // 과목 이름 - val professor: String = "", // 교수이름 - val majorType: String = "", // 개설학과 - val selectedSemester: String = "", - val semesterList: String = "", - val examInfo: String, // 시험 방식 - val examType: String = "", - val examDifficulty: String, // 시험 난이도 - val content: String, -) - -internal fun MyExamEvaluationResponse.toModel() = MyExamEvaluation( - id = id, - lectureName = lectureName, - professor = professor, - majorType = majorType, - selectedSemester = selectedSemester, - semesterList = semesterList.replace(" ", "").split(","), - examInfo = examInfo.replace(" ", "").split(","), - examType = examType, - examDifficulty = examDifficulty, - content = content, -) diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/MyLectureEvaluationResponse.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/MyLectureEvaluationResponse.kt deleted file mode 100644 index 56b257782..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/MyLectureEvaluationResponse.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.suwiki.remote.lectureevaluation.response - -import com.suwiki.common.model.lectureevaluation.lecture.LectureInfo -import com.suwiki.common.model.lectureevaluation.lecture.MyLectureEvaluation -import kotlinx.serialization.Serializable - -@Serializable -data class MyLectureEvaluationResponse( - val id: Long, - val lectureName: String, // 과목이름 - val professor: String, // 교수이름 - val majorType: String, // 개설학과 - val selectedSemester: String, - val semesterList: String, - val totalAvg: Float, // 총점 - val satisfaction: Float, // 만족도 - val learning: Float, // 배움지수 - val honey: Float, // 꿀강지수 - val team: Int, // 조별모임 유무(없음 == 0, 있음 == 1) - val difficulty: Int, // 학점 잘주는가? (까다로움 == 0, 보통 == 1, 학점느님 ==2) - val homework: Int, // 과제양 (없음 ==0, 보통 == 1, 많음 == 2) - val content: String, -) - -internal fun MyLectureEvaluationResponse.toModel() = MyLectureEvaluation( - id = id, - lectureInfo = LectureInfo( - semesterList = semesterList.replace(" ", "").split(","), - professor = professor, - majorType = majorType, - lectureType = "", - lectureName = lectureName, - ), - selectedSemester = selectedSemester, - totalAvg = totalAvg, - satisfaction = satisfaction, - learning = learning, - honey = honey, - team = team, - difficulty = difficulty, - homework = homework, - content = content, -) diff --git a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/PurchaseHistoryResponse.kt b/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/PurchaseHistoryResponse.kt deleted file mode 100644 index 036734095..000000000 --- a/remote/lectureevaluation/src/main/java/com/suwiki/remote/lectureevaluation/response/PurchaseHistoryResponse.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.suwiki.remote.lectureevaluation.response - -import com.suwiki.common.model.lectureevaluation.PurchaseHistory -import kotlinx.datetime.LocalDateTime -import kotlinx.datetime.toJavaLocalDateTime -import kotlinx.serialization.Serializable - -@Serializable -data class PurchaseHistoryResponse( - val id: Long, - val lectureName: String, - val professor: String, - val majorType: String, - val createDate: LocalDateTime, -) - -internal fun PurchaseHistoryResponse.toModel() = PurchaseHistory( - id = id, - lectureName = lectureName, - professor = professor, - majorType = majorType, - createDate = createDate.toJavaLocalDateTime(), -) diff --git a/remote/login/.gitignore b/remote/login/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/remote/login/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/remote/login/build.gradle.kts b/remote/login/build.gradle.kts deleted file mode 100644 index 162ff78ca..000000000 --- a/remote/login/build.gradle.kts +++ /dev/null @@ -1,17 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.remote) - alias(libs.plugins.kotlin.serialization) -} - -android { - namespace = "com.suwiki.remote.login" -} - -dependencies { - implementation(projects.data.login) - - implementation(libs.retrofit.core) - implementation(libs.kotlinx.serialization.json) - implementation(libs.kotlinx.datetime) -} diff --git a/remote/login/consumer-rules.pro b/remote/login/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/remote/login/proguard-rules.pro b/remote/login/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/remote/login/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/remote/login/src/main/AndroidManifest.xml b/remote/login/src/main/AndroidManifest.xml deleted file mode 100644 index 8bdb7e14b..000000000 --- a/remote/login/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/remote/login/src/main/java/com/suwiki/remote/login/api/LoginApi.kt b/remote/login/src/main/java/com/suwiki/remote/login/api/LoginApi.kt deleted file mode 100644 index 52f69939e..000000000 --- a/remote/login/src/main/java/com/suwiki/remote/login/api/LoginApi.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.suwiki.remote.login.api - -import com.suwiki.remote.common.retrofit.ApiResult -import com.suwiki.remote.login.request.FindIdRequest -import com.suwiki.remote.login.request.FindPasswordRequest -import com.suwiki.remote.login.request.LoginRequest -import com.suwiki.remote.login.response.SuccessCheckResponse -import com.suwiki.remote.login.response.TokenResponse -import retrofit2.http.Body -import retrofit2.http.POST - -// TODO : v2 api로 업그레이드 필요. -interface LoginApi { - companion object { - const val USER = "/user" - } - - // 아이디 찾기 API - @POST("$USER/find-id") - suspend fun findId( - @Body findIdRequest: FindIdRequest, - ): ApiResult - - // 비밀번호 찾기(임시 비밀번호 전송) API - @POST("$USER/find-pw") - suspend fun findPassword( - @Body findPasswordRequest: FindPasswordRequest, - ): ApiResult - - // 로그인 요청 API - @POST("$USER/login") - suspend fun login( - @Body loginRequest: LoginRequest, - ): ApiResult -} diff --git a/remote/login/src/main/java/com/suwiki/remote/login/datasource/RemoteLoginDataSourceImpl.kt b/remote/login/src/main/java/com/suwiki/remote/login/datasource/RemoteLoginDataSourceImpl.kt deleted file mode 100644 index 011b10bb7..000000000 --- a/remote/login/src/main/java/com/suwiki/remote/login/datasource/RemoteLoginDataSourceImpl.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.suwiki.remote.login.datasource - -import com.suwiki.common.model.exception.RequestFailException -import com.suwiki.common.model.user.Token -import com.suwiki.data.login.datasource.RemoteLoginDataSource -import com.suwiki.remote.login.api.LoginApi -import com.suwiki.remote.login.request.FindIdRequest -import com.suwiki.remote.login.request.FindPasswordRequest -import com.suwiki.remote.login.request.LoginRequest -import com.suwiki.remote.login.response.toModel -import javax.inject.Inject - -class RemoteLoginDataSourceImpl @Inject constructor( - private val loginApi: LoginApi, -) : RemoteLoginDataSource { - - override suspend fun findId(email: String) { - loginApi - .findId(FindIdRequest(email)) - .getOrThrow() - .run { - if (!success) throw RequestFailException() - } - } - - override suspend fun findPassword(loginId: String, email: String) { - loginApi - .findPassword( - FindPasswordRequest(loginId, email), - ) - .getOrThrow() - .run { - if (!success) throw RequestFailException() - } - } - - override suspend fun login(loginId: String, password: String): Token { - return loginApi.login( - LoginRequest( - loginId = loginId, - password = password, - ), - ).getOrThrow().toModel() - } -} diff --git a/remote/login/src/main/java/com/suwiki/remote/login/di/ApiModule.kt b/remote/login/src/main/java/com/suwiki/remote/login/di/ApiModule.kt deleted file mode 100644 index 91602764b..000000000 --- a/remote/login/src/main/java/com/suwiki/remote/login/di/ApiModule.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.suwiki.remote.login.di - -import com.suwiki.remote.common.di.AuthRetrofit -import com.suwiki.remote.login.api.LoginApi -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import retrofit2.Retrofit -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -object ApiModule { - - @Singleton - @Provides - fun provideUserApi(@AuthRetrofit retrofit: Retrofit): LoginApi { - return retrofit.create(LoginApi::class.java) - } -} diff --git a/remote/login/src/main/java/com/suwiki/remote/login/di/RemoteDataSourceModule.kt b/remote/login/src/main/java/com/suwiki/remote/login/di/RemoteDataSourceModule.kt deleted file mode 100644 index ebe86dbd6..000000000 --- a/remote/login/src/main/java/com/suwiki/remote/login/di/RemoteDataSourceModule.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.suwiki.remote.login.di - -import com.suwiki.data.login.datasource.RemoteLoginDataSource -import com.suwiki.remote.login.datasource.RemoteLoginDataSourceImpl -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -abstract class RemoteDataSourceModule { - - @Singleton - @Binds - abstract fun bindRemoteLoginDatasource( - remoteLoginDataSourceImpl: RemoteLoginDataSourceImpl, - ): RemoteLoginDataSource -} diff --git a/remote/login/src/main/java/com/suwiki/remote/login/request/FindIdRequest.kt b/remote/login/src/main/java/com/suwiki/remote/login/request/FindIdRequest.kt deleted file mode 100644 index bc5366068..000000000 --- a/remote/login/src/main/java/com/suwiki/remote/login/request/FindIdRequest.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.suwiki.remote.login.request - -import kotlinx.serialization.Serializable - -@Serializable -data class FindIdRequest(val email: String) diff --git a/remote/login/src/main/java/com/suwiki/remote/login/request/FindPasswordRequest.kt b/remote/login/src/main/java/com/suwiki/remote/login/request/FindPasswordRequest.kt deleted file mode 100644 index 47a0c4c2e..000000000 --- a/remote/login/src/main/java/com/suwiki/remote/login/request/FindPasswordRequest.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.suwiki.remote.login.request - -import kotlinx.serialization.Serializable - -@Serializable -data class FindPasswordRequest( - val loginId: String, - val email: String, -) diff --git a/remote/login/src/main/java/com/suwiki/remote/login/request/LoginRequest.kt b/remote/login/src/main/java/com/suwiki/remote/login/request/LoginRequest.kt deleted file mode 100644 index 9b4a84b36..000000000 --- a/remote/login/src/main/java/com/suwiki/remote/login/request/LoginRequest.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.suwiki.remote.login.request - -import kotlinx.serialization.Serializable - -@Serializable -data class LoginRequest( - val loginId: String, - val password: String, -) diff --git a/remote/login/src/main/java/com/suwiki/remote/login/response/SuccessCheckResponse.kt b/remote/login/src/main/java/com/suwiki/remote/login/response/SuccessCheckResponse.kt deleted file mode 100644 index b7bc7f9f2..000000000 --- a/remote/login/src/main/java/com/suwiki/remote/login/response/SuccessCheckResponse.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.suwiki.remote.login.response - -import kotlinx.serialization.Serializable - -@Serializable -data class SuccessCheckResponse( - val success: Boolean, -) diff --git a/remote/login/src/main/java/com/suwiki/remote/login/response/TokenResponse.kt b/remote/login/src/main/java/com/suwiki/remote/login/response/TokenResponse.kt deleted file mode 100644 index 02aaeb33f..000000000 --- a/remote/login/src/main/java/com/suwiki/remote/login/response/TokenResponse.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.suwiki.remote.login.response - -import com.suwiki.common.model.user.Token -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -data class TokenResponse( - @SerialName("AccessToken") val accessToken: String, - @SerialName("RefreshToken") val refreshToken: String, -) - -internal fun TokenResponse.toModel() = Token( - accessToken = accessToken, - refreshToken = refreshToken, -) diff --git a/remote/notice/.gitignore b/remote/notice/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/remote/notice/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/remote/notice/build.gradle.kts b/remote/notice/build.gradle.kts deleted file mode 100644 index 539cd3f91..000000000 --- a/remote/notice/build.gradle.kts +++ /dev/null @@ -1,17 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.remote) - alias(libs.plugins.kotlin.serialization) -} - -android { - namespace = "com.suwiki.remote.notice" -} - -dependencies { - implementation(projects.data.notice) - - implementation(libs.retrofit.core) - implementation(libs.kotlinx.serialization.json) - implementation(libs.kotlinx.datetime) -} diff --git a/remote/notice/consumer-rules.pro b/remote/notice/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/remote/notice/proguard-rules.pro b/remote/notice/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/remote/notice/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/remote/notice/src/main/AndroidManifest.xml b/remote/notice/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e68a..000000000 --- a/remote/notice/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/remote/notice/src/main/java/com/suwiki/remote/notice/api/NoticeApi.kt b/remote/notice/src/main/java/com/suwiki/remote/notice/api/NoticeApi.kt deleted file mode 100644 index 7ff918a3e..000000000 --- a/remote/notice/src/main/java/com/suwiki/remote/notice/api/NoticeApi.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.suwiki.remote.notice.api - -import com.suwiki.remote.common.retrofit.ApiResult -import com.suwiki.remote.notice.response.DataResponse -import com.suwiki.remote.notice.response.NoticeDetailResponse -import com.suwiki.remote.notice.response.NoticeResponse -import com.suwiki.remote.notice.response.UpdateMandatoryResponse -import retrofit2.http.GET -import retrofit2.http.Query - -interface NoticeApi { - companion object { - const val NOTICE: String = "/notice" - const val QUERY_NOTICE_ID = "noticeId" - const val QUERY_PAGE = "page" - } - - // 공지사항 리스트 API - @GET("$NOTICE/all") - suspend fun getNoticeList( - @Query(QUERY_PAGE) page: Int, - ): ApiResult>> - - // 공지사항 API - @GET("$NOTICE/") - suspend fun getNotice( - @Query(QUERY_NOTICE_ID) id: Long, - ): ApiResult> - - @GET("/client/version/update-mandatory") - suspend fun checkUpdateMandatory( - @Query("os") os: String = "android", - @Query("versionCode") versionCode: Long, - ): ApiResult -} diff --git a/remote/notice/src/main/java/com/suwiki/remote/notice/datasource/RemoteNoticeDataSourceImpl.kt b/remote/notice/src/main/java/com/suwiki/remote/notice/datasource/RemoteNoticeDataSourceImpl.kt deleted file mode 100644 index 066dab41e..000000000 --- a/remote/notice/src/main/java/com/suwiki/remote/notice/datasource/RemoteNoticeDataSourceImpl.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.suwiki.remote.notice.datasource - -import com.suwiki.common.model.notice.Notice -import com.suwiki.common.model.notice.NoticeDetail -import com.suwiki.data.notice.datasource.RemoteNoticeDataSource -import com.suwiki.remote.notice.api.NoticeApi -import com.suwiki.remote.notice.response.toModel -import javax.inject.Inject - -class RemoteNoticeDataSourceImpl @Inject constructor( - private val noticeApi: NoticeApi, -) : RemoteNoticeDataSource { - - override suspend fun getNoticeList(page: Int): List { - return noticeApi.getNoticeList(page).getOrThrow().data.map { it.toModel() } - } - - override suspend fun getNoticeDetail(id: Long): NoticeDetail { - return noticeApi.getNotice(id).getOrThrow().data.toModel() - } - - override suspend fun checkUpdateMandatory(versionCode: Long): Boolean { - return noticeApi.checkUpdateMandatory(versionCode = versionCode).getOrThrow().isUpdateMandatory - } -} diff --git a/remote/notice/src/main/java/com/suwiki/remote/notice/di/ApiModule.kt b/remote/notice/src/main/java/com/suwiki/remote/notice/di/ApiModule.kt deleted file mode 100644 index 7565750be..000000000 --- a/remote/notice/src/main/java/com/suwiki/remote/notice/di/ApiModule.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.suwiki.remote.notice.di - -import com.suwiki.remote.common.di.NoAuthRetrofit -import com.suwiki.remote.notice.api.NoticeApi -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import retrofit2.Retrofit -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -object ApiModule { - - @Singleton - @Provides - fun provideNoticeApi(@NoAuthRetrofit retrofit: Retrofit): NoticeApi { - return retrofit.create(NoticeApi::class.java) - } -} diff --git a/remote/notice/src/main/java/com/suwiki/remote/notice/di/RemoteDataSourceModule.kt b/remote/notice/src/main/java/com/suwiki/remote/notice/di/RemoteDataSourceModule.kt deleted file mode 100644 index cea37f796..000000000 --- a/remote/notice/src/main/java/com/suwiki/remote/notice/di/RemoteDataSourceModule.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.suwiki.remote.notice.di - -import com.suwiki.data.notice.datasource.RemoteNoticeDataSource -import com.suwiki.remote.notice.datasource.RemoteNoticeDataSourceImpl -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -abstract class RemoteDataSourceModule { - - @Singleton - @Binds - abstract fun bindRemoteNoticeDatasource( - remoteNoticeDataSourceImpl: RemoteNoticeDataSourceImpl, - ): RemoteNoticeDataSource -} diff --git a/remote/notice/src/main/java/com/suwiki/remote/notice/response/DataResponse.kt b/remote/notice/src/main/java/com/suwiki/remote/notice/response/DataResponse.kt deleted file mode 100644 index b1f41cb22..000000000 --- a/remote/notice/src/main/java/com/suwiki/remote/notice/response/DataResponse.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.suwiki.remote.notice.response - -import kotlinx.serialization.Serializable - -@Serializable -data class DataResponse(val data: T) diff --git a/remote/notice/src/main/java/com/suwiki/remote/notice/response/NoticeDetailResponse.kt b/remote/notice/src/main/java/com/suwiki/remote/notice/response/NoticeDetailResponse.kt deleted file mode 100644 index 67edd1ca4..000000000 --- a/remote/notice/src/main/java/com/suwiki/remote/notice/response/NoticeDetailResponse.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.suwiki.remote.notice.response - -import com.suwiki.common.model.notice.NoticeDetail -import kotlinx.datetime.LocalDateTime -import kotlinx.datetime.toJavaLocalDateTime -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -data class NoticeDetailResponse( - val id: Long, - val title: String, - @SerialName("modifiedDate") val date: LocalDateTime?, - val content: String, -) - -internal fun NoticeDetailResponse.toModel() = NoticeDetail( - id = id, - title = title, - date = date?.toJavaLocalDateTime(), - content = content, -) diff --git a/remote/notice/src/main/java/com/suwiki/remote/notice/response/NoticeResponse.kt b/remote/notice/src/main/java/com/suwiki/remote/notice/response/NoticeResponse.kt deleted file mode 100644 index 14e1f3b30..000000000 --- a/remote/notice/src/main/java/com/suwiki/remote/notice/response/NoticeResponse.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.suwiki.remote.notice.response - -import com.suwiki.common.model.notice.Notice -import kotlinx.datetime.LocalDateTime -import kotlinx.datetime.toJavaLocalDateTime -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -data class NoticeResponse( - val id: Long, - val title: String, - @SerialName("modifiedDate") val date: LocalDateTime, -) - -internal fun NoticeResponse.toModel() = Notice( - id = id, - title = title, - date = date.toJavaLocalDateTime(), -) diff --git a/remote/notice/src/main/java/com/suwiki/remote/notice/response/UpdateMandatoryResponse.kt b/remote/notice/src/main/java/com/suwiki/remote/notice/response/UpdateMandatoryResponse.kt deleted file mode 100644 index 71baccb44..000000000 --- a/remote/notice/src/main/java/com/suwiki/remote/notice/response/UpdateMandatoryResponse.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.suwiki.remote.notice.response - -import kotlinx.serialization.Serializable - -@Serializable -data class UpdateMandatoryResponse( - val isUpdateMandatory: Boolean, -) diff --git a/remote/signup/.gitignore b/remote/signup/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/remote/signup/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/remote/signup/build.gradle.kts b/remote/signup/build.gradle.kts deleted file mode 100644 index e4f264908..000000000 --- a/remote/signup/build.gradle.kts +++ /dev/null @@ -1,17 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.remote) - alias(libs.plugins.kotlin.serialization) -} - -android { - namespace = "com.suwiki.remote.signup" -} - -dependencies { - implementation(projects.data.signup) - - implementation(libs.retrofit.core) - implementation(libs.kotlinx.serialization.json) - implementation(libs.kotlinx.datetime) -} diff --git a/remote/signup/consumer-rules.pro b/remote/signup/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/remote/signup/proguard-rules.pro b/remote/signup/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/remote/signup/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/remote/signup/src/main/AndroidManifest.xml b/remote/signup/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e68a..000000000 --- a/remote/signup/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/remote/signup/src/main/java/com/suwiki/remote/signup/api/SignUpApi.kt b/remote/signup/src/main/java/com/suwiki/remote/signup/api/SignUpApi.kt deleted file mode 100644 index 8f4fbdc23..000000000 --- a/remote/signup/src/main/java/com/suwiki/remote/signup/api/SignUpApi.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.suwiki.remote.signup.api - -import com.suwiki.remote.common.retrofit.ApiResult -import com.suwiki.remote.signup.request.CheckEmailRequest -import com.suwiki.remote.signup.request.CheckIdRequest -import com.suwiki.remote.signup.request.SignupRequest -import com.suwiki.remote.signup.response.OverlapCheckResponse -import com.suwiki.remote.signup.response.SuccessCheckResponse -import retrofit2.http.Body -import retrofit2.http.POST - -// TODO : v2 api로 업그레이드 필요. -interface SignUpApi { - companion object { - const val USER = "/user" - } - - // 회원가입 요청 API - @POST("$USER/join") - suspend fun signUp(@Body signupRequest: SignupRequest): ApiResult - - // 아이디 중복 확인 요청 API - @POST("$USER/check-id") - suspend fun checkId(@Body checkIdRequest: CheckIdRequest): ApiResult - - // 이메일 중복 확인 요청 API - @POST("$USER/check-email") - suspend fun checkEmail(@Body checkEmailRequest: CheckEmailRequest): ApiResult -} diff --git a/remote/signup/src/main/java/com/suwiki/remote/signup/datasource/RemoteSignUpDataSourceImpl.kt b/remote/signup/src/main/java/com/suwiki/remote/signup/datasource/RemoteSignUpDataSourceImpl.kt deleted file mode 100644 index 22e8b6f88..000000000 --- a/remote/signup/src/main/java/com/suwiki/remote/signup/datasource/RemoteSignUpDataSourceImpl.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.suwiki.remote.signup.datasource - -import com.suwiki.common.model.exception.RequestFailException -import com.suwiki.data.signup.datasource.RemoteSignUpDataSource -import com.suwiki.remote.signup.api.SignUpApi -import com.suwiki.remote.signup.request.CheckEmailRequest -import com.suwiki.remote.signup.request.CheckIdRequest -import com.suwiki.remote.signup.request.SignupRequest -import javax.inject.Inject - -class RemoteSignUpDataSourceImpl @Inject constructor( - private val signUpApi: SignUpApi, -) : RemoteSignUpDataSource { - override suspend fun signUp(id: String, password: String, email: String) { - val request = SignupRequest( - loginId = id, - password = password, - email = email, - ) - - signUpApi - .signUp( - signupRequest = request, - ) - .getOrThrow() - .run { if (!success) throw RequestFailException() } - } - - override suspend fun checkIdOverlap(loginId: String): Boolean { - return signUpApi.checkId(CheckIdRequest(loginId)).getOrThrow().overlap - } - - override suspend fun checkEmailOverlap(email: String): Boolean { - return signUpApi.checkEmail(CheckEmailRequest(email)).getOrThrow().overlap - } -} diff --git a/remote/signup/src/main/java/com/suwiki/remote/signup/di/ApiModule.kt b/remote/signup/src/main/java/com/suwiki/remote/signup/di/ApiModule.kt deleted file mode 100644 index 26cdf4af3..000000000 --- a/remote/signup/src/main/java/com/suwiki/remote/signup/di/ApiModule.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.suwiki.remote.signup.di - -import com.suwiki.remote.common.di.NoAuthRetrofit -import com.suwiki.remote.signup.api.SignUpApi -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import retrofit2.Retrofit - -@Module -@InstallIn(SingletonComponent::class) -object ApiModule { - - @Provides - fun provideSignUpApi(@NoAuthRetrofit retrofit: Retrofit): SignUpApi { - return retrofit.create(SignUpApi::class.java) - } -} diff --git a/remote/signup/src/main/java/com/suwiki/remote/signup/di/RemoteDataSourceModule.kt b/remote/signup/src/main/java/com/suwiki/remote/signup/di/RemoteDataSourceModule.kt deleted file mode 100644 index 778f51b58..000000000 --- a/remote/signup/src/main/java/com/suwiki/remote/signup/di/RemoteDataSourceModule.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.suwiki.remote.signup.di - -import com.suwiki.data.signup.datasource.RemoteSignUpDataSource -import com.suwiki.remote.signup.datasource.RemoteSignUpDataSourceImpl -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -abstract class RemoteDataSourceModule { - - @Singleton - @Binds - abstract fun bindRemoteSignUpDatasource( - remoteSignUpDataSourceImpl: RemoteSignUpDataSourceImpl, - ): RemoteSignUpDataSource -} diff --git a/remote/signup/src/main/java/com/suwiki/remote/signup/request/CheckEmailRequest.kt b/remote/signup/src/main/java/com/suwiki/remote/signup/request/CheckEmailRequest.kt deleted file mode 100644 index c1ff329d6..000000000 --- a/remote/signup/src/main/java/com/suwiki/remote/signup/request/CheckEmailRequest.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.suwiki.remote.signup.request - -import kotlinx.serialization.Serializable - -@Serializable -data class CheckEmailRequest(val email: String) diff --git a/remote/signup/src/main/java/com/suwiki/remote/signup/request/CheckIdRequest.kt b/remote/signup/src/main/java/com/suwiki/remote/signup/request/CheckIdRequest.kt deleted file mode 100644 index bc635f878..000000000 --- a/remote/signup/src/main/java/com/suwiki/remote/signup/request/CheckIdRequest.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.suwiki.remote.signup.request - -import kotlinx.serialization.Serializable - -@Serializable -data class CheckIdRequest(val loginId: String) diff --git a/remote/signup/src/main/java/com/suwiki/remote/signup/request/SignupRequest.kt b/remote/signup/src/main/java/com/suwiki/remote/signup/request/SignupRequest.kt deleted file mode 100644 index 62e5770a1..000000000 --- a/remote/signup/src/main/java/com/suwiki/remote/signup/request/SignupRequest.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.suwiki.remote.signup.request - -import kotlinx.serialization.Serializable - -@Serializable -data class SignupRequest( - val loginId: String, - val password: String, - val email: String, -) diff --git a/remote/signup/src/main/java/com/suwiki/remote/signup/response/OverlapCheckResponse.kt b/remote/signup/src/main/java/com/suwiki/remote/signup/response/OverlapCheckResponse.kt deleted file mode 100644 index c42f476b4..000000000 --- a/remote/signup/src/main/java/com/suwiki/remote/signup/response/OverlapCheckResponse.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.suwiki.remote.signup.response - -import kotlinx.serialization.Serializable - -@Serializable -data class OverlapCheckResponse( - val overlap: Boolean, -) diff --git a/remote/signup/src/main/java/com/suwiki/remote/signup/response/SuccessCheckResponse.kt b/remote/signup/src/main/java/com/suwiki/remote/signup/response/SuccessCheckResponse.kt deleted file mode 100644 index 12930f16a..000000000 --- a/remote/signup/src/main/java/com/suwiki/remote/signup/response/SuccessCheckResponse.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.suwiki.remote.signup.response - -import kotlinx.serialization.Serializable - -@Serializable -data class SuccessCheckResponse( - val success: Boolean, -) diff --git a/remote/user/.gitignore b/remote/user/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/remote/user/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/remote/user/build.gradle.kts b/remote/user/build.gradle.kts deleted file mode 100644 index bc9d4cb61..000000000 --- a/remote/user/build.gradle.kts +++ /dev/null @@ -1,17 +0,0 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed -plugins { - alias(libs.plugins.suwiki.android.remote) - alias(libs.plugins.kotlin.serialization) -} - -android { - namespace = "com.suwiki.remote.user" -} - -dependencies { - implementation(projects.data.user) - - implementation(libs.retrofit.core) - implementation(libs.kotlinx.serialization.json) - implementation(libs.kotlinx.datetime) -} diff --git a/remote/user/consumer-rules.pro b/remote/user/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/remote/user/proguard-rules.pro b/remote/user/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/remote/user/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/remote/user/src/main/AndroidManifest.xml b/remote/user/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e68a..000000000 --- a/remote/user/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/remote/user/src/main/java/com/suwiki/remote/user/api/UserApi.kt b/remote/user/src/main/java/com/suwiki/remote/user/api/UserApi.kt deleted file mode 100644 index 2a84c44b0..000000000 --- a/remote/user/src/main/java/com/suwiki/remote/user/api/UserApi.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.suwiki.remote.user.api - -import com.suwiki.remote.common.retrofit.ApiResult -import com.suwiki.remote.user.request.QuitRequest -import com.suwiki.remote.user.request.ResetPasswordRequest -import com.suwiki.remote.user.response.BanHistoryResponse -import com.suwiki.remote.user.response.BlackListResponse -import com.suwiki.remote.user.response.SuccessCheckResponse -import com.suwiki.remote.user.response.UserResponse -import retrofit2.http.Body -import retrofit2.http.GET -import retrofit2.http.POST - -// TODO : v2 api로 업그레이드 필요. -interface UserApi { - companion object { - const val USER = "/user" - } - - // 비밀번호 재설정 API - @POST("$USER/reset-pw") - suspend fun resetPassword( - @Body resetPasswordRequest: ResetPasswordRequest, - ): ApiResult - - // 회원탈퇴 요청 API - @POST("$USER/quit") - suspend fun quit( - @Body quitRequest: QuitRequest, - ): ApiResult - - // 내 정보 페이지 호출 API - @GET("$USER/my-page") - suspend fun getUserData(): ApiResult - - // 이용제한 내역 조회 API - @GET("$USER/restricted-reason") - suspend fun getBanHistoryData(): ApiResult> - - // 블랙리스트 내역 조회 API - @GET("$USER/blacklist-reason") - suspend fun getBlackListData(): ApiResult> -} diff --git a/remote/user/src/main/java/com/suwiki/remote/user/datasource/RemoteUserDataSourceImpl.kt b/remote/user/src/main/java/com/suwiki/remote/user/datasource/RemoteUserDataSourceImpl.kt deleted file mode 100644 index 01d0fc3af..000000000 --- a/remote/user/src/main/java/com/suwiki/remote/user/datasource/RemoteUserDataSourceImpl.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.suwiki.remote.user.datasource - -import com.suwiki.common.model.exception.RequestFailException -import com.suwiki.common.model.user.Suspension -import com.suwiki.common.model.user.User -import com.suwiki.data.user.datasource.RemoteUserDataSource -import com.suwiki.remote.user.api.UserApi -import com.suwiki.remote.user.request.QuitRequest -import com.suwiki.remote.user.request.ResetPasswordRequest -import com.suwiki.remote.user.response.toModel -import javax.inject.Inject - -class RemoteUserDataSourceImpl @Inject constructor( - private val userApi: UserApi, -) : RemoteUserDataSource { - - override suspend fun resetPassword( - currentPassword: String, - newPassword: String, - ) { - userApi.resetPassword( - ResetPasswordRequest( - currentPassword = currentPassword, - newPassword = newPassword, - ), - ).getOrThrow().run { - if (!success) throw RequestFailException() - } - } - - override suspend fun quit(id: String, password: String) { - userApi.quit( - QuitRequest( - id = id, - password = password, - ), - ) - .getOrThrow() - .run { - if (!success) throw RequestFailException() - } - } - - override suspend fun getUserInfo(): User { - return userApi.getUserData().getOrThrow().toModel() - } - - override suspend fun getBanHistory(): List { - return userApi.getBanHistoryData().getOrThrow().map { it.toModel() } - } - - override suspend fun getBlackList(): List { - return userApi.getBlackListData().getOrThrow().map { it.toModel() } - } -} diff --git a/remote/user/src/main/java/com/suwiki/remote/user/di/ApiModule.kt b/remote/user/src/main/java/com/suwiki/remote/user/di/ApiModule.kt deleted file mode 100644 index 580708e64..000000000 --- a/remote/user/src/main/java/com/suwiki/remote/user/di/ApiModule.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.suwiki.remote.user.di - -import com.suwiki.remote.common.di.AuthRetrofit -import com.suwiki.remote.user.api.UserApi -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import retrofit2.Retrofit -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -object ApiModule { - - @Singleton - @Provides - fun provideUserApi(@AuthRetrofit retrofit: Retrofit): UserApi { - return retrofit.create(UserApi::class.java) - } -} diff --git a/remote/user/src/main/java/com/suwiki/remote/user/di/RemoteDataSourceModule.kt b/remote/user/src/main/java/com/suwiki/remote/user/di/RemoteDataSourceModule.kt deleted file mode 100644 index 11640eef2..000000000 --- a/remote/user/src/main/java/com/suwiki/remote/user/di/RemoteDataSourceModule.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.suwiki.remote.user.di - -import com.suwiki.data.user.datasource.RemoteUserDataSource -import com.suwiki.remote.user.datasource.RemoteUserDataSourceImpl -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -abstract class RemoteDataSourceModule { - - @Singleton - @Binds - abstract fun bindRemoteUserDatasource( - remoteUserDataSourceImpl: RemoteUserDataSourceImpl, - ): RemoteUserDataSource -} diff --git a/remote/user/src/main/java/com/suwiki/remote/user/request/QuitRequest.kt b/remote/user/src/main/java/com/suwiki/remote/user/request/QuitRequest.kt deleted file mode 100644 index 98aea1a42..000000000 --- a/remote/user/src/main/java/com/suwiki/remote/user/request/QuitRequest.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.suwiki.remote.user.request - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -data class QuitRequest( - @SerialName("loginId") - val id: String, - val password: String, -) diff --git a/remote/user/src/main/java/com/suwiki/remote/user/request/ResetPasswordRequest.kt b/remote/user/src/main/java/com/suwiki/remote/user/request/ResetPasswordRequest.kt deleted file mode 100644 index 7fd507568..000000000 --- a/remote/user/src/main/java/com/suwiki/remote/user/request/ResetPasswordRequest.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.suwiki.remote.user.request - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -data class ResetPasswordRequest( - @SerialName("prePassword") - val currentPassword: String, - val newPassword: String, -) diff --git a/remote/user/src/main/java/com/suwiki/remote/user/response/BanHistoryResponse.kt b/remote/user/src/main/java/com/suwiki/remote/user/response/BanHistoryResponse.kt deleted file mode 100644 index fbfeb781a..000000000 --- a/remote/user/src/main/java/com/suwiki/remote/user/response/BanHistoryResponse.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.suwiki.remote.user.response - -import com.suwiki.common.model.user.Suspension -import kotlinx.datetime.LocalDateTime -import kotlinx.datetime.toJavaLocalDateTime -import kotlinx.serialization.Serializable - -@Serializable -data class BanHistoryResponse( - val restrictedReason: String, - val judgement: String, - val createdAt: LocalDateTime, - val restrictingDate: LocalDateTime, -) - -internal fun BanHistoryResponse.toModel() = Suspension.Ban( - reason = restrictedReason, - judgement = judgement, - createdAt = createdAt.toJavaLocalDateTime(), - expiredAt = restrictingDate.toJavaLocalDateTime(), -) diff --git a/remote/user/src/main/java/com/suwiki/remote/user/response/BlackListResponse.kt b/remote/user/src/main/java/com/suwiki/remote/user/response/BlackListResponse.kt deleted file mode 100644 index 088e9e5b4..000000000 --- a/remote/user/src/main/java/com/suwiki/remote/user/response/BlackListResponse.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.suwiki.remote.user.response - -import com.suwiki.common.model.user.Suspension -import kotlinx.datetime.LocalDateTime -import kotlinx.datetime.toJavaLocalDateTime -import kotlinx.serialization.Serializable - -@Serializable -data class BlackListResponse( - val blackListReason: String, // 블랙리스트 사유 - val judgement: String, // 조치사항 - val createdAt: LocalDateTime, // 블랙리스트 된 시각 - val expiredAt: LocalDateTime, // 블랙리스트 풀리는 시각 -) - -internal fun BlackListResponse.toModel() = Suspension.Block( - reason = blackListReason, - judgement = judgement, - createdAt = createdAt.toJavaLocalDateTime(), - expiredAt = expiredAt.toJavaLocalDateTime(), -) diff --git a/remote/user/src/main/java/com/suwiki/remote/user/response/SuccessCheckResponse.kt b/remote/user/src/main/java/com/suwiki/remote/user/response/SuccessCheckResponse.kt deleted file mode 100644 index 8b30d762f..000000000 --- a/remote/user/src/main/java/com/suwiki/remote/user/response/SuccessCheckResponse.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.suwiki.remote.user.response - -import kotlinx.serialization.Serializable - -@Serializable -data class SuccessCheckResponse( - val success: Boolean, -) diff --git a/remote/user/src/main/java/com/suwiki/remote/user/response/TokenResponse.kt b/remote/user/src/main/java/com/suwiki/remote/user/response/TokenResponse.kt deleted file mode 100644 index 6de583a4b..000000000 --- a/remote/user/src/main/java/com/suwiki/remote/user/response/TokenResponse.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.suwiki.remote.user.response - -import com.suwiki.common.model.user.Token -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -data class TokenResponse( - @SerialName("AccessToken") val accessToken: String, - @SerialName("RefreshToken") val refreshToken: String, -) - -internal fun TokenResponse.toModel() = Token( - accessToken = accessToken, - refreshToken = refreshToken, -) diff --git a/remote/user/src/main/java/com/suwiki/remote/user/response/UserResponse.kt b/remote/user/src/main/java/com/suwiki/remote/user/response/UserResponse.kt deleted file mode 100644 index 991257197..000000000 --- a/remote/user/src/main/java/com/suwiki/remote/user/response/UserResponse.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.suwiki.remote.user.response - -import com.suwiki.common.model.user.User -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -data class UserResponse( - @SerialName("loginId") val userId: String, - val email: String, - val point: Int = 0, - val writtenEvaluation: Int = 0, - val writtenExam: Int = 0, - val viewExam: Int = 0, -) - -internal fun UserResponse.toModel() = User( - userId = userId, - email = email, - point = point, - writtenEvaluation = writtenEvaluation, - writtenExam = writtenExam, - viewExam = viewExam, -) diff --git a/settings.gradle.kts b/settings.gradle.kts index 04abfa774..6fb361994 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -26,41 +26,19 @@ include(":common:security") include(":remote:openmajor") include(":remote:timetable") -include(":remote:lectureevaluation") -include(":remote:signup") -include(":remote:notice") -include(":remote:user") -include(":remote:login") include(":local:openmajor") include(":local:timetable") -include(":local:user") -include(":local:login") include(":data:openmajor") include(":data:timetable") -include(":data:lectureevaluation") -include(":data:user") -include(":data:notice") -include(":data:signup") -include(":data:login") include(":domain:openmajor") -include(":domain:user") -include(":domain:signup") -include(":domain:lectureevaluation") include(":domain:timetable") -include(":domain:notice") -include(":domain:login") include(":presentation:navigator") include(":presentation:openmajor") include(":presentation:timetable") -include(":presentation:lectureevaluation") -include(":presentation:myinfo") -include(":presentation:notice") -include(":presentation:signup") -include(":presentation:login") include(":local:common") include(":remote:common") include(":domain:common")