diff --git a/src/routes/user/+layout.svelte b/src/routes/user/+layout.svelte new file mode 100644 index 0000000000000000000000000000000000000000..5859839863e719036a240f46d0b1d857b57dd193 --- /dev/null +++ b/src/routes/user/+layout.svelte @@ -0,0 +1,25 @@ +<script> +</script> + +<main> + <slot /> +</main> + +<style> + :global(html,body) { + margin: 0; + padding: 0; + } + + main { + display: flex; + background-color: transparent; + color: white; + background-image: url('/background.png'); + background-size: cover; + background-position: center; + background-attachment: fixed; + background-repeat: no-repeat; + font-family: 'Rajdhani', 'Courier New', sans-serif; + } +</style> diff --git a/src/routes/user/+page.svelte b/src/routes/user/+page.svelte index d2a9f3458cc6079696eec96394c157ecd2ae7cb8..d95da43555ca917d80fb4d8b46b04245312ab63d 100644 --- a/src/routes/user/+page.svelte +++ b/src/routes/user/+page.svelte @@ -11,22 +11,17 @@ let currentUser: { name: string; email: string; money: number; cyberpsychosis: number; cyberLimit: number } | null = null; let allPurchases: UserPurchase[] = []; - let displayedPurchases: UserPurchase[] = []; let loading = true; let error = ''; let activeCategory = 'all'; - let categories: string[] = []; - let currentUserId = -1; - - let page = 1; - const perPage = 10; + let currentUserId = -1 function getToken(): string | null { return localStorage.getItem('token'); } + // Carrega dados ao montar o componente onMount(async () => { - window.addEventListener('scroll', handleScroll); try { const token = getToken(); if (!token) throw new Error('Usuário não autenticado'); @@ -65,73 +60,43 @@ implant: implants.find(i => i.id === t.implant_id)! })); - // categorias para filtro - categories = [...new Set(allPurchases.map(p => p.implant.bodyPart))]; - - // página inicial - displayedPurchases = allPurchases.slice(0, perPage); } catch (err) { - error = err instanceof Error ? err.message : String(err); + error = err instanceof Error ? err.message : String(err); } finally { - loading = false; + loading = false; } - - return () => window.removeEventListener('scroll', handleScroll); }); - // Carrega próxima “página” de items - function loadMore() { - const start = page * perPage; - const next = allPurchases.slice(start, start + perPage); - if (next.length > 0) { - displayedPurchases = [...displayedPurchases, ...next]; - page += 1; - } - } - - // Detecta fim da página e dispara loadMore - function handleScroll() { - if (window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - 100) { - loadMore(); - } - } - - // Filtra apenas o que vai ser mostrado - function getFiltered() { - return activeCategory === 'all' - ? displayedPurchases - : displayedPurchases.filter(p => p.implant.bodyPart === activeCategory); - } + // Categorias únicas (reativo) + $: categories = [...new Set(allPurchases.map(p => p.implant.bodyPart))]; + + // Lista filtrada (reativo) + $: filteredImplants = activeCategory === 'all' + ? allPurchases + : allPurchases.filter(p => p.implant.bodyPart === activeCategory); </script> <style> - - :global(body) { - margin: 0; - padding: 0; - color: #00f7ff; - font-family: 'Rajdhani', 'Courier New', sans-serif; - } - .error { color: #ff3e3e; text-align: center; } - /* Layout da janela principal */ .window { - display: flex; + display: flex; + width: 100vw; min-height: 100vh; - width: 100%; - } + } /* Estilização do menu lateral */ .navegation { - width: 17%; background: linear-gradient(145deg, #1a1a2e 0%, #16213e 100%); border-right: 1px solid #00f7ff; box-shadow: 2px 0 10px rgba(0, 247, 255, 0.2); + font-family: 'Rajdhani', 'Courier New', sans-serif; + width: 250px; padding: 20px 0; + display: block; } .nav-header h2 { @@ -140,12 +105,12 @@ text-shadow: 0 0 10px #ff073a; border-bottom: 1px solid #00f7ff; padding-bottom: 15px; - margin: 0 15px 20px; + margin: 20px 15px 20px; } .nav-section { - margin: 20px 15px; - } + margin: 20px 15px; + } /* Botão Store */ .nav-button { @@ -178,39 +143,37 @@ cursor: pointer; text-align: left; font-family: 'Rajdhani', 'Courier New', sans-serif; + font-weight: 800; } .filter-btn:hover { - background-color: #9a9f17; + background-color: #fee801; } .filter-btn.active { - background-color: #9a9f17; + background-color:#fee801; border-left: 3px solid #ff073a; } .card-container { - display: flex; - justify-content: center; - flex-direction: row; - flex-wrap: wrap; - gap: 10px; - padding: 1rem; - margin: 0.5rem; - } - - .main-content { - flex: 1; - padding: 20px; - overflow-y: auto; /* Mantém o scroll funcionando */ - background-image: url('/background.png'); + flex: 1; + padding: 2rem; + overflow-y: auto; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); + margin: auto; + gap: 0.5rem; } p { margin-left: 10px; } -</style> + span { + color: #00d0ff; + font-family: 'Rajdhani', 'Courier New', sans-serif; + } +</style> <div class="window"> <div class="navegation"> @@ -224,41 +187,41 @@ <a href="/store" class="nav-button"><strong>STORE</strong></a> </div> - <p> - {#if currentUser} - Nome: {currentUser.name}<br> - Email: {currentUser.email}<br> - Money: {currentUser.money}<br> - Cyber Limit: {currentUser.cyberLimit}<br> - Cyberpsychosis: {currentUser.cyberpsychosis}<br> - {:else if loading} - Carregando informações do usuário... - {:else if error} - Erro ao carregar informações do usuário. - {/if} - </p> + <p> + {#if currentUser} + <span>Nome:</span> {currentUser.name}<br> + <span>Email:</span> {currentUser.email}<br> + <span>Money:</span> {currentUser.money}<br> + <span>CyberLimit:</span> {currentUser.cyberLimit}<br> + <span>Cyberpsychosis:</span> {currentUser.cyberpsychosis}<br> + {:else if loading} + Carregando informações do usuário... + {:else if error} + Erro ao carregar informações do usuário. + {/if} + </p> - <!-- Filtros de categorias --> - <div class="nav-section"> - <button - class="filter-btn" - class:active={activeCategory === 'all'} - on:click={() => activeCategory = 'all'}> - Todos - </button> - {#each categories as cat} + <!-- Filtros de categorias --> + <div class="nav-section"> <button class="filter-btn" - class:active={activeCategory === cat} - on:click={() => activeCategory = cat}> - {cat} + class:active={activeCategory === 'all'} + on:click={() => activeCategory = 'all'}> + Todos </button> - {/each} - </div> + {#each categories as cat} + <button + class="filter-btn" + class:active={activeCategory === cat} + on:click={() => activeCategory = cat}> + {cat} + </button> + {/each} + </div> </div> <!-- Cards dos Implantes --> - <div class="main-content"> + <div class="card-container"> {#if loading} <p>Carregando...</p> {:else if error} @@ -266,19 +229,17 @@ {:else if allPurchases.length === 0} <p>Você ainda não possui implantes comprados.</p> {:else} - <div class="card-container"> - {#each getFiltered() as p (p.implant_id)} - <Card - title={p.implant.name} - bodyPart={p.implant.bodyPart} - price={Number(p.implant.price)} - cyberCost={Number(p.implant.cyberCost)} - showButton={false} - id={p.implant_id} - boughtIds={[]} - /> - {/each} - </div> + {#each filteredImplants as p (p.implant_id)} + <Card + title={p.implant.name} + bodyPart={p.implant.bodyPart} + price={Number(p.implant.price)} + cyberCost={Number(p.implant.cyberCost)} + showButton={false} + id={p.implant_id} + boughtIds={[]} + /> + {/each} {/if} </div> </div> \ No newline at end of file