import {Meta, Source} from '@storybook/addon-docs/blocks';
import '../styles/shared.css';

<Meta title="Guide Du Dev/Migration/Migration depuis Bridge"/>


<div className="header">
  <h1>Migrer de Bridge (Vue3) vers Synapse</h1>
</div>

## 1 - Commencer la migration

- Téléchargez la stack de migration [Starter Kit Synapse](https://gitlab.cnqd.cnamts.fr/human/developpement/sksn_x).

- Transférez les pages de votre projet du Starter Kit Bridge dans le dossier pages du projet Starter Kit Synapse, les composants peuvent être placés dans le dossier components.

- Identifier les dépendances à conserver dans la nouvelle version.
Le package `@cnamts/synapse-bridge` a été remplacé par `@cnamts/synapse`.

- Dans le fichier nuxt.config.ts, ajouter le lien vers votre fichier de style global.

<Source dark code={`
// nuxt.config.ts
export default defineNuxtConfig({
	...
	css: [
		...
		'@/theme/styles.scss' // chemin vers votre fichier de style global
	],
	...
})
`}
/>

- Dans le fichier nuxt.config.ts, ajouter les variables de configurations.

<Source dark code={`
// nuxt.config.ts
export default defineNuxtConfig({
	runtimeConfig: {
		public: {
			// ajouter les variables de configuration public ici
			version: process.env.VUE_APP_VERSION,
		},
		...
	},
	...
})
`}
/>

Pour modifier ces variables sans regénérer le projet, il faut les écraser dans le fichier `.output/public/json/config.env.json`.

Pour utiliser ces variables dans un composant, il faut les importer et les utiliser comme suit :

<Source dark code={`
<script lang="ts">
  export default defineNuxtComponent({
    mounted() {
      console.log(this.$config.public.version)
    }
  })
</script>

<template>
  <div>
    {{ $config.public.version }}
  </div>
</template>
`}
/>

## 2 - Migration du routeur

Dans Nuxt 3, il n’est pas nécessaire de créer un fichier `router/index.ts` comme dans Vue classique. Nuxt 3 utilise un système de routing automatique basé sur les fichiers présents dans le dossier `pages/`.
Cependant, pour ajouter un router personnalisé, voici comment faire :

Ouvrir `router.options.ts` dans le dossier `app/` et ajoutez vos routes :

<Source dark code={`
// app/router.ts
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: () => import('@/pages/index.vue') },
    { path: '/about', component: () => import('@/pages/about.vue') },
    { path: '/contact', component: () => import('@/pages/contact.vue') },
  ],
})

export default router
`}
/>

Voir le [guide de migration de vue-router](https://router.vuejs.org/guide/migration/) pour plus d'informations.

## 3 - Migration des stores VueX vers Pinia

Prenons un exemple de store Vuex :

<Source dark code={`
// Ancien store Vuex (store/index.js)
import { createStore } from 'vuex'

export default createStore({
  state: {
    count: 0,
    user: null,
  },
  mutations: {
    increment(state) {
      state.count++
    },
    setUser(state, user) {
      state.user = user
    }
  },
  actions: {
    async fetchUser({ commit }) {
      const user = await fetch('/api/user').then(res => res.json())
      commit('setUser', user)
    }
  },
  getters: {
    isAuthenticated: state => !!state.user,
  }
})
`}
/>

Nouvelle version avec Pinia :

<Source dark code={`
// stores/counter.ts
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
    user: null as null | { name: string; email: string }
  }),
  actions: {
    increment() {
      this.count++
    },
    async fetchUser() {
      const user = await fetch('/api/user').then(res => res.json())
      this.user = user
    }
  },
  getters: {
    isAuthenticated: (state) => !!state.user,
  }
})
`}
/>

Différences majeures entre Vuex et Pinia :
-	Plus besoin de mutations → On modifie l’état directement !
-	Les getters et actions sont dans le même objet
-	Plus léger et plus performant

Utilisation du store dans les composants Vue :

<Source dark code={`
// Avec Vuex
<script setup>
import { useStore } from 'vuex'
const store = useStore()

store.commit('increment')
console.log(store.state.count)
</script>
`}
/>

<Source dark code={`
// Avec Pinia
<script setup>
import { useCounterStore } from '@/stores/counter'
const counterStore = useCounterStore()

counterStore.increment()
console.log(counterStore.count)
</script>
`}
/>

Nb : pour la persistance des données vous pouvez utiliser le plugin [pinia-plugin-persistedstate](https://prazdevs.github.io/pinia-plugin-persistedstate/).

## 4 - Migration de la syntaxe des composants

La grande différence entre la version Bridge et la version Synapse est la syntaxe des composants qui passe de l'option API à la composition API.
Voir la documentation sur la composition API [ici](https://v3.vuejs.org/guide/composition-api-introduction.html).

Vue 3 introduit la Composition API qui offre plusieurs avantages :

- Meilleure organisation du code pour les projets complexes
- Réutilisation facile avec des fonctions composables
- Meilleure performance grâce à une gestion plus optimisée du rendu
- Meilleur support TypeScript

L'Option API et la Composition API peuvent coexister dans un même projet, mais il est recommandé d'utiliser la composition API pour de meilleures performances et une meilleure organisation du code.

### 4.1 - Migration des `data()`

Avant (Options API) :

<Source dark code={`
<script>
export default {
  data() {
    return {
      count: 0,
      user: {
        name: 'John Doe',
        age: 30
      }
    }
  }
}
</script>
`}
/>

Après (Composition API) :

<Source dark code={`
<script setup>
import { ref, reactive } from 'vue'

const count = ref(0)
const user = reactive({ name: 'John Doe', age: 30 })
</script>
`}
/>

### 4.2 Migration des `methods`

Avant (Options API) :

<Source dark code={`
<script>
export default {
  data() {
    return { count: 0 }
  },
  methods: {
    increment() {
      this.count++
    }
  }
}
</script>
`}
/>

Après (Composition API) :

<Source dark code={`
<script setup>
import { ref } from 'vue'

const count = ref(0)
const increment = () => count.value++
</script>
`}
/>

### 4.3 Migration des `computed`

Avant (Options API) :

<Source dark code={`
<script>
export default {
  data() {
    return { count: 5 }
  },
  computed: {
    doubleCount() {
      return this.count * 2
    }
  }
}
</script>
`}
/>

Après (Composition API) :

<Source dark code={`
<script setup>
import { ref, computed } from 'vue'

const count = ref(5)
const doubleCount = computed(() => count.value * 2)
</script>
`}
/>

### 4.4 Migration des `watch`

Avant (Options API) :

<Source dark code={`
<script>
export default {
  data() {
    return { count: 0 }
  },
  watch: {
    count(newValue, oldValue) {
      console.log(\`Count changed from \${oldValue} to \${newValue}\`)
    }
  }
}
</script>
`}
/>

Après (Composition API) :

<Source dark code={`
<script setup>
import { ref, watch } from 'vue'

const count = ref(0)

watch(count, (newValue, oldValue) => {
  console.log(\`Count changed from \${oldValue} to \${newValue}\`)
})
</script>
`}
/>

`watch()` fonctionne directement sur une variable réactive.

### 4.5 - Migration des Hooks de cycle de vie

Avant (Options API) :

<Source dark code={`
<script>
export default {
  created() {
    console.log('Component created')
  },
  mounted() {
    console.log('Component mounted')
  }
}
</script>
`}
/>

Après (Composition API) :

<Source dark code={`
<script setup>
import { onMounted, onBeforeMount } from 'vue'

onBeforeMount(() => {
  console.log('Component will be created')
})

onMounted(() => {
  console.log('Component mounted')
})
</script>
`}
/>

On remplace les hooks par `onMounted()`, `onBeforeMount()`, etc.

### 4.6 - Migration des `props`

Avant (Options API) :

<Source dark code={`
<script>
export default {
  props: {
    msg: String
  }
}
</script>
`}
/>

Après (Composition API) :

<Source dark code={`
<script setup>
import { defineProps } from 'vue'

const props = defineProps({
  msg: String
})
</script>
`}
/>

### 4.7 - Migration des `emits`

Avant (Options API) :

<Source dark code={`
<script>
export default {
  methods: {
    handleClick() {
      this.$emit('clicked')
    }
  }
}
</script>
`}
/>

Après (Composition API) :

<Source dark code={`
<script setup>
import { defineEmits } from '
import '../styles/shared.css';vue'

const { emit } = defineEmits()

const handleClick = () => {
  emit('clicked')
}
</script>
`}
/>