# Système de blocs

## Principe

Un bloc est l'unité de contenu de base. Chaque bloc est autonome et existe
obligatoirement en trois endroits. Ne jamais créer un bloc partiellement.

```
blocks/schema.js        ← SOURCE DE VÉRITÉ (props, types, défauts)
blocks/core/MonBloc/Back.vue    ← Composant back-office (édition)
blocks/core/MonBloc/Front.vue   ← Composant front-office (rendu)
blocks/index.js         ← Enregistrement du bloc
```

---

## Schéma d'un bloc (schema.js)

```js
// blocks/schema.js
export const BlockSchemas = {

  'nom-du-bloc': {
    label: 'Nom affiché',
    icon: 'nom_icone_material',   // icône Material Icons
    category: 'content',          // 'content' | 'media' | 'metier'
    props: {
      // Types disponibles : string | number | boolean | enum | media | media[] | richtext | color | url
      title: {
        type: 'string',
        required: true,
        default: '',
        label: 'Titre',
      },
      style: {
        type: 'enum',
        values: ['grid', 'list', 'carousel'],
        default: 'grid',
        label: 'Style d\'affichage',
      },
      showFilters: {
        type: 'boolean',
        default: true,
        label: 'Afficher les filtres',
      },
      image: {
        type: 'media',
        required: false,
        label: 'Image',
      },
      images: {
        type: 'media[]',
        required: false,
        label: 'Images',
      },
      content: {
        type: 'richtext',
        required: false,
        label: 'Contenu',
      },
      count: {
        type: 'number',
        default: 6,
        min: 1,
        max: 24,
        label: 'Nombre d\'éléments',
      },
    },
  },

}
```

---

## Composant Back.vue (back-office)

```vue
<!-- blocks/core/MonBloc/Back.vue -->
<template>
  <!-- Aperçu fidèle au rendu front-office -->
  <!-- L'édition des props se fait dans PropsEditor, pas ici -->
  <div class="mon-bloc-preview">
    <h2>{{ props.title }}</h2>
    <!-- aperçu du contenu -->
  </div>
</template>

<script setup>
// Reçoit exactement les props définies dans schema.js
defineProps({
  title: { type: String, default: '' },
  style: { type: String, default: 'grid' },
  // ... toutes les props du schéma
})
</script>
```

**Règles Back.vue :**
- Affiche un aperçu du rendu, pas un formulaire d'édition
- L'édition des props est gérée par PropsEditor.vue (générique, lit le schéma)
- Props identiques à Front.vue — même noms, mêmes types
- Pas d'appels API dans Back.vue

---

## Composant Front.vue (front-office)

```vue
<!-- blocks/core/MonBloc/Front.vue -->
<template>
  <section class="mon-bloc">
    <h2 v-if="title">{{ title }}</h2>
    <!-- rendu final -->
  </section>
</template>

<script setup>
defineProps({
  title: { type: String, default: '' },
  style: { type: String, default: 'grid' },
  // ... toutes les props du schéma
})
</script>

<style scoped>
/* CSS scopé uniquement — pas de classes globales */
.mon-bloc { /* ... */ }
</style>
```

**Règles Front.vue :**
- Aucune logique d'édition, aucun état Quasar
- CSS scopé — ne pas polluer le CSS global
- Accessible : utiliser les balises sémantiques appropriées
- Props identiques à Back.vue

---

## Enregistrement dans index.js

```js
// blocks/index.js
import MonBlocBack  from './core/MonBloc/Back.vue'
import MonBlocFront from './core/MonBloc/Front.vue'

export const BlockRegistry = {
  // ... blocs existants ...

  'mon-bloc': {
    back:  MonBlocBack,
    front: MonBlocFront,
  },
}

// Helpers utilisés par le builder et le renderer
export const getBackComponent  = (type) => BlockRegistry[type]?.back
export const getFrontComponent = (type) => BlockRegistry[type]?.front
export const getBlockTypes     = () => Object.keys(BlockRegistry)
```

---

## Blocs existants

### Blocs génériques (core/)

| Type | Label | Catégorie |
|------|-------|-----------|
| `hero` | Hero | content |
| `text` | Texte riche | content |
| `image` | Image | media |
| `gallery` | Galerie | media |
| `button` | Bouton CTA | content |
| `divider` | Séparateur | content |
| `columns` | Colonnes | content |

### Blocs métier (metier/)

| Type | Label | Catégorie |
|------|-------|-----------|
| `property-list` | Liste de biens | metier |
| `property-card` | Carte d'un bien | metier |
| `booking-form` | Formulaire réservation | metier |
| `availability-calendar` | Calendrier disponibilités | metier |
| `map` | Carte géographique | metier |
| `reviews` | Avis clients | metier |
| `contact-form` | Formulaire contact | metier |

---

## Checklist — Nouveau bloc

- [ ] Schéma ajouté dans `blocks/schema.js`
- [ ] Dossier `blocks/[core|metier]/NomBloc/` créé
- [ ] `Back.vue` créé avec aperçu
- [ ] `Front.vue` créé avec rendu final
- [ ] Props identiques dans Back.vue et Front.vue
- [ ] Bloc enregistré dans `blocks/index.js`
- [ ] Le type (kebab-case) est identique dans schema.js et index.js
