|
@@ -3,6 +3,17 @@
|
|
|
import add_icon from '$lib/assets/add_icon.svg';
|
|
import add_icon from '$lib/assets/add_icon.svg';
|
|
|
import save_icon from '$lib/assets/save_icon.svg';
|
|
import save_icon from '$lib/assets/save_icon.svg';
|
|
|
import trash_icon from '$lib/assets/trash_icon.svg';
|
|
import trash_icon from '$lib/assets/trash_icon.svg';
|
|
|
|
|
+ import edit_icon from '$lib/assets/edit_icon.svg';
|
|
|
|
|
+ import { browser } from '$app/environment';
|
|
|
|
|
+ import check_icon from '$lib/assets/check_icon.svg';
|
|
|
|
|
+ import cancel_icon from '$lib/assets/cancel_icon.svg';
|
|
|
|
|
+ let token = null;
|
|
|
|
|
+ let company = null;
|
|
|
|
|
+
|
|
|
|
|
+ if (browser) {
|
|
|
|
|
+ token = localStorage.getItem('token');
|
|
|
|
|
+ company = Number(localStorage.getItem('company'));
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
let products = [];
|
|
let products = [];
|
|
|
let categories = [];
|
|
let categories = [];
|
|
@@ -55,12 +66,13 @@
|
|
|
product_name: productFormData.name,
|
|
product_name: productFormData.name,
|
|
|
product_price: Number(productFormData.price),
|
|
product_price: Number(productFormData.price),
|
|
|
category_id: categoryObj.id,
|
|
category_id: categoryObj.id,
|
|
|
- company_id: 1
|
|
|
|
|
|
|
+ company_id: company,
|
|
|
|
|
+ product_is_kitchen: productFormData.sendToKitchen
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const requestOptions = {
|
|
const requestOptions = {
|
|
|
method: 'POST',
|
|
method: 'POST',
|
|
|
- headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
|
|
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
|
|
|
body: JSON.stringify(payload),
|
|
body: JSON.stringify(payload),
|
|
|
redirect: 'follow'
|
|
redirect: 'follow'
|
|
|
};
|
|
};
|
|
@@ -97,6 +109,53 @@
|
|
|
isAddingProduct = true;
|
|
isAddingProduct = true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // Função para enviar update para o backend
|
|
|
|
|
+ async function handleUpdateProduct(event) {
|
|
|
|
|
+ event.preventDefault();
|
|
|
|
|
+
|
|
|
|
|
+ token = localStorage.getItem('token');
|
|
|
|
|
+ company = Number(localStorage.getItem('company'));
|
|
|
|
|
+
|
|
|
|
|
+ const myHeaders = new Headers();
|
|
|
|
|
+ myHeaders.append('Authorization', `Bearer ${token}`);
|
|
|
|
|
+ myHeaders.append('Content-Type', 'application/json');
|
|
|
|
|
+
|
|
|
|
|
+ // Aqui você precisa converter o category (nome) para id, se necessário
|
|
|
|
|
+ // Vou supor que você já tem essa informação disponível, por exemplo:
|
|
|
|
|
+ // const category_id = getCategoryIdByName(productFormData.category);
|
|
|
|
|
+
|
|
|
|
|
+ const raw = JSON.stringify({
|
|
|
|
|
+ update_product_id: editingProductId,
|
|
|
|
|
+ product_name: productFormData.name,
|
|
|
|
|
+ product_price: Number(productFormData.price),
|
|
|
|
|
+ product_is_kitchen: productFormData.sendToKitchen ? 1 : 0,
|
|
|
|
|
+ company_id: company
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const requestOptions = {
|
|
|
|
|
+ method: 'POST',
|
|
|
|
|
+ headers: myHeaders,
|
|
|
|
|
+ body: raw,
|
|
|
|
|
+ redirect: 'follow'
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const response = await fetch('https://dev2.mixtech.dev.br/product/update', requestOptions);
|
|
|
|
|
+ const result = await response.json();
|
|
|
|
|
+
|
|
|
|
|
+ if (result.status === 'ok') {
|
|
|
|
|
+ console.log('Produto atualizado com sucesso!');
|
|
|
|
|
+ isAddingProduct = false;
|
|
|
|
|
+ editingProductId = null;
|
|
|
|
|
+ // Aqui você pode recarregar a lista de produtos, se quiser
|
|
|
|
|
+ } else {
|
|
|
|
|
+ console.error('Erro ao atualizar produto:', result.msg || result);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('Erro na requisição de atualização:', error);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
function handleCategorySubmit(event) {
|
|
function handleCategorySubmit(event) {
|
|
|
event.preventDefault();
|
|
event.preventDefault();
|
|
|
|
|
|
|
@@ -111,11 +170,11 @@
|
|
|
|
|
|
|
|
const requestOptions = {
|
|
const requestOptions = {
|
|
|
method: 'POST',
|
|
method: 'POST',
|
|
|
- headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
|
|
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
|
|
|
body: JSON.stringify({
|
|
body: JSON.stringify({
|
|
|
category_name: newCategoryName,
|
|
category_name: newCategoryName,
|
|
|
category_is_kitchen: false,
|
|
category_is_kitchen: false,
|
|
|
- company_id: 1
|
|
|
|
|
|
|
+ company_id: company
|
|
|
}),
|
|
}),
|
|
|
redirect: 'follow'
|
|
redirect: 'follow'
|
|
|
};
|
|
};
|
|
@@ -148,10 +207,10 @@
|
|
|
|
|
|
|
|
fetch('https://dev2.mixtech.dev.br/category/delete', {
|
|
fetch('https://dev2.mixtech.dev.br/category/delete', {
|
|
|
method: 'POST',
|
|
method: 'POST',
|
|
|
- headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
|
|
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
|
|
|
body: JSON.stringify({
|
|
body: JSON.stringify({
|
|
|
category_name: name,
|
|
category_name: name,
|
|
|
- company_id: 1
|
|
|
|
|
|
|
+ company_id: company
|
|
|
}),
|
|
}),
|
|
|
redirect: 'follow'
|
|
redirect: 'follow'
|
|
|
})
|
|
})
|
|
@@ -173,10 +232,10 @@
|
|
|
function handleDeleteProduct(productName) {
|
|
function handleDeleteProduct(productName) {
|
|
|
const requestOptions = {
|
|
const requestOptions = {
|
|
|
method: 'POST',
|
|
method: 'POST',
|
|
|
- headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
|
|
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
|
|
|
body: JSON.stringify({
|
|
body: JSON.stringify({
|
|
|
product_name: productName,
|
|
product_name: productName,
|
|
|
- company_id: 1
|
|
|
|
|
|
|
+ company_id: company
|
|
|
}),
|
|
}),
|
|
|
redirect: 'follow'
|
|
redirect: 'follow'
|
|
|
};
|
|
};
|
|
@@ -197,13 +256,14 @@
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
onMount(() => {
|
|
onMount(() => {
|
|
|
- const companyId = 1;
|
|
|
|
|
-
|
|
|
|
|
const requestOptions = {
|
|
const requestOptions = {
|
|
|
method: 'POST',
|
|
method: 'POST',
|
|
|
- headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
|
|
+ Authorization: `Bearer ${token}`
|
|
|
|
|
+ },
|
|
|
redirect: 'follow',
|
|
redirect: 'follow',
|
|
|
- body: JSON.stringify({ company_id: companyId })
|
|
|
|
|
|
|
+ body: JSON.stringify({ company_id: company })
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
fetch('https://dev2.mixtech.dev.br/category/get', requestOptions)
|
|
fetch('https://dev2.mixtech.dev.br/category/get', requestOptions)
|
|
@@ -212,19 +272,18 @@
|
|
|
if (res.status === 'ok') {
|
|
if (res.status === 'ok') {
|
|
|
categories = res.data.map((categorie) => ({
|
|
categories = res.data.map((categorie) => ({
|
|
|
id: categorie.category_id,
|
|
id: categorie.category_id,
|
|
|
- name: categorie.category_name,
|
|
|
|
|
- isKitchen: categorie.category_is_kitchen === 1
|
|
|
|
|
|
|
+ name: categorie.category_name
|
|
|
}));
|
|
}));
|
|
|
|
|
+
|
|
|
|
|
+ return fetch('https://dev2.mixtech.dev.br/product/get', requestOptions);
|
|
|
} else {
|
|
} else {
|
|
|
- console.error('Erro ao carregar categorias:', res.msg);
|
|
|
|
|
|
|
+ throw new Error(`Erro ao carregar categorias: ${res.msg}`);
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
- .catch((error) => console.error('Erro ao buscar categorias:', error));
|
|
|
|
|
-
|
|
|
|
|
- fetch('https://dev2.mixtech.dev.br/product/get', requestOptions)
|
|
|
|
|
.then((response) => response.json())
|
|
.then((response) => response.json())
|
|
|
.then((res) => {
|
|
.then((res) => {
|
|
|
if (res.status === 'ok') {
|
|
if (res.status === 'ok') {
|
|
|
|
|
+ console.log(res);
|
|
|
products = res.data.map((item) => {
|
|
products = res.data.map((item) => {
|
|
|
const category = categories.find((c) => c.id === item.category_id);
|
|
const category = categories.find((c) => c.id === item.category_id);
|
|
|
return {
|
|
return {
|
|
@@ -232,14 +291,16 @@
|
|
|
name: item.product_name,
|
|
name: item.product_name,
|
|
|
category: category?.name || 'Sem categoria',
|
|
category: category?.name || 'Sem categoria',
|
|
|
price: Number(item.product_price),
|
|
price: Number(item.product_price),
|
|
|
- sendToKitchen: category?.isKitchen || false
|
|
|
|
|
|
|
+ sendToKitchen: item.product_is_kitchen
|
|
|
};
|
|
};
|
|
|
});
|
|
});
|
|
|
} else {
|
|
} else {
|
|
|
console.error('Erro ao carregar produtos:', res.msg);
|
|
console.error('Erro ao carregar produtos:', res.msg);
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
- .catch((error) => console.error('Erro ao buscar produtos:', error));
|
|
|
|
|
|
|
+ .catch((error) => {
|
|
|
|
|
+ console.error('Erro ao buscar dados:', error);
|
|
|
|
|
+ });
|
|
|
});
|
|
});
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
@@ -425,27 +486,55 @@
|
|
|
{#if filteredProducts.length === 0}
|
|
{#if filteredProducts.length === 0}
|
|
|
<p class="p-4 text-center text-gray-400">Nenhum produto encontrado</p>
|
|
<p class="p-4 text-center text-gray-400">Nenhum produto encontrado</p>
|
|
|
{:else}
|
|
{:else}
|
|
|
- <ul class="divide-y divide-gray-700">
|
|
|
|
|
- {#each filteredProducts as product}
|
|
|
|
|
- <li
|
|
|
|
|
- class="flex items-center justify-between p-4 hover:bg-gray-900"
|
|
|
|
|
- on:click={() => handleEditProduct(product)}
|
|
|
|
|
- >
|
|
|
|
|
- <div>
|
|
|
|
|
- <p class="text-sm font-semibold text-white">{product.name}</p>
|
|
|
|
|
- <p class="text-xs text-gray-400">
|
|
|
|
|
- {product.category} • R$ {product.price.toFixed(2)}
|
|
|
|
|
- </p>
|
|
|
|
|
- </div>
|
|
|
|
|
- <button
|
|
|
|
|
- on:click|stopPropagation={() => handleDeleteProduct(product.name)}
|
|
|
|
|
- class="rounded-lg p-1.5 text-red-400 hover:bg-red-900/20"
|
|
|
|
|
- >
|
|
|
|
|
- <img src={trash_icon} alt="Deletar" class="h-4 w-4" />
|
|
|
|
|
- </button>
|
|
|
|
|
- </li>
|
|
|
|
|
- {/each}
|
|
|
|
|
- </ul>
|
|
|
|
|
|
|
+ <div class="overflow-x-auto rounded-lg">
|
|
|
|
|
+ <table
|
|
|
|
|
+ class="min-w-full table-auto divide-y divide-gray-700 text-left text-sm text-white"
|
|
|
|
|
+ >
|
|
|
|
|
+ <thead class="bg-gray-800">
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <th class="px-6 py-3 font-semibold">Nome</th>
|
|
|
|
|
+ <th class="px-6 py-3 font-semibold">Categoria</th>
|
|
|
|
|
+ <th class="px-6 py-3 font-semibold">Preço</th>
|
|
|
|
|
+ <th class="px-6 py-3 font-semibold">Cozinha</th>
|
|
|
|
|
+ <th class="px-6 py-3 text-center font-semibold">Ações</th>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ </thead>
|
|
|
|
|
+ <tbody class="divide-y divide-gray-700 bg-gray-800">
|
|
|
|
|
+ {#each filteredProducts as product}
|
|
|
|
|
+ <tr class="transition-colors hover:bg-gray-800">
|
|
|
|
|
+ <td class="px-6 py-4">{product.name}</td>
|
|
|
|
|
+ <td class="px-6 py-4 text-gray-400">{product.category}</td>
|
|
|
|
|
+ <td class="px-6 py-4 text-gray-400">R$ {product.price.toFixed(2)}</td>
|
|
|
|
|
+ <td class="px-6 py-4">
|
|
|
|
|
+ <div class="mr-1 flex items-center justify-center">
|
|
|
|
|
+ {#if product.sendToKitchen}
|
|
|
|
|
+ <img class="h-4 w-4" src={check_icon} alt="check" />
|
|
|
|
|
+ {:else}
|
|
|
|
|
+ <img class="h-5 w-5" src={cancel_icon} alt="cancel" />
|
|
|
|
|
+ {/if}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </td>
|
|
|
|
|
+ <td class="px-6 py-4">
|
|
|
|
|
+ <div class="flex justify-center gap-4">
|
|
|
|
|
+ <button
|
|
|
|
|
+ on:click={() => handleEditProduct(product)}
|
|
|
|
|
+ class="rounded-lg p-1.5 text-blue-400 hover:bg-blue-900/20"
|
|
|
|
|
+ >
|
|
|
|
|
+ <img src={edit_icon} alt="Editar" class="h-4 w-4" />
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <button
|
|
|
|
|
+ on:click|stopPropagation={() => handleDeleteProduct(product.name)}
|
|
|
|
|
+ class="rounded-lg p-1.5 text-red-400 hover:bg-red-900/20"
|
|
|
|
|
+ >
|
|
|
|
|
+ <img src={trash_icon} alt="Deletar" class="h-4 w-4" />
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ {/each}
|
|
|
|
|
+ </tbody>
|
|
|
|
|
+ </table>
|
|
|
|
|
+ </div>
|
|
|
{/if}
|
|
{/if}
|
|
|
{/if}
|
|
{/if}
|
|
|
</div>
|
|
</div>
|