02/01/26 - 13h

branche_01062025
Cherif 2026-01-02 17:14:24 +00:00
parent 2c6893982f
commit 1e6205b232
41 changed files with 4556 additions and 420 deletions

View File

@ -1,4 +1,4 @@
/* latin-ext */
@ -208,7 +208,7 @@
body {
background-color: white;
font-family: Arial;
font-family: "DM Sans", ui-sans-serif, system-ui, "-apple-system", "Segoe UI", "Roboto", "Arial", "Apple Color Emoji","Segoe UI Emoji";
text-align: center;
}
}

View File

@ -83,6 +83,10 @@ import img_loading_spin from "./mysy_img/mysy_spin_loading.gif";
function App() {
const New_Marktplace_2026 = lazy(() => import("./pages/marketplace_2026"));
const New_Detailled_Class_2026 = lazy(() => import("./pages/detailled_class_2026"));
const New_Landing_Page_2026 = lazy(() => import("./pages/landing_page_2026"));
const New_Marktplace_2025 = lazy(() => import("./pages/new_p_marketplace_2025"));
const New_Test_Header_Footer_2025 = lazy(() => import("./pages/new_p_test_header_footer_2025"));
const Jmjformation_catalogue = lazy(() => import("./pages/jmjformation_catalogue_public"));
@ -141,7 +145,7 @@ function App() {
const AddArticle = lazy(() => import("./pages/addarticle"));
const RechecheArticles = lazy(() => import("./pages/recherchearticles"));
const PartnerLogin1 = lazy(() => import("./pages/partnerlogin1"));
const PartnerLogin0 = lazy(() => import("./pages/partnerlogin0"));
const PartnerLogin0 = lazy(() => import("./pages/partnerlogin0"));
const PartnerLogin = lazy(() => import("./pages/partnerlogin"));
const CreateAccount = lazy(() => import("./pages/createaccount"));
const Partner = lazy(() => import("./pages/partner"));
@ -342,6 +346,10 @@ function App() {
<Route path="/jmjcatalogue" exact component={Jmjformation_catalogue} />
{/* Debut Migration */}
<Route path="/marketplace_26" exact component={New_Marktplace_2026} />
<Route path="/detailled_class_26" exact component={New_Detailled_Class_2026} />
<Route path="/landing_page_26" exact component={New_Landing_Page_2026} />
<Route path="/Partner/:action/:orderid/:packs" exact component={Partner} />
<Route path="/Partner/:action/:orderid" exact component={Partner} />
<Route path="/Partner/:action" exact component={Partner} />

View File

@ -403,12 +403,12 @@ function Account() {
<div className="div_mobile">
<div>
<h1 className="h1_transparent">Connexion MySy Training Technology </h1>
</div>
<div>
<div className="div_gauche">
<div class="main">
<nav class="sidebar">
<div>
<div>
<img class="img-responsive img_user" src={userimgprofil} align="center" alt="MySy Training profile image" />
@ -420,175 +420,171 @@ function Account() {
{isSelected && <div className="nonlable">
<Button variant="outlined" onClick={sendImage} >Enregistrer</Button>
</div>}
</div>
<div className="nom_prenom"> {username && <b> {username} </b>}
<div className="nom_prenom" style={{ color: 'white', paddingLeft:'10px', paddingRight:'10px' }}> {username && <b> {username} </b>}
{!username && <b> xxxx </b>} </div>
<hr className="my_hr" />
{/** Menu pour un utilisateur de type 'user'. Exemple, l'intranet du client d'un client */}
{connected_user_data && connected_user_data.type &&
String(connected_user_data.type) === "user" &&
<div>
{String(menu) !== "affichage" && <div className="sousmenu" onClick={displayPersoInfo}> INFORMATIONS PERSONNELLES</div>}
{String(menu) === "affichage" && <div className="sousmenu sousmenu_selected" onClick={displayPersoInfo}> INFORMATIONS PERSONNELLES</div>}
<hr className="my_hr" />
{/*{String(menu) !== "affichage" && <div className="sousmenu" onClick={"displayProfil_Facture"}> CATALOGUE</div>}
{String(menu) === "affichage" && <div className="sousmenu sousmenu_selected" onClick={"displayProfil_Facture"}> CATALOGUE</div>}
<hr className="my_hr" />*/}
{String(menu) !== "mes_stagiaires" && <div className="sousmenu" onClick={displayProfil_Stagiaires}> APPRENANTS</div>}
{String(menu) === "mes_stagiaires" && <div className="sousmenu sousmenu_selected" onClick={displayProfil_Stagiaires}> APPRENANTS</div>}
<hr className="my_hr" />
{String(menu) !== "mes_conventions" && <div className="sousmenu" onClick={displayProfil_Convention}> CONVENTIONS </div>}
{String(menu) === "mes_conventions" && <div className="sousmenu sousmenu_selected" onClick={displayProfil_Convention}> CONVENTIONS </div>}
<hr className="my_hr" />
{String(menu) !== "mes_convocations" && <div className="sousmenu" onClick={displayProfil_Convocation}> CONVOCATIONS </div>}
{String(menu) === "mes_convocations" && <div className="sousmenu sousmenu_selected" onClick={displayProfil_Convocation}> CONVOCATIONS </div>}
<hr className="my_hr" />
{String(menu) !== "mes_attestations" && <div className="sousmenu" onClick={displayProfil_Attestation}> ATTESTATIONS </div>}
{String(menu) === "mes_attestations" && <div className="sousmenu sousmenu_selected" onClick={displayProfil_Attestation}> ATTESTATIONS </div>}
<hr className="my_hr" />
{String(menu) !== "mes_devis" && <div className="sousmenu" onClick={displayProfil_Devis}> DEVIS</div>}
{String(menu) === "mes_devis" && <div className="sousmenu sousmenu_selected" onClick={displayProfil_Devis}> DEVIS</div>}
<hr className="my_hr" />
{String(menu) !== "mes_factures" && <div className="sousmenu" onClick={displayProfil_Facture}> FACTURES</div>}
{String(menu) === "mes_factures" && <div className="sousmenu sousmenu_selected" onClick={displayProfil_Facture}> FACTURES</div>}
<hr className="my_hr" />
{String(menu) !== "modules_mes_documents" && <div className="sousmenu" onClick={displayProfil_Modules_Mes_Documents}> TOUS LES DOCUMENTS</div>}
{String(menu) === "modules_mes_documents" && <div className="sousmenu sousmenu_selected" onClick={displayProfil_Modules_Mes_Documents}> TOUS LES DOCUMENTS</div>}
<hr className="my_hr" />
{/*<div className="sousmenu" onClick={deletemyaccount}> SUPPRIMER MON COMPTE</div>
<hr className="my_hr" />*/}
</div>}
{/** Menu pour un utilisateur NON type 'user' exemple un apprenant */}
{/*connected_user_data && connected_user_data.type &&
String(connected_user_data.type) !== "student" &&
<div>
<div className="sousmenu" onClick={displayPersoInfo}> INFORMATIONS PERSONNELLES</div>
<hr className="my_hr" />
<div className="sousmenu" onClick={displayProfil_Objectif}> PROFILS & OBJECTIFS</div>
<hr className="my_hr" />
<div className="sousmenu" onClick={"displayProfil_Objectif"}> MES DOCUMENTS</div>
<hr className="my_hr" />
<div className="sousmenu" onClick={displayProfil_Modules_Mes_Documents}> MODULE TOUS DOCUMENTS</div>
<hr className="my_hr" />
<div className="sousmenu" onClick={displayProfil_Facture}> MES FACTURES</div>
<hr className="my_hr" />
</div>*/}
</div>
<div className="div_droite" style={{ border: 'none' }}>
{String(firstConnexion) === "1" &&
<div className="div_droite firstConnexion">
<div className="firstConnexion_text">
<b>Cher Utilisateur, c'est votre première connexion, </b> <br /> &nbsp;<br />
Nous sommes ravis de vous accueillir. Nous vous invitons à modifier votre mot de passe à partir du menu <i>"MES INFORMATIONS"</i> ==&gt; Pavé <i>"SECURITE"</i> puis <i>"MODIFIER"</i> <br /><br />
<Button onClick={(e) => setfirstConnexion()} className="firstConnexion_bton"> &nbsp; &nbsp;<FaHandPointRight /> &nbsp; Fermer</Button><br />
&nbsp; <br /> Merci.
</div>
<ul style={{ paddingLeft: '10px' }}>
<li class="active"> {String(menu) !== "affichage" && <div className="sousmenu" onClick={displayPersoInfo}> MES INFORMATIONS </div>}
{String(menu) === "affichage" && <div className="sousmenu sousmenu_selected" onClick={displayPersoInfo}> MES INFORMATIONS </div>}
<hr className="my_hr" /></li>
<li style={{ textAlign: 'left' }}> {String(menu) !== "mes_stagiaires" && <div className="sousmenu" onClick={displayProfil_Stagiaires}> APPRENANTS</div>}
{String(menu) === "mes_stagiaires" && <div className="sousmenu sousmenu_selected" onClick={displayProfil_Stagiaires}> APPRENANTS</div>}
<hr className="my_hr" /></li>
<li style={{ textAlign: 'left' }}> {String(menu) !== "mes_conventions" && <div className="sousmenu" onClick={displayProfil_Convention}> CONVENTIONS </div>}
{String(menu) === "mes_conventions" && <div className="sousmenu sousmenu_selected" onClick={displayProfil_Convention}> CONVENTIONS </div>}
<hr className="my_hr" />
</li>
<li style={{ textAlign: 'left' }}> {String(menu) !== "mes_convocations" && <div className="sousmenu" onClick={displayProfil_Convocation}> CONVOCATIONS </div>}
{String(menu) === "mes_convocations" && <div className="sousmenu sousmenu_selected" onClick={displayProfil_Convocation}> CONVOCATIONS </div>}
<hr className="my_hr" />
</li>
<li style={{ textAlign: 'left' }}>
{String(menu) !== "mes_attestations" && <div className="sousmenu" onClick={displayProfil_Attestation}> ATTESTATIONS </div>}
{String(menu) === "mes_attestations" && <div className="sousmenu sousmenu_selected" onClick={displayProfil_Attestation}> ATTESTATIONS </div>}
<hr className="my_hr" />
</div>}
{String(myApiResponse) === String("true") && <div className="okUpdateData">
{result}
</li>
<li style={{ textAlign: 'left' }}>
{String(menu) !== "mes_devis" && <div className="sousmenu" onClick={displayProfil_Devis}> DEVIS</div>}
{String(menu) === "mes_devis" && <div className="sousmenu sousmenu_selected" onClick={displayProfil_Devis}> DEVIS</div>}
<hr className="my_hr" />
</li>
<li style={{ textAlign: 'left' }}>
{String(menu) !== "mes_factures" && <div className="sousmenu" onClick={displayProfil_Facture}> FACTURES</div>}
{String(menu) === "mes_factures" && <div className="sousmenu sousmenu_selected" onClick={displayProfil_Facture}> FACTURES</div>}
<hr className="my_hr" />
</li>
<li style={{ textAlign: 'left' }}>
{String(menu) !== "modules_mes_documents" && <div className="sousmenu" onClick={displayProfil_Modules_Mes_Documents}> TOUS LES DOCUMENTS</div>}
{String(menu) === "modules_mes_documents" && <div className="sousmenu sousmenu_selected" onClick={displayProfil_Modules_Mes_Documents}> TOUS LES DOCUMENTS</div>}
<hr className="my_hr" />
</li>
<li style={{ textAlign: 'left' }}>
{String(menu) !== "mes_factures" && <div className="sousmenu" onClick={displayProfil_Facture}> FACTURES</div>}
{String(menu) === "mes_factures" && <div className="sousmenu sousmenu_selected" onClick={displayProfil_Facture}> FACTURES</div>}
<hr className="my_hr" />
</li>
</ul>
</nav>
<div style={{ width: '100%' }}>
{String(firstConnexion) === "1" &&
<div className="div_droite firstConnexion">
<div className="firstConnexion_text">
<b>Cher Utilisateur, c'est votre première connexion, </b> <br /> &nbsp;<br />
Nous sommes ravis de vous accueillir. Nous vous invitons à modifier votre mot de passe à partir du menu <i>"MES INFORMATIONS"</i> ==&gt; Pavé <i>"SECURITE"</i> puis <i>"MODIFIER"</i> <br /><br />
<Button onClick={(e) => setfirstConnexion()} className="firstConnexion_bton"> &nbsp; &nbsp;<FaHandPointRight /> &nbsp; Fermer</Button><br />
&nbsp; <br /> Merci.
</div>
</div>}
{String(myApiResponse) !== String("true") && <div className="koUpdateData">
{result}
{String(myApiResponse) === String("true") && <div className="okUpdateData">
{result}
</div>}
</div>}
{String(myApiResponse) !== String("true") && <div className="koUpdateData">
{result}
{String(menu) === String("mes_factures") && connected_user_data && connected_user_data.partner_owner_recid &&
connected_user_data.partner_client_id &&
<Intranet_Factures_Client partner_client_id={connected_user_data.partner_client_id}
partner_owner_recid={connected_user_data.partner_owner_recid}
my_title={"MES FACTURES"}
type_document={"devis"}
type_user_connected={"user_account"}
filter_all_document={"0"}
/>}
</div>}
{String(menu) === String("mes_devis") && connected_user_data && connected_user_data.partner_owner_recid &&
connected_user_data.partner_client_id &&
<Intranet_Commande_Devis
partner_client_id={connected_user_data.partner_client_id}
partner_owner_recid={""}
my_title={"MES DEVIS"}
type_document={"devis"}
type_user_connected={"user_account"}
filter_all_document={"0"}
/>}
{String(menu) === String("mes_factures") && connected_user_data && connected_user_data.partner_owner_recid &&
connected_user_data.partner_client_id &&
<Intranet_Factures_Client partner_client_id={connected_user_data.partner_client_id}
partner_owner_recid={connected_user_data.partner_owner_recid}
my_title={"MES FACTURES"}
type_document={"devis"}
type_user_connected={"user_account"}
filter_all_document={"0"}
/>}
{String(menu) === String("mes_devis") && connected_user_data && connected_user_data.partner_owner_recid &&
connected_user_data.partner_client_id &&
<Intranet_Commande_Devis
partner_client_id={connected_user_data.partner_client_id}
partner_owner_recid={""}
my_title={"MES DEVIS"}
type_document={"devis"}
type_user_connected={"user_account"}
filter_all_document={"0"}
/>}
{String(menu) === String("modules_mes_documents") && connected_user_data && connected_user_data.partner_owner_recid &&
connected_user_data.partner_client_id &&
<Modules_Mes_Documents
partner_client_id={connected_user_data.partner_client_id}
partner_owner_recid={""}
my_title={"Gestion Documentaire"}
type_user_connected={"user_account"}
type_document={"all"}
/>}
{String(menu) === String("modules_mes_documents") && connected_user_data && connected_user_data.partner_owner_recid &&
connected_user_data.partner_client_id &&
<Modules_Mes_Documents
partner_client_id={connected_user_data.partner_client_id}
partner_owner_recid={""}
my_title={"Gestion Documentaire"}
type_user_connected={"user_account"}
type_document={"all"}
/>}
{String(menu) === String("mes_conventions") && connected_user_data && connected_user_data.partner_owner_recid &&
connected_user_data.partner_client_id &&
<Modules_Mes_Documents partner_client_id={connected_user_data.partner_client_id}
partner_owner_recid={""}
my_title={"MES CONVENTIONS"}
type_document={"convention"}
type_user_connected={"user_account"}
filter_all_document={"0"}
/>}
{String(menu) === String("mes_conventions") && connected_user_data && connected_user_data.partner_owner_recid &&
connected_user_data.partner_client_id &&
<Modules_Mes_Documents partner_client_id={connected_user_data.partner_client_id}
partner_owner_recid={""}
my_title={"MES CONVENTIONS"}
type_document={"convention"}
type_user_connected={"user_account"}
filter_all_document={"0"}
/>}
{String(menu) === String("mes_convocations") && connected_user_data && connected_user_data.partner_owner_recid &&
connected_user_data.partner_client_id &&
<Modules_Mes_Documents partner_client_id={connected_user_data.partner_client_id}
partner_owner_recid={""}
my_title={"MES CONVOCATIONS"}
type_document={"convocation"}
type_user_connected={"user_account"}
filter_all_document={"0"}
/>}
{String(menu) === String("mes_convocations") && connected_user_data && connected_user_data.partner_owner_recid &&
connected_user_data.partner_client_id &&
<Modules_Mes_Documents partner_client_id={connected_user_data.partner_client_id}
partner_owner_recid={""}
my_title={"MES CONVOCATIONS"}
type_document={"convocation"}
type_user_connected={"user_account"}
filter_all_document={"0"}
/>}
{String(menu) === String("mes_attestations") && connected_user_data && connected_user_data.partner_owner_recid &&
connected_user_data.partner_client_id &&
<Modules_Mes_Documents partner_client_id={connected_user_data.partner_client_id}
partner_owner_recid={""}
my_title={"MES ATTESTATIONS"}
type_document={"attestation"}
type_user_connected={"user_account"}
filter_all_document={"0"}
/>}
{String(menu) === String("mes_attestations") && connected_user_data && connected_user_data.partner_owner_recid &&
connected_user_data.partner_client_id &&
<Modules_Mes_Documents partner_client_id={connected_user_data.partner_client_id}
partner_owner_recid={""}
my_title={"MES ATTESTATIONS"}
type_document={"attestation"}
type_user_connected={"user_account"}
filter_all_document={"0"}
/>}
{String(menu) === String("mes_stagiaires") && connected_user_data && connected_user_data.partner_owner_recid &&
connected_user_data.partner_client_id &&
<Intranet_Mes_Stagiaires partner_client_id={connected_user_data.partner_client_id}
partner_owner_recid={connected_user_data.partner_owner_recid}
{String(menu) === String("mes_stagiaires") && connected_user_data && connected_user_data.partner_owner_recid &&
connected_user_data.partner_client_id &&
<Intranet_Mes_Stagiaires partner_client_id={connected_user_data.partner_client_id}
partner_owner_recid={connected_user_data.partner_owner_recid}
/>}
/>}
{String(menu) === String("mes_documents") && <Profil_Objectif />}
{String(menu) === String("mes_documents") && <Profil_Objectif />}
{String(menu) === String("affichage") && <UpdateUserInfo_Intranet_Client />}
</div>
{String(menu) === String("affichage") && <UpdateUserInfo_Intranet_Client />}
</div>
</div>
</div>
);

View File

@ -664,7 +664,7 @@ const AddClassManual = (props) => {
var node = {
"_id": local_id,
"id": localid,
"label": local_code+" - "+String(local_titre).substring(0, 20),
"label": local_code + " - " + String(local_titre).substring(0, 20),
"code": local_code,
"titre": local_titre,
"credit": local_credit,
@ -6483,12 +6483,12 @@ const AddClassManual = (props) => {
}
if (mylocaltraining.ATTESTATION_FORMATION_PDF) {
console.log(" ### eeee = ", mylocaltraining.ATTESTATION_FORMATION_PDF)
console.log(" ### eeee = ", mylocaltraining.ATTESTATION_FORMATION_PDF)
setselected_default_attestation_PDF(mylocaltraining.ATTESTATION_FORMATION_PDF);
}
if (mylocaltraining.ATTESTATION_FORMATION_MAIL) {
console.log(" ### iii = ", mylocaltraining.ATTESTATION_FORMATION_MAIL)
console.log(" ### iii = ", mylocaltraining.ATTESTATION_FORMATION_MAIL)
setselected_default_attestation_Email(mylocaltraining.ATTESTATION_FORMATION_MAIL);
}
@ -7296,7 +7296,6 @@ const AddClassManual = (props) => {
> <font style={{ "color": "#A52A2A" }}> Assistant IA </font> &nbsp;
<AutoFixHighOutlinedIcon style={{ "color": "#A52A2A", fontWeight: "700" }} />
</Button>
{String(props.mytrainingclass.ref).trim() !== "" &&
<Button variant="outlined" onClick={submenu_documents} className="detail_class_submenu" id='documents' name='documents'>Documents </Button>}
@ -7310,6 +7309,10 @@ const AddClassManual = (props) => {
<Button variant="outlined" onClick={submenu_unite_enseignement} className="detail_class_submenu" id='unite_enseignement' name='unite_enseignement'>Unite Enseign. </Button>
{String(props.mytrainingclass.ref).trim() !== "" && <Button variant="outlined" onClick={submenu_piece_jointe}
className="detail_class_submenu" id='piece_jointe' name='piece_jointe'>Pièces Jointes </Button>}
{String(props.mytrainingclass.ref).trim() !== "" &&
<Button variant="outlined" onClick={submenu_documents} className="detail_class_submenu" id='documents' name='documents'>Documents </Button>}
</div>}
{submenu && String(submenu) === "unite_enseignement" &&
@ -7660,7 +7663,7 @@ const AddClassManual = (props) => {
</div>
</div>
{String(props.ispending) === String("0") && <div className="parter_div_filtrer_row" style={{marginTop:'2rem', marginBottom:'3rem'}}>
{String(props.ispending) === String("0") && <div className="parter_div_filtrer_row" style={{ marginTop: '2rem', marginBottom: '3rem' }}>
{(String(datamodification) === String("1") || String(editor_tochange) === String("1")) && <div className="parter_div_filtrer_row_gauche" >
@ -8569,7 +8572,7 @@ const AddClassManual = (props) => {
<div class="separator">
<nav className="separator_label">
Champs spécifiques </nav>
</div>}
</div>}
<div style={{ width: '100%', float: 'left', }}>
@ -10579,7 +10582,7 @@ const AddClassManual = (props) => {
</nav>}
{String(selected_statistic_question_type) === "Moyenne" &&
<nav style={{marginBottom:"1rem"}}>
<nav style={{ marginBottom: "1rem" }}>
Somme totale d'enquêtes sur la période : {Global_Getall_Qry_Survey_Data_result_JSON['global_somme_question_response']} <br />
Moyenne Globale sur la période : {Global_Getall_Qry_Survey_Data_result_JSON['global_moyenne_question_response']} <br />
</nav>}

View File

@ -0,0 +1,326 @@
import React from "react";
import FilterBar from "./marketplace_2026/FilterBar";
import CourseCard from "./marketplace_2026/CourseCard";
import CourseCardSkeleton from "./marketplace_2026/CourseCardSkeleton";
import "./marketplace_2026/marketplace.css";
import Badge from "./marketplace_2026/Badge";
import Button from "./marketplace_2026/Button";
import { Card, CardBody } from "./marketplace_2026/Card";
import { AccordionItem } from "./marketplace_2026/Accordion";
//import "./courseDetail.css";
import { useRef, useState, useEffect } from "react";
import TextField from '@mui/material/TextField';
import 'react-confirm-alert/src/react-confirm-alert.css'; // Import css
import axios from "axios";
import { getCookie, setCookie } from 'react-use-cookie';
import { useHistory } from "react-router-dom";
import { DataGrid, GridToolbar, frFR } from '@mui/x-data-grid';
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
import 'react-tooltip/dist/react-tooltip.css'
import { Tooltip } from 'react-tooltip'
import Autocomplete from '@mui/material/Autocomplete';
import Popup from 'reactjs-popup';
import 'reactjs-popup/dist/index.css';
import img_loading_spin from "./../mysy_img/mysy_spin_loading.gif";
import fr from 'date-fns/locale/fr';
import { registerLocale } from 'react-datepicker';
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import { format } from 'date-fns'
import moment from "moment";
import InputAdornment from '@mui/material/InputAdornment';
import { AiFillCloseCircle } from "react-icons/ai";
import Box from '@mui/material/Box';
import { CiTrash } from "react-icons/ci";
import { MdAddCircleOutline, MdRemoveCircleOutline } from "react-icons/md";
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
import { IoAddCircleOutline } from "react-icons/io5";
import ToggleSwitch from "./ToggleSwitch";
import ToggleSwitch_v2_mysy from "./ToggleSwitch_v2_mysy";
import Module_Alert_Confirmation from "./Module_Alert_Confirmation";
import daygridPlugin from "@fullcalendar/daygrid";
import FullCalendar, { formatDate } from "@fullcalendar/react";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin from "@fullcalendar/interaction";
import allLocales from '@fullcalendar/core/locales-all'
import { makeStyles } from "@material-ui/core/styles";
import Paper from '@material-ui/core/Paper';
import Draggable from 'react-draggable';
import { IconButton } from '@material-ui/core';
import CancelPresentationIcon from '@mui/icons-material/CancelPresentation';
import Module_Historique_Action from "./Module_Historique_Action";
function PaperComponent(props) {
return (
<Draggable
handle="#draggable-dialog-title"
cancel={'[class*="MuiDialogContent-root"]'}
>
<Paper {...props} />
</Draggable>
);
}
const useStyles = makeStyles((theme) => ({
dialog: {
position: 'absolute',
// left: 10,
top: 400
},
paper: {
overflowY: 'unset',
},
customizedButton: {
position: 'absolute',
left: '98%',
top: '-3%',
backgroundColor: 'lightgray',
color: 'gray',
},
}));
const Detailled_Class_2026 = (props) => {
// Mock data — replace with API data (id from router, etc.)
const course = {
title: "Formation Prompt Engineering Niveau débutant",
subtitle: "Acquérir des compétences opérationnelles en intelligence artificielle",
tags: ["CPF", "Certifiante", "Distanciel"],
duration: "3 mois",
format: "Distanciel",
level: "Débutant",
funding: "CPF éligible",
price: "349 €",
nextSession: "15 juin 2025",
satisfaction: "92 %",
};
const syllabus = [
{
title: "Module 1 — Introduction au Prompt Engineering",
items: ["Concepts fondamentaux", "Premiers prompts", "Cas simples"],
},
{
title: "Module 2 — Prompts structurés",
items: ["Méthodologie", "Cas métiers", "Exercices pratiques"],
},
{
title: "Module 3 — Qualité, évaluation, itération",
items: ["Critères de qualité", "Tests & amélioration", "Bonnes pratiques"],
},
];
const similar = [
{
id: "s-1",
title: "Formation IA pour la productivité (niveau débutant)",
provider: "Organisme partenaire",
durationLabel: "12 mois",
tags: ["CPF", "Distanciel", "Nouveau"],
ratingLabel: "4,6 (80)",
coverUrl: "",
},
{
id: "s-2",
title: "Initiation à lIA générative en entreprise",
provider: "Organisme partenaire",
durationLabel: "4 semaines",
tags: ["Certifiante", "Hybride"],
ratingLabel: "4,7 (51)",
coverUrl: "",
},
{
id: "s-3",
title: "Automatisation des tâches avec lIA",
provider: "Organisme partenaire",
durationLabel: "6 semaines",
tags: ["CPF", "Distanciel"],
ratingLabel: "4,5 (39)",
coverUrl: "",
},
];
return (
<div className="detailled_class_2026">
<div className="container pagePadBottom">
<div className="breadcrumb">
<a href="#">Accueil</a> <span></span> <a href="#">Marketplace</a> <span></span>{" "}
<span>{course.title}</span>
</div>
{/* HERO */}
<div className="courseHero">
<div>
<h1 className="courseTitle">{course.title}</h1>
<p className="courseSubtitle">{course.subtitle}</p>
<div className="badgeRow">
{course.tags.map((t) => (
<Badge key={t} tone="info">{t}</Badge>
))}
</div>
<div className="metaGrid">
<div className="metaItem">
<span className="metaIcon"></span>
<span><strong>Durée :</strong> {course.duration}</span>
</div>
<div className="metaItem">
<span className="metaIcon">📍</span>
<span><strong>Format :</strong> {course.format}</span>
</div>
<div className="metaItem">
<span className="metaIcon">🎯</span>
<span><strong>Niveau :</strong> {course.level}</span>
</div>
<div className="metaItem">
<span className="metaIcon">💰</span>
<span><strong>Financement :</strong> {course.funding}</span>
</div>
</div>
</div>
</div>
<div className="courseLayout">
{/* LEFT */}
<div>
{/* Overview */}
<div className="section">
<h2 className="sectionTitle">Présentation de la formation</h2>
<div className="overviewGrid">
<div className="kBlock">
<h3>Ce que vous allez apprendre</h3>
<ul className="kList">
<li><span className="kTick"></span> Comprendre les bases du prompt engineering</li>
<li><span className="kTick"></span> Structurer des prompts efficaces</li>
<li><span className="kTick"></span> Utiliser lIA dans un contexte professionnel</li>
</ul>
</div>
<div className="kBlock">
<h3>Pourquoi cette formation est faite pour vous</h3>
<ul className="kList">
<li><span className="kTick"></span> Formation certifiante reconnue</li>
<li><span className="kTick"></span> Programme aligné sur les besoins métiers</li>
<li><span className="kTick"></span> Adaptée à la reconversion professionnelle</li>
</ul>
</div>
</div>
</div>
<hr className="hr" />
{/* Syllabus */}
<div className="section">
<h2 className="sectionTitle">Programme de la formation</h2>
{syllabus.map((m, idx) => (
<AccordionItem key={m.title} title={m.title} defaultOpen={idx < 2}>
<ul>
{m.items.map((it) => <li key={it}>{it}</li>)}
</ul>
</AccordionItem>
))}
</div>
<hr className="hr" />
{/* Provider / Compliance */}
<div className="section">
<h2 className="sectionTitle">Organisme & conformité</h2>
<div className="kBlock">
<h3>Organisme partenaire MYSA</h3>
<ul className="kList">
<li><span className="kTick"></span> Certifié Qualiopi</li>
<li><span className="kTick"></span> Référencé MYSA</li>
<li><span className="kTick"></span> Taux de satisfaction : {course.satisfaction}</li>
</ul>
</div>
</div>
<hr className="hr" />
{/* Similar */}
<div className="section">
<h2 className="sectionTitle">Formations similaires</h2>
<div className="similarGrid">
{similar.map((c) => (
<CourseCard
key={c.id}
course={c}
isFavorite={false}
onToggleFavorite={() => { }}
onView={() => { }}
/>
))}
</div>
</div>
</div>
{/* RIGHT (Sticky) */}
<div>
<Card className="asideCard">
<CardBody>
<div className="priceRow">
<div className="price">{course.price}</div>
<div className="priceSub">Financement CPF possible</div>
</div>
<Button className="asideCTA">Intégrer dans MYSY</Button>
<div className="secondaryActions">
<button className="linkBtn" type="button">Ajouter aux favoris</button>
<button className="linkBtn" type="button">Comparer</button>
</div>
<div className="asideBlock">
<div className="asideLabel">Prochaine session</div>
<div className="asideLine">
<span>📅 Démarrage</span>
<strong>{course.nextSession}</strong>
</div>
</div>
<div className="asideBlock">
<div className="asideLabel">Garanties</div>
<ul className="asideProof">
<li><span className="kTick"></span> Formation certifiante</li>
<li><span className="kTick"></span> Organisme référencé</li>
<li><span className="kTick"></span> Conforme Qualiopi</li>
</ul>
</div>
</CardBody>
</Card>
</div>
</div>
{/* Mobile sticky CTA */}
<div className="mobileSticky">
<div className="mobileSticky__price">
<strong>{course.price}</strong>
<span>CPF possible</span>
</div>
<Button>Intégrer dans MYSY</Button>
</div>
</div>
</div>
);
}
export default Detailled_Class_2026;

File diff suppressed because it is too large Load Diff

View File

@ -31,7 +31,7 @@ function HebergementLms(props) {
const [menu, setmenu] = useState("default");
const scrollDiv = useRef(null);
// recuperation et gestion du token utilisateur
@ -252,6 +252,14 @@ function HebergementLms(props) {
var _URL = window.URL || window.webkitURL;
var file, img;
var img_height, img_width;
/*
21/12/2025 : important :
Pour donner de la souplesse, on va prendre des marges (techniquement) par rapport aux dimensions recommandées
on va accepter les dimensions suivantes :
largeur : de 50px a 300 px
hauteur : de 50 px à 300px
*/
if ((file = event.target.files[0])) {
img = new Image();
@ -262,8 +270,8 @@ function HebergementLms(props) {
_URL.revokeObjectURL(objectUrl);
// console.log(" img_width = ", img_width, " img_height = ", img_height)
if (parseFloat(img_width) > 130 && parseFloat(img_width) < 260 &&
parseFloat(img_height) > 60 && parseFloat(img_height) < 150) {
if (parseFloat(img_width) > 50 && parseFloat(img_width) < 300 &&
parseFloat(img_height) > 50 && parseFloat(img_height) < 300) {
@ -513,6 +521,15 @@ function HebergementLms(props) {
return;
}
/*
21/12/2025 : important :
Pour donner de la souplesse, on va prendre des marges (techniquement) par rapport aux dimensions recommandées
on va accepter les dimensions suivantes :
largeur : de 1200px a 200 px
hauteur : de 100 px à 500px
*/
setLoading(true);
var _URL = window.URL || window.webkitURL;
@ -527,8 +544,8 @@ function HebergementLms(props) {
img_width = this.width;
//console.log(" img_width = ", img_width);
_URL.revokeObjectURL(objectUrl);
if (parseFloat(img_width) > 1500 && parseFloat(img_width) < 1930 &&
parseFloat(img_height) > 150 && parseFloat(img_height) < 250) {
if (parseFloat(img_width) > 1200 && parseFloat(img_width) < 2000 &&
parseFloat(img_height) > 150 && parseFloat(img_height) < 500) {
//console.log(" img_height est = ", img_height, " < à 1500 ");
@ -920,7 +937,7 @@ Le nom du fichier ne contient que des caractères alphanumériques </i>">
<div className="div_row">
<div className="div_row" style={{ "border": "None" }}>
&nbsp;
</div>
</div>
{String(props.check_user_acces_right("lms", "write")) === "1" && <div className="div_row" style={{ "border": "None", "color": "orange", "textAlign": "center" }}>
<div className="div_row" style={{ "border": "None" }}>
&nbsp;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,192 @@
import React from "react";
import FilterBar from "./marketplace_2026/FilterBar";
import CourseCard from "./marketplace_2026/CourseCard";
import CourseCardSkeleton from "./marketplace_2026/CourseCardSkeleton";
import "./marketplace_2026/marketplace.css";
import { useRef, useState, useEffect } from "react";
import TextField from '@mui/material/TextField';
import 'react-confirm-alert/src/react-confirm-alert.css'; // Import css
import Button from '@mui/material/Button';
import axios from "axios";
import { getCookie, setCookie } from 'react-use-cookie';
import { useHistory } from "react-router-dom";
import { DataGrid, GridToolbar, frFR } from '@mui/x-data-grid';
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
import 'react-tooltip/dist/react-tooltip.css'
import { Tooltip } from 'react-tooltip'
import Autocomplete from '@mui/material/Autocomplete';
import Popup from 'reactjs-popup';
import 'reactjs-popup/dist/index.css';
import img_loading_spin from "./../mysy_img/mysy_spin_loading.gif";
import fr from 'date-fns/locale/fr';
import { registerLocale } from 'react-datepicker';
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import { format } from 'date-fns'
import moment from "moment";
import InputAdornment from '@mui/material/InputAdornment';
import { AiFillCloseCircle } from "react-icons/ai";
import Box from '@mui/material/Box';
import { CiTrash } from "react-icons/ci";
import { MdAddCircleOutline, MdRemoveCircleOutline } from "react-icons/md";
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
import { IoAddCircleOutline } from "react-icons/io5";
import ToggleSwitch from "./ToggleSwitch";
import ToggleSwitch_v2_mysy from "./ToggleSwitch_v2_mysy";
import Module_Alert_Confirmation from "./Module_Alert_Confirmation";
import daygridPlugin from "@fullcalendar/daygrid";
import FullCalendar, { formatDate } from "@fullcalendar/react";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin from "@fullcalendar/interaction";
import allLocales from '@fullcalendar/core/locales-all'
import { makeStyles } from "@material-ui/core/styles";
import Paper from '@material-ui/core/Paper';
import Draggable from 'react-draggable';
import { IconButton } from '@material-ui/core';
import CancelPresentationIcon from '@mui/icons-material/CancelPresentation';
import Module_Historique_Action from "./Module_Historique_Action";
function PaperComponent(props) {
return (
<Draggable
handle="#draggable-dialog-title"
cancel={'[class*="MuiDialogContent-root"]'}
>
<Paper {...props} />
</Draggable>
);
}
const useStyles = makeStyles((theme) => ({
dialog: {
position: 'absolute',
// left: 10,
top: 400
},
paper: {
overflowY: 'unset',
},
customizedButton: {
position: 'absolute',
left: '98%',
top: '-3%',
backgroundColor: 'lightgray',
color: 'gray',
},
}));
const MarketPlace_2026 = (props) => {
const initialFilters = {
q: "",
goal: "Tous",
format: "Tous",
duration: "Toutes",
funding: "Tous",
level: "Tous",
sort: "Pertinence",
};
const mockCourses = Array.from({ length: 12 }).map((_, i) => ({
id: `c-${i}`,
title: `Formation ${i + 1} — Intitulé clair et professionnel`,
provider: "Organisme partenaire",
durationLabel: "3 mois",
tags: ["CPF", "Certifiante", "Distanciel"],
ratingLabel: "4,7 (123)",
coverUrl: "",
}));
const [filters, setFilters] = React.useState(initialFilters);
const [loading, setLoading] = React.useState(false);
const [favorites, setFavorites] = React.useState({});
// Simulation chargement (remplace par API)
React.useEffect(() => {
setLoading(true);
const t = setTimeout(() => setLoading(false), 450);
return () => clearTimeout(t);
}, [filters]);
const onReset = () => setFilters(initialFilters);
const results = mockCourses; // TODO: appliquer filtres
const New_Option_Trie = [
{ "id": "Pertinence", "label": "Pertinence", "value": "Pertinence" },
{ "id": "Popularité", "label": "Popularité", "value": "Popularité" },
{ "id": "Nouveautés", "label": "Nouveautés", "value": "Nouveautés" },
{ "id": "", "label": "", "value": "" },
]
return (
<div className="marketplace_2026">
<div className="container">
<div className="marketHero">
<h1 className="h1">Marketplace de formations</h1>
<p className="p-muted">
Accédez aux meilleures formations certifiantes, filtrées selon vos objectifs professionnels.
</p>
</div>
<FilterBar
value={filters}
onChange={(patch) => setFilters((s) => ({ ...s, ...patch }))}
onReset={onReset}
/>
<div className="resultsRow" style={{ justifyContent: 'unset' }}>
<div className="resultsText">
{loading ? "Chargement…" : `${results.length} formations correspondent à vos critères`}
</div>
<div className="resultsText">
Trier parr
<select className="select" {...props}>
{New_Option_Trie.map((o) => (
<option key={o.value} value={o.value}>{o.label}</option>
))}
</select>
</div>
</div>
<div className="grid">
{loading
? Array.from({ length: 8 }).map((_, i) => <CourseCardSkeleton key={i} />)
: results.map((c) => (
<CourseCard
key={c.id}
course={c}
isFavorite={!!favorites[c.id]}
onToggleFavorite={(id) =>
setFavorites((f) => ({ ...f, [id]: !f[id] }))
}
onView={(id) => console.log("go to course", id)}
/>
))}
</div>
<div style={{ height: "40px" }} />
</div>
</div>
);
}
export default MarketPlace_2026;

View File

@ -10,13 +10,15 @@ import { useHistory } from "react-router-dom";
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
import ManageHistoryIcon from '@mui/icons-material/ManageHistory';
import 'react-tooltip/dist/react-tooltip.css'
import { Tooltip } from 'react-tooltip'
import fileDownload from 'js-file-download'
import Popup from 'reactjs-popup';
import 'reactjs-popup/dist/index.css';
import { FcCancel, FcApproval, FcAcceptDatabase, FcPrint } from "react-icons/fc";
import fr from 'date-fns/locale/fr';
import { registerLocale } from 'react-datepicker';
import DatePicker from "react-datepicker";
@ -43,10 +45,7 @@ import ToggleSwitch_v2_mysy from "./ToggleSwitch_v2_mysy";
import ToggleSwitch_v3_mysy from "./ToggleSwitch_v3_mysy";
import Autocomplete from '@mui/material/Autocomplete';
import FullCalendar, { formatDate } from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin from "@fullcalendar/interaction";
import { FcSearch } from "react-icons/fc";
import { Fab } from "@material-ui/core";
import {
@ -1611,7 +1610,7 @@ const Module_Editique = (props) => {
setGet_Class_Default_Document_id_api("false");
setGet_Class_Default_Document_id_message(res.data.message);
// alert(res.data.message);
// setdisplay_alert_mysy("1");
// setdisplay_alert_mysy("1");
//setalert_message(res.data.message);
//setalert_type("error");
@ -1626,6 +1625,17 @@ const Module_Editique = (props) => {
})
}
const [Dialog_Config_Doc_Relance_Setup_open, setDialog_Config_Doc_Relance_Setup_open] = React.useState(false);
const Dialog_Config_Doc_Relance_Setup_handleClose = () => {
//alert(" Utiliser le bouton 'fermer' ");
//setOpen(false);
};
const Dialog_Config_Relance_Setup_handleClose_buton = () => {
setDialog_Config_Doc_Relance_Setup_open(false);
};
return (
<div className="module_editique">
@ -1645,6 +1655,131 @@ const Module_Editique = (props) => {
{/*** FIN Affichage des messages d'alerte*/}
{/* Dialog pour gerer les Config_Doc_Relance_Setup */}
<Dialog
open={Dialog_Config_Doc_Relance_Setup_open}
className="displaypartnersession"
static
onClose={() => null}
PaperProps={{
className: classes.paper, // Apply the paper style
style: {
overflowY: 'unset',
position: 'absolute',
top: '5rem',
margin: "2px",
},
}}
hideBackdrop={true}
disableScrollLock
classes={{
paper: classes.dialog
}}
PaperComponent={PaperComponent}
aria-labelledby="draggable-dialog-title"
>
<DialogTitle style={{ cursor: 'move', fontFamily: "DM Sans" }} id="draggable-dialog-title">MySy Information</DialogTitle>
<DialogContent className="DialogContent_width" style={{ "minHeight": "5rem" }}>
<DialogContentText>
<div style={{ "textAlign": "left" }}>
p_doc_automatic_setup_courrier_template_type_document_ref_interne = {p_doc_automatic_setup_courrier_template_type_document_ref_interne} <br />
action_server_ref_interne_doc = {action_server_ref_interne_doc}
{String(p_doc_automatic_setup_courrier_template_type_document_ref_interne) !== action_server_ref_interne_doc &&
<nav>
Aucun traitement d'envoi automatique pour <b> {action_server_ref_interne_doc} </b> <br />
</nav>}
{String(p_doc_automatic_setup_courrier_template_type_document_ref_interne) === action_server_ref_interne_doc &&
<div className="div_row" style={{ "padding": "5px", "border": "None" }}>
Traitement Automatique : {p_doc_automatic_setup_nom_document} <br />
<nav>
<div className="session_caract_Dialog"> Document <br />
<TextField
sx={{ '& legend': { display: 'none' }, '& fieldset': { top: 0 } }}
required
name="nom_document"
id="nom_document"
InputLabelProps={{
shrink: true,
}}
disabled={false}
className="disabled_style"
value={p_doc_automatic_setup_nom_document}
style={{ background: '#ECEFF1' }}
/>
</div>
<div className="div_row" style={{ "border": "None" }}>
&nbsp;
</div>
{String(is_modified_doc_automatic_setup) === "1" && <div className="div_row" style={{ "border": "None", "color": "orange", "textAlign": "center" }}>
/!\ Pensez à enregistrer les modifications
</div>}
<div className="div_row" style={{ "border": "None" }}>
<div className="div_row_droite" style={{ "textAlign": 'right', 'marginRight': '15px' }}>
{String(edit_doc_automatic_setup) === "1" && <Button variant="contained" className="bton_edit"
onClick={(e) => {
setedit_doc_automatic_setup("1");
}
}>Editer
</Button>}
</div>
</div>
</nav>
</div>}
</div>
</DialogContentText>
</DialogContent>
<DialogActions>
<IconButton
// autoFocus
onClick={Dialog_Config_Relance_Setup_handleClose_buton}
color="primary"
className={classes.customizedButton}
>
<CancelPresentationIcon />
</IconButton>
<div className="div_row">
<div className="div_row_gauche">
&nbsp;
</div>
{String(is_modified_doc_automatic_setup) === "1" && <div className="div_row_droite" style={{ "textAlign": 'center' }}>
<Button onClick={"Update_Session_Automatic_Doc_Setup"} className="bton_enreg_dialog" >Enregistrer</Button>
</div>}
</div>
</DialogActions>
</Dialog>
{/* FIN Dialog pour gerer les Config_Doc_Relance_Setup */}
{/**** Dialog Pour les Droits d'acces **/}
<Dialog
@ -3328,9 +3463,6 @@ const Module_Editique = (props) => {
setDialog_FACTURATION_FORMATION_open(true);
}
}}>
{(JSON.parse(document).courrier_template_nom)}
</div>
@ -3412,6 +3544,26 @@ const Module_Editique = (props) => {
</nav>
))}
<div style={{ display: "inline-block", width: "15%", textAlign: "left", paddingLeft: "0.5rem", "float": "left", height: "2.5rem", }}>
r00 &nbsp; <ManageHistoryIcon style={{ marginTop: '10px', fontSize: '24px', cursor:'pointer' }}
onClick={(event) => {
if (String(write_access_automatic_document_setup) !== "1") {
setDialog_Access_Right_message("Vos droits ne sont pas suffisants pour accéder cette fonction");
setDialog_Acces_Right_open(true);
return;
}
setaction_server_nom_doc(String(JSON.parse(document).courrier_template_nom))
setaction_server_ref_interne_doc(String(JSON.parse(document).courrier_template_ref_interne))
setDialog_Config_Doc_Relance_Setup_open(true);
}}
/>
</div>
</div>}
@ -3539,6 +3691,7 @@ const Module_Editique = (props) => {
</a>
</div>
{String(read_access_automatic_document_setup) === "1" && Get_Given_Session_List_Automatic_Traitement_result && Get_Given_Session_List_Automatic_Traitement_result.map((x) => (
<nav>
{x.courrier_template_type_document_ref_interne === String(JSON.parse(document).courrier_template_ref_interne) &&
@ -3607,7 +3760,9 @@ const Module_Editique = (props) => {
</nav>
))}
<div style={{ display: "inline-block", width: "15%", textAlign: "left", paddingLeft: "0.5rem", "float": "left", height: "2.5rem", }}>
r01&nbsp; <ManageHistoryIcon style={{ marginTop: '10px', fontSize: '24px', cursor:'pointer' }} />
</div>
</div>}
@ -3800,6 +3955,9 @@ const Module_Editique = (props) => {
</nav>
))}
<div style={{ display: "inline-block", width: "15%", textAlign: "left", paddingLeft: "0.5rem", "float": "left", height: "2.5rem", }}>
r02&nbsp; <ManageHistoryIcon style={{ marginTop: '10px', fontSize: '24px' , cursor:'pointer'}} />
</div>
</div>}
@ -3896,7 +4054,9 @@ const Module_Editique = (props) => {
</nav>
))}
<div style={{ display: "inline-block", width: "15%", textAlign: "left", paddingLeft: "0.5rem", "float": "left", height: "2.5rem", }}>
r03&nbsp; <ManageHistoryIcon style={{ marginTop: '10px', fontSize: '24px', cursor:'pointer' }} />
</div>
</div>}
@ -4021,6 +4181,10 @@ const Module_Editique = (props) => {
</div>
<div style={{ display: "inline-block", width: "15%", textAlign: "left", paddingLeft: "0.5rem", "float": "left", height: "2.5rem", }}>
r04&nbsp; <ManageHistoryIcon style={{ marginTop: '10px', fontSize: '24px', cursor:'pointer' }} />
</div>
</div>}
</div>

View File

@ -25,7 +25,7 @@ import { format } from 'date-fns'
import moment from "moment";
import SendIcon from '@mui/icons-material/Send';
import axios from "axios";
import mysy_logo2 from "../mysy_img2/Logo_MySy.png"
import mysy_logo2 from "../mysy_img2/Logo_MySy.png"
import New_C_Header_2025_V2 from "./header_automatic_files/Header";

View File

@ -1948,7 +1948,7 @@ const Partner_Commande = (props) => {
if (point_config_tva.config_value) {
setpartner_taux_tva(point_config_tva.config_value);
// console.log(" GGG TVA PART = ", point_config_tva.config_value);
// console.log(" GGG TVA PART = ", point_config_tva.config_value);
}
} else {
@ -3078,11 +3078,11 @@ const Partner_Commande = (props) => {
// console.log(" GLOBAL #### partner_taux_tva = ", partner_taux_tva, " ### qty = ", qty, " ### unit_price = ", unit_price, " ### total_base1 = ", total_base1, " ### total_reduction = ", total_reduction, " ### reduct_value = ", reduct_value);
// console.log(" GLOBAL #### partner_taux_tva = ", partner_taux_tva, " ### qty = ", qty, " ### unit_price = ", unit_price, " ### total_base1 = ", total_base1, " ### total_reduction = ", total_reduction, " ### reduct_value = ", reduct_value);
const total_taux_tax_bef = parseFloat(String(partner_taux_tva)) / 100;
// console.log(" GLOBAL #### total_taux_tax_bef = ", total_taux_tax_bef);
// console.log(" GLOBAL #### total_taux_tax_bef = ", total_taux_tax_bef);
const total_taux_tax = 1 + total_taux_tax_bef;
@ -3309,7 +3309,7 @@ const Partner_Commande = (props) => {
setp_add_line_item_total_amount_ttc("");
setp_add_line_item_type_apprenant("");
// setpartner_taux_tva("20");
// setpartner_taux_tva("20");
setselected_order_line_id("");
@ -3720,7 +3720,7 @@ const Partner_Commande = (props) => {
//var reduct_type = p_add_line_item_type_reduction;
//console.log(" reduct_type = ", reduct_type);
// console.log(" p_add_line_item_type_reduction = ", p_add_line_item_type_reduction);
// console.log(" p_add_line_item_type_reduction = ", p_add_line_item_type_reduction);
if (String(p_add_line_item_type_reduction) === "fixe") {
console.log("fixe : p_add_line_item_reduction_value = ", reduct_value);
@ -3734,7 +3734,7 @@ const Partner_Commande = (props) => {
// console.log(" #### partner_taux_tva = ", partner_taux_tva, " ### qty = ", qty, " ### unit_price = ", unit_price, " ### total_base1 = ", total_base1, " ### total_reduction = ", total_reduction, " ### reduct_value = ", reduct_value);
// console.log(" #### partner_taux_tva = ", partner_taux_tva, " ### qty = ", qty, " ### unit_price = ", unit_price, " ### total_base1 = ", total_base1, " ### total_reduction = ", total_reduction, " ### reduct_value = ", reduct_value);
var montant_taxe_tva = ((total_base1 - total_reduction) * [parseFloat(String(partner_taux_tva)) / 100]).toFixed(2);
var montant_ttc = ((total_base1 - total_reduction) * (1 + [parseFloat(String(partner_taux_tva)) / 100])).toFixed(2); //(total_base2 + montant_taxe_tva).toFixed(2);
@ -3742,7 +3742,7 @@ const Partner_Commande = (props) => {
// 20/08/2024 - enlever la réduction du total ht
total_base1 = total_base1 - total_reduction;
// console.log(" #### montant_taxe_tva = ", montant_taxe_tva, " ### montant_ttc = ", montant_ttc);
// console.log(" #### montant_taxe_tva = ", montant_taxe_tva, " ### montant_ttc = ", montant_ttc);
setp_add_line_item_reduction_total_amount(String(total_reduction));
setp_add_line_item_total_amount_ht(String(total_base1));
@ -5699,6 +5699,8 @@ const Partner_Commande = (props) => {
position: 'absolute',
// top: '5rem',
margin: "2px",
maxWidth: 'unset',
width: '50rem'
},
}}
hideBackdrop={true}
@ -5848,147 +5850,193 @@ const Partner_Commande = (props) => {
</div>}
{String(p_detail_header_statut_label).toLowerCase() === "facturé" && <div className="session_caract_Dialog" > <b>Quantité </b>
<TextField
margin="dense"
id="ref_article_qty"
//label="Quantité"
//type="number"
fullWidth
//variant="standard"
value={p_add_line_item_qty}
disabled
type="text"
/>
</div>}
{String(p_detail_header_statut_label).toLowerCase() !== "facturé" && <div className="session_caract_Dialog" > <b> Quantité </b>
<TextField
required
margin="dense"
id="ref_article_qty"
//label="Quantité"
//type="number"
fullWidth
//variant="standard"
value={p_add_line_item_qty}
onChange={(e) => {
setp_add_line_item_qty(e.target.value);
Recalcul_Item_Amounts();
}
}
type="number"
/>
</div>}
{String(p_detail_header_statut_label).toLowerCase() !== "facturé" && <div className="session_caract_Dialog" > <b> Prix Unitaire </b>
<TextField
required
margin="dense"
id="ref_article_unit_price"
name="ref_article_unit_price"
//label="Prix Unitaire"
{String(p_detail_header_statut_label).toLowerCase() !== "facturé" &&
<div className="div_row" style={{ "width": "100%", }}>
fullWidth
//variant="standard"
value={p_add_line_item_price}
onChange={(e) => {
setp_add_line_item_price(e.target.value);
Recalcul_Item_Amounts();
}
}
type="number"
<div className="session_caract_Dialog" style={{ "textAlign": "left", "width": "50%", "height": "5rem", "float": "left" }}> <b> Quantité </b>
/>
</div>}
<TextField
required
margin="dense"
id="ref_article_qty"
//label="Quantité"
//type="number"
fullWidth
//variant="standard"
value={p_add_line_item_qty}
onChange={(e) => {
setp_add_line_item_qty(e.target.value);
Recalcul_Item_Amounts();
}
}
type="number"
{String(p_detail_header_statut_label).toLowerCase() === "facturé" && <div className="session_caract_Dialog" > <b> Prix Unitaire </b>
<TextField
/>
margin="dense"
id="ref_article_unit_price"
name="ref_article_unit_price"
//label="Prix Unitaire"
</div>
fullWidth
//variant="standard"
value={p_add_line_item_price}
disabled
type="text"
/>
</div>}
<div className="session_caract_Dialog" style={{ "textAlign": "left", "width": "50%", "height": "5rem", "float": "right" }} > <b> Prix Unitaire </b>
<TextField
required
margin="dense"
id="ref_article_unit_price"
name="ref_article_unit_price"
//label="Prix Unitaire"
<div className="session_caract_Dialog" > Taux TVA
<TextField
fullWidth
//variant="standard"
value={p_add_line_item_price}
onChange={(e) => {
setp_add_line_item_price(e.target.value);
Recalcul_Item_Amounts();
}
}
margin="dense"
id="ref_article_taux_tva"
name="ref_article_taux_tva"
//label="Prix Unitaire"
type="number"
fullWidth
//variant="standard"
value={partner_taux_tva}
/>
</div>
onChange={(e) => {
setpartner_taux_tva(e.target.value);
Recalcul_Item_Amounts();
}
}
</div>}
type="number"
/>
</div>
{String(p_detail_header_statut_label).toLowerCase() !== "facturé" && <div className="session_caract_Dialog" > Type apprenant
<Autocomplete
disablePortal
name="detail_type_apprenant"
id="detail_type_apprenant"
// className="disabled_style"
options={New_type_apprenant}
value={New_type_apprenant.filter((val) => val.value === String(p_add_line_item_type_apprenant))[0].label}
onChange={(event, value) => {
if (value && value.id) {
setp_add_line_item_type_apprenant(value.id);
} else {
setp_add_line_item_type_apprenant("");
}
}}
renderInput={(params) => <TextField {...params} label="" placeholder="Choisir une option"
inputProps={{ ...params.inputProps, style: { fontSize: 12, height: "1.4rem" } }}
{String(p_detail_header_statut_label).toLowerCase() === "facturé" &&
<div className="div_row" style={{ "width": "100%", }}>
<div className="session_caract_Dialog" style={{ "textAlign": "left", "width": "50%", "height": "5rem", "float": "left" }}> <b>Quantité </b>
<TextField
margin="dense"
id="ref_article_qty"
//label="Quantité"
//type="number"
fullWidth
//variant="standard"
value={p_add_line_item_qty}
disabled
type="text"
/>
</div>
<div className="session_caract_Dialog" style={{ "textAlign": "left", "width": "50%", "height": "5rem", "float": "right" }} > <b> Prix Unitaire </b>
<TextField
margin="dense"
id="ref_article_unit_price"
name="ref_article_unit_price"
//label="Prix Unitaire"
fullWidth
//variant="standard"
value={p_add_line_item_price}
disabled
type="text"
/>
</div>
</div>}
{String(p_detail_header_statut_label).toLowerCase() !== "facturé" &&
<div className="div_row" style={{ "width": "100%", }}>
<div className="session_caract_Dialog" style={{ "textAlign": "left", "width": "50%", "height": "5rem", "float": "left" }}> Taux TVA
<TextField
margin="dense"
id="ref_article_taux_tva"
name="ref_article_taux_tva"
//label="Prix Unitaire"
fullWidth
//variant="standard"
value={partner_taux_tva}
onChange={(e) => {
setpartner_taux_tva(e.target.value);
Recalcul_Item_Amounts();
}
}
type="number"
/>
</div>
<div className="session_caract_Dialog" style={{ "textAlign": "left", "width": "50%", "height": "5rem", "float": "right" }}> Type apprenant
<Autocomplete
disablePortal
name="detail_type_apprenant"
id="detail_type_apprenant"
// className="disabled_style"
options={New_type_apprenant}
value={New_type_apprenant.filter((val) => val.value === String(p_add_line_item_type_apprenant))[0].label}
onChange={(event, value) => {
if (value && value.id) {
setp_add_line_item_type_apprenant(value.id);
} else {
setp_add_line_item_type_apprenant("");
}
}}
renderInput={(params) => <TextField {...params} label="" placeholder="Choisir une option"
inputProps={{ ...params.inputProps, style: { fontSize: 12, height: "1.4rem" } }}
/>
}
/>
</div>
</div>}
{String(p_detail_header_statut_label).toLowerCase() === "facturé" && <div className="div_row" style={{ "width": "100%", }}>
<div className="session_caract_Dialog" style={{ "textAlign": "left", "width": "50%", "height": "5rem", "float": "left" }}> Taux TVA
<TextField
margin="dense"
id="ref_article_taux_tva"
name="ref_article_taux_tva"
//label="Prix Unitaire"
fullWidth
//variant="standard"
value={partner_taux_tva}
disabled={true}
type="number"
/>
}
/>
</div>}
</div>
{String(p_detail_header_statut_label).toLowerCase() === "facturé" && <div className="session_caract_Dialog" > Type apprenant
<TextField
<div className="session_caract_Dialog" style={{ "textAlign": "left", "width": "50%", "height": "5rem", "float": "right" }}> Type apprenant
<TextField
margin="dense"
id="detail_type_apprenant"
name="detail_type_apprenant"
//label="Prix Unitaire"
margin="dense"
id="detail_type_apprenant"
name="detail_type_apprenant"
//label="Prix Unitaire"
fullWidth
//variant="standard"
value={New_type_apprenant.filter((val) => val.value === String(p_add_line_item_type_apprenant))[0].label}
disabled
type="text"
/>
fullWidth
//variant="standard"
value={New_type_apprenant.filter((val) => val.value === String(p_add_line_item_type_apprenant))[0].label}
disabled
type="text"
/>
</div>
</div>}
</div>}
@ -8404,6 +8452,9 @@ const Partner_Commande = (props) => {
En confirmant cette opération, vous allez <i><font color="red"> lancer le processus de facturation</font></i>. <br />
</div>
<div className="gest_actions">
<div style={{ "width": "45%", "float": "left" }}>
<button className="gest_bton_popup" onClick={(event) => {

View File

@ -7,22 +7,22 @@ const Layout_Without_Testimony = () => {
return (
<div className="footer_automatic_files">
<div className="layout_main_section">
<div className="layout_testimonial_section">
&nbsp;
</div>
<div className="layout_call_to_action_section">
<div className="layout_testimonial_section">
&nbsp;
</div>
<br />
<div className="layout_call_to_action_section">
<CallToActionSection />
</div>
<div className="layout_footer_section">
<div className="layout_footer_section">
<FooterSection />
</div>
</div>
</div>
);
};
export default Layout_Without_Testimony;

View File

@ -277,6 +277,10 @@ const Header = () => {
{/*<a href="/Recherche-Article-formation" className="menu-link">Blog</a>*/}
<div className="separator"></div>
<a href="/marketplace" className="menu-link">Marketplace</a>
<div className="separator"></div>
<a href="/marketplace_26" className="menu-link">Marketplace 26</a>
</nav>
</div>

View File

@ -0,0 +1,29 @@
import React from "react";
import "./accordion.css";
/**
* Simple, accessible accordion item.
* - defaultOpen: boolean
* - title: string
*/
export function AccordionItem({ title, defaultOpen = false, children }) {
const [open, setOpen] = React.useState(!!defaultOpen);
return (
<div className="acc">
<button
type="button"
className="acc__head"
aria-expanded={open}
onClick={() => setOpen((v) => !v)}
>
<span className="acc__title">{title}</span>
<span className={`acc__chev ${open ? "acc__chev--open" : ""}`}></span>
</button>
<div className={`acc__panel ${open ? "acc__panel--open" : ""}`}>
<div className="acc__content">{children}</div>
</div>
</div>
);
}

View File

@ -0,0 +1,6 @@
import React from "react";
import "./badge.css";
export default function Badge({ tone = "info", children }) {
return <span className={`badge badge--${tone}`}>{children}</span>;
}

View File

@ -0,0 +1,28 @@
import React from "react";
import "./button.css";
export default function Button({
variant = "primary",
size = "md",
leftIcon,
rightIcon,
className = "",
...props
}) {
return (
<div className="marketplace_2026">
<button
className={`btn btn--${variant} btn--${size} ${className}`}
{...props}
>
{leftIcon ? <span className="btn__icon">{leftIcon}</span> : null}
<span className="btn__label">{props.children}</span>
{rightIcon ? <span className="btn__icon">{rightIcon}</span> : null}
</button>
</div>
);
}

View File

@ -0,0 +1,10 @@
import React from "react";
import "./card.css";
export function Card({ className = "", ...props }) {
return <div className={`card ${className}`} {...props} />;
}
export function CardBody({ className = "", ...props }) {
return <div className={`card__body ${className}`} {...props} />;
}

View File

@ -0,0 +1,50 @@
import React from "react";
import { Card } from "./Card";
import Badge from "./Badge";
import Button from "./Button";
import "./courseCard.css";
export default function CourseCard({ course, isFavorite, onToggleFavorite, onView }) {
const tags = (course.tags || []).slice(0, 3);
return (
<Card className="courseCard">
<div className="courseCard__media">
{course.coverUrl ? (
<img className="courseCard__img" src={course.coverUrl} alt="" loading="lazy" />
) : (
<div className="courseCard__img courseCard__img--empty" />
)}
<button
type="button"
className={`favBtn ${isFavorite ? "favBtn--on" : ""}`}
aria-label={isFavorite ? "Retirer des favoris" : "Ajouter aux favoris"}
onClick={() => onToggleFavorite?.(course.id)}
>
</button>
</div>
<div className="courseCard__body">
<div className="courseCard__title" title={course.title}>{course.title}</div>
<div className="courseCard__provider">{course.provider}</div>
<div className="courseCard__tags">
{tags.map((t) => (
<Badge key={t} tone="info">{t}</Badge>
))}
</div>
<div className="courseCard__meta">
<span> {course.durationLabel}</span>
<span>{course.ratingLabel ? `${course.ratingLabel}` : "✔ Validé MYSA"}</span>
</div>
<Button className="courseCard__cta" onClick={() => onView?.(course.id)}>
Voir la formation
</Button>
</div>
</Card>
);
}

View File

@ -0,0 +1,32 @@
import React from "react";
import { Card } from "./Card";
import Skeleton from "./Skeleton";
export default function CourseCardSkeleton() {
return (
<Card style={{ overflow: "hidden" }}>
<Skeleton className="skMedia" />
<div style={{ padding: "24px", display: "flex", flexDirection: "column", gap: "12px" }}>
<Skeleton className="skLine skLine--lg" />
<Skeleton className="skLine skLine--sm" />
<div style={{ display: "flex", gap: "8px" }}>
<Skeleton className="skPill" />
<Skeleton className="skPill skPill--w" />
<Skeleton className="skPill" />
</div>
<Skeleton className="skLine" />
<Skeleton className="skBtn" />
</div>
<style>{`
.skMedia { height: 140px; border-radius: 0; }
.skLine { height: 12px; }
.skLine--lg { width: 80%; }
.skLine--sm { width: 45%; }
.skPill { height: 24px; width: 72px; border-radius: var(--r-pill); }
.skPill--w { width: 92px; }
.skBtn { height: 48px; border-radius: var(--r-pill); }
`}</style>
</Card>
);
}

View File

@ -0,0 +1,91 @@
import React from "react";
import Input from "./Input";
import Select from "./Select";
import Button from "./Button";
import "./marketplace.css";
const toOpts = (arr) => arr.map((x) => ({ value: x, label: x }));
export default function FilterBar({ value, onChange, onReset }) {
return (
<div className="filterBar">
<Input
value={value.q}
onChange={(e) => onChange({ q: e.target.value })}
placeholder="Rechercher une formation, une compétence, un organisme"
leftIcon={<span>🔎</span>}
/>
<div className="filterGrid">
<Select
label="Objectif"
value={value.goal}
onChange={(e) => onChange({ goal: e.target.value })}
options={toOpts(["Tous", "Reconversion", "Montée en compétences", "Certification", "Catalogue"])}
/>
<Select
label="Format"
value={value.format}
onChange={(e) => onChange({ format: e.target.value })}
options={toOpts(["Tous", "Présentiel", "Distanciel", "Hybride"])}
/>
<Select
label="Durée"
value={value.duration}
onChange={(e) => onChange({ duration: e.target.value })}
options={toOpts(["Toutes", "< 1 mois", "13 mois", "36 mois", "> 6 mois"])}
/>
<Select
label="Financement"
value={value.funding}
onChange={(e) => onChange({ funding: e.target.value })}
options={toOpts(["Tous", "CPF", "Entreprise", "Autre"])}
/>
<Select
label="Niveau"
value={value.level}
onChange={(e) => onChange({ level: e.target.value })}
options={toOpts(["Tous", "Débutant", "Intermédiaire", "Avancé"])}
/>
</div>
<div className="filterFooter">
<div className="sortWrap">
<Select
label="Trier par"
value={value.sort}
onChange={(e) => onChange({ sort: e.target.value })}
options={toOpts(["Pertinence", "Popularité", "Nouveautés"])}
/>
</div>
<Button variant="ghost" onClick={onReset}>Réinitialiser</Button>
</div>
<style>{`
.filterGrid {
margin-top: 16px;
display: grid;
gap: 12px;
grid-template-columns: repeat(5, 1fr);
}
.filterFooter {
margin-top: 16px;
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
}
.sortWrap { width: 240px; }
@media (max-width: 900px) {
.filterGrid { grid-template-columns: 1fr 1fr; }
.sortWrap { width: 100%; }
}
@media (max-width: 520px) {
.filterGrid { grid-template-columns: 1fr; }
}
`}</style>
</div>
);
}

View File

@ -0,0 +1,12 @@
import React from "react";
import "./input.css";
export default function Input({ leftIcon, rightSlot, className = "", ...props }) {
return (
<div className={`inputWrap ${className}`}>
{leftIcon ? <div className="inputWrap__left">{leftIcon}</div> : null}
<input className={`input ${leftIcon ? "input--pl" : ""}`} {...props} />
{rightSlot ? <div className="inputWrap__right">{rightSlot}</div> : null}
</div>
);
}

View File

@ -0,0 +1,15 @@
import React from "react";
import "./select.css";
export default function Select({ label, options = [], className = "", ...props }) {
return (
<label className={`selectWrap ${className}`}>
{label ? <div className="selectWrap__label">{label}</div> : null}
<select className="select" {...props}>
{options.map((o) => (
<option key={o.value} value={o.value}>{o.label}</option>
))}
</select>
</label>
);
}

View File

@ -0,0 +1,6 @@
import React from "react";
import "./skeleton.css";
export default function Skeleton({ className = "" }) {
return <div className={`sk ${className}`} />;
}

View File

@ -0,0 +1,63 @@
.acc {
border: 1px solid var(--c-border);
border-radius: var(--r-md);
background: var(--c-surface);
box-shadow: var(--sh-xs);
overflow: hidden;
}
.acc + .acc { margin-top: var(--s-3); }
.acc__head {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--s-3);
padding: var(--s-4) var(--s-5);
border: 0;
background: transparent;
cursor: pointer;
text-align: left;
}
.acc__head:focus-visible { box-shadow: var(--ring); outline: none; }
.acc__title {
font-size: var(--fs-14);
font-weight: 700;
color: var(--c-navy);
}
.acc__chev {
width: 28px;
height: 28px;
border-radius: var(--r-pill);
display: inline-flex;
align-items: center;
justify-content: center;
color: var(--c-muted);
background: rgba(20, 32, 51, 0.05);
transition: transform 140ms ease, background 140ms ease;
}
.acc__chev--open { transform: rotate(180deg); background: rgba(30, 99, 255, 0.10); color: var(--c-navy); }
.acc__panel {
max-height: 0;
overflow: hidden;
transition: max-height 220ms ease;
}
.acc__panel--open {
max-height: 600px;
}
.acc__content {
padding: 0 var(--s-5) var(--s-5) var(--s-5);
color: var(--c-text);
font-size: var(--fs-14);
line-height: 1.55;
text-align: left;
}
.acc__content ul {
margin: var(--s-2) 0 0 0;
padding-left: 18px;
}
.acc__content li { margin: 6px 0; color: var(--c-text); }

View File

@ -0,0 +1,23 @@
.badge {
display: inline-flex;
align-items: center;
height: 24px;
padding: 0 10px;
border-radius: var(--r-pill);
font-size: var(--fs-12);
font-weight: 600;
white-space: nowrap;
}
.badge--info {
background: rgba(30, 99, 255, 0.10);
color: var(--c-navy);
}
.badge--trust {
background: var(--c-surface);
border: 1px solid var(--c-border);
color: var(--c-text);
}
.badge--highlight {
background: rgba(245, 158, 11, 0.18);
color: var(--c-text);
}

View File

@ -0,0 +1,92 @@
:root {
/* Brand */
--c-primary: #1e63ff;
--c-primary-600: #1a56db;
--c-navy: #0b1f3a;
/* Neutrals */
--c-bg: #f6f8fc;
--c-surface: #ffffff;
--c-border: #e6ecf5;
--c-text: #142033;
--c-muted: #6b778c;
/* States */
--c-success: #22c55e;
--c-warning: #f59e0b;
/* Radius */
--r-sm: 8px;
--r-md: 12px;
--r-pill: 999px;
/* Spacing */
--s-1: 4px;
--s-2: 8px;
--s-3: 12px;
--s-4: 16px;
--s-5: 20px;
--s-6: 24px;
--s-8: 32px;
--s-10: 40px;
/* Typography */
--font: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial, "Apple Color Emoji","Segoe UI Emoji";
--fs-12: 12px;
--fs-14: 14px;
--fs-16: 16px;
--fs-20: 20px;
--fs-28: 28px;
/* Shadows (subtle, Inquisico-like) */
--sh-xs: 0 2px 10px rgba(12, 26, 75, 0.06);
--sh-sm: 0 6px 18px rgba(12, 26, 75, 0.08);
/* Focus ring */
--ring: 0 0 0 3px rgba(30, 99, 255, 0.18);
}
.btn {
height: 48px;
padding: 0 18px;
border-radius: var(--r-pill);
border: 1px solid transparent;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 10px;
cursor: pointer;
font-weight: 600;
font-size: var(--fs-14);
transition: transform 120ms ease, background 120ms ease, border-color 120ms ease;
outline: none;
}
.btn:focus-visible { box-shadow: var(--ring); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.55; cursor: not-allowed; }
.btn--primary {
background: #3e6ee3;
color: white;
box-shadow: var(--sh-xs);
}
.btn--primary:hover { background: #1a56db; }
.btn--secondary {
background: transparent;
color: #1e63ff;
border-color: #1e63ff;
}
.btn--secondary:hover { background: rgba(30, 99, 255, 0.06); }
.btn--ghost {
background: transparent;
color: var(--c-text);
}
.btn--ghost:hover { background: rgba(20, 32, 51, 0.06); }
.btn--sm { height: 36px; padding: 0 14px; }
.btn__icon { display: inline-flex; align-items: center; }
.btn__label { line-height: 1; }

View File

@ -0,0 +1,8 @@
.card {
background: var(--c-surface);
border: 1px solid var(--c-border);
border-radius: var(--r-md);
box-shadow: var(--sh-xs);
}
.card__body { padding: var(--s-6); }

View File

@ -0,0 +1,59 @@
.courseCard {
overflow: hidden;
transition: box-shadow 140ms ease, transform 140ms ease;
}
/*.courseCard:hover { box-shadow: var(--sh-sm); transform: translateY(-1px); }*/
.courseCard:hover {
transform: translateY(-4px);
box-shadow: 0 12px 30px rgba(0,0,0,.08);
}
.courseCard__media { position: relative; height: 140px; background: var(--c-bg); }
.courseCard__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.courseCard__img--empty { background: linear-gradient(135deg, rgba(30,99,255,0.12), rgba(20,32,51,0.06)); }
.favBtn {
position: absolute;
top: 12px;
right: 12px;
height: 38px;
width: 38px;
border-radius: var(--r-pill);
border: 1px solid var(--c-border);
background: rgba(255,255,255,0.95);
box-shadow: var(--sh-xs);
cursor: pointer;
color: var(--c-muted);
font-size: 16px;
line-height: 1;
transition: background 120ms ease, transform 120ms ease, color 120ms ease;
}
.favBtn:hover { background: var(--c-bg); }
.favBtn:active { transform: translateY(1px); }
.favBtn--on { color: var(--c-primary); }
.courseCard__body { padding: var(--s-6); display: flex; flex-direction: column; gap: var(--s-3); }
.courseCard__title {
font-size: var(--fs-14);
font-weight: 700;
color: var(--c-navy);
line-height: 1.3;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.courseCard__provider { font-size: var(--fs-12); color: var(--c-muted); }
.courseCard__tags { display: flex; gap: var(--s-2); flex-wrap: wrap; }
.courseCard__meta {
display: flex;
justify-content: space-between;
gap: var(--s-3);
font-size: var(--fs-12);
color: var(--c-muted);
}
.courseCard__cta { width: 100%; }

View File

@ -0,0 +1,49 @@
.inputWrap {
position: relative;
width: 100%;
margin-bottom: 3rem;
}
.input {
width: 100%;
height: 48px;
border-radius: var(--r-md);
border: 1px solid var(--c-border);
background: var(--c-surface);
padding: 0 14px;
font-size: var(--fs-14);
color: var(--c-text);
box-shadow: var(--sh-xs);
outline: none;
transition: box-shadow 120ms ease, border-color 120ms ease;
}
.input::placeholder {
color: var(--c-muted);
}
.input:focus {
box-shadow: var(--ring);
border-color: rgba(30, 99, 255, 0.35);
}
.input--pl {
padding-left: 44px;
height: 65px;
border-radius: 50px;
}
.inputWrap__left {
position: absolute;
left: 14px;
top: 50%;
transform: translateY(-50%);
color: var(--c-muted);
}
.inputWrap__right {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
}

View File

@ -0,0 +1,76 @@
.marketHero { padding: var(--s-8) 0; }
:root {
/* Brand */
--c-primary: #1e63ff;
--c-primary-600: #1a56db;
--c-navy: #0b1f3a;
/* Neutrals */
--c-bg: #f6f8fc;
--c-surface: #ffffff;
--c-border: #e6ecf5;
--c-text: #142033;
--c-muted: #6b778c;
/* States */
--c-success: #22c55e;
--c-warning: #f59e0b;
/* Radius */
--r-sm: 8px;
--r-md: 12px;
--r-pill: 999px;
/* Spacing */
--s-1: 4px;
--s-2: 8px;
--s-3: 12px;
--s-4: 16px;
--s-5: 20px;
--s-6: 24px;
--s-8: 32px;
--s-10: 40px;
/* Typography */
--font: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial, "Apple Color Emoji","Segoe UI Emoji";
--fs-12: 12px;
--fs-14: 14px;
--fs-16: 16px;
--fs-20: 20px;
--fs-28: 28px;
/* Shadows (subtle, Inquisico-like) */
--sh-xs: 0 2px 10px rgba(12, 26, 75, 0.06);
--sh-sm: 0 6px 18px rgba(12, 26, 75, 0.08);
/* Focus ring */
--ring: 0 0 0 3px rgba(30, 99, 255, 0.18);
}
.filterBar {
background: rgba(30, 99, 255, 0.10);
border: 1px solid var(--c-border);
border-radius: var(--r-md);
box-shadow: var(--sh-xs);
padding: var(--s-6);
}
.grid {
margin-top: var(--s-6);
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: var(--s-4);
}
@media (max-width: 1100px) { .grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 820px) { .grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .grid { grid-template-columns: 1fr; } }
.resultsRow {
margin-top: var(--s-4);
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--s-4);
}
.resultsText { color: var(--c-muted); font-size: var(--fs-14); }

View File

@ -0,0 +1,19 @@
.selectWrap { display: block; width: 100%; }
.selectWrap__label {
font-size: var(--fs-12);
color: var(--c-muted);
margin-bottom: 6px;
}
.select {
width: 100%;
height: 40px;
border-radius: var(--r-md);
border: 1px solid var(--c-border);
background: var(--c-surface);
padding: 0 10px;
font-size: var(--fs-14);
color: var(--c-text);
box-shadow: var(--sh-xs);
outline: none;
}
.select:focus { box-shadow: var(--ring); border-color: rgba(30, 99, 255, 0.35); }

View File

@ -0,0 +1,10 @@
@keyframes pulse {
0% { opacity: 0.55; }
50% { opacity: 1; }
100% { opacity: 0.55; }
}
.sk {
background: rgba(20, 32, 51, 0.08);
border-radius: var(--r-md);
animation: pulse 1.2s ease-in-out infinite;
}

View File

@ -0,0 +1,22 @@
import Partner from "../components/Partner";
import Detailled_Class_2026 from "../components/Detailled_Class_2026";
import New_C_Footer_2025_V2 from "../components/footer_automatic_files/Layout";
import New_C_Header_2025_V2 from "../components/header_automatic_files/Header";
import New_C_Footer_Without_Testimony_2025_V2 from "../components/footer_automatic_files/Layout_Without_Testimony";
const recherche_draft = () => {
return (
<div>
<New_C_Header_2025_V2 />
<Detailled_Class_2026 />
<New_C_Footer_Without_Testimony_2025_V2 />
</div>
)
}
export default recherche_draft;

View File

@ -0,0 +1,22 @@
import Partner from "../components/Partner";
import LandingPage_2026 from "../components/LandingPage_2026"
import New_C_Footer_2025_V2 from "../components/footer_automatic_files/Layout";
import New_C_Header_2025_V2 from "../components/header_automatic_files/Header";
import New_C_Footer_Without_Testimony_2025_V2 from "../components/footer_automatic_files/Layout_Without_Testimony";
const landing_page_2026 = () => {
return (
<div>
<New_C_Header_2025_V2 />
<LandingPage_2026 />
<New_C_Footer_Without_Testimony_2025_V2 />
</div>
)
}
export default landing_page_2026;

View File

@ -0,0 +1,22 @@
import Partner from "../components/Partner";
import MarketPlace_2026 from "../components/MarketPlace_2026"
import New_C_Footer_2025_V2 from "../components/footer_automatic_files/Layout";
import New_C_Header_2025_V2 from "../components/header_automatic_files/Header";
import New_C_Footer_Without_Testimony_2025_V2 from "../components/footer_automatic_files/Layout_Without_Testimony";
const marketplace_2026 = () => {
return (
<div>
<New_C_Header_2025_V2 />
<MarketPlace_2026 />
<New_C_Footer_Without_Testimony_2025_V2 />
</div>
)
}
export default marketplace_2026;

View File

@ -6,11 +6,10 @@ import New_C_Footer_Without_Testimony_2025_V2 from "../components/footer_automat
const recherche_draft = () => {
return (
<div>
<div>
<New_C_Header_2025_V2 />
<Partner />
<New_C_Footer_Without_Testimony_2025_V2 />
</div>

View File

@ -1139,7 +1139,7 @@
font-size: 0.75rem;
text-align: left;
margin-bottom: 0.8rem;
color: black;
color: white;
cursor: pointer;
}
@ -1410,10 +1410,87 @@
}
}
/* Structure principale */
.main {
display: flex;
flex: 1;
}
/* Panneau latéral */
.sidebar {
width: 220px;
background-color: #1a1a1a;
border-right: 1px solid #2a2a2a;
padding: 1rem 0;
}
.sidebar ul {
list-style: none;
}
.sidebar li {
//padding: 0.75rem 1.5rem;
cursor: pointer;
color: #ccc;
transition: background 0.2s, color 0.2s;
}
.sidebar li:hover {
background-color: #2b2b2b;
color: #4fa3ff;
}
.sidebar li.active {
background-color: #2a2a2a;
color: #4fa3ff;
}
/* Grille de fichiers */
.file-grid {
flex: 1;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
gap: 1rem;
padding: 1.5rem;
overflow-y: auto;
}
.file-card {
background-color: #1e1e1e;
border: 1px solid #2a2a2a;
border-radius: 8px;
padding: 1rem;
text-align: center;
transition: transform 0.2s, box-shadow 0.2s;
max-height: 10rem;
}
.file-card:hover {
transform: translateY(-3px);
box-shadow: 0 0 10px rgba(79, 163, 255, 0.3);
}
.file-icon {
font-size: 2rem;
margin-bottom: 0.5rem;
}
.file-name {
font-weight: 500;
margin-bottom: 0.25rem;
}
.file-date {
font-size: 0.8rem;
color: #888;
}
// end media
.sousmenu_selected {
font-family: "DM Sans", "sans-serif";
color: white;
color: wheat;
font-weight: 700;
font-size: small;
text-align: left;

View File

@ -0,0 +1,366 @@
.detailled_class_2026 {
:root {
/* Brand */
--c-primary: #1e63ff;
--c-primary-600: #1a56db;
--c-navy: #0b1f3a;
/* Neutrals */
--c-bg: #f6f8fc;
--c-surface: #ffffff;
--c-border: #e6ecf5;
--c-text: #142033;
--c-muted: #6b778c;
/* States */
--c-success: #22c55e;
--c-warning: #f59e0b;
/* Radius */
--r-sm: 8px;
--r-md: 12px;
--r-pill: 999px;
/* Spacing */
--s-1: 4px;
--s-2: 8px;
--s-3: 12px;
--s-4: 16px;
--s-5: 20px;
--s-6: 24px;
--s-8: 32px;
--s-10: 40px;
/* Typography */
--font: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial, "Apple Color Emoji", "Segoe UI Emoji";
--fs-12: 12px;
--fs-14: 14px;
--fs-16: 16px;
--fs-20: 20px;
--fs-28: 28px;
/* Shadows (subtle, Inquisico-like) */
--sh-xs: 0 2px 10px rgba(12, 26, 75, 0.06);
--sh-sm: 0 6px 18px rgba(12, 26, 75, 0.08);
/* Focus ring */
--ring: 0 0 0 3px rgba(30, 99, 255, 0.18);
}
/* Course Detail Page — Variante 1 (institutionnelle) */
.breadcrumb {
padding: var(--s-4) 0 0 0;
font-size: var(--fs-12);
color: var(--c-muted);
}
.breadcrumb a {
color: var(--c-muted);
}
.breadcrumb a:hover {
color: var(--c-text);
}
.courseHero {
padding: var(--s-6) 0 var(--s-6) 0;
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: var(--s-6);
}
.courseTitle {
margin: 0;
font-size: var(--fs-28);
font-weight: 800;
color: var(--c-navy);
letter-spacing: -0.01em;
}
.courseSubtitle {
margin: var(--s-2) 0 0 0;
color: var(--c-muted);
font-size: var(--fs-14);
line-height: 1.55;
max-width: 64ch;
}
.badgeRow {
margin-top: var(--s-4);
display: flex;
flex-wrap: wrap;
gap: var(--s-2);
}
.metaGrid {
margin-top: var(--s-4);
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: var(--s-3);
max-width: 560px;
}
.metaItem {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 12px;
border: 1px solid var(--c-border);
border-radius: var(--r-md);
background: var(--c-surface);
box-shadow: var(--sh-xs);
font-size: var(--fs-14);
color: var(--c-text);
}
.metaIcon {
color: var(--c-muted);
}
.courseLayout {
display: grid;
grid-template-columns: minmax(0, 1fr) 360px;
gap: var(--s-6);
padding-bottom: var(--s-10);
}
.section {
margin-top: var(--s-6);
}
.sectionTitle {
margin: 0 0 var(--s-3) 0;
font-size: var(--fs-20);
font-weight: 800;
color: var(--c-navy);
text-align: left;
}
.hr {
height: 1px;
background: var(--c-border);
border: 0;
margin: var(--s-6) 0;
}
.overviewGrid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--s-4);
}
.kBlock {
border: 1px solid var(--c-border);
border-radius: var(--r-md);
background: var(--c-surface);
box-shadow: var(--sh-xs);
padding: var(--s-5);
}
.kBlock h3 {
margin: 0 0 var(--s-3) 0;
font-size: var(--fs-14);
font-weight: 800;
color: var(--c-navy);
}
.kList {
margin: 0;
padding-left: 0;
list-style: none;
}
.kList li {
display: flex;
gap: 10px;
margin: 10px 0;
color: var(--c-text);
font-size: var(--fs-14);
}
.kTick {
color: var(--c-success);
font-weight: 900;
}
.asideCard {
position: sticky;
top: 18px;
align-self: start;
}
.priceRow {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: var(--s-3);
}
.price {
font-size: 26px;
font-weight: 900;
color: var(--c-navy);
}
.priceSub {
color: var(--c-muted);
font-size: var(--fs-12);
}
.asideBlock {
margin-top: var(--s-4);
padding-top: var(--s-4);
border-top: 1px solid var(--c-border);
}
.asideLabel {
color: var(--c-muted);
font-size: var(--fs-12);
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
margin-bottom: var(--s-2);
}
.asideLine {
display: flex;
align-items: center;
justify-content: space-between;
font-size: var(--fs-14);
color: var(--c-text);
margin: 10px 0;
}
.asideProof {
margin: var(--s-3) 0 0 0;
padding-left: 0;
list-style: none;
}
.asideProof li {
display: flex;
gap: 10px;
margin: 10px 0;
color: var(--c-text);
font-size: var(--fs-14);
}
.asideCTA {
width: 100%;
margin-top: var(--s-4);
}
.secondaryActions {
margin-top: var(--s-3);
display: flex;
gap: var(--s-2);
}
.linkBtn {
border: 1px solid var(--c-border);
background: var(--c-surface);
border-radius: var(--r-pill);
height: 36px;
padding: 0 14px;
cursor: pointer;
color: var(--c-text);
font-weight: 600;
font-size: var(--fs-12);
box-shadow: var(--sh-xs);
}
.linkBtn:hover {
background: rgba(20, 32, 51, 0.05);
}
.linkBtn:focus-visible {
outline: none;
box-shadow: var(--ring);
}
.similarGrid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--s-4);
}
/* Mobile */
.mobileSticky {
display: none;
}
@media (max-width: 980px) {
.courseLayout {
grid-template-columns: 1fr;
}
.asideCard {
position: relative;
top: 0;
}
.courseHero {
flex-direction: column;
}
}
@media (max-width: 720px) {
.metaGrid {
grid-template-columns: 1fr;
}
.overviewGrid {
grid-template-columns: 1fr;
}
.similarGrid {
grid-template-columns: 1fr;
}
.asideCard {
display: none;
}
.mobileSticky {
display: flex;
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: rgba(246, 248, 252, 0.92);
backdrop-filter: blur(10px);
border-top: 1px solid var(--c-border);
padding: 10px var(--s-4);
gap: var(--s-3);
align-items: center;
justify-content: space-between;
z-index: 50;
}
.mobileSticky__price {
display: flex;
flex-direction: column;
gap: 2px;
}
.mobileSticky__price strong {
font-size: 16px;
color: var(--c-navy);
}
.mobileSticky__price span {
font-size: 12px;
color: var(--c-muted);
}
.pagePadBottom {
padding-bottom: 72px;
}
}
}

View File

@ -0,0 +1,249 @@
.marketplace_2026 {
:root {
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
}
body {
font-family: var(--font);
color: var(--c-text);
background: var(--c-bg);
}
a {
color: inherit;
text-decoration: none;
}
button,
input,
select {
font-family: inherit;
}
.container {
max-width: 1240px;
margin: 0 auto;
padding: 0 var(--s-4);
}
.h1 {
font-size: var(--fs-28);
font-weight: 700;
color: var(--c-navy);
margin: 0;
}
.p-muted {
margin: var(--s-2) 0 0 0;
color: var(--c-muted);
font-size: var(--fs-14);
line-height: 1.5;
}
:root {
/* Brand */
--c-primary: #1e63ff;
--c-primary-600: #1a56db;
--c-navy: #0b1f3a;
/* Neutrals */
--c-bg: #f6f8fc;
--c-surface: #ffffff;
--c-border: #e6ecf5;
--c-text: #142033;
--c-muted: #6b778c;
/* States */
--c-success: #22c55e;
--c-warning: #f59e0b;
/* Radius */
--r-sm: 8px;
--r-md: 12px;
--r-pill: 999px;
/* Spacing */
--s-1: 4px;
--s-2: 8px;
--s-3: 12px;
--s-4: 16px;
--s-5: 20px;
--s-6: 24px;
--s-8: 32px;
--s-10: 40px;
/* Typography */
--font: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial, "Apple Color Emoji", "Segoe UI Emoji";
--fs-12: 12px;
--fs-14: 14px;
--fs-16: 16px;
--fs-20: 20px;
--fs-28: 28px;
/* Shadows (subtle, Inquisico-like) */
--sh-xs: 0 2px 10px rgba(12, 26, 75, 0.06);
--sh-sm: 0 6px 18px rgba(12, 26, 75, 0.08);
/* Focus ring */
--ring: 0 0 0 3px rgba(30, 99, 255, 0.18);
}
.btn {
height: 48px;
padding: 0 18px;
border-radius: var(--r-pill);
border: 1px solid transparent;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 10px;
cursor: pointer;
font-weight: 600;
font-size: var(--fs-14);
transition: transform 120ms ease, background 120ms ease, border-color 120ms ease;
outline: none;
}
.btn:focus-visible {
box-shadow: var(--ring);
}
.btn:active {
transform: translateY(1px);
}
.btn:disabled {
opacity: 0.55;
cursor: not-allowed;
}
.btn--primary {
background: #3e6ee3;
color: white;
box-shadow: var(--sh-xs);
transition: background-color 0.2s ease;
}
.btn--primary:hover {
background: #355fd0;
}
.btn--secondary {
background: transparent;
color: #1e63ff;
border-color: #1e63ff;
}
.btn--secondary:hover {
background: rgba(30, 99, 255, 0.06);
}
.btn--ghost {
background: transparent;
color: var(--c-text);
}
.btn--ghost:hover {
background: rgba(20, 32, 51, 0.06);
}
.btn--sm {
height: 36px;
padding: 0 14px;
}
.btn__icon {
display: inline-flex;
align-items: center;
}
.btn__label {
line-height: 1;
}
}

View File

@ -217,4 +217,8 @@
@import "./components/new_buttonhilight_2025";
@import "./components/new_s_article_detail_2025";
@import "./components/new_s_article_2025";
@import "./components/new_s_formation_2025";
@import "./components/new_s_formation_2025";
// Market Place 2026
@import "./components/marketplace_2026";
@import "./components/detailled_class_2026";