6 Commits
Lab1 ... Lab2

46 changed files with 1588 additions and 29 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
.gradle/file-system.probe Normal file

Binary file not shown.

8
.idea/gradle.xml generated
View File

@@ -7,7 +7,13 @@
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" />
<option name="gradleJvm" value="jbr-17" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>

View File

@@ -0,0 +1,41 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
</profile>
</component>

2
.idea/misc.xml generated
View File

@@ -1,6 +1,6 @@
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

221
.idea/workspace.xml generated
View File

@@ -1,31 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidLayouts">
<shared>
<config />
</shared>
</component>
<component name="AutoImportSettings">
<option name="autoReloadType" value="NONE" />
</component>
<component name="ChangeListManager">
<list default="true" id="dc3793c7-c725-42e8-8eda-044c95f334c1" name="Changes" comment="коммит1" />
<list default="true" id="dc3793c7-c725-42e8-8eda-044c95f334c1" name="Changes" comment="Лаб 2 выглядит как предварительный конец 2 лабы">
<change beforePath="$PROJECT_DIR$/.gradle/8.0/executionHistory/executionHistory.bin" beforeDir="false" afterPath="$PROJECT_DIR$/.gradle/8.0/executionHistory/executionHistory.bin" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.gradle/8.0/executionHistory/executionHistory.lock" beforeDir="false" afterPath="$PROJECT_DIR$/.gradle/8.0/executionHistory/executionHistory.lock" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.gradle/8.0/fileHashes/fileHashes.bin" beforeDir="false" afterPath="$PROJECT_DIR$/.gradle/8.0/fileHashes/fileHashes.bin" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.gradle/8.0/fileHashes/fileHashes.lock" beforeDir="false" afterPath="$PROJECT_DIR$/.gradle/8.0/fileHashes/fileHashes.lock" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.gradle/8.0/fileHashes/resourceHashesCache.bin" beforeDir="false" afterPath="$PROJECT_DIR$/.gradle/8.0/fileHashes/resourceHashesCache.bin" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.gradle/buildOutputCleanup/buildOutputCleanup.lock" beforeDir="false" afterPath="$PROJECT_DIR$/.gradle/buildOutputCleanup/buildOutputCleanup.lock" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.gradle/buildOutputCleanup/outputFiles.bin" beforeDir="false" afterPath="$PROJECT_DIR$/.gradle/buildOutputCleanup/outputFiles.bin" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.gradle/file-system.probe" beforeDir="false" afterPath="$PROJECT_DIR$/.gradle/file-system.probe" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/build.gradle.kts" beforeDir="false" afterPath="$PROJECT_DIR$/app/build.gradle.kts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/composeui/CreatePet.kt" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/composeui/CreatePet.kt" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/composeui/EditPet.kt" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/composeui/EditPet.kt" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/composeui/Home.kt" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/composeui/Home.kt" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/composeui/Login.kt" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/composeui/Login.kt" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/composeui/PlayPet.kt" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/composeui/PlayPet.kt" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/composeui/Profile.kt" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/composeui/Profile.kt" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/composeui/navigation/MyPage.kt" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/composeui/navigation/MyPage.kt" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/models/user/composeui/PetList.kt" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/models/user/composeui/PetList.kt" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/models/user/composeui/StudentView.kt" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/models/user/composeui/StudentView.kt" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/models/user/composeui/UserList.kt" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/models/user/composeui/UserList.kt" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ExecutionTargetManager" SELECTED_TARGET="device_and_snapshot_combo_box_target[RF8N601QWVE]" />
<component name="ExternalProjectsData">
<projectState path="$PROJECT_DIR$">
<ProjectState />
</projectState>
</component>
<component name="ExternalProjectsManager">
<system id="GRADLE">
<state>
<task path="$PROJECT_DIR$/app">
<activation />
</task>
<projects_view>
<tree_state>
<expand />
<expand>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="PMUapp" type="f1a62948:ProjectNode" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="PMUapp" type="f1a62948:ProjectNode" />
<item name="app" type="2d1252cf:ModuleNode" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="PMUapp" type="f1a62948:ProjectNode" />
<item name="app" type="2d1252cf:ModuleNode" />
<item name="Tasks" type="e4a08cd1:TasksNode" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="PMUapp" type="f1a62948:ProjectNode" />
<item name="app" type="2d1252cf:ModuleNode" />
<item name="Tasks" type="e4a08cd1:TasksNode" />
<item name="other" type="c8890929:TasksNode$1" />
</path>
</expand>
<select />
</tree_state>
</projects_view>
</state>
</system>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Kotlin File" />
<option value="Kotlin Class" />
</list>
</option>
</component>
<component name="Git.Settings">
<option name="RECENT_BRANCH_BY_REPOSITORY">
<map>
<entry key="$PROJECT_DIR$" value="main" />
<entry key="$PROJECT_DIR$" value="Lab1" />
</map>
</option>
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
@@ -33,6 +99,9 @@
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProblemsViewState">
<option name="selectedTabId" value="ProjectErrors" />
</component>
<component name="ProjectId" id="2WToW0mvjPzND9QiCAmC6MXKLwF" />
<component name="ProjectLevelVcsManager">
<ConfirmationsSetting value="2" id="Add" />
@@ -47,9 +116,102 @@
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.cidr.known.project.marker": "true",
"cidr.known.project.marker": "true"
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
"cidr.known.project.marker": "true",
"com.android.tools.idea.devicemanager.tab": "Physical",
"last_opened_file_path": "C:/Users/Kate/AndroidStudioProjects/Ihonkina_PIbd-31_PMU/app/src/main/java/com/example/pmuapp/composeui/navigation",
"settings.editor.selected.configurable": "experimental"
}
}]]></component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\Users\Kate\AndroidStudioProjects\Ihonkina_PIbd-31_PMU\app\src\main\java\com\example\pmuapp\composeui\navigation" />
<recent name="C:\Users\Kate\AndroidStudioProjects\Ihonkina_PIbd-31_PMU\app\src\main\java\com\example\pmuapp\models\user\composeui" />
<recent name="C:\Users\Kate\AndroidStudioProjects\Ihonkina_PIbd-31_PMU\app\src\main\java\com\example\pmuapp\composeui" />
<recent name="C:\Users\Kate\AndroidStudioProjects\Ihonkina_PIbd-31_PMU\app\src\main\res\drawable" />
<recent name="C:\Users\Kate\AndroidStudioProjects\Ihonkina_PIbd-31_PMU\app\src\main\java\com\example\pmuapp" />
</key>
<key name="MoveFile.RECENT_KEYS">
<recent name="C:\Users\Kate\AndroidStudioProjects\Ihonkina_PIbd-31_PMU\app\src\main\java\com\example\pmuapp\composeui" />
</key>
<key name="CreateKotlinClassDialog.RecentsKey">
<recent name="com.example.pmuapp.composeui" />
</key>
<key name="MoveKotlinTopLevelDeclarationsDialog.RECENTS_KEY">
<recent name="com.example.pmuapp.composeui" />
</key>
<key name="CopyKotlinDeclarationDialog.RECENTS_KEY">
<recent name="com.example.pmuapp.composeui.navigation" />
</key>
</component>
<component name="RunManager">
<configuration name="app" type="AndroidRunConfigurationType" factoryName="Android App">
<module name="PMUapp.app.main" />
<option name="DEPLOY" value="true" />
<option name="DEPLOY_APK_FROM_BUNDLE" value="false" />
<option name="DEPLOY_AS_INSTANT" value="false" />
<option name="ARTIFACT_NAME" value="" />
<option name="PM_INSTALL_OPTIONS" value="" />
<option name="ALL_USERS" value="false" />
<option name="ALWAYS_INSTALL_WITH_PM" value="false" />
<option name="CLEAR_APP_STORAGE" value="false" />
<option name="ACTIVITY_EXTRA_FLAGS" value="" />
<option name="MODE" value="default_activity" />
<option name="CLEAR_LOGCAT" value="false" />
<option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
<option name="INSPECTION_WITHOUT_ACTIVITY_RESTART" value="false" />
<option name="TARGET_SELECTION_MODE" value="DEVICE_AND_SNAPSHOT_COMBO_BOX" />
<option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
<option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
<option name="DEBUGGER_TYPE" value="Auto" />
<Auto>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
<option name="DEBUG_SANDBOX_SDK" value="false" />
</Auto>
<Hybrid>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
<option name="DEBUG_SANDBOX_SDK" value="false" />
</Hybrid>
<Java>
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
<option name="DEBUG_SANDBOX_SDK" value="false" />
</Java>
<Native>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
<option name="DEBUG_SANDBOX_SDK" value="false" />
</Native>
<Profilers>
<option name="ADVANCED_PROFILING_ENABLED" value="false" />
<option name="STARTUP_PROFILING_ENABLED" value="false" />
<option name="STARTUP_CPU_PROFILING_ENABLED" value="false" />
<option name="STARTUP_CPU_PROFILING_CONFIGURATION_NAME" value="Java/Kotlin Method Sample (legacy)" />
<option name="STARTUP_NATIVE_MEMORY_PROFILING_ENABLED" value="false" />
<option name="NATIVE_MEMORY_SAMPLE_RATE_BYTES" value="2048" />
</Profilers>
<option name="DEEP_LINK" value="" />
<option name="ACTIVITY_CLASS" value="" />
<option name="SEARCH_ACTIVITY_IN_GLOBAL_SCOPE" value="false" />
<option name="SKIP_ACTIVITY_VALIDATION" value="false" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
@@ -66,7 +228,49 @@
<option name="project" value="LOCAL" />
<updated>1696766359976</updated>
</task>
<option name="localTasksCounter" value="2" />
<task id="LOCAL-00002" summary="добавление отчета лаб 1">
<created>1696766847352</created>
<option name="number" value="00002" />
<option name="presentableId" value="LOCAL-00002" />
<option name="project" value="LOCAL" />
<updated>1696766847352</updated>
</task>
<task id="LOCAL-00003" summary="Лаб 2 начало">
<created>1697038354150</created>
<option name="number" value="00003" />
<option name="presentableId" value="LOCAL-00003" />
<option name="project" value="LOCAL" />
<updated>1697038354150</updated>
</task>
<task id="LOCAL-00004" summary="Лаб 2 нало работы с пользователем">
<created>1697041852651</created>
<option name="number" value="00004" />
<option name="presentableId" value="LOCAL-00004" />
<option name="project" value="LOCAL" />
<updated>1697041852651</updated>
</task>
<task id="LOCAL-00005" summary="Лаб 2 питомцы просто добавлены">
<created>1697054812374</created>
<option name="number" value="00005" />
<option name="presentableId" value="LOCAL-00005" />
<option name="project" value="LOCAL" />
<updated>1697054812374</updated>
</task>
<task id="LOCAL-00006" summary="Лаб 2 выглядит как предварительный конец 2 лабы">
<created>1697086817058</created>
<option name="number" value="00006" />
<option name="presentableId" value="LOCAL-00006" />
<option name="project" value="LOCAL" />
<updated>1697086817058</updated>
</task>
<task id="LOCAL-00007" summary="Лаб 2 выглядит как предварительный конец 2 лабы">
<created>1697086828529</created>
<option name="number" value="00007" />
<option name="presentableId" value="LOCAL-00007" />
<option name="project" value="LOCAL" />
<updated>1697086828529</updated>
</task>
<option name="localTasksCounter" value="8" />
<servers />
</component>
<component name="Vcs.Log.Tabs.Properties">
@@ -95,6 +299,11 @@
<component name="VcsManagerConfiguration">
<option name="ADD_EXTERNAL_FILES_SILENTLY" value="true" />
<MESSAGE value=оммит1" />
<option name="LAST_COMMIT_MESSAGE" value="коммит1" />
<MESSAGE value="добавление отчета лаб 1" />
<MESSAGE value="Лаб 2 начало" />
<MESSAGE value="Лаб 2 нало работы с пользователем" />
<MESSAGE value="Лаб 2 питомцы просто добавлены" />
<MESSAGE value="Лаб 2 выглядит как предварительный конец 2 лабы" />
<option name="LAST_COMMIT_MESSAGE" value="Лаб 2 выглядит как предварительный конец 2 лабы" />
</component>
</project>

View File

@@ -5,12 +5,13 @@ plugins {
android {
namespace = "com.example.pmuapp"
compileSdk = 33
compileSdk = 34
defaultConfig {
applicationId = "com.example.pmuapp"
minSdk = 24
targetSdk = 33
targetSdk = 34
versionCode = 1
versionName = "1.0"
@@ -50,15 +51,19 @@ android {
}
dependencies {
implementation ("io.coil-kt:coil-compose:1.4.0")
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
implementation("androidx.activity:activity-compose:1.7.2")
implementation(platform("androidx.compose:compose-bom:2023.03.00"))
implementation("androidx.navigation:navigation-compose:2.6.0")
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")
implementation("com.google.android.engage:engage-core:1.3.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.compose.ui:ui-graphics-android:1.5.3")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")

View File

@@ -13,7 +13,7 @@
android:theme="@style/Theme.PMUapp"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:name=".MainComposeActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.PMUapp">

View File

@@ -1,46 +1,43 @@
package com.example.pmuapp
import android.content.res.Configuration
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.pmuapp.composeui.navigation.MainNavbar
import com.example.pmuapp.ui.theme.PMUappTheme
class MainActivity : ComponentActivity() {
class MainComposeActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
PMUappTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Greeting("Android")
MainNavbar()
}
}
}
}
}
@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 Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
fun MainNavbarPreview() {
PMUappTheme {
Greeting("Android")
Surface(
color = MaterialTheme.colorScheme.background
) {
MainNavbar()
}
}
}

View File

@@ -0,0 +1,86 @@
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.example.pmuapp.R
import com.example.pmuapp.models.user.model.Pet
import com.example.pmuapp.models.user.model.User
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CreatePet(navController: NavController, onSaveClick: (Pet) -> Unit) {
var selectedImage by remember { mutableStateOf(R.drawable.pet1) }
var petName by remember { mutableStateOf("") }
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
val imageIds = intArrayOf(
R.drawable.pet1,
R.drawable.pet2,
R.drawable.pet3,
R.drawable.pet4,
R.drawable.pet5,
R.drawable.pet6,
R.drawable.pet7,
R.drawable.pet8
)
LazyRow(
modifier = Modifier.fillMaxWidth(),
contentPadding = PaddingValues(horizontal = 8.dp)
) {
items(imageIds.size) { index ->
val imageId = imageIds[index]
Image(
painter = painterResource(id = imageId),
contentDescription = null,
modifier = Modifier
.size(100.dp)
.padding(4.dp)
.clickable {
selectedImage = imageId
}
)
}
}
Spacer(modifier = Modifier.height(16.dp))
TextField(
value = petName,
onValueChange = { petName = it },
label = { Text("Имя питомца") },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = {
if (petName.isNotEmpty()) {
val newPet = Pet(0, petName, selectedImage, "")
onSaveClick(newPet)
petName = ""
selectedImage = R.drawable.pet1
navController.popBackStack()
}
},
modifier = Modifier.fillMaxWidth()
) {
Text("Сохранить")
}
}
}

View File

@@ -0,0 +1,109 @@
package com.example.pmuapp.composeui
import android.os.Build
import android.os.Build.*
import androidx.annotation.RequiresApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.example.pmuapp.composeui.navigation.Screen
import com.example.pmuapp.models.user.model.AuthViewModel
import com.example.pmuapp.models.user.model.PetViewModel
import com.example.pmuapp.models.user.model.UserViewModel
@RequiresApi(VERSION_CODES.O)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EditPet(navController: NavController ,authViewModel: AuthViewModel, petViewModel: PetViewModel, userViewModel: UserViewModel, petId: Int) {
val pet = (authViewModel.currentUser?.petId ?: emptyList()).find { it.id == petId }
var petName by remember { mutableStateOf(pet?.name ?: "") }
var petNotes by remember { mutableStateOf(pet?.notes ?: "") }
Column(
modifier = Modifier
.fillMaxSize()
.padding(10.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
val imageResId = pet?.imageResId ?: 0
Image(
painter = painterResource(id = imageResId),
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.height(200.dp)
)
OutlinedTextField(
value = petName,
onValueChange = { petName = it },
label = { Text("Имя питомца") },
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp)
)
Text(
text = "Заметка о питомце",
style = TextStyle(fontSize = 16.sp),
modifier = Modifier.padding(top = 8.dp)
)
TextField(
value = petNotes,
onValueChange = { petNotes = it },
label = { Text("Заметки") },
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp)
.heightIn(max = 200.dp)
.padding(16.dp),
readOnly = false
)
Spacer(modifier = Modifier.weight(1f))
val editedPetId = Screen.PlayPet.route.replace("{id}", pet?.id.toString())
Button(
onClick = {
val updatedPet = pet?.copy(name = petName, notes = petNotes) ?: return@Button
petViewModel.updatePet(updatedPet)
userViewModel.updatePetOnUser(authViewModel.currentUser?.id ?: -1, updatedPet)
authViewModel.currentUser=userViewModel.getUser(authViewModel.currentUser?.id ?: -1)
val petId = Screen.EditPet.route.replace("{id}", pet.id.toString())
navController?.navigate(editedPetId)
},
modifier = Modifier.padding(16.dp)
) {
Text("Сохранить")
}
}
}

View File

@@ -0,0 +1,40 @@
package com.example.pmuapp.composeui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.example.pmuapp.composeui.navigation.Screen
import com.example.pmuapp.models.user.composeui.PetList
import com.example.pmuapp.models.user.model.AuthViewModel
import com.example.pmuapp.models.user.model.PetViewModel
import com.example.pmuapp.models.user.model.UserViewModel
@Composable
fun Home(navController: NavController, authViewModel: AuthViewModel, petViewModel:PetViewModel, userViewModel:UserViewModel) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Button(
onClick = {
navController.navigate(Screen.CreatePet.route)
}
) {
Text("Создать питомца")
}
Spacer(modifier = Modifier.height(16.dp))
PetList(navController,authViewModel, petViewModel, userViewModel, authViewModel.currentUser?.id ?: -1)
}
}

View File

@@ -0,0 +1,104 @@
package com.example.pmuapp.composeui
import android.content.Intent
import android.content.res.Configuration
import android.net.Uri
import android.widget.TextView
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
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.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.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.navigation.NavController
import androidx.navigation.NavHostController
import com.example.pmuapp.R
import com.example.pmuapp.composeui.navigation.Screen
import com.example.pmuapp.models.user.model.AuthViewModel
import com.example.pmuapp.models.user.model.User
import com.example.pmuapp.ui.theme.PMUappTheme
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Login(
navController: NavHostController,
authViewModel: AuthViewModel,
users: List<User>
) {
var username by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
TextField(
value = username,
onValueChange = { username = it },
label = { Text("Username") },
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 16.dp)
)
TextField(
value = password,
onValueChange = { password = it },
label = { Text("Password") },
visualTransformation = PasswordVisualTransformation(),
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 16.dp)
)
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = {
val authenticatedUser = users.find { it.login == username && it.password == password }
if (authenticatedUser != null) {
authViewModel.currentUser = authenticatedUser
navController.navigate(Screen.Profile.route)
} else {
println("Authentication failed")
}
},
modifier = Modifier.fillMaxWidth()
) {
Text("Login")
}
}
}

View File

@@ -0,0 +1,91 @@
package com.example.pmuapp.composeui
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.example.pmuapp.composeui.navigation.Screen
import com.example.pmuapp.models.user.model.AuthViewModel
import com.example.pmuapp.models.user.model.PetViewModel
import com.example.pmuapp.models.user.model.UserViewModel
@RequiresApi(Build.VERSION_CODES.O)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PlayPet(navController: NavController,authViewModel: AuthViewModel, petViewModel: PetViewModel, userViewModel: UserViewModel, petId: Int) {
val pet = (authViewModel.currentUser?.petId ?: emptyList()).find { it.id == petId }
Column(
modifier = Modifier
.fillMaxSize()
.padding(10.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
val imageResId = pet?.imageResId ?: 0
Image(
painter = painterResource(id = imageResId),
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.height(200.dp)
)
Text(
text = pet?.name ?: "",
style = TextStyle(fontWeight = FontWeight.Bold, fontSize = 24.sp),
modifier = Modifier.padding(top = 8.dp)
)
Text(
text = "Заметка о питомце",
style = TextStyle(fontSize = 16.sp),
modifier = Modifier.padding(top = 8.dp)
)
TextField(
value = pet?.notes ?: "",
onValueChange = { },
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp)
.heightIn(max = 200.dp)
.padding(16.dp),
readOnly = true
)
Spacer(modifier = Modifier.weight(1f))
val petId = Screen.EditPet.route.replace("{id}", pet?.id.toString())
Button(
onClick = {
navController?.navigate(petId)
},
modifier = Modifier.padding(16.dp)
) {
Text("Изменить")
}
}
}

View File

@@ -0,0 +1,131 @@
package com.example.pmuapp.composeui
import android.annotation.SuppressLint
import android.net.Uri
import androidx.activity.OnBackPressedCallback
import androidx.activity.OnBackPressedDispatcher
import androidx.activity.compose.BackHandler
import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
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.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import coil.compose.rememberImagePainter
import com.example.pmuapp.composeui.navigation.Screen
import com.example.pmuapp.models.user.model.User
import kotlinx.coroutines.flow.callbackFlow
@OptIn(ExperimentalMaterial3Api::class)
@SuppressLint("RememberReturnType")
@Composable
fun Profile(navController: NavController,currentUser: User?, onSaveClick: (User) -> Unit) {
val nameState = remember { mutableStateOf(currentUser?.name.orEmpty()) }
val loginState = remember { mutableStateOf(currentUser?.login.orEmpty()) }
val passwordState = remember { mutableStateOf(currentUser?.password.orEmpty()) }
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
currentUser?.let { user ->
Image(
painter = rememberImagePainter(data = user.imageResId),
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.height(200.dp)
)
}
val selectedImageUri = remember { mutableStateOf<Uri?>(null) }
val imagePickerLauncher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { result: Uri? ->
result?.let { uri ->
selectedImageUri.value = uri
}
}
Button(
onClick = {
imagePickerLauncher.launch("image/*")
},
modifier = Modifier.fillMaxWidth()
) {
Text("Загрузить фото")
}
TextField(
value = nameState.value,
onValueChange = { nameState.value = it },
label = { Text("Name") },
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 16.dp)
)
TextField(
value = loginState.value,
onValueChange = { loginState.value = it },
label = { Text("Login") },
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 16.dp)
)
TextField(
value = passwordState.value,
onValueChange = { passwordState.value = it },
label = { Text("Password") },
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 16.dp)
)
Button(
onClick = {
val updatedUser = User(
currentUser?.id ?: 0,
nameState.value,
loginState.value,
passwordState.value,
currentUser?.petId ?: emptyList(),
selectedImageUri.value?.toString() ?: "",
)
onSaveClick(updatedUser)
},
modifier = Modifier.fillMaxWidth()
) {
Text("Сохранить")
}
Button(
onClick = {
navController.navigate(Screen.Login.route)
},
modifier = Modifier.fillMaxWidth()
) {
Text("Выйти")
}
}
}

View File

@@ -0,0 +1,238 @@
package com.example.pmuapp.composeui.navigation
import CreatePet
import android.content.res.Configuration
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.navigation.NavDestination
import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import com.example.pmuapp.R
import com.example.pmuapp.composeui.EditPet
import com.example.pmuapp.composeui.Home
import com.example.pmuapp.composeui.Login
import com.example.pmuapp.composeui.PlayPet
import com.example.pmuapp.composeui.Profile
import com.example.pmuapp.models.user.composeui.PetList
import com.example.pmuapp.models.user.composeui.UserList
import com.example.pmuapp.models.user.model.AuthViewModel
import com.example.pmuapp.models.user.model.PetViewModel
import com.example.pmuapp.models.user.model.UserViewModel
import com.example.pmuapp.ui.theme.PMUappTheme
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Topbar(
navController: NavHostController,
currentScreen: Screen?
) {
TopAppBar(
colors = TopAppBarDefaults.smallTopAppBarColors(
containerColor = MaterialTheme.colorScheme.primary,
titleContentColor = MaterialTheme.colorScheme.onPrimary,
),
title = {
Text(stringResource(currentScreen?.resourceId ?: R.string.app_name))
},
navigationIcon = {
if (currentScreen == Screen.PlayPet) {
IconButton(
onClick = {
navController.navigate(Screen.Home.route)
}
) {
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = "Back",
tint = MaterialTheme.colorScheme.onPrimary
)
}
} else if (
navController.previousBackStackEntry != null
&& (currentScreen == null || !currentScreen.showInBottomBar)
) {
IconButton(onClick = { navController.navigateUp() }) {
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = "Back",
tint = MaterialTheme.colorScheme.onPrimary
)
}
}
}
)
}
@Composable
fun Navbar(
navController: NavHostController,
currentDestination: NavDestination?,
modifier: Modifier = Modifier
) {
NavigationBar(modifier) {
Screen.bottomBarItems.forEach { screen ->
NavigationBarItem(
icon = { Icon(screen.icon, contentDescription = null) },
label = { Text(stringResource(screen.resourceId)) },
selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
onClick = {
navController.navigate(screen.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
)
}
}
}
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun NavHost(
navController: NavHostController,
innerPadding: PaddingValues,
authViewModel: AuthViewModel,
userViewModel: UserViewModel,
petViewModel: PetViewModel
) {
NavHost(
navController = navController,
startDestination = Screen.Login.route,
modifier = Modifier.padding(innerPadding)
) {
composable(Screen.Login.route) {
Login(navController, authViewModel,userViewModel.getUsers())
}
composable(Screen.Profile.route) {
val currentUser = authViewModel.currentUser ?: userViewModel.getUsers().firstOrNull()
if (currentUser != null) {
Profile(navController,
currentUser = currentUser,
onSaveClick = {updatedUser ->
userViewModel.updateUser(updatedUser)
authViewModel.currentUser = updatedUser
navController.navigate(Screen.Profile.route)
}
)
} else {
}
}
composable(Screen.UserList.route) { UserList(navController, userViewModel) }
composable(Screen.Home.route) { Home(navController, authViewModel,petViewModel,userViewModel) }
composable(Screen.CreatePet.route) {
val currentUser = authViewModel.currentUser ?: userViewModel.getUsers().firstOrNull()
CreatePet ( navController, onSaveClick = { newPet ->
var adedPet = petViewModel.createPet(newPet)
userViewModel.addPetToUser(currentUser?.id ?:0, adedPet)
authViewModel.currentUser = userViewModel.getUser(currentUser?.id ?:0)
}
)
}
composable(
Screen.UserView.route,
arguments = listOf(navArgument("id") { type = NavType.IntType })
) { backStackEntry ->
val userId = backStackEntry.arguments?.getInt("id") ?: -1
Box(
contentAlignment = Alignment.TopCenter,
modifier = Modifier.fillMaxSize()
) {
PetList(navController,authViewModel, petViewModel, userViewModel, userId)
}
}
composable(
Screen.PlayPet.route,
arguments = listOf(navArgument("id") { type = NavType.IntType })
) { backStackEntry ->
val petId = backStackEntry.arguments?.getInt("id") ?: -1
PlayPet(navController,authViewModel, petViewModel, userViewModel, petId)
}
composable(
Screen.EditPet.route,
arguments = listOf(navArgument("id") { type = NavType.IntType })
) { backStackEntry ->
val petId = backStackEntry.arguments?.getInt("id") ?: -1
EditPet(navController,authViewModel, petViewModel, userViewModel, petId)
}
}
}
@RequiresApi(Build.VERSION_CODES.O)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainNavbar() {
val navController = rememberNavController()
val authViewModel = remember { AuthViewModel() }
val userViewModel =remember {UserViewModel() }
val petViewModel = remember {PetViewModel()}
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
val currentScreen = currentDestination?.route?.let { Screen.getItem(it) }
Scaffold(
topBar = {
Topbar(navController, currentScreen)
},
bottomBar = {
if (currentScreen == null || currentScreen.showInBottomBar) {
Navbar(navController, currentDestination)
}
}
) { innerPadding ->
NavHost(navController, innerPadding, authViewModel, userViewModel, petViewModel )
}
}
//@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 MainNavbarPreview() {
// PMUappTheme {
// Surface(
// color = MaterialTheme.colorScheme.background
// ) {
// MainNavbar()
// }
// }
//}

View File

@@ -0,0 +1,58 @@
package com.example.pmuapp.composeui.navigation
import androidx.annotation.StringRes
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.List
import androidx.compose.material.icons.filled.Person
import androidx.compose.ui.graphics.vector.ImageVector
import com.example.pmuapp.R
enum class Screen(
val route: String,
@StringRes val resourceId: Int,
val icon: ImageVector = Icons.Filled.Favorite,
val showInBottomBar: Boolean = true
) {
UserList(
"user-list", R.string.users_title, Icons.Filled.List
),
Home(
"home", R.string.home_title, Icons.Filled.Home
),
Profile(
"profile", R.string.user_my_title, Icons.Filled.Person
),
UserView(
"user-view/{id}", R.string.user_view_title, showInBottomBar = false
),
Login(
"login", R.string.login_title, showInBottomBar = false
),
CreatePet(
"createpet", R.string.create_pet_title, showInBottomBar = false
),
PlayPet(
"playpet/{id}", R.string.play_pet_title,showInBottomBar = false
),
EditPet(
"editpet/{id}", R.string.edit_pet_title,showInBottomBar = false
);
companion object {
val bottomBarItems = listOf(
UserList,
Home,
Profile,
)
fun getItem(route: String): Screen? {
val findRoute = route.split("/").first()
return values().find { value -> value.route.startsWith(findRoute) }
}
}
}

View File

@@ -0,0 +1,118 @@
package com.example.pmuapp.models.user.composeui
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.example.pmuapp.composeui.navigation.Screen
import com.example.pmuapp.models.user.model.AuthViewModel
import com.example.pmuapp.models.user.model.PetViewModel
import com.example.pmuapp.models.user.model.User
import com.example.pmuapp.models.user.model.UserViewModel
@OptIn(ExperimentalFoundationApi::class, ExperimentalLayoutApi::class)
@Composable
fun PetList(navController: NavController, authViewModel: AuthViewModel, petViewModel: PetViewModel, userViewModel: UserViewModel, userId: Int) {
val currentUser = userViewModel.getUser(userId)
var pets = currentUser.petId
LazyColumn(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
if (userId != authViewModel.currentUser?.id ?: -1) {
item {
Text(
text = currentUser?.name + " (" + currentUser.login + ")",
style = TextStyle(
fontSize = 24.sp,
fontWeight = FontWeight.Bold
),
modifier = Modifier.padding(16.dp)
)
}
}
item {
FlowRow() {
pets.forEach { pet ->
val imageId = pet.imageResId
val petName = pet.name
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(8.dp)
) {
Image(
painter = painterResource(id = imageId),
contentDescription = null,
modifier = Modifier.size(100.dp)
)
Text(
text = petName,
modifier = Modifier.padding(top = 4.dp)
)
if (userId == authViewModel.currentUser?.id ?: -1) {
val petId = Screen.PlayPet.route.replace("{id}", pet.id.toString())
Button(
onClick = {
navController?.navigate(petId)
},
) {
Text("Играть")
}
IconButton(
onClick = {
petViewModel.deletePet(pet)
userViewModel.deletePet(
currentUser?.id
?: 0,
pet.id
)
authViewModel.currentUser =
userViewModel.getUser(
currentUser?.id
?: 0
)
}
) {
Icon(
imageVector = Icons.Default.Delete,
contentDescription = "Удалить"
)
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,49 @@
package com.example.pmuapp.models.user.composeui
import android.content.res.Configuration
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.pmuapp.R
import com.example.pmuapp.models.user.model.User
import com.example.pmuapp.ui.theme.PMUappTheme
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun StudentView(user: User) {
Column(
Modifier
.fillMaxWidth()
.padding(all = 10.dp)
) {
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = user.name, onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.user_name))
}
)
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = user.login, onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.user_login))
}
)
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = user.password, onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.user_login))
}
)
}
}

View File

@@ -0,0 +1,41 @@
package com.example.pmuapp.models.user.composeui
import android.content.res.Configuration
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.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.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.example.pmuapp.composeui.navigation.Screen
import com.example.pmuapp.models.user.model.User
import com.example.pmuapp.models.user.model.UserViewModel
import com.example.pmuapp.ui.theme.PMUappTheme
@Composable
fun UserList(navController: NavController?,
userViewModel: UserViewModel
) {
val users = userViewModel.users.value
Column(Modifier.padding(all = 10.dp)) {
users.forEachIndexed() { index, user ->
val userId = Screen.UserView.route.replace("{id}", index.toString())
Button(
modifier = Modifier
.fillMaxWidth()
.padding(all = 10.dp),
onClick = { navController?.navigate(userId) }) {
Text("${user.login}")
}
}
}
}

View File

@@ -0,0 +1,10 @@
package com.example.pmuapp.models.user.model
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
class AuthViewModel : ViewModel() {
var currentUser: User? by mutableStateOf(null)
}

View File

@@ -0,0 +1,68 @@
package com.example.pmuapp.models.user.model
import android.media.Image
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import com.example.pmuapp.R
import java.io.Serializable
data class Pet(
var id: Int,
val name: String,
val imageResId: Int,
val notes: String
) : Serializable
class PetViewModel : ViewModel() {
var pets: MutableState<List<Pet>> = mutableStateOf(
emptyList()
)
val availablePetImages: List<Int> = listOf(
R.drawable.pet1,
R.drawable.pet2,
R.drawable.pet3,
R.drawable.pet4,
R.drawable.pet5,
R.drawable.pet6,
R.drawable.pet7,
R.drawable.pet8,
)
fun createPet(newPet: Pet): Pet {
newPet.id = pets.value.size.toInt()
val updatedPets = pets.value.toMutableList()
updatedPets.add(newPet)
pets.value = updatedPets
return newPet
}
fun deletePet(pet: Pet) {
val updatedPets = pets.value.toMutableList()
updatedPets.remove(pet)
pets.value = updatedPets
}
fun updatePet(updatedPet: Pet) {
val updatedPets = pets.value.toMutableList()
val index = updatedPets.indexOfFirst { it.id == updatedPet.id }
if (index != -1) {
updatedPets[index] = updatedPet
pets.value = updatedPets
}
}
}
// fun updateUser(updatedUser: User) {
// val updatedUsers = users.value.toMutableList()
// val index = updatedUsers.indexOfFirst { it.login == updatedUser.login }
// if (index != -1) {
// updatedUsers[index] = updatedUser
// users.value = updatedUsers
// }
// }

View File

@@ -0,0 +1,129 @@
package com.example.pmuapp.models.user.model
import android.net.Uri
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import com.example.pmuapp.R
import java.io.Serializable
data class User(
val id: Int,
val name: String,
val login: String,
val password: String,
val petId: List<Pet>,
val imageResId: String // Добавляем поле для хранения ID ресурса изображения пользователя
) : Serializable
class UserViewModel : ViewModel() {
val imageUri: Uri = Uri.parse("android.resource://com.example.pmuapp/${R.drawable.avatar}")
var users: MutableState<List<User>> = mutableStateOf(
listOf(
User(0,"Иван", "ivan", "111111", emptyList(),imageUri.toString()),
User(1,"Анна", "ann", "111111", emptyList(),imageUri.toString()),
User(2,"Лиза", "liza", "111111",emptyList(),imageUri.toString())
)
)
val availablePetImages: List<Int> = listOf(
R.drawable.pet1,
R.drawable.pet2,
R.drawable.pet3,
R.drawable.pet4,
R.drawable.pet5,
R.drawable.pet6,
R.drawable.pet7,
R.drawable.pet8,
)
fun getUsers(): List<User> {
return users.value
}
fun getUser(id:Int): User {
return users.value.get(id)
}
fun getPets(id:Int): List<Pet> {
return users.value.get(id).petId
}
// Function to add a pet to a user
fun addPetToUser(userId: Int, newPet: Pet) {
val updatedUsers = users.value.toMutableList()
val user = updatedUsers.find { it.id == userId }
user?.let {
val updatedPets = user.petId.toMutableList()
updatedPets.add(newPet)
val updatedUser = user.copy(petId = updatedPets)
val userIndex = updatedUsers.indexOf(user)
updatedUsers[userIndex] = updatedUser
users.value = updatedUsers
}
}
fun deletePet(userId: Int, petIdToDelete: Int) {
val updatedUsers = users.value.toMutableList()
// Найдем пользователя по userId
val user = updatedUsers.find { it.id == userId }
user?.let { user ->
val updatedPets = user.petId.toMutableList()
// Найдем питомца по petId и удалим его из списка питомцев
val petToDelete = updatedPets.find { it.id == petIdToDelete }
petToDelete?.let { pet ->
updatedPets.remove(pet)
}
// Обновим пользователя с обновленным списком питомцев
val updatedUser = user.copy(petId = updatedPets)
// Обновим список пользователей
val userIndex = updatedUsers.indexOf(user)
updatedUsers[userIndex] = updatedUser
users.value = updatedUsers
}
}
fun updatePetOnUser(userId: Int, updatedPet: Pet) {
val updatedUsers = users.value.toMutableList()
// Найдем пользователя по userId
val user = updatedUsers.find { it.id == userId }
user?.let { user ->
val updatedPets = user.petId.toMutableList()
// Найдем питомца по petId и обновим его
val petToUpdate = updatedPets.find { it.id == updatedPet.id }
petToUpdate?.let { pet ->
val petIndex = updatedPets.indexOf(pet)
updatedPets[petIndex] = updatedPet
}
// Обновим пользователя с обновленным списком питомцев
val updatedUser = user.copy(petId = updatedPets)
// Обновим список пользователей
val userIndex = updatedUsers.indexOf(user)
updatedUsers[userIndex] = updatedUser
users.value = updatedUsers
}
}
fun updateUser(updatedUser: User) {
val updatedUsers = users.value.toMutableList()
val index = updatedUsers.indexOfFirst { it.login == updatedUser.login }
if (index != -1) {
updatedUsers[index] = updatedUser
users.value = updatedUsers
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

View File

@@ -1,3 +1,31 @@
<resources>
<string name="app_name">PMUapp</string>
<string name="app_name">Мой питомец</string>
<string name="user_name">Имя</string>
<string name="user_login">Логин</string>
<string name="user_password">Пароль</string>
<string name="users_title">Пользователи</string>
<string name="user_view_title">Профиль пользователя</string>
<string name="home_title">Мой дом</string>
<string name="user_my_title">Мой профиль</string>
<string name="login_title">Авторизация</string>
<string name="create_pet_title">Создание питомца</string>
<string name="pet_notes">Заметка питомца</string>
<string name="play_pet_title">Мой питомец</string>
<string name="edit_pet_title">Изменение питомца</string>
<string name="about_text">
<p>Это текст <b>о нас</b>!</p>\n\n
<p>Здесь могла быть Ваша реклама!</p>\n\n
<p>Наш сайт <a href="https://ulstu.ru">ulstu.ru</a></p>
</string>
<string-array name="available_pet_images">
<item>@drawable/avatar</item>
<item>@drawable/pet1</item>
<item>@drawable/pet2</item>
<item>@drawable/pet3</item>
<item>@drawable/pet4</item>
<item>@drawable/pet5</item>
<item>@drawable/pet6</item>
<item>@drawable/pet7</item>
<item>@drawable/pet8</item>
</string-array>
</resources>

View File

@@ -21,3 +21,4 @@ kotlin.code.style=official
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
android.overridePathCheck=true