Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
6316b927b7 | |||
7ec106a409 | |||
8aef08d754 | |||
3cacfd64b4 | |||
d1d9601b6c |
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
BIN
Layout/DeliveryApp.fig
Normal file
BIN
Layout/DeliveryApp.fig
Normal file
Binary file not shown.
@ -1,6 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
id("org.jetbrains.kotlin.android")
|
id("org.jetbrains.kotlin.android")
|
||||||
|
id("kotlin-kapt")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@ -18,6 +19,11 @@ android {
|
|||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
useSupportLibrary = true
|
useSupportLibrary = true
|
||||||
}
|
}
|
||||||
|
kapt {
|
||||||
|
arguments {
|
||||||
|
arg("room.schemaLocation", "$projectDir/schemas")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@ -46,8 +52,14 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
tasks.withType(type = org.jetbrains.kotlin.gradle.internal.KaptGenerateStubsTask::class) {
|
||||||
|
kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("androidx.navigation:navigation-compose:2.6.0")
|
||||||
implementation("androidx.core:core-ktx:1.9.0")
|
implementation("androidx.core:core-ktx:1.9.0")
|
||||||
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1")
|
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1")
|
||||||
implementation("androidx.activity:activity-compose:1.7.0")
|
implementation("androidx.activity:activity-compose:1.7.0")
|
||||||
@ -63,4 +75,12 @@ dependencies {
|
|||||||
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
|
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
|
||||||
debugImplementation("androidx.compose.ui:ui-tooling")
|
debugImplementation("androidx.compose.ui:ui-tooling")
|
||||||
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
||||||
|
|
||||||
|
// Room
|
||||||
|
val room_version = "2.5.1"
|
||||||
|
implementation("androidx.room:room-ktx:$room_version")
|
||||||
|
kapt ("androidx.room:room-compiler:$room_version")
|
||||||
|
implementation ("androidx.lifecycle:lifecycle-viewmodel-compose:2.5.0")
|
||||||
|
|
||||||
|
implementation ("androidx.compose.runtime:runtime-livedata:1.0.0-beta01")
|
||||||
}
|
}
|
108
app/schemas/com.example.pmu_2023.database.AppDatabase/2.json
Normal file
108
app/schemas/com.example.pmu_2023.database.AppDatabase/2.json
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 2,
|
||||||
|
"identityHash": "92c4ab5b3a31c5bee1cd30524bdd2448",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "users",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` INTEGER PRIMARY KEY AUTOINCREMENT, `fio` TEXT NOT NULL, `password` TEXT NOT NULL, `address` TEXT NOT NULL, `phone` TEXT NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "userId",
|
||||||
|
"columnName": "userId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "fio",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "password",
|
||||||
|
"columnName": "password",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "address",
|
||||||
|
"columnName": "address",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "phone",
|
||||||
|
"columnName": "phone",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"userId"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "parcels",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`parcelId` INTEGER PRIMARY KEY AUTOINCREMENT, `parcel_name` TEXT NOT NULL, `track_number` TEXT NOT NULL, `status` TEXT NOT NULL, `description` TEXT NOT NULL, `userOwnerId` INTEGER NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "parcelId",
|
||||||
|
"columnName": "parcelId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "parcel_name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "trackNumber",
|
||||||
|
"columnName": "track_number",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "status",
|
||||||
|
"columnName": "status",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "description",
|
||||||
|
"columnName": "description",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "userOwnerId",
|
||||||
|
"columnName": "userOwnerId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"parcelId"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"views": [],
|
||||||
|
"setupQueries": [
|
||||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '92c4ab5b3a31c5bee1cd30524bdd2448')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
android:name=".database.App"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
|
BIN
app/src/main/assets/database/example.db
Normal file
BIN
app/src/main/assets/database/example.db
Normal file
Binary file not shown.
141
app/src/main/java/com/example/pmu_2023/Forms/Login.kt
Normal file
141
app/src/main/java/com/example/pmu_2023/Forms/Login.kt
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
package com.example.pmu_2023.Forms
|
||||||
|
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
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.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.text.style.TextDecoration
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import com.example.pmu_2023.Greeting
|
||||||
|
import com.example.pmu_2023.database.AppDatabase
|
||||||
|
import com.example.pmu_2023.database.MainViewModel
|
||||||
|
import com.example.pmu_2023.logic.model.User
|
||||||
|
import com.example.pmu_2023.ui.theme.MainBlue
|
||||||
|
import com.example.pmu_2023.ui.theme.PMU_2023Theme
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.FlowCollector
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.example.pmu_2023.MainActivity
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Login(
|
||||||
|
navController: NavController?,
|
||||||
|
mainViewModel: MainViewModel
|
||||||
|
){
|
||||||
|
var LoginText by rememberSaveable { mutableStateOf("")}
|
||||||
|
var PassText by rememberSaveable { mutableStateOf("")}
|
||||||
|
var data by remember { mutableStateOf<User?>(null)}
|
||||||
|
var isLoading by remember { mutableStateOf(false)}
|
||||||
|
if (isLoading){
|
||||||
|
LaunchedEffect(Unit){
|
||||||
|
val newData = withContext(Dispatchers.IO){
|
||||||
|
mainViewModel.getUserByNameAndPass(LoginText, PassText)
|
||||||
|
}
|
||||||
|
data = newData
|
||||||
|
val userId = Screen.ParcelList.route.replace("{id}", data?.userId.toString())
|
||||||
|
isLoading = false
|
||||||
|
navController?.navigate(userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Column (
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(all = 10.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center
|
||||||
|
|
||||||
|
) {
|
||||||
|
Login_Field(value = LoginText, onInputChanged = {LoginText = it} ,name = "Email", label = "Введите логин...")
|
||||||
|
Login_Field(value = PassText, onInputChanged = {PassText = it} ,name = "Password", label = "Введите пароль...")
|
||||||
|
Text(
|
||||||
|
text = "Регистрация",
|
||||||
|
style = TextStyle(textDecoration = TextDecoration.Underline),
|
||||||
|
fontSize = 15.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 10.dp)
|
||||||
|
.clickable { navController?.navigate("registration") },
|
||||||
|
textAlign = TextAlign.End
|
||||||
|
)
|
||||||
|
Spacer(Modifier.size(20.dp))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
isLoading = true
|
||||||
|
},
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Войти",
|
||||||
|
fontSize = 22.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun Login_Field(value: String, onInputChanged: (String) -> Unit, name: String, label: String){
|
||||||
|
|
||||||
|
Column (modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 10.dp)) {
|
||||||
|
Text(
|
||||||
|
text = name,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 18.sp
|
||||||
|
)
|
||||||
|
TextField(
|
||||||
|
value = value,
|
||||||
|
onValueChange = onInputChanged,
|
||||||
|
placeholder = {
|
||||||
|
Text(text = label)
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
310
app/src/main/java/com/example/pmu_2023/Forms/MainForm.kt
Normal file
310
app/src/main/java/com/example/pmu_2023/Forms/MainForm.kt
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
package com.example.pmu_2023.Forms
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
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.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.AccountBox
|
||||||
|
import androidx.compose.material.icons.filled.Add
|
||||||
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
|
import androidx.compose.material.icons.filled.Close
|
||||||
|
import androidx.compose.material.icons.filled.Menu
|
||||||
|
import androidx.compose.material3.DrawerState
|
||||||
|
import androidx.compose.material3.DrawerValue
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.ModalDrawerSheet
|
||||||
|
import androidx.compose.material3.ModalNavigationDrawer
|
||||||
|
import androidx.compose.material3.NavigationDrawerItem
|
||||||
|
import androidx.compose.material3.NavigationDrawerItemDefaults
|
||||||
|
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.material3.rememberDrawerState
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
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.drawBehind
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
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.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.pmu_2023.R
|
||||||
|
import com.example.pmu_2023.database.MainViewModel
|
||||||
|
import com.example.pmu_2023.logic.composeui.CreateParcel
|
||||||
|
import com.example.pmu_2023.logic.composeui.ParcelList
|
||||||
|
import com.example.pmu_2023.logic.composeui.ParcelView
|
||||||
|
import com.example.pmu_2023.logic.composeui.UpdateParcel
|
||||||
|
import com.example.pmu_2023.logic.composeui.UserProfileView
|
||||||
|
import com.example.pmu_2023.logic.model.User
|
||||||
|
import com.example.pmu_2023.ui.theme.PMU_2023Theme
|
||||||
|
import com.example.pmu_2023.ui.theme.PurpleGrey80
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun Topbar(
|
||||||
|
navController: NavHostController,
|
||||||
|
currentScreen: Screen?,
|
||||||
|
drawerState: DrawerState,
|
||||||
|
scope: CoroutineScope,
|
||||||
|
mainViewModel: MainViewModel
|
||||||
|
) {
|
||||||
|
TopAppBar(
|
||||||
|
colors = TopAppBarDefaults.smallTopAppBarColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.primary,
|
||||||
|
titleContentColor = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
),
|
||||||
|
title = {
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
text = stringResource(currentScreen?.resourceId ?: R.string.app_name),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
},
|
||||||
|
navigationIcon = {
|
||||||
|
if (
|
||||||
|
navController.previousBackStackEntry != null
|
||||||
|
&& (currentScreen == null || !currentScreen.showInDrawer)
|
||||||
|
) {
|
||||||
|
IconButton(onClick = { navController.navigateUp() }) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.ArrowBack,
|
||||||
|
contentDescription = null,
|
||||||
|
tint = MaterialTheme.colorScheme.onPrimary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(
|
||||||
|
currentScreen != Screen.Login
|
||||||
|
&& currentScreen != Screen.Registration
|
||||||
|
) {
|
||||||
|
IconButton(onClick = {
|
||||||
|
scope.launch {
|
||||||
|
drawerState.open()
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.Menu,
|
||||||
|
contentDescription = "Menu",
|
||||||
|
tint = MaterialTheme.colorScheme.onPrimary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
actions = {
|
||||||
|
if(currentScreen == Screen.ParcelList) {
|
||||||
|
IconButton(onClick = {
|
||||||
|
val userId = Screen.CreateParcel.route.replace("{id}", mainViewModel.curUid.value.toString())
|
||||||
|
navController.navigate(userId)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.Add,
|
||||||
|
contentDescription = "Add Parcel",
|
||||||
|
tint = MaterialTheme.colorScheme.onPrimary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Navhost(
|
||||||
|
navController: NavHostController,
|
||||||
|
innerPadding: PaddingValues,
|
||||||
|
mainViewModel: MainViewModel,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
NavHost(
|
||||||
|
navController,
|
||||||
|
startDestination = Screen.Login.route,
|
||||||
|
modifier.padding(innerPadding)
|
||||||
|
) {
|
||||||
|
composable(Screen.ParcelList.route,
|
||||||
|
arguments = listOf(navArgument("id") { type = NavType.IntType })
|
||||||
|
) { backStackEntry ->
|
||||||
|
backStackEntry.arguments?.let { ParcelList(navController, it.getInt("id"), mainViewModel) }
|
||||||
|
}
|
||||||
|
composable(Screen.Login.route) { Login(navController, mainViewModel) }
|
||||||
|
composable(Screen.Registration.route) { Registration(navController, mainViewModel) }
|
||||||
|
composable(
|
||||||
|
Screen.ParcelView.route,
|
||||||
|
arguments = listOf(navArgument("id") { type = NavType.IntType })
|
||||||
|
) { backStackEntry ->
|
||||||
|
backStackEntry.arguments?.let { ParcelView(it.getInt("id"), mainViewModel) }
|
||||||
|
}
|
||||||
|
composable(
|
||||||
|
Screen.CreateParcel.route,
|
||||||
|
arguments = listOf(navArgument("id") { type = NavType.IntType })
|
||||||
|
) { backStackEntry ->
|
||||||
|
backStackEntry.arguments?.let { CreateParcel(it.getInt("id"), mainViewModel) }
|
||||||
|
}
|
||||||
|
composable(
|
||||||
|
Screen.UpdateParcel.route,
|
||||||
|
arguments = listOf(navArgument("id") { type = NavType.IntType })
|
||||||
|
) { backStackEntry ->
|
||||||
|
backStackEntry.arguments?.let { UpdateParcel(it.getInt("id"), mainViewModel) }
|
||||||
|
}
|
||||||
|
composable(
|
||||||
|
Screen.UserProfileView.route,
|
||||||
|
arguments = listOf(navArgument("id") { type = NavType.IntType })
|
||||||
|
) { backStackEntry ->
|
||||||
|
backStackEntry.arguments?.let { UserProfileView(it.getInt("id"), mainViewModel) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun MainContent(
|
||||||
|
mainViewModel: MainViewModel = viewModel(factory = MainViewModel.factory)
|
||||||
|
) {
|
||||||
|
val navController = rememberNavController()
|
||||||
|
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||||
|
val currentDestination = navBackStackEntry?.destination
|
||||||
|
val currentScreen = currentDestination?.route?.let { Screen.getItem(it) }
|
||||||
|
|
||||||
|
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
var selectedItemIndex by rememberSaveable { mutableStateOf(0) }
|
||||||
|
|
||||||
|
ModalNavigationDrawer(
|
||||||
|
gesturesEnabled = false,
|
||||||
|
drawerContent = {
|
||||||
|
ModalDrawerSheet {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(100.dp)
|
||||||
|
.drawBehind {
|
||||||
|
drawLine(
|
||||||
|
Color.Black,
|
||||||
|
Offset(0f, size.height),
|
||||||
|
Offset(size.width, size.height),
|
||||||
|
5f
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.background(PurpleGrey80),
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Меню",
|
||||||
|
fontSize = 24.sp,
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
Screen.DrawerItems.forEachIndexed { index, item ->
|
||||||
|
NavigationDrawerItem(
|
||||||
|
label = {
|
||||||
|
Text(stringResource(item.resourceId))
|
||||||
|
},
|
||||||
|
selected = index == selectedItemIndex,
|
||||||
|
onClick = {
|
||||||
|
val userId = item.route.replace("{id}", mainViewModel.curUid.value.toString())
|
||||||
|
navController.navigate(userId){
|
||||||
|
popUpTo(navController.graph.findStartDestination().id) {
|
||||||
|
saveState = true
|
||||||
|
}
|
||||||
|
launchSingleTop = true
|
||||||
|
restoreState = true
|
||||||
|
}
|
||||||
|
selectedItemIndex = index
|
||||||
|
scope.launch {
|
||||||
|
drawerState.close()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon = {
|
||||||
|
Icon(
|
||||||
|
imageVector = if (index == selectedItemIndex) {
|
||||||
|
item.selectedIcon
|
||||||
|
} else item.unselectedIcon,
|
||||||
|
contentDescription = stringResource(item.resourceId)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(NavigationDrawerItemDefaults.ItemPadding)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
NavigationDrawerItem(
|
||||||
|
label = {
|
||||||
|
Text(stringResource(R.string.quit_title))
|
||||||
|
},
|
||||||
|
selected = 2 == selectedItemIndex,
|
||||||
|
onClick = {
|
||||||
|
navController.navigate("login")
|
||||||
|
selectedItemIndex = 2
|
||||||
|
scope.launch {
|
||||||
|
drawerState.close()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon = {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.Close,
|
||||||
|
contentDescription = stringResource(R.string.quit_title)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(NavigationDrawerItemDefaults.ItemPadding)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
drawerState = drawerState
|
||||||
|
) {
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
Topbar(navController, currentScreen, drawerState, scope, mainViewModel)
|
||||||
|
},
|
||||||
|
) {innerPadding ->
|
||||||
|
Navhost(navController, innerPadding, mainViewModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun MainFormPreview() {
|
||||||
|
PMU_2023Theme {
|
||||||
|
Surface(
|
||||||
|
color = MaterialTheme.colorScheme.background
|
||||||
|
) {
|
||||||
|
MainContent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
113
app/src/main/java/com/example/pmu_2023/Forms/Registration.kt
Normal file
113
app/src/main/java/com/example/pmu_2023/Forms/Registration.kt
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
package com.example.pmu_2023.Forms
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.ArrowDropDown
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
import androidx.compose.material3.DropdownMenu
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextField
|
||||||
|
import androidx.compose.material3.TextFieldColors
|
||||||
|
import androidx.compose.material3.TextFieldDefaults
|
||||||
|
import androidx.compose.material3.contentColorFor
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.text.style.TextDecoration
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import com.example.pmu_2023.database.MainViewModel
|
||||||
|
import com.example.pmu_2023.logic.model.Parcel
|
||||||
|
import com.example.pmu_2023.logic.model.User
|
||||||
|
import com.example.pmu_2023.ui.theme.MainBlue
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Registration(
|
||||||
|
navController: NavController?,
|
||||||
|
mainViewModel: MainViewModel
|
||||||
|
){
|
||||||
|
var NameText by rememberSaveable { mutableStateOf("")}
|
||||||
|
var PassText by rememberSaveable { mutableStateOf("")}
|
||||||
|
var AddressText by rememberSaveable { mutableStateOf("")}
|
||||||
|
var PhoneText by rememberSaveable { mutableStateOf("")}
|
||||||
|
|
||||||
|
Column (
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize(),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.SpaceEvenly
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(20.dp)
|
||||||
|
) {
|
||||||
|
Registr_Field(value = NameText, onInputChanged = {NameText = it} ,name = "Email", label = "Придумайте логин...")
|
||||||
|
Registr_Field(value = PassText, onInputChanged = {PassText = it} ,name = "Password", label = "Придумайте пароль...")
|
||||||
|
Registr_Field(value = AddressText, onInputChanged = {AddressText = it} ,name = "Password", label = "Введите адрес...")
|
||||||
|
Registr_Field(value = PhoneText, onInputChanged = {PhoneText = it} ,name = "Password", label = "Введите номер телефона...")
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
val newUser = User(NameText, PassText, AddressText, PhoneText)
|
||||||
|
mainViewModel.insertUser(newUser)
|
||||||
|
navController?.navigate("login")
|
||||||
|
},
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Text(
|
||||||
|
text = "Зарегистрироваться",
|
||||||
|
fontSize = 22.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun Registr_Field(value: String, onInputChanged: (String) -> Unit, name: String, label: String){
|
||||||
|
|
||||||
|
Column (modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 10.dp)) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = value,
|
||||||
|
onValueChange = onInputChanged,
|
||||||
|
label = {
|
||||||
|
Text(text = label)
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
56
app/src/main/java/com/example/pmu_2023/Forms/Screen.kt
Normal file
56
app/src/main/java/com/example/pmu_2023/Forms/Screen.kt
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package com.example.pmu_2023.Forms
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.AccountBox
|
||||||
|
import androidx.compose.material.icons.filled.Close
|
||||||
|
import androidx.compose.material.icons.filled.Favorite
|
||||||
|
import androidx.compose.material.icons.filled.Info
|
||||||
|
import androidx.compose.material.icons.filled.List
|
||||||
|
import androidx.compose.material.icons.outlined.AccountBox
|
||||||
|
import androidx.compose.material.icons.outlined.Close
|
||||||
|
import androidx.compose.material.icons.outlined.List
|
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import com.example.pmu_2023.R
|
||||||
|
|
||||||
|
enum class Screen(
|
||||||
|
val route: String,
|
||||||
|
@StringRes val resourceId: Int,
|
||||||
|
val selectedIcon: ImageVector = Icons.Filled.Favorite,
|
||||||
|
val unselectedIcon: ImageVector = Icons.Filled.Favorite,
|
||||||
|
val showInDrawer: Boolean = true
|
||||||
|
) {
|
||||||
|
ParcelList(
|
||||||
|
"parcel-list/{id}", R.string.parcel_list_title, Icons.Filled.List, Icons.Outlined.List
|
||||||
|
),
|
||||||
|
Login(
|
||||||
|
"login", R.string.login_title
|
||||||
|
),
|
||||||
|
Registration(
|
||||||
|
"registration", R.string.registration_title
|
||||||
|
),
|
||||||
|
ParcelView(
|
||||||
|
"parcel-view/{id}", R.string.parcel_view_title, showInDrawer = false
|
||||||
|
),
|
||||||
|
CreateParcel(
|
||||||
|
"parcel-create/{id}", R.string.parcel_create_title, showInDrawer = false
|
||||||
|
),
|
||||||
|
UpdateParcel(
|
||||||
|
"parcel-update/{id}", R.string.parcel_update_title, showInDrawer = false
|
||||||
|
),
|
||||||
|
UserProfileView(
|
||||||
|
"user-view/{id}", R.string.user_view_title, Icons.Filled.AccountBox, Icons.Outlined.AccountBox
|
||||||
|
);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val DrawerItems = listOf(
|
||||||
|
ParcelList,
|
||||||
|
UserProfileView
|
||||||
|
)
|
||||||
|
|
||||||
|
fun getItem(route: String): Screen? {
|
||||||
|
val findRoute = route.split("/").first()
|
||||||
|
return values().find { value -> value.route.startsWith(findRoute) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ import androidx.compose.material3.Text
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import com.example.pmu_2023.Forms.MainContent
|
||||||
import com.example.pmu_2023.ui.theme.PMU_2023Theme
|
import com.example.pmu_2023.ui.theme.PMU_2023Theme
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
@ -19,7 +20,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
PMU_2023Theme {
|
PMU_2023Theme {
|
||||||
// A surface container using the 'background' color from the theme
|
// A surface container using the 'background' color from the theme
|
||||||
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
|
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
|
||||||
Greeting("Android")
|
MainContent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
app/src/main/java/com/example/pmu_2023/database/App.kt
Normal file
7
app/src/main/java/com/example/pmu_2023/database/App.kt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package com.example.pmu_2023.database
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
|
||||||
|
class App : Application() {
|
||||||
|
val database by lazy { AppDatabase.createDataBase(this) }
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.example.pmu_2023.database
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.room.AutoMigration
|
||||||
|
import androidx.room.Database
|
||||||
|
import androidx.room.Room
|
||||||
|
import androidx.room.RoomDatabase
|
||||||
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
|
import com.example.pmu_2023.logic.dao.ParcelDao
|
||||||
|
import com.example.pmu_2023.logic.dao.UserDao
|
||||||
|
import com.example.pmu_2023.logic.model.Parcel
|
||||||
|
import com.example.pmu_2023.logic.model.User
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@Database(
|
||||||
|
entities = [User::class, Parcel::class],
|
||||||
|
version = 2,
|
||||||
|
exportSchema = true
|
||||||
|
)
|
||||||
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
|
abstract val userDao: UserDao
|
||||||
|
abstract val parcelDao: ParcelDao
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val DB_NAME: String = "pmy-db"
|
||||||
|
|
||||||
|
fun createDataBase(context: Context): AppDatabase {
|
||||||
|
return Room.databaseBuilder(
|
||||||
|
context,
|
||||||
|
AppDatabase::class.java,
|
||||||
|
DB_NAME
|
||||||
|
).createFromAsset("database/example.db")
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package com.example.pmu_2023.database
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.lifecycle.viewmodel.CreationExtras
|
||||||
|
import com.example.pmu_2023.logic.model.Parcel
|
||||||
|
import com.example.pmu_2023.logic.model.User
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.coroutineScope
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class MainViewModel(val database: AppDatabase) : ViewModel() {
|
||||||
|
|
||||||
|
//User Logic
|
||||||
|
|
||||||
|
var curUid = mutableStateOf<Int?>(null)
|
||||||
|
suspend fun getUserByNameAndPass(name: String, password: String): User? {
|
||||||
|
val getUser = database.userDao.getByLogin(name, password)
|
||||||
|
curUid.value = getUser?.userId
|
||||||
|
return getUser
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getUserById(id: Int?): User?{
|
||||||
|
return database.userDao.getById(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun insertUser(user: User) = viewModelScope.launch {
|
||||||
|
database.userDao.insert(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Parcel Logic
|
||||||
|
suspend fun getParcelById(id: Int?): Parcel?{
|
||||||
|
return database.parcelDao.getById(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getParcelsById(id: Int?): Flow<List<Parcel>> {
|
||||||
|
return database.parcelDao.getAllByUid(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteParcel(parcel: Parcel?) = viewModelScope.launch {
|
||||||
|
database.parcelDao.delete(parcel)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun insertParcel(parcel: Parcel) = viewModelScope.launch {
|
||||||
|
database.parcelDao.insert(parcel)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateParcel(parcel: Parcel) = viewModelScope.launch {
|
||||||
|
database.parcelDao.update(parcel)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object{
|
||||||
|
val factory: ViewModelProvider.Factory = object : ViewModelProvider.Factory{
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun <T : ViewModel> create(
|
||||||
|
modelClass: Class<T>,
|
||||||
|
extras: CreationExtras): T {
|
||||||
|
val database = (checkNotNull(extras[APPLICATION_KEY]) as App).database
|
||||||
|
return MainViewModel(database) as T
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
package com.example.pmu_2023.logic.composeui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
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.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.example.pmu_2023.R
|
||||||
|
import com.example.pmu_2023.database.MainViewModel
|
||||||
|
import com.example.pmu_2023.logic.model.Parcel
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CreateParcel(
|
||||||
|
id: Int,
|
||||||
|
mainViewModel: MainViewModel
|
||||||
|
) {
|
||||||
|
|
||||||
|
var NameText by rememberSaveable { mutableStateOf("") }
|
||||||
|
var TrackText by rememberSaveable { mutableStateOf("") }
|
||||||
|
var StatusText by rememberSaveable { mutableStateOf("") }
|
||||||
|
var DescriptionText by rememberSaveable { mutableStateOf("") }
|
||||||
|
|
||||||
|
Column(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(all = 10.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Input_Field(value = NameText, onInputChanged = {NameText = it}, label = stringResource(id = R.string.parcel_name) )
|
||||||
|
Input_Field(value = TrackText, onInputChanged = {TrackText = it}, label = stringResource(id = R.string.track_number))
|
||||||
|
Input_Field(value = StatusText, onInputChanged = {StatusText = it}, label = stringResource(id = R.string.status))
|
||||||
|
Input_Field(value = DescriptionText, onInputChanged = {DescriptionText = it}, label = stringResource(id = R.string.description))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
val newParcel = Parcel(NameText, TrackText, StatusText, DescriptionText, id)
|
||||||
|
mainViewModel.insertParcel(newParcel)
|
||||||
|
},
|
||||||
|
Modifier.padding(10.dp),
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Создать",
|
||||||
|
fontSize = 22.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun Input_Field(value: String, onInputChanged: (String) -> Unit, label: String){
|
||||||
|
OutlinedTextField(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 10.dp),
|
||||||
|
value = value,
|
||||||
|
onValueChange = onInputChanged,
|
||||||
|
label = {
|
||||||
|
Text(label)
|
||||||
|
},
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,171 @@
|
|||||||
|
package com.example.pmu_2023.logic.composeui
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.RowScope
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
|
import androidx.compose.material.icons.filled.Edit
|
||||||
|
import androidx.compose.material.icons.outlined.Edit
|
||||||
|
import androidx.compose.material3.AlertDialog
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.State
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
|
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.draw.drawBehind
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import com.example.pmu_2023.Forms.Screen
|
||||||
|
import com.example.pmu_2023.database.MainViewModel
|
||||||
|
import com.example.pmu_2023.logic.model.Parcel
|
||||||
|
import com.example.pmu_2023.logic.model.User
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.collect
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RowScope.TableCell(
|
||||||
|
text: String,
|
||||||
|
weight: Float
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
Modifier
|
||||||
|
.weight(weight)
|
||||||
|
.padding(8.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun ParcelList(navController: NavController?,
|
||||||
|
id: Int,
|
||||||
|
mainViewModel: MainViewModel
|
||||||
|
) {
|
||||||
|
val itemsList = remember { mutableStateListOf<Parcel>()}
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
mainViewModel.getParcelsById(id).collect {data ->
|
||||||
|
itemsList.clear()
|
||||||
|
itemsList.addAll(data)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val openDialog = remember { mutableStateOf(false) }
|
||||||
|
var isDeleteParcel by remember { mutableStateOf<Parcel?>(null)}
|
||||||
|
|
||||||
|
if (openDialog.value) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = {
|
||||||
|
openDialog.value = false
|
||||||
|
},
|
||||||
|
title = { Text(text = "Подтверждение действия") },
|
||||||
|
text = { Text("Удалить выбранный элемент?") },
|
||||||
|
confirmButton = {
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
openDialog.value = false
|
||||||
|
mainViewModel.deleteParcel(isDeleteParcel)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text("OK", fontSize = 22.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
LazyColumn(modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(16.dp) )
|
||||||
|
{
|
||||||
|
item {
|
||||||
|
Row(
|
||||||
|
Modifier
|
||||||
|
.background(Color.Gray)
|
||||||
|
.drawBehind {
|
||||||
|
|
||||||
|
drawLine(
|
||||||
|
Color.Black,
|
||||||
|
Offset(0f, size.height),
|
||||||
|
Offset(size.width, size.height),
|
||||||
|
4f
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
TableCell(text = "№", weight = .1f)
|
||||||
|
TableCell(text = "Название", weight = .3f)
|
||||||
|
TableCell(text = "Номер отслеживания", weight = .6f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
itemsIndexed(itemsList)
|
||||||
|
{index, item ->
|
||||||
|
val parcelViewId = Screen.ParcelView.route.replace("{id}", item.parcelId.toString())
|
||||||
|
val parcelUpdId = Screen.UpdateParcel.route.replace("{id}", item.parcelId.toString())
|
||||||
|
Row(Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable {
|
||||||
|
navController?.navigate(parcelViewId)
|
||||||
|
}
|
||||||
|
.pointerInput(Unit) {
|
||||||
|
detectHorizontalDragGestures { change, dragAmount ->
|
||||||
|
isDeleteParcel = item
|
||||||
|
openDialog.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.drawBehind {
|
||||||
|
drawLine(
|
||||||
|
Color.Black,
|
||||||
|
Offset(0f, size.height),
|
||||||
|
Offset(size.width, size.height),
|
||||||
|
3f
|
||||||
|
)
|
||||||
|
},
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
){
|
||||||
|
TableCell(text = (index+1).toString(), weight = .1f)
|
||||||
|
TableCell(text = item.name, weight = .3f)
|
||||||
|
TableCell(text = item.trackNumber, weight = .5f)
|
||||||
|
IconButton(
|
||||||
|
onClick = {
|
||||||
|
navController?.navigate(parcelUpdId)
|
||||||
|
},
|
||||||
|
Modifier.weight(.1f)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.Edit,
|
||||||
|
contentDescription = "Edit",
|
||||||
|
tint = Color.Black
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package com.example.pmu_2023.logic.composeui
|
||||||
|
|
||||||
|
import com.example.pmu_2023.ui.theme.PMU_2023Theme
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
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 androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.example.pmu_2023.Forms.Screen
|
||||||
|
import com.example.pmu_2023.R
|
||||||
|
import com.example.pmu_2023.database.MainViewModel
|
||||||
|
import com.example.pmu_2023.logic.model.Parcel
|
||||||
|
import com.example.pmu_2023.logic.model.User
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun ParcelView(
|
||||||
|
id: Int,
|
||||||
|
mainViewModel: MainViewModel
|
||||||
|
) {
|
||||||
|
var parcel by remember { mutableStateOf<Parcel?>(null) }
|
||||||
|
LaunchedEffect(Unit){
|
||||||
|
val newData = withContext(Dispatchers.IO){
|
||||||
|
mainViewModel.getParcelById(id)
|
||||||
|
}
|
||||||
|
parcel = newData
|
||||||
|
}
|
||||||
|
Column(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(all = 10.dp)
|
||||||
|
) {
|
||||||
|
parcel?.let {
|
||||||
|
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
||||||
|
value = it.trackNumber, onValueChange = {}, readOnly = true,
|
||||||
|
label = {
|
||||||
|
Text(stringResource(id = R.string.track_number ))
|
||||||
|
},
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
)
|
||||||
|
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
||||||
|
value = it.name, onValueChange = {}, readOnly = true,
|
||||||
|
label = {
|
||||||
|
Text(stringResource(id = R.string.parcel_name ))
|
||||||
|
},
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
)
|
||||||
|
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
||||||
|
value = it.description, onValueChange = {}, readOnly = true,
|
||||||
|
label = {
|
||||||
|
Text(stringResource(id = R.string.description ))
|
||||||
|
},
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
)
|
||||||
|
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
||||||
|
value = it.status, onValueChange = {}, readOnly = true,
|
||||||
|
label = {
|
||||||
|
Text(stringResource(id = R.string.status ))
|
||||||
|
},
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
package com.example.pmu_2023.logic.composeui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
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.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
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.graphics.Color
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.example.pmu_2023.Forms.Screen
|
||||||
|
import com.example.pmu_2023.R
|
||||||
|
import com.example.pmu_2023.database.MainViewModel
|
||||||
|
import com.example.pmu_2023.logic.model.Parcel
|
||||||
|
import com.example.pmu_2023.logic.model.User
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun UpdateParcel(
|
||||||
|
id: Int,
|
||||||
|
mainViewModel: MainViewModel
|
||||||
|
) {
|
||||||
|
var NameText by rememberSaveable { mutableStateOf("") }
|
||||||
|
var TrackText by rememberSaveable { mutableStateOf("") }
|
||||||
|
var StatusText by rememberSaveable { mutableStateOf("") }
|
||||||
|
var DescriptionText by rememberSaveable { mutableStateOf("") }
|
||||||
|
|
||||||
|
var data by remember { mutableStateOf<Parcel?>(null)}
|
||||||
|
|
||||||
|
LaunchedEffect(Unit){
|
||||||
|
val newData = withContext(Dispatchers.IO){
|
||||||
|
mainViewModel.getParcelById(id)
|
||||||
|
}
|
||||||
|
data = newData
|
||||||
|
|
||||||
|
NameText = newData?.name.toString()
|
||||||
|
TrackText = newData?.trackNumber.toString()
|
||||||
|
StatusText = newData?.status.toString()
|
||||||
|
DescriptionText = newData?.description.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Column(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(all = 10.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Input_Field(value = NameText, onInputChanged = {NameText = it}, label = stringResource(id = R.string.parcel_name) )
|
||||||
|
Input_Field(value = TrackText, onInputChanged = {TrackText = it}, label = stringResource(id = R.string.track_number))
|
||||||
|
Input_Field(value = StatusText, onInputChanged = {StatusText = it}, label = stringResource(id = R.string.status))
|
||||||
|
Input_Field(value = DescriptionText, onInputChanged = {DescriptionText = it}, label = stringResource(id = R.string.description))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
val newParcel = Parcel(id, NameText, TrackText, StatusText, DescriptionText, data!!.userOwnerId)
|
||||||
|
mainViewModel.updateParcel(newParcel)
|
||||||
|
},
|
||||||
|
Modifier.padding(10.dp),
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Сохранить изменения",
|
||||||
|
fontSize = 22.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,92 @@
|
|||||||
|
package com.example.pmu_2023.logic.composeui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
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.ui.Alignment
|
||||||
|
import androidx.compose.ui.Alignment.Companion.Center
|
||||||
|
import androidx.compose.ui.Alignment.Companion.CenterHorizontally
|
||||||
|
import androidx.compose.ui.Alignment.Companion.CenterStart
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.draw.shadow
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.RectangleShape
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.example.pmu_2023.R
|
||||||
|
import com.example.pmu_2023.database.MainViewModel
|
||||||
|
import com.example.pmu_2023.logic.model.Parcel
|
||||||
|
import com.example.pmu_2023.logic.model.User
|
||||||
|
import com.example.pmu_2023.ui.theme.Purple80
|
||||||
|
import com.example.pmu_2023.ui.theme.PurpleGrey80
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun UserProfileView(
|
||||||
|
id: Int,
|
||||||
|
mainViewModel: MainViewModel
|
||||||
|
){
|
||||||
|
var user by remember { mutableStateOf<User?>(null) }
|
||||||
|
LaunchedEffect(Unit){
|
||||||
|
val newData = withContext(Dispatchers.IO){
|
||||||
|
mainViewModel.getUserById(id)
|
||||||
|
}
|
||||||
|
user = newData
|
||||||
|
}
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
) {
|
||||||
|
Box(modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(10.dp)
|
||||||
|
.clip(RoundedCornerShape(10.dp))
|
||||||
|
.background(PurpleGrey80)
|
||||||
|
){
|
||||||
|
Column(Modifier
|
||||||
|
.padding(15.dp)
|
||||||
|
) {
|
||||||
|
user?.let {
|
||||||
|
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
||||||
|
value = it.name, onValueChange = {}, readOnly = true,
|
||||||
|
label = {
|
||||||
|
Text("Имя")
|
||||||
|
},
|
||||||
|
shape = RectangleShape
|
||||||
|
)
|
||||||
|
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
||||||
|
value = it.address, onValueChange = {}, readOnly = true,
|
||||||
|
label = {
|
||||||
|
Text("Адрес")
|
||||||
|
},
|
||||||
|
shape = RectangleShape
|
||||||
|
)
|
||||||
|
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
||||||
|
value = it.phone, onValueChange = {}, readOnly = true,
|
||||||
|
label = {
|
||||||
|
Text("Номер телефона")
|
||||||
|
},
|
||||||
|
shape = RectangleShape
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.example.pmu_2023.logic.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Query
|
||||||
|
import androidx.room.Update
|
||||||
|
import com.example.pmu_2023.logic.model.Parcel
|
||||||
|
import com.example.pmu_2023.logic.model.User
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface ParcelDao {
|
||||||
|
@Insert
|
||||||
|
suspend fun insert(parcel: Parcel)
|
||||||
|
|
||||||
|
@Update
|
||||||
|
suspend fun update(parcel: Parcel)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
suspend fun delete(parcel: Parcel?)
|
||||||
|
|
||||||
|
@Query("select * from parcels where userOwnerId = :uid")
|
||||||
|
fun getAllByUid(uid: Int?): Flow<List<Parcel>>
|
||||||
|
@Query("select * from parcels where parcelId = :id")
|
||||||
|
suspend fun getById(id: Int?): Parcel?
|
||||||
|
}
|
33
app/src/main/java/com/example/pmu_2023/logic/dao/UserDao.kt
Normal file
33
app/src/main/java/com/example/pmu_2023/logic/dao/UserDao.kt
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package com.example.pmu_2023.logic.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Query
|
||||||
|
import androidx.room.Transaction
|
||||||
|
import androidx.room.Update
|
||||||
|
import com.example.pmu_2023.logic.model.User
|
||||||
|
import com.example.pmu_2023.logic.model.UserWithParcels
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface UserDao {
|
||||||
|
@Insert
|
||||||
|
suspend fun insert(user: User)
|
||||||
|
|
||||||
|
@Update
|
||||||
|
suspend fun update(user: User)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
suspend fun delete(user: User)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM users WHERE fio = :name AND password = :passwd")
|
||||||
|
suspend fun getByLogin(name: String, passwd: String): User?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM users WHERE userId = :id")
|
||||||
|
suspend fun getById(id: Int?): User?
|
||||||
|
|
||||||
|
@Transaction
|
||||||
|
@Query("SELECT * FROM users")
|
||||||
|
fun getUserWithParcels(): List<UserWithParcels>
|
||||||
|
}
|
40
app/src/main/java/com/example/pmu_2023/logic/model/Parcel.kt
Normal file
40
app/src/main/java/com/example/pmu_2023/logic/model/Parcel.kt
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package com.example.pmu_2023.logic.model
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.Ignore
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(tableName = "parcels")
|
||||||
|
data class Parcel(
|
||||||
|
@PrimaryKey(autoGenerate = true,)
|
||||||
|
val parcelId: Int?,
|
||||||
|
@ColumnInfo(name = "parcel_name")
|
||||||
|
val name: String,
|
||||||
|
@ColumnInfo(name = "track_number")
|
||||||
|
val trackNumber: String,
|
||||||
|
val status: String,
|
||||||
|
val description: String,
|
||||||
|
val userOwnerId: Int
|
||||||
|
){
|
||||||
|
@Ignore
|
||||||
|
constructor(
|
||||||
|
name: String,
|
||||||
|
trackNumber: String,
|
||||||
|
status: String,
|
||||||
|
description: String,
|
||||||
|
userOwnerId: Int
|
||||||
|
) : this(null, name, trackNumber, status, description, userOwnerId)
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
other as Parcel
|
||||||
|
if (parcelId != other.parcelId) return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return parcelId ?: -1
|
||||||
|
}
|
||||||
|
}
|
37
app/src/main/java/com/example/pmu_2023/logic/model/User.kt
Normal file
37
app/src/main/java/com/example/pmu_2023/logic/model/User.kt
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package com.example.pmu_2023.logic.model
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.Ignore
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(tableName = "users")
|
||||||
|
data class User(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
val userId: Int?,
|
||||||
|
@ColumnInfo(name = "fio")
|
||||||
|
val name: String,
|
||||||
|
val password: String,
|
||||||
|
val address: String,
|
||||||
|
val phone: String
|
||||||
|
){
|
||||||
|
@Ignore
|
||||||
|
constructor(
|
||||||
|
name: String,
|
||||||
|
password: String,
|
||||||
|
address: String,
|
||||||
|
phone: String
|
||||||
|
) : this(null, name, password, address, phone)
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
other as User
|
||||||
|
if (userId != other.userId) return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return userId ?: -1
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.example.pmu_2023.logic.model
|
||||||
|
|
||||||
|
import androidx.room.Embedded
|
||||||
|
import androidx.room.Relation
|
||||||
|
|
||||||
|
|
||||||
|
data class UserWithParcels (
|
||||||
|
@Embedded
|
||||||
|
val user: User,
|
||||||
|
@Relation(
|
||||||
|
parentColumn = "userId",
|
||||||
|
entityColumn = "userOwnerId"
|
||||||
|
)
|
||||||
|
val parcels: List<Parcel>
|
||||||
|
)
|
@ -8,4 +8,6 @@ val Pink80 = Color(0xFFEFB8C8)
|
|||||||
|
|
||||||
val Purple40 = Color(0xFF6650a4)
|
val Purple40 = Color(0xFF6650a4)
|
||||||
val PurpleGrey40 = Color(0xFF625b71)
|
val PurpleGrey40 = Color(0xFF625b71)
|
||||||
val Pink40 = Color(0xFF7D5260)
|
val Pink40 = Color(0xFF7D5260)
|
||||||
|
|
||||||
|
val MainBlue = Color(0xFF6583D2)
|
@ -1,3 +1,16 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">PMU_2023</string>
|
<string name="app_name">PMU_2023</string>
|
||||||
|
<string name="track_number">Номер отслеживания</string>
|
||||||
|
<string name="parcel_name">Название</string>
|
||||||
|
<string name="status">Статус</string>
|
||||||
|
<string name="description">Описание</string>
|
||||||
|
<string name="client">Заказчик</string>
|
||||||
|
<string name="parcel_list_title">Список посылок</string>
|
||||||
|
<string name="parcel_view_title">Информация о посылке</string>
|
||||||
|
<string name="login_title">Авторизация</string>
|
||||||
|
<string name="registration_title">Регистрация</string>
|
||||||
|
<string name="parcel_create_title">Добавить посылку</string>
|
||||||
|
<string name="parcel_update_title">Изменить посылку</string>
|
||||||
|
<string name="user_view_title">Профиль пользователя</string>
|
||||||
|
<string name="quit_title">Выход</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in New Issue
Block a user