Forráskód Böngészése

add the new table and other components

gdias 3 hónapja
szülő
commit
f80b282db4

+ 105 - 0
src/lib/components/containers/Tables.svelte

@@ -0,0 +1,105 @@
+<script>
+  import { createEventDispatcher } from 'svelte';
+
+  // Título do bloco da tabela
+  export let title = 'Lista';
+
+  // Ex: [{ key: "nome", label: "Nome" }, { key: "preco", label: "Preço" }]
+  export let columns = [];
+  // Ex: [{ nome: "Produto 1", preco: 100 }, { nome: "Produto 2", preco: 200 }]
+  export let data = [];
+
+  // Controla exibição da coluna de ações
+  export let showActions = true;
+
+  const dispatch = createEventDispatcher();
+
+  function handleAddTop() {
+    dispatch('addTop');
+  }
+
+  function handleEditRow(row) {
+    dispatch('editRow', { row });
+  }
+
+  function handleDeleteRow(row) {
+    dispatch('deleteRow', { row });
+  }
+</script>
+
+<div class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm">
+  <div class="flex items-center justify-between px-5 py-4 border-b border-gray-200 dark:border-gray-700">
+    <h3 class="text-base font-semibold text-gray-800 dark:text-gray-100">{title}</h3>
+    <button
+      class="inline-flex items-center justify-center rounded-md bg-blue-600 hover:bg-blue-700 text-white w-10 h-10 focus:outline-none focus:ring-2 focus:ring-blue-500"
+      type="button"
+      title="Adicionar"
+      on:click={handleAddTop}
+    >
+      <img src="/icons/plus-white.svg" alt="Adicionar" class="w-6 h-6" />
+      <span class="sr-only">Adicionar</span>
+    </button>
+  </div>
+
+  <div class="overflow-x-auto">
+    <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+      <thead class="bg-gray-50 dark:bg-gray-700">
+        <tr>
+          {#each columns as col}
+            <th class="px-6 py-3 text-left text-sm font-semibold uppercase tracking-wide text-gray-700 dark:text-gray-200">
+              {col.label}
+            </th>
+          {/each}
+          {#if showActions}
+            <th class="px-6 py-3 text-right text-sm font-semibold uppercase tracking-wide text-gray-700 dark:text-gray-200">Ações</th>
+          {/if}
+        </tr>
+      </thead>
+      <tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
+        {#if data.length > 0}
+          {#each data as row}
+            <tr class="hover:bg-gray-50 dark:hover:bg-gray-700/60">
+              {#each columns as col}
+                <td class="px-6 py-3 text-base text-gray-700 dark:text-gray-300">
+                  {row[col.key]}
+                </td>
+              {/each}
+              {#if showActions}
+                <td class="px-6 py-3 text-sm text-right whitespace-nowrap">
+                  <div class="inline-flex items-center gap-2">
+                    <button
+                      class="inline-flex items-center justify-center w-9 h-9 rounded-md border border-gray-200 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700"
+                      type="button"
+                      title="Editar"
+                      on:click={() => handleEditRow(row)}
+                    >
+                      <img src="/icons/edit-light.svg" alt="Editar" class="w-5 h-5 block dark:hidden" />
+                      <img src="/icons/edit-dark.svg" alt="Editar" class="w-5 h-5 hidden dark:block" />
+                      <span class="sr-only">Editar</span>
+                    </button>
+                    <button
+                      class="inline-flex items-center justify-center w-9 h-9 rounded-md border border-gray-200 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700"
+                      type="button"
+                      title="Excluir"
+                      on:click={() => handleDeleteRow(row)}
+                    >
+                      <img src="/icons/trash-light.svg" alt="Excluir" class="w-5 h-5 block dark:hidden" />
+                      <img src="/icons/trash-dark.svg" alt="Excluir" class="w-5 h-5 hidden dark:block" />
+                      <span class="sr-only">Excluir</span>
+                    </button>
+                  </div>
+                </td>
+              {/if}
+            </tr>
+          {/each}
+        {:else}
+          <tr>
+            <td colspan={columns.length + (showActions ? 1 : 0)} class="px-4 py-6 text-center text-gray-400 dark:text-gray-500">
+              Nenhum dado encontrado
+            </td>
+          </tr>
+        {/if}
+      </tbody>
+    </table>
+  </div>
+</div>

+ 56 - 0
src/lib/components/containers/cpr/RegisterCpr.svelte

@@ -0,0 +1,56 @@
+<script>
+    let additive = "";
+    let contractCode = "";
+    let issuer = "";
+    let outside = false;
+  </script>
+  
+  <div class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm">
+  <form class="space-y-4 p-4">
+    <div class="grid grid-cols-2 gap-4">
+      <div>
+        <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Aditivo *</label>
+        <input
+          bind:value={additive}
+          class="mt-1 block w-full rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700/70 text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-400 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
+          placeholder="Digite o nome"
+        />
+      </div>
+    </div>
+  
+    <div>
+      <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Código Contrato *</label>
+      <select
+        bind:value={contractCode}
+        class="mt-1 block w-full rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700/70 text-gray-900 dark:text-gray-200 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
+      >
+        <option value="">Código Contrato</option>
+        <option value="1">Categoria 1</option>
+        <option value="2">Categoria 2</option>
+      </select>
+    </div>
+
+    <div>
+        <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Emissor *</label>
+        <select
+          bind:value={issuer}
+          class="mt-1 block w-full rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700/70 text-gray-900 dark:text-gray-200 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
+        >
+          <option value="">Emissor</option>
+          <option value="1">Categoria 1</option>
+          <option value="2">Categoria 2</option>
+        </select>
+      </div>
+  
+    <div class="flex gap-4">
+      <label class="flex items-center gap-2 text-gray-700 dark:text-gray-300">
+        <input type="checkbox" bind:checked={outside} class="accent-blue-600" />
+        CPR Externo
+      </label>
+    </div>
+  
+    <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-lg">
+      Registrar CPR
+    </button>
+  </form>
+  </div>

+ 26 - 0
src/lib/components/containers/cpr/Tabs.svelte

@@ -0,0 +1,26 @@
+<script>
+    export let tabs = [];
+    export let active = 0;
+  
+    function selectTab(index) {
+      active = index;
+      const event = new CustomEvent("change", { detail: index });
+      dispatchEvent(event);
+    }
+  </script>
+  
+  <div class="flex border-b border-gray-200">
+    {#each tabs as tab, i}
+      <button
+        class={`px-4 py-2 -mb-px border-b-2 ${
+          i === active
+            ? "border-blue-600 text-blue-600 font-medium"
+            : "border-transparent text-gray-500 hover:text-gray-700"
+        }`}
+        on:click={() => selectTab(i)}
+      >
+        {tab}
+      </button>
+    {/each}
+  </div>
+  

+ 0 - 1
src/lib/layout/SideBar.svelte

@@ -15,7 +15,6 @@
     { id: 'dashboard', href: '/dashboard', label: 'Início', icon: dashboardIcon },
     { id: 'cpr', href: '/cpr', label: 'CPR', icon: cprIcon },
     { id: 'commodities', href: '/commodities', label: 'Commodities', icon: commoditiesIcon },
-    { id: 'tokens', href: '/tokens', label: 'Tokens', icon: tokensIcon },
     { id: 'bank', href: '/bank', label: 'Bank', icon: bankIcon },
     { id: 'operations', href: '/operations', label: 'Operação', icon: operationsIcon },
     { id: 'marketplace', href: '/marketplace', label: 'Marketplace', icon: marketplaceIcon },

+ 1 - 1
src/routes/+page.svelte

@@ -114,7 +114,7 @@
     </div>
 
     <p class="mt-6 text-center text-sm text-gray-600 dark:text-gray-400">
-      Ainda não tem conta? <a href="#" class="text-blue-600 hover:text-blue-500">Fale com o suporte</a>
+      Esqueceu a senha? <a href="#" class="text-blue-600 hover:text-blue-500">Fale com o suporte</a>
     </p>
   </div>
   

+ 52 - 7
src/routes/cpr/+page.svelte

@@ -1,18 +1,63 @@
 <script>
   import Header from '$lib/layout/Header.svelte';
-  import SectionMenu from '$lib/components/containers/SectionMenu.svelte';
+  import Tabs from '$lib/components/containers/cpr/Tabs.svelte';
+  import RegisterCpr from '$lib/components/containers/cpr/RegisterCpr.svelte';
+  import Tables from '$lib/components/containers/Tables.svelte';
 
   const breadcrumb = [{ label: 'Início' }, { label: 'CPR', active: true }];
-  const options = [
-    { icon: 'contract', label: 'Contrato', onClick: () => {} },
-    { icon: 'issue', label: 'Emissão', onClick: () => {} },
-    { icon: 'register', label: 'Registro', onClick: () => {} },
+  let activeTab = 0;
+  const tabs = ["Contrato", "Registro", "Emissão"];
+
+  let columns = [
+    { key: "nome", label: "Nome" },
+    { key: "status", label: "Status" }
+  ];
+
+  let data = [
+    { nome: "CPR A", status: "Disponível" },
+    { nome: "CPR B", status: "Indisponível" }
   ];
+
+  function handleAddTop() {
+    // Ao clicar em "+", mudar para a aba de Registro (index 1) e exibir Tabs + Form
+    activeTab = 1;
+  }
+
+  function handleDeleteRow(e) {
+    const { row } = e.detail;
+    // Remove pelo objeto (referência) para manter simples no exemplo
+    data = data.filter((r) => r !== row);
+  }
+
+  function handleEditRow(e) {
+    const { row } = e.detail;
+    // Exemplo simples: alterna status ao editar
+    data = data.map((r) =>
+      r === row ? { ...r, status: r.status === 'Disponível' ? 'Indisponível' : 'Disponível' } : r
+    );
+  }
 </script>
 
 <div>
   <Header title="CPR - Cédula de Produto Rural" subtitle="Gestão de contratos, emissão e registro de CPRs" breadcrumb={breadcrumb} />
-  <div class="p-8">
-    <SectionMenu title="Opções de CPR" {options} />
+  <div class="p-4">
+    <div class="max-w-6xl mx-auto mt-4">
+    
+      {#if activeTab === 0}
+        <Tables
+          title="Produtos"
+          columns={columns}
+          data={data}
+          on:addTop={handleAddTop}
+          on:editRow={handleEditRow}
+          on:deleteRow={handleDeleteRow}
+        />
+      {:else if activeTab === 1}
+      <Tabs {tabs} bind:active={activeTab} />
+      <div class="mt-4">
+        <RegisterCpr />
+      </div>
+      {/if}
+    </div>
   </div>
 </div>

+ 1 - 1
src/routes/dashboard/+page.svelte

@@ -16,7 +16,7 @@
   const breadcrumb = [{ label: 'Início', active: true }];
 </script>
 
-<Header title="Dashboard" subtitle="Visão geral do sistema de commodities" breadcrumb={breadcrumb} />
+<Header title="Início" subtitle="Visão geral do sistema de commodities" breadcrumb={breadcrumb} />
 <div class="p-8 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
   {#each stats as stat}
     <StatsCard {...stat} />

+ 3 - 0
static/icons/edit-dark.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#e5e7eb">
+  <path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25Zm2.92 2.83H5v-.92l8.19-8.19.92.92-8.19 8.19Zm10.61-12.2c.2-.2.2-.51 0-.71l-1.7-1.7a.5.5 0 0 0-.71 0l-1.37 1.37 2.41 2.41 1.37-1.37Z"/>
+</svg>

+ 3 - 0
static/icons/edit-light.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#374151">
+  <path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25Zm2.92 2.83H5v-.92l8.19-8.19.92.92-8.19 8.19Zm10.61-12.2c.2-.2.2-.51 0-.71l-1.7-1.7a.5.5 0 0 0-.71 0l-1.37 1.37 2.41 2.41 1.37-1.37Z"/>
+</svg>

+ 3 - 0
static/icons/edit.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
+  <path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25Zm2.92 2.83H5v-.92l8.19-8.19.92.92-8.19 8.19Zm10.61-12.2c.2-.2.2-.51 0-.71l-1.7-1.7a.5.5 0 0 0-.71 0l-1.37 1.37 2.41 2.41 1.37-1.37Z"/>
+</svg>

+ 3 - 0
static/icons/plus-dark.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#e5e7eb">
+  <path d="M12 5c.552 0 1 .448 1 1v5h5c.552 0 1 .448 1 1s-.448 1-1 1h-5v5c0 .552-.448 1-1 1s-1-.448-1-1v-5H6c-.552 0-1-.448-1-1s.448-1 1-1h5V6c0-.552.448-1 1-1Z"/>
+</svg>

+ 3 - 0
static/icons/plus-light.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#374151">
+  <path d="M12 5c.552 0 1 .448 1 1v5h5c.552 0 1 .448 1 1s-.448 1-1 1h-5v5c0 .552-.448 1-1 1s-1-.448-1-1v-5H6c-.552 0-1-.448-1-1s.448-1 1-1h5V6c0-.552.448-1 1-1Z"/>
+</svg>

+ 3 - 0
static/icons/plus-white.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#ffffff">
+  <path d="M12 5c.552 0 1 .448 1 1v5h5c.552 0 1 .448 1 1s-.448 1-1 1h-5v5c0 .552-.448 1-1 1s-1-.448-1-1v-5H6c-.552 0-1-.448-1-1s.448-1 1-1h5V6c0-.552.448-1 1-1Z"/>
+</svg>

+ 3 - 0
static/icons/plus.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
+  <path d="M12 5c.552 0 1 .448 1 1v5h5c.552 0 1 .448 1 1s-.448 1-1 1h-5v5c0 .552-.448 1-1 1s-1-.448-1-1v-5H6c-.552 0-1-.448-1-1s.448-1 1-1h5V6c0-.552.448-1 1-1Z"/>
+</svg>

+ 3 - 0
static/icons/trash-dark.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#e5e7eb">
+  <path d="M9 3a1 1 0 0 0-1 1v1H5.5a1 1 0 1 0 0 2H6v11a3 3 0 0 0 3 3h6a3 3 0 0 0 3-3V7h.5a1 1 0 1 0 0-2H16V4a1 1 0 0 0-1-1H9Zm2 4a1 1 0 1 1 2 0v10a1 1 0 1 1-2 0V7Zm-3 0a1 1 0 1 1 2 0v10a1 1 0 1 1-2 0V7Zm8 0a1 1 0 1 1 2 0v10a1 1 0 1 1-2 0V7Z"/>
+</svg>

+ 3 - 0
static/icons/trash-light.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#374151">
+  <path d="M9 3a1 1 0 0 0-1 1v1H5.5a1 1 0 1 0 0 2H6v11a3 3 0 0 0 3 3h6a3 3 0 0 0 3-3V7h.5a1 1 0 1 0 0-2H16V4a1 1 0 0 0-1-1H9Zm2 4a1 1 0 1 1 2 0v10a1 1 0 1 1-2 0V7Zm-3 0a1 1 0 1 1 2 0v10a1 1 0 1 1-2 0V7Zm8 0a1 1 0 1 1 2 0v10a1 1 0 1 1-2 0V7Z"/>
+</svg>

+ 3 - 0
static/icons/trash.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
+  <path d="M9 3a1 1 0 0 0-1 1v1H5.5a1 1 0 1 0 0 2H6v11a3 3 0 0 0 3 3h6a3 3 0 0 0 3-3V7h.5a1 1 0 1 0 0-2H16V4a1 1 0 0 0-1-1H9Zm2 4a1 1 0 1 1 2 0v10a1 1 0 1 1-2 0V7Zm-3 0a1 1 0 1 1 2 0v10a1 1 0 1 1-2 0V7Zm8 0a1 1 0 1 1 2 0v10a1 1 0 1 1-2 0V7Z"/>
+</svg>