Add docker

This commit is contained in:
Evgenii Saenko
2025-12-17 11:52:18 +03:00
parent 2d5b329b36
commit ea390b1533
38 changed files with 1359 additions and 165 deletions

View File

@@ -1,10 +1,43 @@
package cc.essaenko.modules.news
import io.ktor.http.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.serialization.Serializable
import cc.essaenko.shared.pagination.Page
fun Route.adminNewsRoutes(svc: NewsService) = route("/news") {
@Serializable
data class NewsUpdateRequest(
val title: String? = null,
val slug: String? = null,
val summary: String? = null,
val content: String? = null,
val status: String? = null,
val imageUrl: String? = null,
)
fun Route.adminNewsRoutes(svc: NewsService) = route("/admin/news") {
get {
val limit = call.request.queryParameters["limit"]?.toIntOrNull() ?: 50
val page = call.request.queryParameters["page"]?.toIntOrNull() ?: 1
if (page < 1) {
return@get call.respond(
HttpStatusCode.BadRequest,
mapOf("error" to "page must be greater than 0")
)
}
val offset = (page - 1) * limit
val pageData = svc.listAdmin(limit, offset)
call.respond(
Page(
items = pageData.items.map { it.toDto() },
total = pageData.total,
limit = pageData.limit,
offset = pageData.offset
)
)
}
post {
val payload = call.receive<NewsCreate>()
val id = svc.create(payload)
@@ -12,8 +45,8 @@ fun Route.adminNewsRoutes(svc: NewsService) = route("/news") {
}
put("{slug}") {
val slug = call.parameters["slug"]!!
val body = call.receive<Map<String, String>>()
val ok = svc.update(slug, body["summary"].orEmpty(), body["content"].orEmpty())
val body = call.receive<NewsUpdateRequest>()
val ok = svc.update(slug, body.toDomain())
call.respond(mapOf("updated" to ok))
}
post("{slug}/publish") {
@@ -31,16 +64,48 @@ fun Route.adminNewsRoutes(svc: NewsService) = route("/news") {
fun Route.publicNewsRoutes(svc: NewsService) = route("/news") {
get {
val items = svc.list()
call.respond(items.map {
// можно вернуть Entity напрямую (оно сериализуемо, если поля простые),
// но лучше собрать DTO — показываю минимально:
mapOf("id" to it.id, "title" to it.title, "slug" to it.slug, "summary" to it.summary)
})
val limit = call.request.queryParameters["limit"]?.toIntOrNull() ?: 20
val page = call.request.queryParameters["page"]?.toIntOrNull() ?: 1
if (page < 1) {
return@get call.respond(
HttpStatusCode.BadRequest,
mapOf("error" to "page must be greater than 0")
)
}
val offset = (page - 1) * limit
val pageData = svc.list(limit, offset)
call.respond(
Page(
items = pageData.items.map { it.toDto() },
total = pageData.total,
limit = pageData.limit,
offset = pageData.offset
)
)
}
get("{slug}") {
val slug = call.parameters["slug"]!!
val item = svc.get(slug)
call.respond(item)
call.respond(item.toDto())
}
}
}
private fun NewsUpdateRequest.toDomain() = NewsUpdate(
title = title,
slug = slug,
summary = summary,
content = content,
status = status,
imageUrl = imageUrl
)
private fun News.toDto() = NewsDTO(
id = id,
title = title,
content = content,
imageUrl = imageUrl,
slug = slug,
summary = summary,
publishedAt = publishedAt,
status = status,
)