From 0986609d55057b962d9006e57165843d49d720a5 Mon Sep 17 00:00:00 2001
From: Maxime Princelle <maxime@princelle.org>
Date: Fri, 17 Dec 2021 14:12:16 +0100
Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20add=20add=20product=20with=20back?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/App.tsx                    |   2 +
 src/apis/back.ts               |  54 +++++++++++
 src/components/core/navbar.tsx |   4 +-
 src/pages/add_product.tsx      | 163 +++++++++++++++++++++++++++++++++
 4 files changed, 222 insertions(+), 1 deletion(-)
 create mode 100644 src/pages/add_product.tsx

diff --git a/src/App.tsx b/src/App.tsx
index 4cb233a..228d676 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -12,6 +12,7 @@ import Sell from './pages/sell';
 import Login from './pages/login';
 import Stock from './pages/stock';
 import Users from './pages/users';
+import AddProduct from './pages/add_product';
 import Main from './components/layout/main';
 
 export default function App() {
@@ -27,6 +28,7 @@ export default function App() {
                 <Route index element={<Sell />} />
                 <Route path="stock" element={<Stock />} />
                 <Route path="users" element={<Users />} />
+                <Route path="add-product" element={<AddProduct />} />
               </Route>
               <Route path="*" element={<h1>No match !</h1>} />
             </Routes>
diff --git a/src/apis/back.ts b/src/apis/back.ts
index 0932f46..d53e6a9 100644
--- a/src/apis/back.ts
+++ b/src/apis/back.ts
@@ -30,3 +30,57 @@ export async function getItems(): Promise<Product[]> {
 
   return products;
 };
+
+export async function getCategories(): Promise<any[]> {
+  const categories = await axios.get(`${BASE_URL}/category`, {
+    headers: {
+      'Content-Type': 'application/json',
+      'apikey': APIKEY,
+    }
+  }).then(({ data }) => data)
+    .catch(error => {
+      console.error(error);
+      return [];
+    });
+
+  return categories;
+}
+
+export async function addItem(name: string, price: number, priceAdherant: number, stock: number, category_id: any): Promise<any> {
+  // Create the item without stock
+  let item = await axios.post(`${BASE_URL}/item`, {
+    name: name,
+    price: price,
+    subscriber_price: priceAdherant,
+    category: category_id,
+  }, {
+    headers: {
+      'Content-Type': 'application/json',
+      'apikey': APIKEY,
+    }}).then(({ data }) => {
+      console.log(data)
+      return data;
+    })
+    .catch(error => {
+      console.error(error);
+      return null;
+    });
+
+  // Create the stock
+  if (item) {
+    await axios.put(`${BASE_URL}/stock`, {
+      item_id: item.id,
+      quantity: stock,
+    }, {
+      headers: {
+        'Content-Type': 'application/json',
+        'apikey': APIKEY,
+      }}).then(({ data }) => data)
+      .catch(error => {
+        console.error(error);
+        return [];
+      });
+  } else {
+    console.error("Error while creating item");
+  }
+}
\ No newline at end of file
diff --git a/src/components/core/navbar.tsx b/src/components/core/navbar.tsx
index 617daca..2a859e7 100644
--- a/src/components/core/navbar.tsx
+++ b/src/components/core/navbar.tsx
@@ -5,7 +5,8 @@ import {
   CurrencyEuroIcon,
   //HomeIcon,
   ShoppingCartIcon,
-  XIcon
+  XIcon,
+  PlusCircleIcon
 } from '@heroicons/react/outline';
 
 import { Link } from 'react-router-dom';
@@ -15,6 +16,7 @@ const navigation = [
   { name: 'Vendre', href: '/dashboard', icon: CurrencyEuroIcon },
   { name: 'Gestion des stocks', href: '/dashboard/stock', icon: ShoppingCartIcon },
   { name: 'Utilisateurs', href: '/dashboard/users', icon: UsersIcon },
+  { name: 'Ajouter un product', href: '/dashboard/add-product', icon: PlusCircleIcon },
 ];
 
 function classNames(...classes: unknown[]) {
diff --git a/src/pages/add_product.tsx b/src/pages/add_product.tsx
new file mode 100644
index 0000000..c0d9d3d
--- /dev/null
+++ b/src/pages/add_product.tsx
@@ -0,0 +1,163 @@
+import { useState, useEffect } from 'react';
+
+import { getCategories, addItem } from '../apis/back';
+
+const AddProduct = () => {
+  const [categories, setCategories] = useState<any[]>([]);
+
+  const [name, setName] = useState("");
+  const [price, setPrice] = useState(0);
+  const [priceAdherant, setPriceAdherant] = useState(0);
+  const [stock, setStock] = useState(0);
+  const [category_id, setCategory] = useState("n/a");
+
+  useEffect(() => {
+    getCategories().then((data) => {
+      setCategories(data);
+    }).catch((_) => {
+      setCategories([]);
+    });
+  }, []);
+
+  function createItem() {
+    if (category_id !== "n/a") {
+      console.log("Creating item: " + name + " " + price + " " + priceAdherant + " " + stock + " " + category_id);
+      addItem(name, price, priceAdherant, stock, category_id).then((data) => {
+        console.log(data);
+  
+        // Reset form data
+        setName("");
+        setPrice(0);
+        setPriceAdherant(0);
+        setStock(0);
+        setCategory("n/a");
+      }).catch((_) => {
+        console.log("Error");
+      });
+    } else {
+      console.log("Please select a category");
+    }
+  }
+
+  return (
+    <div className="max-w-7xl mx-auto px-4 sm:px-6 md:px-8">
+    <div className="pt-8">
+      <div className="mb-12">
+        <h3 className="text-3xl leading-6 font-medium text-gray-900">Ajouter un produit</h3>
+      </div>
+      <div className="">
+        <div className="mt-5">
+          <label htmlFor="name" className="block text-sm font-medium text-gray-700">
+            Nom
+          </label>
+          <div className="mt-1">
+            <input
+              type="text"
+              name="name"
+              id="name"
+              onChange={(e) => setName(e.target.value)}
+              value={name}
+              className="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md"
+            />
+          </div>
+        </div>
+
+        <div>
+          <p className="mt-10 text-xl">Prix</p>
+          <div className="flex flex-row w-full mt-3">
+            <div className="w-1/2 mr-2">
+              <label htmlFor="price" className="block text-sm font-medium text-gray-700">
+                Prix (normal)
+              </label>
+              <div className="mt-1">
+                <input
+                  type="number"
+                  name="price"
+                  id="price"
+                  onChange={(e) => setPrice(parseFloat(e.target.value))}
+                  value={price}
+                  min="0.5"
+                  placeholder="1.5"
+                  step="0.5"
+                  className="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md"
+                />
+              </div>
+            </div>
+
+            <div className="w-1/2 ml-2">
+              <label htmlFor="price-adherant" className="block text-sm font-medium text-gray-700">
+                Prix (adhérent)
+              </label>
+              <div className="mt-1">
+                <input
+                  type="number"
+                  name="price-adherant"
+                  id="price-adherant"
+                  onChange={(e) => setPriceAdherant(parseFloat(e.target.value))}
+                  value={priceAdherant}
+                  min="0.5"
+                  placeholder="1.5"
+                  step="0.5"
+                  className="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md"
+                />
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <div>
+          <p className="mt-10 text-xl">Catégorie</p>
+          <div className="flex flex-row w-full mt-3">
+            <div className="w-1/2">
+              <div className="mt-1">
+                <select
+                  id="category"
+                  name="category"
+                  onChange={(e) => setCategory(e.target.value.toString())}
+                  value={category_id}
+                  className="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md"
+                >
+                  <option value="0">Choisir une catégorie</option>
+                  {categories.map((category) => (
+                    <option key={category.id} value={category.id}>
+                      {category.name}
+                    </option>
+                  ))}
+                </select>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <div>
+          <p className="mt-10 text-xl">Quantité</p>
+          <div className="flex flex-row w-full mt-3">
+          <div className="w-1/2">
+              <div className="mt-1">
+                <input
+                  type="number"
+                  name="quantity"
+                  id="quantity"
+                  onChange={(e) => setStock(parseInt(e.target.value))}
+                  value={stock}
+                  min="0"
+                  placeholder="1"
+                  step="1"
+                  className="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md"
+                />
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <button type="button" className="mt-10 w-full sm:w-auto bg-indigo-500 text-white py-2 px-4 rounded-md hover:bg-indigo-600" onClick={() => {createItem()}}>
+          Ajouter
+        </button>
+
+      </div>
+    </div>
+    </div>
+  )
+}
+
+export default AddProduct;
\ No newline at end of file
-- 
GitLab