Skip to content

Commit

Permalink
Add /api/challenges
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-magda committed Nov 8, 2023
1 parent 9050c51 commit 220b898
Show file tree
Hide file tree
Showing 11 changed files with 176 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.hyperskill.app.challenges.data.repository

import org.hyperskill.app.challenges.data.source.ChallengesRemoteDataSource
import org.hyperskill.app.challenges.domain.model.Challenge
import org.hyperskill.app.challenges.domain.repository.ChallengesRepository

internal class ChallengesRepositoryImpl(
private val challengesRemoteDataSource: ChallengesRemoteDataSource
) : ChallengesRepository {
override suspend fun getChallenges(): Result<List<Challenge>> =
challengesRemoteDataSource.getChallenges()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.hyperskill.app.challenges.data.source

import org.hyperskill.app.challenges.domain.model.Challenge

interface ChallengesRemoteDataSource {
suspend fun getChallenges(): Result<List<Challenge>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.hyperskill.app.challenges.domain.model

import kotlinx.datetime.LocalDate
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class Challenge(
@SerialName("id")
val id: Long,
@SerialName("title")
val title: String,
@SerialName("description")
val description: String,
@SerialName("target_type")
internal val targetTypeValue: Int,
@SerialName("starting_date")
val startingDate: LocalDate,
@SerialName("interval_duration_days")
val intervalDurationDays: Int,
@SerialName("intervals_count")
val intervalsCount: Int,
@SerialName("status")
internal val statusValue: String,
@SerialName("reward_link")
val rewardLink: String?,
@SerialName("progress")
val progress: List<Boolean>,
@SerialName("finish_date")
val finishDate: LocalDate,
@SerialName("current_interval")
val currentInterval: Int?
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.hyperskill.app.challenges.domain.repository

import org.hyperskill.app.challenges.domain.model.Challenge

interface ChallengesRepository {
suspend fun getChallenges(): Result<List<Challenge>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.hyperskill.app.challenges.injection

import org.hyperskill.app.challenges.domain.repository.ChallengesRepository

interface ChallengesDataComponent {
val challengesRepository: ChallengesRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.hyperskill.app.challenges.injection

import org.hyperskill.app.challenges.data.repository.ChallengesRepositoryImpl
import org.hyperskill.app.challenges.data.source.ChallengesRemoteDataSource
import org.hyperskill.app.challenges.domain.repository.ChallengesRepository
import org.hyperskill.app.challenges.remote.ChallengesRemoteDataSourceImpl
import org.hyperskill.app.core.injection.AppGraph

internal class ChallengesDataComponentImpl(appGraph: AppGraph) : ChallengesDataComponent {
private val challengesRemoteDataSource: ChallengesRemoteDataSource =
ChallengesRemoteDataSourceImpl(appGraph.networkComponent.authorizedHttpClient)

override val challengesRepository: ChallengesRepository
get() = ChallengesRepositoryImpl(challengesRemoteDataSource)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.hyperskill.app.challenges.remote

import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.request.get
import org.hyperskill.app.challenges.data.source.ChallengesRemoteDataSource
import org.hyperskill.app.challenges.domain.model.Challenge
import org.hyperskill.app.challenges.remote.model.ChallengesResponse

internal class ChallengesRemoteDataSourceImpl(
private val httpClient: HttpClient
) : ChallengesRemoteDataSource {
override suspend fun getChallenges(): Result<List<Challenge>> =
kotlin.runCatching {
httpClient
.get("/api/challenges")
.body<ChallengesResponse>()
.challenges
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.hyperskill.app.challenges.remote.model

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.hyperskill.app.challenges.domain.model.Challenge
import org.hyperskill.app.core.remote.Meta
import org.hyperskill.app.core.remote.MetaResponse

@Serializable
class ChallengesResponse(
@SerialName("meta")
override val meta: Meta,

@SerialName("challenges")
val challenges: List<Challenge>
) : MetaResponse
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import org.hyperskill.app.auth.injection.AuthComponent
import org.hyperskill.app.auth.injection.AuthCredentialsComponent
import org.hyperskill.app.auth.injection.AuthSocialComponent
import org.hyperskill.app.badges.injection.BadgesDataComponent
import org.hyperskill.app.challenges.injection.ChallengesDataComponent
import org.hyperskill.app.comments.injection.CommentsDataComponent
import org.hyperskill.app.debug.injection.DebugComponent
import org.hyperskill.app.devices.injection.DevicesDataComponent
Expand Down Expand Up @@ -151,4 +152,5 @@ interface AppGraph {
fun buildBadgesDataComponent(): BadgesDataComponent
fun buildNotificationsOnboardingComponent(): NotificationsOnboardingComponent
fun buildFirstProblemOnboardingComponent(): FirstProblemOnboardingComponent
fun buildChallengesDataComponent(): ChallengesDataComponent
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import org.hyperskill.app.auth.injection.AuthSocialComponent
import org.hyperskill.app.auth.injection.AuthSocialComponentImpl
import org.hyperskill.app.badges.injection.BadgesDataComponent
import org.hyperskill.app.badges.injection.BadgesDataComponentImpl
import org.hyperskill.app.challenges.injection.ChallengesDataComponent
import org.hyperskill.app.challenges.injection.ChallengesDataComponentImpl
import org.hyperskill.app.comments.injection.CommentsDataComponent
import org.hyperskill.app.comments.injection.CommentsDataComponentImpl
import org.hyperskill.app.debug.injection.DebugComponent
Expand Down Expand Up @@ -411,4 +413,7 @@ abstract class BaseAppGraph : AppGraph {

override fun buildFirstProblemOnboardingComponent(): FirstProblemOnboardingComponent =
FirstProblemOnboardingComponentImpl(this)

override fun buildChallengesDataComponent(): ChallengesDataComponent =
ChallengesDataComponentImpl(this)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.hyperskill.challenges

import kotlin.test.Test
import kotlin.test.assertEquals
import kotlinx.datetime.LocalDate
import org.hyperskill.app.challenges.domain.model.Challenge
import org.hyperskill.app.network.injection.NetworkModule

class ChallengeDeserializationTest {
companion object {
private val TEST_JSON_STRING = """
{
"id": 6,
"title": "QA ☾⋆",
"description": "The Challenge! Ho-ho-ho!🎅\r\nHurry up and get yor prise!",
"target_type": 14,
"starting_date": "2023-11-02",
"interval_duration_days": 1,
"intervals_count": 1,
"status": "not completed",
"reward_link": null,
"progress":
[
false
],
"finish_date": "2023-11-03",
"current_interval": null
}
""".trimIndent()
}

@Test
fun `Test Challenge deserialization`() {
val json = NetworkModule.provideJson()
val expected = Challenge(
id = 6,
title = "QA ☾⋆",
description = "The Challenge! Ho-ho-ho!🎅\r\nHurry up and get yor prise!",
targetTypeValue = 14,
startingDate = LocalDate.parse("2023-11-02"),
intervalDurationDays = 1,
intervalsCount = 1,
statusValue = "not completed",
rewardLink = null,
progress = listOf(false),
finishDate = LocalDate.parse("2023-11-03"),
currentInterval = null
)
val decodedObject = json.decodeFromString(Challenge.serializer(), TEST_JSON_STRING)
assertEquals(expected, decodedObject)
}
}

0 comments on commit 220b898

Please sign in to comment.