Files
SnapAndSolve/app/src/main/java/com/example/snapandsolve/MainScreen.kt
fr2651 7781551e02 status hinzugefügt
regelbasiertes styling
architektur überarbeitet
2026-02-06 15:34:39 +01:00

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()
}
*/