Compare commits
2 Commits
v0.1.0-alp
...
main
| Author | SHA1 | Date |
|---|---|---|
|
|
fefe280b9f | |
|
|
250a1f1617 |
|
|
@ -0,0 +1,49 @@
|
|||
# ====================================================================
|
||||
# RYM Horizon - Git Ignore Rules
|
||||
# ====================================================================
|
||||
|
||||
# --- Système d'Exploitation (Hôtes & Laboratoires) ---
|
||||
# Fedora / Linux généraux
|
||||
.directory
|
||||
.Trash-*
|
||||
*~
|
||||
|
||||
# Fichiers systèmes Windows / macOS au cas où un collaborateur en utilise
|
||||
Thumbs.db
|
||||
Desktop.ini
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# --- Éditeurs de Code & IDE ---
|
||||
# VS Codium / VS Code
|
||||
.vscode/
|
||||
*.code-workspace
|
||||
.history/
|
||||
|
||||
# --- Infrastructure locale (Podman / Docker) ---
|
||||
.docker/
|
||||
.podman/
|
||||
*.tar
|
||||
*.tar.gz
|
||||
# Ne pas ignorer les fichiers de conf Nginx si nécessaire,
|
||||
# mais ignorer les logs locaux si générés dans le projet
|
||||
*.log
|
||||
|
||||
# --- Fichiers d'environnement & Sécurité ---
|
||||
# Contient les clés d'API, secrets RYM Bank, accès serveurs
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
*.pem
|
||||
*.key
|
||||
*.secret
|
||||
|
||||
# --- Dépendances futures ---
|
||||
# Pour anticiper l'arrivée de Node.js, npm, ou de préprocesseurs CSS
|
||||
node_modules/
|
||||
.npm/
|
||||
dist/
|
||||
build/
|
||||
.sass-cache/
|
||||
.cache/
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"rules": {
|
||||
"block-no-empty": true,
|
||||
"color-no-invalid-hex": true,
|
||||
"comment-no-empty": true,
|
||||
"declaration-block-no-duplicate-properties": true,
|
||||
"declaration-block-no-shorthand-property-overrides": true
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
RYM Horizon — Spécifications Architecturales
|
||||
|
||||
Version : 3.0.0 (Souveraine & Épurée)
|
||||
|
||||
Date : Samedi 23 Mai 2026
|
||||
|
||||
Statut : Validé en Laboratoire Local
|
||||
1. Philosophie & Alignement Géopolitique
|
||||
|
||||
RYM Horizon est le cockpit d'organisation temporelle et de gestion des actifs de la performance pour l'athlète d'endurance. Conformément à la charte "Tout sauf US", l'intégralité de l'environnement de développement et de déploiement est étanche aux lois extra-territoriales américaines (Cloud Act, EAR).
|
||||
|
||||
Hébergement cible : Serveurs souverains européens (Debian VPS).
|
||||
|
||||
Laboratoire local : Conteneurisé sous OS Européen (Allemagne/Suède).
|
||||
|
||||
Flux Financiers : Intégration native exclusive des rails européens (Wero / Euro Numérique).
|
||||
|
||||
2. Infrastructure du Laboratoire Local (Podman & openSUSE)
|
||||
|
||||
Pour valider le fonctionnement de l'application sans dépendance externe, le projet est exécuté dans un bac à sable isolé.
|
||||
Composants techniques :
|
||||
|
||||
Orchestrateur : Podman (Rootless, natif Fedora, sans démon privilégié).
|
||||
|
||||
Système d'Exploitation : openSUSE Leap 15.6 (Distribution allemande/suédoise, ultra-stable).
|
||||
|
||||
Serveur Web : Nginx (Configuration optimisée).
|
||||
|
||||
Architecture Réseau & Ports :
|
||||
|
||||
Pour des raisons de sécurité (mode Rootless de Podman), le conteneur n'a pas les droits pour ouvrir le port standard 80. La configuration a été basculée sur le port 8080. Un tunnel de port lie la machine hôte au conteneur.
|
||||
|
||||
Accès local de développement : http://localhost:8080
|
||||
|
||||
3. Spécifications Fonctionnelles de l'Interface (v3.0.0)
|
||||
|
||||
L'interface abandonne le look "calendrier de bureau" au profit d'un cockpit de vie multi-échelle, inspiré de la clarté de Runna, de la précision de Garmin et du minimalisme de Stripe/Vercel.
|
||||
Les 4 Échelles Temporelles :
|
||||
|
||||
Vue Jour : Découpage de la journée en cours (Matin / Après-midi / Soir) pour coller au bi-quotidien des athlètes.
|
||||
|
||||
Vue Semaine : Timeline horizontale fluide avec capacité de réorganisation des séances (Drag & Drop).
|
||||
|
||||
Vue Mois : Aperçu stratégique de la charge globale et des blocs d'assimilation.
|
||||
|
||||
Vue Macro / Olympiades : Planification à long terme des objectifs majeurs (Ex: Ironman, Pics de forme) et des budgets matériels associés.
|
||||
|
||||
Cockpit Physiologique & Matériel (Les Spinners) :
|
||||
|
||||
Indicateurs circulaires fins calculant en temps réel :
|
||||
|
||||
Fraîcheur / VRC : Niveau de tolérance à la charge d'entraînement.
|
||||
|
||||
Santé Matériel : Indice d'usure des actifs critiques (chaînes, chaussures carbone) corrélé directement à la RYM Bank pour le provisionnement budgétaire automatique.
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
# Journal des Modifications — RYM Horizon
|
||||
|
||||
Toutes les modifications notables de ce projet seront documentées dans ce fichier.
|
||||
|
||||
Le format est basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.0.0/)
|
||||
et ce projet respecte le [Versionnement Sémantique](https://semver.org/lang/fr/).
|
||||
|
||||
---
|
||||
|
||||
## [3.1.0] - 2026-05-27
|
||||
### Ajouté
|
||||
- **Moteur Drag & Drop Natif :** Implémentation d'un système de planification agile (Kanban) dans `app.js` permettant de glisser-déposer les séances d'entraînement à la souris sans aucune dépendance logicielle externe.
|
||||
- **Cockpit Physiologique & Matériel :** Intégration de 4 indicateurs de performance (Fraîcheur VRC, Charge Hebdo, Usure Chaîne Vélo, Paires Carbone) basés sur des tracés SVG natifs et légers.
|
||||
- **Gouvernance & Linters :** Déploiement des fichiers de configuration modernes `eslint.config.js` (Format Flat Config de niveau industriel) et `.stylelintrc.json` à la racine du projet.
|
||||
|
||||
### Modifié
|
||||
- **Design System Responsif :** Optimisation de la structure Bootstrap 5 pour forcer l'alignement des "spinners" sur une seule ligne (`row`) sur écran desktop et une répartition fluide sur mobile.
|
||||
- **Pont de Développement :** Restructuration du conteneur de validation openSUSE Leap 15.6 via un montage de volume Podman sécurisé (`:Z`) permettant l'audit du code en temps réel depuis l'hôte Fedora.
|
||||
|
||||
## [3.0.0] - 2026-05-23
|
||||
|
||||
### Ajouté
|
||||
- **Architecture W3C :** Découplage complet et strict du code source en trois entités distinctes (`index.html`, `style.css`, `app.js`).
|
||||
- **Logique JS Moderne :** Remplacement des attributs obsolètes `onclick` par un gestionnaire d'événements JavaScript non-intrusif basé sur les `data-attributes`.
|
||||
- **Documentation :** Création du fichier `ARCHITECTURE.md` figeant la vision technique et la philosophie souveraine du projet.
|
||||
- **Sécurité & Git :** Déploiement d'un fichier `.gitignore` standardisé pour protéger les secrets de la RYM Bank (fichiers `.env`, clés privées).
|
||||
- **Cockpit à 4 Échelles :** Intégration de la vision multi-échelle (Jour J détaillé / Semaine fluide / Aperçu Mensuel / Macro-Olympiades).
|
||||
- **Indicateurs Fins :** Implémentation des "spinners" circulaires en CSS pur pour le suivi de la fraîcheur physiologique (VRC) et de la santé du matériel.
|
||||
|
||||
### Modifié
|
||||
- **Infrastructure Lab :** Bascule du serveur de test local vers un conteneur souverain européen **openSUSE Leap 15.6** opéré via **Podman** (Rootless).
|
||||
- **Réseau :** Configuration et routage du serveur Nginx local sur le port alternatif `8080` pour contourner les restrictions de privilèges.
|
||||
|
||||
### Sécurisé
|
||||
- Exclusion stricte des fichiers de configuration locaux et des dossiers caches d'éditeurs (`.vscode/`).
|
||||
|
||||
---
|
||||
|
||||
## [2.4.0] - 2026-05-10
|
||||
|
||||
### Ajouté
|
||||
- Première ébauche de la vue calendrier hebdomadaire en tableau standard.
|
||||
- Intégration des boutons d'exports de rapports pour l'Espace Expert (Cohort-Dashboard).
|
||||
- Intégration visuelle de l'état de synchronisation avec l'API Strava.
|
||||
- Structure HTML de base intégrant Bootstrap 5 (version monolithique avec style et script intégrés).
|
||||
|
||||
---
|
||||
|
||||
## [1.0.0] - 2026-04-01
|
||||
|
||||
### Ajouté
|
||||
- Initialisation du projet RYM Horizon.
|
||||
- Maquette de principe de l'interface et choix de la charte graphique de base.
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
====================================================================
|
||||
RYM HORIZON — CONTRAT DE LICENCE COMMERCIALE ET DE CONFIDENTIALITÉ
|
||||
====================================================================
|
||||
|
||||
Version : 1.0.0
|
||||
Date de révision : 23 Mai 2026
|
||||
Titulaire des droits : RYM Bank / Écosystème RYM
|
||||
Juridiction exclusive : République Française / Union Européenne
|
||||
|
||||
--------------------------------------------------------------------
|
||||
1. PROPRIÉTÉ ET DROITS D'AUTEUR
|
||||
--------------------------------------------------------------------
|
||||
Le présent logiciel, incluant sans limitation le code source (HTML,
|
||||
CSS, JavaScript), l'architecture technique, les éléments graphiques,
|
||||
l'arborescence et la documentation associée (ci-après "le Logiciel"),
|
||||
est la propriété exclusive et entière de son auteur originel et de
|
||||
la structure RYM Bank.
|
||||
|
||||
Le Logiciel est protégé par les lois françaises et internationales
|
||||
relatives au droit d'auteur et à la propriété intellectuelle.
|
||||
Tous droits non expressément concédés par le présent contrat sont
|
||||
strictement réservés par le titulaire des droits.
|
||||
|
||||
--------------------------------------------------------------------
|
||||
2. SOUVERAINETÉ ET ÉTANCHÉITÉ COMPORTEMENTALE
|
||||
--------------------------------------------------------------------
|
||||
Conformément à la charte fondamentale de l'écosystème RYM, ce logiciel
|
||||
est conçu pour garantir une étanchéité absolue vis-à-vis des lois
|
||||
extra-territoriales étrangères (notamment le US Cloud Act / USA PATRIOT Act).
|
||||
|
||||
Toute intégration future, modification ou exploitation du code source
|
||||
doit impérativement respecter cette clause d'étanchéité et de
|
||||
souveraineté numérique européenne.
|
||||
|
||||
--------------------------------------------------------------------
|
||||
3. RESTRICTIONS D'UTILISATION ET DE DISTRIBUTION
|
||||
--------------------------------------------------------------------
|
||||
Sauf autorisation écrite, préalable et expresse du titulaire des
|
||||
droits, il est strictement interdit de :
|
||||
- Copier, modifier, adapter, traduire ou créer des œuvres dérivées
|
||||
du Logiciel à des fins commerciales externes ou personnelles.
|
||||
- Distribuer, louer, sous-licencier, vendre ou transférer le Logiciel
|
||||
ou son code source à des tiers.
|
||||
- Divulguer ou publier le code source sur des forges logicielles
|
||||
publiques non contrôlées ou non hébergées en Europe de manière souveraine.
|
||||
|
||||
--------------------------------------------------------------------
|
||||
4. CLAUSE PARTICULIÈRE : RECRUTEMENT ET COLLABORATION (LEAD TECH)
|
||||
--------------------------------------------------------------------
|
||||
Le présent code source est structuré selon les meilleures pratiques du
|
||||
W3C à des fins d'audit technique et d'intégration de collaborateurs
|
||||
clés (notamment un Lead Technical Officer).
|
||||
|
||||
L'accès à ce code par un tiers dans le cadre d'un recrutement, d'un
|
||||
partenariat ou d'un co-développement implique de plein droit une
|
||||
obligation stricte de secret professionnel, de réserve et de non-divulgation.
|
||||
|
||||
--------------------------------------------------------------------
|
||||
5. EXCLUSION DE GARANTIE
|
||||
--------------------------------------------------------------------
|
||||
Le Logiciel est fourni "en l'état", sans garantie d'aucune sorte,
|
||||
expresse ou implicite, y compris mais sans s'y limiter, les garanties
|
||||
de commercialisation ou d'adéquation à un usage particulier.
|
||||
|
||||
--------------------------------------------------------------------
|
||||
Fait à usage de droit. Pour toute demande de licence ou contribution :
|
||||
Contact de l'infrastructure : www.gorym.fr
|
||||
====================================================================
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# RYM Horizon
|
||||
|
||||
> Le Cockpit de Performance Souverain pour l'Athlète d'Endurance.
|
||||
|
||||
## Présentation
|
||||
RYM Horizon fusionne l'organisation temporelle, le suivi de la fraîcheur physiologique et la gestion budgétaire de la performance (MCO des actifs), de manière totalement étanche aux technologies extra-territoriales américaines.
|
||||
|
||||
## Installation Rapide (Laboratoire Local)
|
||||
Le projet est configuré pour tourner de manière isolée sur un serveur web openSUSE via Podman.
|
||||
|
||||
1. Lancer le conteneur :
|
||||
podman run -d -p 8080:8080 --name rym-suse-stable registry.opensuse.org/opensuse/leap:latest tail -f /dev/null
|
||||
|
||||
2. Accéder à l'application : `http://localhost:8080`
|
||||
|
||||
## Documentation
|
||||
- Spécifications techniques : `ARCHITECTURE.md`
|
||||
- Historique des versions : `CHANGELOG.md`
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// --- GESTION DES ONGLETS EXISTANTE ---
|
||||
const navLinks = document.querySelectorAll(".nav-link");
|
||||
const tabContents = document.querySelectorAll(".tab-content");
|
||||
|
||||
navLinks.forEach(link => {
|
||||
link.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
navLinks.forEach(l => l.classList.remove("active"));
|
||||
tabContents.forEach(tc => tc.classList.remove("active"));
|
||||
|
||||
link.classList.add("active");
|
||||
const tabId = link.getAttribute("data-tab");
|
||||
document.getElementById(tabId).classList.add("active");
|
||||
});
|
||||
});
|
||||
|
||||
// --- OPTION 1 : DRAG & DROP ENGINE (AAA SOUVERAIN) ---
|
||||
const draggables = document.querySelectorAll(".rym-draggable-workout");
|
||||
const dropZones = document.querySelectorAll(".drop-zone");
|
||||
|
||||
draggables.forEach(draggable => {
|
||||
draggable.addEventListener("dragstart", (e) => {
|
||||
e.dataTransfer.setData("text/plain", draggable.id);
|
||||
// Petit délai pour l'effet visuel de déplacement
|
||||
setTimeout(() => {
|
||||
draggable.style.display = "none";
|
||||
}, 0);
|
||||
});
|
||||
|
||||
draggable.addEventListener("dragend", () => {
|
||||
draggable.style.display = "block";
|
||||
});
|
||||
});
|
||||
|
||||
dropZones.forEach(zone => {
|
||||
zone.addEventListener("dragover", (e) => {
|
||||
e.preventDefault(); // Indispensable pour autoriser le drop
|
||||
zone.classList.add("drag-over");
|
||||
});
|
||||
|
||||
zone.addEventListener("dragleave", () => {
|
||||
zone.classList.remove("drag-over");
|
||||
});
|
||||
|
||||
zone.addEventListener("drop", (e) => {
|
||||
e.preventDefault();
|
||||
zone.classList.remove("drag-over");
|
||||
|
||||
const id = e.dataTransfer.getData("text/plain");
|
||||
const draggableElement = document.getElementById(id);
|
||||
|
||||
if (draggableElement) {
|
||||
zone.appendChild(draggableElement);
|
||||
// Ici se branchera l'appel API asynchrone vers ton Gitea/Serveur
|
||||
const targetDay = zone.getAttribute("data-day");
|
||||
console.log(`Séance déplacée avec succès sur le jour : ${targetDay}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
export default [
|
||||
{
|
||||
languageOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
globals: {
|
||||
window: "readonly",
|
||||
document: "readonly",
|
||||
console: "readonly",
|
||||
setTimeout: "readonly"
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
"no-unused-vars": "warn",
|
||||
"no-undef": "error",
|
||||
"no-console": "off",
|
||||
"eqeqeq": "error",
|
||||
"curly": "error"
|
||||
}
|
||||
}
|
||||
];
|
||||
208
index.html
208
index.html
|
|
@ -6,95 +6,189 @@
|
|||
<title>RYM Horizon | Écosystème Souverain</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<style>
|
||||
:root { --rym-main: #004a99; --rym-dark: #121416; --rym-accent: #00d1b2; --rym-premium: #ffd700; }
|
||||
body { background-color: #f0f2f5; font-family: 'Inter', sans-serif; font-size: 0.9rem; }
|
||||
.sidebar { min-height: 100vh; background: var(--rym-dark); color: white; }
|
||||
.nav-link { color: #8a8d91; border-radius: 10px; padding: 10px 15px; margin-bottom: 4px; cursor: pointer; }
|
||||
.nav-link.active { background: var(--rym-main); color: white; }
|
||||
.sidebar-heading { font-size: 0.7rem; font-weight: 700; text-transform: uppercase; color: #495057; margin-top: 1.5rem; padding-bottom: 5px; border-bottom: 1px solid #343a40; }
|
||||
.card-rym { border: none; border-radius: 18px; box-shadow: 0 4px 20px rgba(0,0,0,0.05); background: white; }
|
||||
.tab-content { display: none; }
|
||||
.tab-content.active { display: block; animation: fadeIn 0.3s; }
|
||||
.premium-zone { border: 2px solid var(--rym-premium); position: relative; }
|
||||
.hour-row { border-bottom: 1px solid #eee; min-height: 40px; display: flex; align-items: center; }
|
||||
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||||
</style>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
<nav class="col-md-2 d-none d-md-block sidebar p-4 sticky-top">
|
||||
<h4 class="fw-bold text-center mb-5">RYM <span class="text-info">HORIZON</span></h4>
|
||||
|
||||
<div class="sidebar-heading">Admin</div>
|
||||
<ul class="nav flex-column"><li class="nav-item"><a class="nav-link active" onclick="showTab(event, 'dashboard')"><i class="bi bi-shield-check me-2"></i> MCO Dashboard</a></li></ul>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" data-tab="dashboard"><i class="bi bi-shield-check me-2"></i> MCO Dashboard</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="sidebar-heading">Finance</div>
|
||||
<ul class="nav flex-column"><li class="nav-item"><a class="nav-link" onclick="showTab(event, 'bank')"><i class="bi bi-bank me-2"></i> RYM Bank</a></li></ul>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-tab="bank"><i class="bi bi-bank me-2"></i> RYM Bank</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="sidebar-heading">Utilisateur</div>
|
||||
<ul class="nav flex-column"><li class="nav-item"><a class="nav-link" onclick="showTab(event, 'activity')"><i class="bi bi-heart-pulse me-2"></i> RYM Coach</a></li></ul>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-tab="activity"><i class="bi bi-heart-pulse me-2"></i> RYM Coach</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="sidebar-heading">Expert</div>
|
||||
<ul class="nav flex-column"><li class="nav-item"><a class="nav-link" onclick="showTab(event, 'clients')"><i class="bi bi-people me-2"></i> Suivi Cohorte</a></li></ul>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-tab="clients"><i class="bi bi-people me-2"></i> Suivi Cohorte</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<main class="col-md-10 ms-sm-auto px-md-5 py-4">
|
||||
|
||||
<div id="dashboard" class="tab-content active">
|
||||
<section id="dashboard" class="tab-content active">
|
||||
<h2 class="mb-4">MCO Dashboard</h2>
|
||||
<div class="card card-rym p-3 w-25"><h6 class="text-muted">Status Infra</h6><p class="text-success mb-0">● Online - France (OVH)</p></div>
|
||||
<div class="card card-rym p-3 w-25">
|
||||
<h6 class="text-muted">Status Infra</h6>
|
||||
<p class="text-success mb-0">● Online - France (OVH)</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div id="bank" class="tab-content">
|
||||
<section id="bank" class="tab-content">
|
||||
<h2 class="mb-4">RYM Bank</h2>
|
||||
<div class="card card-rym p-4 bg-primary text-white w-50 shadow-lg">
|
||||
<h6>Solde Courant</h6>
|
||||
<h2 class="fw-bold">12 450,80 €</h2>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div id="activity" class="tab-content">
|
||||
<section id="activity" class="tab-content">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2>RYM Coach <small class="text-muted fs-6">| Mon Planning</small></h2>
|
||||
<span class="badge bg-primary">Saison : Triathlon</span>
|
||||
</div>
|
||||
|
||||
<div class="card card-rym p-4 shadow-sm mb-4">
|
||||
<h5 class="mb-3 text-primary"><i class="bi bi-activity me-2"></i>Indicateurs de Performance & Souveraineté</h5>
|
||||
<div class="row row-cols-2 row-cols-sm-2 row-cols-md-4 g-3 text-center justify-content-center">
|
||||
|
||||
<div class="col">
|
||||
<div class="rym-spinner-wrapper">
|
||||
<svg class="rym-spinner-svg" viewBox="0 0 36 36">
|
||||
<path class="circle-bg" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
|
||||
<path class="circle-stroke text-success" stroke-dasharray="82, 100" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
|
||||
</svg>
|
||||
<div class="rym-spinner-text">
|
||||
<span class="fw-bold fs-5">82</span><small>%</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="small fw-semibold mt-2">Fraîcheur VRC</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<div class="rym-spinner-wrapper">
|
||||
<svg class="rym-spinner-svg" viewBox="0 0 36 36">
|
||||
<path class="circle-bg" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
|
||||
<path class="circle-stroke text-warning" stroke-dasharray="65, 100" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
|
||||
</svg>
|
||||
<div class="rym-spinner-text">
|
||||
<span class="fw-bold fs-5">65</span><small>%</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="small fw-semibold mt-2">Charge Hebdo</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<div class="rym-spinner-wrapper">
|
||||
<svg class="rym-spinner-svg" viewBox="0 0 36 36">
|
||||
<path class="circle-bg" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
|
||||
<path class="circle-stroke text-info" stroke-dasharray="45, 100" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
|
||||
</svg>
|
||||
<div class="rym-spinner-text">
|
||||
<span class="fw-bold fs-5">45</span><small>%</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="small fw-semibold mt-2">Chaîne Vélo</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<div class="rym-spinner-wrapper">
|
||||
<svg class="rym-spinner-svg" viewBox="0 0 36 36">
|
||||
<path class="circle-bg" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
|
||||
<path class="circle-stroke text-danger" stroke-dasharray="90, 100" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
|
||||
</svg>
|
||||
<div class="rym-spinner-text">
|
||||
<span class="fw-bold fs-5">90</span><small>%</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="small fw-semibold mt-2">Paires Carbone</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card card-rym p-4 shadow-sm mb-5">
|
||||
<h5 class="mb-3 text-primary"><i class="bi bi-calendar-week me-2"></i>Vue Hebdomadaire (Standard)</h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered text-center align-middle">
|
||||
<thead class="bg-dark text-white">
|
||||
<tr><th>Moment</th><th>Lun</th><th>Mar</th><th>Mer</th><th>Jeu</th><th>Ven</th><th>Sam</th><th>Dim</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td class="bg-light fw-bold">Matin</td><td><i class="bi bi-water"></i></td><td>-</td><td><i class="bi bi-bicycle"></i></td><td><i class="bi bi-water"></i></td><td>-</td><td class="bg-info-subtle">Loisir</td><td class="bg-danger-subtle">Repos</td></tr>
|
||||
<tr><td class="bg-light fw-bold">A-M</td><td>-</td><td><i class="bi bi-lightning"></i></td><td>-</td><td>-</td><td><i class="bi bi-lightning"></i></td><td><i class="bi bi-bicycle"></i></td><td>-</td></tr>
|
||||
<tr><td class="bg-light fw-bold">Soir</td><td>-</td><td>-</td><td><i class="bi bi-person-walking"></i></td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h5 class="mb-3 text-primary"><i class="bi bi-calendar-week me-2"></i>Vue Hebdomadaire Dynamique</h5>
|
||||
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-4 row-cols-lg-7 g-2" id="planning-kanban">
|
||||
|
||||
<div class="col">
|
||||
<div class="bg-light p-2 rounded border h-100 drop-zone" data-day="Lun">
|
||||
<div class="fw-bold text-center border-bottom pb-1 mb-2 bg-dark text-white rounded-top small">Lundi</div>
|
||||
<div class="rym-draggable-workout bg-primary text-white p-2 rounded mb-2 shadow-sm small" draggable="true" id="w1">
|
||||
<i class="bi bi-water me-1"></i> Natation : 2500m
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<div class="bg-light p-2 rounded border h-100 drop-zone" data-day="Mar">
|
||||
<div class="fw-bold text-center border-bottom pb-1 mb-2 bg-dark text-white rounded-top small">Mardi</div>
|
||||
<div class="rym-draggable-workout bg-warning text-dark p-2 rounded mb-2 shadow-sm small" draggable="true" id="w2">
|
||||
<i class="bi bi-lightning me-1"></i> VMA Balayage
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<div class="bg-light p-2 rounded border h-100 drop-zone" data-day="Mer">
|
||||
<div class="fw-bold text-center border-bottom pb-1 mb-2 bg-dark text-white rounded-top small">Mercredi</div>
|
||||
<div class="rym-draggable-workout bg-info text-dark p-2 rounded mb-2 shadow-sm small" draggable="true" id="w3">
|
||||
<i class="bi bi-bicycle me-1"></i> Vélo Tempête
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<div class="bg-light p-2 rounded border h-100 drop-zone" data-day="Jeu">
|
||||
<div class="fw-bold text-center border-bottom pb-1 mb-2 bg-dark text-white rounded-top small">Jeudi</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<div class="bg-light p-2 rounded border h-100 drop-zone" data-day="Ven">
|
||||
<div class="fw-bold text-center border-bottom pb-1 mb-2 bg-dark text-white rounded-top small">Vendredi</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<div class="bg-light p-2 rounded border h-100 drop-zone" data-day="Sam">
|
||||
<div class="fw-bold text-center border-bottom pb-1 mb-2 bg-dark text-white rounded-top small">Samedi</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<div class="bg-light p-2 rounded border h-100 drop-zone" data-day="Dim">
|
||||
<div class="fw-bold text-center border-bottom pb-1 mb-2 bg-dark text-white rounded-top small">Dimanche</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card card-rym p-4 premium-zone shadow-lg">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h5 class="fw-bold text-dark"><i class="bi bi-clock me-2"></i>Agenda Précision Premium (24h/24)</h5>
|
||||
<button class="btn btn-warning btn-sm fw-bold">Passer au Premium</button>
|
||||
</div>
|
||||
<div class="bg-light rounded p-3" style="max-height: 250px; overflow-y: auto;">
|
||||
<div class="hour-row"><div class="col-1 fw-bold border-end pe-2">06:00</div><div class="col-11 ps-3 text-muted">Sommeil / Réveil</div></div>
|
||||
<div class="hour-row"><div class="col-1 fw-bold border-end pe-2">07:00</div><div class="col-11 ps-3 bg-primary-subtle text-primary">Natation : 2500m Seuil</div></div>
|
||||
<div class="hour-row"><div class="col-1 fw-bold border-end pe-2">08:00</div><div class="col-11 ps-3">Petit-Déjeuner & Hydratation</div></div>
|
||||
<div class="hour-row"><div class="col-1 fw-bold border-end pe-2 text-primary">...</div><div class="col-11 ps-3">...</div></div>
|
||||
<div class="hour-row"><div class="col-1 fw-bold border-end pe-2">23:00</div><div class="col-11 ps-3 text-muted">Repos / Nuit</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="clients" class="tab-content">
|
||||
<section id="clients" class="tab-content">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2>Espace Expert <small class="text-muted fs-6">| Dashboard Cohorte</small></h2>
|
||||
<div class="btn-group shadow-sm">
|
||||
|
|
@ -128,7 +222,7 @@
|
|||
<hr>
|
||||
<div class="col-6">Cou: 39cm</div><div class="col-6 text-end">Poitrine: 104cm</div>
|
||||
<div class="col-6">Hanches: 92cm</div><div class="col-6 text-end">Taille: 80cm</div>
|
||||
<div class="col-6 text-primary">Cuisse (D/G): 58/58</div><div class="col-6 text-primary text-end">Mollet (D/G): 39/39</div>
|
||||
<div class="col-6">Cuisse (D/G): 58/58</div><div class="col-6 text-primary text-end">Mollet (D/G): 39/39</div>
|
||||
</div>
|
||||
<div class="mt-4 p-2 bg-light border rounded text-center x-small">
|
||||
<i class="bi bi-shield-lock me-1"></i> Données Chiffrées (Souveraineté RYM)
|
||||
|
|
@ -136,19 +230,13 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function showTab(event, tabId) {
|
||||
document.querySelectorAll('.tab-content').forEach(tab => tab.classList.remove('active'));
|
||||
document.querySelectorAll('.nav-link').forEach(link => link.classList.remove('active'));
|
||||
document.getElementById(tabId).classList.add('active');
|
||||
event.currentTarget.classList.add('active');
|
||||
}
|
||||
</script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="app.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,150 @@
|
|||
/* Variables de Design System RYM */
|
||||
:root {
|
||||
--rym-main: #004a99;
|
||||
--rym-dark: #121416;
|
||||
--rym-accent: #00d1b2;
|
||||
--rym-premium: #ffd700;
|
||||
--rym-bg: #f0f2f5;
|
||||
}
|
||||
|
||||
/* Base App Layout */
|
||||
body {
|
||||
background-color: var(--rym-bg);
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
/* Navigation & Sidebar UI */
|
||||
.sidebar {
|
||||
min-height: 100vh;
|
||||
background: var(--rym-dark);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.sidebar-heading {
|
||||
font-size: 0.7rem;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
color: #495057;
|
||||
margin-top: 1.5rem;
|
||||
padding-bottom: 5px;
|
||||
border-bottom: 1px solid #343a40;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
color: #8a8d91;
|
||||
border-radius: 10px;
|
||||
padding: 10px 15px;
|
||||
margin-bottom: 4px;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
|
||||
.nav-link:hover {
|
||||
color: white;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.nav-link.active {
|
||||
background: var(--rym-main);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* UI Components */
|
||||
.card-rym {
|
||||
border: none;
|
||||
border-radius: 18px;
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,0.05);
|
||||
background: white;
|
||||
}
|
||||
|
||||
.premium-zone {
|
||||
border: 2px solid var(--rym-premium);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Agenda Components */
|
||||
.agenda-scroll {
|
||||
max-height: 250px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.hour-row {
|
||||
border-bottom: 1px solid #eee;
|
||||
min-height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Router / Navigation Tabs States */
|
||||
.tab-content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-content.active {
|
||||
display: block;
|
||||
animation: fadeIn 0.3s forwards;
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(4px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
/* --- CONFIGURATION DES SPINNERS (OPTION 2) --- */
|
||||
.rym-spinner-wrapper {
|
||||
position: relative;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.rym-spinner-svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
.circle-bg {
|
||||
fill: none;
|
||||
stroke: #e6e6e6;
|
||||
stroke-width: 2.8;
|
||||
}
|
||||
|
||||
.circle-stroke {
|
||||
fill: none;
|
||||
stroke-width: 2.8;
|
||||
stroke-linecap: round;
|
||||
transition: stroke-dasharray 0.5s ease;
|
||||
}
|
||||
|
||||
.rym-spinner-text {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* --- DRAG AND DROP KANBAN (OPTION 1) --- */
|
||||
.drop-zone {
|
||||
min-height: 140px;
|
||||
transition: background-color 0.2s ease, border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.drop-zone.drag-over {
|
||||
background-color: #e2e8f0 !important;
|
||||
border: 2px dashed #0dcaf0 !important;
|
||||
}
|
||||
|
||||
.rym-draggable-workout {
|
||||
cursor: grab;
|
||||
transition: transform 0.1s ease, opacity 0.1s ease;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.rym-draggable-workout:active {
|
||||
cursor: grabbing;
|
||||
opacity: 0.5;
|
||||
}
|
||||
Loading…
Reference in New Issue