How I Built a Chicken Meat Ordering Website with WhatsApp Checkout and Admin Panel

in a time where speed and convenience dominate the shopping experience, I decided to build something different: Chicken Realtor, a quick-commerce web platform dedicated to selling fresh chicken meats online. This wasn’t just another eCommerce site — it’s a streamlined solution that connects buyers and sellers instantly using WhatsApp, while giving admins full control of products and orders through a custom dashboard.

In this blog post, I’ll walk you through how I planned, built, and deployed this smart poultry sales system.


💡 The Idea Behind Chicken Realtor

Many local meat businesses still rely on offline methods: phone calls, walk-ins, or inconsistent third-party apps. But what if they had a system that:

  • Showed all available chicken products in a beautiful layout
  • Let customers add items to a cart and quickly check out
  • Used WhatsApp to finalize orders (no need for complex payment gateways)
  • Gave the admin a full dashboard to manage inventory and view orders

That’s exactly what Chicken Realtor solves.


🔧 Tech Stack Used

I chose a tech stack that’s lightweight but powerful:

  • Frontend: HTML, CSS (Tailwind CSS), JavaScript
  • Backend: PHP with MySQL for database interactions
  • Integration: WhatsApp Checkout via wa.me API
  • Hosting: cPanel + Shared Hosting for quick deployment

Frontend Features

  • Product Categories: Boneless, Drumsticks, Wings, Full Chicken
  • Dynamic Cart System: Users can increase/decrease quantity, see real-time updates
  • Checkout via WhatsApp: Once ready, a pre-filled message is sent with product list + quantity + total + user info
  • Responsive UI: Designed mobile-first using TailwindCSS

Backend & Admin Panel Features

  • Admin Login: Secured with session-based auth
  • Product Management: Add/edit/delete chicken items with image upload
  • Order Tracker: View past orders placed via WhatsApp (stored in DB)
  • Status Control: Update order status (Pending, Completed, Cancelled)
  • CSV Export: Downloadable order report

Why WhatsApp Checkout?

  • No payment gateway needed (less friction for the user)
  • Direct communication between seller and buyer
  • Familiar UX: Customers already use WhatsApp; no new app required

SEO & Performance Considerations

  • Optimized image loading using loading="lazy"
  • Structured content with proper H1, H2, and meta tags
  • Minimal JS for faster load
  • Canonical tags and alt tags for accessibility

Index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Chicken Realtor - Home</title>
    <link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?display=swap&family=Noto+Sans:wght@400;500;700;900&family=Space+Grotesk:wght@400;500;700">
    <script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
    <style>
        /* Custom styles for the cart bubble and toast */
        .cart-bubble {
            position: absolute;
            top: -5px;
            right: -10px;
            background-color: #f37a24;
            color: white;
            border-radius: 50%;
            width: 20px;
            height: 20px;
            font-size: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
        }
        #toast {
            position: fixed;
            bottom: 80px;
            left: 50%;
            transform: translateX(-50%);
            background-color: #1c130d;
            color: white;
            padding: 10px 20px;
            border-radius: 8px;
            z-index: 1000;
            transition: opacity 0.5s;
        }
    </style>
</head>
<body class="bg-[#fcfaf8]" style="font-family: 'Space Grotesk', 'Noto Sans', sans-serif;">
    <div class="relative flex size-full min-h-screen flex-col justify-between group/design-root overflow-x-hidden">
        <!-- Main Content -->
        <div>
            <!-- Header -->
            <div class="flex items-center bg-[#fcfaf8] p-4 pb-2 justify-between sticky top-0 z-10">
                <div class="w-12"></div> <!-- Spacer -->
                <h1 class="text-[#1c130d] text-lg font-bold leading-tight tracking-[-0.015em] flex-1 text-center">Chicken Realtor</h1>
                <div class="flex w-12 items-center justify-end">
                    <a href="cart.html" id="cart-icon" class="relative flex max-w-[480px] cursor-pointer items-center justify-center overflow-hidden rounded-lg h-12 bg-transparent text-[#1c130d] gap-2 text-base font-bold leading-normal tracking-[0.015em] min-w-0 p-0">
                        <div class="text-[#1c130d]">
                            <svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" fill="currentColor" viewBox="0 0 256 256"><path d="M222.14,58.87A8,8,0,0,0,216,56H54.68L49.79,29.14A16,16,0,0,0,34.05,16H16a8,8,0,0,0,0,16h18L59.56,172.29a24,24,0,0,0,5.33,11.27,28,28,0,1,0,44.4,8.44h45.42A27.75,27.75,0,0,0,152,204a28,28,0,1,0,28-28H83.17a8,8,0,0,1-7.87-6.57L72.13,152h116a24,24,0,0,0,23.61-19.71l12.16-66.86A8,8,0,0,0,222.14,58.87ZM96,204a12,12,0,1,1-12-12A12,12,0,0,1,96,204Zm96,0a12,12,0,1,1-12-12A12,12,0,0,1,192,204Zm4-74.57A8,8,0,0,1,188.1,136H69.22L57.59,72H206.41Z"></path></svg>
                        </div>
                        <span class="cart-bubble hidden">0</span>
                    </a>
                </div>
            </div>

            <!-- Search -->
            <div class="px-4 py-3">
                <label class="flex flex-col min-w-40 h-12 w-full">
                    <div class="flex w-full flex-1 items-stretch rounded-lg h-full">
                        <div class="text-[#9c6c49] flex border-none bg-[#f4ece7] items-center justify-center pl-4 rounded-l-lg border-r-0">
                            <svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" fill="currentColor" viewBox="0 0 256 256"><path d="M229.66,218.34l-50.07-50.06a88.11,88.11,0,1,0-11.31,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z"></path></svg>
                        </div>
                        <input placeholder="Search for chicken" class="form-input flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-lg text-[#1c130d] focus:outline-0 focus:ring-0 border-none bg-[#f4ece7] focus:border-none h-full placeholder:text-[#9c6c49] px-4 rounded-l-none border-l-0 pl-2 text-base font-normal leading-normal" value="">
                    </div>
                </label>
            </div>

            <!-- Categories -->
            <div class="flex gap-3 p-3 overflow-x-auto">
                <div class="flex h-8 shrink-0 items-center justify-center gap-x-2 rounded-lg bg-[#f4ece7] pl-4 pr-4"><p class="text-[#1c130d] text-sm font-medium leading-normal">Raw Chicken</p></div>
                <div class="flex h-8 shrink-0 items-center justify-center gap-x-2 rounded-lg bg-[#f4ece7] pl-4 pr-4"><p class="text-[#1c130d] text-sm font-medium leading-normal">Marinated</p></div>
                <div class="flex h-8 shrink-0 items-center justify-center gap-x-2 rounded-lg bg-[#f4ece7] pl-4 pr-4"><p class="text-[#1c130d] text-sm font-medium leading-normal">Chicken Parts</p></div>
            </div>

            <!-- Product List Container -->
            <div id="product-list-container">
                <!-- Products will be dynamically inserted here by script.js -->
            </div>
        </div>

        <!-- Bottom Navigation -->
        <div class="sticky bottom-0">
            <div class="flex gap-2 border-t border-[#f4ece7] bg-[#fcfaf8] px-4 pb-3 pt-2">
                <a class="flex flex-1 flex-col items-center justify-end gap-1 rounded-full text-[#1c130d]" href="index.html">
                    <div class="text-[#1c130d] flex h-8 items-center justify-center"><svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" fill="currentColor" viewBox="0 0 256 256"><path d="M224,115.55V208a16,16,0,0,1-16,16H168a16,16,0,0,1-16-16V168a8,8,0,0,0-8-8H112a8,8,0,0,0-8,8v40a16,16,0,0,1-16,16H48a16,16,0,0,1-16-16V115.55a16,16,0,0,1,5.17-11.78l80-75.48.11-.11a16,16,0,0,1,21.53,0,1.14,1.14,0,0,0,.11.11l80,75.48A16,16,0,0,1,224,115.55Z"></path></svg></div>
                    <p class="text-[#1c130d] text-xs font-medium leading-normal tracking-[0.015em]">Home</p>
                </a>
                <a class="flex flex-1 flex-col items-center justify-end gap-1 text-[#9c6c49]" href="#">
                    <div class="text-[#9c6c49] flex h-8 items-center justify-center"><svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" fill="currentColor" viewBox="0 0 256 256"><path d="M80,64a8,8,0,0,1,8-8H216a8,8,0,0,1,0,16H88A8,8,0,0,1,80,64Zm136,56H88a8,8,0,0,0,0,16H216a8,8,0,0,0,0-16Zm0,64H88a8,8,0,0,0,0,16H216a8,8,0,0,0,0-16ZM44,52A12,12,0,1,0,56,64,12,12,0,0,0,44,52Zm0,64a12,12,0,1,0,12,12A12,12,0,0,0,44,116Zm0,64a12,12,0,1,0,12,12A12,12,0,0,0,44,180Z"></path></svg></div>
                    <p class="text-[#9c6c49] text-xs font-medium leading-normal tracking-[0.015em]">Categories</p>
                </a>
                <a class="flex flex-1 flex-col items-center justify-end gap-1 text-[#9c6c49]" href="cart.html">
                    <div class="text-[#9c6c49] flex h-8 items-center justify-center"><svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" fill="currentColor" viewBox="0 0 256 256"><path d="M222.14,58.87A8,8,0,0,0,216,56H54.68L49.79,29.14A16,16,0,0,0,34.05,16H16a8,8,0,0,0,0,16h18L59.56,172.29a24,24,0,0,0,5.33,11.27,28,28,0,1,0,44.4,8.44h45.42A27.75,27.75,0,0,0,152,204a28,28,0,1,0,28-28H83.17a8,8,0,0,1-7.87-6.57L72.13,152h116a24,24,0,0,0,23.61-19.71l12.16-66.86A8,8,0,0,0,222.14,58.87ZM96,204a12,12,0,1,1-12-12A12,12,0,0,1,96,204Zm96,0a12,12,0,1,1-12-12A12,12,0,0,1,192,204Zm4-74.57A8,8,0,0,1,188.1,136H69.22L57.59,72H206.41Z"></path></svg></div>
                    <p class="text-[#9c6c49] text-xs font-medium leading-normal tracking-[0.015em]">Cart</p>
                </a>
                <a class="flex flex-1 flex-col items-center justify-end gap-1 text-[#9c6c49]" href="#">
                    <div class="text-[#9c6c49] flex h-8 items-center justify-center"><svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" fill="currentColor" viewBox="0 0 256 256"><path d="M230.92,212c-15.23-26.33-38.7-45.21-66.09-54.16a72,72,0,1,0-73.66,0C63.78,166.78,40.31,185.66,25.08,212a8,8,0,1,0,13.85,8c18.84-32.56,52.14-52,89.07-52s70.23,19.44,89.07,52a8,8,0,1,0,13.85-8ZM72,96a56,56,0,1,1,56,56A56.06,56.06,0,0,1,72,96Z"></path></svg></div>
                    <p class="text-[#9c6c49] text-xs font-medium leading-normal tracking-[0.015em]">Profile</p>
                </a>
            </div>
            <div class="h-5 bg-[#fcfaf8]"></div>
        </div>
    </div>
    
    <!-- Toast Notification -->
    <div id="toast" class="hidden"></div>

    <script src="script.js"></script>
</body>
</html>

product-detail.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Product Details</title>
    <link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?display=swap&family=Noto+Sans:wght@400;500;700;900&family=Space+Grotesk:wght@400;500;700">
    <script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
    <style>
        .cart-bubble {
            position: absolute;
            top: -5px;
            right: -10px;
            background-color: #f37a24;
            color: white;
            border-radius: 50%;
            width: 20px;
            height: 20px;
            font-size: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
        }
        #toast {
            position: fixed;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            background-color: #1c130d;
            color: white;
            padding: 10px 20px;
            border-radius: 8px;
            z-index: 1000;
            transition: opacity 0.5s;
        }
    </style>
</head>
<body class="bg-[#fcfaf8]" style="font-family: 'Space Grotesk', 'Noto Sans', sans-serif;">
    <div class="relative flex size-full min-h-screen flex-col justify-between group/design-root overflow-x-hidden">
        <!-- Main Content -->
        <div>
            <!-- Header -->
            <div class="flex items-center bg-[#fcfaf8] p-4 pb-2 justify-between">
                <a href="index.html" class="text-[#1c130d] flex size-12 shrink-0 items-center">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" fill="currentColor" viewBox="0 0 256 256"><path d="M224,128a8,8,0,0,1-8,8H59.31l58.35,58.34a8,8,0,0,1-11.32,11.32l-72-72a8,8,0,0,1,0-11.32l72-72a8,8,0,0,1,11.32,11.32L59.31,120H216A8,8,0,0,1,224,128Z"></path></svg>
                </a>
                <h1 class="text-[#1c130d] text-lg font-bold leading-tight tracking-[-0.015em] flex-1 text-center">Product Details</h1>
                <div class="flex w-12 items-center justify-end">
                     <a href="cart.html" id="cart-icon" class="relative flex max-w-[480px] cursor-pointer items-center justify-center overflow-hidden rounded-lg h-12 bg-transparent text-[#1c130d] gap-2 text-base font-bold leading-normal tracking-[0.015em] min-w-0 p-0">
                        <div class="text-[#1c130d]">
                            <svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" fill="currentColor" viewBox="0 0 256 256"><path d="M222.14,58.87A8,8,0,0,0,216,56H54.68L49.79,29.14A16,16,0,0,0,34.05,16H16a8,8,0,0,0,0,16h18L59.56,172.29a24,24,0,0,0,5.33,11.27,28,28,0,1,0,44.4,8.44h45.42A27.75,27.75,0,0,0,152,204a28,28,0,1,0,28-28H83.17a8,8,0,0,1-7.87-6.57L72.13,152h116a24,24,0,0,0,23.61-19.71l12.16-66.86A8,8,0,0,0,222.14,58.87ZM96,204a12,12,0,1,1-12-12A12,12,0,0,1,96,204Zm96,0a12,12,0,1,1-12-12A12,12,0,0,1,192,204Zm4-74.57A8,8,0,0,1,188.1,136H69.22L57.59,72H206.41Z"></path></svg>
                        </div>
                        <span class="cart-bubble hidden">0</span>
                    </a>
                </div>
            </div>

            <!-- Product Detail Container -->
            <div id="product-detail-container" class="p-4">
                <!-- Product details will be dynamically inserted here -->
            </div>
        </div>
    </div>
    
    <!-- Toast Notification -->
    <div id="toast" class="hidden"></div>

    <script src="script.js"></script>
</body>
</html>

cart.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Your Cart</title>
    <link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?display=swap&family=Noto+Sans:wght@400;500;700;900&family=Space+Grotesk:wght@400;500;700">
    <script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
    <style>
        /* Style for quantity buttons */
        .quantity-btn {
            background-color: #f4ece7;
            color: #1c130d;
            border-radius: 50%;
            width: 24px;
            height: 24px;
            font-weight: bold;
            border: 1px solid #e0d5cb;
        }
    </style>
</head>
<body class="bg-[#fcfaf8]" style="font-family: 'Space Grotesk', 'Noto Sans', sans-serif;">
    <div class="relative flex size-full min-h-screen flex-col bg-[#fcfaf8] justify-between group/design-root overflow-x-hidden">
        <!-- Main Content -->
        <div>
            <!-- Header -->
            <div class="flex items-center bg-[#fcfaf8] p-4 pb-2 justify-between">
                <a href="index.html" class="text-[#1c130d] flex size-12 shrink-0 items-center -ml-4">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" fill="currentColor" viewBox="0 0 256 256"><path d="M224,128a8,8,0,0,1-8,8H59.31l58.35,58.34a8,8,0,0,1-11.32,11.32l-72-72a8,8,0,0,1,0-11.32l72-72a8,8,0,0,1,11.32,11.32L59.31,120H216A8,8,0,0,1,224,128Z"></path></svg>
                </a>
                <h1 class="text-[#1c130d] text-lg font-bold leading-tight tracking-[-0.015em] flex-1 text-center pr-8">Cart</h1>
            </div>

            <!-- Cart Items Container -->
            <div id="cart-items-container">
                <!-- Cart items will be dynamically inserted here -->
            </div>

            <!-- Totals Section -->
            <div class="px-4 pt-4">
                <div class="flex items-center gap-4 bg-[#fcfaf8] min-h-14 justify-between">
                    <p class="text-[#1c130d] text-base font-normal leading-normal flex-1 truncate">Subtotal</p>
                    <div class="shrink-0"><p id="subtotal-amount" class="text-[#1c130d] text-base font-normal leading-normal">$0.00</p></div>
                </div>
                <div class="flex items-center gap-4 bg-[#fcfaf8] min-h-14 justify-between">
                    <p class="text-[#1c130d] text-base font-normal leading-normal flex-1 truncate">Shipping</p>
                    <div class="shrink-0"><p id="shipping-amount" class="text-[#1c130d] text-base font-normal leading-normal">$0.00</p></div>
                </div>
                <div class="flex items-center gap-4 bg-[#fcfaf8] min-h-14 justify-between border-t border-[#f4ece7] pt-2">
                    <p class="text-[#1c130d] text-base font-bold leading-normal flex-1 truncate">Total</p>
                    <div class="shrink-0"><p id="total-amount" class="text-[#1c130d] text-base font-bold leading-normal">$0.00</p></div>
                </div>
            </div>
        </div>

        <!-- Checkout Button -->
        <div class="p-4">
            <a href="checkout.html" class="flex min-w-[84px] max-w-[480px] cursor-pointer items-center justify-center overflow-hidden rounded-lg h-12 px-5 flex-1 bg-[#f37a24] text-white text-base font-bold leading-normal tracking-[0.015em]">
                <span class="truncate">Proceed to Checkout</span>
            </a>
            <div class="h-5 bg-[#fcfaf8]"></div>
        </div>
    </div>

    <script src="script.js"></script>
</body>
</html>

checkout.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Checkout</title>
    <link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?display=swap&family=Noto+Sans:wght@400;500;700;900&family=Space+Grotesk:wght@400;500;700">
    <script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
</head>
<body class="bg-[#fcfaf8]" style="font-family: 'Space Grotesk', 'Noto Sans', sans-serif;">
    <div class="relative flex size-full min-h-screen flex-col bg-[#fcfaf8] justify-between group/design-root overflow-x-hidden">
        <!-- Main Content -->
        <div>
            <!-- Header -->
            <div class="flex items-center bg-[#fcfaf8] p-4 pb-2 justify-between">
                <a href="cart.html" class="text-[#1c130d] flex size-12 shrink-0 items-center -ml-4">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" fill="currentColor" viewBox="0 0 256 256"><path d="M224,128a8,8,0,0,1-8,8H59.31l58.35,58.34a8,8,0,0,1-11.32,11.32l-72-72a8,8,0,0,1,0-11.32l72-72a8,8,0,0,1,11.32,11.32L59.31,120H216A8,8,0,0,1,224,128Z"></path></svg>
                </a>
                <h1 class="text-[#1c130d] text-lg font-bold leading-tight tracking-[-0.015em] flex-1 text-center pr-8">Checkout</h1>
            </div>

            <!-- Order Summary -->
            <h2 class="text-[#1c130d] text-lg font-bold leading-tight tracking-[-0.015em] px-4 pb-2 pt-4">Order Summary</h2>
            <div id="checkout-summary-container">
                <!-- Checkout summary will be dynamically inserted here -->
            </div>

            <!-- Delivery Details -->
            <h2 class="text-[#1c130d] text-lg font-bold leading-tight tracking-[-0.015em] px-4 pb-2 pt-4">Delivery Details</h2>
            <div class="px-4 space-y-4">
                <label class="flex flex-col">
                    <p class="text-[#1c130d] text-base font-medium leading-normal pb-2">Name</p>
                    <input id="name" placeholder="Enter your full name" class="form-input flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-lg text-[#1c130d] focus:outline-0 focus:ring-2 focus:ring-[#f37a24] border-none bg-[#f4ece7] h-14 placeholder:text-[#9c6c49] p-4 text-base font-normal leading-normal">
                </label>
                <label class="flex flex-col">
                    <p class="text-[#1c130d] text-base font-medium leading-normal pb-2">Address</p>
                    <input id="address" placeholder="Enter your full address" class="form-input flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-lg text-[#1c130d] focus:outline-0 focus:ring-2 focus:ring-[#f37a24] border-none bg-[#f4ece7] h-14 placeholder:text-[#9c6c49] p-4 text-base font-normal leading-normal">
                </label>
                <label class="flex flex-col">
                    <p class="text-[#1c130d] text-base font-medium leading-normal pb-2">City</p>
                    <input id="city" placeholder="Enter your city" class="form-input flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-lg text-[#1c130d] focus:outline-0 focus:ring-2 focus:ring-[#f37a24] border-none bg-[#f4ece7] h-14 placeholder:text-[#9c6c49] p-4 text-base font-normal leading-normal">
                </label>
                <label class="flex flex-col">
                    <p class="text-[#1c130d] text-base font-medium leading-normal pb-2">Zip Code</p>
                    <input id="zip" type="tel" placeholder="Enter your zip code" class="form-input flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-lg text-[#1c130d] focus:outline-0 focus:ring-2 focus:ring-[#f37a24] border-none bg-[#f4ece7] h-14 placeholder:text-[#9c6c49] p-4 text-base font-normal leading-normal">
                </label>
            </div>
            
            <!-- Totals Section -->
            <h2 class="text-[#1c130d] text-lg font-bold leading-tight tracking-[-0.015em] px-4 pb-2 pt-4">Total</h2>
             <div class="px-4">
                <div class="flex items-center gap-4 bg-[#fcfaf8] min-h-14 justify-between">
                    <p class="text-[#1c130d] text-base font-normal leading-normal flex-1 truncate">Subtotal</p>
                    <div class="shrink-0"><p id="subtotal-amount" class="text-[#1c130d] text-base font-normal leading-normal">$0.00</p></div>
                </div>
                <div class="flex items-center gap-4 bg-[#fcfaf8] min-h-14 justify-between">
                    <p class="text-[#1c130d] text-base font-normal leading-normal flex-1 truncate">Shipping</p>
                    <div class="shrink-0"><p id="shipping-amount" class="text-[#1c130d] text-base font-normal leading-normal">$0.00</p></div>
                </div>
                <div class="flex items-center gap-4 bg-[#fcfaf8] min-h-14 justify-between border-t border-[#f4ece7] pt-2">
                    <p class="text-[#1c130d] text-base font-bold leading-normal flex-1 truncate">Total</p>
                    <div class="shrink-0"><p id="total-amount" class="text-[#1c130d] text-base font-bold leading-normal">$0.00</p></div>
                </div>
            </div>
        </div>

        <!-- Checkout Button -->
        <div class="p-4">
            <button id="whatsapp-checkout-btn" class="flex min-w-[84px] max-w-[480px] cursor-pointer items-center justify-center overflow-hidden rounded-lg h-12 px-5 flex-1 bg-[#25D366] text-white text-base font-bold leading-normal tracking-[0.015em]">
                <span class="truncate">Checkout on WhatsApp</span>
            </button>
            <div class="h-5 bg-[#fcfaf8]"></div>
        </div>
    </div>

    <script src="script.js"></script>
</body>
</html>

script.js

// This script will be linked to all your HTML pages.
// It uses localStorage to remember the cart contents even if the user closes the browser.

document.addEventListener('DOMContentLoaded', () => {
    // --- DATA ---
    // Product data. In a real application, this would come from a database.
    const products = [
        {
            id: 1,
            name: 'Whole Chicken',
            category: 'Fresh',
            price: 5.99,
            unit: 'kg',
            image: 'https://lh3.googleusercontent.com/aida-public/AB6AXuAXVUcp24HVw4TEvMJ6lG2nECTa3_9a_rXHbo0vMss5R_V1o2q9AYyEM6kw81UjduMPE21TVZ1mLq3-G3SQTN_qNsUTAXQF297on6v4j1CJIJuJ-p9bCEHhiSIu-6B8poEOPVi2sOOVTXG81sI1IgWM0ZR2_WLKXpwHvNc-fMbAnjk6J6v2ifXIU2KVbJ5dEW30HPHOUJ6yrhqlnme1JCjaic0oq35XARf8a9uoApu8xTfoBuL4HvHmnKtI7VUdOvaT1MzwfIWYTCGu'
        },
        {
            id: 2,
            name: 'Chicken Breast',
            category: 'Fresh',
            price: 7.99,
            unit: 'kg',
            image: 'https://lh3.googleusercontent.com/aida-public/AB6AXuDFU-pZshccrj9ripa2XwD0xH0l3eQTPz36QWo3VxdGNzj-KIzMScJMl-wCA9ldlx_CrZSK170Vkt7YkzhjZgFWtLgT_qGo2Q6inYQjB2oNl7PhCGP1ZbQHbRdVZ6brRZ68zaPw04Ay9e8Zj6NI6BAEVpNN1BCltVKnnJ3VNw61IlShCkFvJGjZiYG-HQ9aVlTZDodb6k-d6olYNSDC5ReSHvl2jGdzyYudi7h2RyQyTDKIzwOHW8Dsx4-XTH5j8CvUm0NPqrFYhKZK'
        },
        {
            id: 3,
            name: 'Lemon Herb Chicken',
            category: 'Marinated',
            price: 6.49,
            unit: 'kg',
            image: 'https://lh3.googleusercontent.com/aida-public/AB6AXuCSDATvYXg_oSJIpKdGhfg0dHKbLDyPanT4kjigDMBDYihPl0A-oeahskOkhrsz_Pk9ovYLb9avh1e6kI5FvYKGFpFjSFMeW6xw4B0RiZF8QqRLoH6txqQSngpfvRuHzZOX4hbmy2F11DYvAeGhfwTpqUpm6bZQCSQ2AaaSZhHe_4OWsuzGXP3lEqN2AO_ISfi7E5C8NNZwAC66i1vPKTU9nUtJJdBdFlsJn0WD94T69YcvNXJfWeSihEoaECs5TBcJwSgPnfQ-ehEF'
        },
        {
            id: 4,
            name: 'Chicken Thighs',
            category: 'Fresh',
            price: 4.99,
            unit: 'kg',
            image: 'https://lh3.googleusercontent.com/aida-public/AB6AXuChSMYS1oMTW2pku_6Fra6QmNSRHFslLM3wAOhBsCinV3uwAlWDrqo8wnq8qqxTcptvA6QzKqyvVvqyQoHZxIKw7yfuC7CzFCDsjznOfeqh7mkuBYNJA-kNovRahyzSmlLHn0Cudh1HjOZ7WWCyEYF58InZDzcMZnA5n6ADqJRQt_3xM832DK0kph5aM6CKZr4lvPFuvwbRBqyhhd0g2lnH0BvlSjUt6HIYRbDbVgkuTYy93uQtoMyAE6M7Ogx7vm84cjG5CwFjyvVi'
        },
        {
            id: 5,
            name: 'Spicy Chicken Wings',
            category: 'Marinated',
            price: 5.49,
            unit: 'kg',
            image: 'https://lh3.googleusercontent.com/aida-public/AB6AXuB93QuJ-e6eWFCCfqcam4FHtYRu9wWheGf8lHhJrUA8bUE8_AMDRfuZOBkvhDglY2Vrp4UycC2MlqA0P5LXdUo1fEl7RCgFc5yTfN7Vb2THOVBZC5bNG73Z2pgDl3EQswz8BkrP_zocIctfvyHFowJ8CtJWGhyv1jrh2BO7WYlwvdVdFuN4v0xhb5uTWn7beBT84LT6U67QsuCitI1Pzv3j-FJR_H8oX4ZtXb6rNPaDBHyF2FKVSz376F8c7uuUU2_rjxU2s1zHK4gg'
        },
        {
            id: 6,
            name: 'Chicken Drumsticks',
            category: 'Fresh',
            price: 3.99,
            unit: 'kg',
            image: 'https://lh3.googleusercontent.com/aida-public/AB6AXuAt59suoZMhFd1fU1HI61nsdLG3Tjb5L4C57p8oCJlrwGoeWsXhBZ2utCx4YYEtDRBPDgxAbnI3MXT9E8BNOEwi_aSjzfXQrRb70rU3uR5Gn3FfmZFY5A0dzrMQ5TpYyQXbhMzsvZ4XCltLu-eMCHGg8CYqkiN0g_-VmOM2tm75go2NdAw9amiCuh4sA6QgX79Vf3LOK8AYV830dzy31b-eIKq7rB5SqN7b-yA_yfjFKz80JM64d2iGnPlVnpKpAG8XT1RA6Q8etm4F'
        }
    ];

    // --- CART LOGIC ---
    // Function to get the cart from localStorage
    const getCart = () => {
        const cart = localStorage.getItem('chickenShopCart');
        return cart ? JSON.parse(cart) : [];
    };

    // Function to save the cart to localStorage
    const saveCart = (cart) => {
        localStorage.setItem('chickenShopCart', JSON.stringify(cart));
        updateCartIcon();
    };

    // Function to add an item to the cart
    const addToCart = (productId) => {
        const cart = getCart();
        const product = products.find(p => p.id === productId);
        if (!product) return;

        const existingItem = cart.find(item => item.id === productId);
        if (existingItem) {
            existingItem.quantity++;
        } else {
            cart.push({ id: productId, quantity: 1 });
        }
        saveCart(cart);
        
        // Show a confirmation message
        const toast = document.getElementById('toast');
        if (toast) {
            toast.textContent = `${product.name} added to cart!`;
            toast.classList.remove('hidden');
            setTimeout(() => {
                toast.classList.add('hidden');
            }, 2000);
        }
    };
    
    // Function to update item quantity in cart
    const updateQuantity = (productId, newQuantity) => {
        let cart = getCart();
        if (newQuantity <= 0) {
            cart = cart.filter(item => item.id !== productId);
        } else {
            const itemInCart = cart.find(item => item.id === productId);
            if (itemInCart) {
                itemInCart.quantity = newQuantity;
            }
        }
        saveCart(cart);
        // Re-render the page if we are on cart or checkout
        if (document.getElementById('cart-items-container') || document.getElementById('checkout-summary-container')) {
             location.reload();
        }
    };

    // Function to get total item count for the cart icon
    const getCartItemCount = () => {
        return getCart().reduce((total, item) => total + item.quantity, 0);
    };
    
    // Function to update the cart icon bubble
    const updateCartIcon = () => {
        const cartIcon = document.getElementById('cart-icon');
        if (cartIcon) {
            const itemCount = getCartItemCount();
            const bubble = cartIcon.querySelector('.cart-bubble');
            if (bubble) {
                 if (itemCount > 0) {
                    bubble.textContent = itemCount;
                    bubble.classList.remove('hidden');
                } else {
                    bubble.classList.add('hidden');
                }
            }
        }
    };


    // --- PAGE-SPECIFIC RENDERING ---

    // Render product list on index.html
    const renderProducts = () => {
        const container = document.getElementById('product-list-container');
        if (!container) return;

        container.innerHTML = ''; // Clear existing content
        products.forEach(product => {
            const productCard = document.createElement('div');
            productCard.className = 'p-4';
            productCard.innerHTML = `
                <div class="flex items-stretch justify-between gap-4 rounded-lg cursor-pointer product-card" data-id="${product.id}">
                    <div class="flex flex-[2_2_0px] flex-col gap-4">
                        <div class="flex flex-col gap-1">
                            <p class="text-[#9c6c49] text-sm font-normal leading-normal">${product.category}</p>
                            <p class="text-[#1c130d] text-base font-bold leading-tight">${product.name}</p>
                            <p class="text-[#9c6c49] text-sm font-normal leading-normal">$${product.price.toFixed(2)} / ${product.unit}</p>
                        </div>
                        <button data-id="${product.id}" class="add-to-cart-btn flex min-w-[84px] max-w-[480px] cursor-pointer items-center justify-center overflow-hidden rounded-lg h-8 px-4 flex-row-reverse bg-[#f4ece7] text-[#1c130d] text-sm font-medium leading-normal w-fit">
                            <span class="truncate">Add to Cart</span>
                        </button>
                    </div>
                    <div class="w-full bg-center bg-no-repeat aspect-video bg-cover rounded-lg flex-1" style="background-image: url('${product.image}');"></div>
                </div>
            `;
            container.appendChild(productCard);
        });
        
        // Add event listeners after rendering
        document.querySelectorAll('.add-to-cart-btn').forEach(button => {
            button.addEventListener('click', (e) => {
                e.stopPropagation(); // Prevent card click when button is clicked
                const productId = parseInt(e.currentTarget.dataset.id);
                addToCart(productId);
            });
        });

        document.querySelectorAll('.product-card').forEach(card => {
            card.addEventListener('click', (e) => {
                const productId = parseInt(e.currentTarget.dataset.id);
                window.location.href = `product-detail.html?id=${productId}`;
            });
        });
    };
    
    // Render product details on product-detail.html
    const renderProductDetails = () => {
        const container = document.getElementById('product-detail-container');
        if (!container) return;

        const urlParams = new URLSearchParams(window.location.search);
        const productId = parseInt(urlParams.get('id'));
        const product = products.find(p => p.id === productId);

        if (!product) {
            container.innerHTML = '<p class="text-center text-[#1c130d]">Product not found.</p>';
            return;
        }

        container.innerHTML = `
            <div class="w-full h-64 bg-center bg-no-repeat bg-cover rounded-lg" style="background-image: url('${product.image}');"></div>
            <div class="p-4">
                <p class="text-[#9c6c49] text-sm font-normal leading-normal">${product.category}</p>
                <h2 class="text-[#1c130d] text-2xl font-bold leading-tight mt-1">${product.name}</h2>
                <p class="text-xl text-[#f37a24] font-bold mt-2">$${product.price.toFixed(2)} / ${product.unit}</p>
                <p class="text-[#9c6c49] mt-4">This is a placeholder description for our high-quality, farm-fresh ${product.name}. Perfect for any meal, guaranteed to be delicious and tender.</p>
                 <button data-id="${product.id}" class="add-to-cart-btn flex w-full mt-6 min-w-[84px] max-w-[480px] cursor-pointer items-center justify-center overflow-hidden rounded-lg h-12 px-5 bg-[#f37a24] text-white text-base font-bold leading-normal tracking-[0.015em]">
                    <span class="truncate">Add to Cart</span>
                </button>
            </div>
        `;
        
        // Add event listener
        document.querySelector('.add-to-cart-btn').addEventListener('click', (e) => {
            const productId = parseInt(e.currentTarget.dataset.id);
            addToCart(productId);
        });
    };

    // Render items in cart.html and checkout.html
    const renderCartItems = (containerId, isCheckout = false) => {
        const container = document.getElementById(containerId);
        if (!container) return;

        const cart = getCart();
        container.innerHTML = ''; // Clear
        let subtotal = 0;

        if (cart.length === 0) {
            container.innerHTML = '<p class="text-center text-[#9c6c49] p-4">Your cart is empty.</p>';
        } else {
            cart.forEach(item => {
                const product = products.find(p => p.id === item.id);
                if (product) {
                    subtotal += product.price * item.quantity;
                    const itemElement = document.createElement('div');
                    itemElement.className = 'flex items-center gap-4 bg-[#fcfaf8] px-4 min-h-[72px] py-2 justify-between';
                    itemElement.innerHTML = `
                        <div class="flex items-center gap-4 flex-1">
                            ${!isCheckout ? `<div class="bg-center bg-no-repeat aspect-square bg-cover rounded-lg size-14" style="background-image: url('${product.image}');"></div>` : ''}
                            <div class="flex flex-col justify-center">
                                <p class="text-[#1c130d] text-base font-medium leading-normal line-clamp-1">${product.name}</p>
                                ${isCheckout 
                                    ? `<p class="text-[#9c6c49] text-sm font-normal leading-normal line-clamp-2">${item.quantity} x $${product.price.toFixed(2)}</p>`
                                    : `<div class="flex items-center gap-2 mt-1">
                                          <button class="quantity-btn" data-id="${product.id}" data-change="-1">-</button>
                                          <span class="text-[#1c130d]">${item.quantity}</span>
                                          <button class="quantity-btn" data-id="${product.id}" data-change="1">+</button>
                                      </div>`
                                }
                            </div>
                        </div>
                        <div class="shrink-0"><p class="text-[#1c130d] text-base font-normal leading-normal">$${(product.price * item.quantity).toFixed(2)}</p></div>
                    `;
                    container.appendChild(itemElement);
                }
            });
        }
        
        // Update totals
        const shipping = cart.length > 0 ? 5.00 : 0.00;
        const total = subtotal + shipping;
        
        document.getElementById('subtotal-amount').textContent = `$${subtotal.toFixed(2)}`;
        document.getElementById('shipping-amount').textContent = `$${shipping.toFixed(2)}`;
        document.getElementById('total-amount').textContent = `$${total.toFixed(2)}`;
        
        // Add event listeners for quantity buttons if on cart page
        if (!isCheckout) {
            document.querySelectorAll('.quantity-btn').forEach(button => {
                button.addEventListener('click', e => {
                    const productId = parseInt(e.currentTarget.dataset.id);
                    const change = parseInt(e.currentTarget.dataset.change);
                    const cart = getCart();
                    const item = cart.find(i => i.id === productId);
                    if (item) {
                        updateQuantity(productId, item.quantity + change);
                    }
                });
            });
        }
    };

    // --- WHATSAPP CHECKOUT ---
    const handleWhatsAppCheckout = () => {
        const checkoutButton = document.getElementById('whatsapp-checkout-btn');
        if (!checkoutButton) return;

        checkoutButton.addEventListener('click', () => {
            const name = document.getElementById('name').value.trim();
            const address = document.getElementById('address').value.trim();
            const city = document.getElementById('city').value.trim();
            const zip = document.getElementById('zip').value.trim();

            if (!name || !address || !city || !zip) {
                alert('Please fill in all delivery details.');
                return;
            }

            const cart = getCart();
            if (cart.length === 0) {
                alert('Your cart is empty.');
                return;
            }

            let message = "Hello! I'd like to place an order:\n\n";
            let subtotal = 0;

            cart.forEach(item => {
                const product = products.find(p => p.id === item.id);
                if (product) {
                    const itemTotal = product.price * item.quantity;
                    subtotal += itemTotal;
                    message += `*${product.name}*\n`;
                    message += `  - Quantity: ${item.quantity} ${product.unit}\n`;
                    message += `  - Price: $${itemTotal.toFixed(2)}\n\n`;
                }
            });
            
            const shipping = 5.00;
            const total = subtotal + shipping;

            message += `*Subtotal:* $${subtotal.toFixed(2)}\n`;
            message += `*Shipping:* $${shipping.toFixed(2)}\n`;
            message += `*Total:* $${total.toFixed(2)}\n\n`;
            message += "*Delivery Details:*\n";
            message += `Name: ${name}\n`;
            message += `Address: ${address}, ${city}, ${zip}\n\n`;
            message += "Thank you!";

            const phoneNumber = "917898004784"; // Country code + number
            const whatsappUrl = `https://wa.me/${phoneNumber}?text=${encodeURIComponent(message)}`;

            window.open(whatsappUrl, '_blank');
        });
    };


    // --- INITIALIZATION ---
    // Router to call the correct function based on the page
    const page = window.location.pathname.split("/").pop();

    if (page === 'index.html' || page === '') {
        renderProducts();
    }
    
    if (page === 'product-detail.html') {
        renderProductDetails();
    }

    if (page === 'cart.html') {
        renderCartItems('cart-items-container', false);
    }
    
    if (page === 'checkout.html') {
        renderCartItems('checkout-summary-container', true);
        handleWhatsAppCheckout();
    }

    // Update cart icon on all pages
    updateCartIcon();
});

Conclusion

See also  Learn Pygame Basic

Chicken Realtor is not just a project — it’s a template for how small meat sellers and butchers can modernize their business without relying on expensive platforms or third-party services. By blending eCommerce with WhatsApp, we unlocked instant communication and frictionless shopping.

I’m proud of how this turned out, and I hope more businesses adopt similar lightweight, powerful tools in the future.

Want to build something like this for your own niche? I’m available for freelance or hourly project work — rockzahmad@gmail.com . 🚀

Leave a Comment

Your email address will not be published. Required fields are marked *

Ads Blocker Image Powered by Code Help Pro

Ads Blocker Detected!!!

we provide projects, courses, and other stuff for free. in order for running we use Google ads to make revenue. please disable adblocker to support us.

Powered By
100% Free SEO Tools - Tool Kits PRO