Some checks failed
Deploy XIP / deploy (push) Failing after 37s
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).
134 lines
3.1 KiB
Vue
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>
|