pet_data/app/components/pixel/PlayerPanel.vue

112 lines
4.9 KiB
Vue

<template>
<div class="h-full flex flex-col p-4 gap-4 bg-[#1b1026] overflow-y-auto custom-scrollbar">
<!-- Pet Avatar -->Portrait & Basic Info -->
<PixelFrame class="flex-shrink-0" title="PET INFO">
<!-- Helper Buttons Overlay -->
<div class="absolute top-1 right-1 z-30">
<button
@click="$emit('openAchievements')"
class="p-1 bg-[#2b193f] border border-[#f6b26b] hover:bg-[#3d2459] active:translate-y-0.5 group"
title="Achievements"
>
<Trophy :size="14" class="text-[#f6b26b] group-hover:text-white" />
</button>
</div>
<div class="flex flex-col items-center p-1 relative">
<div class="w-20 h-20 bg-[#1b1026] border-4 border-[#4a3b5e] mb-2 relative overflow-hidden group shadow-inner flex items-center justify-center">
<!-- Background for portrait -->
<div class="absolute inset-0 bg-[#2b193f] opacity-50" />
<!-- The Animated Pixel Avatar -->
<div class="scale-110 transform translate-y-1">
<PixelAvatar
skinColor="#ffdbac"
hairColor="#e0d8f0"
outfitColor="#9fd75b"
/>
</div>
<!-- Scanline on portrait -->
<div class="absolute inset-0 bg-[linear-gradient(rgba(0,0,0,0)_50%,rgba(0,0,0,0.2)_50%)] bg-[length:100%_4px] pointer-events-none z-20" />
</div>
<h2 class="text-xl text-[#f6b26b] tracking-[0.2em] font-bold border-b-2 border-[#f6b26b] mb-1 leading-none pb-1">{{ stats.name }}</h2>
<span class="text-xs text-[#8f80a0] uppercase tracking-wide">{{ stats.class }}</span>
</div>
</PixelFrame>
<!-- Vitals - Updated to Health, Hunger, Happiness -->
<div class="flex flex-col gap-1 px-1">
<RetroResourceBar :current="stats.hp" :max="stats.maxHp" type="hp" label="Health" :icon="Heart" />
<RetroResourceBar v-if="stats.hunger !== undefined" :current="stats.hunger" :max="stats.maxHunger || 100" type="energy" label="Hunger" :icon="Drumstick" />
<RetroResourceBar v-if="stats.happiness !== undefined" :current="stats.happiness" :max="stats.maxHappiness || 100" type="mana" label="Happy" :icon="Smile" />
</div>
<!-- Pet Details Grid -->
<PixelFrame class="flex-shrink-0 mt-1" variant="inset">
<div class="grid grid-cols-2 gap-x-2 gap-y-2 text-[10px] uppercase text-[#8f80a0]">
<div class="flex flex-col border-r border-[#4a3b5e] pr-1">
<span class="text-[#4a3b5e]">Age</span>
<span class="text-[#e0d8f0] font-mono tracking-wide">{{ stats.age }}</span>
</div>
<div class="flex flex-col pl-1">
<span class="text-[#4a3b5e]">Gen</span>
<span class="text-[#e0d8f0] font-mono tracking-wide">{{ stats.generation }}</span>
</div>
<div class="flex items-center gap-1 border-t border-[#4a3b5e] pt-1 col-span-2">
<Ruler :size="10" />
<span class="text-[#e0d8f0]">{{ stats.height }}</span>
<span class="text-[#4a3b5e] mx-1">|</span>
<Scale :size="10" />
<span class="text-[#e0d8f0]">{{ stats.weight }}</span>
</div>
</div>
</PixelFrame>
<!-- Fate & God Favor -->
<div class="flex flex-col gap-2 mt-2 px-1">
<!-- Fate -->
<div v-if="stats.fate" class="flex items-center gap-2 bg-[#2b193f] p-1 border border-[#4a3b5e] rounded">
<Leaf :size="12" color="#99e550" />
<div class="flex flex-col leading-none">
<span class="text-[8px] text-[#8f80a0] uppercase">Fate</span>
<span class="text-[10px] text-[#e0d8f0] tracking-wide">{{ stats.fate }}</span>
</div>
</div>
<!-- God Favor -->
<div v-if="stats.godFavor" class="flex flex-col gap-1">
<div class="flex justify-between text-[10px] text-[#8f80a0] uppercase">
<span>Favor: {{ stats.godFavor.name }}</span>
<span>{{ stats.godFavor.current }}/{{ stats.godFavor.max }}</span>
</div>
<div class="h-2 bg-[#150c1f] border border-[#4a3b5e] rounded-full overflow-hidden">
<div :style="{ width: `${(stats.godFavor.current / stats.godFavor.max) * 100}%` }" class="h-full bg-[#f6b26b]" />
</div>
</div>
</div>
<!-- Gold -->
<div class="mt-auto px-1 pb-1">
<RetroCounter :icon="Coins" :value="stats.gold || 0" color="#ffe762" />
</div>
</div>
</template>
<script setup lang="ts">
import { Ruler, Scale, Heart, Smile, Drumstick, Coins, Leaf, Trophy } from 'lucide-vue-next';
import PixelFrame from './PixelFrame.vue';
import RetroResourceBar from './RetroResourceBar.vue';
import RetroCounter from './RetroCounter.vue';
import PixelAvatar from './PixelAvatar.vue';
import type { EntityStats } from '~/types/pixel';
interface Props {
stats: EntityStats;
}
defineProps<Props>();
defineEmits(['openAchievements']);
</script>