sin-titulo

Pasted Nov 8, 2026, 10:38 PM1 file1,467 lines

Scan to open on your phone

Point a camera at the QR code - it opens this exact paste, no app needed.

https://codepastes.com/zzgs9hfsgq9p8adk
sin-titulo

package com.negocio.desinfectantes.ui.produccion

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.background
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.Alignment
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType
import com.negocio.desinfectantes.data.*

private val Navy = Color(0xFF101D35)
private val CardBlue = Color(0xFF1B2D4A)
private val AccentBlue = Color(0xFF2585F5)
private val SoftBlue = Color(0xFFA9BEDB)

@Composable
fun ProduccionScreen(
    modifier: Modifier = Modifier,
    productos: List<ProductoEntity>,
    aromas: List<AromaEntity>,
    presentaciones: List<PresentacionEntity>,
    onVolver: () -> Unit,
    onGuardar: (PresentacionEntity, Int, Int, Int) -> Unit
) {
    var productoSeleccionado by remember {
        mutableStateOf<ProductoEntity?>(null)
    }

    var aromaSeleccionado by remember {
        mutableStateOf<AromaEntity?>(null)
    }

    var presentacionSeleccionada by remember {
        mutableStateOf<PresentacionEntity?>(null)
    }

    var cantidadProducida by remember { mutableStateOf("") }
    var cantidadBarrancas by remember { mutableStateOf("") }
    var cantidadValledupar by remember { mutableStateOf("") }

    var menuProducto by remember { mutableStateOf(false) }
    var menuAroma by remember { mutableStateOf(false) }
    var menuPresentacion by remember { mutableStateOf(false) }

    val aromasDisponibles = aromas.filter {
        it.productoId == productoSeleccionado?.id && it.activo
    }

    val presentacionesDisponibles = presentaciones.filter {
        it.aromaId == aromaSeleccionado?.id && it.activo
    }

    val producidas = cantidadProducida.toIntOrNull()
    val barrancas = cantidadBarrancas.toIntOrNull()
    val valledupar = cantidadValledupar.toIntOrNull()

    val totalDistribuido =
        (barrancas ?: 0) + (valledupar ?: 0)

    val datosCompletos =
        presentacionSeleccionada != null &&
                producidas != null && producidas > 0 &&
                barrancas != null && valledupar != null &&
                barrancas >= 0 && valledupar >= 0

    val distribucionCorrecta =
        datosCompletos && totalDistribuido == producidas

    val mensajeValidacion = when {
        cantidadProducida.isNotEmpty() && (producidas == null || producidas <= 0) ->
            "Escribe una cantidad fabricada válida."

        cantidadBarrancas.isNotEmpty() && barrancas == null ->
            "La cantidad de Barrancas no es válida."

        cantidadValledupar.isNotEmpty() && valledupar == null ->
            "La cantidad de Valledupar no es válida."

        datosCompletos && totalDistribuido > producidas!! ->
            "Has distribuido ${totalDistribuido - producidas} unidades de más."

        datosCompletos && totalDistribuido < producidas!! ->
            "Faltan ${producidas - totalDistribuido} unidades por distribuir."

        distribucionCorrecta ->
            null

        else ->
            null
    }

    Column(
        modifier = modifier
            .fillMaxSize()
            .background(Navy)
            .verticalScroll(rememberScrollState())
            .padding(20.dp)
    ) {

        Row(
            verticalAlignment = Alignment.CenterVertically
        ) {
            TextButton(onClick = onVolver) {
                Text("← Volver", color = SoftBlue)
            }
        }

        Text(
            "Nueva producción",
            color = Color.White,
            style = MaterialTheme.typography.headlineMedium,
            fontWeight = FontWeight.Bold
        )

        Spacer(modifier = Modifier.height(8.dp))

        Text(
            "Registra lo que fabricaste y distribuye las unidades entre tus sedes.",
            color = SoftBlue,
            style = MaterialTheme.typography.bodyMedium
        )

        Spacer(modifier = Modifier.height(24.dp))

        // PRODUCTO

        Text("1. Seleccionar producto", color = Color.White)

        Spacer(modifier = Modifier.height(8.dp))

        Box {
            OutlinedButton(
                onClick = { menuProducto = true },
                modifier = Modifier.fillMaxWidth(),
                shape = RoundedCornerShape(12.dp)
            ) {
                Text(
                    productoSeleccionado?.nombre ?: "Elegir producto",
                    modifier = Modifier.weight(1f)
                )
                Text("▼")
            }

            DropdownMenu(
                expanded = menuProducto,
                onDismissRequest = { menuProducto = false }
            ) {
                productos.filter { it.activo }.forEach { producto ->
                    DropdownMenuItem(
                        text = { Text(producto.nombre) },
                        onClick = {
                            productoSeleccionado = producto
                            aromaSeleccionado = null
                            presentacionSeleccionada = null
                            menuProducto = false
                        }
                    )
                }
            }
        }

        Spacer(modifier = Modifier.height(18.dp))

        // AROMA

        Text("2. Seleccionar aroma", color = Color.White)

        Spacer(modifier = Modifier.height(8.dp))

        Box {
            OutlinedButton(
                onClick = { menuAroma = true },
                enabled = productoSeleccionado != null,
                modifier = Modifier.fillMaxWidth(),
                shape = RoundedCornerShape(12.dp)
            ) {
                Text(
                    aromaSeleccionado?.nombre ?: "Elegir aroma",
                    modifier = Modifier.weight(1f)
                )
                Text("▼")
            }

            DropdownMenu(
                expanded = menuAroma,
                onDismissRequest = { menuAroma = false }
            ) {
                aromasDisponibles.forEach { aroma ->
                    DropdownMenuItem(
                        text = { Text(aroma.nombre) },
                        onClick = {
                            aromaSeleccionado = aroma
                            presentacionSeleccionada = null
                            menuAroma = false
                        }
                    )
                }
            }
        }

        Spacer(modifier = Modifier.height(18.dp))

        // PRESENTACION

        Text("3. Seleccionar presentación", color = Color.White)

        Spacer(modifier = Modifier.height(8.dp))

        Box {
            OutlinedButton(
                onClick = { menuPresentacion = true },
                enabled = aromaSeleccionado != null,
                modifier = Modifier.fillMaxWidth(),
                shape = RoundedCornerShape(12.dp)
            ) {
                Text(
                    presentacionSeleccionada?.nombre
                        ?: "Elegir presentación",
                    modifier = Modifier.weight(1f)
                )
                Text("▼")
            }

            DropdownMenu(
                expanded = menuPresentacion,
                onDismissRequest = { menuPresentacion = false }
            ) {
                presentacionesDisponibles.forEach { presentacion ->
                    DropdownMenuItem(
                        text = {
                            Text(
                                "${presentacion.nombre} • ${presentacion.contenidoMl} ml"
                            )
                        },
                        onClick = {
                            presentacionSeleccionada = presentacion
                            menuPresentacion = false
                        }
                    )
                }
            }
        }

        Spacer(modifier = Modifier.height(24.dp))

        // CANTIDAD FABRICADA

        Text(
            "4. Cantidad fabricada",
            color = Color.White,
            fontWeight = FontWeight.Bold
        )

        Spacer(modifier = Modifier.height(8.dp))

        OutlinedTextField(
            value = cantidadProducida,
            onValueChange = {
                cantidadProducida = it.filter { c -> c.isDigit() }
            },
            modifier = Modifier.fillMaxWidth(),
            placeholder = { Text("Ejemplo: 100") },
            label = { Text("Unidades fabricadas") },
            keyboardOptions = KeyboardOptions(
                keyboardType = KeyboardType.Number
            ),
            singleLine = true
        )

        Spacer(modifier = Modifier.height(24.dp))

        // DISTRIBUCION

        Text(
            "5. Distribución por sede",
            color = Color.White,
            fontWeight = FontWeight.Bold
        )

        Spacer(modifier = Modifier.height(8.dp))

        Card(
            colors = CardDefaults.cardColors(
                containerColor = CardBlue
            ),
            shape = RoundedCornerShape(16.dp)
        ) {
            Column(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(16.dp)
            ) {

                Text(
                    "Barrancas",
                    color = Color.White,
                    fontWeight = FontWeight.Medium
                )

                Spacer(modifier = Modifier.height(6.dp))

                OutlinedTextField(
                    value = cantidadBarrancas,
                    onValueChange = {
                        cantidadBarrancas = it.filter { c -> c.isDigit() }
                    },
                    modifier = Modifier.fillMaxWidth(),
                    placeholder = { Text("Unidades para Barrancas") },
                    keyboardOptions = KeyboardOptions(
                        keyboardType = KeyboardType.Number
                    ),
                    singleLine = true
                )

                Spacer(modifier = Modifier.height(18.dp))

                Text(
                    "Valledupar",
                    color = Color.White,
                    fontWeight = FontWeight.Medium
                )

                Spacer(modifier = Modifier.height(6.dp))

                OutlinedTextField(
                    value = cantidadValledupar,
                    onValueChange = {
                        cantidadValledupar = it.filter { c -> c.isDigit() }
                    },
                    modifier = Modifier.fillMaxWidth(),
                    placeholder = { Text("Unidades para Valledupar") },
                    keyboardOptions = KeyboardOptions(
                        keyboardType = KeyboardType.Number
                    ),
                    singleLine = true
                )
            }
        }

        Spacer(modifier = Modifier.height(18.dp))

        // RESUMEN DE DISTRIBUCION

        Text(
            "Total distribuido: $totalDistribuido unidades",
            color = SoftBlue,
            fontWeight = FontWeight.Medium
        )

        Spacer(modifier = Modifier.height(10.dp))

        if (mensajeValidacion != null) {
            Text(
                "⚠ $mensajeValidacion",
                color = Color(0xFFFF7777),
                style = MaterialTheme.typography.bodyMedium,
                fontWeight = FontWeight.Medium
            )
        }

        if (distribucionCorrecta) {
            Text(
                "✓ Distribución correcta. Todas las unidades están asignadas.",
                color = Color(0xFF65D69A),
                style = MaterialTheme.typography.bodyMedium,
                fontWeight = FontWeight.Medium
            )
        }

        Spacer(modifier = Modifier.height(20.dp))

        // GUARDAR PRODUCCION

        Button(
            onClick = {
                if (distribucionCorrecta) {
                    onGuardar(
                        presentacionSeleccionada!!,
                        producidas!!,
                        barrancas!!,
                        valledupar!!
                    )
                }
            },
            enabled = distribucionCorrecta,
            modifier = Modifier
                .fillMaxWidth()
                .height(54.dp),
            shape = RoundedCornerShape(14.dp),
            colors = ButtonDefaults.buttonColors(
                containerColor = AccentBlue,
                disabledContainerColor = Color(0xFF34445D)
            )
        ) {
            Text(
                "Guardar producción",
                fontWeight = FontWeight.Bold
            )
        }

        Spacer(modifier = Modifier.height(30.dp))
    }
}


package com.negocio.desinfectantes

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.negocio.desinfectantes.ui.theme.DesinfectantesAppTheme
import com.negocio.desinfectantes.ui.productos.ProductosScreen
import com.negocio.desinfectantes.ui.productos.AgregarProductoScreen
import com.negocio.desinfectantes.ui.productos.AromasScreen
import com.negocio.desinfectantes.ui.inactivos.RegistrosInactivosScreen
import androidx.compose.ui.platform.LocalContext
import com.negocio.desinfectantes.data.DatabaseProvider
import com.negocio.desinfectantes.data.ProductoEntity
import com.negocio.desinfectantes.data.AromaEntity
import com.negocio.desinfectantes.data.PresentacionEntity
import kotlinx.coroutines.launch
import java.util.UUID
import androidx.compose.runtime.collectAsState
import com.negocio.desinfectantes.ui.productos.AgregarAromaScreen
import com.negocio.desinfectantes.ui.productos.PresentacionesScreen
import com.negocio.desinfectantes.ui.productos.AgregarPresentacionScreen
import com.negocio.desinfectantes.ui.productos.EditarPresentacionScreen
import com.negocio.desinfectantes.ui.produccion.ProduccionScreen
import com.negocio.desinfectantes.ui.inventario.InventarioScreen
import com.negocio.desinfectantes.data.ProduccionEntity
import com.negocio.desinfectantes.ui.clientes.ClienteScreen
import com.negocio.desinfectantes.data.ClienteEntity
import com.negocio.desinfectantes.data.DistribucionProduccionEntity
import com.negocio.desinfectantes.data.InventarioEntity
import com.negocio.desinfectantes.data.MovimientoInventarioEntity
import com.negocio.desinfectantes.ui.ventas.VentaScreen
import com.negocio.desinfectantes.ui.ventas.HistorialVentasScreen
import com.negocio.desinfectantes.ui.reportes.ReportesScreen
import java.util.Calendar
import java.util.Locale
import java.text.NumberFormat
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.res.painterResource
import androidx.compose.foundation.Image
import androidx.compose.ui.graphics.ColorFilter
private val Navy = Color(0xFF101D35)
private val CardBlue = Color(0xFF1B2D4A)
private val AccentBlue = Color(0xFF2585F5)
private val SoftBlue = Color(0xFFA9BEDB)
private val White = Color(0xFFFFFFFF)

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()

        setContent {
            DesinfectantesAppTheme {
                PrestigeCleanApp()
            }
        }
    }
}

@Composable
fun PrestigeCleanApp() {
    var selectedTab by remember { mutableStateOf("Inicio") }
    var ventaInicialId by remember {
        mutableStateOf<String?>(null)
    }
    var mostrarFormularioProducto by remember { mutableStateOf(false) }
    var mostrarRegistrosInactivos by remember {
        mutableStateOf(false)
    }
    var productoSeleccionado by remember {
        mutableStateOf<ProductoEntity?>(null)
    }
    var mostrarFormularioAroma by remember {
        mutableStateOf(false)
    }
    var aromaSeleccionado by remember {
        mutableStateOf<AromaEntity?>(null)
    }
    var mostrarFormularioPresentacion by remember {
        mutableStateOf(false)
    }
    var mensajeAroma by remember {
        mutableStateOf<String?>(null)
    }
    var presentacionSeleccionada by remember {
        mutableStateOf<PresentacionEntity?>(null)
    }
    val context = LocalContext.current

    val scope = rememberCoroutineScope()

    val productoDao = remember {
        DatabaseProvider.obtenerBaseDatos(context).productoDao()
    }
    val productos by productoDao.obtenerProductos()
        .collectAsState(initial = emptyList())
    val productosInactivos by productoDao.obtenerProductosInactivos()
        .collectAsState(initial = emptyList())
    val aromasInactivos by productoDao.obtenerTodosAromasInactivos()
        .collectAsState(initial = emptyList())

    val presentacionesInactivas by productoDao.obtenerTodasPresentacionesInactivas()
        .collectAsState(initial = emptyList())
    val todosProductos by productoDao.obtenerTodosProductos()
        .collectAsState(initial = emptyList())

    val todosAromas by productoDao.obtenerTodosAromas()
        .collectAsState(initial = emptyList())
    val aromasFlow = remember(productoSeleccionado?.id) {
        productoSeleccionado?.let {
            productoDao.obtenerAromas(it.id)
        } ?: kotlinx.coroutines.flow.flowOf(emptyList())
    }

    val aromas by aromasFlow.collectAsState(initial = emptyList())
    val presentacionesFlow = remember(aromaSeleccionado?.id) {
        aromaSeleccionado?.let {
            productoDao.obtenerPresentaciones(it.id)
        } ?: kotlinx.coroutines.flow.flowOf(emptyList())
    }

    val presentaciones by presentacionesFlow.collectAsState(initial = emptyList())

    val todasPresentacionesActivas by productoDao
        .obtenerTodasPresentacionesActivas()
        .collectAsState(initial = emptyList())
    val inventarios by productoDao
        .obtenerTodoInventario()
        .collectAsState(initial = emptyList())
    val clientes by productoDao.obtenerClientes()
        .collectAsState(initial = emptyList())
    val ventas by productoDao.obtenerVentas()
        .collectAsState(initial = emptyList())
    val todosLosPagos by productoDao.obtenerTodosLosPagos()
        .collectAsState(initial = emptyList())

    // FECHAS DEL DIA ACTUAL
    var inicioDia by remember {
        mutableStateOf(
            Calendar.getInstance().apply {
                set(Calendar.HOUR_OF_DAY, 0)
                set(Calendar.MINUTE, 0)
                set(Calendar.SECOND, 0)
                set(Calendar.MILLISECOND, 0)
            }.timeInMillis
        )
    }

    val finDia = remember(inicioDia) {
        Calendar.getInstance().apply {
            timeInMillis = inicioDia
            add(Calendar.DAY_OF_MONTH, 1)
        }.timeInMillis
    }

// ACTUALIZAR AUTOMATICAMENTE AL LLEGAR LA MEDIANOCHE
    LaunchedEffect(Unit) {
        while (true) {
            val ahora = Calendar.getInstance()

            val proximaMedianoche = (ahora.clone() as Calendar).apply {
                set(Calendar.HOUR_OF_DAY, 0)
                set(Calendar.MINUTE, 0)
                set(Calendar.SECOND, 0)
                set(Calendar.MILLISECOND, 0)
                add(Calendar.DAY_OF_MONTH, 1)
            }.timeInMillis

            val tiempoEspera = proximaMedianoche - System.currentTimeMillis()

            kotlinx.coroutines.delay(tiempoEspera.coerceAtLeast(1L))

            inicioDia = Calendar.getInstance().apply {
                set(Calendar.HOUR_OF_DAY, 0)
                set(Calendar.MINUTE, 0)
                set(Calendar.SECOND, 0)
                set(Calendar.MILLISECOND, 0)
            }.timeInMillis
        }
    }

// ESTADISTICAS DE ROOM

    val ventasDelDia by productoDao
        .obtenerVentasDelDia(inicioDia, finDia)
        .collectAsState(initial = 0.0)

    val dineroRecibidoHoy by productoDao
        .obtenerDineroRecibidoDelDia(inicioDia, finDia)
        .collectAsState(initial = 0.0)

    val totalPorCobrar by productoDao
        .obtenerTotalPorCobrar()
        .collectAsState(initial = 0.0)

    val inventarioDisponible by productoDao
        .obtenerInventarioDisponible()
        .collectAsState(initial = 0)

// FORMATO DE PESOS COLOMBIANOS

    val formatoPesos = remember {
        NumberFormat.getCurrencyInstance(Locale("es", "CO")).apply {
            maximumFractionDigits = 0
            minimumFractionDigits = 0
        }
    }

    Scaffold(
        containerColor = Navy,
        bottomBar = {
            NavigationBar(
                containerColor = CardBlue,
                contentColor = White
            ) {
                NavigationBarItem(
                    selected = selectedTab == "Inicio",
                    onClick = { selectedTab = "Inicio" },
                    icon = { Text("⌂", fontSize = 22.sp) },
                    label = { Text("Inicio") },
                    colors = navColors()
                )

                NavigationBarItem(
                    selected = selectedTab == "Ventas",
                    onClick = { selectedTab = "Ventas" },
                    icon = { Text("$", fontSize = 22.sp) },
                    label = { Text("Ventas") },
                    colors = navColors()
                )

                NavigationBarItem(
                    selected = selectedTab == "Productos",
                    onClick = { selectedTab = "Productos" },
                    icon = {
                        Icon(
                            painter = painterResource(id = R.drawable.ic_bottle),
                            contentDescription = "Productos",
                            tint = navColors().unselectedIconColor
                        )
                    },
                    label = { Text("Productos") },
                    colors = navColors()
                )

                NavigationBarItem(
                    selected = selectedTab == "Clientes",
                    onClick = { selectedTab = "Clientes" },
                    icon = { Text("♙", fontSize = 22.sp) },
                    label = { Text("Clientes") },
                    colors = navColors()
                )

                NavigationBarItem(
                    selected = selectedTab == "Reportes",
                    onClick = { selectedTab = "Reportes" },
                    icon = { Text("▤", fontSize = 22.sp) },
                    label = { Text("Reportes") },
                    colors = navColors()
                )
            }
        }
    ) { innerPadding ->

        when (selectedTab) {
            "Inicio" -> DashboardScreen(
                modifier = Modifier.padding(innerPadding),
                onNavigate = { selectedTab = it },
                ventasHoy = formatoPesos.format(ventasDelDia),
                dineroRecibido = formatoPesos.format(dineroRecibidoHoy),
                porCobrar = formatoPesos.format(totalPorCobrar),
                inventario = inventarioDisponible.toString()
            )

            "Ventas" -> VentaScreen(
                modifier = Modifier.padding(innerPadding),
                clientes = clientes,
                productos = productos,
                aromas = todosAromas.filter { it.activo },
                presentaciones = todasPresentacionesActivas,
                productoDao = productoDao,
                onVolver = { selectedTab = "Inicio" }
            )

            "Produccion" -> ProduccionScreen(
                modifier = Modifier.padding(innerPadding),
                productos = productos,
                aromas = todosAromas.filter { it.activo },
                presentaciones = todasPresentacionesActivas,
                onVolver = {
                    selectedTab = "Inicio"
                },
                onGuardar = { presentacion, producidas, barrancas, valledupar ->

                    scope.launch {

                        val fecha = System.currentTimeMillis()
                        val produccionId = UUID.randomUUID().toString()

                        // Crear el registro del lote fabricado.
                        val nuevaProduccion = ProduccionEntity(
                            id = produccionId,
                            presentacionId = presentacion.id,
                            cantidadProducida = producidas,
                            fechaCreacion = fecha
                        )

                        val distribuciones = mutableListOf<DistribucionProduccionEntity>()
                        val inventarios = mutableListOf<InventarioEntity>()
                        val movimientos = mutableListOf<MovimientoInventarioEntity>()

                        // Preparar la distribución de las dos sedes.
                        val sedes = listOf(
                            "Barrancas" to barrancas,
                            "Valledupar" to valledupar
                        )

                        sedes.forEach { (sede, cantidad) ->

                            if (cantidad > 0) {

                                // Registrar la cantidad enviada a esta sede.
                                distribuciones.add(
                                    DistribucionProduccionEntity(
                                        id = UUID.randomUUID().toString(),
                                        produccionId = produccionId,
                                        sede = sede,
                                        cantidad = cantidad,
                                        fechaCreacion = fecha
                                    )
                                )

                                // Consultar si ya existe inventario para esa sede.
                                val inventarioActual = productoDao.buscarInventario(
                                    presentacionId = presentacion.id,
                                    sede = sede
                                )

                                // Sumar las nuevas unidades a las existentes.
                                val inventarioActualizado = if (inventarioActual != null) {

                                    inventarioActual.copy(
                                        cantidadDisponible =
                                            inventarioActual.cantidadDisponible + cantidad,
                                        fechaActualizacion = fecha
                                    )

                                } else {

                                    InventarioEntity(
                                        id = UUID.randomUUID().toString(),
                                        presentacionId = presentacion.id,
                                        sede = sede,
                                        cantidadDisponible = cantidad,
                                        cantidadReservada = 0,
                                        fechaActualizacion = fecha
                                    )
                                }

                                inventarios.add(inventarioActualizado)

                                // Registrar el movimiento de entrada.
                                movimientos.add(
                                    MovimientoInventarioEntity(
                                        id = UUID.randomUUID().toString(),
                                        presentacionId = presentacion.id,
                                        sede = sede,
                                        tipoMovimiento = "PRODUCCION",
                                        cantidad = cantidad,
                                        referenciaId = produccionId,
                                        observacion = "Entrada por producción",
                                        fechaCreacion = fecha
                                    )
                                )
                            }
                        }

                        // Guardar todo en una sola transacción.
                        productoDao.registrarProduccionCompleta(
                            produccion = nuevaProduccion,
                            distribuciones = distribuciones,
                            inventarios = inventarios,
                            movimientos = movimientos
                        )

                        selectedTab = "Inicio"
                    }
                }
            )

            "Productos" -> {
                if (mostrarRegistrosInactivos) {

                    RegistrosInactivosScreen(
                        productos = productosInactivos,
                        aromas = aromasInactivos,
                        presentaciones = presentacionesInactivas,
                        todosProductos = todosProductos,
                        todosAromas = todosAromas,
                        onVolver = {
                            mostrarRegistrosInactivos = false
                        },
                        onReactivarProducto = { producto ->
                            scope.launch {
                                productoDao.reactivarProducto(producto.id)
                            }
                        },
                        onReactivarAroma = { aroma ->
                            scope.launch {
                                productoDao.reactivarAroma(aroma.id)
                            }
                        },
                        onReactivarPresentacion = { presentacion ->
                            scope.launch {
                                productoDao.reactivarPresentacion(presentacion.id)
                            }
                        }
                    )
                } else if (mostrarFormularioProducto) {

                    AgregarProductoScreen(
                        onVolver = {
                            mostrarFormularioProducto = false
                        },
                        onGuardar = { nombre, tipo, aroma ->

                            scope.launch {
                                val productoId = UUID.randomUUID().toString()

                                val producto = ProductoEntity(
                                    id = productoId,
                                    nombre = nombre,
                                    tipo = tipo
                                )

                                val nuevoAroma = AromaEntity(
                                    id = UUID.randomUUID().toString(),
                                    productoId = productoId,
                                    nombre = aroma
                                )

                                productoDao.guardarProducto(producto)
                                productoDao.guardarAroma(nuevoAroma)

                                mostrarFormularioProducto = false
                            }
                        }
                    )

                } else if (productoSeleccionado != null) {

                    if (mostrarFormularioAroma) {

                        AgregarAromaScreen(
                            nombreProducto = productoSeleccionado!!.nombre,

                            onVolver = {
                                mostrarFormularioAroma = false
                            },

                            onGuardar = { nombreAroma ->
                                scope.launch {
                                    val nuevoAroma = AromaEntity(
                                        id = UUID.randomUUID().toString(),
                                        productoId = productoSeleccionado!!.id,
                                        nombre = nombreAroma
                                    )

                                    productoDao.guardarAroma(nuevoAroma)

                                    mostrarFormularioAroma = false
                                }
                            }
                        )

                    } else if (aromaSeleccionado != null) {
                        if (presentacionSeleccionada != null) {
                            EditarPresentacionScreen(
                                nombreProducto = productoSeleccionado!!.nombre,
                                nombreAroma = aromaSeleccionado!!.nombre,
                                presentacion = presentacionSeleccionada!!,
                                onVolver = {
                                    presentacionSeleccionada = null
                                },
                                onGuardar = { nombre, contenido, precio ->
                                    scope.launch {
                                        val presentacionActualizada = presentacionSeleccionada!!.copy(
                                            nombre = nombre,
                                            contenidoMl = contenido,
                                            precio = precio
                                        )

                                        productoDao.guardarPresentacion(presentacionActualizada)

                                        presentacionSeleccionada = null
                                    }
                                },
                                onEliminar = {
                                    scope.launch {
                                        val idPresentacion = presentacionSeleccionada!!.id

                                        val existencias =
                                            productoDao.contarExistenciasPresentacion(idPresentacion)

                                        if (existencias > 0) {
                                            mensajeAroma =
                                                "No se puede eliminar esta presentación porque todavía tiene $existencias unidades en inventario."
                                        } else {
                                            productoDao.eliminarPresentacion(idPresentacion)
                                        }

                                        presentacionSeleccionada = null
                                    }
                                }
                            )
                        } else if (mostrarFormularioPresentacion) {

                            AgregarPresentacionScreen(
                                nombreProducto = productoSeleccionado!!.nombre,
                                nombreAroma = aromaSeleccionado!!.nombre,

                                onVolver = {
                                    mostrarFormularioPresentacion = false
                                },

                                onGuardar = { nombre, contenido, precio ->
                                    scope.launch {
                                        val nuevaPresentacion = PresentacionEntity(
                                            id = UUID.randomUUID().toString(),
                                            aromaId = aromaSeleccionado!!.id,
                                            nombre = nombre,
                                            contenidoMl = contenido,
                                            precio = precio
                                        )

                                        productoDao.guardarPresentacion(nuevaPresentacion)

                                        mostrarFormularioPresentacion = false
                                    }
                                }
                            )

                        } else {
                            PresentacionesScreen(
                                nombreProducto = productoSeleccionado!!.nombre,
                                nombreAroma = aromaSeleccionado!!.nombre,
                                presentaciones = presentaciones,
                                onVolver = {
                                    aromaSeleccionado = null
                                },
                                onAgregarPresentacion = {
                                    mostrarFormularioPresentacion = true
                                },
                                onSeleccionarPresentacion = { presentacion ->
                                    presentacionSeleccionada = presentacion
                                }
                            )
                        }
                    } else {

                        AromasScreen(
                            nombreProducto = productoSeleccionado!!.nombre,
                            aromas = aromas,

                            onVolver = {
                                productoSeleccionado = null
                            },

                            onAgregarAroma = {
                                mostrarFormularioAroma = true
                            },

                            onSeleccionarAroma = { aroma ->
                                aromaSeleccionado = aroma
                            },

                            onEliminarAroma = { aroma ->
                                scope.launch {
                                    val cantidad = productoDao.contarPresentacionesDeAroma(aroma.id)

                                    if (cantidad == 0) {
                                        productoDao.eliminarAroma(aroma.id)
                                    } else {
                                        mensajeAroma =
                                            "No se puede eliminar este aroma porque tiene $cantidad presentación(es) registradas."
                                    }
                                }
                            },

                            onEditarAroma = { aroma, nuevoNombre ->
                                scope.launch {
                                    productoDao.actualizarAroma(
                                        aromaId = aroma.id,
                                        nuevoNombre = nuevoNombre
                                    )
                                }
                            }
                        )
                    }
                } else {

                    ProductosScreen(
                        modifier = Modifier.padding(innerPadding),
                        productos = productos,
                        onAgregarProducto = {
                            mostrarFormularioProducto = true
                        },
                        onVerInactivos = {
                            mostrarRegistrosInactivos = true
                        },
                        onSeleccionarProducto = { producto ->
                            productoSeleccionado = producto
                        },
                        onDesactivarProducto = { producto ->
                            scope.launch {
                                val cantidadAromas =
                                    productoDao.contarAromasDeProducto(producto.id)

                                if (cantidadAromas > 0) {
                                    mensajeAroma =
                                        "No se puede desactivar este producto porque tiene $cantidadAromas aroma(s) registrados."
                                } else {
                                    productoDao.desactivarProducto(producto.id)
                                }
                            }
                        },
                        onEditarProducto = { producto, nuevoNombre, nuevoTipo ->
                            scope.launch {
                                productoDao.actualizarProducto(
                                    productoId = producto.id,
                                    nombre = nuevoNombre,
                                    tipo = nuevoTipo
                                )
                            }
                        }
                    )
                }
            }

            "Inventario" -> InventarioScreen(
                modifier = Modifier.padding(innerPadding),
                productos = productos,
                aromas = todosAromas,
                presentaciones = todasPresentacionesActivas,
                inventarios = inventarios,
                onVolver = {
                    selectedTab = "Inicio"
                }
            )


            "Clientes" -> ClienteScreen(
                modifier = Modifier.padding(innerPadding),
                clientes = clientes,
                onGuardar = { cliente ->
                    scope.launch {
                        productoDao.guardarCliente(cliente)
                    }
                },
                onDesactivar = { clienteId ->
                    scope.launch {
                        productoDao.desactivarCliente(clienteId)
                    }
                },
                onVolver = {
                    selectedTab = "Inicio"
                }
            )
            "Historial" -> HistorialVentasScreen(
                modifier = Modifier.padding(innerPadding),
                ventas = ventas,
                clientes = clientes,
                productos = todosProductos,
                aromas = todosAromas,
                presentaciones = todasPresentacionesActivas + presentacionesInactivas,
                productoDao = productoDao,
                onVolver = {
                    ventaInicialId = null
                    selectedTab = "Inicio"
                },
                ventaInicialId = ventaInicialId
            )

            "Reportes" -> ReportesScreen(
                modifier = Modifier.padding(innerPadding),
                ventas = ventas,
                clientes = clientes,
                pagos = todosLosPagos,
                onAbrirVenta = { ventaId ->
                    ventaInicialId = ventaId
                    selectedTab = "Historial"
                }
            )
        }
    }

    if (mensajeAroma != null) {
        AlertDialog(
            onDismissRequest = {
                mensajeAroma = null
            },
            title = {
                Text("No se puede eliminar")
            },
            text = {
                Text(mensajeAroma!!)
            },
            confirmButton = {
                TextButton(
                    onClick = {
                        mensajeAroma = null
                    }
                ) {
                    Text("Entendido")
                }
            }
        )
    }
}

@Composable
fun navColors() = NavigationBarItemDefaults.colors(
    selectedIconColor = AccentBlue,
    selectedTextColor = AccentBlue,
    indicatorColor = Color(0xFF263F62),
    unselectedIconColor = SoftBlue,
    unselectedTextColor = SoftBlue
)

@Composable
fun DashboardScreen(
    modifier: Modifier = Modifier,
    onNavigate: (String) -> Unit,
    ventasHoy: String,
    dineroRecibido: String,
    porCobrar: String,
    inventario: String
) {
    Column(
        modifier = modifier
            .fillMaxSize()
            .background(Navy)
            .verticalScroll(rememberScrollState())
            .padding(20.dp),
        verticalArrangement = Arrangement.spacedBy(20.dp)
    ) {

        Row(
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(12.dp)
        ) {
            Box(
                modifier = Modifier
                    .size(48.dp)
                    .background(AccentBlue, RoundedCornerShape(14.dp)),
                contentAlignment = Alignment.Center
            ) {
                Text(
                    "PC",
                    color = White,
                    fontSize = 20.sp,
                    fontWeight = FontWeight.Bold
                )
            }

            Column(modifier = Modifier.weight(1f)) {
                Text(
                    "PRESTIGE CLEAN",
                    color = White,
                    fontSize = 17.sp,
                    fontWeight = FontWeight.Bold
                )
                Text(
                    "Panel de administración",
                    color = SoftBlue,
                    fontSize = 12.sp
                )
            }

            Text("●", color = Color(0xFF4ADE80), fontSize = 13.sp)
        }

        Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
            Text(
                "¡Bienvenido!",
                color = White,
                fontSize = 25.sp,
                fontWeight = FontWeight.Bold
            )
            Text(
                "Este es el resumen de tu negocio.",
                color = SoftBlue,
                fontSize = 14.sp
            )
        }

        Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
            Text(
                "Resumen del día",
                color = White,
                fontSize = 18.sp,
                fontWeight = FontWeight.Bold
            )

            Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
                MetricCard(
                    "Ventas de hoy",
                    ventasHoy,
                    "Operaciones registradas",
                    Modifier.weight(1f)
                )
                MetricCard(
                    "Dinero recibido",
                    dineroRecibido,
                    "Pagos recibidos",
                    Modifier.weight(1f)
                )
            }

            Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
                MetricCard(
                    "Por cobrar",
                    porCobrar,
                    "Saldos pendientes",
                    Modifier.weight(1f)
                )
                MetricCard(
                    "Inventario",
                    inventario,
                    "Unidades disponibles",
                    Modifier.weight(1f)
                )
            }
        }

        Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
            Text(
                "Accesos rápidos",
                color = White,
                fontSize = 18.sp,
                fontWeight = FontWeight.Bold
            )

            Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
                ActionCard(
                    "+",
                    "Nueva venta",
                    Modifier.weight(1f)
                ) { onNavigate("Ventas") }

                ActionCard(
                    symbol = "",
                    title = "Productos",
                    modifier = Modifier.weight(1f),
                    iconRes = R.drawable.ic_bottle
                ) {
                    onNavigate("Productos")
                }
            }

            Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
                ActionCard(
                    "♙",
                    "Clientes",
                    Modifier.weight(1f)
                ) { onNavigate("Clientes") }

                ActionCard(
                    "◷",
                    "Historial",
                    Modifier.weight(1f)
                ) { onNavigate("Historial") }
            }
            Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {

                ActionCard(
                    "⚙",
                    "Producción",
                    Modifier.weight(1f)
                ) { onNavigate("Produccion") }

                ActionCard(
                    "▤",
                    "Inventario",
                    Modifier.weight(1f)
                ) { onNavigate("Inventario") }
            }
        }

        Text(
            "Prestige Clean  •  Gestión inteligente de tu negocio",
            color = SoftBlue,
            fontSize = 11.sp,
            modifier = Modifier
                .fillMaxWidth()
                .padding(top = 4.dp),
        )
    }
}

@Composable
fun MetricCard(
    title: String,
    value: String,
    description: String,
    modifier: Modifier = Modifier
) {
    Card(
        modifier = modifier,
        shape = RoundedCornerShape(18.dp),
        colors = CardDefaults.cardColors(
            containerColor = CardBlue
        )
    ) {
        Column(
            modifier = Modifier.padding(14.dp),
            verticalArrangement = Arrangement.spacedBy(7.dp)
        ) {
            Text(
                title,
                color = SoftBlue,
                fontSize = 12.sp
            )

            Text(
                value,
                color = White,
                fontSize = 23.sp,
                fontWeight = FontWeight.Bold
            )

            Text(
                description,
                color = SoftBlue,
                fontSize = 10.sp
            )
        }
    }
}


@Composable
fun ActionCard(
    symbol: String,
    title: String,
    modifier: Modifier = Modifier,
    iconRes: Int? = null,
    onClick: () -> Unit
) {
    Card(
        modifier = modifier.clickable { onClick() },
        shape = RoundedCornerShape(18.dp),
        colors = CardDefaults.cardColors(
            containerColor = CardBlue
        )
    ) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .padding(16.dp),
            verticalArrangement = Arrangement.spacedBy(12.dp)
        ) {
            if (iconRes != null) {
                Image(
                    painter = painterResource(id = iconRes),
                    contentDescription = title,
                    modifier = Modifier.size(27.dp),
                    colorFilter = ColorFilter.tint(AccentBlue)
                )
            } else {
                Text(
                    symbol,
                    color = AccentBlue,
                    fontSize = 27.sp,
                    fontWeight = FontWeight.Bold
                )
            }

            Text(
                title,
                color = White,
                fontSize = 14.sp,
                fontWeight = FontWeight.SemiBold
            )
        }
    }
}


@Composable
fun SectionScreen(
    title: String,
    description: String,
    symbol: String,
    modifier: Modifier = Modifier
) {
    Column(
        modifier = modifier
            .fillMaxSize()
            .background(Navy)
            .padding(24.dp),
        verticalArrangement = Arrangement.spacedBy(16.dp)
    ) {
        Text(
            title,
            color = White,
            fontSize = 26.sp,
            fontWeight = FontWeight.Bold
        )

        Box(
            modifier = Modifier
                .size(70.dp)
                .background(CardBlue, RoundedCornerShape(20.dp)),
            contentAlignment = Alignment.Center
        ) {
            Text(
                symbol,
                color = AccentBlue,
                fontSize = 32.sp
            )
        }

        Text(
            description,
            color = SoftBlue,
            fontSize = 15.sp
        )

        Text(
            "Estamos preparando esta sección.",
            color = White,
            fontSize = 13.sp
        )
    }
}

51,633 chars · codepastes.com