From fff289b9bd7af2cdd84df00a5b33d2154c05bbc4 Mon Sep 17 00:00:00 2001 From: Yulim Lee <81607335+yulimle@users.noreply.github.com> Date: Mon, 30 Dec 2024 18:23:27 +0900 Subject: [PATCH 1/2] add html --- src/jsMain/kotlin/todoapp/TodoClientApplication.kt | 12 +++++++++++- src/jvmMain/kotlin/todoapp/web/IndexRouter.kt | 4 ++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/jsMain/kotlin/todoapp/TodoClientApplication.kt b/src/jsMain/kotlin/todoapp/TodoClientApplication.kt index 62221f3..a909433 100644 --- a/src/jsMain/kotlin/todoapp/TodoClientApplication.kt +++ b/src/jsMain/kotlin/todoapp/TodoClientApplication.kt @@ -1,6 +1,9 @@ package todoapp import kotlinx.browser.document +import kotlinx.html.dom.create +import kotlinx.html.h1 +import kotlinx.html.js.div /** * 클라이언트 애플리케이션 진입점(entry point) @@ -10,5 +13,12 @@ import kotlinx.browser.document fun main() { val container = document.getElementById("root") ?: error("Couldn't find root container!") - TODO("Client application entry point") +// TODO("Client application entry point!") + container.appendChild( + document.create.div { + h1 { + + "Hello, Kotlin/JS!" + } + } + ) } diff --git a/src/jvmMain/kotlin/todoapp/web/IndexRouter.kt b/src/jvmMain/kotlin/todoapp/web/IndexRouter.kt index 390851f..da5d09c 100644 --- a/src/jvmMain/kotlin/todoapp/web/IndexRouter.kt +++ b/src/jvmMain/kotlin/todoapp/web/IndexRouter.kt @@ -35,6 +35,10 @@ class IndexRouter : RouterFunction { // TODO 다음 HTML 태그를 작성하세요 //
// + div{ + id = "root" + } + script (src="/main.js"){ } } } } From 66bb154bca666984181bb05bae70b7b7b164993b Mon Sep 17 00:00:00 2001 From: Yulim Lee <81607335+yulimle@users.noreply.github.com> Date: Tue, 31 Dec 2024 15:51:30 +0900 Subject: [PATCH 2/2] =?UTF-8?q?kotlin=EC=97=90=EC=84=9C=20react?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 2 ++ .../support/InMemoryTodoManager.kt | 5 ++++- .../kotlin/todoapp/TodoClientApplication.kt | 19 +++++++++++++------ src/jsMain/kotlin/todoapp/ui/todo/TodoPage.kt | 11 +++++++++++ .../kotlin/todoapp/ui/welcome/WelcomePage.kt | 19 +++++++++++++++++-- src/jvmMain/kotlin/todoapp/web/TodoRouter.kt | 18 +++++++++++------- 6 files changed, 58 insertions(+), 16 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index ec68990..d470a47 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -60,6 +60,7 @@ dependencyManagement { } kotlin { + // 지원하는 대상(플랫폼) 설정 jvm { withJava() compilations.all { @@ -103,6 +104,7 @@ kotlin { } } } + // 언어 설정 및 리소스 종속성 설정 가능 sourceSets { val commonMain by getting { dependencies { diff --git a/src/commonMain/kotlin/todoapp/application/support/InMemoryTodoManager.kt b/src/commonMain/kotlin/todoapp/application/support/InMemoryTodoManager.kt index fcbb1ae..3181db2 100644 --- a/src/commonMain/kotlin/todoapp/application/support/InMemoryTodoManager.kt +++ b/src/commonMain/kotlin/todoapp/application/support/InMemoryTodoManager.kt @@ -31,7 +31,10 @@ class InMemoryTodoManager( override suspend fun byId(id: TodoId): Todo = loadTodoById(id) override suspend fun register(text: String): TodoId { - TODO("Todo registration logic is not ready") + return Todo.create(text = text, idGenerator = todoIdGenerator).apply { + todos.add(this) + logger.info { "registered todo (id: $id)" } + }.id } override suspend fun modify(id: TodoId, text: String, completed: Boolean) { diff --git a/src/jsMain/kotlin/todoapp/TodoClientApplication.kt b/src/jsMain/kotlin/todoapp/TodoClientApplication.kt index a909433..5ca1dd7 100644 --- a/src/jsMain/kotlin/todoapp/TodoClientApplication.kt +++ b/src/jsMain/kotlin/todoapp/TodoClientApplication.kt @@ -4,6 +4,10 @@ import kotlinx.browser.document import kotlinx.html.dom.create import kotlinx.html.h1 import kotlinx.html.js.div +import react.create +import react.dom.client.createRoot +import todoapp.ui.App +import todoapp.ui.welcome.WelcomePage /** * 클라이언트 애플리케이션 진입점(entry point) @@ -14,11 +18,14 @@ fun main() { val container = document.getElementById("root") ?: error("Couldn't find root container!") // TODO("Client application entry point!") - container.appendChild( - document.create.div { - h1 { - + "Hello, Kotlin/JS!" - } - } +// container.appendChild( +// document.create.div { +// h1 { +// + "Hello, Kotlin/JS!" +// } +// } +// ) + createRoot(container = container).render( + App.create() ) } diff --git a/src/jsMain/kotlin/todoapp/ui/todo/TodoPage.kt b/src/jsMain/kotlin/todoapp/ui/todo/TodoPage.kt index 898b23b..45ba18b 100644 --- a/src/jsMain/kotlin/todoapp/ui/todo/TodoPage.kt +++ b/src/jsMain/kotlin/todoapp/ui/todo/TodoPage.kt @@ -9,7 +9,10 @@ import todoapp.application.TodoCleanup import todoapp.application.TodoFind import todoapp.application.TodoModification import todoapp.application.TodoRegistry +import todoapp.ui.todo.TodoComponents.ControlBar import todoapp.ui.todo.TodoComponents.Info +import todoapp.ui.todo.TodoComponents.ListContainer +import todoapp.ui.todo.TodoComponents.WriteBox import todoapp.ui.todo.TodoProviders.TodoProvider external interface TodoPageProps : Props { @@ -23,6 +26,14 @@ val TodoPage = FC { props -> section { className = ClassName("todoapp") TodoProvider { + TodoComponents.WriteBox { + WriteBox { + text = "todos" + } + } + ListContainer() + ControlBar() + // header: 할 일 작성하기 영역 // main: 할 일 목록 영역 // footer: 할 일 남은 갯수, 필터링 영역 diff --git a/src/jsMain/kotlin/todoapp/ui/welcome/WelcomePage.kt b/src/jsMain/kotlin/todoapp/ui/welcome/WelcomePage.kt index 49df811..1be1657 100644 --- a/src/jsMain/kotlin/todoapp/ui/welcome/WelcomePage.kt +++ b/src/jsMain/kotlin/todoapp/ui/welcome/WelcomePage.kt @@ -4,10 +4,18 @@ import csstype.* import emotion.react.css import react.FC import react.Props +import react.dom.html.InputType import react.dom.html.ReactHTML.div +import react.dom.html.ReactHTML.input import react.dom.html.ReactHTML.section +import react.useState -val WelcomePage = FC { +external interface WelcomePageProps : Props{ + var name: String? +} + +val WelcomePage = FC { + val (name, setName) = useState(it.name ?: "SpringRunner") section { css { position = Position.absolute @@ -20,7 +28,14 @@ val WelcomePage = FC { fontSize = 20.px fontWeight = FontWeight.bold } - +"Hello, SpringRunner" + +"Hello, $name" + } + input { + type = InputType.text + value = name + onChange = { event -> + setName(event.currentTarget.value) + } } } } diff --git a/src/jvmMain/kotlin/todoapp/web/TodoRouter.kt b/src/jvmMain/kotlin/todoapp/web/TodoRouter.kt index fc1830f..f7b4d0a 100644 --- a/src/jvmMain/kotlin/todoapp/web/TodoRouter.kt +++ b/src/jvmMain/kotlin/todoapp/web/TodoRouter.kt @@ -32,10 +32,10 @@ class TodoRouter( ok().bodyValueAndAwait(find.all()) } - // TODO 할 일 일련번호로 할 일을 조회하는 HandlerFunction을 작성하세요 - // 요청 : GET /{id} - // 응답 : Todo Instance - // 귀뜸: TodoFind 인터페이스가 제공하는 byId 메서드를 이용해보세요 + GET("/{id}") { request -> + val id = TodoId(request.pathVariable("id")) + ok().bodyValueAndAwait(find.byId(id)) + } POST("") { request -> val command = request.awaitBody().apply { @@ -48,10 +48,10 @@ class TodoRouter( } PUT("/{id}") { request -> val id = TodoId(request.pathVariable("id")) - val command = request.awaitBody() - // TODO command 객체 값을 검증하세요 - // 귀띔: 할 일 등록하기 핸들러의 코드를 잘 살펴보세요 + val command = request.awaitBody().apply { + validator.process(target = this) + } modification.modify(id, command.text, command.completed) ok().bodyValueAndAwait(find.byId(id)) @@ -61,6 +61,10 @@ class TodoRouter( // 요청 : DELETE /{id} // 응답 : Unit // 귀뜸: TodoCleanup 인터페이스가 제공하는 clear 메서드를 이용해보세요 + DELETE("/{id}") { request -> + cleanup.clear(TodoId(request.pathVariable("id"))) + ok().buildAndAwait() + } POST("/clear-completed") { cleanup.clearAllCompleted()