piclets / src /lib /components /Battle /PicletInfo.svelte
Fraser's picture
rm legacy
1f2c086
<script lang="ts">
import type { PicletInstance } from '$lib/db/schema';
import { getXpProgress, getXpTowardsNextLevel } from '$lib/services/levelingService';
import { TYPE_DATA } from '$lib/types/picletTypes';
export let piclet: PicletInstance;
export let hpPercentage: number;
export let isPlayer: boolean;
$: xpTowardsNext = isPlayer ? getXpTowardsNextLevel(piclet.xp, piclet.level, piclet.tier) : { current: 0, needed: 0, percentage: 0 };
// Type-based styling
$: typeData = TYPE_DATA[piclet.primaryType];
$: typeColor = typeData.color;
$: typeLogoPath = `/classes/${piclet.primaryType}.png`;
$: hpColor = hpPercentage > 0.5 ? '#34c759' : hpPercentage > 0.25 ? '#ffcc00' : '#ff3b30';
</script>
<div class="piclet-info-wrapper {isPlayer ? 'player-info-wrapper' : 'enemy-info-wrapper'}">
<div class="piclet-info">
<!-- Type Logo (Foreground) -->
<div class="type-logo-container">
<img
src={typeLogoPath}
alt={piclet.primaryType}
class="type-logo"
/>
</div>
<!-- Content Area -->
<div class="content-area">
<!-- Name and Level Row -->
<div class="header-row">
<div class="piclet-name">{piclet.nickname}</div>
<div class="level-text">Lv.{piclet.level}</div>
</div>
<!-- HP Section -->
<div class="stat-row">
<div class="stat-label">HP</div>
<div class="hp-bar">
<div
class="hp-fill"
style="width: {hpPercentage * 100}%; background-color: {hpColor}"
></div>
</div>
</div>
<!-- XP Section (Player only) -->
{#if isPlayer}
<div class="stat-row">
<div class="stat-label">XP</div>
<div class="xp-bar">
<div
class="xp-fill"
style="width: {xpTowardsNext.percentage}%"
></div>
</div>
</div>
{/if}
</div>
</div>
<!-- Triangle Pointer -->
<div class="triangle-pointer {isPlayer ? 'player-pointer' : 'enemy-pointer'}"></div>
</div>
<style>
.piclet-info-wrapper {
position: absolute;
display: flex;
align-items: center;
}
.player-info-wrapper {
right: 16px;
bottom: 20px;
flex-direction: row-reverse;
}
.enemy-info-wrapper {
left: 16px;
top: 20px;
flex-direction: row;
}
.piclet-info {
background: rgba(255, 255, 255, 0.9);
border-radius: 8px;
padding: 10px;
min-width: 160px;
display: flex;
align-items: flex-start;
gap: 10px;
}
/* Type Logo Container */
.type-logo-container {
flex-shrink: 0;
margin-top: 2px;
}
.type-logo {
width: 35px;
height: 35px;
object-fit: contain;
border-radius: 6px;
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(4px);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
/* Content Area */
.content-area {
flex: 1;
min-width: 0; /* Allows flex item to shrink below content size */
}
/* Header Row */
.header-row {
display: flex;
align-items: baseline;
justify-content: space-between;
margin-bottom: 6px;
gap: 8px;
}
.piclet-name {
font-weight: 600;
font-size: 14px;
color: #1a1a1a;
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.level-text {
font-size: 11px;
font-weight: 600;
color: #666;
flex-shrink: 0;
}
/* Stat Rows */
.stat-row {
display: flex;
align-items: center;
gap: 6px;
margin-bottom: 3px;
}
.stat-row:last-child {
margin-bottom: 0;
}
.stat-label {
font-size: 9px;
font-weight: 600;
color: #666;
text-transform: uppercase;
letter-spacing: 0.3px;
width: 16px;
flex-shrink: 0;
}
/* HP Bar */
.hp-bar {
height: 6px;
background: #e0e0e0;
border-radius: 3px;
overflow: hidden;
flex: 1;
min-width: 80px;
}
.hp-fill {
height: 100%;
transition: width 0.5s ease, background-color 0.3s ease;
}
/* XP Bar */
.xp-bar {
height: 5px;
background: #e0e0e0;
border-radius: 2.5px;
overflow: hidden;
flex: 1;
min-width: 80px;
}
.xp-fill {
height: 100%;
background: #2196f3;
transition: width 1.2s ease-out;
}
/* Triangle Pointer */
.triangle-pointer {
width: 0;
height: 0;
border-style: solid;
}
.player-pointer {
border-width: 8px 16px 8px 0;
border-color: transparent rgba(255, 255, 255, 0.9) transparent transparent;
margin-right: -1px;
}
.enemy-pointer {
border-width: 8px 0 8px 16px;
border-color: transparent transparent transparent rgba(255, 255, 255, 0.9);
margin-left: -1px;
}
@media (max-width: 768px) {
.piclet-info {
min-width: 140px;
padding: 8px;
gap: 8px;
}
.type-logo {
width: 28px;
height: 28px;
}
.piclet-name {
font-size: 12px;
}
.level-text {
font-size: 10px;
}
.hp-bar, .xp-bar {
min-width: 60px;
}
}
</style>