Jelajahi Sumber

FEATURE: add the mobile view, add the logo on the sidebar

gdias 2 bulan lalu
induk
melakukan
18f62a1dff
4 mengubah file dengan 60 tambahan dan 7 penghapusan
  1. TEMPAT SAMPAH
      src/lib/assets/logo2.png
  2. 57 4
      src/lib/layout/SideBar.svelte
  3. 1 1
      src/routes/+layout.svelte
  4. 2 2
      src/routes/trading/+page.svelte

TEMPAT SAMPAH
src/lib/assets/logo2.png


+ 57 - 4
src/lib/layout/SideBar.svelte

@@ -10,29 +10,78 @@
   import reportsIcon from '$lib/assets/icons/sidebar/reports.svg?raw';
   import usersIcon from '$lib/assets/icons/sidebar/users.svg?raw';
   import settingsIcon from '$lib/assets/icons/sidebar/settings.svg?raw';
+  import logo from '$lib/assets/logo2.png';
+  import { onMount } from 'svelte';
 
   const navItems = [
     { 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: 'bank', href: '/bank', label: 'Bank', icon: bankIcon },
-    { id: 'operations', href: '/operations', label: 'Operação', icon: operationsIcon },
+    { id: 'trading', href: '/trading', label: 'Trading', icon: operationsIcon },
     { id: 'marketplace', href: '/marketplace', label: 'Marketplace', icon: marketplaceIcon },
     { id: 'reports', href: '/reports', label: 'Relatórios', icon: reportsIcon },
     { id: 'users', href: '/users', label: 'Usuários', icon: usersIcon },
     { id: 'settings', href: '/settings', label: 'Configurações', icon: settingsIcon },
   ];
+
+  // Responsividade: fechado em telas pequenas, aberto em >= md
+  let isOpen = false;
+  const MD = 768;
+
+  function syncWithViewport() {
+    isOpen = typeof window !== 'undefined' && window.innerWidth >= MD;
+  }
+
+  function openSidebar() {
+    isOpen = true;
+  }
+
+  function closeSidebar() {
+    if (typeof window !== 'undefined' && window.innerWidth < MD) {
+      isOpen = false;
+    }
+  }
+
+  onMount(() => {
+    syncWithViewport();
+    const onResize = () => syncWithViewport();
+    window.addEventListener('resize', onResize);
+    return () => window.removeEventListener('resize', onResize);
+  });
 </script>
 
-<aside class="w-64 bg-white dark:bg-gray-900 border-r border-gray-200 dark:border-gray-700 fixed h-full overflow-auto">
-  <div class="p-6 bg-gray-100 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700">
-    <h1 class="text-lg font-semibold text-gray-800 dark:text-gray-100">TooEasy Commodities</h1>
+<!-- Botão de toggle (só mobile) -->
+<button
+  class="md:hidden fixed top-4 left-4 z-50 inline-flex items-center justify-center rounded-md p-2 bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 shadow text-gray-700 dark:text-gray-200"
+  aria-label={isOpen ? 'Fechar menu' : 'Abrir menu'}
+  on:click={() => (isOpen ? closeSidebar() : openSidebar())}
+>
+  {#if isOpen}
+    <!-- Ícone X -->
+    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
+      <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
+    </svg>
+  {:else}
+    <!-- Ícone hambúrguer -->
+    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
+      <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5M3.75 17.25h16.5" />
+    </svg>
+  {/if}
+</button>
+
+<aside class="w-64 bg-white dark:bg-gray-900 border-r border-gray-200 dark:border-gray-700 fixed h-full overflow-auto transform transition-transform duration-200 ease-in-out z-40 {isOpen ? 'translate-x-0' : '-translate-x-full'} md:translate-x-0">
+  <div class="p-5 bg-gray-100 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 flex items-center">
+    <img src={logo} alt="TooEasy Commodities" class="w-24">
+    <h1 class="text-lg font-semibold text-gray-800 dark:text-gray-100 ml-2">TooEasy Commodities</h1>
+    <!-- Fechar removido: o botão fixo acima faz o toggle no mobile -->
   </div>
   <ul class="mt-4">
     {#each navItems as item}
       <li>
         <a
           href={item.href}
+          on:click={closeSidebar}
           class="flex items-center w-full px-4 py-2 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-gray-900 dark:hover:text-white font-medium border-l-4 {$page.url.pathname.startsWith(item.href) ? 'border-blue-500 bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white' : 'border-transparent'}"
         >
           <span class="mr-3 [&>svg]:w-5 [&>svg]:h-5 {$page.url.pathname.startsWith(item.href) ? 'text-blue-500' : 'text-gray-500 dark:text-gray-400'}">{@html item.icon}</span>
@@ -42,3 +91,7 @@
     {/each}
   </ul>
 </aside>
+
+{#if isOpen}
+  <div class="fixed inset-0 bg-black/40 md:hidden z-30" on:click={closeSidebar}></div>
+{/if}

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

@@ -28,7 +28,7 @@
 		</main>
 	  {:else}
 		<Sidebar />
-		<main class="flex-1 ml-64 bg-gray-50 dark:bg-gray-900">
+		<main class="flex-1 md:ml-64 bg-gray-50 dark:bg-gray-900">
 		  <DashboardGuard>
 			{@render children?.()}
 		  </DashboardGuard>

+ 2 - 2
src/routes/operations/+page.svelte → src/routes/trading/+page.svelte

@@ -1,10 +1,10 @@
 <script>
   import Header from '$lib/layout/Header.svelte';
   import EmptyState from '$lib/components/ui/EmptyState.svelte';
-  const breadcrumb = [{ label: 'Início' }, { label: 'Operação', active: true }];
+  const breadcrumb = [{ label: 'Início' }, { label: 'Trading', active: true }];
 </script>
 
 <div>
-  <Header title="Operação" subtitle="Operações do sistema" breadcrumb={breadcrumb} />
+  <Header title="Trading" subtitle="Trading do sistema" breadcrumb={breadcrumb} />
   <EmptyState title="Área em Desenvolvimento" description="Esta funcionalidade estará disponível em breve." />
 </div>