Available Functions
The src/services/api.js module exports three async functions for fetching menu data. All functions are promise-based and should be used with async/await or .then()/.catch() patterns.
getCategorias
Fetches all menu categories from the backend.
Function Signature
export const getCategorias = async () => Promise < Category [] >
Parameters
This function takes no parameters
Return Type
Array of category objects Unique category identifier
Display name of the category (e.g., “Hamburguesas”, “Bebidas”)
Material Symbols icon name (e.g., “lunch_dining”, “local_cafe”)
Implementation
const BASE_URL = "https://apiqsp-production.up.railway.app" ;
export const getCategorias = async () => {
const res = await fetch ( ` ${ BASE_URL } /categories` );
if ( ! res . ok ) throw new Error ( "Error al cargar categorías" );
return res . json ();
};
HTTP Request
curl https://apiqsp-production.up.railway.app/categories
Example Response
[
{
"id" : 1 ,
"name" : "Hamburguesas" ,
"icon" : "lunch_dining"
},
{
"id" : 2 ,
"name" : "Bebidas" ,
"icon" : "local_cafe"
},
{
"id" : 3 ,
"name" : "Postres" ,
"icon" : "cake"
}
]
Error Handling
try {
const categories = await getCategorias ();
console . log ( categories );
} catch ( error ) {
console . error ( 'Failed to load categories:' , error . message );
// Error message: "Error al cargar categorías"
}
This endpoint is typically called once on component mount to populate the navigation menu.
getComidas
Fetches all products across all categories.
Function Signature
export const getComidas = async () => Promise < Product [] >
Parameters
This function takes no parameters
Return Type
Array of product objects Unique product identifier
Product name (e.g., “Hamburguesa Clásica”)
Product price as a number
Full URL to the product image
Optional badge label (e.g., “Popular”, “Nuevo”, “Especial”)
Reference to the parent category ID
Implementation
export const getComidas = async () => {
const res = await fetch ( ` ${ BASE_URL } /products` );
if ( ! res . ok ) throw new Error ( "Error al cargar comidas" );
return res . json ();
};
HTTP Request
curl https://apiqsp-production.up.railway.app/products
Example Response
[
{
"id" : 1 ,
"name" : "Hamburguesa Clásica" ,
"price" : 8.99 ,
"imageUrl" : "https://example.com/images/burger-classic.jpg" ,
"badge" : "Popular" ,
"categoryId" : 1
},
{
"id" : 2 ,
"name" : "Coca Cola" ,
"price" : 2.50 ,
"imageUrl" : "https://example.com/images/coca-cola.jpg" ,
"badge" : null ,
"categoryId" : 2
}
]
Error Handling
try {
const products = await getComidas ();
console . log ( `Loaded ${ products . length } products` );
} catch ( error ) {
console . error ( 'Failed to load products:' , error . message );
// Error message: "Error al cargar comidas"
}
This endpoint returns ALL products regardless of category. For filtered results, use getProductsByCategory() instead.
getProductsByCategory
Fetches products filtered by a specific category ID.
Function Signature
export const getProductsByCategory = async ( categoryId : number ) => Promise < Product [] >
Parameters
The unique identifier of the category to filter by. Must match a valid category ID from getCategorias().
Return Type
Array of product objects belonging to the specified category Unique product identifier
Implementation
export const getProductsByCategory = async ( categoryId ) => {
const res = await fetch ( ` ${ BASE_URL } /products/category/ ${ categoryId } ` );
if ( ! res . ok ) throw new Error ( "Error al cargar productos de la categoría" );
return res . json ();
};
HTTP Request
# Fetch products for category ID 1
curl https://apiqsp-production.up.railway.app/products/category/1
Usage Example
// Fetch all hamburgers (category ID 1)
const hamburgers = await getProductsByCategory ( 1 );
// Fetch all drinks (category ID 2)
const drinks = await getProductsByCategory ( 2 );
Example Response
[
{
"id" : 1 ,
"name" : "Hamburguesa Clásica" ,
"price" : 8.99 ,
"imageUrl" : "https://example.com/images/burger-classic.jpg" ,
"badge" : "Popular"
},
{
"id" : 3 ,
"name" : "Hamburguesa BBQ" ,
"price" : 10.99 ,
"imageUrl" : "https://example.com/images/burger-bbq.jpg" ,
"badge" : "Nuevo"
}
]
Error Handling
try {
const products = await getProductsByCategory ( 999 );
// May return empty array or throw error if category doesn't exist
} catch ( error ) {
console . error ( 'Failed to load category products:' , error . message );
// Error message: "Error al cargar productos de la categoría"
}
If the category ID is valid but has no products, the API returns an empty array [] rather than throwing an error.
Endpoint Summary
GET /categories Returns all menu categories with icons
GET /products Returns all products across categories
GET /products/category/:id Returns products for specific category
Common Patterns
Sequential Data Loading
Load categories first, then products based on user selection:
// 1. Load categories on mount
const categories = await getCategorias ();
// 2. Load products when user selects a category
const products = await getProductsByCategory ( selectedCategoryId );
Error Recovery
Implement retry logic for failed requests:
const fetchWithRetry = async ( fn , retries = 3 ) => {
for ( let i = 0 ; i < retries ; i ++ ) {
try {
return await fn ();
} catch ( error ) {
if ( i === retries - 1 ) throw error ;
await new Promise ( resolve => setTimeout ( resolve , 1000 * ( i + 1 )));
}
}
};
const categories = await fetchWithRetry (() => getCategorias ());
Type Safety
For TypeScript projects, define interfaces:
interface Category {
id : number ;
name : string ;
icon : string ;
}
interface Product {
id : number ;
name : string ;
price : number ;
imageUrl : string ;
badge : string | null ;
}
export const getCategorias = async () : Promise < Category []> => {
const res = await fetch ( ` ${ BASE_URL } /categories` );
if ( ! res . ok ) throw new Error ( "Error al cargar categorías" );
return res . json ();
};
Next Steps
See Real Usage Examples Learn how these functions are used in actual components from the Q-Sopa codebase