поиск
This commit is contained in:
parent
3dc39aa82f
commit
55a0ac8581
@ -1,6 +1,5 @@
|
|||||||
package com.example.myapplication.api.cinema
|
package com.example.myapplication.api.cinema
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.paging.ExperimentalPagingApi
|
import androidx.paging.ExperimentalPagingApi
|
||||||
import androidx.paging.Pager
|
import androidx.paging.Pager
|
||||||
import androidx.paging.PagingConfig
|
import androidx.paging.PagingConfig
|
||||||
@ -24,11 +23,7 @@ class RestCinemaRepository(
|
|||||||
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
|
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
|
||||||
private val database: AppDatabase
|
private val database: AppDatabase
|
||||||
) : CinemaRepository {
|
) : CinemaRepository {
|
||||||
override fun getAllCinemas(): Flow<PagingData<Cinema>> {
|
override fun getAllCinemas(name: String): Flow<PagingData<Cinema>> {
|
||||||
Log.d(RestCinemaRepository::class.simpleName, "Get cinemas")
|
|
||||||
|
|
||||||
val pagingSourceFactory = { dbCinemaRepository.getAllCinemasPagingSource() }
|
|
||||||
|
|
||||||
@OptIn(ExperimentalPagingApi::class)
|
@OptIn(ExperimentalPagingApi::class)
|
||||||
return Pager(
|
return Pager(
|
||||||
config = PagingConfig(
|
config = PagingConfig(
|
||||||
@ -42,8 +37,13 @@ class RestCinemaRepository(
|
|||||||
dbRemoteKeyRepository,
|
dbRemoteKeyRepository,
|
||||||
database,
|
database,
|
||||||
),
|
),
|
||||||
pagingSourceFactory = pagingSourceFactory
|
) {
|
||||||
).flow
|
if (name.isEmpty()) {
|
||||||
|
dbCinemaRepository.getAllCinemasPagingSource()
|
||||||
|
} else {
|
||||||
|
dbCinemaRepository.getAllCinemasPagingSource(name)
|
||||||
|
}
|
||||||
|
}.flow
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getCinema(uid: Int): CinemaWithSessions {
|
override suspend fun getCinema(uid: Int): CinemaWithSessions {
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
package com.example.myapplication.composeui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Search
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Search(
|
||||||
|
initValue: String,
|
||||||
|
onDone: (String) -> Unit,
|
||||||
|
modifier: Modifier
|
||||||
|
) {
|
||||||
|
val maxLength = 20
|
||||||
|
val (value, setValue) = remember { mutableStateOf(initValue) }
|
||||||
|
fun clear() {
|
||||||
|
setValue("")
|
||||||
|
onDone("")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleChange(newValue: String) {
|
||||||
|
if (newValue.length > maxLength) {
|
||||||
|
return
|
||||||
|
} else if (newValue.isEmpty()) {
|
||||||
|
clear()
|
||||||
|
}
|
||||||
|
setValue(newValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleDone() {
|
||||||
|
onDone(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicTextField(
|
||||||
|
value = value,
|
||||||
|
onValueChange = { handleChange(it) },
|
||||||
|
modifier = modifier,
|
||||||
|
singleLine = true,
|
||||||
|
keyboardActions = KeyboardActions(
|
||||||
|
onDone = { handleDone() }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.width(16.dp))
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.Search,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(30.dp)
|
||||||
|
.clickable { handleDone() },
|
||||||
|
tint = MaterialTheme.colorScheme.secondary,
|
||||||
|
)
|
||||||
|
}
|
@ -12,13 +12,9 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.BasicTextField
|
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.filled.Person
|
import androidx.compose.material.icons.filled.Person
|
||||||
import androidx.compose.material.icons.filled.Search
|
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.NavigationBar
|
import androidx.compose.material3.NavigationBar
|
||||||
@ -29,9 +25,6 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
@ -49,6 +42,7 @@ import androidx.navigation.navArgument
|
|||||||
import com.example.myapplication.LiveStore
|
import com.example.myapplication.LiveStore
|
||||||
import com.example.myapplication.composeui.Cart
|
import com.example.myapplication.composeui.Cart
|
||||||
import com.example.myapplication.composeui.Report
|
import com.example.myapplication.composeui.Report
|
||||||
|
import com.example.myapplication.composeui.Search
|
||||||
import com.example.myapplication.database.entities.composeui.CinemaList
|
import com.example.myapplication.database.entities.composeui.CinemaList
|
||||||
import com.example.myapplication.database.entities.composeui.CinemaView
|
import com.example.myapplication.database.entities.composeui.CinemaView
|
||||||
import com.example.myapplication.database.entities.composeui.OrderList
|
import com.example.myapplication.database.entities.composeui.OrderList
|
||||||
@ -64,7 +58,6 @@ fun Topbar(
|
|||||||
navController: NavHostController,
|
navController: NavHostController,
|
||||||
currentScreen: Screen?
|
currentScreen: Screen?
|
||||||
) {
|
) {
|
||||||
var searchQuery by remember { mutableStateOf("") }
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@ -100,35 +93,22 @@ fun Topbar(
|
|||||||
|
|
||||||
Spacer(modifier = Modifier.width(16.dp))
|
Spacer(modifier = Modifier.width(16.dp))
|
||||||
|
|
||||||
BasicTextField(
|
if (currentScreen?.route == Screen.CinemaList.route) {
|
||||||
value = searchQuery,
|
Search(
|
||||||
onValueChange = { newValue -> searchQuery = newValue },
|
initValue = LiveStore.searchRequest.value ?: "",
|
||||||
modifier = Modifier
|
onDone = {
|
||||||
.weight(1f)
|
LiveStore.searchRequest.value = it
|
||||||
.height(36.dp)
|
},
|
||||||
.background(
|
modifier = Modifier
|
||||||
color = MaterialTheme.colorScheme.onPrimary,
|
.weight(1f)
|
||||||
RoundedCornerShape(18.dp)
|
.height(36.dp)
|
||||||
)
|
.background(
|
||||||
.padding(start = 13.dp, top = 8.dp),
|
color = MaterialTheme.colorScheme.onPrimary,
|
||||||
keyboardOptions = KeyboardOptions.Default.copy(
|
RoundedCornerShape(18.dp)
|
||||||
imeAction = androidx.compose.ui.text.input.ImeAction.Search
|
)
|
||||||
),
|
.padding(start = 13.dp, top = 8.dp)
|
||||||
keyboardActions = KeyboardActions(
|
|
||||||
onSearch = { }
|
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.width(16.dp))
|
|
||||||
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Default.Search,
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier
|
|
||||||
.size(30.dp)
|
|
||||||
.clickable { },
|
|
||||||
tint = MaterialTheme.colorScheme.secondary
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
@ -48,8 +49,13 @@ fun CinemaList(
|
|||||||
viewModel: CinemaListViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
viewModel: CinemaListViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||||
) {
|
) {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
val cinemaPagingItems = viewModel.cinemaListUiState.collectAsLazyPagingItems()
|
val cinemaPagingItems = viewModel.cinemaPagingFlow.flow.collectAsLazyPagingItems()
|
||||||
val user = LiveStore.user.observeAsState()
|
val user = LiveStore.user.observeAsState()
|
||||||
|
val searchPattern = LiveStore.searchRequest.observeAsState("")
|
||||||
|
|
||||||
|
LaunchedEffect(searchPattern.value) {
|
||||||
|
viewModel.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {},
|
topBar = {},
|
||||||
|
@ -1,17 +1,35 @@
|
|||||||
package com.example.myapplication.database.entities.composeui
|
package com.example.myapplication.database.entities.composeui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
import androidx.paging.PagingData
|
import androidx.paging.PagingData
|
||||||
|
import androidx.paging.cachedIn
|
||||||
|
import com.example.myapplication.LiveStore
|
||||||
import com.example.myapplication.database.entities.model.Cinema
|
import com.example.myapplication.database.entities.model.Cinema
|
||||||
import com.example.myapplication.database.entities.repository.CinemaRepository
|
import com.example.myapplication.database.entities.repository.CinemaRepository
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.emptyFlow
|
||||||
|
|
||||||
class CinemaListViewModel(
|
class CinemaListViewModel(
|
||||||
private val cinemaRepository: CinemaRepository
|
private val cinemaRepository: CinemaRepository
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
val cinemaListUiState: Flow<PagingData<Cinema>> = cinemaRepository.getAllCinemas()
|
var cinemaPagingFlow by mutableStateOf(ProductPagingFlowState())
|
||||||
|
private set
|
||||||
|
|
||||||
|
fun refresh() {
|
||||||
|
val name = "%${LiveStore.searchRequest.value}%"
|
||||||
|
val pagingSource = cinemaRepository.getAllCinemas(name)
|
||||||
|
cinemaPagingFlow = ProductPagingFlowState(pagingSource.cachedIn(viewModelScope))
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun deleteCinema(cinema: Cinema) {
|
suspend fun deleteCinema(cinema: Cinema) {
|
||||||
cinemaRepository.deleteCinema(cinema)
|
cinemaRepository.deleteCinema(cinema)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class ProductPagingFlowState(
|
||||||
|
val flow: Flow<PagingData<Cinema>> = emptyFlow(),
|
||||||
|
)
|
@ -14,6 +14,8 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
interface CinemaDao {
|
interface CinemaDao {
|
||||||
@Query("select * from cinemas order by name")
|
@Query("select * from cinemas order by name")
|
||||||
fun getAll(): PagingSource<Int, Cinema>
|
fun getAll(): PagingSource<Int, Cinema>
|
||||||
|
@Query("select * from cinemas where cinemas.name like :name order by name collate nocase asc")
|
||||||
|
fun getAll(name: String): PagingSource<Int, Cinema>
|
||||||
|
|
||||||
@Query(
|
@Query(
|
||||||
"SELECT c.*, s.uid as session_uid, s.date_time, s.price, s.max_count-IFNULL(SUM(os.count), 0) as available_count, c.uid as cinema_id " +
|
"SELECT c.*, s.uid as session_uid, s.date_time, s.price, s.max_count-IFNULL(SUM(os.count), 0) as available_count, c.uid as cinema_id " +
|
||||||
|
@ -6,7 +6,7 @@ import com.example.myapplication.database.entities.model.CinemaWithSessions
|
|||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface CinemaRepository {
|
interface CinemaRepository {
|
||||||
fun getAllCinemas(): Flow<PagingData<Cinema>>
|
fun getAllCinemas(name: String): Flow<PagingData<Cinema>>
|
||||||
suspend fun getCinema(uid: Int): CinemaWithSessions
|
suspend fun getCinema(uid: Int): CinemaWithSessions
|
||||||
suspend fun insertCinema(cinema: Cinema)
|
suspend fun insertCinema(cinema: Cinema)
|
||||||
suspend fun updateCinema(cinema: Cinema)
|
suspend fun updateCinema(cinema: Cinema)
|
||||||
|
@ -13,7 +13,7 @@ import kotlinx.coroutines.flow.first
|
|||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
class OfflineCinemaRepository(private val cinemaDao: CinemaDao) : CinemaRepository {
|
class OfflineCinemaRepository(private val cinemaDao: CinemaDao) : CinemaRepository {
|
||||||
override fun getAllCinemas(): Flow<PagingData<Cinema>> = Pager(
|
override fun getAllCinemas(name: String): Flow<PagingData<Cinema>> = Pager(
|
||||||
config = PagingConfig(
|
config = PagingConfig(
|
||||||
pageSize = AppContainer.LIMIT,
|
pageSize = AppContainer.LIMIT,
|
||||||
enablePlaceholders = false
|
enablePlaceholders = false
|
||||||
@ -21,6 +21,7 @@ class OfflineCinemaRepository(private val cinemaDao: CinemaDao) : CinemaReposito
|
|||||||
pagingSourceFactory = cinemaDao::getAll
|
pagingSourceFactory = cinemaDao::getAll
|
||||||
).flow
|
).flow
|
||||||
|
|
||||||
|
|
||||||
override suspend fun getCinema(uid: Int): CinemaWithSessions {
|
override suspend fun getCinema(uid: Int): CinemaWithSessions {
|
||||||
val item = cinemaDao.getByUid(uid)
|
val item = cinemaDao.getByUid(uid)
|
||||||
.map { map ->
|
.map { map ->
|
||||||
@ -43,6 +44,8 @@ class OfflineCinemaRepository(private val cinemaDao: CinemaDao) : CinemaReposito
|
|||||||
|
|
||||||
fun getAllCinemasPagingSource(): PagingSource<Int, Cinema> = cinemaDao.getAll()
|
fun getAllCinemasPagingSource(): PagingSource<Int, Cinema> = cinemaDao.getAll()
|
||||||
|
|
||||||
|
fun getAllCinemasPagingSource(name: String): PagingSource<Int, Cinema> = cinemaDao.getAll(name)
|
||||||
|
|
||||||
suspend fun insertCinemas(cinemas: List<Cinema>) =
|
suspend fun insertCinemas(cinemas: List<Cinema>) =
|
||||||
cinemaDao.insert(*cinemas.toTypedArray())
|
cinemaDao.insert(*cinemas.toTypedArray())
|
||||||
|
|
||||||
|
74803
server/data.json
74803
server/data.json
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user