Course work: implement full performance CRUD

This commit is contained in:
abazov73 2023-12-27 01:21:02 +04:00
parent a687ff002f
commit 2eca8db087
14 changed files with 606 additions and 14 deletions

View File

@ -67,7 +67,8 @@ dependencies {
implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3") implementation("androidx.compose.material3:material3:1.1.2")
implementation("androidx.compose.material:material:1.4.3")
// Room // Room
val room_version = "2.5.2" val room_version = "2.5.2"

View File

@ -60,6 +60,22 @@ interface MyServerService {
@Body credentials: Credentials @Body credentials: Credentials
): Token ): Token
@POST("api/performances")
suspend fun createPerformance(
@Body performance: PerformanceRemote,
)
@PUT("api/performances/{id}")
suspend fun updatePerformance(
@Path("id") id: Int,
@Body student: PerformanceRemote,
)
@DELETE("api/performances/{id}")
suspend fun deletePerformance(
@Path("id") id: Int,
)
companion object { companion object {
private const val BASE_URL = "http://10.0.2.2:8000/" private const val BASE_URL = "http://10.0.2.2:8000/"

View File

@ -41,3 +41,13 @@ suspend fun PerformanceRemote.toPerformanceWithPeople(service: MyServerService):
actorsList.toList() actorsList.toList()
) )
} }
fun Performance.toPerformanceRemote(): PerformanceRemote = PerformanceRemote(
performance_uid!!,
title,
description,
authorId!!,
directorId!!,
imageURL,
previewImageURL
)

View File

@ -6,6 +6,7 @@ import androidx.paging.PagingConfig
import androidx.paging.PagingData import androidx.paging.PagingData
import com.example.mobile_labs.api.MyServerService import com.example.mobile_labs.api.MyServerService
import com.example.mobile_labs.api.models.toPerformance import com.example.mobile_labs.api.models.toPerformance
import com.example.mobile_labs.api.models.toPerformanceRemote
import com.example.mobile_labs.api.models.toPerformanceWithPeople import com.example.mobile_labs.api.models.toPerformanceWithPeople
import com.example.mobile_labs.api.people.RestPersonRepository import com.example.mobile_labs.api.people.RestPersonRepository
import com.example.mobile_labs.common.AppDataContainer import com.example.mobile_labs.common.AppDataContainer
@ -50,4 +51,16 @@ class RestPerformanceRepository(
override suspend fun getPerformance(uid: Int): PerformanceWithPeople = override suspend fun getPerformance(uid: Int): PerformanceWithPeople =
service.getPerformance(uid).toPerformanceWithPeople(service) service.getPerformance(uid).toPerformanceWithPeople(service)
override suspend fun insertPerformance(performance: Performance) {
service.createPerformance(performance.toPerformanceRemote())
}
override suspend fun updatePerformance(performance: Performance) {
service.updatePerformance(performance.performance_uid!!, performance.toPerformanceRemote())
}
override suspend fun deletePerformance(performance: Performance) {
service.deletePerformance(performance.performance_uid !!)
}
} }

View File

@ -64,6 +64,6 @@ class AppDataContainer(val context: Context) : AppContainer {
companion object { companion object {
const val TIMEOUT = 5000L const val TIMEOUT = 5000L
const val LIMIT = 3 const val LIMIT = 20
} }
} }

View File

@ -8,7 +8,9 @@ import androidx.lifecycle.viewmodel.viewModelFactory
import com.example.mobile_labs.TheatreApplication import com.example.mobile_labs.TheatreApplication
import com.example.mobile_labs.ui.event.list.EventListViewModel import com.example.mobile_labs.ui.event.list.EventListViewModel
import com.example.mobile_labs.ui.login.LoginViewModel import com.example.mobile_labs.ui.login.LoginViewModel
import com.example.mobile_labs.ui.performance.list.AdminPerformanceListViewModel
import com.example.mobile_labs.ui.performance.list.PerformanceListViewModel import com.example.mobile_labs.ui.performance.list.PerformanceListViewModel
import com.example.mobile_labs.ui.performance.view.AdminPerformanceViewModel
import com.example.mobile_labs.ui.performance.view.PerformanceViewModel import com.example.mobile_labs.ui.performance.view.PerformanceViewModel
import com.example.mobile_labs.ui.person.list.PeopleListViewModel import com.example.mobile_labs.ui.person.list.PeopleListViewModel
@ -29,6 +31,12 @@ object AppViewModelProvider {
initializer { initializer {
LoginViewModel() LoginViewModel()
} }
initializer {
AdminPerformanceListViewModel(theatreApplication().container.performanceRestRepository)
}
initializer {
AdminPerformanceViewModel(this.createSavedStateHandle(), theatreApplication().container.performanceRestRepository)
}
} }
} }

View File

@ -8,4 +8,7 @@ import kotlinx.coroutines.flow.Flow
interface PerformanceRepository { interface PerformanceRepository {
fun getAllPerformances(): Flow<PagingData<Performance>> fun getAllPerformances(): Flow<PagingData<Performance>>
suspend fun getPerformance(uid: Int): PerformanceWithPeople suspend fun getPerformance(uid: Int): PerformanceWithPeople
suspend fun insertPerformance(performance: Performance)
suspend fun updatePerformance(performance: Performance)
suspend fun deletePerformance(performance: Performance)
} }

View File

@ -24,11 +24,11 @@ class OfflinePerformanceRepository(private val performanceDao: PerformanceDao) :
).flow ).flow
override suspend fun getPerformance(uid: Int): PerformanceWithPeople = performanceDao.getByUid(uid).first(); override suspend fun getPerformance(uid: Int): PerformanceWithPeople = performanceDao.getByUid(uid).first();
suspend fun insertPerformance(performance: Performance) = performanceDao.insert(performance); override suspend fun insertPerformance(performance: Performance) = performanceDao.insert(performance);
suspend fun updatePerformance(performance: Performance) = performanceDao.update(performance); override suspend fun updatePerformance(performance: Performance) = performanceDao.update(performance);
suspend fun deletePerformance(performance: Performance) = performanceDao.delete(performance); override suspend fun deletePerformance(performance: Performance) = performanceDao.delete(performance);
suspend fun clearPerformances() = performanceDao.deleteAll() suspend fun clearPerformances() = performanceDao.deleteAll()

View File

@ -1,6 +1,7 @@
package com.example.mobile_labs.ui.navigation package com.example.mobile_labs.ui.navigation
import android.content.res.Configuration import android.content.res.Configuration
import android.util.Log
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
@ -37,7 +38,9 @@ import com.example.mobile_labs.api.MyServerService
import com.example.mobile_labs.ui.about.About import com.example.mobile_labs.ui.about.About
import com.example.mobile_labs.ui.event.list.EventList import com.example.mobile_labs.ui.event.list.EventList
import com.example.mobile_labs.ui.login.Login import com.example.mobile_labs.ui.login.Login
import com.example.mobile_labs.ui.performance.list.AdminPerformanceList
import com.example.mobile_labs.ui.performance.list.PerformanceList import com.example.mobile_labs.ui.performance.list.PerformanceList
import com.example.mobile_labs.ui.performance.view.AdminPerformanceView
import com.example.mobile_labs.ui.performance.view.PerformanceView import com.example.mobile_labs.ui.performance.view.PerformanceView
import com.example.mobile_labs.ui.person.list.PeopleList import com.example.mobile_labs.ui.person.list.PeopleList
@ -79,8 +82,26 @@ fun Navbar(
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
NavigationBar(modifier) { NavigationBar(modifier) {
if (MyServerService.getToken().isBlank()) {
Screen.bottomBarItems.forEach { screen -> Screen.bottomBarItems.forEach { screen ->
if (MyServerService.getToken().isBlank() || screen.route !== "login") { NavigationBarItem(
icon = { Icon(screen.icon, contentDescription = null) },
label = { Text(stringResource(screen.resourceId)) },
selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
onClick = {
navController.navigate(screen.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = false
}
launchSingleTop = true
restoreState = false
}
}
)
}
}
else {
Screen.adminBottomBarItems.forEach { screen ->
NavigationBarItem( NavigationBarItem(
icon = { Icon(screen.icon, contentDescription = null) }, icon = { Icon(screen.icon, contentDescription = null) },
label = { Text(stringResource(screen.resourceId)) }, label = { Text(stringResource(screen.resourceId)) },
@ -113,8 +134,13 @@ fun Navhost(
) { ) {
composable(Screen.Schedule.route) { EventList(navController) } composable(Screen.Schedule.route) { EventList(navController) }
composable(Screen.Repertoire.route) { composable(Screen.Repertoire.route) {
if (MyServerService.getToken().isNotBlank()) {
AdminPerformanceList(navController)
}
else {
PerformanceList(navController) PerformanceList(navController)
} }
}
composable(Screen.PeopleList.route) { PeopleList() } composable(Screen.PeopleList.route) { PeopleList() }
composable(Screen.About.route) { About() } composable(Screen.About.route) { About() }
if (MyServerService.getToken().isBlank()) { if (MyServerService.getToken().isBlank()) {
@ -124,9 +150,14 @@ fun Navhost(
Screen.PerformanceView.route, Screen.PerformanceView.route,
arguments = listOf(navArgument("id") { type = NavType.IntType }) arguments = listOf(navArgument("id") { type = NavType.IntType })
) { backStackEntry -> ) { backStackEntry ->
if (MyServerService.getToken().isNotBlank()) {
AdminPerformanceView(navController)
}
else {
backStackEntry.arguments?.let { PerformanceView() } backStackEntry.arguments?.let { PerformanceView() }
} }
} }
}
} }
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)

View File

@ -38,16 +38,16 @@ enum class Screen(
); );
companion object { companion object {
val bottomBarItems = if (MyServerService.getToken().isBlank()) listOf( val bottomBarItems = listOf(
Schedule, Schedule,
Repertoire, Repertoire,
PeopleList, PeopleList,
About, About,
Login Login
) else listOf( )
Schedule,
val adminBottomBarItems = listOf(
Repertoire, Repertoire,
PeopleList,
About, About,
) )

View File

@ -0,0 +1,261 @@
package com.example.mobile_labs.ui.performance.list
import android.content.res.Configuration
import android.util.Log
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.spring
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.DismissDirection
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.DismissState
import androidx.compose.material3.DismissValue
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SwipeToDismiss
import androidx.compose.material3.rememberDismissState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import androidx.paging.PagingData
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemContentType
import androidx.paging.compose.itemKey
import coil.compose.AsyncImage
import com.example.mobile_labs.R
import com.example.mobile_labs.api.MyServerService
import com.example.mobile_labs.database.performance.model.Performance
import com.example.mobile_labs.common.AppViewModelProvider
import com.example.mobile_labs.ui.navigation.Screen
import com.example.mobile_labs.ui.theme.Mobile_LabsTheme
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
@Composable
fun AdminPerformanceList(
navController: NavController,
viewModel: AdminPerformanceListViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
val coroutineScope = rememberCoroutineScope()
val performanceListUiState = viewModel.performanceListUiState.collectAsLazyPagingItems()
Scaffold(
topBar = {},
floatingActionButton = {
FloatingActionButton(
onClick = {
val route = Screen.PerformanceView.route.replace("{id}", 0.toString())
navController.navigate(route)
},
) {
Icon(Icons.Filled.Add, "Добавить")
}
}
) { innerPadding ->
PerformanceList(
modifier = Modifier
.padding(innerPadding)
.fillMaxSize(),
performanceList = performanceListUiState,
onClick = { uid: Int ->
val route = Screen.PerformanceView.route.replace("{id}", uid.toString())
navController.navigate(route)
},
onSwipe = { performance: Performance ->
coroutineScope.launch {
viewModel.deleteStudent(performance)
}
}
)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DismissBackground(dismissState: DismissState) {
val color = when (dismissState.dismissDirection) {
DismissDirection.StartToEnd -> Color.Transparent
DismissDirection.EndToStart -> Color(0xFFFF1744)
null -> Color.Transparent
}
val direction = dismissState.dismissDirection
Row(
modifier = Modifier
.fillMaxSize()
.background(color)
.padding(12.dp, 8.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End
) {
if (direction == DismissDirection.EndToStart) {
Icon(
Icons.Default.Delete,
contentDescription = "delete",
tint = Color.White
)
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun SwipeToDelete(
dismissState: DismissState,
performance: Performance,
onClick: (uid: Int) -> Unit
) {
SwipeToDismiss(
modifier = Modifier.zIndex(1f),
state = dismissState,
directions = setOf(
DismissDirection.EndToStart
),
background = {
DismissBackground(dismissState)
},
dismissContent = {
PerformanceListItem(performance = performance,
modifier = Modifier
.padding(vertical = 7.dp)
.clickable { onClick(performance.performance_uid!!) })
}
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun PerformanceList(
modifier: Modifier = Modifier,
performanceList: LazyPagingItems<Performance>,
onClick: (uid: Int) -> Unit,
onSwipe: (performance: Performance) -> Unit
) {
Column(
modifier = modifier
) {
if (performanceList.itemCount == 0) {
Text(
text = stringResource(R.string.performance_missing_description),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.titleLarge
)
} else {
LazyColumn(modifier = Modifier.padding(all = 10.dp)) {
items(
count = performanceList.itemCount,
key = performanceList.itemKey(),
contentType = performanceList.itemContentType()
) { index ->
val performance = performanceList[index]
performance?.let {
var show by remember { mutableStateOf(true) }
val dismissState = rememberDismissState(
confirmValueChange = {
if (it == DismissValue.DismissedToStart ||
it == DismissValue.DismissedToEnd
) {
show = false
true
} else false
}, positionalThreshold = { 200.dp.toPx() }
)
AnimatedVisibility(
show, exit = fadeOut(spring())
) {
SwipeToDelete(
dismissState = dismissState,
performance = performance,
onClick = onClick
)
}
LaunchedEffect(show) {
if (!show) {
delay(800)
onSwipe(performance)
}
}
}
}
}
}
}
}
@Composable
private fun PerformanceListItem(
performance: Performance,
modifier: Modifier = Modifier,
) {
Card(
modifier = modifier.fillMaxWidth(),
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
) {
Column(
modifier = modifier.padding(all = 10.dp)
) {
AsyncImage(model = performance.imageURL, contentDescription = "")
Button(
modifier = Modifier
.fillMaxWidth()
.padding(all = 10.dp),
onClick = { }) {
Text(performance.title)
}
}
}
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun AdminSchedulePreview() {
Mobile_LabsTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
PerformanceList(
performanceList = MutableStateFlow(
PagingData.empty<Performance>()
).collectAsLazyPagingItems(),
onClick = {},
onSwipe = {}
)
}
}
}

View File

@ -0,0 +1,17 @@
package com.example.mobile_labs.ui.performance.list
import androidx.lifecycle.ViewModel
import androidx.paging.PagingData
import com.example.mobile_labs.common.PerformanceRepository
import com.example.mobile_labs.database.performance.model.Performance
import kotlinx.coroutines.flow.Flow
class AdminPerformanceListViewModel(
private val performanceRepository: PerformanceRepository
) : ViewModel() {
val performanceListUiState: Flow<PagingData<Performance>> = performanceRepository.getAllPerformances()
suspend fun deleteStudent(performance: Performance) {
performanceRepository.deletePerformance(performance)
}
}

View File

@ -0,0 +1,129 @@
package com.example.mobile_labs.ui.performance.view
import android.content.res.Configuration
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import coil.compose.AsyncImage
import com.example.mobile_labs.R
import com.example.mobile_labs.common.AppViewModelProvider
import com.example.mobile_labs.ui.theme.Mobile_LabsTheme
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AdminPerformanceView(
navController: NavController,
viewModel: AdminPerformanceViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
val coroutineScope = rememberCoroutineScope()
PerformanceEdit(
performanceUiState = viewModel.performanceUiState,
onClick = {
coroutineScope.launch {
viewModel.savePerformance()
navController.popBackStack()
}
},
onUpdate = viewModel::updateUiState,
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun PerformanceEdit(
performanceUiState: AdminPerformanceUiState,
onClick: () -> Unit,
onUpdate: (AdminPerformanceDetails) -> Unit,
) {
Column(
Modifier
.fillMaxWidth()
.padding(all = 10.dp)
) {
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
value = performanceUiState.performanceDetails.title,
onValueChange = { onUpdate(performanceUiState.performanceDetails.copy(title = it)) },
label = {Text("Название")},
singleLine = true
)
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
value = performanceUiState.performanceDetails.description,
onValueChange = { onUpdate(performanceUiState.performanceDetails.copy(description = it)) },
label = {Text("Описание")},
singleLine = true
)
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
value = performanceUiState.performanceDetails.imageURL,
onValueChange = { onUpdate(performanceUiState.performanceDetails.copy(imageURL = it)) },
label = { Text("URL изображения") },
singleLine = true,
)
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
value = performanceUiState.performanceDetails.previewImageUrl,
onValueChange = { onUpdate(performanceUiState.performanceDetails.copy(previewImageUrl = it)) },
label = {Text("URL превью")},
singleLine = true
)
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
value = performanceUiState.performanceDetails.authorId.toString(),
onValueChange = { onUpdate(performanceUiState.performanceDetails.copy(authorId = it.toInt())) },
label = {Text("Автор")},
singleLine = true,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Phone)
)
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
value = performanceUiState.performanceDetails.directorId.toString(),
onValueChange = { onUpdate(performanceUiState.performanceDetails.copy(directorId = it.toInt())) },
label = {Text("Режиссер")},
singleLine = true,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Phone)
)
Button(
onClick = onClick,
enabled = performanceUiState.isEntryValid,
shape = MaterialTheme.shapes.small,
modifier = Modifier.fillMaxWidth()
) {
Text(text = "Сохранить")
}
}
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun AdminPerformanceViewPreview() {
Mobile_LabsTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
PerformanceView()
}
}
}

View File

@ -0,0 +1,103 @@
package com.example.mobile_labs.ui.performance.view
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.mobile_labs.database.performance.model.PerformanceWithPeople
import com.example.mobile_labs.common.PerformanceRepository
import com.example.mobile_labs.database.performance.model.Performance
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
class AdminPerformanceViewModel(
savedStateHandle: SavedStateHandle,
private val performanceRepository: PerformanceRepository
) : ViewModel() {
var performanceUiState by mutableStateOf(AdminPerformanceUiState())
private set
private val performanceUid: Int = checkNotNull(savedStateHandle["id"])
init {
viewModelScope.launch {
if (performanceUid > 0) {
performanceUiState = performanceRepository.getPerformance(performanceUid)
.toUiStateAdmin()
}
}
}
fun updateUiState(performanceDetails: AdminPerformanceDetails) {
performanceUiState = AdminPerformanceUiState(
performanceDetails = performanceDetails,
isEntryValid = validateInput(performanceDetails)
)
}
suspend fun savePerformance() {
if (validateInput()) {
if (performanceUid > 0) {
performanceRepository.updatePerformance(
performanceUiState.performanceDetails.toPerformance(performanceUid)
)
} else {
performanceRepository.insertPerformance(
performanceUiState.performanceDetails.toPerformance()
)
}
}
}
private fun validateInput(uiState: AdminPerformanceDetails = performanceUiState.performanceDetails): Boolean {
return with(uiState) {
title.isNotBlank()
&& description.isNotBlank()
}
}
}
data class AdminPerformanceUiState(
val performanceDetails: AdminPerformanceDetails = AdminPerformanceDetails(),
val isEntryValid: Boolean = false
)
data class AdminPerformanceDetails(
val title: String = "",
val authorName: String = "",
val actorsList: String = "",
val imageURL: String = "",
val description: String = "",
val authorId: Int = 0,
val directorId: Int = 0,
val previewImageUrl: String = "",
)
fun PerformanceWithPeople.toAdminDetails(): AdminPerformanceDetails = AdminPerformanceDetails(
title = performance.title,
authorName = String.format("%s %s", author.last_name, author.first_name),
actorsList = buildString { for (actor in actors) append(actor.last_name + " " + actor.first_name + "\n") },
imageURL = performance.imageURL,
description = performance.description,
authorId = performance.authorId!!,
directorId = performance.directorId!!,
previewImageUrl = performance.previewImageURL,
)
fun PerformanceWithPeople.toUiStateAdmin(): AdminPerformanceUiState = AdminPerformanceUiState(
performanceDetails = this.toAdminDetails(),
)
fun AdminPerformanceDetails.toPerformance(uid: Int = 0): Performance = Performance(
performance_uid = uid,
title = title,
authorId = authorId,
directorId = directorId,
imageURL = imageURL,
description = description,
previewImageURL = previewImageUrl
)