migrate to Vue3
This commit is contained in:
643
GUIDE_DEVELOPPEMENT.md
Normal file
643
GUIDE_DEVELOPPEMENT.md
Normal file
@@ -0,0 +1,643 @@
|
||||
# Guide de Développement - Application Binôme (Stack Moderne)
|
||||
|
||||
## 🚀 Vue d'Ensemble
|
||||
|
||||
L'application **Binôme** est maintenant basée sur une stack moderne Vue 3 + Vite + Pinia, optimisée pour le développement et la performance.
|
||||
|
||||
### Stack Technique
|
||||
|
||||
- **Frontend** : Vue 3.5.17 + TypeScript
|
||||
- **Build Tool** : Vite 7.0.5
|
||||
- **State Management** : Pinia 3.0.3 avec persistence
|
||||
- **Routing** : Vue Router 4.5.1
|
||||
- **Styling** : SCSS avec variables globales
|
||||
- **PWA** : vite-plugin-pwa
|
||||
- **Package Manager** : pnpm
|
||||
- **Node.js** : v20 (LTS)
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Prérequis et Installation
|
||||
|
||||
### Prérequis Système
|
||||
|
||||
```bash
|
||||
# Node.js version 20 (LTS)
|
||||
node --version # doit afficher v20.x.x
|
||||
|
||||
# pnpm installé globalement
|
||||
npm install -g pnpm@latest
|
||||
```
|
||||
|
||||
### Installation du Projet
|
||||
|
||||
```bash
|
||||
# Cloner le projet
|
||||
git clone <repository-url>
|
||||
cd binome
|
||||
|
||||
# Installer les dépendances
|
||||
pnpm install
|
||||
|
||||
# Vérifier l'installation
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📜 Scripts Disponibles
|
||||
|
||||
### Scripts de Développement
|
||||
|
||||
```bash
|
||||
# Démarrer le serveur de développement
|
||||
pnpm dev
|
||||
# → Lance Vite dev server sur http://localhost:8080
|
||||
# → Hot Module Replacement (HMR) activé
|
||||
# → Ouverture automatique du navigateur
|
||||
|
||||
# Prévisualiser la build de production
|
||||
pnpm preview
|
||||
# → Sert la version buildée localement
|
||||
# → Utile pour tester avant déploiement
|
||||
```
|
||||
|
||||
### Scripts de Build
|
||||
|
||||
```bash
|
||||
# Build de production
|
||||
pnpm build
|
||||
# → Génère le dossier /dist optimisé
|
||||
# → Minification et tree-shaking automatiques
|
||||
# → Source maps incluses
|
||||
|
||||
# Analyser la build
|
||||
pnpm build --analyze
|
||||
# → Affiche la taille des bundles
|
||||
# → Identifie les dépendances lourdes
|
||||
```
|
||||
|
||||
### Scripts de Qualité
|
||||
|
||||
```bash
|
||||
# Linter ESLint
|
||||
pnpm lint
|
||||
# → Vérifie et corrige automatiquement le code
|
||||
# → Supporte .vue, .ts, .js files
|
||||
# → Configuration dans .eslintrc.js
|
||||
|
||||
# Type checking TypeScript
|
||||
pnpm type-check
|
||||
# → Vérifie les types sans compilation
|
||||
# → Utile en CI/CD
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Architecture du Projet
|
||||
|
||||
### Structure des Dossiers
|
||||
|
||||
```
|
||||
src/
|
||||
├── assets/ # Ressources statiques (SVG, images)
|
||||
├── components/ # Composants Vue réutilisables
|
||||
│ ├── ChilledMusic.vue
|
||||
│ ├── DevSession.vue
|
||||
│ ├── IntervalInput.vue
|
||||
│ ├── SpotifyMusic.vue
|
||||
│ ├── SWNewVersion.vue
|
||||
│ └── ZoneMusic.vue
|
||||
├── hooks/ # Composables Vue 3
|
||||
│ ├── useInterval.ts
|
||||
│ ├── useMusic.ts
|
||||
│ ├── useSpotify.ts
|
||||
│ ├── useTimer.ts
|
||||
│ └── useWakeLock.ts
|
||||
├── lib/ # Bibliothèques externes
|
||||
│ └── spotify-player.js # ⚠️ CRITIQUE - Ne pas modifier
|
||||
├── locales/ # Fichiers de traduction i18n
|
||||
│ ├── en.json
|
||||
│ └── fr.json
|
||||
├── router/ # Configuration Vue Router
|
||||
│ └── index.ts
|
||||
├── store/ # Store Pinia
|
||||
│ └── index.ts
|
||||
├── styles/ # Styles SCSS globaux
|
||||
│ ├── app.scss
|
||||
│ ├── plume.scss
|
||||
│ └── variables.scss
|
||||
├── types/ # Types TypeScript
|
||||
│ └── StopwatchState.ts
|
||||
├── utils/ # Utilitaires
|
||||
│ ├── notification.ts
|
||||
│ └── spotify.ts
|
||||
├── views/ # Pages/Vues principales
|
||||
│ ├── Home.vue
|
||||
│ ├── Privacy.vue
|
||||
│ └── SpotifyCallback.vue
|
||||
├── App.vue # Composant racine
|
||||
├── i18n.ts # Configuration internationalisation
|
||||
└── main.ts # Point d'entrée de l'application
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Patterns de Développement
|
||||
|
||||
### 1. Composants Vue 3
|
||||
|
||||
#### Composition API avec `<script setup>`
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="my-component">
|
||||
<h2>{{ title }}</h2>
|
||||
<button @click="increment">Count: {{ count }}</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
// Props avec TypeScript
|
||||
interface Props {
|
||||
title: string
|
||||
initialCount?: number
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
initialCount: 0
|
||||
})
|
||||
|
||||
// État réactif
|
||||
const count = ref(props.initialCount)
|
||||
|
||||
// Méthodes
|
||||
const increment = () => {
|
||||
count.value++
|
||||
}
|
||||
|
||||
// Émissions d'événements
|
||||
const emit = defineEmits<{
|
||||
countChanged: [value: number]
|
||||
}>()
|
||||
|
||||
// Watcher
|
||||
watch(count, (newValue) => {
|
||||
emit('countChanged', newValue)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.my-component {
|
||||
padding: 1rem;
|
||||
border: 1px solid $primary-color; // Variable SCSS globale
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
#### Composables (Hooks Personnalisés)
|
||||
|
||||
```typescript
|
||||
// hooks/useCounter.ts
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
export function useCounter(initialValue = 0) {
|
||||
const count = ref(initialValue)
|
||||
|
||||
const increment = () => count.value++
|
||||
const decrement = () => count.value--
|
||||
const reset = () => count.value = initialValue
|
||||
|
||||
const isEven = computed(() => count.value % 2 === 0)
|
||||
|
||||
return {
|
||||
count: readonly(count),
|
||||
increment,
|
||||
decrement,
|
||||
reset,
|
||||
isEven
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Store Pinia
|
||||
|
||||
#### Définition du Store
|
||||
|
||||
```typescript
|
||||
// store/modules/timer.ts
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
interface TimerState {
|
||||
currentTime: number
|
||||
isRunning: boolean
|
||||
interval: number
|
||||
}
|
||||
|
||||
export const useTimerStore = defineStore('timer', {
|
||||
state: (): TimerState => ({
|
||||
currentTime: 0,
|
||||
isRunning: false,
|
||||
interval: 5
|
||||
}),
|
||||
|
||||
getters: {
|
||||
formattedTime: (state) => {
|
||||
const minutes = Math.floor(state.currentTime / 60)
|
||||
const seconds = state.currentTime % 60
|
||||
return `${minutes}:${seconds.toString().padStart(2, '0')}`
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
startTimer() {
|
||||
this.isRunning = true
|
||||
},
|
||||
|
||||
stopTimer() {
|
||||
this.isRunning = false
|
||||
},
|
||||
|
||||
resetTimer() {
|
||||
this.currentTime = 0
|
||||
this.isRunning = false
|
||||
}
|
||||
},
|
||||
|
||||
// Persistence automatique
|
||||
persist: {
|
||||
key: 'timer-store',
|
||||
storage: localStorage,
|
||||
paths: ['interval'] // Seuls certains champs
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### Utilisation dans les Composants
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { useTimerStore } from '@/store'
|
||||
|
||||
const timerStore = useTimerStore()
|
||||
|
||||
// Accès direct aux propriétés réactives
|
||||
const { currentTime, isRunning, formattedTime } = storeToRefs(timerStore)
|
||||
|
||||
// Accès aux actions
|
||||
const { startTimer, stopTimer, resetTimer } = timerStore
|
||||
</script>
|
||||
```
|
||||
|
||||
### 3. Internationalisation (i18n)
|
||||
|
||||
#### Utilisation dans les Composants
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div>
|
||||
<h1>{{ $t('welcome.title') }}</h1>
|
||||
<p>{{ $t('welcome.message', { name: userName }) }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t, locale } = useI18n()
|
||||
|
||||
// Changement de langue
|
||||
const switchLanguage = (lang: string) => {
|
||||
locale.value = lang
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
#### Ajout de Nouvelles Traductions
|
||||
|
||||
```json
|
||||
// locales/fr.json
|
||||
{
|
||||
"welcome": {
|
||||
"title": "Bienvenue dans Binôme",
|
||||
"message": "Bonjour {name}, prêt pour une session de programmation ?"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Styling et Thèmes
|
||||
|
||||
### Variables SCSS Globales
|
||||
|
||||
```scss
|
||||
// styles/variables.scss
|
||||
$primary-color: #f8efba;
|
||||
$secondary-color: #333;
|
||||
$font-family: 'Arial', sans-serif;
|
||||
$border-radius: 8px;
|
||||
$spacing-unit: 1rem;
|
||||
|
||||
// Breakpoints
|
||||
$mobile: 768px;
|
||||
$tablet: 1024px;
|
||||
$desktop: 1200px;
|
||||
```
|
||||
|
||||
### Utilisation dans les Composants
|
||||
|
||||
```vue
|
||||
<style lang="scss" scoped>
|
||||
.component {
|
||||
background-color: $primary-color;
|
||||
padding: $spacing-unit;
|
||||
border-radius: $border-radius;
|
||||
|
||||
@media (max-width: $mobile) {
|
||||
padding: $spacing-unit / 2;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Configuration de Développement
|
||||
|
||||
### Vite Configuration ([`vite.config.ts`](vite.config.ts:1))
|
||||
|
||||
```typescript
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import { VitePWA } from 'vite-plugin-pwa'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
VitePWA({
|
||||
registerType: 'autoUpdate',
|
||||
workbox: {
|
||||
skipWaiting: true,
|
||||
clientsClaim: true
|
||||
}
|
||||
})
|
||||
],
|
||||
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': resolve(__dirname, 'src')
|
||||
}
|
||||
},
|
||||
|
||||
server: {
|
||||
port: 8080,
|
||||
open: true,
|
||||
hmr: true
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### TypeScript Configuration
|
||||
|
||||
```json
|
||||
// tsconfig.json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Tests et Qualité
|
||||
|
||||
### ESLint Configuration
|
||||
|
||||
```javascript
|
||||
// .eslintrc.js
|
||||
module.exports = {
|
||||
extends: [
|
||||
'plugin:vue/vue3-essential',
|
||||
'eslint:recommended',
|
||||
'@vue/typescript/recommended'
|
||||
],
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Commandes de Vérification
|
||||
|
||||
```bash
|
||||
# Vérification complète avant commit
|
||||
pnpm lint && pnpm type-check && pnpm build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📱 PWA et Service Worker
|
||||
|
||||
### Configuration PWA
|
||||
|
||||
L'application est configurée comme PWA avec :
|
||||
|
||||
- **Manifest** : Icônes, couleurs, mode d'affichage
|
||||
- **Service Worker** : Cache automatique, mise à jour en arrière-plan
|
||||
- **Raccourcis** : Accès rapide aux fonctionnalités
|
||||
|
||||
### Gestion des Mises à Jour
|
||||
|
||||
```vue
|
||||
<!-- components/SWNewVersion.vue -->
|
||||
<template>
|
||||
<div v-if="needRefresh" class="update-banner">
|
||||
<p>{{ $t('notification.update.body') }}</p>
|
||||
<button @click="updateSW">{{ $t('update') }}</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useRegisterSW } from 'virtual:pwa-register/vue'
|
||||
|
||||
const { needRefresh, updateServiceWorker } = useRegisterSW()
|
||||
|
||||
const updateSW = async () => {
|
||||
await updateServiceWorker()
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎵 Intégration Spotify
|
||||
|
||||
### Fichier Critique : [`spotify-player.js`](src/lib/spotify-player.js:1)
|
||||
|
||||
⚠️ **ATTENTION** : Ce fichier ne doit JAMAIS être modifié
|
||||
|
||||
- Contient le SDK Spotify personnalisé
|
||||
- 571 lignes de code critique
|
||||
- Toute modification peut casser l'intégration Spotify
|
||||
|
||||
### Utilisation du Player Spotify
|
||||
|
||||
```typescript
|
||||
// hooks/useSpotify.ts
|
||||
import { ref } from 'vue'
|
||||
|
||||
export function useSpotify() {
|
||||
const player = ref<any>(null)
|
||||
const isReady = ref(false)
|
||||
|
||||
const initializePlayer = (token: string) => {
|
||||
// Utilisation du spotify-player.js
|
||||
player.value = new window.Spotify.Player({
|
||||
name: 'Binôme Player',
|
||||
getOAuthToken: (cb: (token: string) => void) => {
|
||||
cb(token)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
player,
|
||||
isReady,
|
||||
initializePlayer
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Déploiement
|
||||
|
||||
### Build de Production
|
||||
|
||||
```bash
|
||||
# Génération des fichiers optimisés
|
||||
pnpm build
|
||||
|
||||
# Vérification de la build
|
||||
pnpm preview
|
||||
```
|
||||
|
||||
### Netlify (Configuration dans [`netlify.toml`](netlify.toml:1))
|
||||
|
||||
```toml
|
||||
[build]
|
||||
command = "pnpm build"
|
||||
publish = "dist"
|
||||
|
||||
[[redirects]]
|
||||
from = "/*"
|
||||
to = "/index.html"
|
||||
status = 200
|
||||
```
|
||||
|
||||
### Variables d'Environnement
|
||||
|
||||
```bash
|
||||
# .env.local (non versionné)
|
||||
VITE_SPOTIFY_CLIENT_ID=your_client_id
|
||||
VITE_API_BASE_URL=https://api.example.com
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Debugging et Outils
|
||||
|
||||
### Vue DevTools
|
||||
|
||||
- Extension navigateur pour Vue 3
|
||||
- Inspection des composants et du store Pinia
|
||||
- Timeline des événements
|
||||
|
||||
### Vite DevTools
|
||||
|
||||
- HMR (Hot Module Replacement)
|
||||
- Source maps automatiques
|
||||
- Inspection des modules
|
||||
|
||||
### Console de Debug
|
||||
|
||||
```typescript
|
||||
// Activation du debug en développement
|
||||
if (import.meta.env.DEV) {
|
||||
console.log('Mode développement activé')
|
||||
// Exposition du store pour debug
|
||||
window.__PINIA__ = pinia
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Ressources et Documentation
|
||||
|
||||
### Documentation Officielle
|
||||
|
||||
- [Vue 3](https://vuejs.org/)
|
||||
- [Vite](https://vitejs.dev/)
|
||||
- [Pinia](https://pinia.vuejs.org/)
|
||||
- [Vue Router](https://router.vuejs.org/)
|
||||
|
||||
### Outils Recommandés
|
||||
|
||||
- **IDE** : VS Code avec extensions Vue
|
||||
- **Extensions** : Vetur, TypeScript Vue Plugin
|
||||
- **Browser** : Chrome/Firefox avec Vue DevTools
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Workflow de Développement
|
||||
|
||||
### 1. Démarrage d'une Nouvelle Fonctionnalité
|
||||
|
||||
```bash
|
||||
# Créer une branche
|
||||
git checkout -b feature/nouvelle-fonctionnalite
|
||||
|
||||
# Démarrer le serveur de dev
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
### 2. Développement
|
||||
|
||||
- Modifier les fichiers dans `src/`
|
||||
- Tester en temps réel avec HMR
|
||||
- Utiliser Vue DevTools pour debug
|
||||
|
||||
### 3. Tests et Validation
|
||||
|
||||
```bash
|
||||
# Vérification du code
|
||||
pnpm lint
|
||||
|
||||
# Build de test
|
||||
pnpm build && pnpm preview
|
||||
```
|
||||
|
||||
### 4. Commit et Push
|
||||
|
||||
```bash
|
||||
# Commit avec message descriptif
|
||||
git add .
|
||||
git commit -m "feat: ajout de la nouvelle fonctionnalité"
|
||||
git push origin feature/nouvelle-fonctionnalite
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Guide créé le 20 juillet 2025**
|
||||
**Version de l'application** : Stack moderne Vue 3 + Vite + Pinia
|
||||
**Prochaine mise à jour** : Après résolution des problèmes techniques identifiés
|
||||
Reference in New Issue
Block a user