This commit is contained in:
abazov73 2023-12-04 00:20:47 +04:00
parent 16257cf1b6
commit 7707836c12
38 changed files with 798 additions and 364 deletions

View File

@ -14,6 +14,7 @@
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.Mobile_Labs" android:theme="@style/Theme.Mobile_Labs"
android:name=".TheatreApplication"
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"

View File

@ -10,7 +10,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import com.example.mobile_labs.composeui.navigation.MainNavbar import com.example.mobile_labs.ui.navigation.MainNavbar
import com.example.mobile_labs.ui.theme.Mobile_LabsTheme import com.example.mobile_labs.ui.theme.Mobile_LabsTheme
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {

View File

@ -0,0 +1,14 @@
package com.example.mobile_labs
import android.app.Application
import com.example.mobile_labs.database.AppContainer
import com.example.mobile_labs.database.AppDataContainer
class TheatreApplication : Application() {
lateinit var container: AppContainer
override fun onCreate() {
super.onCreate()
container = AppDataContainer(this)
}
}

View File

@ -0,0 +1,33 @@
package com.example.mobile_labs.database
import android.content.Context
import com.example.mobile_labs.database.event.repository.EventRepository
import com.example.mobile_labs.database.event.repository.OfflineEventRepository
import com.example.mobile_labs.database.performance.repository.OfflinePerformanceRepository
import com.example.mobile_labs.database.performance.repository.PerformanceRepository
import com.example.mobile_labs.database.person.repository.OfflinePersonRepository
import com.example.mobile_labs.database.person.repository.PersonRepository
interface AppContainer {
val personRepository: PersonRepository
val eventRepository: EventRepository
val performanceRepository: PerformanceRepository
}
class AppDataContainer(private val context: Context) : AppContainer {
override val eventRepository: EventRepository by lazy {
OfflineEventRepository(AppDatabase.getInstance(context).eventDao())
}
override val performanceRepository: PerformanceRepository by lazy {
OfflinePerformanceRepository(AppDatabase.getInstance(context).performanceDao())
}
override val personRepository: PersonRepository by lazy {
OfflinePersonRepository(AppDatabase.getInstance(context).personDao())
}
companion object {
const val TIMEOUT = 5000L
}
}

View File

@ -5,14 +5,14 @@ import androidx.room.Database
import androidx.room.Room import androidx.room.Room
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import androidx.sqlite.db.SupportSQLiteDatabase import androidx.sqlite.db.SupportSQLiteDatabase
import com.example.mobile_labs.event.dao.EventDao import com.example.mobile_labs.database.event.dao.EventDao
import com.example.mobile_labs.event.model.Event import com.example.mobile_labs.database.event.model.Event
import com.example.mobile_labs.performance.dao.PerformanceDao import com.example.mobile_labs.database.performance.dao.PerformanceDao
import com.example.mobile_labs.performance.dao.PerformancePersonDao import com.example.mobile_labs.database.performance.dao.PerformancePersonDao
import com.example.mobile_labs.performance.model.Performance import com.example.mobile_labs.database.performance.model.Performance
import com.example.mobile_labs.performance.model.PerformancePersonCrossRef import com.example.mobile_labs.database.performance.model.PerformancePersonCrossRef
import com.example.mobile_labs.person.dao.PersonDao import com.example.mobile_labs.database.person.dao.PersonDao
import com.example.mobile_labs.person.model.Person import com.example.mobile_labs.database.person.model.Person
import com.example.mobile_labs.user.dao.UserDao import com.example.mobile_labs.user.dao.UserDao
import com.example.mobile_labs.user.model.User import com.example.mobile_labs.user.model.User
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope

View File

@ -1,13 +1,13 @@
package com.example.mobile_labs.event.dao package com.example.mobile_labs.database.event.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete import androidx.room.Delete
import androidx.room.Insert import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import androidx.room.Update import androidx.room.Update
import com.example.mobile_labs.event.model.Event import com.example.mobile_labs.database.event.model.Event
import com.example.mobile_labs.event.model.EventWithPerformance import com.example.mobile_labs.database.event.model.EventWithPerformance
import com.example.mobile_labs.performance.model.Performance import com.example.mobile_labs.database.performance.model.Performance
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao
@ -19,7 +19,7 @@ interface EventDao {
fun getAllWithPerformance(dateFrom: String): Flow<List<EventWithPerformance>> fun getAllWithPerformance(dateFrom: String): Flow<List<EventWithPerformance>>
@Query("select * from events where events.uid = :uid") @Query("select * from events where events.uid = :uid")
suspend fun getByUid(uid: Int): EventWithPerformance fun getByUid(uid: Int): Flow<EventWithPerformance>
@Insert @Insert
suspend fun insert(event: Event) suspend fun insert(event: Event)

View File

@ -1,4 +1,4 @@
package com.example.mobile_labs.event.model package com.example.mobile_labs.database.event.model
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
@ -7,8 +7,8 @@ import androidx.room.PrimaryKey
import androidx.room.TypeConverter import androidx.room.TypeConverter
import androidx.room.TypeConverters import androidx.room.TypeConverters
import com.example.mobile_labs.converters.LocalDateConverter import com.example.mobile_labs.converters.LocalDateConverter
import com.example.mobile_labs.performance.model.Performance import com.example.mobile_labs.database.performance.model.Performance
import com.example.mobile_labs.person.model.Person import com.example.mobile_labs.database.person.model.Person
import java.io.Serializable import java.io.Serializable
import java.time.LocalDate import java.time.LocalDate

View File

@ -1,8 +1,8 @@
package com.example.mobile_labs.event.model package com.example.mobile_labs.database.event.model
import androidx.room.Embedded import androidx.room.Embedded
import androidx.room.Relation import androidx.room.Relation
import com.example.mobile_labs.performance.model.Performance import com.example.mobile_labs.database.performance.model.Performance
data class EventWithPerformance ( data class EventWithPerformance (
@Embedded @Embedded

View File

@ -0,0 +1,14 @@
package com.example.mobile_labs.database.event.repository
import com.example.mobile_labs.database.event.model.Event
import com.example.mobile_labs.database.event.model.EventWithPerformance
import kotlinx.coroutines.flow.Flow
interface EventRepository {
fun getAll(): Flow<List<Event>>
fun getAllWithPerformance(): Flow<List<EventWithPerformance>>
fun getEvent(uid: Int): Flow<EventWithPerformance?>
suspend fun insertEvent(event: Event)
suspend fun updateEvent(event: Event)
suspend fun deleteEvent(event: Event)
}

View File

@ -0,0 +1,22 @@
package com.example.mobile_labs.database.event.repository
import com.example.mobile_labs.database.event.dao.EventDao
import com.example.mobile_labs.database.event.model.Event
import com.example.mobile_labs.database.event.model.EventWithPerformance
import kotlinx.coroutines.flow.Flow
import java.time.LocalDate
import java.time.format.DateTimeFormatter
class OfflineEventRepository(private val eventDao: EventDao) : EventRepository {
override fun getAll(): Flow<List<Event>> = eventDao.getAll();
override fun getAllWithPerformance(): Flow<List<EventWithPerformance>> = eventDao.getAllWithPerformance(LocalDate.now().format(
DateTimeFormatter.ofPattern("dd.MM")
))
override fun getEvent(uid: Int): Flow<EventWithPerformance?> = eventDao.getByUid(uid);
override suspend fun insertEvent(event: Event) = eventDao.insert(event);
override suspend fun updateEvent(event: Event) = eventDao.update(event);
override suspend fun deleteEvent(event: Event) = eventDao.delete(event);
}

View File

@ -1,13 +1,13 @@
package com.example.mobile_labs.performance.dao package com.example.mobile_labs.database.performance.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete import androidx.room.Delete
import androidx.room.Insert import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import androidx.room.Update import androidx.room.Update
import com.example.mobile_labs.performance.model.Performance import com.example.mobile_labs.database.performance.model.Performance
import com.example.mobile_labs.performance.model.PerformanceWithPeople import com.example.mobile_labs.database.performance.model.PerformanceWithPeople
import com.example.mobile_labs.person.model.Person import com.example.mobile_labs.database.person.model.Person
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao
@ -16,7 +16,7 @@ interface PerformanceDao {
fun getAll(): Flow<List<Performance>> fun getAll(): Flow<List<Performance>>
@Query("select * from performances where performances.performance_uid = :uid") @Query("select * from performances where performances.performance_uid = :uid")
suspend fun getByUid(uid: Int): PerformanceWithPeople fun getByUid(uid: Int): Flow<PerformanceWithPeople>
@Insert @Insert
suspend fun insert(performance: Performance) suspend fun insert(performance: Performance)

View File

@ -1,13 +1,13 @@
package com.example.mobile_labs.performance.dao package com.example.mobile_labs.database.performance.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete import androidx.room.Delete
import androidx.room.Insert import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import androidx.room.Update import androidx.room.Update
import com.example.mobile_labs.performance.model.Performance import com.example.mobile_labs.database.performance.model.Performance
import com.example.mobile_labs.performance.model.PerformancePersonCrossRef import com.example.mobile_labs.database.performance.model.PerformancePersonCrossRef
import com.example.mobile_labs.performance.model.PerformanceWithPeople import com.example.mobile_labs.database.performance.model.PerformanceWithPeople
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao

View File

@ -1,10 +1,10 @@
package com.example.mobile_labs.performance.model package com.example.mobile_labs.database.performance.model
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
import androidx.room.ForeignKey import androidx.room.ForeignKey
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import com.example.mobile_labs.person.model.Person import com.example.mobile_labs.database.person.model.Person
import java.io.Serializable import java.io.Serializable
@Entity(tableName = "performances", foreignKeys = [ @Entity(tableName = "performances", foreignKeys = [

View File

@ -1,4 +1,4 @@
package com.example.mobile_labs.performance.model package com.example.mobile_labs.database.performance.model
import androidx.room.Entity import androidx.room.Entity

View File

@ -1,10 +1,10 @@
package com.example.mobile_labs.performance.model package com.example.mobile_labs.database.performance.model
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Embedded import androidx.room.Embedded
import androidx.room.Junction import androidx.room.Junction
import androidx.room.Relation import androidx.room.Relation
import com.example.mobile_labs.person.model.Person import com.example.mobile_labs.database.person.model.Person
data class PerformanceWithPeople ( data class PerformanceWithPeople (
@Embedded @Embedded

View File

@ -0,0 +1,17 @@
package com.example.mobile_labs.database.performance.repository
import com.example.mobile_labs.database.performance.dao.PerformanceDao
import com.example.mobile_labs.database.performance.model.Performance
import com.example.mobile_labs.database.performance.model.PerformanceWithPeople
import kotlinx.coroutines.flow.Flow
class OfflinePerformanceRepository(private val performanceDao: PerformanceDao) : PerformanceRepository {
override fun getAllPerformances(): Flow<List<Performance>> = performanceDao.getAll();
override fun getPerformance(uid: Int): Flow<PerformanceWithPeople?> = performanceDao.getByUid(uid);
override suspend fun insertPerformance(performance: Performance) = performanceDao.insert(performance);
override suspend fun updatePerformance(performance: Performance) = performanceDao.update(performance);
override suspend fun deletePerformance(performance: Performance) = performanceDao.delete(performance);
}

View File

@ -0,0 +1,13 @@
package com.example.mobile_labs.database.performance.repository
import com.example.mobile_labs.database.performance.model.Performance
import com.example.mobile_labs.database.performance.model.PerformanceWithPeople
import kotlinx.coroutines.flow.Flow
interface PerformanceRepository {
fun getAllPerformances(): Flow<List<Performance>>
fun getPerformance(uid: Int): Flow<PerformanceWithPeople?>
suspend fun insertPerformance(performance: Performance)
suspend fun updatePerformance(performance: Performance)
suspend fun deletePerformance(performance: Performance)
}

View File

@ -1,11 +1,11 @@
package com.example.mobile_labs.person.dao package com.example.mobile_labs.database.person.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete import androidx.room.Delete
import androidx.room.Insert import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import androidx.room.Update import androidx.room.Update
import com.example.mobile_labs.person.model.Person import com.example.mobile_labs.database.person.model.Person
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@Dao @Dao
@ -14,7 +14,7 @@ interface PersonDao {
fun getAll(): Flow<List<Person>> fun getAll(): Flow<List<Person>>
@Query("select * from people where people.uid = :uid") @Query("select * from people where people.uid = :uid")
suspend fun getByUid(uid: Int): Person fun getByUid(uid: Int): Flow<Person>
@Insert @Insert
suspend fun insert(person: Person) suspend fun insert(person: Person)

View File

@ -1,4 +1,4 @@
package com.example.mobile_labs.person.model package com.example.mobile_labs.database.person.model
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity

View File

@ -0,0 +1,17 @@
package com.example.mobile_labs.database.person.repository
import com.example.mobile_labs.database.person.dao.PersonDao
import com.example.mobile_labs.database.person.model.Person
import kotlinx.coroutines.flow.Flow
class OfflinePersonRepository(private val personDao: PersonDao) : PersonRepository {
override fun getAllPeople(): Flow<List<Person>> = personDao.getAll();
override fun getPerson(uid: Int): Flow<Person?> = personDao.getByUid(uid);
override suspend fun insertPerson(person: Person) = personDao.insert(person);
override suspend fun updatePerson(person: Person) = personDao.update(person);
override suspend fun deletePerson(person: Person) = personDao.delete(person);
}

View File

@ -0,0 +1,12 @@
package com.example.mobile_labs.database.person.repository
import com.example.mobile_labs.database.person.model.Person
import kotlinx.coroutines.flow.Flow
interface PersonRepository {
fun getAllPeople(): Flow<List<Person>>
fun getPerson(uid: Int): Flow<Person?>
suspend fun insertPerson(person: Person)
suspend fun updatePerson(person: Person)
suspend fun deletePerson(person: Person)
}

View File

@ -1,92 +0,0 @@
package com.example.mobile_labs.event.composeui
import android.content.res.Configuration
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import coil.compose.AsyncImage
import com.example.mobile_labs.composeui.navigation.Screen
import com.example.mobile_labs.database.AppDatabase
import com.example.mobile_labs.event.model.EventWithPerformance
import com.example.mobile_labs.person.model.Person
import com.example.mobile_labs.ui.theme.Mobile_LabsTheme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.util.Calendar
@Composable
fun Schedule(navController: NavController?) {
val context = LocalContext.current
val events = remember { mutableStateListOf<EventWithPerformance>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
val dateNow = LocalDate.now().toString()
AppDatabase.getInstance(context).eventDao().getAllWithPerformance(dateNow).collect { data ->
events.clear()
events.addAll(data)
}
}
}
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.padding(all = 10.dp)
.verticalScroll(rememberScrollState())) {
events.forEachIndexed() { _, event ->
val performanceId = Screen.PerformanceView.route.replace("{id}", event.performance.performance_uid.toString())
Row(Modifier.padding(all = 10.dp)) {
Text(modifier = Modifier.padding(all = 5.dp), textAlign = TextAlign.Center, text = event.event.date.format(DateTimeFormatter.ofPattern("dd.MM")))
AsyncImage(model = event.performance.previewImageURL,
contentDescription = "performance preview image",
contentScale = ContentScale.Crop,
modifier = Modifier
.height(100.dp)
.width(100.dp))
Button(
modifier = Modifier
.fillMaxWidth()
.padding(all = 10.dp),
onClick = { navController?.navigate(performanceId) }) {
Text(event.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 SchedulePreview() {
Mobile_LabsTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
Schedule(navController = null)
}
}
}

View File

@ -1,108 +0,0 @@
package com.example.mobile_labs.performance.composeui
import android.content.res.Configuration
import android.util.Log
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import coil.compose.AsyncImage
import com.example.mobile_labs.composeui.navigation.Screen
import com.example.mobile_labs.database.AppDatabase
import com.example.mobile_labs.performance.model.Performance
import com.example.mobile_labs.person.model.Person
import com.example.mobile_labs.ui.theme.Mobile_LabsTheme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Repertoire(navController: NavController?) {
val context = LocalContext.current
val performances = remember { mutableStateListOf<Performance>() }
var performancesFiltered = remember { mutableStateListOf<Performance>() }
var title by remember { mutableStateOf("") }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).performanceDao().getAll().collect { data ->
performances.clear()
performances.addAll(data)
performancesFiltered.addAll(data)
}
}
}
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.padding(all = 10.dp)
.verticalScroll(rememberScrollState())) {
TextField(value = title, label = {Text(text = "Поиск...")}, onValueChange = { title = it;
if (title != "") {
val data = performances.filter { performance -> performance.title.contains(title) }
performancesFiltered.clear()
performancesFiltered.addAll(data)
} else {
performancesFiltered.clear()
performancesFiltered.addAll(performances)
} })
performancesFiltered.forEachIndexed() { index, performance ->
val performanceId = Screen.PerformanceView.route.replace("{id}", performance.performance_uid.toString())
Row(Modifier.padding(all = 10.dp)) {
AsyncImage(model = performance.previewImageURL,
contentDescription = "performance preview image",
contentScale = ContentScale.Crop,
modifier = Modifier
.height(100.dp)
.width(100.dp))
Button(
modifier = Modifier
.fillMaxWidth()
.padding(all = 10.dp),
onClick = { navController?.navigate(performanceId) }) {
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 RepertoirePreview() {
Mobile_LabsTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
Repertoire(navController = null)
}
}
}

View File

@ -1,76 +0,0 @@
package com.example.mobile_labs.person.composeui
import android.content.res.Configuration
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import coil.compose.AsyncImage
import com.example.mobile_labs.composeui.navigation.Screen
import com.example.mobile_labs.database.AppDatabase
import com.example.mobile_labs.performance.composeui.Repertoire
import com.example.mobile_labs.person.model.Person
import com.example.mobile_labs.ui.theme.Mobile_LabsTheme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Composable
fun PeopleList(navController: NavController?) {
val context = LocalContext.current
val people = remember { mutableStateListOf<Person>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).personDao().getAll().collect { data ->
people.clear()
people.addAll(data)
}
}
}
Column(Modifier.padding(all = 10.dp)) {
LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 100.dp))
{
items(people) {
Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier
.width(300.dp)
.height(200.dp)) {
AsyncImage(model = it.imageURL, contentDescription = "person image")
Text(text = "${it.last_name} ${it.first_name}", textAlign = TextAlign.Center)
}
}
}
}
}
@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 PeopleListPreview() {
Mobile_LabsTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
Repertoire(navController = null)
}
}
}

View File

@ -0,0 +1,32 @@
package com.example.mobile_labs.ui
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.createSavedStateHandle
import androidx.lifecycle.viewmodel.CreationExtras
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.example.mobile_labs.TheatreApplication
import com.example.mobile_labs.ui.event.list.EventListViewModel
import com.example.mobile_labs.ui.performance.list.PerformanceListViewModel
import com.example.mobile_labs.ui.performance.view.PerformanceViewModel
import com.example.mobile_labs.ui.person.list.PeopleListViewModel
object AppViewModelProvider {
val Factory = viewModelFactory {
initializer {
PeopleListViewModel(theatreApplication().container.personRepository)
}
initializer {
EventListViewModel(theatreApplication().container.eventRepository)
}
initializer {
PerformanceListViewModel(theatreApplication().container.performanceRepository)
}
initializer {
PerformanceViewModel(this.createSavedStateHandle(), theatreApplication().container.performanceRepository)
}
}
}
fun CreationExtras.theatreApplication(): TheatreApplication =
(this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as TheatreApplication)

View File

@ -1,12 +1,8 @@
package com.example.mobile_labs.composeui package com.example.mobile_labs.ui.about
import android.content.Intent
import android.content.res.Configuration import android.content.res.Configuration
import android.net.Uri
import android.widget.TextView import android.widget.TextView
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding

View File

@ -0,0 +1,139 @@
package com.example.mobile_labs.ui.event.list
import android.content.res.Configuration
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
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.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import coil.compose.AsyncImage
import com.example.mobile_labs.R
import com.example.mobile_labs.database.AppDatabase
import com.example.mobile_labs.database.event.model.Event
import com.example.mobile_labs.database.event.model.EventWithPerformance
import com.example.mobile_labs.database.person.model.Person
import com.example.mobile_labs.ui.AppViewModelProvider
import com.example.mobile_labs.ui.navigation.Screen
import com.example.mobile_labs.ui.person.list.PeopleListViewModel
import com.example.mobile_labs.ui.theme.Mobile_LabsTheme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.time.LocalDate
import java.time.format.DateTimeFormatter
@Composable
fun EventList(
navController: NavController,
viewModel: EventListViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
val eventListUiState by viewModel.eventListUiState.collectAsState()
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.padding(all = 10.dp)) {
EventList(
eventList = eventListUiState.eventList,
onClick = {uid : Int ->
val route = Screen.PerformanceView.route.replace("{id}", uid.toString())
navController.navigate(route)
}
)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun EventList(
modifier: Modifier = Modifier,
eventList: List<EventWithPerformance>,
onClick: (uid: Int) -> Unit
) {
Column(
modifier = modifier
) {
if (eventList.isEmpty()) {
Text(
text = stringResource(R.string.events_missing_description),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.titleLarge
)
} else {
LazyColumn(modifier = Modifier.padding(all = 10.dp)) {
items(items = eventList, key = { it.event.uid !! }) { event ->
EventListItem(event = event, modifier = Modifier
.padding(vertical = 7.dp), onClick = onClick)
}
}
}
}
}
@Composable
private fun EventListItem(
event: EventWithPerformance, modifier: Modifier = Modifier,
onClick: (uid: Int) -> Unit
) {
Card(
modifier = modifier.fillMaxWidth(),
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
) {
Column(
modifier = modifier.padding(all = 10.dp)
) {
Text(
text = event.event.date.format(DateTimeFormatter.ofPattern("dd.MM"))
)
AsyncImage(model = event.performance.imageURL, contentDescription = "")
Button(
modifier = Modifier
.fillMaxWidth()
.padding(all = 10.dp),
onClick = { onClick(event.event.performanceId !!) }) {
Text(event.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 SchedulePreview() {
Mobile_LabsTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
EventList(eventList = listOf(), onClick = {})
}
}
}

View File

@ -0,0 +1,26 @@
package com.example.mobile_labs.ui.event.list
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.mobile_labs.database.AppDataContainer
import com.example.mobile_labs.database.event.repository.EventRepository
import com.example.mobile_labs.database.event.model.Event
import com.example.mobile_labs.database.event.model.EventWithPerformance
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
class EventListViewModel(
private val eventRepository: EventRepository
) : ViewModel() {
val eventListUiState: StateFlow<EventListUiState> = eventRepository.getAllWithPerformance().map {
EventListUiState(it)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
initialValue = EventListUiState()
)
}
data class EventListUiState(val eventList: List<EventWithPerformance> = listOf())

View File

@ -1,4 +1,4 @@
package com.example.mobile_labs.composeui.navigation package com.example.mobile_labs.ui.navigation
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
@ -33,11 +33,11 @@ import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument import androidx.navigation.navArgument
import com.example.mobile_labs.ui.theme.Mobile_LabsTheme import com.example.mobile_labs.ui.theme.Mobile_LabsTheme
import com.example.mobile_labs.R import com.example.mobile_labs.R
import com.example.mobile_labs.composeui.About import com.example.mobile_labs.ui.about.About
import com.example.mobile_labs.event.composeui.Schedule import com.example.mobile_labs.ui.event.list.EventList
import com.example.mobile_labs.performance.composeui.PerformanceView import com.example.mobile_labs.ui.performance.list.PerformanceList
import com.example.mobile_labs.performance.composeui.Repertoire import com.example.mobile_labs.ui.performance.view.PerformanceView
import com.example.mobile_labs.person.composeui.PeopleList import com.example.mobile_labs.ui.person.list.PeopleList
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@ -107,15 +107,15 @@ fun Navhost(
startDestination = Screen.Schedule.route, startDestination = Screen.Schedule.route,
modifier.padding(innerPadding) modifier.padding(innerPadding)
) { ) {
composable(Screen.Schedule.route) { Schedule(navController) } composable(Screen.Schedule.route) { EventList(navController) }
composable(Screen.Repertoire.route) { Repertoire(navController) } composable(Screen.Repertoire.route) { PerformanceList(navController) }
composable(Screen.PeopleList.route) { PeopleList(navController) } composable(Screen.PeopleList.route) { PeopleList() }
composable(Screen.About.route) { About() } composable(Screen.About.route) { About() }
composable( composable(
Screen.PerformanceView.route, Screen.PerformanceView.route,
arguments = listOf(navArgument("id") { type = NavType.IntType }) arguments = listOf(navArgument("id") { type = NavType.IntType })
) { backStackEntry -> ) { backStackEntry ->
backStackEntry.arguments?.let { PerformanceView(it.getInt("id")) } backStackEntry.arguments?.let { PerformanceView() }
} }
} }
} }

View File

@ -1,4 +1,4 @@
package com.example.mobile_labs.composeui.navigation package com.example.mobile_labs.ui.navigation
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons

View File

@ -0,0 +1,138 @@
package com.example.mobile_labs.ui.performance.list
import com.example.mobile_labs.ui.event.list.EventListViewModel
import android.content.res.Configuration
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
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.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import coil.compose.AsyncImage
import com.example.mobile_labs.R
import com.example.mobile_labs.database.AppDatabase
import com.example.mobile_labs.database.event.model.Event
import com.example.mobile_labs.database.event.model.EventWithPerformance
import com.example.mobile_labs.database.performance.model.Performance
import com.example.mobile_labs.database.person.model.Person
import com.example.mobile_labs.ui.AppViewModelProvider
import com.example.mobile_labs.ui.navigation.Screen
import com.example.mobile_labs.ui.person.list.PeopleListViewModel
import com.example.mobile_labs.ui.theme.Mobile_LabsTheme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.time.LocalDate
import java.time.format.DateTimeFormatter
@Composable
fun PerformanceList(
navController: NavController,
viewModel: PerformanceListViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
val performanceListUiState by viewModel.performanceListUiState.collectAsState()
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.padding(all = 10.dp)) {
PerformanceList(
performanceList = performanceListUiState.performanceList,
onClick = {uid : Int ->
val route = Screen.PerformanceView.route.replace("{id}", uid.toString())
navController.navigate(route)
}
)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun PerformanceList(
modifier: Modifier = Modifier,
performanceList: List<Performance>,
onClick: (uid: Int) -> Unit
) {
Column(
modifier = modifier
) {
if (performanceList.isEmpty()) {
Text(
text = stringResource(R.string.performance_missing_description),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.titleLarge
)
} else {
LazyColumn(modifier = Modifier.padding(all = 10.dp)) {
items(items = performanceList, key = { it.performance_uid !! }) { performance ->
PerformanceListItem(performance = performance, modifier = Modifier
.padding(vertical = 7.dp), onClick = onClick)
}
}
}
}
}
@Composable
private fun PerformanceListItem(
performance: Performance, modifier: Modifier = Modifier,
onClick: (uid: Int) -> Unit
) {
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 = { onClick(performance.performance_uid !!) }) {
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 SchedulePreview() {
Mobile_LabsTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
PerformanceList(performanceList = listOf(), onClick = {})
}
}
}

View File

@ -0,0 +1,29 @@
package com.example.mobile_labs.ui.performance.list
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.mobile_labs.database.AppDataContainer
import com.example.mobile_labs.database.performance.model.Performance
import com.example.mobile_labs.database.performance.repository.PerformanceRepository
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
class PerformanceListViewModel(
private val performanceRepository: PerformanceRepository
) : ViewModel() {
val performanceListUiState: StateFlow<PerformanceListUiState> = performanceRepository.getAllPerformances().map {
PerformanceListUiState(it)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
initialValue = PerformanceListUiState()
)
// suspend fun deleteStudent(student: Student) {
// studentRepository.deleteStudent(student)
// }
}
data class PerformanceListUiState(val performanceList: List<Performance> = listOf())

View File

@ -1,75 +1,58 @@
package com.example.mobile_labs.performance.composeui package com.example.mobile_labs.ui.performance.view
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController import androidx.navigation.NavController
import coil.compose.AsyncImage import coil.compose.AsyncImage
import com.example.mobile_labs.composeui.navigation.Screen
import com.example.mobile_labs.ui.theme.Mobile_LabsTheme
import com.example.mobile_labs.R import com.example.mobile_labs.R
import com.example.mobile_labs.database.AppDatabase import com.example.mobile_labs.database.AppDatabase
import com.example.mobile_labs.performance.model.PerformanceWithPeople import com.example.mobile_labs.database.performance.model.PerformanceWithPeople
import com.example.mobile_labs.ui.AppViewModelProvider
import com.example.mobile_labs.ui.theme.Mobile_LabsTheme
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun PerformanceView(id: Int) { fun PerformanceView(
val context = LocalContext.current viewModel: PerformanceViewModel = viewModel(factory = AppViewModelProvider.Factory)
val (performaceWithPeople, setPerformanceWithPeople) = remember { mutableStateOf<PerformanceWithPeople?>(null) } ) {
LaunchedEffect(Unit) { val performanceWithPeople = viewModel.performanceUiState.performanceDetails;
withContext(Dispatchers.IO) {
setPerformanceWithPeople(AppDatabase.getInstance(context).performanceDao().getByUid(id))
}
}
var actorsText = ""
performaceWithPeople?.actors?.forEach {
if (actorsText != "") actorsText += "\n"
actorsText += "${it.last_name} ${it.first_name}"
}
Column( Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier modifier = Modifier
.padding(all = 10.dp) .padding(all = 10.dp)) {
.verticalScroll(rememberScrollState())) { Text(text = performanceWithPeople.authorName, textAlign = TextAlign.Center)
Text(text = "${performaceWithPeople?.author?.last_name} ${performaceWithPeople?.author?.first_name}", textAlign = TextAlign.Center) Text(text = performanceWithPeople.title, textAlign = TextAlign.Center, fontSize = 30.sp)
Text(text = performaceWithPeople?.performance?.title ?: "", textAlign = TextAlign.Center, fontSize = 30.sp) AsyncImage(model = performanceWithPeople.imageURL, contentDescription = "performance image")
AsyncImage(model = performaceWithPeople?.performance?.imageURL, contentDescription = "performance image") OutlinedTextField(modifier = Modifier.fillMaxWidth(), value = performanceWithPeople.description, onValueChange = {}, readOnly = true,
OutlinedTextField(modifier = Modifier.fillMaxWidth(), value = performaceWithPeople?.performance?.description ?: "", onValueChange = {}, readOnly = true,
label = { label = {
Text(stringResource(id = R.string.performance_description)) Text(stringResource(id = R.string.performance_description))
} }
) )
OutlinedTextField(modifier = Modifier.fillMaxWidth(), value = actorsText, onValueChange = {}, readOnly = true, OutlinedTextField(modifier = Modifier.fillMaxWidth(), value = performanceWithPeople.actorsList, onValueChange = {}, readOnly = true,
label = { label = {
Text(stringResource(id = R.string.performance_actors)) Text(stringResource(id = R.string.performance_actors))
} }
@ -85,7 +68,7 @@ fun PerformanceViewPreview() {
Surface( Surface(
color = MaterialTheme.colorScheme.background color = MaterialTheme.colorScheme.background
) { ) {
PerformanceView(id = 0) PerformanceView()
} }
} }
} }

View File

@ -0,0 +1,60 @@
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.Performance
import com.example.mobile_labs.database.performance.model.PerformanceWithPeople
import com.example.mobile_labs.database.performance.repository.PerformanceRepository
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
class PerformanceViewModel(
savedStateHandle: SavedStateHandle,
private val performanceRepository: PerformanceRepository
) : ViewModel() {
var performanceUiState by mutableStateOf(PerformanceUiState())
private set
private val studentUid: Int = checkNotNull(savedStateHandle["id"])
init {
viewModelScope.launch {
if (studentUid > 0) {
performanceUiState = performanceRepository.getPerformance(studentUid)
.filterNotNull()
.first()
.toUiState()
}
}
}
}
data class PerformanceUiState(
val performanceDetails: PerformanceDetails = PerformanceDetails(),
)
data class PerformanceDetails(
val title: String = "",
val authorName: String = "",
val actorsList: String = "",
val imageURL: String = "",
val description: String = ""
)
fun PerformanceWithPeople.toDetails(): PerformanceDetails = PerformanceDetails(
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,
)
fun PerformanceWithPeople.toUiState(): PerformanceUiState = PerformanceUiState(
performanceDetails = this.toDetails(),
)

View File

@ -0,0 +1,136 @@
package com.example.mobile_labs.ui.person.list
import android.content.res.Configuration
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.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
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.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import coil.compose.AsyncImage
import com.example.mobile_labs.R
import com.example.mobile_labs.ui.navigation.Screen
import com.example.mobile_labs.database.AppDatabase
import com.example.mobile_labs.database.event.model.EventWithPerformance
import com.example.mobile_labs.database.person.model.Person
import com.example.mobile_labs.ui.AppViewModelProvider
import com.example.mobile_labs.ui.theme.Mobile_LabsTheme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.time.LocalDate
import java.time.format.DateTimeFormatter
@Composable
fun PeopleList(
viewModel: PeopleListViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
val peopleListUiState by viewModel.personListUiState.collectAsState()
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.padding(all = 10.dp)) {
PeopleList(
modifier = Modifier
.fillMaxSize(),
peopleList = peopleListUiState.personList
)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun PeopleList(
modifier: Modifier = Modifier,
peopleList: List<Person>,
) {
Column(
modifier = modifier
) {
if (peopleList.isEmpty()) {
Text(
text = stringResource(R.string.people_missing_description),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.titleLarge
)
} else {
LazyColumn(modifier = Modifier.padding(all = 10.dp)) {
items(items = peopleList, key = { it.uid !! }) { person ->
PeopleListItem(person = person, modifier = Modifier
.padding(vertical = 7.dp))
}
}
}
}
}
@Composable
private fun PeopleListItem(
person: Person, modifier: Modifier = Modifier
) {
Card(
modifier = modifier.fillMaxWidth(),
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
) {
Column(
modifier = modifier.padding(all = 10.dp)
) {
Row {
AsyncImage(model = person.imageURL, contentDescription = "")
Text(
text = String.format("%s %s", person.first_name, person.last_name),
textAlign = TextAlign.Center,
modifier = Modifier.padding(10.dp),
style = MaterialTheme.typography.displaySmall
)
}
}
}
}
@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 PeopleListPreview() {
Mobile_LabsTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
PeopleList(peopleList = listOf())
}
}
}

View File

@ -0,0 +1,25 @@
package com.example.mobile_labs.ui.person.list
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.mobile_labs.database.AppDataContainer
import com.example.mobile_labs.database.person.model.Person
import com.example.mobile_labs.database.person.repository.PersonRepository
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
class PeopleListViewModel(
private val personRepository: PersonRepository
) : ViewModel() {
val personListUiState: StateFlow<PersonListUiState> = personRepository.getAllPeople().map {
PersonListUiState(it)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
initialValue = PersonListUiState()
)
}
data class PersonListUiState(val personList: List<Person> = listOf())

View File

@ -5,7 +5,7 @@ import androidx.room.Delete
import androidx.room.Insert import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import androidx.room.Update import androidx.room.Update
import com.example.mobile_labs.person.model.Person import com.example.mobile_labs.database.person.model.Person
import com.example.mobile_labs.user.model.User import com.example.mobile_labs.user.model.User
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow

View File

@ -9,6 +9,9 @@
<string name="people_main_title">Люди театра</string> <string name="people_main_title">Люди театра</string>
<string name="about_main_title">О нас</string> <string name="about_main_title">О нас</string>
<string name="performance_view_main_title">Представление</string> <string name="performance_view_main_title">Представление</string>
<string name="people_missing_description">Данные о людях отсутствуют</string>
<string name="events_missing_description">Данные о событиях отсутствуют</string>
<string name="performance_missing_description">Данные о представлениях отсутствуют</string>
<string name="about_text"> <string name="about_text">
<p> <p>
Netus quis congue nascetur ullamcorper nibh, nostra iaculis turpis! Facilisi pretium vehicula purus porttitor vitae aliquet dignissim. Donec diam molestie litora magnis dolor aptent scelerisque mus. Sit mi, venenatis interdum. Commodo vel malesuada tincidunt eget. Aenean laoreet lacinia platea sem? Libero urna odio diam? Nisl, sodales nisi gravida. Interdum elementum libero turpis dapibus tristique per sed maecenas ante integer massa? Tortor molestie sapien himenaeos condimentum. Facilisis accumsan ullamcorper semper fermentum elementum quisque. Curae;, vivamus ante hac elit fringilla odio ornare curabitur quisque magna commodo. Placerat proin! Netus quis congue nascetur ullamcorper nibh, nostra iaculis turpis! Facilisi pretium vehicula purus porttitor vitae aliquet dignissim. Donec diam molestie litora magnis dolor aptent scelerisque mus. Sit mi, venenatis interdum. Commodo vel malesuada tincidunt eget. Aenean laoreet lacinia platea sem? Libero urna odio diam? Nisl, sodales nisi gravida. Interdum elementum libero turpis dapibus tristique per sed maecenas ante integer massa? Tortor molestie sapien himenaeos condimentum. Facilisis accumsan ullamcorper semper fermentum elementum quisque. Curae;, vivamus ante hac elit fringilla odio ornare curabitur quisque magna commodo. Placerat proin!