229 lines
6.9 KiB
Kotlin
229 lines
6.9 KiB
Kotlin
package com.example.snapandsolve
|
|
|
|
import DamageFilterDialog
|
|
import DamageListDialog
|
|
import MapViewModel
|
|
import android.app.Application
|
|
import androidx.compose.foundation.layout.*
|
|
import androidx.compose.material.icons.Icons
|
|
import androidx.compose.material.icons.filled.Add
|
|
import androidx.compose.material.icons.filled.FilterAlt
|
|
import androidx.compose.material.icons.filled.FormatListNumbered
|
|
import androidx.compose.material.icons.filled.Menu
|
|
import androidx.compose.material3.*
|
|
import androidx.compose.runtime.*
|
|
import androidx.compose.runtime.saveable.rememberSaveable
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.graphics.Color
|
|
import androidx.compose.ui.platform.LocalContext
|
|
import androidx.compose.ui.unit.dp
|
|
import applyDamageFilter
|
|
import com.example.snapandsolve.camera.AlbumViewModel
|
|
import com.example.snapandsolve.ui.theme.*
|
|
import com.example.snapandsolve.ui.theme.composable.SideSlider
|
|
import com.example.snapandsolve.ui.theme.composable.SliderMenuItem
|
|
import com.example.snapandsolve.view.ReportDialog
|
|
import getActiveFilters
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.launch
|
|
|
|
|
|
@Composable
|
|
fun MainScreen(modifier: Modifier = Modifier, application: Application) {
|
|
var showReport by rememberSaveable { mutableStateOf(false) }
|
|
var sliderOpen by rememberSaveable { mutableStateOf(false) }
|
|
val mapViewModel = remember { MapViewModel(application) }
|
|
val albumViewModel = remember { AlbumViewModel(Dispatchers.Default) }
|
|
|
|
fun openReport() {
|
|
showReport = true
|
|
sliderOpen = false
|
|
}
|
|
|
|
fun closeReport() {
|
|
showReport = false
|
|
}
|
|
|
|
LaunchedEffect(mapViewModel.reopenReport) {
|
|
if (mapViewModel.reopenReport) {
|
|
showReport = true
|
|
mapViewModel.consumeReopenReport()
|
|
}
|
|
}
|
|
|
|
|
|
Scaffold(
|
|
modifier = Modifier.fillMaxSize(),
|
|
topBar = { AppTopBar() },
|
|
bottomBar = {
|
|
BottomAppBar(
|
|
modifier = Modifier.height(120.dp),
|
|
containerColor = AppColor,
|
|
) {
|
|
IconButton(onClick = { sliderOpen = !sliderOpen; showReport = false }) {
|
|
Icon(Icons.Default.Menu, contentDescription = "Menu")
|
|
}
|
|
}
|
|
},
|
|
floatingActionButton = {
|
|
LargeFloatingActionButton(
|
|
onClick = {
|
|
mapViewModel.resetDraft()
|
|
mapViewModel.closeFeatureInfo()
|
|
openReport()
|
|
},
|
|
modifier = Modifier.offset(y = 64.dp),
|
|
containerColor = ButtonColor
|
|
) {
|
|
Icon(Icons.Default.Add, contentDescription = "Add")
|
|
}
|
|
},
|
|
floatingActionButtonPosition = FabPosition.Center,
|
|
) { innerPadding ->
|
|
ContentScreen(
|
|
modifier = Modifier.padding(innerPadding),
|
|
mapViewModel = mapViewModel,
|
|
albumViewModel = albumViewModel,
|
|
showReport = showReport,
|
|
sliderOpen = sliderOpen,
|
|
onDismissReport = ::closeReport
|
|
)
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
fun ContentScreen(
|
|
modifier: Modifier = Modifier,
|
|
mapViewModel: MapViewModel,
|
|
albumViewModel: AlbumViewModel,
|
|
showReport: Boolean,
|
|
sliderOpen: Boolean,
|
|
onDismissReport: () -> Unit
|
|
) {
|
|
val context = LocalContext.current
|
|
val coroutineScope = rememberCoroutineScope()
|
|
|
|
// NEU: State für Filter-Dialog
|
|
var showFilterDialog by remember { mutableStateOf(false) }
|
|
|
|
var showDamageList by remember { mutableStateOf(false) }
|
|
|
|
Box(modifier = modifier.fillMaxSize()) {
|
|
// Map
|
|
MapSegment(
|
|
modifier = Modifier.fillMaxSize(),
|
|
mapViewModel = mapViewModel
|
|
)
|
|
|
|
// Dialog
|
|
if (showDamageList) {
|
|
DamageListDialog(
|
|
onDismiss = { showDamageList = false },
|
|
onDamageClick = { feature ->
|
|
mapViewModel.selectedFeature = feature
|
|
mapViewModel.showFeatureInfo = true
|
|
},
|
|
mapViewModel = mapViewModel
|
|
)
|
|
}
|
|
|
|
// Report Overlay
|
|
if (showReport) {
|
|
ReportDialog(
|
|
onCancel = onDismissReport,
|
|
onClose = onDismissReport,
|
|
viewModel = albumViewModel,
|
|
mapViewModel = mapViewModel
|
|
)
|
|
}
|
|
|
|
// Feature Info Dialog
|
|
if (mapViewModel.showFeatureInfo) {
|
|
FeatureInfoDialog(
|
|
feature = mapViewModel.selectedFeature,
|
|
onDismiss = { mapViewModel.closeFeatureInfo() },
|
|
onRate = { feature, isPositive ->
|
|
coroutineScope.launch {
|
|
mapViewModel.updateFeatureRating(feature, isPositive, context)
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
// Filter Dialog - NEU!
|
|
if (showFilterDialog) {
|
|
DamageFilterDialog(
|
|
damageTypes = MapViewModel.DAMAGE_TYPES, // <-- Nutzt zentrale Liste
|
|
currentFilters = mapViewModel.getActiveFilters(),
|
|
onDismiss = { showFilterDialog = false },
|
|
onApplyFilter = { selectedTypes, startDate, endDate ->
|
|
coroutineScope.launch {
|
|
mapViewModel.applyDamageFilter(selectedTypes, startDate, endDate)
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
// Side Slider
|
|
SideSlider(visible = sliderOpen) {
|
|
Text(
|
|
"Menü",
|
|
style = MaterialTheme.typography.titleMedium,
|
|
modifier = Modifier.padding(bottom = 12.dp)
|
|
)
|
|
|
|
SliderMenuItem(
|
|
text = "Schäden filtern",
|
|
icon = Icons.Default.FilterAlt,
|
|
onClick = {
|
|
showFilterDialog = true // <-- Öffnet Filter-Dialog
|
|
}
|
|
)
|
|
|
|
SliderMenuItem(
|
|
text = "Schadensliste",
|
|
icon = Icons.Default.FormatListNumbered,
|
|
onClick = { showDamageList = true }
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
@Composable
|
|
fun AppTopBar(
|
|
modifier: Modifier = Modifier
|
|
) {
|
|
MediumTopAppBar(
|
|
title = {
|
|
Text("Scan And Solve")
|
|
},
|
|
colors = TopAppBarDefaults.mediumTopAppBarColors(
|
|
containerColor = AppColor,
|
|
titleContentColor = Color.White
|
|
)
|
|
)
|
|
}
|
|
|
|
/*
|
|
suspend fun loadFirstAttachmentBitmap(
|
|
feature: ArcGISFeature
|
|
): ImageBitmap? {
|
|
|
|
// Feature muss geladen sein
|
|
feature.load().getOrThrow()
|
|
|
|
// Attachments abrufen
|
|
val attachments = feature.fetchAttachments().getOrThrow()
|
|
|
|
val first = attachments.firstOrNull() ?: return null
|
|
|
|
// Attachment-Daten laden
|
|
val data = first.fetchData().getOrThrow()
|
|
|
|
val bitmap = BitmapFactory.decodeByteArray(data, 0, data.size)
|
|
return bitmap.asImageBitmap()
|
|
}
|
|
*/
|
|
|