In modern e-commerce architectures, a dedicated Producer Dashboard is essential for allowing vendors or creators to manage their inventory and track incoming sales. This article breaks down how to build a functional React dashboard that handles data fetching, form management, and conditional rendering.
Core Functionalities
The ProducerDashboard component serves two primary purposes:
Inventory Management: A dynamic form to add new products to the database.
Order Tracking: A live view of customer orders specific to the logged-in producer.
Key Technical Concepts
- Authentication Guarding
Before the component renders its main content, it checks for a user object. If the user isn’t logged in, it uses the useNavigate hook from react-router-dom to redirect them to the login page. This ensures that sensitive data and producer tools remain protected.
- Managing Complex State
The component utilizes the useState hook to manage several different types of data:
Orders: An array to store data fetched from the API.
Form Data: An object used to track multiple input fields simultaneously.
Feedback UI: State variables for error and message to provide real-time updates to the user.
- Data Fetching with useEffect
The component uses useEffect to trigger an asynchronous fetch call. By including [user] in the dependency array, the dashboard automatically refreshes or loads data whenever the user context changes.
The Implementation
Below is the complete React code for the ProducerDashboard.
JavaScript
import { useState, useEffect } from ‘react’
import { useNavigate } from ‘react-router-dom’
import ‘./ProducerDashboard.css’
function ProducerDashboard({ user }) {
const navigate = useNavigate()
const [orders, setOrders] = useState([])
const [form, setForm] = useState({
product_name: ”,
product_price: ”,
product_stock: ”,
product_description: ”
})
const [message, setMessage] = useState(”)
const [error, setError] = useState(”)
useEffect(() => {
// Redirect if user is not authenticated
if (!user) {
navigate(‘/login’);
return
}
const load = async () => {
try {
const res = await fetch(`/api/producer/orders/${user.producerID}`)
const data = await res.json()
setOrders(data)
} catch (err) {
console.error("Failed to load orders", err)
}
}
load()
}, [user, navigate])
const handleChange = (e) => {
// Dynamically update form state based on input name
setForm({ …form, [e.target.name]: e.target.value })
}
const addProduct = async () => {
// Basic Validation
if (!form.product_name) { setError(‘Please enter a product name’); return }
if (!form.product_price) { setError(‘Please enter a price’); return }
if (!form.product_stock) { setError(‘Please enter stock level’); return }
const res = await fetch('/api/products', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
...form,
producerID: user.producerID
})
})
if (res.ok) {
setMessage('Product added!')
setError('')
// Reset form after successful submission
setForm({
product_name: '',
product_price: '',
product_stock: '',
product_description: ''
})
} else {
setError('Failed to add product. Please try again.')
}
}
if (!user) return
Please log in as a producer.
return (
Producer Dashboard
{/* Section 1: Product Entry */}
<div className="dashboard-section">
<h2>Add New Product</h2>
<input
name="product_name"
placeholder="Product name"
value={form.product_name}
onChange={handleChange}
/>
<input
name="product_price"
placeholder="Price"
value={form.product_price}
onChange={handleChange}
/>
<input
name="product_stock"
placeholder="Stock"
value={form.product_stock}
onChange={handleChange}
/>
<textarea
name="product_description"
placeholder="Description"
value={form.product_description}
onChange={handleChange}
/>
{error && <p className="error">{error}</p>}
{message && <p className="success">{message}</p>}
<button onClick={addProduct}>Add Product</button>
</div>
{/* Section 2: Order Management */}
<div className="dashboard-section">
<h2>Customer Orders</h2>
{orders.length === 0 && <p>No orders yet.</p>}
{orders.map(order => (
<div key={order.orderID} className="order-card">
<p className="order-product"><strong>{order.product_name}</strong></p>
<p>Customer: {order.first_name} {order.last_name}</p>
<p>Quantity: {order.product_quantity}</p>
<p>Date: {new Date(order.order_date).toLocaleDateString()}</p>
</div>
))}
</div>
</div>
)
}
export default ProducerDashboard
Best Practices Observed
Controlled Components: All inputs are linked to the React state via the value and onChange attributes, making the UI the "single source of truth."
RESTful Interaction: The code uses standard HTTP methods (GET for retrieving orders and POST for creating products).
User Feedback: It provides immediate visual feedback (success/error messages) which is vital for a good user experience.
Scalable Formatting: By using .map() to render orders, the dashboard can handle any number of sales entries dynamically.