From 70a27f2421ed0602031342d3c44ac5228212cd07 Mon Sep 17 00:00:00 2001 From: jps Date: Thu, 15 Jan 2026 10:10:00 +0100 Subject: [PATCH 1/2] Ajout settings visuels --- app/controllers/Plugin.php | 174 +++++++++++++++++++++------ assets/css/admin.css | 218 ++++++++++++++++++++++++++++++++++ assets/js/admin.js | 39 ++++++ templates/admin/dashboard.php | 184 ++++++++++++++++++++++++---- templates/admin/settings.php | 23 ++-- 5 files changed, 564 insertions(+), 74 deletions(-) diff --git a/app/controllers/Plugin.php b/app/controllers/Plugin.php index fba0bec..220d03a 100644 --- a/app/controllers/Plugin.php +++ b/app/controllers/Plugin.php @@ -1173,7 +1173,14 @@ class PEPPOL_Plugin { * * @return string|null */ - public static function get_vat_notice_message(): ?string { + /** + * Récupère toutes les notices TVA à afficher + * + * @return array Tableau de notices, chaque notice contient 'message' et 'type' (info, warning, etc.) + */ + public static function get_vat_notice_message(): array { + $notices = []; + // Vérifier d'abord si un champ TVA client a été détecté $vat_field_key = (string) get_option('esi_peppol_vat_field_key', ''); $auto_detected = (bool) get_option('esi_peppol_vat_field_auto_detected', false); @@ -1181,35 +1188,45 @@ class PEPPOL_Plugin { // Si aucun champ TVA détecté, proposer la détection dans settings if ($vat_field_key === '' && $auto_detected) { $settings_url = admin_url('admin.php?page=esi-peppol-settings'); - return sprintf( - /* translators: %s: URL vers la page de réglages */ - __('Aucun champ TVA client n\'a été détecté automatiquement. Vous pouvez utiliser l\'outil de détection dans ESI Peppol > Configuration pour rechercher manuellement les champs TVA dans vos commandes.', 'esi_peppol'), - esc_url($settings_url) - ); + $notices[] = [ + 'message' => sprintf( + /* translators: %s: URL vers la page de réglages */ + __('Aucun champ TVA client n\'a été détecté automatiquement. Vous pouvez utiliser l\'outil de détection dans ESI Peppol > Configuration pour rechercher manuellement les champs TVA dans vos commandes.', 'esi_peppol'), + esc_url($settings_url) + ), + 'type' => 'warning' + ]; } $vat_number = (string) get_option('woocommerce_store_vat_number', ''); - if ($vat_number !== '') { - return null; + // Si le numéro de TVA est renseigné, on ne vérifie pas les autres notices liées au TVA + if ($vat_number === '') { + $api_key = (string) get_option('esi_peppol_api_key', ''); + $password = (string) get_option('esi_peppol_password', ''); + + if ($api_key === '' && $password === '') { + // Invitation initiale + $notices[] = [ + 'message' => __( + 'Pour finaliser la mise en place de Peppol, pensez à renseigner le numéro de TVA de la boutique dans WooCommerce > Réglages > Général.', + 'esi_peppol' + ), + 'type' => 'info' + ]; + } else { + // Rappel après configuration du connecteur + $notices[] = [ + 'message' => __( + 'Votre connecteur ESI Peppol est configuré, mais le numéro de TVA de la boutique n\'est pas encore renseigné dans WooCommerce > Réglages > Général. Sans ce numéro, les factures Peppol risquent d\'être incomplètes.', + 'esi_peppol' + ), + 'type' => 'warning' + ]; + } } - $api_key = (string) get_option('esi_peppol_api_key', ''); - $password = (string) get_option('esi_peppol_password', ''); - - if ($api_key === '' && $password === '') { - // Invitation initiale - return __( - 'Pour finaliser la mise en place de Peppol, pensez à renseigner le numéro de TVA de la boutique dans WooCommerce > Réglages > Général.', - 'esi_peppol' - ); - } - - // Rappel après configuration du connecteur - return __( - 'Votre connecteur ESI Peppol est configuré, mais le numéro de TVA de la boutique n\'est pas encore renseigné dans WooCommerce > Réglages > Général. Sans ce numéro, les factures Peppol risquent d\'être incomplètes.', - 'esi_peppol' - ); + return $notices; } /** @@ -1226,27 +1243,106 @@ class PEPPOL_Plugin { return; } - $vat_notice_message = self::get_vat_notice_message(); + $vat_notices = self::get_vat_notice_message(); - if (empty($vat_notice_message)) { + if (empty($vat_notices)) { return; } - $api_key = (string) \get_option('esi_peppol_api_key', ''); - $password = (string) \get_option('esi_peppol_password', ''); - $vat_field_key = (string) \get_option('esi_peppol_vat_field_key', ''); - $auto_detected = (bool) \get_option('esi_peppol_vat_field_auto_detected', false); - - // Si aucun champ TVA détecté, utiliser notice-warning - if ($vat_field_key === '' && $auto_detected) { - $notice_class = 'notice-warning'; - } else { - $notice_class = ($api_key === '' && $password === '') ? 'notice-info' : 'notice-warning'; + foreach ($vat_notices as $notice) { + $notice_class = 'notice-' . $notice['type']; + echo '

' . + \wp_kses_post($notice['message']) . + '

'; + } + } + + /** + * Vérifie l'état de configuration des settings ESI Peppol + * + * @return array Tableau avec l'état de chaque étape du setup + */ + public static function check_settings_status(): array { + $status = [ + 'vat_number' => [ + 'completed' => false, + 'value' => '', + 'label' => __('Numéro de TVA de la boutique', 'esi_peppol'), + 'description' => __('Le numéro de TVA de votre boutique doit être renseigné dans WooCommerce > Réglages > Général', 'esi_peppol'), + 'action_url' => admin_url('admin.php?page=wc-settings&tab=general'), + 'action_label' => __('Configurer dans WooCommerce', 'esi_peppol'), + ], + 'vat_field' => [ + 'completed' => false, + 'value' => '', + 'label' => __('Champ TVA client', 'esi_peppol'), + 'description' => __('Le champ utilisé pour récupérer le numéro de TVA du client dans les commandes', 'esi_peppol'), + 'action_url' => admin_url('admin.php?page=esi-peppol-settings'), + 'action_label' => __('Détecter le champ TVA', 'esi_peppol'), + ], + 'api_credentials' => [ + 'completed' => false, + 'value' => '', + 'label' => __('Identifiants API', 'esi_peppol'), + 'description' => __('Votre clé API et mot de passe pour vous connecter à la plateforme ESI Peppol', 'esi_peppol'), + 'action_url' => admin_url('admin.php?page=esi-peppol-settings'), + 'action_label' => __('Configurer les identifiants', 'esi_peppol'), + ], + 'webhook' => [ + 'completed' => true, // Toujours disponible + 'value' => '', + 'label' => __('URL Webhook', 'esi_peppol'), + 'description' => __('URL à configurer dans votre profil d\'entreprise sur la plateforme', 'esi_peppol'), + 'action_url' => admin_url('admin.php?page=esi-peppol-settings'), + 'action_label' => __('Voir l\'URL webhook', 'esi_peppol'), + ], + 'email' => [ + 'completed' => false, + 'optional' => true, + 'value' => '', + 'label' => __('Email de notification', 'esi_peppol'), + 'description' => __('Adresse email pour recevoir les notifications en cas d\'erreur d\'envoi des factures', 'esi_peppol'), + 'action_url' => admin_url('admin.php?page=esi-peppol-settings'), + 'action_label' => __('Configurer l\'email', 'esi_peppol'), + ], + ]; + + // Vérifier le numéro de TVA de la boutique + $vat_number = (string) get_option('woocommerce_store_vat_number', ''); + if ($vat_number !== '') { + $status['vat_number']['completed'] = true; + $status['vat_number']['value'] = $vat_number; } - echo '

' . - \wp_kses_post($vat_notice_message) . - '

'; + // Vérifier le champ TVA client + $vat_field_key = (string) get_option('esi_peppol_vat_field_key', ''); + if ($vat_field_key !== '') { + $status['vat_field']['completed'] = true; + $status['vat_field']['value'] = $vat_field_key; + } + + // Vérifier les identifiants API + $api_key = (string) get_option('esi_peppol_api_key', ''); + $password = (string) get_option('esi_peppol_password', ''); + if ($api_key !== '' && $password !== '') { + $status['api_credentials']['completed'] = true; + $status['api_credentials']['value'] = substr($api_key, 0, 8) . '...'; // Masquer partiellement + } + + // Récupérer l'URL webhook + if (class_exists(\ESI_PEPPOL\controllers\PEPPOL_Webhook_controller::class)) { + $webhook_url = \ESI_PEPPOL\controllers\PEPPOL_Webhook_controller::get_webhook_url(); + $status['webhook']['value'] = $webhook_url; + } + + // Vérifier l'email + $email = (string) get_option('esi_peppol_email', ''); + if ($email !== '') { + $status['email']['completed'] = true; + $status['email']['value'] = $email; + } + + return $status; } public static function write_log($message, $level = 'INFO') { diff --git a/assets/css/admin.css b/assets/css/admin.css index 756fd39..e87ccba 100644 --- a/assets/css/admin.css +++ b/assets/css/admin.css @@ -403,3 +403,221 @@ a.statut:visited { height: 16px; line-height: 1; } + +/* Styles pour le dashboard et le setup guidé */ +.esi-peppol-dashboard-wrap { + max-width: 1200px; +} + +.esi-peppol-dashboard-intro { + font-size: 15px; + color: #50575e; + margin-bottom: 30px; +} + +.esi-peppol-setup-guide { + background: #ffffff; + border-radius: 12px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); + padding: 32px; + margin: 30px 0; +} + +.esi-peppol-setup-title { + margin: 0 0 32px 0; + font-size: 24px; + font-weight: 600; + color: #1d2327; + border-bottom: 2px solid #f0f0f1; + padding-bottom: 16px; +} + +.esi-peppol-setup-step { + margin-bottom: 24px; + padding: 24px; + background: #f9f9f9; + border-radius: 8px; + border-left: 4px solid #c3c4c7; + transition: all 0.3s ease; +} + +.esi-peppol-setup-step:last-child { + margin-bottom: 0; +} + +.esi-peppol-setup-step.completed { + background: #f0f9f4; + border-left-color: #10b981; +} + +.esi-peppol-setup-step.pending { + background: #fffbf0; + border-left-color: #f59e0b; +} + +.esi-peppol-setup-step.esi-peppol-step-no-check { + background: #f0f6ff; + border-left-color: #3b82f6; +} + +.esi-peppol-setup-step.esi-peppol-step-optional { + background: #f8f9fa; + border-left-color: #9ca3af; + opacity: 0.9; +} + +.esi-peppol-step-header { + display: flex; + align-items: flex-start; + gap: 20px; +} + +.esi-peppol-step-number { + flex-shrink: 0; + width: 48px; + height: 48px; + border-radius: 50%; + background: #ffffff; + display: flex; + align-items: center; + justify-content: center; + font-size: 20px; + font-weight: 600; + color: #50575e; + border: 3px solid #c3c4c7; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.esi-peppol-setup-step.completed .esi-peppol-step-number { + background: #10b981; + border-color: #10b981; + color: #ffffff; +} + +.esi-peppol-setup-step.pending .esi-peppol-step-number { + background: #ffffff; + border-color: #f59e0b; + color: #f59e0b; +} + +.esi-peppol-setup-step.esi-peppol-step-no-check .esi-peppol-step-number { + background: #ffffff; + border-color: #3b82f6; + color: #3b82f6; +} + +.esi-peppol-setup-step.esi-peppol-step-optional .esi-peppol-step-number { + background: #ffffff; + border-color: #9ca3af; + color: #9ca3af; +} + +.esi-peppol-check-icon { + font-size: 28px; + line-height: 1; + font-weight: 700; +} + +.esi-peppol-step-content { + flex: 1; +} + +.esi-peppol-step-title { + margin: 0 0 8px 0; + font-size: 18px; + font-weight: 600; + color: #1d2327; + display: flex; + align-items: center; + gap: 12px; +} + +.esi-peppol-optional-badge { + display: inline-block; + padding: 2px 8px; + background: #e5e7eb; + color: #6b7280; + border-radius: 4px; + font-size: 12px; + font-weight: 500; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.esi-peppol-step-description { + margin: 0 0 16px 0; + font-size: 14px; + color: #646970; + line-height: 1.6; +} + +.esi-peppol-step-value { + margin-top: 12px; + padding: 12px; + background: #ffffff; + border-radius: 6px; + border: 1px solid #d1d5db; +} + +.esi-peppol-step-value strong { + display: block; + margin-bottom: 6px; + font-size: 13px; + color: #374151; + font-weight: 600; +} + +.esi-peppol-step-value code { + display: inline-block; + padding: 4px 8px; + background: #f3f4f6; + border: 1px solid #d1d5db; + border-radius: 4px; + font-family: 'Courier New', Courier, monospace; + font-size: 13px; + color: #1f2937; +} + +.esi-peppol-webhook-display { + display: flex; + align-items: center; + gap: 12px; + margin: 16px 0; + padding: 12px; + background: #ffffff; + border-radius: 6px; + border: 1px solid #d1d5db; +} + +.esi-peppol-webhook-url { + flex: 1; + padding: 8px 12px; + background: #f9fafb; + border: 1px solid #e5e7eb; + border-radius: 4px; + font-family: 'Courier New', Courier, monospace; + font-size: 13px; + color: #1f2937; + word-break: break-all; + line-height: 1.5; +} + +.esi-peppol-step-note { + margin: 12px 0 0 0; + font-size: 13px; + color: #6b7280; + font-style: italic; +} + +.esi-peppol-dashboard-actions { + margin-top: 40px; + padding-top: 30px; + border-top: 2px solid #f0f0f1; +} + +.esi-peppol-dashboard-actions h2 { + margin: 0 0 16px 0; + font-size: 20px; + font-weight: 600; + color: #1d2327; +} diff --git a/assets/js/admin.js b/assets/js/admin.js index 6c98ea5..96da828 100644 --- a/assets/js/admin.js +++ b/assets/js/admin.js @@ -507,6 +507,45 @@ }); } + // Copier l'URL webhook depuis le dashboard (avec data-copy-text) + $(document).on('click', '.esi-peppol-copy-webhook-url[data-copy-text]', function (e) { + e.preventDefault(); + var $btn = $(this); + var text = $btn.attr('data-copy-text'); + + if (text) { + // Utiliser l'API Clipboard moderne si disponible + if (navigator.clipboard && navigator.clipboard.writeText) { + navigator.clipboard.writeText(text).then(function () { + var originalText = $btn.text(); + $btn.text('Copié !'); + setTimeout(function () { + $btn.text(originalText); + }, 2000); + }).catch(function (err) { + console.error('Erreur lors de la copie:', err); + }); + } else { + // Fallback pour les anciens navigateurs + try { + var $temp = $('