Guía 1: Creación del proyecto y layout moderno

React Native con Expo - App móvil de inventario

"Antes de programar un CRUD completo, construiremos la base visual y la estructura inicial de la aplicación."

Introducción Objetivo Proyecto Creación Estructura App.js HomeScreen Componentes Código final Actividad

1) Introducción

En esta serie de guías construiremos una aplicación móvil de inventario usando React Native con Expo.

La aplicación final permitirá administrar dos elementos principales: categorías y productos.

Categorías

Servirán para clasificar los productos. Por ejemplo: tecnología, oficina, accesorios, limpieza o alimentos.

CRUD 1

Productos

Serán los artículos del inventario. Cada producto deberá pertenecer a una categoría.

CRUD 2
Importante: en esta primera guía todavía no construiremos el CRUD completo. Primero crearemos la base del proyecto, la estructura de carpetas y una pantalla inicial moderna. Más adelante agregaremos navegación, formularios, consumo de API y operaciones CRUD.

2) Objetivo de la guía

Al finalizar esta guía, tendrás creada la primera versión visual de la aplicación. Esta pantalla funcionará como el inicio del sistema de inventario.

En esta guía aprenderás a:

  • Crear un proyecto de React Native usando Expo.
  • Organizar carpetas para pantallas y componentes.
  • Crear una pantalla principal llamada HomeScreen.
  • Usar componentes básicos de React Native.
  • Usar useState para manejar datos temporales.
  • Crear un layout moderno con tarjetas, secciones y listas.
  • Separar partes de la interfaz en componentes reutilizables.

Resultado esperado

Sistema de inventario

Inventario App

Administra categorías y productos.

3 Categorías
5 Productos
Laptop Dell

$850.00 - Stock: 8

Tecnología
Mouse inalámbrico

$18.50 - Stock: 25

Accesorios
Silla ejecutiva

$95.00 - Stock: 4

Oficina

3) Proyecto que construiremos

La aplicación se llamará Inventario App. Su propósito será administrar productos y categorías desde una app móvil.

Relación entre los datos

Un producto estará relacionado con una categoría. Por ejemplo:

Categoría Producto Ejemplo
Tecnología Laptop Dell La laptop pertenece a la categoría Tecnología.
Accesorios Mouse inalámbrico El mouse pertenece a la categoría Accesorios.
Oficina Silla ejecutiva La silla pertenece a la categoría Oficina.

Endpoints que se usarán más adelante

Para esta serie de guías asumiremos que ya existen endpoints para realizar las operaciones de categorías y productos.

Endpoints asumidos
GET     /categorias
POST    /categorias
PUT     /categorias/:id
DELETE  /categorias/:id

GET     /productos
POST    /productos
PUT     /productos/:id
DELETE  /productos/:id
En esta guía no consumiremos todavía estos endpoints. Primero usaremos datos temporales dentro de la app. Esto nos permitirá concentrarnos en la estructura visual.

4) Creación del proyecto con Expo

En primer lugar, crearemos un proyecto nuevo de Expo. Expo nos permite trabajar con React Native de forma más sencilla, probar la app en el navegador, emulador o dispositivo físico, y desarrollar sin configurar todo manualmente desde cero.

Paso 1: Crear el proyecto

Abre una terminal en la carpeta donde guardarás tus proyectos y escribe:

Terminal
npx create-expo-app@latest inventario-app --template blank

Con este comando se creará una carpeta llamada inventario-app. Dentro estará el proyecto inicial.

Paso 2: Entrar a la carpeta

Terminal
cd inventario-app

Paso 3: Instalar Safe Area Context

Para evitar problemas con la parte superior de la pantalla en algunos dispositivos, usaremos react-native-safe-area-context.

Terminal
npx expo install react-native-safe-area-context

Paso 4: Ejecutar el proyecto

Terminal
npx expo start

Al ejecutar este comando, Expo mostrará opciones para abrir la app en Android, iOS, web o mediante Expo Go.

Nota: si estás usando un dispositivo físico, puedes escanear el código QR desde la app Expo Go.

5) Organización inicial de carpetas

Ahora vamos a ordenar el proyecto. Aunque al inicio la aplicación será pequeña, es importante organizarla desde el principio.

Carpetas que crearemos

inventario-app/
├── App.js
├── src/
│ ├── screens/
│ │ └── HomeScreen.js
│ └── components/
│ ├── StatCard.js
│ ├── CategoryPill.js
│ └── ProductCard.js
└── package.json

La carpeta screens guardará las pantallas principales. La carpeta components guardará piezas reutilizables de la interfaz.

Crear carpetas desde la terminal

Terminal
mkdir src
mkdir src/screens
mkdir src/components
También puedes crear las carpetas manualmente desde Visual Studio Code.

6) Preparación del archivo App.js

El archivo App.js es el punto de entrada principal de la aplicación.

Al crear un proyecto nuevo, Expo coloca código de ejemplo dentro de este archivo. Nosotros lo reemplazaremos poco a poco.

Primero, deja el archivo así:

App.js
import { StatusBar } from 'expo-status-bar';
import { Text, View } from 'react-native';

export default function App() {
  return (
    <View>
      <Text>Inventario App</Text>
      <StatusBar style="auto" />
    </View>
  );
}

Este código solamente muestra un texto en pantalla. Todavía no tiene diseño. Lo usamos únicamente para comprobar que la app funciona.

Explicación rápida:
  • View funciona como un contenedor.
  • Text permite mostrar texto en pantalla.
  • StatusBar controla la barra superior del dispositivo.

Ahora conectaremos App.js con una pantalla

Más adelante tendremos varias pantallas (inicio, categorías, productos, perfil, etc.). Por eso, en lugar de colocar todo dentro de App.js, crearemos pantallas separadas como HomeScreen.js.

Vamos a cambiar App.js paso a paso.

Paso 1: Importar HomeScreen

Agrega una nueva línea de importación:

Importación
import { StatusBar } from 'expo-status-bar';
import HomeScreen from './src/screens/HomeScreen';

Esta línea importa el componente HomeScreen que crearemos después.

Paso 2: Reemplazar el contenido de App

Ahora, en la función App, reemplaza el contenido del return por:

App.js completo
import { StatusBar } from 'expo-status-bar';
import HomeScreen from './src/screens/HomeScreen';

export default function App() {
  return (
    <>
      <HomeScreen />
      <StatusBar style="light" />
    </>
  );
}

Aquí:

Todavía aparecerá un error porque el archivo HomeScreen.js aún no existe. Lo crearemos en el siguiente paso.

7) Creación de la pantalla HomeScreen

Dentro de la carpeta src/screens, crea un archivo llamado:

HomeScreen.js

Paso 1: Crear la pantalla básica

Primero escribiremos una pantalla sencilla para comprobar que todo está conectado correctamente.

La pantalla tendrá tres partes importantes:

src/screens/HomeScreen.js
import { View, Text, StyleSheet } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';

export default function HomeScreen() {
  return (
    <SafeAreaView style={styles.container}>
      <View>
        <Text>Inventario App</Text>
      </View>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f8fafc',
  },
});

En este punto ya deberías ver el texto Inventario App en la pantalla.

Inventario App

¿Qué significa flex: 1?

Indica que el contenedor debe ocupar todo el espacio disponible de la pantalla.

Paso 2: Agregar un ScrollView

Como la pantalla tendrá varias tarjetas y listas de productos, agregaremos un ScrollView. Esto permitirá desplazarse si el contenido no cabe completo en la pantalla.

Paso 2.1: Importar ScrollView

Modifica la primera línea para agregar ScrollView:

Importación
import { ScrollView, View, Text, StyleSheet } from 'react-native';

Paso 2.2: Envolver el contenido en ScrollView

src/screens/HomeScreen.js
import { ScrollView, View, Text, StyleSheet } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';

export default function HomeScreen() {
  return (
    <SafeAreaView style={styles.container}>
      <ScrollView contentContainerStyle={styles.content}>
        <Text>Inventario App</Text>
      </ScrollView>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f8fafc',
  },
  content: {
    padding: 20,
  },
});

Ahora el contenido está dentro de un ScrollView. Nota que usamos contentContainerStyle={styles.content}. Este atributo nos permite aplicar estilos al contenido interno del ScrollView (agregar espaciado, etc.).

Paso 3: Crear el encabezado principal paso a paso

Reemplazaremos el texto simple por un encabezado visual. Vamos a construirlo gradualmente.

Paso 3.1: Crear el contenedor del encabezado

Reemplaza el texto "Inventario App" por esto:

Encabezado básico
<View style={styles.header}>
  <Text>Inventario App</Text>
</View>

En este punto, tendrás una caja azul con el texto.

Paso 3.2: Agregar el "kicker" (etiqueta pequeña)

Ahora agrega un texto antes del título principal:

Encabezado con etiqueta
<View style={styles.header}>
  <Text style={styles.kicker}>Sistema de inventario</Text>
  <Text>Inventario App</Text>
</View>

El "kicker" es un pequeño texto superior que describe el contexto.

Paso 3.3: Estilizar el título principal

Dale estilos especiales al título:

Encabezado con título estilizado
<View style={styles.header}>
  <Text style={styles.kicker}>Sistema de inventario</Text>
  <Text style={styles.title}>Inventario App</Text>
</View>

Paso 3.4: Agregar el subtítulo descriptivo

Finalmente, agrega un subtítulo debajo del título:

Encabezado completo
<View style={styles.header}>
  <Text style={styles.kicker}>Sistema de inventario</Text>
  <Text style={styles.title}>Inventario App</Text>
  <Text style={styles.subtitle}>
    Administra categorías y productos desde una aplicación móvil.
  </Text>
</View>

Paso 4: Agregar estilos del encabezado paso a paso

Agregaremos los estilos en el mismo orden que agregamos los elementos.

Paso 4.1: Estilo del contenedor principal

Estilo del header
const styles = StyleSheet.create({
  container: { ... },
  content: { ... },
  header: {
    backgroundColor: '#1a5276',
    padding: 22,
    borderRadius: 22,
    marginBottom: 20,
  },
});

Esto crea una caja azul oscura con bordes redondeados.

Paso 4.2: Estilos del kicker y título

Estilos de textos
const styles = StyleSheet.create({
  ...
  header: { ... },
  kicker: {
    color: '#bfdbfe',
    fontSize: 13,
    fontWeight: '800',
    textTransform: 'uppercase',
    marginBottom: 6,
  },
  title: {
    color: '#ffffff',
    fontSize: 30,
    fontWeight: '900',
  },
});

El kicker es pequeño y azul claro. El title es grande y blanco.

Paso 4.3: Estilo del subtítulo

Estilo del subtítulo
const styles = StyleSheet.create({
  ...
  header: { ... },
  kicker: { ... },
  title: { ... },
  subtitle: {
    color: '#e0f2fe',
    fontSize: 15,
    marginTop: 8,
  },
});

Paso 5: HomeScreen después del encabezado

Después de seguir los pasos anteriores, tu archivo debería verse así:

src/screens/HomeScreen.js
import { ScrollView, View, Text, StyleSheet } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';

export default function HomeScreen() {
  return (
    <SafeAreaView style={styles.container}>
      <ScrollView contentContainerStyle={styles.content}>

        <View style={styles.header}>
          <Text style={styles.kicker}>Sistema de inventario</Text>
          <Text style={styles.title}>Inventario App</Text>
          <Text style={styles.subtitle}>
            Administra categorías y productos desde una aplicación móvil.
          </Text>
        </View>

      </ScrollView>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f8fafc',
  },
  content: {
    padding: 20,
  },
  header: {
    backgroundColor: '#1a5276',
    padding: 22,
    borderRadius: 22,
    marginBottom: 20,
  },
  kicker: {
    color: '#bfdbfe',
    fontSize: 13,
    fontWeight: '800',
    textTransform: 'uppercase',
    marginBottom: 6,
  },
  title: {
    color: '#ffffff',
    fontSize: 30,
    fontWeight: '900',
  },
  subtitle: {
    color: '#e0f2fe',
    fontSize: 15,
    marginTop: 8,
  },
});

En este punto, la pantalla debería tener un encabezado atractivo con fondo azul. El encabezado mostrará el nombre de la app y una descripción debajo.

Sistema de inventario

Inventario App

Administra categorías y productos desde una aplicación móvil.

¿Qué hemos hecho hasta aquí?
  • Creamos una pantalla con SafeAreaView para evitar problemas con el dispositivo.
  • Agregamos ScrollView para poder desplazarse si hay más contenido.
  • Creamos un encabezado con título, subtítulo y estilos atractivos.

8) Agregar datos temporales con useState

Aunque más adelante los datos vendrán desde una API, por ahora usaremos datos temporales dentro de la aplicación.

Para eso utilizaremos el Hook useState, que nos permite guardar datos dentro del componente.

Paso 1: Importar useState

En la parte superior del archivo, necesitamos importar useState desde React. Esto nos permitirá usar estados en nuestro componente.

Importaciones
import { useState } from 'react';
import { ScrollView, View, Text, StyleSheet } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';

Paso 2: Crear el estado de categorías

Dentro de la función HomeScreen, antes del return, crearemos un arreglo de categorías usando useState.

Cada categoría tendrá dos propiedades:

Estado de categorías
const [categorias] = useState([
  { id: 1, nombre: 'Tecnología' },
  { id: 2, nombre: 'Accesorios' },
  { id: 3, nombre: 'Oficina' },
]);

Paso 3: Crear el estado de productos

Debajo del estado anterior, agregaremos un arreglo de productos. Cada producto estará asociado a una categoría.

Cada producto tiene:

Estado de productos
const [productos] = useState([
  {
    id: 1,
    nombre: 'Laptop Dell',
    precio: 850,
    stock: 8,
    categoriaId: 1,
  },
  {
    id: 2,
    nombre: 'Mouse inalámbrico',
    precio: 18.5,
    stock: 25,
    categoriaId: 2,
  },
  {
    id: 3,
    nombre: 'Silla ejecutiva',
    precio: 95,
    stock: 4,
    categoriaId: 3,
  },
]);

Observa que la primera laptop tiene categoriaId: 1, lo que significa que pertenece a "Tecnología". El mouse tiene categoriaId: 2 (Accesorios), y la silla tiene categoriaId: 3 (Oficina).

En este momento los datos no se pueden agregar, editar ni eliminar. Eso lo haremos en las siguientes guías. Por ahora, estos datos solo existen mientras la app está abierta.

Paso 4: Crear cálculos simples

Ahora crearemos algunos valores que nos servirán para mostrar estadísticas en la pantalla. Estos valores se calcularán automáticamente a partir de los datos.

Cálculos para estadísticas
const totalCategorias = categorias.length;
const totalProductos = productos.length;
const productosBajoStock = productos.filter(producto => producto.stock <= 5).length;

Estos valores funcionan así:

9) Creación de componentes reutilizables

En React Native es recomendable dividir la interfaz en componentes pequeños. Esto hace que el código sea más ordenado y fácil de mantener.

Componente 1: StatCard

Este componente mostrará una estadística en una tarjeta. Por ejemplo, usaremos para mostrar: cantidad de categorías, cantidad de productos, y cantidad de productos con bajo stock.

Crea el archivo:

src/components/StatCard.js

Paso 1: Entender las props

Este componente recibe tres datos (props) desde su padre:

Paso 2: Escribir el componente

src/components/StatCard.js
import { View, Text, StyleSheet } from 'react-native';

export default function StatCard({ titulo, valor, descripcion }) {
  return (
    <View style={styles.card}>
      <Text style={styles.valor}>{valor}</Text>
      <Text style={styles.titulo}>{titulo}</Text>
      <Text style={styles.descripcion}>{descripcion}</Text>
    </View>
  );
}

La estructura es simple:

  1. Un contenedor principal (View) que actúa como la tarjeta.
  2. Tres textos: el valor (el número grande), el título, y la descripción.

Paso 3: Agregar estilos

Estilos de StatCard
const styles = StyleSheet.create({
  card: {
    flex: 1,
    backgroundColor: '#ffffff',
    padding: 16,
    borderRadius: 18,
    borderWidth: 1,
    borderColor: '#e2e8f0',
  },
  valor: {
    fontSize: 26,
    fontWeight: '900',
    color: '#1a5276',
  },
  titulo: {
    fontSize: 14,
    fontWeight: '800',
    color: '#0f172a',
    marginTop: 4,
  },
  descripcion: {
    fontSize: 12,
    color: '#64748b',
    marginTop: 4,
  },
});

El estilo flex: 1 hace que la tarjeta crezca y ocupe el espacio disponible junto a otras tarjetas.

¿Qué son las props?

Las props son datos que un componente recibe desde otro componente padre. En este caso, cuando usemos StatCard, le pasaremos titulo, valor y descripcion.

Usar StatCard en HomeScreen

Primero, importa el componente en HomeScreen.js.

Importar componente
import StatCard from '../components/StatCard';

Luego, debajo del encabezado, agregaremos las tarjetas de estadísticas paso a paso.

Paso 1: Crear el contenedor para dos tarjetas

Primera fila de estadísticas
<View style={styles.statsContainer}>
  <StatCard
    titulo="Categorías"
    valor={totalCategorias}
    descripcion="Registradas"
  />

  <StatCard
    titulo="Productos"
    valor={totalProductos}
    descripcion="En inventario"
  />
</View>

Aquí mostramos dos tarjetas lado a lado: una para categorías y otra para productos. Cada una recibe props con el título, el valor numérico y una descripción.

Paso 2: Agregar una segunda fila con la tercera estadística

Segunda fila de estadísticas
<View style={styles.statsContainer}>
  <StatCard
    titulo="Bajo stock"
    valor={productosBajoStock}
    descripcion="Requieren revisión"
  />
</View>

Esta segunda fila muestra una sola tarjeta: los productos con bajo stock. Es importante destacar esta métrica porque señala productos que necesitan atención.

Finalmente, agrega este estilo:

Estilo para estadísticas
statsContainer: {
  flexDirection: 'row',
  gap: 12,
  marginBottom: 12,
},

Ahora la pantalla debería mostrar el encabezado seguido de las tarjetas de estadísticas.

Sistema de inventario

Inventario App

Administra categorías y productos desde una aplicación móvil.

3 Categorías
3 Productos
1 Bajo stock
¿Por qué grid con dos columnas?

El estilo flexDirection: 'row' hace que las tarjetas se muestren una al lado de la otra. Con dos tarjetas caben bien. La tercera tarjeta va en una fila aparte automáticamente.

Componente 2: CategoryPill

Este es un componente pequeño y visual que mostrará el nombre de una categoría en una pequeña "píldora" redondeada. Es el chip naranja que ves en las tarjetas de productos.

Crea el archivo:

src/components/CategoryPill.js

Paso 1: Crear el componente

Es muy sencillo: recibe el nombre de la categoría y lo muestra con estilos especiales.

src/components/CategoryPill.js
import { Text, StyleSheet } from 'react-native';

export default function CategoryPill({ nombre }) {
  return (
    <Text style={styles.pill}>
      {nombre}
    </Text>
  );
}

Paso 2: Agregar estilos

Los estilos crean una "píldora" redondeada con fondo naranja:

Estilos de CategoryPill
const styles = StyleSheet.create({
  pill: {
    alignSelf: 'flex-start',
    backgroundColor: '#ffedd5',
    color: '#c2410c',
    paddingHorizontal: 10,
    paddingVertical: 5,
    borderRadius: 999,
    fontSize: 12,
    fontWeight: '900',
    marginTop: 8,
  },
});

El borderRadius: 999 hace que sea completamente redondeado (como una píldora). El alignSelf: 'flex-start' hace que ocupe solo el ancho que necesita.

Componente 3: ProductCard

Este componente mostrará la información de cada producto en una tarjeta visual. Cada tarjeta mostrará el nombre, precio, stock, categoría y un badge indicando si el stock es bajo.

Crea el archivo:

src/components/ProductCard.js

Paso 1: Importar dependencias

Necesitamos importar los componentes de React Native y el componente CategoryPill que creamos antes:

Importaciones
import { View, Text, StyleSheet } from 'react-native';
import CategoryPill from './CategoryPill';

Paso 2: Crear la estructura paso a paso

Vamos a construir el componente gradualmente, agregando una parte a la vez.

Paso 2.1: Crear la tarjeta principal

Primero, creamos solo el contenedor exterior (la tarjeta blanca):

ProductCard - Paso 1
export default function ProductCard({ producto, categoria }) {
  return (
    <View style={styles.card}>
      <Text>Producto</Text>
    </View>
  );
}

En este punto, solo mostramos una tarjeta blanca con un texto simple.

Paso 2.2: Agregar la estructura interna (row)

Ahora agregamos una fila (View con flexDirection: 'row') que divide el contenido en dos partes: la información a la izquierda y el badge a la derecha.

ProductCard - Paso 2
export default function ProductCard({ producto, categoria }) {
  return (
    <View style={styles.card}>
      <View style={styles.row}>
        <Text>Información del producto</Text>
        <Text>Badge</Text>
      </View>
    </View>
  );
}

Ahora la tarjeta tiene dos columnas: una para la información y otra para el badge.

Paso 2.3: Llenar la sección de información

Reemplazamos el texto de "Información" por un View que contiene todos los detalles:

ProductCard - Paso 3
export default function ProductCard({ producto, categoria }) {
  return (
    <View style={styles.card}>
      <View style={styles.row}>
        <View style={styles.info}>
          <Text style={styles.nombre}>{producto.nombre}</Text>
          <Text style={styles.detalle}>
            Precio: ${producto.precio.toFixed(2)}
          </Text>
          <Text style={styles.detalle}>
            Stock: {producto.stock} unidades
          </Text>
          <CategoryPill nombre={categoria} />
        </View>
        <Text>Badge</Text>
      </View>
    </View>
  );
}

Ahora mostramos:

Paso 2.4: Agregar el badge de estado

Finalmente, reemplazamos el "Badge" temporal por un View que muestra si el stock es bajo o normal:

ProductCard - Paso 4 (Final)
export default function ProductCard({ producto, categoria }) {
  return (
    <View style={styles.card}>
      <View style={styles.row}>
        <View style={styles.info}>
          <Text style={styles.nombre}>{producto.nombre}</Text>
          <Text style={styles.detalle}>
            Precio: ${producto.precio.toFixed(2)}
          </Text>
          <Text style={styles.detalle}>
            Stock: {producto.stock} unidades
          </Text>
          <CategoryPill nombre={categoria} />
        </View>

        <View style={styles.badge}>
          <Text style={styles.badgeText}>
            {producto.stock <= 5 ? 'Bajo' : 'OK'}
          </Text>
        </View>
      </View>
    </View>
  );
}

El badge usa una condición: producto.stock <= 5 ? 'Bajo' : 'OK'. Esto significa: "si el stock es menor o igual a 5, muestra 'Bajo', sino muestra 'OK'".

¿Por qué paso a paso?

Construir los componentes gradualmente ayuda a entender cada parte. Si vemos todo de una vez, es más difícil de seguir. Así vamos de lo simple a lo complejo.

Paso 3: Agregar estilos gradualmente

Agregaremos los estilos en el mismo orden que agregamos el código.

Paso 3.1: Estilos para la tarjeta principal

Estilos básicos
const styles = StyleSheet.create({
  card: {
    backgroundColor: '#ffffff',
    padding: 16,
    borderRadius: 18,
    marginBottom: 12,
    borderWidth: 1,
    borderColor: '#e2e8f0',
  },
});

Esto crea una tarjeta blanca con bordes suaves y un pequeño espaciado debajo.

Paso 3.2: Agregar estilos para la fila

Estilos para row
const styles = StyleSheet.create({
  card: {
    backgroundColor: '#ffffff',
    padding: 16,
    borderRadius: 18,
    marginBottom: 12,
    borderWidth: 1,
    borderColor: '#e2e8f0',
  },
  row: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    gap: 12,
  },
});

El flexDirection: 'row' coloca los elementos uno al lado del otro. El justifyContent: 'space-between' los separa (uno a la izquierda, otro a la derecha).

Paso 3.3: Estilos para la información

Estilos para nombre, detalles
const styles = StyleSheet.create({
  card: { ... },
  row: { ... },
  info: {
    flex: 1,
  },
  nombre: {
    fontSize: 17,
    fontWeight: '900',
    color: '#0f172a',
  },
  detalle: {
    color: '#64748b',
    marginTop: 3,
  },
});

El flex: 1 en info hace que ocupe todo el espacio disponible. El nombre es texto grande y oscuro. El detalle es más pequeño y gris.

Paso 3.4: Estilos finales para el badge

Estilos para badge (completos)
const styles = StyleSheet.create({
  card: { ... },
  row: { ... },
  info: { ... },
  nombre: { ... },
  detalle: { ... },
  badge: {
    backgroundColor: '#e0f2fe',
    borderRadius: 12,
    paddingHorizontal: 10,
    paddingVertical: 6,
    alignSelf: 'flex-start',
  },
  badgeText: {
    color: '#0369a1',
    fontWeight: '900',
    fontSize: 12,
  },
});

El badge es una pequeña caja azul clara con esquinas redondeadas. El alignSelf: 'flex-start' hace que ocupe solo el ancho que necesita.

Usar ProductCard en HomeScreen

Ahora usaremos este componente en la pantalla principal. Primero, importa el componente:

Importar ProductCard
import ProductCard from '../components/ProductCard';

Paso 1: Crear una función auxiliar

Los productos tienen categoriaId (un número), pero nosotros queremos mostrar el nombre de la categoría (un texto). Por eso necesitamos una función que busque el nombre a partir del ID.

Por ejemplo: si un producto tiene categoriaId: 1, esta función debe retornar "Tecnología".

Función para obtener categoría
function obtenerNombreCategoria(categoriaId) {
  const categoriaEncontrada = categorias.find(
    categoria => categoria.id === categoriaId
  );

  return categoriaEncontrada ? categoriaEncontrada.nombre : 'Sin categoría';
}

Esta función:

  1. Busca en el arreglo de categorías una que tenga el ID que pasamos.
  2. Si la encuentra, retorna el nombre. Si no encuentra nada, retorna "Sin categoría".

Paso 2: Agregar el encabezado de la sección

Debajo de las tarjetas de estadísticas, agregamos un título para la sección de productos:

Encabezado de productos
<View style={styles.sectionBlock}>
  <Text style={styles.sectionTitle}>Productos recientes</Text>
</View>

Paso 3: Agregar el listado de productos

Dentro de esa sección, agregamos un bloque que recorre todos los productos y crea un ProductCard para cada uno.

Reemplaza el código anterior por este:

Listado de productos (versión completa)
<View style={styles.sectionBlock}>
  <Text style={styles.sectionTitle}>Productos recientes</Text>

  {productos.map(producto => (
    <ProductCard
      key={producto.id}
      producto={producto}
      categoria={obtenerNombreCategoria(producto.categoriaId)}
    />
  ))}
</View>

El método .map() recorre cada producto del arreglo y ejecuta una función para cada uno. En este caso:

Paso 4: Agregar estilos de la sección

Estilos de sección
sectionBlock: {
  marginTop: 10,
},
sectionTitle: {
  fontSize: 20,
  fontWeight: '900',
  color: '#0f172a',
  marginBottom: 12,
},

Ahora la pantalla debería mostrar encabezado, estadísticas y una lista de productos.

Sistema de inventario

Inventario App

Administra categorías y productos desde una aplicación móvil.

3 Categorías
3 Productos
1 Bajo stock

Productos recientes

Laptop Dell

$850.00 - Stock: 8

Tecnología
Mouse inalámbrico

$18.50 - Stock: 25

Accesorios
Silla ejecutiva

$95.00 - Stock: 4

Oficina

10) Código final de la Guía 1

Al terminar todos los pasos anteriores, los archivos principales deben quedar así.

11) Actividad práctica

Ahora es tu turno. Realiza los siguientes cambios en la aplicación.

Ejercicio 1

Cambia el título Inventario App por el nombre de tu propia aplicación.

Ejercicio 2

Agrega dos categorías nuevas al arreglo de categorías.

Ejercicio 3

Agrega tres productos nuevos al arreglo de productos. Recuerda que cada producto debe tener:

  • id
  • nombre
  • precio
  • stock
  • categoriaId

Ejercicio 4

Modifica los colores del encabezado y de las tarjetas para personalizar la apariencia de la app.

Checklist de revisión

En la siguiente guía agregaremos navegación entre pantallas. La app comenzará a tener secciones separadas para inicio, categorías, productos y perfil.