From 7707836c1202224636b8a439fdb752825836802d Mon Sep 17 00:00:00 2001 From: abazov73 <92822431+abazov73@users.noreply.github.com> Date: Mon, 4 Dec 2023 00:20:47 +0400 Subject: [PATCH] Lab 04 --- app/src/main/AndroidManifest.xml | 1 + .../com/example/mobile_labs/MainActivity.kt | 2 +- .../example/mobile_labs/TheatreApplication.kt | 14 ++ .../mobile_labs/database/AppContainer.kt | 33 +++++ .../mobile_labs/database/AppDatabase.kt | 16 +- .../{ => database}/event/dao/EventDao.kt | 10 +- .../{ => database}/event/model/Event.kt | 6 +- .../event/model/EventWithPerformance.kt | 4 +- .../event/repository/EventRepository.kt | 14 ++ .../repository/OfflineEventRepository.kt | 22 +++ .../performance/dao/PerformanceDao.kt | 10 +- .../performance/dao/PerformancePersonDao.kt | 8 +- .../performance/model/Performance.kt | 4 +- .../model/PerformancePersonCrossRef.kt | 2 +- .../model/PerformanceWithPeople.kt | 4 +- .../OfflinePerformanceRepository.kt | 17 +++ .../repository/PerformanceRepository.kt | 13 ++ .../{ => database}/person/dao/PersonDao.kt | 6 +- .../{ => database}/person/model/Person.kt | 2 +- .../repository/OfflinePersonRepository.kt | 17 +++ .../person/repository/PersonRepository.kt | 12 ++ .../mobile_labs/event/composeui/Schedule.kt | 92 ------------ .../performance/composeui/Repertoire.kt | 108 -------------- .../person/composeui/PeopleList.kt | 76 ---------- .../mobile_labs/ui/AppViewModelProvider.kt | 32 ++++ .../{composeui => ui/about}/About.kt | 6 +- .../mobile_labs/ui/event/list/EventList.kt | 139 ++++++++++++++++++ .../ui/event/list/EventListViewModel.kt | 26 ++++ .../navigation/MainNavbar.kt | 20 +-- .../{composeui => ui}/navigation/Screen.kt | 2 +- .../ui/performance/list/PerformanceList.kt | 138 +++++++++++++++++ .../list/PerformanceListViewModel.kt | 29 ++++ .../performance/view}/PerformanceView.kt | 51 +++---- .../performance/view/PerformanceViewModel.kt | 60 ++++++++ .../mobile_labs/ui/person/list/PeopleList.kt | 136 +++++++++++++++++ .../ui/person/list/PeopleListViewModel.kt | 25 ++++ .../example/mobile_labs/user/dao/UserDao.kt | 2 +- app/src/main/res/values/strings.xml | 3 + 38 files changed, 798 insertions(+), 364 deletions(-) create mode 100644 app/src/main/java/com/example/mobile_labs/TheatreApplication.kt create mode 100644 app/src/main/java/com/example/mobile_labs/database/AppContainer.kt rename app/src/main/java/com/example/mobile_labs/{ => database}/event/dao/EventDao.kt (68%) rename app/src/main/java/com/example/mobile_labs/{ => database}/event/model/Event.kt (81%) rename app/src/main/java/com/example/mobile_labs/{ => database}/event/model/EventWithPerformance.kt (69%) create mode 100644 app/src/main/java/com/example/mobile_labs/database/event/repository/EventRepository.kt create mode 100644 app/src/main/java/com/example/mobile_labs/database/event/repository/OfflineEventRepository.kt rename app/src/main/java/com/example/mobile_labs/{ => database}/performance/dao/PerformanceDao.kt (64%) rename app/src/main/java/com/example/mobile_labs/{ => database}/performance/dao/PerformancePersonDao.kt (66%) rename app/src/main/java/com/example/mobile_labs/{ => database}/performance/model/Performance.kt (92%) rename app/src/main/java/com/example/mobile_labs/{ => database}/performance/model/PerformancePersonCrossRef.kt (76%) rename app/src/main/java/com/example/mobile_labs/{ => database}/performance/model/PerformanceWithPeople.kt (83%) create mode 100644 app/src/main/java/com/example/mobile_labs/database/performance/repository/OfflinePerformanceRepository.kt create mode 100644 app/src/main/java/com/example/mobile_labs/database/performance/repository/PerformanceRepository.kt rename app/src/main/java/com/example/mobile_labs/{ => database}/person/dao/PersonDao.kt (77%) rename app/src/main/java/com/example/mobile_labs/{ => database}/person/model/Person.kt (92%) create mode 100644 app/src/main/java/com/example/mobile_labs/database/person/repository/OfflinePersonRepository.kt create mode 100644 app/src/main/java/com/example/mobile_labs/database/person/repository/PersonRepository.kt delete mode 100644 app/src/main/java/com/example/mobile_labs/event/composeui/Schedule.kt delete mode 100644 app/src/main/java/com/example/mobile_labs/performance/composeui/Repertoire.kt delete mode 100644 app/src/main/java/com/example/mobile_labs/person/composeui/PeopleList.kt create mode 100644 app/src/main/java/com/example/mobile_labs/ui/AppViewModelProvider.kt rename app/src/main/java/com/example/mobile_labs/{composeui => ui/about}/About.kt (88%) create mode 100644 app/src/main/java/com/example/mobile_labs/ui/event/list/EventList.kt create mode 100644 app/src/main/java/com/example/mobile_labs/ui/event/list/EventListViewModel.kt rename app/src/main/java/com/example/mobile_labs/{composeui => ui}/navigation/MainNavbar.kt (88%) rename app/src/main/java/com/example/mobile_labs/{composeui => ui}/navigation/Screen.kt (96%) create mode 100644 app/src/main/java/com/example/mobile_labs/ui/performance/list/PerformanceList.kt create mode 100644 app/src/main/java/com/example/mobile_labs/ui/performance/list/PerformanceListViewModel.kt rename app/src/main/java/com/example/mobile_labs/{performance/composeui => ui/performance/view}/PerformanceView.kt (54%) create mode 100644 app/src/main/java/com/example/mobile_labs/ui/performance/view/PerformanceViewModel.kt create mode 100644 app/src/main/java/com/example/mobile_labs/ui/person/list/PeopleList.kt create mode 100644 app/src/main/java/com/example/mobile_labs/ui/person/list/PeopleListViewModel.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 60f7bd8..7f574bd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,6 +14,7 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Mobile_Labs" + android:name=".TheatreApplication" tools:targetApi="31"> > @Query("select * from events where events.uid = :uid") - suspend fun getByUid(uid: Int): EventWithPerformance + fun getByUid(uid: Int): Flow @Insert suspend fun insert(event: Event) diff --git a/app/src/main/java/com/example/mobile_labs/event/model/Event.kt b/app/src/main/java/com/example/mobile_labs/database/event/model/Event.kt similarity index 81% rename from app/src/main/java/com/example/mobile_labs/event/model/Event.kt rename to app/src/main/java/com/example/mobile_labs/database/event/model/Event.kt index ce3a46a..f89d212 100644 --- a/app/src/main/java/com/example/mobile_labs/event/model/Event.kt +++ b/app/src/main/java/com/example/mobile_labs/database/event/model/Event.kt @@ -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.Entity @@ -7,8 +7,8 @@ import androidx.room.PrimaryKey import androidx.room.TypeConverter import androidx.room.TypeConverters import com.example.mobile_labs.converters.LocalDateConverter -import com.example.mobile_labs.performance.model.Performance -import com.example.mobile_labs.person.model.Person +import com.example.mobile_labs.database.performance.model.Performance +import com.example.mobile_labs.database.person.model.Person import java.io.Serializable import java.time.LocalDate diff --git a/app/src/main/java/com/example/mobile_labs/event/model/EventWithPerformance.kt b/app/src/main/java/com/example/mobile_labs/database/event/model/EventWithPerformance.kt similarity index 69% rename from app/src/main/java/com/example/mobile_labs/event/model/EventWithPerformance.kt rename to app/src/main/java/com/example/mobile_labs/database/event/model/EventWithPerformance.kt index 715e743..b54973f 100644 --- a/app/src/main/java/com/example/mobile_labs/event/model/EventWithPerformance.kt +++ b/app/src/main/java/com/example/mobile_labs/database/event/model/EventWithPerformance.kt @@ -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.Relation -import com.example.mobile_labs.performance.model.Performance +import com.example.mobile_labs.database.performance.model.Performance data class EventWithPerformance ( @Embedded diff --git a/app/src/main/java/com/example/mobile_labs/database/event/repository/EventRepository.kt b/app/src/main/java/com/example/mobile_labs/database/event/repository/EventRepository.kt new file mode 100644 index 0000000..47eba28 --- /dev/null +++ b/app/src/main/java/com/example/mobile_labs/database/event/repository/EventRepository.kt @@ -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> + fun getAllWithPerformance(): Flow> + fun getEvent(uid: Int): Flow + suspend fun insertEvent(event: Event) + suspend fun updateEvent(event: Event) + suspend fun deleteEvent(event: Event) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/database/event/repository/OfflineEventRepository.kt b/app/src/main/java/com/example/mobile_labs/database/event/repository/OfflineEventRepository.kt new file mode 100644 index 0000000..7fc908f --- /dev/null +++ b/app/src/main/java/com/example/mobile_labs/database/event/repository/OfflineEventRepository.kt @@ -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> = eventDao.getAll(); + override fun getAllWithPerformance(): Flow> = eventDao.getAllWithPerformance(LocalDate.now().format( + DateTimeFormatter.ofPattern("dd.MM") + )) + override fun getEvent(uid: Int): Flow = 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); +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/performance/dao/PerformanceDao.kt b/app/src/main/java/com/example/mobile_labs/database/performance/dao/PerformanceDao.kt similarity index 64% rename from app/src/main/java/com/example/mobile_labs/performance/dao/PerformanceDao.kt rename to app/src/main/java/com/example/mobile_labs/database/performance/dao/PerformanceDao.kt index ff1d8b4..4903bd0 100644 --- a/app/src/main/java/com/example/mobile_labs/performance/dao/PerformanceDao.kt +++ b/app/src/main/java/com/example/mobile_labs/database/performance/dao/PerformanceDao.kt @@ -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.Delete import androidx.room.Insert import androidx.room.Query import androidx.room.Update -import com.example.mobile_labs.performance.model.Performance -import com.example.mobile_labs.performance.model.PerformanceWithPeople -import com.example.mobile_labs.person.model.Person +import com.example.mobile_labs.database.performance.model.Performance +import com.example.mobile_labs.database.performance.model.PerformanceWithPeople +import com.example.mobile_labs.database.person.model.Person import kotlinx.coroutines.flow.Flow @Dao @@ -16,7 +16,7 @@ interface PerformanceDao { fun getAll(): Flow> @Query("select * from performances where performances.performance_uid = :uid") - suspend fun getByUid(uid: Int): PerformanceWithPeople + fun getByUid(uid: Int): Flow @Insert suspend fun insert(performance: Performance) diff --git a/app/src/main/java/com/example/mobile_labs/performance/dao/PerformancePersonDao.kt b/app/src/main/java/com/example/mobile_labs/database/performance/dao/PerformancePersonDao.kt similarity index 66% rename from app/src/main/java/com/example/mobile_labs/performance/dao/PerformancePersonDao.kt rename to app/src/main/java/com/example/mobile_labs/database/performance/dao/PerformancePersonDao.kt index cf1ee34..5384177 100644 --- a/app/src/main/java/com/example/mobile_labs/performance/dao/PerformancePersonDao.kt +++ b/app/src/main/java/com/example/mobile_labs/database/performance/dao/PerformancePersonDao.kt @@ -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.Delete import androidx.room.Insert import androidx.room.Query import androidx.room.Update -import com.example.mobile_labs.performance.model.Performance -import com.example.mobile_labs.performance.model.PerformancePersonCrossRef -import com.example.mobile_labs.performance.model.PerformanceWithPeople +import com.example.mobile_labs.database.performance.model.Performance +import com.example.mobile_labs.database.performance.model.PerformancePersonCrossRef +import com.example.mobile_labs.database.performance.model.PerformanceWithPeople import kotlinx.coroutines.flow.Flow @Dao diff --git a/app/src/main/java/com/example/mobile_labs/performance/model/Performance.kt b/app/src/main/java/com/example/mobile_labs/database/performance/model/Performance.kt similarity index 92% rename from app/src/main/java/com/example/mobile_labs/performance/model/Performance.kt rename to app/src/main/java/com/example/mobile_labs/database/performance/model/Performance.kt index 4d89099..fa4fc2e 100644 --- a/app/src/main/java/com/example/mobile_labs/performance/model/Performance.kt +++ b/app/src/main/java/com/example/mobile_labs/database/performance/model/Performance.kt @@ -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.Entity import androidx.room.ForeignKey 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 @Entity(tableName = "performances", foreignKeys = [ diff --git a/app/src/main/java/com/example/mobile_labs/performance/model/PerformancePersonCrossRef.kt b/app/src/main/java/com/example/mobile_labs/database/performance/model/PerformancePersonCrossRef.kt similarity index 76% rename from app/src/main/java/com/example/mobile_labs/performance/model/PerformancePersonCrossRef.kt rename to app/src/main/java/com/example/mobile_labs/database/performance/model/PerformancePersonCrossRef.kt index 3dcdb40..612f808 100644 --- a/app/src/main/java/com/example/mobile_labs/performance/model/PerformancePersonCrossRef.kt +++ b/app/src/main/java/com/example/mobile_labs/database/performance/model/PerformancePersonCrossRef.kt @@ -1,4 +1,4 @@ -package com.example.mobile_labs.performance.model +package com.example.mobile_labs.database.performance.model import androidx.room.Entity diff --git a/app/src/main/java/com/example/mobile_labs/performance/model/PerformanceWithPeople.kt b/app/src/main/java/com/example/mobile_labs/database/performance/model/PerformanceWithPeople.kt similarity index 83% rename from app/src/main/java/com/example/mobile_labs/performance/model/PerformanceWithPeople.kt rename to app/src/main/java/com/example/mobile_labs/database/performance/model/PerformanceWithPeople.kt index 5ba6849..b415961 100644 --- a/app/src/main/java/com/example/mobile_labs/performance/model/PerformanceWithPeople.kt +++ b/app/src/main/java/com/example/mobile_labs/database/performance/model/PerformanceWithPeople.kt @@ -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.Embedded import androidx.room.Junction import androidx.room.Relation -import com.example.mobile_labs.person.model.Person +import com.example.mobile_labs.database.person.model.Person data class PerformanceWithPeople ( @Embedded diff --git a/app/src/main/java/com/example/mobile_labs/database/performance/repository/OfflinePerformanceRepository.kt b/app/src/main/java/com/example/mobile_labs/database/performance/repository/OfflinePerformanceRepository.kt new file mode 100644 index 0000000..ea6cdaf --- /dev/null +++ b/app/src/main/java/com/example/mobile_labs/database/performance/repository/OfflinePerformanceRepository.kt @@ -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> = performanceDao.getAll(); + override fun getPerformance(uid: Int): Flow = 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); +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/database/performance/repository/PerformanceRepository.kt b/app/src/main/java/com/example/mobile_labs/database/performance/repository/PerformanceRepository.kt new file mode 100644 index 0000000..bdea708 --- /dev/null +++ b/app/src/main/java/com/example/mobile_labs/database/performance/repository/PerformanceRepository.kt @@ -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> + fun getPerformance(uid: Int): Flow + suspend fun insertPerformance(performance: Performance) + suspend fun updatePerformance(performance: Performance) + suspend fun deletePerformance(performance: Performance) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/person/dao/PersonDao.kt b/app/src/main/java/com/example/mobile_labs/database/person/dao/PersonDao.kt similarity index 77% rename from app/src/main/java/com/example/mobile_labs/person/dao/PersonDao.kt rename to app/src/main/java/com/example/mobile_labs/database/person/dao/PersonDao.kt index e7d0962..98a0d9b 100644 --- a/app/src/main/java/com/example/mobile_labs/person/dao/PersonDao.kt +++ b/app/src/main/java/com/example/mobile_labs/database/person/dao/PersonDao.kt @@ -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.Delete import androidx.room.Insert import androidx.room.Query 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 @Dao @@ -14,7 +14,7 @@ interface PersonDao { fun getAll(): Flow> @Query("select * from people where people.uid = :uid") - suspend fun getByUid(uid: Int): Person + fun getByUid(uid: Int): Flow @Insert suspend fun insert(person: Person) diff --git a/app/src/main/java/com/example/mobile_labs/person/model/Person.kt b/app/src/main/java/com/example/mobile_labs/database/person/model/Person.kt similarity index 92% rename from app/src/main/java/com/example/mobile_labs/person/model/Person.kt rename to app/src/main/java/com/example/mobile_labs/database/person/model/Person.kt index 32934cf..cb1516c 100644 --- a/app/src/main/java/com/example/mobile_labs/person/model/Person.kt +++ b/app/src/main/java/com/example/mobile_labs/database/person/model/Person.kt @@ -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.Entity diff --git a/app/src/main/java/com/example/mobile_labs/database/person/repository/OfflinePersonRepository.kt b/app/src/main/java/com/example/mobile_labs/database/person/repository/OfflinePersonRepository.kt new file mode 100644 index 0000000..712823f --- /dev/null +++ b/app/src/main/java/com/example/mobile_labs/database/person/repository/OfflinePersonRepository.kt @@ -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> = personDao.getAll(); + override fun getPerson(uid: Int): Flow = 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); + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/database/person/repository/PersonRepository.kt b/app/src/main/java/com/example/mobile_labs/database/person/repository/PersonRepository.kt new file mode 100644 index 0000000..cfc29a3 --- /dev/null +++ b/app/src/main/java/com/example/mobile_labs/database/person/repository/PersonRepository.kt @@ -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> + fun getPerson(uid: Int): Flow + suspend fun insertPerson(person: Person) + suspend fun updatePerson(person: Person) + suspend fun deletePerson(person: Person) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/event/composeui/Schedule.kt b/app/src/main/java/com/example/mobile_labs/event/composeui/Schedule.kt deleted file mode 100644 index c243017..0000000 --- a/app/src/main/java/com/example/mobile_labs/event/composeui/Schedule.kt +++ /dev/null @@ -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() } - 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) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/performance/composeui/Repertoire.kt b/app/src/main/java/com/example/mobile_labs/performance/composeui/Repertoire.kt deleted file mode 100644 index 453bfb2..0000000 --- a/app/src/main/java/com/example/mobile_labs/performance/composeui/Repertoire.kt +++ /dev/null @@ -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() } - var performancesFiltered = remember { mutableStateListOf() } - 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) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/person/composeui/PeopleList.kt b/app/src/main/java/com/example/mobile_labs/person/composeui/PeopleList.kt deleted file mode 100644 index 343545e..0000000 --- a/app/src/main/java/com/example/mobile_labs/person/composeui/PeopleList.kt +++ /dev/null @@ -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() } - 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) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/ui/AppViewModelProvider.kt b/app/src/main/java/com/example/mobile_labs/ui/AppViewModelProvider.kt new file mode 100644 index 0000000..e45783d --- /dev/null +++ b/app/src/main/java/com/example/mobile_labs/ui/AppViewModelProvider.kt @@ -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) \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/composeui/About.kt b/app/src/main/java/com/example/mobile_labs/ui/about/About.kt similarity index 88% rename from app/src/main/java/com/example/mobile_labs/composeui/About.kt rename to app/src/main/java/com/example/mobile_labs/ui/about/About.kt index 942e6dc..fa1f390 100644 --- a/app/src/main/java/com/example/mobile_labs/composeui/About.kt +++ b/app/src/main/java/com/example/mobile_labs/ui/about/About.kt @@ -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.net.Uri import android.widget.TextView -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding diff --git a/app/src/main/java/com/example/mobile_labs/ui/event/list/EventList.kt b/app/src/main/java/com/example/mobile_labs/ui/event/list/EventList.kt new file mode 100644 index 0000000..1423443 --- /dev/null +++ b/app/src/main/java/com/example/mobile_labs/ui/event/list/EventList.kt @@ -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, + 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 = {}) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/ui/event/list/EventListViewModel.kt b/app/src/main/java/com/example/mobile_labs/ui/event/list/EventListViewModel.kt new file mode 100644 index 0000000..e4d6663 --- /dev/null +++ b/app/src/main/java/com/example/mobile_labs/ui/event/list/EventListViewModel.kt @@ -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 = eventRepository.getAllWithPerformance().map { + EventListUiState(it) + }.stateIn( + scope = viewModelScope, + started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT), + initialValue = EventListUiState() + ) +} + +data class EventListUiState(val eventList: List = listOf()) \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/composeui/navigation/MainNavbar.kt b/app/src/main/java/com/example/mobile_labs/ui/navigation/MainNavbar.kt similarity index 88% rename from app/src/main/java/com/example/mobile_labs/composeui/navigation/MainNavbar.kt rename to app/src/main/java/com/example/mobile_labs/ui/navigation/MainNavbar.kt index acfbcba..5ce5fb1 100644 --- a/app/src/main/java/com/example/mobile_labs/composeui/navigation/MainNavbar.kt +++ b/app/src/main/java/com/example/mobile_labs/ui/navigation/MainNavbar.kt @@ -1,4 +1,4 @@ -package com.example.mobile_labs.composeui.navigation +package com.example.mobile_labs.ui.navigation import android.content.res.Configuration import androidx.compose.foundation.layout.PaddingValues @@ -33,11 +33,11 @@ import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import com.example.mobile_labs.ui.theme.Mobile_LabsTheme import com.example.mobile_labs.R -import com.example.mobile_labs.composeui.About -import com.example.mobile_labs.event.composeui.Schedule -import com.example.mobile_labs.performance.composeui.PerformanceView -import com.example.mobile_labs.performance.composeui.Repertoire -import com.example.mobile_labs.person.composeui.PeopleList +import com.example.mobile_labs.ui.about.About +import com.example.mobile_labs.ui.event.list.EventList +import com.example.mobile_labs.ui.performance.list.PerformanceList +import com.example.mobile_labs.ui.performance.view.PerformanceView +import com.example.mobile_labs.ui.person.list.PeopleList @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -107,15 +107,15 @@ fun Navhost( startDestination = Screen.Schedule.route, modifier.padding(innerPadding) ) { - composable(Screen.Schedule.route) { Schedule(navController) } - composable(Screen.Repertoire.route) { Repertoire(navController) } - composable(Screen.PeopleList.route) { PeopleList(navController) } + composable(Screen.Schedule.route) { EventList(navController) } + composable(Screen.Repertoire.route) { PerformanceList(navController) } + composable(Screen.PeopleList.route) { PeopleList() } composable(Screen.About.route) { About() } composable( Screen.PerformanceView.route, arguments = listOf(navArgument("id") { type = NavType.IntType }) ) { backStackEntry -> - backStackEntry.arguments?.let { PerformanceView(it.getInt("id")) } + backStackEntry.arguments?.let { PerformanceView() } } } } diff --git a/app/src/main/java/com/example/mobile_labs/composeui/navigation/Screen.kt b/app/src/main/java/com/example/mobile_labs/ui/navigation/Screen.kt similarity index 96% rename from app/src/main/java/com/example/mobile_labs/composeui/navigation/Screen.kt rename to app/src/main/java/com/example/mobile_labs/ui/navigation/Screen.kt index 6520232..ac02e5a 100644 --- a/app/src/main/java/com/example/mobile_labs/composeui/navigation/Screen.kt +++ b/app/src/main/java/com/example/mobile_labs/ui/navigation/Screen.kt @@ -1,4 +1,4 @@ -package com.example.mobile_labs.composeui.navigation +package com.example.mobile_labs.ui.navigation import androidx.annotation.StringRes import androidx.compose.material.icons.Icons diff --git a/app/src/main/java/com/example/mobile_labs/ui/performance/list/PerformanceList.kt b/app/src/main/java/com/example/mobile_labs/ui/performance/list/PerformanceList.kt new file mode 100644 index 0000000..be607da --- /dev/null +++ b/app/src/main/java/com/example/mobile_labs/ui/performance/list/PerformanceList.kt @@ -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, + 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 = {}) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/ui/performance/list/PerformanceListViewModel.kt b/app/src/main/java/com/example/mobile_labs/ui/performance/list/PerformanceListViewModel.kt new file mode 100644 index 0000000..0c714d7 --- /dev/null +++ b/app/src/main/java/com/example/mobile_labs/ui/performance/list/PerformanceListViewModel.kt @@ -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 = 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 = listOf()) \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/performance/composeui/PerformanceView.kt b/app/src/main/java/com/example/mobile_labs/ui/performance/view/PerformanceView.kt similarity index 54% rename from app/src/main/java/com/example/mobile_labs/performance/composeui/PerformanceView.kt rename to app/src/main/java/com/example/mobile_labs/ui/performance/view/PerformanceView.kt index be1f0b9..f7d9fcd 100644 --- a/app/src/main/java/com/example/mobile_labs/performance/composeui/PerformanceView.kt +++ b/app/src/main/java/com/example/mobile_labs/ui/performance/view/PerformanceView.kt @@ -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 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.OutlinedTextField 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.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue +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.compose.ui.unit.sp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController 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.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.withContext @OptIn(ExperimentalMaterial3Api::class) @Composable -fun PerformanceView(id: Int) { - val context = LocalContext.current - val (performaceWithPeople, setPerformanceWithPeople) = remember { mutableStateOf(null) } - LaunchedEffect(Unit) { - 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}" - } +fun PerformanceView( + viewModel: PerformanceViewModel = viewModel(factory = AppViewModelProvider.Factory) +) { + val performanceWithPeople = viewModel.performanceUiState.performanceDetails; Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier - .padding(all = 10.dp) - .verticalScroll(rememberScrollState())) { - Text(text = "${performaceWithPeople?.author?.last_name} ${performaceWithPeople?.author?.first_name}", textAlign = TextAlign.Center) - Text(text = performaceWithPeople?.performance?.title ?: "", textAlign = TextAlign.Center, fontSize = 30.sp) - AsyncImage(model = performaceWithPeople?.performance?.imageURL, contentDescription = "performance image") - OutlinedTextField(modifier = Modifier.fillMaxWidth(), value = performaceWithPeople?.performance?.description ?: "", onValueChange = {}, readOnly = true, + .padding(all = 10.dp)) { + Text(text = performanceWithPeople.authorName, textAlign = TextAlign.Center) + Text(text = performanceWithPeople.title, textAlign = TextAlign.Center, fontSize = 30.sp) + AsyncImage(model = performanceWithPeople.imageURL, contentDescription = "performance image") + OutlinedTextField(modifier = Modifier.fillMaxWidth(), value = performanceWithPeople.description, onValueChange = {}, readOnly = true, label = { 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 = { Text(stringResource(id = R.string.performance_actors)) } @@ -85,7 +68,7 @@ fun PerformanceViewPreview() { Surface( color = MaterialTheme.colorScheme.background ) { - PerformanceView(id = 0) + PerformanceView() } } } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/ui/performance/view/PerformanceViewModel.kt b/app/src/main/java/com/example/mobile_labs/ui/performance/view/PerformanceViewModel.kt new file mode 100644 index 0000000..b48bb9f --- /dev/null +++ b/app/src/main/java/com/example/mobile_labs/ui/performance/view/PerformanceViewModel.kt @@ -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(), +) \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/ui/person/list/PeopleList.kt b/app/src/main/java/com/example/mobile_labs/ui/person/list/PeopleList.kt new file mode 100644 index 0000000..f87b361 --- /dev/null +++ b/app/src/main/java/com/example/mobile_labs/ui/person/list/PeopleList.kt @@ -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, +) { + 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()) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/ui/person/list/PeopleListViewModel.kt b/app/src/main/java/com/example/mobile_labs/ui/person/list/PeopleListViewModel.kt new file mode 100644 index 0000000..9d5422d --- /dev/null +++ b/app/src/main/java/com/example/mobile_labs/ui/person/list/PeopleListViewModel.kt @@ -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 = personRepository.getAllPeople().map { + PersonListUiState(it) + }.stateIn( + scope = viewModelScope, + started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT), + initialValue = PersonListUiState() + ) +} + +data class PersonListUiState(val personList: List = listOf()) \ No newline at end of file diff --git a/app/src/main/java/com/example/mobile_labs/user/dao/UserDao.kt b/app/src/main/java/com/example/mobile_labs/user/dao/UserDao.kt index 9529bc9..596762b 100644 --- a/app/src/main/java/com/example/mobile_labs/user/dao/UserDao.kt +++ b/app/src/main/java/com/example/mobile_labs/user/dao/UserDao.kt @@ -5,7 +5,7 @@ import androidx.room.Delete import androidx.room.Insert import androidx.room.Query 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 kotlinx.coroutines.flow.Flow diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9f87ca6..3530317 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -9,6 +9,9 @@ Люди театра О нас Представление + Данные о людях отсутствуют + Данные о событиях отсутствуют + Данные о представлениях отсутствуют

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!