webapp
Build / build (push) Has been cancelled

This commit is contained in:
gpatruno
2026-06-06 21:59:51 +02:00
parent 02d2af0993
commit 48a1b900c7
279 changed files with 7488 additions and 238 deletions
+10
View File
@@ -0,0 +1,10 @@
<%- include('partials/page-start') %>
<section class="panel coming-soon-page">
<div class="coming-soon-icon">⏳</div>
<h1><%= heading %></h1>
<p><%= description %></p>
<a class="btn" href="/">Retour au dashboard</a>
</section>
<%- include('partials/page-end') %>
+9
View File
@@ -0,0 +1,9 @@
<%- include('partials/page-start') %>
<section class="panel error-page">
<h1><%= title %></h1>
<p><%= message %></p>
<a class="btn" href="/">Retour au dashboard</a>
</section>
<%- include('partials/page-end') %>
+106
View File
@@ -0,0 +1,106 @@
<%- include('partials/page-start') %>
<%- include('partials/page-header', { title, subtitle: 'Vue d\'ensemble du serveur en temps réel' }) %>
<section class="stats-grid">
<article class="stat-card">
<span class="stat-label">Joueurs en ligne</span>
<strong class="stat-value accent"><%= fmt.formatNumber(stats.onlinePlayers) %></strong>
</article>
<article class="stat-card">
<span class="stat-label">Joueurs inscrits</span>
<strong class="stat-value"><%= fmt.formatNumber(stats.totalPlayers) %></strong>
</article>
<article class="stat-card">
<span class="stat-label">Niveau moyen</span>
<strong class="stat-value"><%= stats.averageLevel %></strong>
</article>
<article class="stat-card">
<span class="stat-label">Money en circulation</span>
<strong class="stat-value"><%= fmt.formatMoney(stats.totalMoney) %></strong>
</article>
<article class="stat-card">
<span class="stat-label">Groupes actifs</span>
<strong class="stat-value"><%= fmt.formatNumber(stats.totalGroups) %></strong>
</article>
</section>
<section class="panel">
<div class="panel-header">
<h2>Joueurs connectés</h2>
<span class="badge"><%= onlinePlayers.length %></span>
</div>
<% if (onlinePlayers.length === 0) { %>
<p class="empty">Aucun joueur connecté pour le moment.</p>
<% } else { %>
<table class="table">
<thead>
<tr>
<th>Joueur</th>
<th>Niveau</th>
<th>Classe</th>
<th>Race</th>
<th>Money</th>
<th></th>
</tr>
</thead>
<tbody>
<% onlinePlayers.forEach(function(p) { %>
<tr>
<td>
<span class="player-name">
<span class="status-dot online inline"></span>
<%= p.display_name %>
</span>
</td>
<td><%= p.level %></td>
<td><%= p.classLabel %></td>
<td><%= p.raceLabel %></td>
<td><%= fmt.formatMoney(p.money) %></td>
<td><a class="link" href="/players/<%= p.uuid %>">Profil</a></td>
</tr>
<% }); %>
</tbody>
</table>
<% } %>
</section>
<section class="panel">
<div class="panel-header">
<h2>Dernières connexions</h2>
</div>
<% if (recentPlayers.length === 0) { %>
<p class="empty">Aucun joueur enregistré.</p>
<% } else { %>
<table class="table">
<thead>
<tr>
<th>Joueur</th>
<th>Niveau</th>
<th>Statut</th>
<th>Dernière connexion</th>
<th></th>
</tr>
</thead>
<tbody>
<% recentPlayers.forEach(function(p) { %>
<tr>
<td><%= p.display_name %></td>
<td><%= p.level %></td>
<td>
<% if (p.isOnline) { %>
<span class="tag tag-online">En ligne</span>
<% } else { %>
<span class="tag tag-offline">Hors ligne</span>
<% } %>
</td>
<td><%= fmt.formatTimestamp(p.last_date_connected) %></td>
<td><a class="link" href="/players/<%= p.uuid %>">Profil</a></td>
</tr>
<% }); %>
</tbody>
</table>
<% } %>
</section>
<%- include('partials/page-end') %>
+4
View File
@@ -0,0 +1,4 @@
</main>
</div>
</body>
</html>
+8
View File
@@ -0,0 +1,8 @@
<header class="page-header">
<div>
<h1><%= title %></h1>
<% if (typeof subtitle !== 'undefined' && subtitle) { %>
<p class="subtitle"><%= subtitle %></p>
<% } %>
</div>
</header>
+42
View File
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= title %> · Orion.ovh</title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<div class="layout">
<aside class="sidebar">
<div class="brand">
<span class="brand-mark">O</span>
<div>
<strong>Orion.ovh</strong>
<small>Serveur MMORPG</small>
</div>
</div>
<nav class="nav">
<% nav.forEach(function(item) { %>
<a href="<%= item.href %>" class="nav-link<%= page === item.key ? ' active' : '' %>">
<%= item.label %>
</a>
<% }); %>
</nav>
<div class="sidebar-footer">
<% if (sessionUser) { %>
<span class="status-dot online"></span>
<span><%= sessionUser.displayName %></span>
<% } else if (dbStatus.exists) { %>
<span class="status-dot online"></span> Base connectée
<% } else { %>
<span class="status-dot offline"></span> Base indisponible
<% } %>
</div>
</aside>
<main class="main">
<% if (!dbStatus.exists) { %>
<div class="alert alert-warning">
Fichier <code>mmorpg.db</code> introuvable. Démarrez le serveur Hytale pour initialiser la base à la racine du monorepo.
</div>
<% } %>
+80
View File
@@ -0,0 +1,80 @@
<div class="profile-layout">
<section class="panel profile-card">
<div class="profile-head">
<div class="avatar"><%= player.display_name.charAt(0).toUpperCase() %></div>
<div>
<h2><%= player.display_name %></h2>
<p class="muted"><%= player.uuid %></p>
<% if (player.isOnline) { %>
<span class="tag tag-online">En ligne</span>
<% } else { %>
<span class="tag tag-offline">Hors ligne</span>
<% } %>
</div>
</div>
<dl class="detail-grid">
<div>
<dt>Niveau</dt>
<dd><%= player.level %></dd>
</div>
<div>
<dt>Expérience</dt>
<dd><%= fmt.formatNumber(player.experience) %></dd>
</div>
<div>
<dt>Classe</dt>
<dd><%= player.classLabel %></dd>
</div>
<div>
<dt>Race</dt>
<dd><%= player.raceLabel %></dd>
</div>
<div>
<dt>Money</dt>
<dd><%= fmt.formatMoney(player.money) %></dd>
</div>
<div>
<dt>Temps de jeu</dt>
<dd><%= fmt.formatDuration(player.total_time_play) %></dd>
</div>
<div>
<dt>Création du compte</dt>
<dd><%= fmt.formatTimestamp(player.date_creation || player.created_at) %></dd>
</div>
<div>
<dt>Dernière connexion</dt>
<dd><%= fmt.formatTimestamp(player.last_date_connected) %></dd>
</div>
</dl>
<% if (player.jobs.length > 0) { %>
<div class="chip-list">
<span class="chip-label">Métiers</span>
<% player.jobs.forEach(function(job) { %>
<span class="chip"><%= job %></span>
<% }); %>
</div>
<% } %>
<% if (player.powers.length > 0) { %>
<div class="chip-list">
<span class="chip-label">Pouvoirs</span>
<% player.powers.forEach(function(power) { %>
<span class="chip"><%= power %></span>
<% }); %>
</div>
<% } %>
<% if (group) { %>
<p class="group-info">Membre du groupe <code><%= group.id %></code></p>
<% } %>
</section>
<% if (typeof comingSoon !== 'undefined' && comingSoon) { %>
<section class="panel coming-soon">
<h2>Fonctionnalités à venir</h2>
<p>Inventaire, compétences détaillées, historique de combat et statistiques avancées seront disponibles prochainement sur cette page.</p>
</section>
<% } %>
</div>
+49
View File
@@ -0,0 +1,49 @@
<%- include('../partials/page-start') %>
<%- include('../partials/page-header', { title, subtitle: players.length + ' joueur(s) enregistré(s)' }) %>
<section class="panel">
<% if (players.length === 0) { %>
<p class="empty">Aucun joueur trouvé dans la base de données.</p>
<% } else { %>
<table class="table table-clickable">
<thead>
<tr>
<th>Joueur</th>
<th>Niveau</th>
<th>XP</th>
<th>Classe</th>
<th>Race</th>
<th>Money</th>
<th>Statut</th>
<th>Temps de jeu</th>
</tr>
</thead>
<tbody>
<% players.forEach(function(p) { %>
<tr class="row-link" onclick="window.location='/players/<%= p.uuid %>'">
<td>
<span class="player-name"><%= p.display_name %></span>
<small class="muted"><%= p.uuid %></small>
</td>
<td><%= p.level %></td>
<td><%= fmt.formatNumber(p.experience) %></td>
<td><%= p.classLabel %></td>
<td><%= p.raceLabel %></td>
<td><%= fmt.formatMoney(p.money) %></td>
<td>
<% if (p.isOnline) { %>
<span class="tag tag-online">En ligne</span>
<% } else { %>
<span class="tag tag-offline">Hors ligne</span>
<% } %>
</td>
<td><%= fmt.formatDuration(p.total_time_play) %></td>
</tr>
<% }); %>
</tbody>
</table>
<% } %>
</section>
<%- include('../partials/page-end') %>
+9
View File
@@ -0,0 +1,9 @@
<%- include('../partials/page-start') %>
<%- include('../partials/page-header', { title: player.display_name, subtitle: 'Profil joueur' }) %>
<%- include('../partials/player-card', { player, group, comingSoon }) %>
<p class="back-link"><a class="link" href="/players">← Retour à la liste</a></p>
<%- include('../partials/page-end') %>
+19
View File
@@ -0,0 +1,19 @@
<%- include('../partials/page-start') %>
<%- include('../partials/page-header', { title: 'Mon profil', subtitle: 'Connecté en tant que ' + player.display_name }) %>
<div class="profile-actions">
<form method="post" action="/profile/logout">
<button type="submit" class="btn btn-secondary">Se déconnecter</button>
</form>
<a class="link" href="/players/<%= player.uuid %>">Voir le profil public</a>
</div>
<%- include('../partials/player-card', { player, group, comingSoon: false }) %>
<section class="panel coming-soon">
<h2>À venir</h2>
<p>Inventaire, historique de combat et gestion avancée du compte seront ajoutés prochainement.</p>
</section>
<%- include('../partials/page-end') %>
+38
View File
@@ -0,0 +1,38 @@
<%- include('../partials/page-start') %>
<%- include('../partials/page-header', { title: 'Mon profil', subtitle: 'Connexion à Orion.ovh' }) %>
<section class="panel auth-panel">
<% if (needsMigration) { %>
<div class="alert alert-warning">
La colonne <code>password_hash</code> est absente. Redémarrez le serveur Hytale pour appliquer la migration.
</div>
<% } %>
<% if (error) { %>
<div class="alert alert-error"><%= error %></div>
<% } %>
<form class="auth-form" method="post" action="/profile/login">
<label>
Pseudo
<input type="text" name="pseudo" value="<%= pseudo %>" autocomplete="username" required autofocus>
</label>
<label>
Mot de passe
<input type="password" name="password" autocomplete="current-password" required>
</label>
<button type="submit" class="btn btn-block">Se connecter</button>
</form>
<div class="auth-help">
<h2>Première connexion ?</h2>
<p>
Rejoignez le serveur Hytale, puis définissez votre mot de passe web en jeu :
</p>
<pre><code>/mmorpg password MonMotDePasse</code></pre>
<p class="muted">Minimum <%= auth.MIN_PASSWORD_LENGTH %> caractères. Vous pourrez le modifier à tout moment avec la même commande.</p>
</div>
</section>
<%- include('../partials/page-end') %>