Files
XIP/frontend/src/components/ChatHeader.vue
Kerboul cfa2eadec9
Some checks failed
Deploy XIP / deploy (push) Failing after 37s
feat: conformite enonce - explorer, favoris, stats perso, tests, slots
Fonctionnel
- Backend messages : GET /api/messages/:id (detail) + recherche (q),
  pagination par curseur (before/limit) avec enveloppe { items, nextCursor,
  hasMore } ; le flux temps reel garde l'ancien format quand aucun parametre.
- Explorer (/explorer) : catalogue distant, recherche debouncee + annulable
  (AbortController), filtre, defilement infini, etat garde (keep-alive).
- Details par id : /message/:id et /shop/p/:id (consomment route.params).
- Favoris (/favoris) : liste perso persistee en localStorage, notation
  (note/rating/statut) via modale, refletee partout (bouton favori).
- Mes stats (/mes-stats) : agregats derives des favoris (note moyenne, top
  pays/auteurs, statuts), auto-mis a jour, route gardee si liste vide.
- Routeur : pages secondaires en lazy-load + repli, garde beforeEnter.

Technique
- Slots : PrefSection (slot defaut + slot nomme) enveloppe les 5 sections
  "Mes Persos" ; Modal (Teleport + slots).
- v-model custom : SearchBox (defineModel + debounce).
- Directive custom : v-click-outside.
- Tests Vitest : 25 tests (etat, fonctions, composants), ~86% du code metier.
- Retrait d'Ionic (inutilise). Script typecheck backend ; tsconfig @types/bun.
- Correctif type : garde stockLimit nullable dans l'achat (catalog.ts).
- README complet (URL, stack, run, tests, secrets, deploiement, mention IA).
2026-05-31 23:59:34 +02:00

134 lines
3.1 KiB
Vue

<!-- En-tête du chat -->
<template>
<header class="chat-header">
<div class="header-left">
<span class="xip-title">XIP</span>
<span class="chat-label">Chat</span>
<span class="online-dot" aria-hidden="true" />
<span class="online-count">{{ connectedCount }} connectés</span>
</div>
<div class="header-right">
<ThemePicker v-model="theme" />
<span v-if="ip" class="me-ip" :title="'Ton pseudo = ton IP'">{{ ip }}</span>
<span class="balance" :class="{ 'balance--free': freeMode }" title="Tes crédits XIP">
<span class="balance-coin"></span>
<span class="balance-val">{{ displayBalance() }}</span>
<span class="balance-unit">cr</span>
</span>
<router-link to="/shop" class="shop-link">🛒 Shop</router-link>
<span class="channel-badge"># général</span>
</div>
</header>
</template>
<script setup lang="ts">
import { useWallet } from '@/composables/useWallet';
import { useTheme } from '@/composables/useTheme';
import ThemePicker from './ThemePicker.vue';
defineProps<{ connectedCount: number }>();
const { ip, freeMode, displayBalance } = useWallet();
const { theme } = useTheme();
</script>
<style scoped>
.chat-header {
height: 52px;
flex-shrink: 0;
background: var(--xip-header-bg);
border-bottom: 1px solid var(--xip-header-border);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 16px 0 20px;
}
.header-left {
display: flex;
align-items: center;
gap: 8px;
}
.header-right {
display: flex;
align-items: center;
gap: 12px;
}
.xip-title {
font-family: Arial, sans-serif;
font-size: 18px;
font-weight: bold;
color: #7ab8cc;
}
.chat-label {
font-family: Arial, sans-serif;
font-size: 14px;
font-weight: bold;
color: #aaaacc;
}
.online-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #44aa66;
}
.online-count {
font-family: Arial, sans-serif;
font-size: 11px;
color: #557766;
}
.me-ip {
font-family: 'Courier New', monospace;
font-size: 11px;
color: #5566aa;
}
.balance {
display: inline-flex;
align-items: baseline;
gap: 4px;
background: #131322;
border: 1px solid #2a2a44;
border-radius: 12px;
padding: 3px 10px;
font-family: 'Courier New', monospace;
}
.balance-coin { color: #aa8833; font-size: 11px; }
.balance-val { color: #ccaa44; font-size: 13px; font-weight: bold; }
.balance-unit { color: #886633; font-size: 9px; }
.balance--free .balance-val { color: #44aa77; }
.balance--free .balance-coin { color: #44aa77; }
.shop-link {
font-family: Arial, sans-serif;
font-size: 12px;
font-weight: bold;
color: #6699aa;
text-decoration: none;
border: 1px solid #33445566;
border-radius: 12px;
padding: 4px 12px;
transition: background 0.15s;
}
.shop-link:hover {
background: #1a2530;
}
.channel-badge {
background: #131320;
border: 1px solid #222233;
border-radius: 12px;
padding: 4px 14px;
font-family: Arial, sans-serif;
font-size: 10px;
color: #5555aa;
}
</style>