# 🌐 WB-Onboard - Website Builder Plugin

## 🚀 Getting Started

### 📋 Prerequisites

- Node.js
- npm

### 💻 Installation

1. Clone the repository
2. add the plugin in the `wp-content/plugins/` folder
3. Install dependencies:

```bash
npm install
```

3. Start the development server:

```bash
npm run start
```

## 📁 Project Structure

The project follows a feature-based architecture:

```
src/
├── components/         # Shared/reusable components
│   ├── inputs/        # Form input components
│   ├── service-handler/
│   └── ...
├── features/          # Feature-specific modules
│   ├── context/       # Global context and state management
│   ├── form/         # Form-related features
│   ├── navigation/   # Navigation components
│   └── steps/        # Step-based form components / you can find the page components here
│
└── App.js            # Main application component
```

## ⚡ Signal System

The project uses @preact/signals-react for state management. Key signals include:

### 📊 formData Signal

Global signal for managing form data across the application. Located in `src/features/context/TOD.FormulaireData.js`.

### ✅ stepValidator Signal

Manages form validation between steps. Key features:

- Each step component can set its own validation function
- Validation functions are chained together
- Automatically cleans up when switching steps
- Used in conjunction with ErrorHandling component for field-level validation

Example usage:

```javascript
// In a step component
useEffect(() => {
  stepValidator.value.fn = validateForm;
  return () => {
    stepValidator.value.fn = () => true;
  };
}, []);
```

## 📝 Form Steps

The application follows a multi-step form process:

1. Welcome
2. General Information
3. Services
4. Home Page

The idee its if you want to add a new step you need to add it in the `TOD.meta.steps.js` file.

Each step is defined in `src/features/steps/meta-data/TOD.meta.steps.js` and includes:

- Unique ID
- Title
- Timeline title
- Associated component

## ✨ Form Validation

Form validation is handled at two levels:

1. 🔍 Field-level validation using the ErrorHandling component
2. 🔒 Step-level validation using the stepValidator signal

The ErrorHandling component (`src/components/ErrorHandling/ErrorHandling.js`) provides:

- Real-time validation
- Error message display
- Integration with the stepValidator signal

## Section Form Pattern Guide

### 1. File Structure

```
src/features/form/yourSectionName/
├── TOD.YourSection.jsx
└── TOD.YourSection.css
```

### 2. Component Structure

#### Basic Component Setup

```javascript
import React from "react";
import { formData } from "../../context/TOD.FormulaireData";
import TODToggle from "../../../components/inputs/toggle/TOD.Toggle";
import "./TOD.YourSection.css";

const YourSection = ({ pageName }) => {
  // Component code here
};

YourSection.type = "your-section-type";
```

#### Required Methods

1. **handleChange**: Updates section data in the global store

```javascript
const handleChange = (field, value) => {
  formData.value = {
    ...formData.value,
    [pageName]: {
      ...formData.value[pageName],
      sections: formData.value[pageName].sections.map((section) =>
        section.type === YourSection.type
          ? { ...section, data: { ...section.data, [field]: value } }
          : section
      ),
    },
  };
};
```

2. **getSection**: Retrieves current section data

```javascript
const getSection = () => {
  return formData.value[pageName].sections.find(
    (section) => section.type === YourSection.type
  );
};
```

3. **init**: Static method for section initialization

```javascript
YourSection.init = (pageName) => {
  const exists = formData.value[pageName].sections.some(
    (section) => section.type === YourSection.type
  );

  if (!exists) {
    const id = formData.value[pageName].sections.length;
    formData.value[pageName].sections.push({
      id,
      type: YourSection.type,
      data: {
        isVisible: true,
        // Your default data here
      },
    });
    formData.value[pageName].sectionsOrder.push(id);
  }
};
```

### 3. Standard Layout Structure

```jsx
return (
  <div
    className={`your-section ${
      !section.data.isVisible ? "section-hidden" : ""
    }`}
  >
    {/* Header */}
    <div className="form-layout-header">
      <div className="form-layout-title">
        <h3>Your Section Title</h3>
        <p>Your section description</p>
      </div>
      <div className="form-layout-options">
        <TODToggle
          value={section.data.isVisible ?? true}
          onChange={(value) => handleChange("isVisible", value)}
          label="Show this section?"
        />
      </div>
    </div>

    {/* Content */}
    {section.data.isVisible && (
      <div className="form-layout-content">{/* Your form fields here */}</div>
    )}
  </div>
);
```

### 4. CSS Structure

```css
.your-section {
  background-color: var(--color-gray-15);
  border-radius: 8px;
  margin-bottom: 20px;
  transition: opacity 0.3s ease;
  overflow: hidden;
}

.your-section.section-hidden {
  opacity: 0.6;
}

/* Standard layout styles */
.your-section .form-layout-header {
  /* ... */
}
.your-section .form-layout-content {
  /* ... */
}
.your-section .form-group {
  /* ... */
}
```

### 5. Usage in Parent Component

```javascript
import YourSection from "./yourSection/TOD.YourSection";

const forms = [YourSection /* other sections... */];
<PageSectionManager forms={forms} pageName="pageName" />;
```

This pattern ensures consistency across all section forms and makes them work seamlessly with the `PageSectionManager`.

### Ajouter des icônes à IconSelect

Pour ajouter de nouvelles icônes au composant IconSelect :

1. Créer un nouveau composant d'icône dans `src/components/icons/` :

```jsx
export const NewIcon = () => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
  >
    // ... path de l'icône ...
  </svg>
);
```

2. Exporter l'icône dans `src/components/icons/index.jsx` :

```jsx
export { NewIcon } from "./newIcon";
```

3. Ajouter l'icône à la liste des icônes dans `src/components/inputs/icon-select/TOD.IconSelect.jsx` :

```jsx
const icons = [
  { id: "new-icon", name: "New Icon", component: NewIcon },
  // ... autres icônes
];
```

4. Pour limiter les icônes disponibles dans un IconSelect spécifique, vous pouvez utiliser le prop `icons_spec` :

```jsx
<IconSelect
  value={value}
  onChange={onChange}
  icons_spec={[
    {
      label: "Facebook",
      value: "facebook",
      component: FacebookIcon,
    },
    // ... autres icônes spécifiques
  ]}
/>
```

Si `icons_spec` n'est pas fourni, le composant affichera toutes les icônes disponibles dans `index.jsx`.

Les composants qui utilisent IconSelect :

- BookingStep
- InformationSection
- TestimonialSection
- ReviewContactSection
- WhyChooseSection
