Overview
The Customer role represents regular users of the restaurant system who can browse the menu, add items to their cart, place orders, and view their order history. Customers do not require special permissions and have access to public-facing features.
Customers can browse the menu without authentication, but must be logged in to add items to cart and place orders.
User Authentication
Customers can access the system through standard authentication:
// routes/web.php - Line 29
Route :: get ( '/redirects' , [ HomeController :: class , 'redirects' ])
-> middleware ( 'auth' )
-> name ( 'redirects' );
Post-Login Redirect
After login, customers are redirected based on their role:
// app/Http/Controllers/HomeController.php - Lines 38-62
public function redirects ( Request $request )
{
$user = Auth :: user ();
if ( ! $user ) {
return redirect () -> route ( 'home' );
}
// Staff roles redirect to admin panel
if ( method_exists ( $user , 'hasRole' )) {
if ( $user -> hasAnyRole ([ 'admin' , 'chef' , 'mesero' ])) {
return redirect () -> route ( 'admin.dashboard' );
}
}
// Regular customers redirect to home
switch ( $user -> usertype ?? null ) {
case 'admin' :
case 'chef' :
case 'mesero' :
return redirect () -> route ( 'admin.dashboard' );
default :
return redirect () -> route ( 'home' );
}
}
Public Features
Browse Menu View all available dishes with descriptions and pricing.
View Categories Filter menu items by category (appetizers, mains, desserts, etc.).
Item Details See detailed information including ingredients, nutrition, and allergens.
Chef Profiles Learn about the restaurant’s culinary team.
Public Routes
// routes/web.php - Lines 28-32
Route :: get ( '/' , [ HomeController :: class , 'index' ]) -> name ( 'home' );
Route :: get ( '/comidaview' , [ HomeController :: class , 'comidaview' ]) -> name ( 'comidaview' );
Route :: get ( '/menu' , [ HomeController :: class , 'comidaview' ]) -> name ( 'menu' );
Route :: get ( '/infocomida/{food}' , [ HomeController :: class , 'infocomida' ]) -> name ( 'infocomida' );
Home Page
// app/Http/Controllers/HomeController.php - Lines 22-32
public function index ()
{
// Paginated menu items to optimize performance
$foods = Food :: with ( 'category' ) -> latest () -> paginate ( 12 );
$chefs = Chef :: all ();
$user = Auth :: user ();
$count = $user ? Cart :: where ( 'user_id' , $user -> id ) -> count () : 0 ;
$categories = Category :: withCount ( 'foods' ) -> get ();
return view ( 'home' , compact ( 'foods' , 'chefs' , 'count' , 'categories' ));
}
// app/Http/Controllers/HomeController.php - Lines 67-74
public function comidaview ()
{
$foods = Food :: with ( 'category' ) -> paginate ( 24 );
$user = Auth :: user ();
$count = $user ? Cart :: where ( 'user_id' , $user -> id ) -> count () : 0 ;
return view ( 'comidaview' , compact ( 'foods' , 'count' ));
}
Viewing Item Details
// app/Http/Controllers/HomeController.php - Lines 79-82
public function infocomida ( Food $food )
{
return view ( 'infocomida' , compact ( 'food' ));
}
Add to Cart Add items with specified quantities to your cart.
View Cart Review all items before placing order.
Update Quantity Modify item quantities in your cart.
Remove Items Delete items you no longer want.
Cart Routes
// routes/web.php - Lines 39-42
Route :: middleware ([ 'auth' ]) -> group ( function () {
Route :: get ( '/cart' , [ CartController :: class , 'index' ]) -> name ( 'cart.index' );
Route :: post ( '/cart/{food}' , [ CartController :: class , 'store' ]) -> name ( 'cart.store' );
Route :: delete ( '/cart/{cart}' , [ CartController :: class , 'destroy' ]) -> name ( 'cart.destroy' );
});
Viewing Cart
Login Required
Customer must be authenticated to access their cart.
Navigate to Cart
Access cart page at /cart to see all added items.
Review Items
Check item names, quantities, prices, and total amount.
Proceed to Checkout
Continue to order confirmation when ready.
// app/Http/Controllers/CartController.php - Lines 17-35
public function index () : View
{
$user = Auth :: user ();
if ( ! $user ) {
return redirect () -> route ( 'login' );
}
// Get cart items with food details
$items = Cart :: with ( 'food' )
-> where ( 'user_id' , $user -> id )
-> get ();
$count = $items -> count ();
return view ( 'showcart' , [
'items' => $items ,
'count' => $count ,
]);
}
Adding to Cart
// app/Http/Controllers/CartController.php - Lines 41-59
public function store ( Request $request , Food $food ) : RedirectResponse
{
$request -> validate ([
'quantity' => 'required|integer|min:1' ,
]);
$user = Auth :: user ();
if ( ! $user ) {
return redirect () -> route ( 'login' )
-> with ( 'error' , 'Debes iniciar sesión para añadir al carrito.' );
}
// Update existing or create new cart item
Cart :: updateOrCreate (
[ 'user_id' => $user -> id , 'food_id' => $food -> id ],
[ 'quantity' => $request -> input ( 'quantity' )]
);
return redirect () -> back () -> with ( 'success' , 'Producto agregado al carrito.' );
}
The system uses updateOrCreate to prevent duplicate items in the cart. If the item already exists, it updates the quantity instead of creating a duplicate.
Removing from Cart
// app/Http/Controllers/CartController.php - Lines 65-77
public function destroy ( Cart $cart ) : RedirectResponse
{
$user = Auth :: user ();
// Security: only owner can remove items
if ( ! $user || $cart -> user_id !== $user -> id ) {
abort ( 403 , 'No autorizado.' );
}
$cart -> delete ();
return redirect () -> back () -> with ( 'success' , 'Item eliminado del carrito.' );
}
Order Placement
Customers can place orders with delivery information.
Order Route
// routes/web.php - Line 44
Route :: post ( '/orderconfirm' , [ HomeController :: class , 'orderConfirm' ]) -> name ( 'order.confirm' );
Order Workflow
Review Cart
Check all items and quantities in your cart at /cart.
Enter Details
Provide customer name, phone number, and delivery address.
Confirm Order
Submit the order - system validates all information.
Process Payment
Order is created with ‘pending’ status and total amount calculated.
Clear Cart
Successfully ordered items are removed from cart automatically.
Order Confirmation Logic
// app/Http/Controllers/HomeController.php - Lines 110-212
public function orderConfirm ( Request $request )
{
// Validate customer information
$request -> validate ([
'name' => 'required|string|max:255' ,
'phone' => 'required|string|max:40' ,
'address' => 'nullable|string' ,
]);
$user = Auth :: user ();
$items = $request -> input ( 'items' );
// Process order in transaction
DB :: beginTransaction ();
try {
// Create order
$order = Order :: create ([
'user_id' => $user ? $user -> id : null ,
'customer_name' => $request -> name ,
'phone' => $request -> phone ,
'address' => $request -> address ,
'total' => 0 ,
'status' => 'pending' ,
]);
// Create order items
$total = 0 ;
foreach ( $normalized as $it ) {
$orderItem = $order -> items () -> create ([
'food_id' => $it [ 'food_id' ] ?? null ,
'title' => $it [ 'title' ],
'price' => $it [ 'price' ],
'quantity' => $it [ 'quantity' ],
'subtotal' => $it [ 'subtotal' ],
]);
$total += $it [ 'subtotal' ];
}
$order -> update ([ 'total' => $total ]);
// Clear cart items
if ( $user ) {
$foodIds = array_filter ( array_column ( $normalized , 'food_id' ));
if ( count ( $foodIds ) > 0 ) {
Cart :: where ( 'user_id' , $user -> id )
-> whereIn ( 'food_id' , $foodIds )
-> delete ();
}
}
DB :: commit ();
return redirect () -> route ( 'home' )
-> with ( 'success' , 'Orden creada correctamente. ID: ' . $order -> id );
} catch ( \ Throwable $e ) {
DB :: rollBack ();
return redirect () -> back ()
-> with ( 'error' , 'No se pudo procesar la orden. Intente de nuevo.' );
}
}
Order Data Structure
Each order includes:
Field Type Required Description user_id integer No Foreign key to users (null for guests) customer_name string Yes Name for delivery phone string Yes Contact phone number address string No Delivery address total decimal Yes Total order amount (auto-calculated) status string Yes Order status (pending, confirmed, delivered)
Order Items
Each order contains multiple order items:
Field Type Description order_id integer Foreign key to orders food_id integer Foreign key to foods title string Item name (snapshot) price decimal Price at time of order quantity integer Number of items ordered subtotal decimal Price × Quantity
Order items store a snapshot of the food name and price at the time of order, so historical orders remain accurate even if menu items are updated or deleted.
Available Features
Menu Browsing View all dishes with categories and filters
Item Details See ingredients, nutrition, and pricing details
Cart Management Add, update, and remove items from cart
Order Placement Place orders with delivery information
Category Filtering Browse menu by food categories
Chef Profiles View information about restaurant chefs
Customer Workflows
Browse and Order Workflow
Browse Menu
Visit homepage or /menu to see all available dishes.
Filter by Category
Use category filters to find specific types of food.
View Details
Click on items to see ingredients, calories, and full description.
Add to Cart
Select quantity and add desired items to your cart.
Review Cart
Navigate to /cart to verify all items and quantities.
Place Order
Enter delivery details and confirm your order.
Cart Management Workflow
Login First
Authenticate to enable cart functionality.
Add Multiple Items
Browse menu and add different dishes to your cart.
Review Selections
Check cart to see all items and total price.
Modify as Needed
Update quantities or remove items you no longer want.
Proceed to Checkout
When satisfied, move forward with order placement.
API Examples
Add Item to Cart
POST /cart/5
Content-Type: application/json
Authorization: Bearer {token}
{
"quantity" : 2
}
View Cart
GET /cart
Authorization: Bearer {token}
Remove from Cart
DELETE /cart/12
Authorization: Bearer {token}
Place Order
POST /orderconfirm
Content-Type: application/json
Authorization: Bearer {token}
{
"name" : "John Doe",
"phone" : "+1234567890",
"address" : "123 Main St, Apartment 4B",
"items" : [
{
"food_id" : 5,
"quantity" : 2
},
{
"food_id" : 8,
"quantity" : 1
}
]
}
Guest Ordering
The system supports guest checkout - users can place orders without creating an account, though they must still provide contact information for delivery.
For guest orders, the user_id field is set to null:
$order = Order :: create ([
'user_id' => $user ? $user -> id : null , // null for guests
'customer_name' => $request -> name ,
'phone' => $request -> phone ,
'address' => $request -> address ,
'total' => 0 ,
'status' => 'pending' ,
]);
Security Features
Cart Ownership Validation
The system ensures customers can only access and modify their own cart items:
if ( ! $user || $cart -> user_id !== $user -> id ) {
abort ( 403 , 'No autorizado.' );
}
Transaction Safety
Order placement uses database transactions to ensure data consistency:
DB :: beginTransaction ();
try {
// Create order and items
DB :: commit ();
} catch ( \ Throwable $e ) {
DB :: rollBack ();
// Handle error
}
All customer inputs are validated:
Name: Required, max 255 characters
Phone: Required, max 40 characters
Address: Optional string
Quantity: Required integer, minimum 1
Best Practices
Review Before Ordering - Always check cart contents before placing order
Accurate Information - Provide correct phone and address for delivery
Clear Cart - Remove items you don’t want rather than leaving them
Check Details - Read item descriptions for allergies and preferences
Save Time - Use category filters to find items quickly
Guest Checkout - You can order without an account, but creating one provides order history