Initial commit
Some checks failed
Merge core/template-android-project to this repo / merge-if-needed (push) Has been cancelled
Some checks failed
Merge core/template-android-project to this repo / merge-if-needed (push) Has been cancelled
This commit is contained in:
@@ -1,5 +1,10 @@
|
|||||||
package ru.myitschool.work.core
|
package ru.myitschool.work.core
|
||||||
|
|
||||||
|
|
||||||
|
// ДАННЫЙ КЛАСС ПРИ ТЕСТИРОВАНИИ БУДЕТ ВОЗВРАЩЁН В ОРИГИНАЛЬНОЕ ЗНАЧЕНИЕ
|
||||||
|
// Используйте ссылки только из переменных этого класса
|
||||||
|
// Можете изменить хост, но для тестирование он будет подменён тестовым сервером
|
||||||
|
|
||||||
object Constants {
|
object Constants {
|
||||||
const val HOST = "http://10.0.2.2:8080"
|
const val HOST = "http://10.0.2.2:8080"
|
||||||
const val USER_URL = "/user"
|
const val USER_URL = "/user"
|
||||||
|
|||||||
@@ -1,26 +1,14 @@
|
|||||||
package ru.myitschool.work.data
|
package ru.myitschool.work.data
|
||||||
|
|
||||||
import ru.myitschool.work.data.source.NetworkDataSource
|
|
||||||
import ru.myitschool.work.domain.entities.BookingEntity
|
|
||||||
import ru.myitschool.work.domain.entities.UserEntity
|
import ru.myitschool.work.domain.entities.UserEntity
|
||||||
|
|
||||||
object AppRepository {
|
object AppRepository {
|
||||||
suspend fun loadData(): Result<UserEntity> {
|
suspend fun loadData(): UserEntity {
|
||||||
return NetworkDataSource.getUser().map { dto ->
|
TODO("заверши написание кода")
|
||||||
UserEntity(
|
|
||||||
name = dto.name,
|
|
||||||
bookingList = dto.booking.map { bookingDto ->
|
|
||||||
BookingEntity(
|
|
||||||
roomName = bookingDto.room,
|
|
||||||
time = bookingDto.time
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun addBook(room: String, time: String): Result<Unit> {
|
suspend fun addBook(room: String, time: String) {
|
||||||
return NetworkDataSource.addBook(room, time)
|
// TODO: заверши написание кода
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package ru.myitschool.work.data.dto
|
|
||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class ErrorDto(
|
|
||||||
@SerialName("error")
|
|
||||||
val error: String,
|
|
||||||
)
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package ru.myitschool.work.data.dto
|
|
||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class UserDto(
|
|
||||||
@SerialName("name")
|
|
||||||
val name: String,
|
|
||||||
@SerialName("booking")
|
|
||||||
val booking: List<BookingDto>
|
|
||||||
) {
|
|
||||||
@Serializable
|
|
||||||
data class BookingDto(
|
|
||||||
@SerialName("room")
|
|
||||||
val room: String,
|
|
||||||
@SerialName("time")
|
|
||||||
val time: String,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
package ru.myitschool.work.data.source
|
|
||||||
|
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import io.ktor.client.call.body
|
|
||||||
import io.ktor.client.engine.cio.CIO
|
|
||||||
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
|
|
||||||
import io.ktor.client.request.forms.FormPart
|
|
||||||
import io.ktor.client.request.forms.MultiPartFormDataContent
|
|
||||||
import io.ktor.client.request.forms.formData
|
|
||||||
import io.ktor.client.request.get
|
|
||||||
import io.ktor.client.request.post
|
|
||||||
import io.ktor.client.request.setBody
|
|
||||||
import io.ktor.http.HttpStatusCode
|
|
||||||
import io.ktor.serialization.kotlinx.json.json
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.serialization.json.Json
|
|
||||||
import ru.myitschool.work.core.Constants
|
|
||||||
import ru.myitschool.work.data.dto.ErrorDto
|
|
||||||
import ru.myitschool.work.data.dto.UserDto
|
|
||||||
|
|
||||||
object NetworkDataSource {
|
|
||||||
private val client by lazy {
|
|
||||||
HttpClient(CIO) {
|
|
||||||
install(ContentNegotiation) {
|
|
||||||
json(
|
|
||||||
Json {
|
|
||||||
isLenient = true
|
|
||||||
ignoreUnknownKeys = true
|
|
||||||
explicitNulls = true
|
|
||||||
encodeDefaults = true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getUser(): Result<UserDto> = withContext(Dispatchers.IO) {
|
|
||||||
return@withContext runCatching {
|
|
||||||
val response = client.get(Constants.FULL_USER_URL)
|
|
||||||
if (response.status == HttpStatusCode.OK) {
|
|
||||||
response.body<UserDto>()
|
|
||||||
} else {
|
|
||||||
error(response.body<ErrorDto>().error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun addBook(
|
|
||||||
room: String,
|
|
||||||
time: String,
|
|
||||||
): Result<Unit> = withContext(Dispatchers.IO) {
|
|
||||||
return@withContext runCatching {
|
|
||||||
val response = client.post(Constants.FULL_BOOK_URL) {
|
|
||||||
setBody(
|
|
||||||
MultiPartFormDataContent(
|
|
||||||
formData(
|
|
||||||
FormPart("room", room),
|
|
||||||
FormPart("time", time),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (response.status == HttpStatusCode.OK) {
|
|
||||||
Unit
|
|
||||||
} else {
|
|
||||||
error(response.body<ErrorDto>().error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,9 +9,11 @@ class AddBookUseCase(
|
|||||||
room: String,
|
room: String,
|
||||||
time: String,
|
time: String,
|
||||||
): Result<Unit> {
|
): Result<Unit> {
|
||||||
return repository.addBook(
|
return Result.success(
|
||||||
room = room,
|
repository.addBook(
|
||||||
time = time,
|
room = room,
|
||||||
|
time = time,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,6 @@ class GetUserDataUseCase(
|
|||||||
private val repository: AppRepository
|
private val repository: AppRepository
|
||||||
) {
|
) {
|
||||||
suspend operator fun invoke(): Result<UserEntity> {
|
suspend operator fun invoke(): Result<UserEntity> {
|
||||||
return repository.loadData()
|
return Result.success(repository.loadData())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package ru.myitschool.work.domain.entities
|
package ru.myitschool.work.domain.entities
|
||||||
|
|
||||||
|
// ДАННЫЙ КЛАСС ЗАПРЕЩЕНО МОДИЦИФИРОВАТЬ! ПРИ ТЕСТИРОВАНИИ ОН БУДЕТ ВОЗВРАЩЁН В ОРИГИНАЛЬНОЕ ЗНАЧЕНИЕ
|
||||||
data class BookingEntity(
|
data class BookingEntity(
|
||||||
val roomName: String,
|
val roomName: String,
|
||||||
val time: String,
|
val time: String,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package ru.myitschool.work.domain.entities
|
package ru.myitschool.work.domain.entities
|
||||||
|
|
||||||
|
// ДАННЫЙ КЛАСС ЗАПРЕЩЕНО МОДИЦИФИРОВАТЬ! ПРИ ТЕСТИРОВАНИИ ОН БУДЕТ ВОЗВРАЩЁН В ОРИГИНАЛЬНОЕ ЗНАЧЕНИЕ
|
||||||
data class UserEntity(
|
data class UserEntity(
|
||||||
val name: String,
|
val name: String,
|
||||||
val bookingList: List<BookingEntity>
|
val bookingList: List<BookingEntity>
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import ru.myitschool.work.ui.theme.WorkTheme
|
import ru.myitschool.work.ui.theme.WorkTheme
|
||||||
|
|
||||||
|
// ДАННЫЙ КЛАСС ЗАПРЕЩЕНО МОДИЦИФИРОВАТЬ! ПРИ ТЕСТИРОВАНИИ ОН БУДЕТ ВОЗВРАЩЁН В ОРИГИНАЛЬНОЕ ЗНАЧЕНИЕ
|
||||||
class RootActivity : ComponentActivity() {
|
class RootActivity : ComponentActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package ru.myitschool.work.ui.root
|
package ru.myitschool.work.ui.root
|
||||||
|
|
||||||
|
// ДАННЫЙ КЛАСС ЗАПРЕЩЕНО МОДИЦИФИРОВАТЬ! ПРИ ТЕСТИРОВАНИИ ОН БУДЕТ ВОЗВРАЩЁН В ОРИГИНАЛЬНОЕ ЗНАЧЕНИЕ
|
||||||
sealed interface RootIntent {
|
sealed interface RootIntent {
|
||||||
data object LoadData: RootIntent
|
data object LoadData: RootIntent
|
||||||
data class AddBook(
|
data class AddBook(
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package ru.myitschool.work.ui.root
|
|||||||
|
|
||||||
import ru.myitschool.work.domain.entities.UserEntity
|
import ru.myitschool.work.domain.entities.UserEntity
|
||||||
|
|
||||||
|
// ДАННЫЙ КЛАСС ЗАПРЕЩЕНО МОДИЦИФИРОВАТЬ! ПРИ ТЕСТИРОВАНИИ ОН БУДЕТ ВОЗВРАЩЁН В ОРИГИНАЛЬНОЕ ЗНАЧЕНИЕ
|
||||||
sealed interface RootState {
|
sealed interface RootState {
|
||||||
data object NotLoaded: RootState
|
data object NotLoaded: RootState
|
||||||
data object Loading: RootState
|
data object Loading: RootState
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import ru.myitschool.work.data.AppRepository
|
|||||||
import ru.myitschool.work.domain.AddBookUseCase
|
import ru.myitschool.work.domain.AddBookUseCase
|
||||||
import ru.myitschool.work.domain.GetUserDataUseCase
|
import ru.myitschool.work.domain.GetUserDataUseCase
|
||||||
|
|
||||||
|
// ДАННЫЙ КЛАСС ЗАПРЕЩЕНО МОДИЦИФИРОВАТЬ! ПРИ ТЕСТИРОВАНИИ ОН БУДЕТ ВОЗВРАЩЁН В ОРИГИНАЛЬНОЕ ЗНАЧЕНИЕ
|
||||||
class RootViewModel : ViewModel() {
|
class RootViewModel : ViewModel() {
|
||||||
private val getUserDataUseCase by lazy {
|
private val getUserDataUseCase by lazy {
|
||||||
GetUserDataUseCase(
|
GetUserDataUseCase(
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package ru.myitschool.work.ui.theme
|
|||||||
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|
||||||
|
// ДАННЫЙ КЛАСС ЗАПРЕЩЕНО МОДИЦИФИРОВАТЬ! ПРИ ТЕСТИРОВАНИИ ОН БУДЕТ ВОЗВРАЩЁН В ОРИГИНАЛЬНОЕ ЗНАЧЕНИЕ
|
||||||
val Purple80 = Color(0xFFD0BCFF)
|
val Purple80 = Color(0xFFD0BCFF)
|
||||||
val PurpleGrey80 = Color(0xFFCCC2DC)
|
val PurpleGrey80 = Color(0xFFCCC2DC)
|
||||||
val Pink80 = Color(0xFFEFB8C8)
|
val Pink80 = Color(0xFFEFB8C8)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import androidx.compose.material3.lightColorScheme
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
|
||||||
|
// ДАННЫЙ КЛАСС ЗАПРЕЩЕНО МОДИЦИФИРОВАТЬ! ПРИ ТЕСТИРОВАНИИ ОН БУДЕТ ВОЗВРАЩЁН В ОРИГИНАЛЬНОЕ ЗНАЧЕНИЕ
|
||||||
private val DarkColorScheme = darkColorScheme(
|
private val DarkColorScheme = darkColorScheme(
|
||||||
primary = Purple80,
|
primary = Purple80,
|
||||||
secondary = PurpleGrey80,
|
secondary = PurpleGrey80,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import androidx.compose.ui.text.font.FontFamily
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
||||||
// Set of Material typography styles to start with
|
// ДАННЫЙ КЛАСС ЗАПРЕЩЕНО МОДИЦИФИРОВАТЬ! ПРИ ТЕСТИРОВАНИИ ОН БУДЕТ ВОЗВРАЩЁН В ОРИГИНАЛЬНОЕ ЗНАЧЕНИЕ
|
||||||
val Typography = Typography(
|
val Typography = Typography(
|
||||||
bodyLarge = TextStyle(
|
bodyLarge = TextStyle(
|
||||||
fontFamily = FontFamily.Default,
|
fontFamily = FontFamily.Default,
|
||||||
@@ -15,20 +15,4 @@ val Typography = Typography(
|
|||||||
lineHeight = 24.sp,
|
lineHeight = 24.sp,
|
||||||
letterSpacing = 0.5.sp
|
letterSpacing = 0.5.sp
|
||||||
)
|
)
|
||||||
/* Other default text styles to override
|
|
||||||
titleLarge = TextStyle(
|
|
||||||
fontFamily = FontFamily.Default,
|
|
||||||
fontWeight = FontWeight.Normal,
|
|
||||||
fontSize = 22.sp,
|
|
||||||
lineHeight = 28.sp,
|
|
||||||
letterSpacing = 0.sp
|
|
||||||
),
|
|
||||||
labelSmall = TextStyle(
|
|
||||||
fontFamily = FontFamily.Default,
|
|
||||||
fontWeight = FontWeight.Medium,
|
|
||||||
fontSize = 11.sp,
|
|
||||||
lineHeight = 16.sp,
|
|
||||||
letterSpacing = 0.5.sp
|
|
||||||
)
|
|
||||||
*/
|
|
||||||
)
|
)
|
||||||
Reference in New Issue
Block a user