Notas sobre los JSON y su estructura - enchufin/el-brases-menu GitHub Wiki

Contexto

Para evitar la duplicación visual de títulos en la interfaz, implemento la siguiente lógica:

Cuando un grupo contiene una única sección con el mismo nombre:

  • Solo se muestra el título del grupo (como encabezado principal)

  • Se omite el título de la sección

Implementación

  1. Estructura de Datos (carta.json)
{
  "grupos": [
    {
      "id": "brasa",
      "secciones": ["a_la_brasa"]
    }
  ]
}
  1. Manejo de Traducciones (traducciones.json)
{
  "grupos": {
    "brasa": {
      "cast": "A la brasa",
      "cat": "A la brasa", 
      "eng": "Grilled"
    }
  },
  "secciones": {
    "a_la_brasa": {
      "cast": "",
      "cat": "",
      "eng": ""
    }
  }
}
  1. Lógica de Renderizado
// Grupo.jsx
<GrupoHeader title={translate(`grupos.${grupoId}`)}/>

// Seccion.jsx
{translate(`secciones.${seccionId}`) && <h3>{...}</h3>}
// Seccion.jsx
const Seccion = ({ seccionId }) => {
  //custom hook para la traduccion mediante el context
  const { translate } = useLanguage();
  const nombreSeccion = translate(`secciones.${seccionId}`);

  return (
    <div className="seccion">
      {/* Título solo se muestra si hay texto */}
      {nombreSeccion && <h3>{nombreSeccion}</h3>}
      {/* Items... */}
    </div>
  );
};

Alternativa

Para evitar añadir ID individuales para un mismo caso. Se puede colocar un mismo ID con la misma solución

{
  "grupos": [
    {
      "id": "postres",
      "secciones": ["todos"]  // ← ID compartido
    },
    {
      "id": "brasa",
      "secciones": ["todos"]  // ← Mismo ID
    }
  ]
}
{
  "secciones": {
    "todos": {  // ← Única entrada para todas las secciones vacías
      "cast": "",
      "cat": "",
      "eng": ""
    }
  }
}

Normalización de estructura en Precios

  1. Todos los items usan objetos (incluso si solo tienen un formato), para garantizar consistencia.
  2. Se introduce una clave default para items con un único formato/precio.
  3. Los formatos específicos (chupito, copa, etc.) solo se incluyen si existen.
{
  // Items con un solo formato → usan "default"
  "agua_con_gas": { "default": 2.00 },
  "gaseosa": { "default": 2.50 },
  "refresco": { "default": 2.50 },
  
  // Items con múltiples formatos
  "frangelico": {
    "chupito": 3.50,
    "copa": 6.00
  },
  "baileys": { 
    "copa": 5.50,
    "combinado": 7.50 
  },
  
  // Items con precio variable (null)
  "calamar_rabo": { "default": null }
}

gestión de datos por el componente ItemPrecios.jsx

import PropTypes from 'prop-types';
import { useLanguage, usePrecios } from '@hooks';

const ItemPrecios = ({ itemId, formatos }) => {
  const { translate } = useLanguage();
  const precios = usePrecios();

  return (
    <div className="precios">
      {formatos?.map(formato => {
        const precio = precios[itemId]?.[formato] ?? precios[itemId]?.default;
        
        return (
          <div key={formato}>
            <span>{translate(`formatos.${formato}`)}:</span>
            <span>
              {precio === null 
                ? translate('precio_variable') 
                : `${precio?.toFixed(2)}€`}
            </span>
          </div>
        );
      })}
      
      {!formatos && (
        <span>
          {precios[itemId]?.default === null 
            ? translate('precio_variable') 
            : `${precios[itemId]?.default?.toFixed(2)}€`}
        </span>
      )}
    </div>
  );
};
// Definición de PropTypes
ItemPrecios.propTypes = {
  itemId: PropTypes.string.isRequired,     // ID debe ser string obligatorio
  formatos: PropTypes.arrayOf(PropTypes.string) // Array de strings opcional
};

ItemPrecios.defaultProps = {
  formatos: null // Si no se pasan formatos, será null
};

export default ItemPrecios;
⚠️ **GitHub.com Fallback** ⚠️