|
|
@@ -0,0 +1,325 @@
|
|
|
+<script>
|
|
|
+ import { onMount } from 'svelte';
|
|
|
+ import add_icon from '$lib/assets/add_icon.svg';
|
|
|
+ import save_icon from '$lib/assets/save_icon.svg';
|
|
|
+ import trash_icon from '$lib/assets/trash_icon.svg';
|
|
|
+
|
|
|
+ let products = [];
|
|
|
+ let categories = [];
|
|
|
+
|
|
|
+ let isAddingProduct = false;
|
|
|
+ let editingProductId = null;
|
|
|
+ let productFormData = {
|
|
|
+ name: '',
|
|
|
+ category: '',
|
|
|
+ price: 0,
|
|
|
+ sendToKitchen: false
|
|
|
+ };
|
|
|
+
|
|
|
+ let isAddingCategory = false;
|
|
|
+ let newCategoryName = '';
|
|
|
+ let selectedCategoryFilter = '';
|
|
|
+
|
|
|
+ $: filteredProducts = selectedCategoryFilter
|
|
|
+ ? products.filter((p) => p.category === selectedCategoryFilter)
|
|
|
+ : products;
|
|
|
+
|
|
|
+ function resetProductForm() {
|
|
|
+ productFormData = {
|
|
|
+ name: '',
|
|
|
+ category: categories[0]?.name ?? '',
|
|
|
+ price: 0,
|
|
|
+ sendToKitchen: false
|
|
|
+ };
|
|
|
+ editingProductId = null;
|
|
|
+ isAddingProduct = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleProductSubmit(event) {
|
|
|
+ event.preventDefault();
|
|
|
+
|
|
|
+ if (!productFormData.name || !productFormData.category || productFormData.price <= 0) {
|
|
|
+ console.error('Preencha todos os campos corretamente');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (editingProductId) {
|
|
|
+ const index = products.findIndex((p) => p.id === editingProductId);
|
|
|
+ if (index !== -1) {
|
|
|
+ products[index] = {
|
|
|
+ ...products[index],
|
|
|
+ ...productFormData
|
|
|
+ };
|
|
|
+ products = products; // Força reatividade
|
|
|
+ console.log('Produto atualizado com sucesso!');
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ const newProduct = {
|
|
|
+ id: Date.now(),
|
|
|
+ ...productFormData
|
|
|
+ };
|
|
|
+ products = [...products, newProduct];
|
|
|
+ console.log('Produto criado com sucesso!');
|
|
|
+ }
|
|
|
+
|
|
|
+ resetProductForm();
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleEditProduct(product) {
|
|
|
+ productFormData = {
|
|
|
+ name: product.name,
|
|
|
+ category: product.category,
|
|
|
+ price: product.price,
|
|
|
+ sendToKitchen: product.sendToKitchen
|
|
|
+ };
|
|
|
+ editingProductId = product.id;
|
|
|
+ isAddingProduct = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleCategorySubmit(event) {
|
|
|
+ event.preventDefault();
|
|
|
+
|
|
|
+ if (!newCategoryName) {
|
|
|
+ console.error('Digite o nome da categoria');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (categories.some((c) => c.name === newCategoryName)) {
|
|
|
+ console.error('Essa categoria já existe');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ categories = [...categories, { name: newCategoryName }];
|
|
|
+ console.log('Categoria criada com sucesso');
|
|
|
+ newCategoryName = '';
|
|
|
+ isAddingCategory = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleDeleteCategory(name) {
|
|
|
+ categories = categories.filter((c) => c.name !== name);
|
|
|
+ products = products.filter((p) => p.category !== name);
|
|
|
+ if (selectedCategoryFilter === name) selectedCategoryFilter = '';
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleDeleteProduct(id) {
|
|
|
+ products = products.filter((p) => p.id !== id);
|
|
|
+ }
|
|
|
+
|
|
|
+ onMount(() => {
|
|
|
+ const requestOptions = { method: 'GET', redirect: 'follow' };
|
|
|
+
|
|
|
+ fetch('https://fakestoreapi.com/users', requestOptions)
|
|
|
+ .then((response) => response.json())
|
|
|
+ .then((data) => {
|
|
|
+ categories = data.map((categorie) => ({
|
|
|
+ name: categorie.username
|
|
|
+ }));
|
|
|
+ })
|
|
|
+ .catch((error) => console.error(error));
|
|
|
+
|
|
|
+ fetch('https://fakestoreapi.com/users', requestOptions)
|
|
|
+ .then((response) => response.json())
|
|
|
+ .then((data) => {
|
|
|
+ products = data.map((item, index) => ({
|
|
|
+ id: Date.now() + index,
|
|
|
+ name: item.address.street,
|
|
|
+ category: item.username,
|
|
|
+ price: Math.floor(Math.random() * 50 + 10),
|
|
|
+ sendToKitchen: Math.random() > 0.5
|
|
|
+ }));
|
|
|
+ })
|
|
|
+ .catch((error) => console.error(error));
|
|
|
+ });
|
|
|
+</script>
|
|
|
+
|
|
|
+<div class="container mx-auto">
|
|
|
+ <div class="flex flex-col">
|
|
|
+ <h1 class="mb-6 text-2xl font-bold">Gerenciar Produtos</h1>
|
|
|
+
|
|
|
+ <div class="grid grid-cols-1 gap-6 lg:grid-cols-3">
|
|
|
+ <!-- Categories -->
|
|
|
+ <div class="overflow-hidden rounded-lg bg-gray-800 shadow-lg">
|
|
|
+ <div class="flex items-center justify-between bg-gray-700 p-4">
|
|
|
+ <h2 class="text-lg font-semibold">Categorias</h2>
|
|
|
+ <button
|
|
|
+ on:click={() => (isAddingCategory = true)}
|
|
|
+ class="rounded-lg bg-emerald-600 p-1.5 hover:bg-emerald-700"
|
|
|
+ >
|
|
|
+ <img src={add_icon} alt="Adicionar" class="h-4 w-4" />
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {#if isAddingCategory}
|
|
|
+ <form on:submit={handleCategorySubmit} class="space-y-4 p-4">
|
|
|
+ <div>
|
|
|
+ <p class="mb-1 block text-sm text-gray-400">Nome da Categoria</p>
|
|
|
+ <input
|
|
|
+ bind:value={newCategoryName}
|
|
|
+ class="w-full rounded-md border border-gray-600 bg-gray-700 px-3 py-2 focus:ring-emerald-500"
|
|
|
+ placeholder="Ex: Bebidas, Porções..."
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="flex space-x-2">
|
|
|
+ <button
|
|
|
+ type="button"
|
|
|
+ on:click={() => {
|
|
|
+ isAddingCategory = false;
|
|
|
+ newCategoryName = '';
|
|
|
+ }}
|
|
|
+ class="rounded-lg bg-gray-700 px-4 py-2 hover:bg-gray-600"
|
|
|
+ >
|
|
|
+ Cancelar
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ type="submit"
|
|
|
+ class="flex items-center rounded-lg bg-emerald-600 px-4 py-2 hover:bg-emerald-700"
|
|
|
+ >
|
|
|
+ <img src={save_icon} alt="Salvar" class="mr-2 h-4 w-4" /> Salvar
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </form>
|
|
|
+ {:else}
|
|
|
+ <div class="divide-y divide-gray-700">
|
|
|
+ {#if categories.length === 0}
|
|
|
+ <div class="p-4 text-center text-gray-400">Nenhuma categoria cadastrada</div>
|
|
|
+ {:else}
|
|
|
+ {#each categories as category}
|
|
|
+ <div
|
|
|
+ class="flex cursor-pointer items-center justify-between p-4 hover:bg-gray-900"
|
|
|
+ on:click={() => (selectedCategoryFilter = category.name)}
|
|
|
+ >
|
|
|
+ <span>{category.name}</span>
|
|
|
+ <button
|
|
|
+ on:click|preventDefault|stopPropagation={() =>
|
|
|
+ handleDeleteCategory(category.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>
|
|
|
+ {/each}
|
|
|
+ {#if selectedCategoryFilter}
|
|
|
+ <div class="p-4">
|
|
|
+ <button
|
|
|
+ on:click={() => (selectedCategoryFilter = '')}
|
|
|
+ class="w-full rounded-md bg-red-600 py-1 text-sm hover:bg-red-700"
|
|
|
+ >
|
|
|
+ Remover Filtro
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ {/if}
|
|
|
+ {/if}
|
|
|
+ </div>
|
|
|
+ {/if}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- Products -->
|
|
|
+ <div class="overflow-hidden rounded-lg bg-gray-800 shadow-lg lg:col-span-2">
|
|
|
+ <div class="flex items-center justify-between bg-gray-700 p-4">
|
|
|
+ <h2 class="text-lg font-semibold">Produtos</h2>
|
|
|
+ <button
|
|
|
+ on:click={() => {
|
|
|
+ if (!categories.length) return;
|
|
|
+ resetProductForm(); // já atribui a categoria
|
|
|
+ isAddingProduct = true;
|
|
|
+ }}
|
|
|
+ class="rounded-lg bg-emerald-600 p-1.5 hover:bg-emerald-700"
|
|
|
+ >
|
|
|
+ <img src={add_icon} alt="Adicionar" class="h-4 w-4" />
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {#if isAddingProduct}
|
|
|
+ <form on:submit={handleProductSubmit} class="space-y-4 p-4">
|
|
|
+ <div>
|
|
|
+ <p class="mb-1 block text-sm text-gray-400">Nome do Produto</p>
|
|
|
+ <input
|
|
|
+ bind:value={productFormData.name}
|
|
|
+ class="w-full rounded-md border border-gray-600 bg-gray-700 px-3 py-2 focus:ring-emerald-500"
|
|
|
+ placeholder="Ex: Cerveja..."
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div>
|
|
|
+ <p class="mb-1 block text-sm text-gray-400">Categoria</p>
|
|
|
+ <select
|
|
|
+ bind:value={productFormData.category}
|
|
|
+ class="w-full rounded-md border border-gray-600 bg-gray-700 px-3 py-2 focus:ring-emerald-500"
|
|
|
+ >
|
|
|
+ {#each categories as category}
|
|
|
+ <option value={category.name}>{category.name}</option>
|
|
|
+ {/each}
|
|
|
+ </select>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div>
|
|
|
+ <p class="mb-1 block text-sm text-gray-400">Preço (R$)</p>
|
|
|
+ <input
|
|
|
+ type="number"
|
|
|
+ min="0"
|
|
|
+ step="0.01"
|
|
|
+ bind:value={productFormData.price}
|
|
|
+ class="w-full rounded-md border border-gray-600 bg-gray-700 px-3 py-2 focus:ring-emerald-500"
|
|
|
+ placeholder="0.00"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="flex items-center">
|
|
|
+ <input
|
|
|
+ id="sendToKitchen"
|
|
|
+ type="checkbox"
|
|
|
+ bind:checked={productFormData.sendToKitchen}
|
|
|
+ class="h-4 w-4 rounded border border-gray-600 bg-gray-700"
|
|
|
+ />
|
|
|
+ <label for="sendToKitchen" class="ml-2 text-sm text-gray-300"
|
|
|
+ >Enviar para a cozinha</label
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="flex space-x-2">
|
|
|
+ <button
|
|
|
+ type="button"
|
|
|
+ on:click={resetProductForm}
|
|
|
+ class="rounded-lg bg-gray-700 px-4 py-2 hover:bg-gray-600"
|
|
|
+ >
|
|
|
+ Cancelar
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ type="submit"
|
|
|
+ class="flex items-center rounded-lg bg-emerald-600 px-4 py-2 hover:bg-emerald-700"
|
|
|
+ >
|
|
|
+ <img src={save_icon} alt="Salvar" class="mr-2 h-4 w-4" /> Salvar
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </form>
|
|
|
+ {:else}
|
|
|
+ <!-- Lista de Produtos -->
|
|
|
+ {#if filteredProducts.length === 0}
|
|
|
+ <p class="p-4 text-center text-gray-400">Nenhum produto encontrado</p>
|
|
|
+ {: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.id)}
|
|
|
+ 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>
|
|
|
+ {/if}
|
|
|
+ {/if}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</div>
|