123
This commit is contained in:
8
local.properties
Normal file
8
local.properties
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
## This file must *NOT* be checked into Version Control Systems,
|
||||||
|
# as it contains information specific to your local configuration.
|
||||||
|
#
|
||||||
|
# Location of the SDK. This is only used by Gradle.
|
||||||
|
# For customization when using a Version Control System, please read the
|
||||||
|
# header note.
|
||||||
|
#Fri Dec 12 08:17:55 YEKT 2025
|
||||||
|
sdk.dir=D\:\\androidstudio
|
||||||
16
src/main/kotlin/Application.kt
Normal file
16
src/main/kotlin/Application.kt
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package com.example
|
||||||
|
|
||||||
|
import io.ktor.serialization.kotlinx.json.json
|
||||||
|
import io.ktor.server.application.*
|
||||||
|
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
io.ktor.server.netty.EngineMain.main(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Application.module() {
|
||||||
|
install(ContentNegotiation) {
|
||||||
|
json()
|
||||||
|
}
|
||||||
|
configureRouting()
|
||||||
|
}
|
||||||
11
src/main/kotlin/data/mapper/BookingMapper.kt
Normal file
11
src/main/kotlin/data/mapper/BookingMapper.kt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package com.example.data.mapper
|
||||||
|
|
||||||
|
import com.example.data.remote.dto.BookingResponse
|
||||||
|
import com.example.domain.models.Booking
|
||||||
|
|
||||||
|
fun BookingResponse.toDomain(): Booking {
|
||||||
|
return Booking(
|
||||||
|
room = room,
|
||||||
|
time = time
|
||||||
|
)
|
||||||
|
}
|
||||||
37
src/main/kotlin/data/remote/BookingApi.kt
Normal file
37
src/main/kotlin/data/remote/BookingApi.kt
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package com.example.data.remote
|
||||||
|
|
||||||
|
import com.example.data.remote.dto.BookingResponse
|
||||||
|
import com.example.data.remote.dto.UserResponse
|
||||||
|
import io.ktor.client.*
|
||||||
|
import io.ktor.client.call.*
|
||||||
|
import io.ktor.client.request.*
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.client.request.forms.*
|
||||||
|
|
||||||
|
interface BookingApi {
|
||||||
|
suspend fun getUser(): UserResponse
|
||||||
|
suspend fun bookRoom(room: String, time: String): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
class BookingApiImpl(private val client: HttpClient) : BookingApi {
|
||||||
|
private val baseUrl = "http://localhost:8080"
|
||||||
|
|
||||||
|
override suspend fun getUser(): UserResponse {
|
||||||
|
return client.get("$baseUrl/user").body()
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun bookRoom(room: String, time: String): Boolean {
|
||||||
|
return try {
|
||||||
|
val response = client.submitForm(
|
||||||
|
url = "$baseUrl/book",
|
||||||
|
formParameters = Parameters.build {
|
||||||
|
append("room", room)
|
||||||
|
append("time", time)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
response.status == HttpStatusCode.OK
|
||||||
|
} catch (e: Exception) {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/main/kotlin/data/remote/dto/UserResponse.kt
Normal file
20
src/main/kotlin/data/remote/dto/UserResponse.kt
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package com.example.data.remote.dto
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class UserResponse(
|
||||||
|
@SerialName("name")
|
||||||
|
val name: String,
|
||||||
|
@SerialName("booking")
|
||||||
|
val booking: List<BookingResponse>
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class BookingResponse(
|
||||||
|
@SerialName("room")
|
||||||
|
val room: String,
|
||||||
|
@SerialName("time")
|
||||||
|
val time: String
|
||||||
|
)
|
||||||
23
src/main/kotlin/data/repository/BookingRepositoryImpl.kt
Normal file
23
src/main/kotlin/data/repository/BookingRepositoryImpl.kt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package com.example.data.repository
|
||||||
|
|
||||||
|
import com.example.data.mapper.toDomain
|
||||||
|
import com.example.data.remote.BookingApi
|
||||||
|
import com.example.domain.models.Booking
|
||||||
|
import com.example.domain.repository.BookingRepository
|
||||||
|
|
||||||
|
class BookingRepositoryImpl(
|
||||||
|
private val api: BookingApi
|
||||||
|
) : BookingRepository {
|
||||||
|
|
||||||
|
override suspend fun getBookings(): List<Booking> {
|
||||||
|
return try {
|
||||||
|
api.getUser().booking.map { it.toDomain() }
|
||||||
|
} catch (e: Exception) {
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun addBooking(room: String, time: String): Boolean {
|
||||||
|
return api.bookRoom(room, time)
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/main/kotlin/di/Dependencies.kt
Normal file
41
src/main/kotlin/di/Dependencies.kt
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package com.example.di
|
||||||
|
|
||||||
|
import com.example.data.remote.BookingApi
|
||||||
|
import com.example.data.remote.BookingApiImpl
|
||||||
|
import com.example.data.repository.BookingRepositoryImpl
|
||||||
|
import com.example.domain.repository.BookingRepository
|
||||||
|
import com.example.presentation.BookingViewModel
|
||||||
|
import io.ktor.client.*
|
||||||
|
import io.ktor.client.engine.cio.*
|
||||||
|
import io.ktor.client.plugins.contentnegotiation.*
|
||||||
|
import io.ktor.client.plugins.logging.*
|
||||||
|
import io.ktor.serialization.kotlinx.json.*
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
object Dependencies {
|
||||||
|
val httpClient: HttpClient by lazy {
|
||||||
|
HttpClient(CIO) {
|
||||||
|
install(ContentNegotiation) {
|
||||||
|
json(Json {
|
||||||
|
ignoreUnknownKeys = true
|
||||||
|
isLenient = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
install(Logging) {
|
||||||
|
level = LogLevel.ALL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val bookingApi: BookingApi by lazy {
|
||||||
|
BookingApiImpl(httpClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
val bookingRepository: BookingRepository by lazy {
|
||||||
|
BookingRepositoryImpl(bookingApi)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createBookingViewModel(): BookingViewModel {
|
||||||
|
return BookingViewModel(bookingRepository)
|
||||||
|
}
|
||||||
|
}
|
||||||
6
src/main/kotlin/domain/models/Booking.kt
Normal file
6
src/main/kotlin/domain/models/Booking.kt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package com.example.domain.models
|
||||||
|
|
||||||
|
data class Booking(
|
||||||
|
val room: String,
|
||||||
|
val time: String
|
||||||
|
)
|
||||||
6
src/main/kotlin/domain/models/User.kt
Normal file
6
src/main/kotlin/domain/models/User.kt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package com.example.domain.models
|
||||||
|
|
||||||
|
data class User(
|
||||||
|
val name: String,
|
||||||
|
val bookings: List<Booking>
|
||||||
|
)
|
||||||
8
src/main/kotlin/domain/repositories/BookingRepository.kt
Normal file
8
src/main/kotlin/domain/repositories/BookingRepository.kt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package com.example.domain.repository
|
||||||
|
|
||||||
|
import com.example.domain.models.Booking
|
||||||
|
|
||||||
|
interface BookingRepository {
|
||||||
|
suspend fun getBookings(): List<Booking>
|
||||||
|
suspend fun addBooking(room: String, time: String): Boolean
|
||||||
|
}
|
||||||
63
src/main/kotlin/presentation/viewmodels/BookingViewModel.kt
Normal file
63
src/main/kotlin/presentation/viewmodels/BookingViewModel.kt
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package com.example.presentation
|
||||||
|
|
||||||
|
import com.example.domain.models.Booking
|
||||||
|
import com.example.domain.repository.BookingRepository
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
|
class BookingViewModel(
|
||||||
|
private val repository: BookingRepository,
|
||||||
|
private val coroutineContext: CoroutineContext = Dispatchers.Default
|
||||||
|
) {
|
||||||
|
private var bookings: List<Booking> = emptyList()
|
||||||
|
private var error: String? = null
|
||||||
|
private val scope = CoroutineScope(coroutineContext)
|
||||||
|
|
||||||
|
// Колбэки для обновления UI
|
||||||
|
var onBookingsUpdated: (List<Booking>) -> Unit = {}
|
||||||
|
var onError: (String?) -> Unit = {}
|
||||||
|
|
||||||
|
fun loadBookings() {
|
||||||
|
scope.launch {
|
||||||
|
try {
|
||||||
|
bookings = repository.getBookings()
|
||||||
|
error = null
|
||||||
|
onBookingsUpdated(bookings)
|
||||||
|
onError(null)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
error = "Ошибка загрузки: ${e.message}"
|
||||||
|
onError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addBooking(room: String, time: String) {
|
||||||
|
if (room.isBlank() || time.isBlank()) {
|
||||||
|
error = "Заполните все поля"
|
||||||
|
onError(error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.launch {
|
||||||
|
try {
|
||||||
|
val success = repository.addBooking(room, time)
|
||||||
|
if (success) {
|
||||||
|
loadBookings() // Обновляем список
|
||||||
|
} else {
|
||||||
|
error = "Ошибка бронирования"
|
||||||
|
onError(error)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
error = "Ошибка: ${e.message}"
|
||||||
|
onError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCurrentBookings(): List<Booking> = bookings
|
||||||
|
fun getCurrentError(): String? = error
|
||||||
|
|
||||||
|
fun dispose() {
|
||||||
|
scope.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user