Notas sobre los JSON y su estructura - enchufin/el-brases-menu GitHub Wiki
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
- Estructura de Datos (carta.json)
{
"grupos": [
{
"id": "brasa",
"secciones": ["a_la_brasa"]
}
]
}
- Manejo de Traducciones (traducciones.json)
{
"grupos": {
"brasa": {
"cast": "A la brasa",
"cat": "A la brasa",
"eng": "Grilled"
}
},
"secciones": {
"a_la_brasa": {
"cast": "",
"cat": "",
"eng": ""
}
}
}
- 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>
);
};
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": ""
}
}
}
- Todos los items usan objetos (incluso si solo tienen un formato), para garantizar consistencia.
- Se introduce una clave
default
para items con un único formato/precio. - 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 }
}
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;