diff --git a/build.gradle.kts b/build.gradle.kts index d9e6c06..87bfe22 100755 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,13 +12,24 @@ application { } dependencies { + // СЕРВЕРНЫЕ ЗАВИСИМОСТИ KTOR implementation(libs.ktor.server.content.negotiation) implementation(libs.ktor.serialization.kotlinx.json) implementation(libs.ktor.server.core) implementation(libs.ktor.server.netty) implementation(libs.logback.classic) - implementation(libs.ktor.server.core) implementation(libs.ktor.server.config.yaml) + + // HTTP-клиент для Kotlin/JVM (не Android!) + implementation("io.ktor:ktor-client-cio:2.3.9") + implementation("io.ktor:ktor-client-content-negotiation:2.3.9") + implementation("io.ktor:ktor-client-logging:2.3.9") + + // Корутины и сериализация + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2") + + // Тесты testImplementation(libs.ktor.server.test.host) testImplementation(libs.kotlin.test.junit) -} +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 213dd3b..faab862 100755 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,6 +2,7 @@ kotlin = "2.2.20" ktor = "3.3.0" logback = "1.4.14" +lifecycleViewmodelAndroid = "2.10.0" [libraries] ktor-server-content-negotiation = { module = "io.ktor:ktor-server-content-negotiation", version.ref = "ktor" } @@ -12,6 +13,7 @@ logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "lo ktor-server-config-yaml = { module = "io.ktor:ktor-server-config-yaml", version.ref = "ktor" } ktor-server-test-host = { module = "io.ktor:ktor-server-test-host", version.ref = "ktor" } kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" } +lifecycle-viewmodel-android = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-android", version.ref = "lifecycleViewmodelAndroid" } [plugins] kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } diff --git a/src/main/kotlin/Application.kt b/src/main/kotlin/Application.kt deleted file mode 100755 index 378958a..0000000 --- a/src/main/kotlin/Application.kt +++ /dev/null @@ -1,16 +0,0 @@ -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) { - io.ktor.server.netty.EngineMain.main(args) -} - -fun Application.module() { - install(ContentNegotiation) { - json() - } - configureRouting() -} diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt new file mode 100644 index 0000000..7895ed5 --- /dev/null +++ b/src/main/kotlin/Main.kt @@ -0,0 +1,37 @@ +package com.example + +import com.example.di.Dependencies +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.delay + +fun main() = runBlocking { + val viewModel = Dependencies.createBookingViewModel() + + // Настраиваем колбэки + viewModel.onBookingsUpdated = { bookings -> + println("Бронирования обновлены:") + bookings.forEach { booking -> + println(" Комната: ${booking.room}, Время: ${booking.time}") + } + } + + viewModel.onError = { error -> + if (error != null) { + println("Ошибка: $error") + } + } + + // Загружаем текущие бронирования + println("Загружаем бронирования...") + viewModel.loadBookings() + + delay(1000) // Ждём загрузки + + // Добавляем новое бронирование + println("\nДобавляем новое бронирование...") + viewModel.addBooking("505.6", "14:00 - 16:00") + + delay(1000) // Ждём обработки + + viewModel.dispose() +} \ No newline at end of file diff --git a/src/main/kotlin/Routing.kt b/src/main/kotlin/Routing.kt index 45b01a5..321eeda 100755 --- a/src/main/kotlin/Routing.kt +++ b/src/main/kotlin/Routing.kt @@ -8,6 +8,7 @@ import io.ktor.http.content.PartData import io.ktor.http.content.forEachPart import io.ktor.server.application.* import io.ktor.server.request.receiveMultipart +import io.ktor.server.request.receiveParameters import io.ktor.server.response.* import io.ktor.server.routing.* @@ -27,38 +28,29 @@ fun Application.configureRouting() { get("/user") { call.respond(UserDto(booking = booking)) } + + // ЗАМЕНИТЕ ЭТОТ БЛОК (от post("/book") до закрывающей скобки): post("/book") { - var room = "" - var time = "" - val multipartData = call.receiveMultipart() + try { + // Получаем данные в формате x-www-form-urlencoded + val parameters = call.receiveParameters() + val room = parameters["room"]?.trim() ?: "" + val time = parameters["time"]?.trim() ?: "" - multipartData.forEachPart { part -> - try { - if (part !is PartData.FormItem) return@forEachPart - when (part.name) { - "room" -> { - room = part.value.trim() - } - - "time" -> { - time = part.value.trim() - } - - else -> Unit - } - } finally { - part.dispose() + if (room.isEmpty() || time.isEmpty()) { + call.respond( + HttpStatusCode.BadRequest, + ErrorDto(error = "Fields 'room' and 'time' are required") + ) + } else { + booking.add(BookingDto(room = room, time = time)) + call.respond(HttpStatusCode.OK, mapOf("success" to true)) } - } - - if (room.isEmpty() && time.isEmpty()) { + } catch (e: Exception) { call.respond( HttpStatusCode.BadRequest, - ErrorDto(error = "Field is empty") + ErrorDto(error = "Invalid request format") ) - } else { - booking.add(BookingDto(room = room, time = time)) - call.respond(HttpStatusCode.OK) } } }