<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bastien Moriel</title>
    <description>The latest articles on DEV Community by Bastien Moriel (@bastienmorel).</description>
    <link>https://dev.to/bastienmorel</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3880488%2F9e4e1f3b-806a-4d3f-a634-aaa9df4e0edd.png</url>
      <title>DEV Community: Bastien Moriel</title>
      <link>https://dev.to/bastienmorel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bastienmorel"/>
    <language>en</language>
    <item>
      <title>react shop practice</title>
      <dc:creator>Bastien Moriel</dc:creator>
      <pubDate>Thu, 16 Apr 2026 12:26:42 +0000</pubDate>
      <link>https://dev.to/bastienmorel/react-shop-practice-2c1k</link>
      <guid>https://dev.to/bastienmorel/react-shop-practice-2c1k</guid>
      <description>&lt;p&gt;import { useState, useEffect } from 'react'&lt;br&gt;
import { useNavigate } from 'react-router-dom'&lt;br&gt;
import './Marketplace.css'&lt;/p&gt;

&lt;p&gt;function Marketplace({ user }) {&lt;br&gt;
  const navigate = useNavigate()&lt;br&gt;
  const [products, setProducts]     = useState([])&lt;br&gt;
  const [quantities, setQuantities] = useState({})&lt;br&gt;
  const [basket, setBasket]         = useState([])&lt;br&gt;
  const [message, setMessage]       = useState('')&lt;/p&gt;

&lt;p&gt;useEffect(() =&amp;gt; {&lt;br&gt;
    const load = async () =&amp;gt; {&lt;br&gt;
      const res  = await fetch('/api/products')&lt;br&gt;
      const data = await res.json()&lt;br&gt;
      setProducts(data)&lt;br&gt;
    }&lt;br&gt;
    load()&lt;br&gt;
  }, [])&lt;/p&gt;

&lt;p&gt;const changeQty = (id, delta) =&amp;gt; {&lt;br&gt;
    setQuantities(prev =&amp;gt; ({&lt;br&gt;
      ...prev,&lt;br&gt;
      [id]: Math.max(1, (prev[id] || 1) + delta)&lt;br&gt;
    }))&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;const addToBasket = (product) =&amp;gt; {&lt;br&gt;
    if (!user) { navigate('/login'); return }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const qty      = quantities[product.productID] || 1
const existing = basket.find(i =&amp;gt; i.productID === product.productID)

if (existing) {
  setBasket(basket.map(i =&amp;gt;
    i.productID === product.productID
      ? { ...i, quantity: i.quantity + qty }
      : i
  ))
} else {
  setBasket([...basket, {
    productID:     product.productID,
    product_name:  product.product_name,
    product_price: product.product_price,
    quantity:      qty
  }])
}

setMessage('Added to basket!')
setTimeout(() =&amp;gt; setMessage(''), 2000)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;const goToCheckout = () =&amp;gt; {&lt;br&gt;
    if (basket.length === 0) { alert('Your basket is empty'); return }&lt;br&gt;
    navigate('/checkout', { state: { basket } })&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;return (&lt;br&gt;
    &lt;/p&gt;
&lt;br&gt;
      &lt;h1&gt;Marketplace&lt;/h1&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  {message &amp;amp;&amp;amp; &amp;lt;p className="success"&amp;gt;{message}&amp;lt;/p&amp;gt;}

  {basket.length &amp;gt; 0 &amp;amp;&amp;amp; (
    &amp;lt;button className="basket-btn" onClick={goToCheckout}&amp;gt;
      Go to Checkout ({basket.length} items)
    &amp;lt;/button&amp;gt;
  )}

  &amp;lt;div className="product-grid"&amp;gt;
    {products.map(product =&amp;gt; (
      &amp;lt;div key={product.productID} className="product-card"&amp;gt;
        &amp;lt;div className="product-img" /&amp;gt;
        &amp;lt;p className="product-name"&amp;gt;{product.product_name}&amp;lt;/p&amp;gt;
        &amp;lt;p className="product-price"&amp;gt;£{Number(product.product_price).toFixed(2)}&amp;lt;/p&amp;gt;
        &amp;lt;p className="product-stock"&amp;gt;Stock: {product.product_stock}&amp;lt;/p&amp;gt;
        &amp;lt;p className="product-desc"&amp;gt;{product.product_description}&amp;lt;/p&amp;gt;
        &amp;lt;div className="product-controls"&amp;gt;
          &amp;lt;button onClick={() =&amp;gt; changeQty(product.productID, -1)}&amp;gt;-&amp;lt;/button&amp;gt;
          &amp;lt;span&amp;gt;{quantities[product.productID] || 1}&amp;lt;/span&amp;gt;
          &amp;lt;button onClick={() =&amp;gt; changeQty(product.productID, +1)}&amp;gt;+&amp;lt;/button&amp;gt;
          &amp;lt;button onClick={() =&amp;gt; addToBasket(product)}&amp;gt;
            {user ? 'Add to Basket' : 'Login to Order'}
          &amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    ))}
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;)&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;export default Marketplace&lt;/p&gt;

&lt;p&gt;.page { padding: 30px; }&lt;/p&gt;

&lt;p&gt;.success {&lt;br&gt;
  background: #A2C24A;&lt;br&gt;
  color: white;&lt;br&gt;
  padding: 10px;&lt;br&gt;
  border-radius: 6px;&lt;br&gt;
  margin-bottom: 15px;&lt;br&gt;
  text-align: center;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.basket-btn {&lt;br&gt;
  background: #144A5C;&lt;br&gt;
  color: white;&lt;br&gt;
  border: none;&lt;br&gt;
  padding: 10px 20px;&lt;br&gt;
  border-radius: 6px;&lt;br&gt;
  cursor: pointer;&lt;br&gt;
  font-family: 'Gluten', cursive;&lt;br&gt;
  margin-bottom: 20px;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.product-grid {&lt;br&gt;
  display: grid;&lt;br&gt;
  grid-template-columns: repeat(3, 1fr);&lt;br&gt;
  gap: 20px;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.product-card {&lt;br&gt;
  border: 1px solid #ccc;&lt;br&gt;
  border-radius: 8px;&lt;br&gt;
  padding: 16px;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.product-img {&lt;br&gt;
  background: #c8c8c8;&lt;br&gt;
  height: 120px;&lt;br&gt;
  border-radius: 6px;&lt;br&gt;
  margin-bottom: 10px;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.product-name { font-weight: 700; margin-bottom: 5px; }&lt;br&gt;
.product-price { color: #A2C24A; font-weight: 700; margin-bottom: 5px; }&lt;br&gt;
.product-stock { font-size: 13px; margin-bottom: 5px; }&lt;br&gt;
.product-desc { font-size: 13px; color: #666; margin-bottom: 10px; }&lt;/p&gt;

&lt;p&gt;.product-controls {&lt;br&gt;
  display: flex;&lt;br&gt;
  align-items: center;&lt;br&gt;
  gap: 8px;&lt;br&gt;
  flex-wrap: wrap;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.product-controls button {&lt;br&gt;
  background: #144A5C;&lt;br&gt;
  color: white;&lt;br&gt;
  border: none;&lt;br&gt;
  border-radius: 6px;&lt;br&gt;
  padding: 6px 12px;&lt;br&gt;
  cursor: pointer;&lt;br&gt;
  font-family: 'Gluten', cursive;&lt;br&gt;
}&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>python system practice</title>
      <dc:creator>Bastien Moriel</dc:creator>
      <pubDate>Thu, 16 Apr 2026 12:25:52 +0000</pubDate>
      <link>https://dev.to/bastienmorel/python-system-practice-3fd9</link>
      <guid>https://dev.to/bastienmorel/python-system-practice-3fd9</guid>
      <description>&lt;p&gt;@app.route("/api/health")&lt;br&gt;
def health():&lt;br&gt;
    return jsonify({"status": "ok"})&lt;/p&gt;

&lt;p&gt;@app.route("/api/register", methods=["POST"])&lt;br&gt;
def register():&lt;br&gt;
    data = request.get_json()&lt;br&gt;
    conn = get_db()&lt;br&gt;
    cursor = conn.cursor()&lt;br&gt;
    hashed = bcrypt.hashpw(&lt;br&gt;
        data["password"].encode('utf-8'),&lt;br&gt;
        bcrypt.gensalt()&lt;br&gt;
    ).decode('utf-8')&lt;br&gt;
    cursor.execute(&lt;br&gt;
        "INSERT INTO customers (first_name, last_name, email, PWD_Hash, Address) VALUES (%s,%s,%s,%s,%s)",&lt;br&gt;
        (data["first_name"], data["last_name"], data["email"], hashed, data["address"])&lt;br&gt;
    )&lt;br&gt;
    conn.commit()&lt;br&gt;
    conn.close()&lt;br&gt;
    return jsonify({"message": "Account created"})&lt;/p&gt;

&lt;p&gt;@app.route("/api/login", methods=["POST"])&lt;br&gt;
def login():&lt;br&gt;
    data = request.get_json()&lt;br&gt;
    conn = get_db()&lt;br&gt;
    cursor = conn.cursor(dictionary=True)&lt;br&gt;
    cursor.execute(&lt;br&gt;
        "SELECT * FROM customers WHERE email = %s",&lt;br&gt;
        (data["email"],)&lt;br&gt;
    )&lt;br&gt;
    customer = cursor.fetchone()&lt;br&gt;
    conn.close()&lt;br&gt;
    if not customer:&lt;br&gt;
        return jsonify({"error": "Wrong email or password"}), 401&lt;br&gt;
    password_correct = bcrypt.checkpw(&lt;br&gt;
        data["password"].encode('utf-8'),&lt;br&gt;
        customer["PWD_Hash"].encode('utf-8')&lt;br&gt;
    )&lt;br&gt;
    if not password_correct:&lt;br&gt;
        return jsonify({"error": "Wrong email or password"}), 401&lt;br&gt;
    return jsonify({&lt;br&gt;
        "customerID": customer["customerID"],&lt;br&gt;
        "name": customer["first_name"],&lt;br&gt;
        "role": "customer"&lt;br&gt;
    })&lt;/p&gt;

&lt;p&gt;@app.route("/api/producer/login", methods=["POST"])&lt;br&gt;
def producer_login():&lt;br&gt;
    data = request.get_json()&lt;br&gt;
    conn = get_db()&lt;br&gt;
    cursor = conn.cursor(dictionary=True)&lt;br&gt;
    cursor.execute(&lt;br&gt;
        "SELECT * FROM producers WHERE email=%s AND PWD_Hash=%s",&lt;br&gt;
        (data["email"], data["password"])&lt;br&gt;
    )&lt;br&gt;
    producer = cursor.fetchone()&lt;br&gt;
    conn.close()&lt;br&gt;
    if not producer:&lt;br&gt;
        return jsonify({"error": "Wrong email or password"}), 401&lt;br&gt;
    return jsonify({&lt;br&gt;
        "producerID": producer["producerID"],&lt;br&gt;
        "name": producer["producer_name"],&lt;br&gt;
        "role": "producer"&lt;br&gt;
    })&lt;/p&gt;

&lt;p&gt;@app.route("/api/products")&lt;br&gt;
def get_products():&lt;br&gt;
    conn = get_db()&lt;br&gt;
    cursor = conn.cursor(dictionary=True)&lt;br&gt;
    cursor.execute("SELECT * FROM products")&lt;br&gt;
    products = cursor.fetchall()&lt;br&gt;
    conn.close()&lt;br&gt;
    return jsonify(products)&lt;/p&gt;

&lt;p&gt;@app.route("/api/products", methods=["POST"])&lt;br&gt;
def add_product():&lt;br&gt;
    data = request.get_json()&lt;br&gt;
    conn = get_db()&lt;br&gt;
    cursor = conn.cursor()&lt;br&gt;
    cursor.execute(&lt;br&gt;
        "INSERT INTO products (product_name, product_price, product_stock, product_description, producerID) VALUES (%s,%s,%s,%s,%s)",&lt;br&gt;
        (data["product_name"], data["product_price"], data["product_stock"], data["product_description"], data["producerID"])&lt;br&gt;
    )&lt;br&gt;
    conn.commit()&lt;br&gt;
    conn.close()&lt;br&gt;
    return jsonify({"message": "Product added"})&lt;/p&gt;

&lt;p&gt;@app.route("/api/orders", methods=["POST"])&lt;br&gt;
def place_order():&lt;br&gt;
    data = request.get_json()&lt;br&gt;
    conn = get_db()&lt;br&gt;
    cursor = conn.cursor()&lt;br&gt;
    cursor.execute(&lt;br&gt;
        "INSERT INTO orders (customerID) VALUES (%s)",&lt;br&gt;
        (data["customerID"],)&lt;br&gt;
    )&lt;br&gt;
    order_id = cursor.lastrowid&lt;br&gt;
    for item in data["items"]:&lt;br&gt;
        cursor.execute(&lt;br&gt;
            "INSERT INTO order_details (orderID, productID, product_quantity) VALUES (%s,%s,%s)",&lt;br&gt;
            (order_id, item["productID"], item["quantity"])&lt;br&gt;
        )&lt;br&gt;
    conn.commit()&lt;br&gt;
    conn.close()&lt;br&gt;
    return jsonify({"message": "Order placed"})&lt;/p&gt;

&lt;p&gt;@app.route("/api/orders/&lt;a&gt;int:customer_id&lt;/a&gt;")&lt;br&gt;
def get_orders(customer_id):&lt;br&gt;
    conn = get_db()&lt;br&gt;
    cursor = conn.cursor(dictionary=True)&lt;br&gt;
    cursor.execute("""&lt;br&gt;
        SELECT orders.orderID, products.product_name,&lt;br&gt;
               order_details.product_quantity, orders.order_date&lt;br&gt;
        FROM orders&lt;br&gt;
        JOIN order_details ON orders.orderID = order_details.orderID&lt;br&gt;
        JOIN products ON order_details.productID = products.productID&lt;br&gt;
        WHERE orders.customerID = %s&lt;br&gt;
    """, (customer_id,))&lt;br&gt;
    orders = cursor.fetchall()&lt;br&gt;
    conn.close()&lt;br&gt;
    return jsonify(orders)&lt;/p&gt;

&lt;p&gt;@app.route("/api/producer/orders/&lt;a&gt;int:producer_id&lt;/a&gt;")&lt;br&gt;
def producer_orders(producer_id):&lt;br&gt;
    conn = get_db()&lt;br&gt;
    cursor = conn.cursor(dictionary=True)&lt;br&gt;
    cursor.execute("""&lt;br&gt;
        SELECT orders.orderID, products.product_name,&lt;br&gt;
               order_details.product_quantity, orders.order_date,&lt;br&gt;
               customers.first_name, customers.last_name&lt;br&gt;
        FROM orders&lt;br&gt;
        JOIN order_details ON orders.orderID = order_details.orderID&lt;br&gt;
        JOIN products ON order_details.productID = products.productID&lt;br&gt;
        JOIN customers ON orders.customerID = customers.customerID&lt;br&gt;
        WHERE products.producerID = %s&lt;br&gt;
    """, (producer_id,))&lt;br&gt;
    orders = cursor.fetchall()&lt;br&gt;
    conn.close()&lt;br&gt;
    return jsonify(orders)&lt;/p&gt;

&lt;p&gt;if &lt;strong&gt;name&lt;/strong&gt; == "&lt;strong&gt;main&lt;/strong&gt;":&lt;br&gt;
    app.run(debug=True)`&lt;/p&gt;

</description>
    </item>
    <item>
      <title>react checkout practice</title>
      <dc:creator>Bastien Moriel</dc:creator>
      <pubDate>Thu, 16 Apr 2026 12:21:29 +0000</pubDate>
      <link>https://dev.to/bastienmorel/react-checkout-practice-128c</link>
      <guid>https://dev.to/bastienmorel/react-checkout-practice-128c</guid>
      <description>&lt;p&gt;import { useState } from 'react'&lt;br&gt;
import { useLocation, useNavigate } from 'react-router-dom'&lt;br&gt;
import './Checkout.css'&lt;/p&gt;

&lt;p&gt;function Checkout({ user }) {&lt;br&gt;
  const location = useLocation()&lt;br&gt;
  const navigate  = useNavigate()&lt;br&gt;
  const basket    = location.state?.basket || []&lt;br&gt;
  const [success, setSuccess] = useState(false)&lt;br&gt;
  const [error,   setError]   = useState('')&lt;/p&gt;

&lt;p&gt;const total = basket.reduce((sum, item) =&amp;gt; {&lt;br&gt;
    return sum + item.product_price * item.quantity&lt;br&gt;
  }, 0)&lt;/p&gt;

&lt;p&gt;const placeOrder = async () =&amp;gt; {&lt;br&gt;
    if (!user) { navigate('/login'); return }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const res = await fetch('/api/orders', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    customerID: user.customerID,
    items: basket.map(item =&amp;gt; ({
      productID: item.productID,
      quantity:  item.quantity
    }))
  })
})

const data = await res.json()
if (!res.ok) { setError(data.error); return }
setSuccess(true)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;if (success) {&lt;br&gt;
    return (&lt;br&gt;
      &lt;/p&gt;
&lt;br&gt;
        &lt;h1&gt;Order Placed!&lt;/h1&gt;
&lt;br&gt;
        &lt;p&gt;Thank you for your order.&lt;/p&gt;
&lt;br&gt;
         navigate('/orders')}&amp;gt;&lt;br&gt;
          View My Orders&lt;br&gt;
        &lt;br&gt;
      &lt;br&gt;
    )&lt;br&gt;
  }

&lt;p&gt;return (&lt;br&gt;
    &lt;/p&gt;
&lt;br&gt;
      &lt;h1&gt;Checkout&lt;/h1&gt;
&lt;br&gt;
      {basket.length === 0 ? &lt;p&gt;Your basket is empty.&lt;/p&gt; : (&lt;br&gt;
        &amp;lt;&amp;gt;&lt;br&gt;
          {basket.map((item, index) =&amp;gt; (&lt;br&gt;
            &lt;br&gt;
              &lt;p&gt;{item.product_name}&lt;/p&gt;
&lt;br&gt;
              &lt;p&gt;Quantity: {item.quantity}&lt;/p&gt;
&lt;br&gt;
              &lt;p&gt;£{(item.product_price * item.quantity).toFixed(2)}&lt;/p&gt;
&lt;br&gt;
            &lt;br&gt;
          ))}&lt;br&gt;
          &lt;br&gt;
            &lt;h2&gt;Total: £{total.toFixed(2)}&lt;/h2&gt;
&lt;br&gt;
          &lt;br&gt;
          {error &amp;amp;&amp;amp; &lt;p&gt;{error}&lt;/p&gt;}&lt;br&gt;
          Place Order&lt;br&gt;
        &amp;lt;/&amp;gt;&lt;br&gt;
      )}&lt;br&gt;
    &lt;br&gt;
  )&lt;br&gt;
}

&lt;p&gt;export default Checkout&lt;/p&gt;

&lt;p&gt;.page { padding: 30px; }&lt;br&gt;
.page h1 { margin-bottom: 20px; }&lt;/p&gt;

&lt;p&gt;.checkout-item {&lt;br&gt;
  border: 1px solid #ccc;&lt;br&gt;
  border-radius: 8px;&lt;br&gt;
  padding: 16px;&lt;br&gt;
  margin-bottom: 10px;&lt;br&gt;
  max-width: 500px;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.item-name { font-weight: 700; margin-bottom: 5px; color: #144A5C; }&lt;/p&gt;

&lt;p&gt;.checkout-total { margin: 20px 0; }&lt;br&gt;
.checkout-total h2 { color: #A2C24A; }&lt;/p&gt;

&lt;p&gt;.error {&lt;br&gt;
  color: white;&lt;br&gt;
  background: red;&lt;br&gt;
  padding: 10px;&lt;br&gt;
  border-radius: 6px;&lt;br&gt;
  margin-bottom: 10px;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.order-btn {&lt;br&gt;
  background: #A2C24A;&lt;br&gt;
  color: white;&lt;br&gt;
  border: none;&lt;br&gt;
  padding: 12px 30px;&lt;br&gt;
  border-radius: 6px;&lt;br&gt;
  font-size: 16px;&lt;br&gt;
  cursor: pointer;&lt;br&gt;
  font-family: 'Gluten', cursive;&lt;br&gt;
}&lt;/p&gt;

</description>
    </item>
    <item>
      <title>react orders practice</title>
      <dc:creator>Bastien Moriel</dc:creator>
      <pubDate>Thu, 16 Apr 2026 12:18:50 +0000</pubDate>
      <link>https://dev.to/bastienmorel/react-orders-practice-3l35</link>
      <guid>https://dev.to/bastienmorel/react-orders-practice-3l35</guid>
      <description>&lt;p&gt;import { useState, useEffect } from 'react'&lt;br&gt;
import { useNavigate } from 'react-router-dom'&lt;br&gt;
import './MyOrders.css'&lt;/p&gt;

&lt;p&gt;function MyOrders({ user }) {&lt;br&gt;
  const navigate = useNavigate()&lt;br&gt;
  const [orders, setOrders] = useState([])&lt;/p&gt;

&lt;p&gt;useEffect(() =&amp;gt; {&lt;br&gt;
    if (!user) { navigate('/login'); return }&lt;br&gt;
    const load = async () =&amp;gt; {&lt;br&gt;
      const res  = await fetch(&lt;code&gt;/api/orders/${user.customerID}&lt;/code&gt;)&lt;br&gt;
      const data = await res.json()&lt;br&gt;
      setOrders(data)&lt;br&gt;
    }&lt;br&gt;
    load()&lt;br&gt;
  }, [user])&lt;/p&gt;

&lt;p&gt;if (!user) return &lt;/p&gt;
&lt;p&gt;Please log in.&lt;/p&gt;

&lt;p&gt;return (&lt;br&gt;
    &lt;/p&gt;
&lt;br&gt;
      &lt;h1&gt;My Orders&lt;/h1&gt;
&lt;br&gt;
      {orders.length === 0 &amp;amp;&amp;amp; &lt;p&gt;No orders yet.&lt;/p&gt;}&lt;br&gt;
      {orders.map(order =&amp;gt; (&lt;br&gt;
        &lt;br&gt;
          &lt;p&gt;{order.product_name}&lt;/p&gt;
&lt;br&gt;
          &lt;p&gt;Quantity: {order.product_quantity}&lt;/p&gt;
&lt;br&gt;
          &lt;p&gt;Date: {new Date(order.order_date).toLocaleDateString()}&lt;/p&gt;
&lt;br&gt;
        &lt;br&gt;
      ))}&lt;br&gt;
    &lt;br&gt;
  )&lt;br&gt;
}

&lt;p&gt;export default MyOrders&lt;/p&gt;

</description>
    </item>
    <item>
      <title>css dashboard practice</title>
      <dc:creator>Bastien Moriel</dc:creator>
      <pubDate>Thu, 16 Apr 2026 12:16:23 +0000</pubDate>
      <link>https://dev.to/bastienmorel/css-dashboard-practice-a1o</link>
      <guid>https://dev.to/bastienmorel/css-dashboard-practice-a1o</guid>
      <description>&lt;p&gt;.page { padding: 30px; }&lt;/p&gt;

&lt;p&gt;.dashboard-section {&lt;br&gt;
  margin-bottom: 40px;&lt;br&gt;
  max-width: 500px;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.dashboard-section h2 { margin-bottom: 15px; }&lt;/p&gt;

&lt;p&gt;.dashboard-section input,&lt;br&gt;
.dashboard-section textarea {&lt;br&gt;
  display: block;&lt;br&gt;
  width: 100%;&lt;br&gt;
  padding: 10px;&lt;br&gt;
  margin-bottom: 12px;&lt;br&gt;
  border-radius: 6px;&lt;br&gt;
  border: 1px solid #ccc;&lt;br&gt;
  font-family: 'Gluten', cursive;&lt;br&gt;
  font-size: 14px;&lt;br&gt;
  color: #144A5C;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.dashboard-section textarea { height: 80px; resize: none; }&lt;/p&gt;

&lt;p&gt;.dashboard-section button {&lt;br&gt;
  background: #A2C24A;&lt;br&gt;
  color: white;&lt;br&gt;
  border: none;&lt;br&gt;
  padding: 10px 20px;&lt;br&gt;
  border-radius: 6px;&lt;br&gt;
  cursor: pointer;&lt;br&gt;
  font-family: 'Gluten', cursive;&lt;br&gt;
  font-size: 14px;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.error {&lt;br&gt;
  color: white;&lt;br&gt;
  background: red;&lt;br&gt;
  padding: 10px;&lt;br&gt;
  border-radius: 6px;&lt;br&gt;
  margin-bottom: 10px;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.success {&lt;br&gt;
  color: white;&lt;br&gt;
  background: #A2C24A;&lt;br&gt;
  padding: 10px;&lt;br&gt;
  border-radius: 6px;&lt;br&gt;
  margin-bottom: 10px;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.order-card {&lt;br&gt;
  border: 1px solid #ccc;&lt;br&gt;
  border-radius: 8px;&lt;br&gt;
  padding: 16px;&lt;br&gt;
  margin-bottom: 10px;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.order-product { font-weight: 700; margin-bottom: 8px; color: #144A5C; }&lt;/p&gt;

</description>
    </item>
    <item>
      <title>react loyalty practice</title>
      <dc:creator>Bastien Moriel</dc:creator>
      <pubDate>Thu, 16 Apr 2026 12:11:39 +0000</pubDate>
      <link>https://dev.to/bastienmorel/react-loyalty-practice-5g6c</link>
      <guid>https://dev.to/bastienmorel/react-loyalty-practice-5g6c</guid>
      <description>&lt;p&gt;import './Loyalty.css'&lt;/p&gt;

&lt;p&gt;function Loyalty() {&lt;br&gt;
  return (&lt;br&gt;
    &lt;/p&gt;
&lt;br&gt;
      &lt;h1&gt;Loyalty Scheme&lt;/h1&gt;
&lt;br&gt;
      &lt;p&gt;Complete 8 purchases and get free delivery!&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  &amp;lt;div className="loyalty-section"&amp;gt;
    &amp;lt;h2&amp;gt;Your Rewards&amp;lt;/h2&amp;gt;
    &amp;lt;div className="reward-card"&amp;gt;
      &amp;lt;p&amp;gt;10% off all dairy products&amp;lt;/p&amp;gt;
      &amp;lt;button&amp;gt;Activate&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div className="reward-card"&amp;gt;
      &amp;lt;p&amp;gt;15% off your next order&amp;lt;/p&amp;gt;
      &amp;lt;button&amp;gt;Activate&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;

  &amp;lt;div className="loyalty-section"&amp;gt;
    &amp;lt;h2&amp;gt;Stamp Card&amp;lt;/h2&amp;gt;
    &amp;lt;div className="stamps"&amp;gt;
      {Array.from({ length: 8 }).map((_, i) =&amp;gt; (
        &amp;lt;div key={i} className="stamp"&amp;gt;
          {i === 7 ? 'FREE' : i + 1}
        &amp;lt;/div&amp;gt;
      ))}
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;)&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;export default Loyalty&lt;/p&gt;

&lt;p&gt;.page { padding: 30px; }&lt;br&gt;
.page h1 { margin-bottom: 10px; }&lt;br&gt;
.subtitle { color: #666; margin-bottom: 30px; }&lt;/p&gt;

&lt;p&gt;.loyalty-section { margin-bottom: 30px; }&lt;br&gt;
.loyalty-section h2 { margin-bottom: 15px; }&lt;/p&gt;

&lt;p&gt;.reward-card {&lt;br&gt;
  border: 1px solid #ccc;&lt;br&gt;
  border-radius: 8px;&lt;br&gt;
  padding: 16px;&lt;br&gt;
  margin-bottom: 10px;&lt;br&gt;
  max-width: 400px;&lt;br&gt;
  display: flex;&lt;br&gt;
  justify-content: space-between;&lt;br&gt;
  align-items: center;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.reward-card button {&lt;br&gt;
  background: #A2C24A;&lt;br&gt;
  color: white;&lt;br&gt;
  border: none;&lt;br&gt;
  border-radius: 6px;&lt;br&gt;
  padding: 8px 16px;&lt;br&gt;
  cursor: pointer;&lt;br&gt;
  font-family: 'Gluten', cursive;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;.stamps { display: flex; gap: 10px; flex-wrap: wrap; }&lt;/p&gt;

&lt;p&gt;.stamp {&lt;br&gt;
  width: 55px;&lt;br&gt;
  height: 55px;&lt;br&gt;
  border-radius: 50%;&lt;br&gt;
  background: #A2C24A;&lt;br&gt;
  display: flex;&lt;br&gt;
  align-items: center;&lt;br&gt;
  justify-content: center;&lt;br&gt;
  color: white;&lt;br&gt;
  font-weight: 700;&lt;br&gt;
  font-size: 13px;&lt;br&gt;
}&lt;/p&gt;

</description>
    </item>
    <item>
      <title>react app practice</title>
      <dc:creator>Bastien Moriel</dc:creator>
      <pubDate>Thu, 16 Apr 2026 12:11:21 +0000</pubDate>
      <link>https://dev.to/bastienmorel/react-app-practice-12g8</link>
      <guid>https://dev.to/bastienmorel/react-app-practice-12g8</guid>
      <description>&lt;p&gt;import { useState } from 'react'&lt;br&gt;
import { BrowserRouter, Routes, Route, Link, useNavigate } from 'react-router-dom'&lt;br&gt;
import Home from './pages/Home'&lt;br&gt;
import Login from './pages/Login'&lt;br&gt;
import Marketplace from './pages/Marketplace'&lt;br&gt;
import Checkout from './pages/Checkout'&lt;br&gt;
import MyOrders from './pages/MyOrders'&lt;br&gt;
import ProducerDashboard from './pages/ProducerDashboard'&lt;br&gt;
import Loyalty from './pages/Loyalty'&lt;br&gt;
import './index.css'&lt;/p&gt;

&lt;p&gt;function Navbar({ user, setUser }) {&lt;br&gt;
  const navigate = useNavigate()&lt;/p&gt;

&lt;p&gt;const handleLogout = () =&amp;gt; {&lt;br&gt;
    localStorage.removeItem('user')&lt;br&gt;
    setUser(null)&lt;br&gt;
    navigate('/')&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;return (&lt;br&gt;
    &lt;br&gt;
      Home&lt;br&gt;
      Marketplace&lt;br&gt;
      {user &amp;amp;&amp;amp; user.role === 'customer' &amp;amp;&amp;amp; My Orders}&lt;br&gt;
      {user &amp;amp;&amp;amp; user.role === 'customer' &amp;amp;&amp;amp; Loyalty}&lt;br&gt;
      {user &amp;amp;&amp;amp; user.role === 'producer' &amp;amp;&amp;amp; Dashboard}&lt;br&gt;
      {!user &amp;amp;&amp;amp; Login}&lt;br&gt;
      {user &amp;amp;&amp;amp; &lt;span&gt;Hi {user.name}&lt;/span&gt;}&lt;br&gt;
      {user &amp;amp;&amp;amp; (&lt;br&gt;
        &lt;br&gt;
          Logout&lt;br&gt;
        &lt;br&gt;
      )}&lt;br&gt;
    &lt;br&gt;
  )&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;function App() {&lt;br&gt;
  const [user, setUser] = useState(() =&amp;gt; {&lt;br&gt;
    const saved = localStorage.getItem('user')&lt;br&gt;
    return saved ? JSON.parse(saved) : null&lt;br&gt;
  })&lt;/p&gt;

&lt;p&gt;return (&lt;br&gt;
    &lt;br&gt;
      &lt;br&gt;
      &lt;br&gt;
        } /&amp;gt;&lt;br&gt;
        } /&amp;gt;&lt;br&gt;
        } /&amp;gt;&lt;br&gt;
        } /&amp;gt;&lt;br&gt;
        } /&amp;gt;&lt;br&gt;
        } /&amp;gt;&lt;br&gt;
        } /&amp;gt;&lt;br&gt;
      &lt;br&gt;
    &lt;br&gt;
  )&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;export default App`&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to make Admin Dashboard</title>
      <dc:creator>Bastien Moriel</dc:creator>
      <pubDate>Wed, 15 Apr 2026 12:27:54 +0000</pubDate>
      <link>https://dev.to/bastienmorel/how-to-make-admin-dashboard-56eg</link>
      <guid>https://dev.to/bastienmorel/how-to-make-admin-dashboard-56eg</guid>
      <description>&lt;p&gt;In the modern data landscape, the ability to transform raw numbers into actionable insights is no longer just a "nice-to-have"—it is a necessity. However, building a custom web application traditionally required a deep understanding of HTML, CSS, and JavaScript.&lt;/p&gt;

&lt;p&gt;Enter Streamlit, the open-source Python framework that is effectively "democratizing" dashboard creation. By treating a web app like a simple script, developers can move from a CSV file to a live interactive interface in under ten minutes.&lt;br&gt;
The Architecture of Simplicity&lt;/p&gt;

&lt;p&gt;Most web frameworks follow a "Request-Response" cycle that can be mentally taxing to manage. Streamlit flips this by using a Top-Down Execution model. Every time a user interacts with a widget (like a slider or a button), the entire script reruns from top to bottom.&lt;/p&gt;

&lt;p&gt;While this sounds inefficient, Streamlit handles the heavy lifting through smart caching, ensuring your app stays snappy even with large datasets.&lt;br&gt;
Building a "Random Insights" Tracker&lt;/p&gt;

&lt;p&gt;To demonstrate how little code is required, we can look at a standard analytics use case: tracking sales performance across different regions.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Setup&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;First, we import the "Big Three" of Python data science: pandas for data manipulation, numpy for math, and plotly for the visual heavy lifting.&lt;br&gt;
Python&lt;/p&gt;

&lt;p&gt;import streamlit as st&lt;br&gt;
import pandas as pd&lt;br&gt;
import numpy as np&lt;br&gt;
import plotly.express as px&lt;/p&gt;

&lt;p&gt;st.set_page_config(page_title="Performance Dash", layout="wide")&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Crafting the "Brain" (The Data)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Using a simple function, we can generate a mock dataset to simulate real-world business volatility.&lt;br&gt;
Python&lt;/p&gt;

&lt;p&gt;def get_data(rows):&lt;br&gt;
    return pd.DataFrame({&lt;br&gt;
        'Date': pd.date_range(start='2023-01-01', periods=rows),&lt;br&gt;
        'Sales': np.random.randint(100, 1000, size=rows),&lt;br&gt;
        'Region': np.random.choice(['North', 'South', 'East', 'West'], size=rows)&lt;br&gt;
    })&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Visualizing the Story&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The beauty of modern Python tools is that UI elements—like columns and metrics—are now just single lines of code. By combining Streamlit’s layout options with Plotly’s interactive charts, we create a high-density information environment:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;KPI Metrics: Highlighting total sales and growth at a glance.

Time Series: Using line charts to spot seasonal trends.

Proportional Data: Using donut charts to compare regional market share.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Choosing the Right Tool&lt;/p&gt;

&lt;p&gt;While Streamlit is perfect for rapid prototyping, it is part of a larger ecosystem. Choosing the right tool depends on your end goal:&lt;br&gt;
Tool    Complexity  Best Use Case&lt;br&gt;
Streamlit   Low Internal tools, ML demos, fast iterations.&lt;br&gt;
Plotly Dash Medium  Enterprise-grade apps requiring fine-grained UI control.&lt;br&gt;
Panel   High    Complex scientific apps with massive data streams.&lt;br&gt;
Conclusion&lt;/p&gt;

&lt;p&gt;The barrier to entry for data visualization has never been lower. Whether you are a data scientist looking to showcase a model or a manager trying to track team KPIs, Python provides a robust, "code-first" approach to building professional dashboards without the overhead of a full-stack development team.&lt;/p&gt;

&lt;p&gt;Ready to launch? Save your code, run streamlit run app.py in your terminal, and watch your data come to life.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
