Skip to content

Commit

Permalink
Merge pull request #22 from Nexters/feature/#9_my-page-2
Browse files Browse the repository at this point in the history
#9: 마이페이지 구현
  • Loading branch information
yxnsx authored Aug 14, 2023
2 parents 342f00f + 6b5c773 commit 77a1dee
Show file tree
Hide file tree
Showing 44 changed files with 1,145 additions and 504 deletions.
13 changes: 9 additions & 4 deletions app/src/main/java/com/keyme/app/ui/KeymeApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import com.keyme.presentation.alarm.ui.AlarmDestination
import com.keyme.presentation.alarm.ui.alarmGraph
import com.keyme.presentation.designsystem.theme.KeymeTheme
import com.keyme.presentation.feed.ui.feedGraph
import com.keyme.presentation.myprofile.ui.KeymeTestResultDetailDestination
import com.keyme.presentation.myprofile.ui.keymeTestResultDetailGraph
import com.keyme.presentation.myprofile.ui.KeymeQuestionResultDestination
import com.keyme.presentation.myprofile.ui.keymeQuestionResultGraph
import com.keyme.presentation.myprofile.ui.myProfileGraph
import com.keyme.presentation.nickname.NicknameDestination
import com.keyme.presentation.nickname.nicknameGraph
Expand Down Expand Up @@ -62,9 +62,14 @@ fun KeymeApp() {
},
)
myProfileGraph(
navigateToDetail = { appState.navigate(KeymeTestResultDetailDestination) },
navigateToQuestionResult = { question ->
appState.navigate(
KeymeQuestionResultDestination,
question.questionId,
)
},
nestedGraphs = {
keymeTestResultDetailGraph(onBackClick = appState::onBackClick)
keymeQuestionResultGraph(onBackClick = appState::onBackClick)
},
)
}
Expand Down
12 changes: 12 additions & 0 deletions app/src/main/java/com/keyme/app/ui/KeymeAppState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ class KeymeAppState(
}
}

fun navigate(destination: KeymeNavigationDestination, args: Any) {
if (destination is TopLevelDestination) {
navController.navigate("${destination.route}/$args") {
popUpTo(navController.graph.findStartDestination().id) { saveState = true }
launchSingleTop = true
restoreState = true
}
} else {
navController.navigate("${destination.route}/$args")
}
}

fun onBackClick() {
navController.popBackStack()
}
Expand Down
20 changes: 19 additions & 1 deletion buildSrc/src/main/java/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ object Dependencies {
private val composeNavigation = "androidx.navigation:navigation-compose:${Versions.COMPOSE_NAVIGATION}"
private val runtime_compose = "androidx.lifecycle:lifecycle-runtime-compose:2.6.1"


// ViewModel
private val viewModelKtx = "androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.LIFECYCLE}"

Expand All @@ -44,6 +43,11 @@ object Dependencies {
// Image
private val glide = "com.github.bumptech.glide:glide:${Versions.GLIDE}"

// Coil
private val coil = "io.coil-kt:coil:${Versions.coil}"
private val coil_compose = "io.coil-kt:coil-compose:${Versions.coil}"
private val coil_gif = "io.coil-kt:coil-gif:${Versions.coil}"

// Network
private val retrofit = "com.squareup.retrofit2:retrofit:${Versions.RETROFIT}"
private val gsonConverter = "com.squareup.retrofit2:converter-gson:${Versions.RETROFIT}"
Expand All @@ -61,6 +65,11 @@ object Dependencies {
private val hiltCompiler = "com.google.dagger:hilt-android-compiler:${Versions.HILT}"
private val javaXInject = "javax.inject:javax.inject:${Versions.JAVA_X_INJECT}"

// Paging
private val paging_runtime = "androidx.paging:paging-runtime-ktx:${Versions.paging}"
private val paging_common = "androidx.paging:paging-common-ktx:${Versions.paging}"
private val paging_compose = "androidx.paging:paging-compose:${Versions.paging_compose}"

// Test
private val junit = "junit:junit:${Versions.JUNIT}"

Expand Down Expand Up @@ -117,6 +126,9 @@ object Dependencies {

fun DependencyHandler.setImageDependencies() {
implementation(glide)
implementation(coil)
implementation(coil_compose)
implementation(coil_gif)
}

fun DependencyHandler.setNetworkDependencies() {
Expand Down Expand Up @@ -147,6 +159,12 @@ object Dependencies {
testImplementation(junit)
}

fun DependencyHandler.setPagingDependencies() {
implementation(paging_compose)
implementation(paging_compose)
implementation(paging_runtime)
}

fun DependencyHandler.setAndroidTestDependencies() {
androidTestImplementation(androidJunit)
androidTestImplementation(espressoCore)
Expand Down
7 changes: 7 additions & 0 deletions buildSrc/src/main/java/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ object Versions {
// Image
const val GLIDE = "4.15.1"

// Coil
const val coil = "2.4.0"

// Network
const val RETROFIT = "2.9.0"
const val OKHTTP_INTERCEPTOR = "4.10.0"
Expand All @@ -43,6 +46,10 @@ object Versions {
const val HILT = "2.44"
const val JAVA_X_INJECT = "1"

// Paging
const val paging = "3.1.1"
const val paging_compose = "3.2.0"

// Test
const val JUNIT = "4.13.2"

Expand Down
31 changes: 31 additions & 0 deletions data/src/main/java/com/keyme/data/remote/api/KeymeApi.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package com.keyme.data.remote.api

import com.keyme.domain.entity.request.SignInRequest
import com.keyme.domain.entity.response.MemberStatistics
import com.keyme.domain.entity.response.MemberStatisticsResponse
import com.keyme.domain.entity.response.QuestionStatisticsResponse
import com.keyme.domain.entity.response.SignInResponse
import com.keyme.domain.entity.response.SolvedScoreListResponse
import com.keyme.domain.entity.response.keymetest.KeymeTestResultStatisticsResponse
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Path
import retrofit2.http.Query

interface KeymeApi {

Expand All @@ -19,4 +24,30 @@ interface KeymeApi {
suspend fun getKeymeTestResultStatistics(
@Path("id") questionId: String,
): KeymeTestResultStatisticsResponse

@GET("members/{memberId}/statistics")
suspend fun getMemberStatistics(
@Path("memberId") memberId: String,
@Query("type") type: MemberStatistics.StatisticsType,
): MemberStatisticsResponse

// @GET("questions/{id}/score")
// suspend fun getMyQuestionScore(
// @Path("id") id: String,
// @Query("ownerId") ownerId: String,
// ): MyQuestionScoreResponse

@GET("questions/{id}/statistics")
suspend fun getQuestionStatistics(
@Path("id") id: String,
@Query("ownerId") ownerId: Int,
): QuestionStatisticsResponse

@GET("questions/{id}/solved-scores")
suspend fun getSolvedScoreList(
@Query("cursor") cursor: Int?,
@Path("id") id: String,
@Query("limit") limit: Int = 20,
@Query("ownerId") ownerId: Int,
): SolvedScoreListResponse
}
37 changes: 24 additions & 13 deletions data/src/main/java/com/keyme/data/remote/di/ApiModule.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.keyme.data.remote.di

import com.keyme.data.BuildConfig
import com.keyme.data.remote.api.KeymeApi
import com.keyme.domain.usecase.GetMyMemberTokenUseCase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand All @@ -18,30 +20,39 @@ class ApiModule {

@Provides
@Singleton
fun provideKeymeApi(): KeymeApi {
return getRetrofit().create()
fun provideKeymeApi(getMyMemberTokenUseCase: GetMyMemberTokenUseCase): KeymeApi {
return getRetrofit(getMyMemberTokenUseCase()).create()
}

private fun getRetrofit(): Retrofit {
private fun getRetrofit(memberToken: String): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.keyme.space")
.client(getOkHttpClient())
.client(getOkHttpClient(memberToken))
.addConverterFactory(GsonConverterFactory.create())
.build()
}

private fun getOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(
private fun getOkHttpClient(memberToken: String): OkHttpClient {
val builder = OkHttpClient.Builder()

builder.addInterceptor { chain ->
val origin = chain.request()
chain.request().newBuilder()
.header("Content-Type", "application/json;charset=UTF-8")
.header("Authorization", "Bearer $memberToken")
.method(origin.method, origin.body)
.build()
.let(chain::proceed)
}

if (BuildConfig.DEBUG) {
builder.addInterceptor(
HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
},
)
.addInterceptor { chain ->
chain.request().newBuilder()
.build()
.let(chain::proceed)
}
.build()
}

return builder.build()
}
}
10 changes: 10 additions & 0 deletions data/src/main/java/com/keyme/data/remote/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.keyme.data.remote.di

import com.keyme.data.remote.repositoryimpl.MemberRepositoryImpl
import com.keyme.data.remote.repositoryimpl.QuestionRepositoryImpl
import com.keyme.data.remote.repositoryimpl.ResultCircleRepositoryImpl
import com.keyme.data.remote.repositoryimpl.SignInRepositoryImpl
import com.keyme.data.remote.repositoryimpl.keymetest.KeymeTestResultRepositoryImpl
import com.keyme.domain.repository.MemberRepository
import com.keyme.domain.repository.QuestionRepository
import com.keyme.domain.repository.ResultCircleRepository
import com.keyme.domain.repository.SignInRepository
import com.keyme.domain.repository.keymetest.KeymeTestResultRepository
Expand All @@ -23,4 +27,10 @@ abstract class RepositoryModule {

@Binds
abstract fun bindKeymeTestResultRepository(impl: KeymeTestResultRepositoryImpl): KeymeTestResultRepository

@Binds
abstract fun bindMemberRepository(impl: MemberRepositoryImpl): MemberRepository

@Binds
abstract fun bindQuestionRepository(impl: QuestionRepositoryImpl): QuestionRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.keyme.data.remote.repositoryimpl

import com.keyme.data.remote.api.KeymeApi
import com.keyme.domain.entity.response.MemberStatistics
import com.keyme.domain.entity.response.MemberStatisticsResponse
import com.keyme.domain.repository.MemberRepository
import javax.inject.Inject

class MemberRepositoryImpl @Inject constructor(
private val keymeApi: KeymeApi,
) : MemberRepository {
override suspend fun getStatistics(
memberId: String,
type: MemberStatistics.StatisticsType,
): MemberStatisticsResponse {
return keymeApi.getMemberStatistics(memberId = memberId, type = type)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.keyme.data.remote.repositoryimpl

import com.keyme.data.remote.api.KeymeApi
import com.keyme.domain.entity.response.QuestionStatisticsResponse
import com.keyme.domain.entity.response.SolvedScoreListResponse
import com.keyme.domain.repository.QuestionRepository
import javax.inject.Inject

class QuestionRepositoryImpl @Inject constructor(
private val keymeApi: KeymeApi,
) : QuestionRepository {
override suspend fun getStatistics(questionId: String): QuestionStatisticsResponse {
return keymeApi.getQuestionStatistics(id = questionId, ownerId = 1)
}

override suspend fun getSolvedScoreList(
cursor: Int?,
questionId: String,
limit: Int,
ownerId: Int,
): SolvedScoreListResponse {
return keymeApi.getSolvedScoreList(cursor, questionId, limit, ownerId)
}
}
13 changes: 13 additions & 0 deletions domain/src/main/java/com/keyme/domain/entity/member/Member.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.keyme.domain.entity.member

data class Member(
val friendCode: String,
val id: Int,
val nickname: String,
val profileImage: String,
val profileThumbnail: String,
) {
companion object {
val EMPTY = Member(friendCode = "", id = 0, nickname = "", profileImage = "", profileThumbnail = "")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.keyme.domain.entity.response

data class Category(
val color: String,
val iconUrl: String,
val name: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.keyme.domain.entity.response

data class Coordinate(
val r: Double,
val x: Double,
val y: Double,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.keyme.domain.entity.response

import com.keyme.domain.entity.BaseResponse

class MemberStatisticsResponse : BaseResponse<MemberStatistics>()

data class MemberStatistics(
val memberId: Int = 0,
val results: List<Result> = listOf(),
) {
enum class StatisticsType {
SIMILAR, DIFFERENT
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.keyme.domain.entity.response

// class MyQuestionScoreResponse: BaseResponse<>()
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.keyme.domain.entity.response

import com.keyme.domain.entity.BaseResponse

class QuestionStatisticsResponse : BaseResponse<Question>()

data class Question(
val avgScore: Int,
val category: Category,
val keyword: String,
val questionId: Int,
val title: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.keyme.domain.entity.response

data class Result(
val coordinate: Coordinate,
val question: Question,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.keyme.domain.entity.response

import com.keyme.domain.entity.BaseResponse

class SolvedScoreListResponse : BaseResponse<SolvedScoreList>()

data class SolvedScoreList(
val count: Int,
val results: List<SolvedScore>,
)

data class SolvedScore(
val createAt: String,
val score: Int,
)
Loading

0 comments on commit 77a1dee

Please sign in to comment.