untitled

Pasted Nov 9, 2026, 6:33 AM1 file1,031 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/zzgs99dvqd558tk9
untitled

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
import com.negocio.desinfectantes.data.LoteProduccionEntity
import com.negocio.desinfectantes.data.LoteDetalleEntity
import com.negocio.desinfectantes.data.LoteGastoEntity
import com.negocio.desinfectantes.data.LoteInventarioEntity
import com.negocio.desinfectantes.ui.produccion.HistorialLotesScreen

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())
    val lotes by productoDao.obtenerLotes()
        .collectAsState(initial = emptyList())

    val todosDetallesLote by productoDao.obtenerTodosDetallesLote()
        .collectAsState(initial = emptyList())

    val todosGastosLote by productoDao.obtenerTodosGastosLote()
        .collectAsState(initial = emptyList())

    val todosInventariosLote by productoDao.obtenerTodosInventariosLote()
        .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,
        floatingActionButton = {},
        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" }
            )


            "Productos" -> {
                Box(
                    modifier = Modifier
                        .padding(innerPadding)
                        .fillMaxSize()
                ) {
                    when {
                        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)
                                    }
                                }
                            )
                        }

                        mostrarFormularioProducto -> {
                            AgregarProductoScreen(
                                onVolver = {
                                    mostrarFormularioProducto = false
                                },
                                onGuardar = { nombre, tipo, aroma ->
                                    scope.launch {
                                        try {
                                            val nuevoProductoId = UUID.randomUUID().toString()

                                            val nuevoProducto = ProductoEntity(
                                                id = nuevoProductoId,
                                                nombre = nombre,
                                                tipo = tipo
                                            )

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

                                            productoDao.guardarProducto(nuevoProducto)
                                            productoDao.guardarAroma(nuevoAroma)

                                            mostrarFormularioProducto = false
                                        } catch (e: Exception) {
                                            mensajeAroma = e.message
                                                ?: "No se pudo guardar el producto."
                                        }
                                    }
                                }
                            )
                        }

                        productoSeleccionado != null &&
                                mostrarFormularioAroma -> {
                            AgregarAromaScreen(
                                nombreProducto = productoSeleccionado!!.nombre,
                                onVolver = {
                                    mostrarFormularioAroma = false
                                },
                                onGuardar = { nombre ->
                                    scope.launch {
                                        try {
                                            val nuevoAroma = AromaEntity(
                                                id = UUID.randomUUID().toString(),
                                                productoId = productoSeleccionado!!.id,
                                                nombre = nombre
                                            )

                                            productoDao.guardarAroma(nuevoAroma)
                                            mostrarFormularioAroma = false
                                        } catch (e: Exception) {
                                            mensajeAroma = e.message
                                                ?: "No se pudo guardar el aroma."
                                        }
                                    }
                                }
                            )
                        }

                        productoSeleccionado != null &&
                                aromaSeleccionado != null &&
                                mostrarFormularioPresentacion -> {
                            AgregarPresentacionScreen(
                                nombreProducto = productoSeleccionado!!.nombre,
                                nombreAroma = aromaSeleccionado!!.nombre,
                                onVolver = {
                                    mostrarFormularioPresentacion = false
                                },
                                onGuardar = { nombre, contenido, precio ->
                                    scope.launch {
                                        try {
                                            val nuevaPresentacion = PresentacionEntity(
                                                id = UUID.randomUUID().toString(),
                                                aromaId = aromaSeleccionado!!.id,
                                                nombre = nombre,
                                                contenidoMl = contenido,
                                                precio = precio
                                            )

                                            productoDao.guardarPresentacion(nuevaPresentacion)
                                            mostrarFormularioPresentacion = false
                                        } catch (e: Exception) {
                                            mensajeAroma = e.message
                                                ?: "No se pudo guardar la presentación."
                                        }
                                    }
                                }
                            )
                        }

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

                                            productoDao.guardarPresentacion(actualizada)
                                            presentacionSeleccionada = null
                                        } catch (e: Exception) {
                                            mensajeAroma = e.message
                                                ?: "No se pudo actualizar la presentación."
                                        }
                                    }
                                },
                                onEliminar = {
                                    scope.launch {
                                        try {
                                            productoDao.eliminarPresentacion(
                                                presentacionSeleccionada!!.id
                                            )
                                            presentacionSeleccionada = null
                                        } catch (e: Exception) {
                                            mensajeAroma = e.message
                                                ?: "No se pudo desactivar la presentación."
                                        }
                                    }
                                }
                            )
                        }

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

                        productoSeleccionado != null -> {
                            AromasScreen(
                                nombreProducto = productoSeleccionado!!.nombre,
                                aromas = aromas,
                                onVolver = {
                                    productoSeleccionado = null
                                },
                                onAgregarAroma = {
                                    mostrarFormularioAroma = true
                                },
                                onSeleccionarAroma = { aroma ->
                                    aromaSeleccionado = aroma
                                },
                                onEliminarAroma = { aroma ->
                                    scope.launch {
                                        productoDao.eliminarAroma(aroma.id)
                                    }
                                },
                                onEditarAroma = { aroma, nuevoNombre ->
                                    scope.launch {
                                        productoDao.actualizarAroma(
                                            aroma.id,
                                            nuevoNombre
                                        )
                                    }
                                }
                            )
                        }

                        else -> {
                            ProductosScreen(
                                modifier = Modifier.fillMaxSize(),
                                productos = productos,
                                onAgregarProducto = {
                                    mostrarFormularioProducto = true
                                },
                                onVerInactivos = {
                                    mostrarRegistrosInactivos = true
                                },
                                onVolver = {
                                    selectedTab = "Inicio"
                                },
                                onSeleccionarProducto = { producto ->
                                    productoSeleccionado = producto
                                },
                                onDesactivarProducto = { producto ->
                                    scope.launch {
                                        productoDao.desactivarProducto(producto.id)
                                    }
                                },
                                onEditarProducto = { producto, nombre, tipo ->
                                    scope.launch {
                                        productoDao.actualizarProducto(
                                            producto.id,
                                            nombre,
                                            tipo
                                        )
                                    }
                                }
                            )
                        }
                    }
                }
            }


            "Produccion" -> ProduccionScreen(
                modifier = Modifier.padding(innerPadding),
                productos = productos,
                aromas = todosAromas.filter { it.activo },
                presentaciones = todasPresentacionesActivas,
                onVolver = {
                    selectedTab = "Inicio"
                },
                onGuardar = { lote, detalles, gastos, inventariosLote ->
                    scope.launch {
                        try {
                            productoDao.registrarLoteCompleto(
                                lote = lote,
                                detalles = detalles,
                                gastos = gastos,
                                inventariosLote = inventariosLote
                            )

                            selectedTab = "Inicio"
                        } catch (e: Exception) {
                            mensajeAroma = e.message ?: "No se pudo guardar el lote."
                        }
                    }
                }
            )
            "Inventario" -> InventarioScreen(
                modifier = Modifier.padding(innerPadding),
                productos = todosProductos,
                aromas = todosAromas,
                presentaciones = todasPresentacionesActivas + presentacionesInactivas,
                inventarios = inventarios,
                onVolver = {
                    selectedTab = "Inicio"
                }
            )


            "Lotes" -> HistorialLotesScreen(
                modifier = Modifier.padding(innerPadding),
                lotes = lotes,
                detalles = todosDetallesLote,
                gastos = todosGastosLote,
                inventariosLote = todosInventariosLote,
                productos = todosProductos,
                aromas = todosAromas,
                presentaciones = todasPresentacionesActivas + presentacionesInactivas,
                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") }
            }

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

                Spacer(modifier = Modifier.weight(1f))
            }
        }

        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
        )
    }
}

38,331 chars · codepastes.com