diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0f991aa..f29b705 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -7,13 +7,15 @@ - + // data에 빈 객체 반환 + ): BaseResponse // data에 빈 객체 반환 @GET("/api/posts/{id}") suspend fun getPostDetail( diff --git a/app/src/main/java/com/example/kuit6_android_api/data/di/AppContainer.kt b/app/src/main/java/com/example/kuit6_android_api/data/di/AppContainer.kt new file mode 100644 index 0000000..7e50cf5 --- /dev/null +++ b/app/src/main/java/com/example/kuit6_android_api/data/di/AppContainer.kt @@ -0,0 +1,16 @@ +package com.example.kuit6_android_api.data.di + +import com.example.kuit6_android_api.data.api.ApiService +import com.example.kuit6_android_api.data.api.RetrofitClient +import com.example.kuit6_android_api.data.repository.PostRepository +import com.example.kuit6_android_api.data.repository.PostRepositoryImpl + +class AppContainer{ + private val apiService: ApiService by lazy{ + RetrofitClient.apiService + } + + val postRepository: PostRepository by lazy { + PostRepositoryImpl(apiService) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/kuit6_android_api/data/repository/PostRepository.kt b/app/src/main/java/com/example/kuit6_android_api/data/repository/PostRepository.kt new file mode 100644 index 0000000..06e4fe8 --- /dev/null +++ b/app/src/main/java/com/example/kuit6_android_api/data/repository/PostRepository.kt @@ -0,0 +1,12 @@ +package com.example.kuit6_android_api.data.repository + +import com.example.kuit6_android_api.data.model.request.PostCreateRequest +import com.example.kuit6_android_api.data.model.response.PostResponse + +interface PostRepository{ + suspend fun getPosts(): Result> + suspend fun getPostDetail(postId: Long): Result + suspend fun createPost(author: String, request: PostCreateRequest): Result + suspend fun updatePost(postId: Long, request: PostCreateRequest): Result + suspend fun deletePost(postId: Long): Result +} \ No newline at end of file diff --git a/app/src/main/java/com/example/kuit6_android_api/data/repository/PostRepositoryImpl.kt b/app/src/main/java/com/example/kuit6_android_api/data/repository/PostRepositoryImpl.kt new file mode 100644 index 0000000..86f6d1c --- /dev/null +++ b/app/src/main/java/com/example/kuit6_android_api/data/repository/PostRepositoryImpl.kt @@ -0,0 +1,83 @@ +package com.example.kuit6_android_api.data.repository + +import android.util.Log +import com.example.kuit6_android_api.data.api.ApiService +import com.example.kuit6_android_api.data.model.request.PostCreateRequest +import com.example.kuit6_android_api.data.model.response.PostResponse + +class PostRepositoryImpl( + private val apiService: ApiService +): PostRepository{ + override suspend fun getPosts(): Result> { + return runCatching { + val response = apiService.getPosts() + + if(response.success && response.data != null){ + response.data + }else{ + throw Exception(response.message ?: "게시글 불러오기 실패") + } + }.onFailure { error -> + Log.e("PostRepository", error.message.toString()) + } + } + + override suspend fun getPostDetail(postId: Long): Result { + return runCatching { + val response = apiService.getPostDetail(postId) + + if (response.success && response.data != null){ + response.data + } else{ + throw Exception(response.message ?: "삭제 실패") + } + }.onFailure { error -> + Log.e("PostRepository", error.message.toString()) + } + } + + override suspend fun createPost( + author: String, + request: PostCreateRequest + ): Result { + return runCatching { + val response = apiService.createPost(author, request) + if (response.success && response.data != null){ + response.data + } else{ + throw Exception(response.message ?: "생성 실패") + } + }.onFailure { error -> + Log.e("PostRepository", error.message.toString()) + } + } + + override suspend fun updatePost( + postId: Long, + request: PostCreateRequest + ): Result { + return runCatching { + val response = apiService.updatePost(postId, request) + if (response.success && response.data != null){ + response.data + }else{ + throw Exception(response.message ?: "업데이트 실패") + } + }.onFailure { error -> + Log.e("PostRepository", error.message.toString()) + } + } + + override suspend fun deletePost(postId: Long): Result { + return runCatching { + val response = apiService.deletePost(postId) + if (response.success && response.data != null){ + response.data + }else{ + throw Exception(response.message ?: "삭제 실패") + } + }.onFailure { error -> + Log.e("PostRepository", error.message.toString()) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/kuit6_android_api/ui/navigation/NavGraph.kt b/app/src/main/java/com/example/kuit6_android_api/ui/navigation/NavGraph.kt index cbcdbd0..8556815 100644 --- a/app/src/main/java/com/example/kuit6_android_api/ui/navigation/NavGraph.kt +++ b/app/src/main/java/com/example/kuit6_android_api/ui/navigation/NavGraph.kt @@ -2,7 +2,7 @@ package com.example.kuit6_android_api.ui.navigation import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable @@ -11,6 +11,11 @@ import com.example.kuit6_android_api.ui.post.screen.PostCreateScreen import com.example.kuit6_android_api.ui.post.screen.PostDetailScreen import com.example.kuit6_android_api.ui.post.screen.PostEditScreen import com.example.kuit6_android_api.ui.post.screen.PostListScreen +import com.example.kuit6_android_api.ui.post.viewmodel.PostCreateViewModel +import com.example.kuit6_android_api.ui.post.viewmodel.PostDetailViewModel +import com.example.kuit6_android_api.ui.post.viewmodel.PostEditViewModel +import com.example.kuit6_android_api.ui.post.viewmodel.PostListViewModel +import com.example.kuit6_android_api.ui.post.viewmodel.PostViewModelFactory @Composable fun NavGraph( @@ -23,19 +28,30 @@ fun NavGraph( startDestination = startDestination ) { composable { + val listViewModel: PostListViewModel = viewModel( + factory = PostViewModelFactory { PostListViewModel(it) } + ) + PostListScreen( onPostClick = { postId -> navController.navigate(PostDetailRoute(postId)) }, onCreatePostClick = { navController.navigate(PostCreateRoute) - } + }, + viewModel = listViewModel ) } composable { backStackEntry -> val route = backStackEntry.toRoute() + val detailViewModel: PostDetailViewModel = viewModel( + factory = PostViewModelFactory { PostDetailViewModel(it) } + ) + val editViewModel: PostEditViewModel = viewModel( + factory = PostViewModelFactory { PostEditViewModel(it) } + ) PostDetailScreen( postId = route.postId, onNavigateBack = { @@ -44,11 +60,17 @@ fun NavGraph( onEditClick = { postId -> navController.navigate(PostEditRoute(postId)) }, - snackBarState = snackBarState + snackBarState = snackBarState, + detailViewModel=detailViewModel, + editViewModel=editViewModel ) } composable { + val createViewModel: PostCreateViewModel = viewModel( + factory = PostViewModelFactory { PostCreateViewModel(it) } + ) + PostCreateScreen( onNavigateBack = { navController.popBackStack() @@ -56,12 +78,20 @@ fun NavGraph( onPostCreated = { navController.popBackStack() }, - snackBarState = snackBarState + snackBarState = snackBarState, + postCreateViewModel = createViewModel ) } composable { backStackEntry -> val route = backStackEntry.toRoute() + val detailViewModel: PostDetailViewModel = viewModel( + factory = PostViewModelFactory { PostDetailViewModel(it) } + ) + + val editViewModel: PostEditViewModel = viewModel( + factory = PostViewModelFactory { PostEditViewModel(it) } + ) PostEditScreen( postId = route.postId, @@ -71,7 +101,9 @@ fun NavGraph( onPostUpdated = { navController.popBackStack() }, - snackBarState = snackBarState + snackBarState = snackBarState, + editViewModel = editViewModel, + detailViewModel = detailViewModel ) } } diff --git a/app/src/main/java/com/example/kuit6_android_api/ui/post/screen/PostCreateScreen.kt b/app/src/main/java/com/example/kuit6_android_api/ui/post/screen/PostCreateScreen.kt index 07ec04f..28519c4 100644 --- a/app/src/main/java/com/example/kuit6_android_api/ui/post/screen/PostCreateScreen.kt +++ b/app/src/main/java/com/example/kuit6_android_api/ui/post/screen/PostCreateScreen.kt @@ -47,6 +47,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel +import com.example.kuit6_android_api.ui.post.viewmodel.PostCreateViewModel import com.example.kuit6_android_api.ui.post.viewmodel.PostViewModel import kotlinx.coroutines.launch @@ -56,7 +57,7 @@ fun PostCreateScreen( onNavigateBack: () -> Unit, onPostCreated: () -> Unit, snackBarState: SnackbarHostState, - viewModel: PostViewModel = viewModel() + postCreateViewModel: PostCreateViewModel = viewModel() ) { val context = LocalContext.current var author by remember { mutableStateOf("") } @@ -196,7 +197,7 @@ fun PostCreateScreen( Button( onClick = { val finalAuthor = author - viewModel.createPost(finalAuthor, title, content, null) { + postCreateViewModel.createPost(finalAuthor, title, content, null) { onPostCreated() scope.launch { snackBarState.showSnackbar("게시글이 작성되었습니다.") } } diff --git a/app/src/main/java/com/example/kuit6_android_api/ui/post/screen/PostEditScreen.kt b/app/src/main/java/com/example/kuit6_android_api/ui/post/screen/PostEditScreen.kt index 23a991c..00a6d5b 100644 --- a/app/src/main/java/com/example/kuit6_android_api/ui/post/screen/PostEditScreen.kt +++ b/app/src/main/java/com/example/kuit6_android_api/ui/post/screen/PostEditScreen.kt @@ -46,6 +46,8 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import coil.compose.AsyncImage +import com.example.kuit6_android_api.ui.post.viewmodel.PostDetailViewModel +import com.example.kuit6_android_api.ui.post.viewmodel.PostEditViewModel import com.example.kuit6_android_api.ui.post.viewmodel.PostViewModel import kotlinx.coroutines.launch @@ -56,7 +58,9 @@ fun PostEditScreen( onNavigateBack: () -> Unit, onPostUpdated: () -> Unit, viewModel: PostViewModel = viewModel(), - snackBarState: SnackbarHostState + snackBarState: SnackbarHostState, + editviewModel: PostEditViewModel = viewModel(), + detailViewModel: PostDetailViewModel = viewModel() ) { val post = viewModel.postDetail diff --git a/app/src/main/java/com/example/kuit6_android_api/ui/post/screen/PostListScreen.kt b/app/src/main/java/com/example/kuit6_android_api/ui/post/screen/PostListScreen.kt index 8522d79..fe31d10 100644 --- a/app/src/main/java/com/example/kuit6_android_api/ui/post/screen/PostListScreen.kt +++ b/app/src/main/java/com/example/kuit6_android_api/ui/post/screen/PostListScreen.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon @@ -18,10 +19,14 @@ import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.example.kuit6_android_api.ui.post.component.PostItem +import com.example.kuit6_android_api.ui.post.state.PostListUiState +import com.example.kuit6_android_api.ui.post.viewmodel.PostListViewModel import com.example.kuit6_android_api.ui.post.viewmodel.PostViewModel @OptIn(ExperimentalMaterial3Api::class) @@ -29,13 +34,9 @@ import com.example.kuit6_android_api.ui.post.viewmodel.PostViewModel fun PostListScreen( onPostClick: (Long) -> Unit, onCreatePostClick: () -> Unit, - viewModel: PostViewModel = viewModel() + viewModel: PostListViewModel ) { - val posts = viewModel.posts - - LaunchedEffect(Unit) { - viewModel.getPosts() - } + val uiState by viewModel.uiState.collectAsState() Scaffold( topBar = { @@ -49,19 +50,29 @@ fun PostListScreen( } } ) { paddingValues -> - LazyColumn( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues) - .background(MaterialTheme.colorScheme.background), - contentPadding = PaddingValues(horizontal = 16.dp, vertical = 12.dp), - verticalArrangement = Arrangement.spacedBy(16.dp) - ) { - items(posts) { post -> - PostItem( - post = post, - onClick = { onPostClick(post.id) } - ) + when (uiState){ + is PostListUiState.Loading -> { + CircularProgressIndicator() + } + is PostListUiState.Success -> { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues) + .background(MaterialTheme.colorScheme.background), + contentPadding = PaddingValues(horizontal = 16.dp, vertical = 12.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + items(items = (uiState as PostListUiState.Success).posts) { post -> + PostItem( + post = post, + onClick = { onPostClick(post.id) } + ) + } + } + } + is PostListUiState.Error -> { + Text(text = "로딩 실패") } } } diff --git a/app/src/main/java/com/example/kuit6_android_api/ui/post/state/PostListUiState.kt b/app/src/main/java/com/example/kuit6_android_api/ui/post/state/PostListUiState.kt new file mode 100644 index 0000000..94bf3d2 --- /dev/null +++ b/app/src/main/java/com/example/kuit6_android_api/ui/post/state/PostListUiState.kt @@ -0,0 +1,15 @@ +package com.example.kuit6_android_api.ui.post.state + +import com.example.kuit6_android_api.data.model.response.PostResponse + +sealed class PostListUiState{ + data object Loading : PostListUiState() + + data class Success( + val posts : List + ): PostListUiState() + + data class Error( + val message:String + ): PostListUiState() +} \ No newline at end of file diff --git a/app/src/main/java/com/example/kuit6_android_api/ui/post/state/PostUIState.kt b/app/src/main/java/com/example/kuit6_android_api/ui/post/state/PostUIState.kt new file mode 100644 index 0000000..6bc62fa --- /dev/null +++ b/app/src/main/java/com/example/kuit6_android_api/ui/post/state/PostUIState.kt @@ -0,0 +1,15 @@ +package com.example.kuit6_android_api.ui.post.state + +import com.example.kuit6_android_api.data.model.response.PostResponse + +sealed class PostUIState { + data object Loading: PostUIState() + + data class Success( + val post: PostResponse + ): PostUIState() + + data class Error( + val message: String + ): PostUIState() +} \ No newline at end of file diff --git a/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostCreateViewModel.kt b/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostCreateViewModel.kt new file mode 100644 index 0000000..e7f51e6 --- /dev/null +++ b/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostCreateViewModel.kt @@ -0,0 +1,46 @@ +package com.example.kuit6_android_api.ui.post.viewmodel + +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.kuit6_android_api.data.model.request.PostCreateRequest +import com.example.kuit6_android_api.data.repository.PostRepository +import com.example.kuit6_android_api.ui.post.state.PostUIState +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch + +class PostCreateViewModel( + private val postRepository: PostRepository +): ViewModel() { + private val _uiState = MutableStateFlow(PostUIState.Loading) + val uiState: StateFlow = _uiState.asStateFlow() + + var uploadedImageUrl by mutableStateOf(null) + private set + + fun createPost(author: String = "anonymous", title: String, content: String, imageUrl: String? = null){ + viewModelScope.launch { + _uiState.value = PostUIState.Loading + val request = PostCreateRequest(title, content, imageUrl) + postRepository.createPost(author, request) + .onSuccess { post -> + _uiState.value = PostUIState.Success(post) + } + .onFailure { error -> + _uiState.value = PostUIState.Error( + message = error.message ?: "error" + ) + } + + clearUploadedImageUrl() + } + } + + fun clearUploadedImageUrl(){ + uploadedImageUrl = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostDetailViewModel.kt b/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostDetailViewModel.kt new file mode 100644 index 0000000..23c2466 --- /dev/null +++ b/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostDetailViewModel.kt @@ -0,0 +1,33 @@ +package com.example.kuit6_android_api.ui.post.viewmodel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.kuit6_android_api.data.repository.PostRepository +import com.example.kuit6_android_api.ui.post.state.PostUIState +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch + +class PostDetailViewModel( + private val postRepository: PostRepository +): ViewModel() { + private val _uiState = MutableStateFlow(PostUIState.Loading) + val uiState: StateFlow = _uiState.asStateFlow() + + fun getPostDetail(postId: Long){ + viewModelScope.launch { + _uiState.value = PostUIState.Loading + + postRepository.getPostDetail(postId) + .onSuccess { post -> + _uiState.value = PostUIState.Success(post) + } + .onFailure { error -> + _uiState.value = PostUIState.Error( + message = error.message ?: "error" + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostEditViewModel.kt b/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostEditViewModel.kt new file mode 100644 index 0000000..95c2ae0 --- /dev/null +++ b/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostEditViewModel.kt @@ -0,0 +1,52 @@ +package com.example.kuit6_android_api.ui.post.viewmodel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.kuit6_android_api.data.model.request.PostCreateRequest +import com.example.kuit6_android_api.data.repository.PostRepository +import com.example.kuit6_android_api.ui.post.state.PostUIState +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch + +class PostEditViewModel ( + private val postRepository: PostRepository + ): ViewModel(){ + private val _uiState = MutableStateFlow(PostUIState.Loading) + val uiState: StateFlow = _uiState.asStateFlow() + + + fun deletePost(postId: Long){ + viewModelScope.launch { + _uiState.value = PostUIState.Loading + + postRepository.deletePost(postId) + .onSuccess { post -> + _uiState.value = PostUIState.Success(post) + } + .onFailure { error -> + _uiState.value = PostUIState.Error( + message = error.message ?: "error" + ) + } + } + } + + fun updatePost(postId: Long, title: String, content: String, imageUrl: String? = null){ + viewModelScope.launch { + _uiState.value = PostUIState.Loading + val request = PostCreateRequest(title, content, imageUrl) + + postRepository.updatePost(postId, request) + .onSuccess { post -> + _uiState.value = PostUIState.Success(post) + } + .onFailure { error -> + _uiState.value = PostUIState.Error( + message = error.message ?: "error" + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostListViewModel.kt b/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostListViewModel.kt new file mode 100644 index 0000000..f93181f --- /dev/null +++ b/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostListViewModel.kt @@ -0,0 +1,41 @@ +package com.example.kuit6_android_api.ui.post.viewmodel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.kuit6_android_api.data.repository.PostRepository +import com.example.kuit6_android_api.ui.post.state.PostListUiState +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch + +class PostListViewModel( + private val postRepository: PostRepository +): ViewModel(){ + private val _uiState = MutableStateFlow(PostListUiState.Loading) + val uiState: StateFlow = _uiState.asStateFlow() + + init { + loadPosts() + } + + private fun loadPosts(){ + viewModelScope.launch { + _uiState.value = PostListUiState.Loading + + postRepository.getPosts() + .onSuccess { posts-> + _uiState.value = PostListUiState.Success(posts) + } + .onFailure { error-> + _uiState.value = PostListUiState.Error( + message = error.message ?: "error" + ) + } + } + } + + fun refresh(){ + loadPosts() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostViewModel.kt b/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostViewModel.kt index d245bd7..061d083 100644 --- a/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostViewModel.kt +++ b/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostViewModel.kt @@ -22,19 +22,6 @@ class PostViewModel : ViewModel() { private set private val apiService = RetrofitClient.apiService - fun getPosts() { - viewModelScope.launch { - runCatching { - apiService.getPosts() - }.onSuccess { response -> - response.data?.let { - if (response.success){ - posts = response.data - } - } - } - } - } fun getPostDetail(postId: Long) { viewModelScope.launch { diff --git a/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostViewModelFactory.kt b/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostViewModelFactory.kt new file mode 100644 index 0000000..449349c --- /dev/null +++ b/app/src/main/java/com/example/kuit6_android_api/ui/post/viewmodel/PostViewModelFactory.kt @@ -0,0 +1,22 @@ +package com.example.kuit6_android_api.ui.post.viewmodel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewmodel.initializer +import androidx.lifecycle.viewmodel.viewModelFactory +import com.example.kuit6_android_api.App +import com.example.kuit6_android_api.data.repository.PostRepository +import okhttp3.Call + +inline fun PostViewModelFactory( + crossinline create: (PostRepository) -> VM +): ViewModelProvider.Factory = viewModelFactory { + initializer { + val application = this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] + as App + + val postRepository = application.container.postRepository + + create(postRepository) + } + }