Download src/lib/components/Scanner/ScanResult.svelte from Fraser/piclets: direct link, hf CLI and curl.
- Browser
- Download file 5.8 kB
-
https://huggingface.co/spaces/Fraser/piclets/resolve/main/src/lib/components/Scanner/ScanResult.svelte
- Command line
-
hf download hf://spaces/Fraser/piclets/src/lib/components/Scanner/ScanResult.svelte
-
curl -L -o ScanResult.svelte https://huggingface.co/spaces/Fraser/piclets/resolve/main/src/lib/components/Scanner/ScanResult.svelte
5.8 kB
| <script lang="ts"> | |
| import type { ScanResult } from '$lib/types'; | |
| import { TYPE_DATA, PicletType } from '$lib/types/picletTypes'; | |
| import { rarityToTier } from '$lib/utils/rarity'; | |
| interface Props { | |
| result: ScanResult; | |
| onReset: () => void; | |
| } | |
| let { result, onReset }: Props = $props(); | |
| const monster = $derived(result.monster); | |
| const tier = $derived(monster ? rarityToTier(monster.rarity) : 'low'); | |
| const typeColor = $derived( | |
| monster ? TYPE_DATA[monster.type as PicletType]?.color ?? '#6c757d' : '#6c757d', | |
| ); | |
| const typeLogoPath = $derived(monster ? `/classes/${monster.type}.png` : ''); | |
| </script> | |
| {#if result.success && monster} | |
| <div class="result-container"> | |
| <div class="success-header"> | |
| <h2> | |
| {#if result.status === 'new'} | |
| You Discovered {monster.name}! | |
| {:else} | |
| {monster.name} was already discovered by {monster.discoverer.username} | |
| {/if} | |
| </h2> | |
| </div> | |
| <div class="piclet-preview" style="--type-color: {typeColor}"> | |
| <div class="image-wrapper"> | |
| <div | |
| class="logo-watermark" | |
| style="background-image: url('{typeLogoPath}')" | |
| ></div> | |
| <img src={monster.image_url} alt={monster.name} class="piclet-image" /> | |
| </div> | |
| <div class="info"> | |
| <h3>{monster.name}</h3> | |
| <div class="badges"> | |
| <span class="type-badge" style="background-color: {typeColor}"> | |
| {monster.type} | |
| </span> | |
| <span class="rarity-badge tier-{tier}"> | |
| {tier} · {monster.rarity} | |
| </span> | |
| </div> | |
| <p class="description">{monster.description}</p> | |
| <div class="stats"> | |
| <span>📏 {monster.height_m} m</span> | |
| <span>⚖️ {monster.weight_kg} kg</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="action-buttons"> | |
| <button class="action-button primary" onclick={onReset}> | |
| Scan Another | |
| </button> | |
| </div> | |
| </div> | |
| {:else} | |
| <div class="result-container"> | |
| <div class="error-header"> | |
| <div class="error-icon">⚠️</div> | |
| <h2>Scan Failed</h2> | |
| <p class="error-message">{result.error ?? 'Something went wrong.'}</p> | |
| </div> | |
| <div class="action-buttons"> | |
| <button class="action-button primary" onclick={onReset}> | |
| Try Again | |
| </button> | |
| </div> | |
| </div> | |
| {/if} | |
| <style> | |
| .result-container { | |
| max-width: 500px; | |
| margin: 0 auto; | |
| padding: 2rem; | |
| text-align: center; | |
| } | |
| .success-header, | |
| .error-header { | |
| margin-bottom: 2rem; | |
| } | |
| .success-icon, | |
| .error-icon { | |
| font-size: 3rem; | |
| margin-bottom: 1rem; | |
| } | |
| .success-header h2, | |
| .error-header h2 { | |
| color: #333; | |
| margin: 0 0 1rem; | |
| font-size: 1.8rem; | |
| font-weight: 600; | |
| } | |
| .success-message, | |
| .error-message { | |
| color: #666; | |
| font-size: 1.1rem; | |
| margin: 0; | |
| } | |
| .success-message strong { | |
| color: #333; | |
| font-weight: 600; | |
| } | |
| .piclet-preview { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 1rem; | |
| margin: 2rem 0; | |
| border: 2px solid var(--type-color, #007bff); | |
| border-radius: 16px; | |
| overflow: hidden; | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); | |
| } | |
| .image-wrapper { | |
| position: relative; | |
| width: 100%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| background: linear-gradient( | |
| 135deg, | |
| color-mix(in srgb, var(--type-color) 12%, white) 0%, | |
| rgba(255, 255, 255, 0.9) 100% | |
| ); | |
| } | |
| .logo-watermark { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| width: 80%; | |
| height: 80%; | |
| background-size: contain; | |
| background-repeat: no-repeat; | |
| background-position: center; | |
| opacity: 0.08; | |
| pointer-events: none; | |
| } | |
| .piclet-image { | |
| width: 240px; | |
| height: 240px; | |
| object-fit: contain; | |
| position: relative; | |
| z-index: 1; | |
| filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.15)); | |
| } | |
| .info { | |
| width: 100%; | |
| padding: 1rem 1.5rem 1.5rem; | |
| text-align: left; | |
| } | |
| .info h3 { | |
| margin: 0 0 0.5rem; | |
| font-size: 1.4rem; | |
| font-weight: 700; | |
| color: #1a1a1a; | |
| text-align: center; | |
| } | |
| .badges { | |
| display: flex; | |
| justify-content: center; | |
| gap: 0.5rem; | |
| margin-bottom: 0.75rem; | |
| } | |
| .type-badge { | |
| padding: 4px 12px; | |
| border-radius: 12px; | |
| font-size: 0.75rem; | |
| font-weight: 600; | |
| text-transform: uppercase; | |
| color: white; | |
| } | |
| .rarity-badge { | |
| padding: 4px 12px; | |
| border-radius: 12px; | |
| font-size: 0.75rem; | |
| font-weight: 600; | |
| text-transform: uppercase; | |
| color: white; | |
| } | |
| .rarity-badge.tier-low { background: #6c757d; } | |
| .rarity-badge.tier-medium { background: #28a745; } | |
| .rarity-badge.tier-high { background: #fd7e14; } | |
| .rarity-badge.tier-legendary { background: #dc3545; } | |
| .description { | |
| font-size: 0.95rem; | |
| color: #555; | |
| line-height: 1.5; | |
| margin: 0 0 0.75rem; | |
| } | |
| .stats { | |
| display: flex; | |
| justify-content: center; | |
| gap: 1.5rem; | |
| font-size: 0.875rem; | |
| color: #888; | |
| } | |
| .action-buttons { | |
| display: flex; | |
| justify-content: center; | |
| margin-top: 2rem; | |
| } | |
| .action-button { | |
| padding: 0.875rem 2rem; | |
| border: none; | |
| border-radius: 12px; | |
| font-weight: 600; | |
| font-size: 1rem; | |
| cursor: pointer; | |
| transition: all 0.2s ease; | |
| min-width: 160px; | |
| } | |
| .action-button.primary { | |
| background: linear-gradient(135deg, #3b82f6, #1d4ed8); | |
| color: white; | |
| box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4); | |
| } | |
| .action-button.primary:hover { | |
| background: linear-gradient(135deg, #2563eb, #1e40af); | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 16px rgba(59, 130, 246, 0.4); | |
| } | |
| .action-button.primary:active { | |
| transform: translateY(0); | |
| } | |
| </style> | |