| @@ -321,8 +321,65 @@ | ||
| 321 | 321 | </div> |
| 322 | 322 | </div> |
| 323 | 323 | </div> |
| 324 | 324 | |
| 325 | + <!-- Satisfaction (last 30 days) — plan-a5b006 --> | |
| 326 | + <div class="mxch-card mxch-satisfaction-card"> | |
| 327 | + <div class="mxch-card-header"> | |
| 328 | + <h3 class="mxch-card-title"> | |
| 329 | + <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"/><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H7"/><path d="M3 10h4"/></svg> | |
| 330 | + <?php esc_html_e('Satisfaction (last 30 days)', 'mxchat'); ?> | |
| 331 | + </h3> | |
| 332 | + </div> | |
| 333 | + <div class="mxch-card-body"> | |
| 334 | + <?php | |
| 335 | + $satisfaction_stats = isset($satisfaction_stats) && is_array($satisfaction_stats) ? $satisfaction_stats : array(); | |
| 336 | + if (empty($satisfaction_stats)) : | |
| 337 | + ?> | |
| 338 | + <p class="mxch-satisfaction-empty"> | |
| 339 | + <?php esc_html_e('No ratings yet. The widget shows the prompt after a conversation has had at least two bot replies and the visitor goes idle for 60 seconds.', 'mxchat'); ?> | |
| 340 | + </p> | |
| 341 | + <?php | |
| 342 | + else : | |
| 343 | + ?> | |
| 344 | + <ul class="mxch-satisfaction-list"> | |
| 345 | + <?php foreach ($satisfaction_stats as $row) : | |
| 346 | + $bot_label = $row['bot_id'] === 'default' | |
| 347 | + ? esc_html__('Default bot', 'mxchat') | |
| 348 | + : esc_html($row['bot_id']); | |
| 349 | + ?> | |
| 350 | + <li class="mxch-satisfaction-row"> | |
| 351 | + <span class="mxch-satisfaction-bot"><?php echo $bot_label; ?></span> | |
| 352 | + <span class="mxch-satisfaction-meta"> | |
| 353 | + <span class="mxch-satisfaction-total"><?php | |
| 354 | + echo esc_html(sprintf( | |
| 355 | + /* translators: %d: number of rated sessions */ | |
| 356 | + _n('%d rated session', '%d rated sessions', $row['total'], 'mxchat'), | |
| 357 | + $row['total'] | |
| 358 | + )); | |
| 359 | + ?></span> | |
| 360 | + <span class="mxch-satisfaction-bar" aria-hidden="true"> | |
| 361 | + <span class="mxch-satisfaction-bar-up" style="width: <?php echo esc_attr($row['positive_pct']); ?>%;"></span> | |
| 362 | + <span class="mxch-satisfaction-bar-down" style="width: <?php echo esc_attr($row['negative_pct']); ?>%;"></span> | |
| 363 | + </span> | |
| 364 | + <span class="mxch-satisfaction-pct mxch-satisfaction-pct-up" title="<?php esc_attr_e('Positive ratings', 'mxchat'); ?>"> | |
| 365 | + <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"/><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H7"/><path d="M3 10h4"/></svg> | |
| 366 | + <?php echo esc_html($row['positive_pct']); ?>% | |
| 367 | + </span> | |
| 368 | + <span class="mxch-satisfaction-pct mxch-satisfaction-pct-down" title="<?php esc_attr_e('Negative ratings', 'mxchat'); ?>"> | |
| 369 | + <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"/><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H17"/><path d="M21 14h-4"/></svg> | |
| 370 | + <?php echo esc_html($row['negative_pct']); ?>% | |
| 371 | + </span> | |
| 372 | + </span> | |
| 373 | + </li> | |
| 374 | + <?php endforeach; ?> | |
| 375 | + </ul> | |
| 376 | + <?php | |
| 377 | + endif; | |
| 378 | + ?> | |
| 379 | + </div> | |
| 380 | + </div> | |
| 381 | + | |
| 325 | 382 | <!-- Activity Chart --> |
| 326 | 383 | <div class="mxch-card mxch-activity-chart-card"> |
| 327 | 384 | <div class="mxch-card-header"> |
| 328 | 385 | <h3 class="mxch-card-title"> |
| @@ -473,8 +530,12 @@ | ||
| 473 | 530 | <div class="mxch-detail-row" id="mxch-detail-email-row" style="display: none;"> |
| 474 | 531 | <span class="mxch-detail-label"><?php esc_html_e('Email', 'mxchat'); ?></span> |
| 475 | 532 | <span class="mxch-detail-value" id="mxch-detail-email">-</span> |
| 476 | 533 | </div> |
| 534 | + <div class="mxch-detail-row" id="mxch-detail-feedback-row" style="display: none;"> | |
| 535 | + <span class="mxch-detail-label"><?php esc_html_e('Feedback', 'mxchat'); ?></span> | |
| 536 | + <span class="mxch-detail-value mxch-detail-feedback-value" id="mxch-detail-feedback">-</span> | |
| 537 | + </div> | |
| 477 | 538 | </div> |
| 478 | 539 | <div class="mxch-details-section" id="mxch-clicked-section" style="display: none;"> |
| 479 | 540 | <h4><?php esc_html_e('Clicked Links', 'mxchat'); ?></h4> |
| 480 | 541 | <div class="mxch-clicked-links" id="mxch-clicked-links"> |
| @@ -693,13 +754,14 @@ | ||
| 693 | 754 | <th class="mxch-leads-col-lead"><?php esc_html_e('Lead', 'mxchat'); ?></th> |
| 694 | 755 | <th class="mxch-leads-col-count"><?php esc_html_e('Conversations', 'mxchat'); ?></th> |
| 695 | 756 | <th class="mxch-leads-col-last"><?php esc_html_e('Last seen', 'mxchat'); ?></th> |
| 696 | 757 | <th class="mxch-leads-col-page"><?php esc_html_e('Top page', 'mxchat'); ?></th> |
| 758 | + <th class="mxch-leads-col-consent"><?php esc_html_e('Consent', 'mxchat'); ?></th> | |
| 697 | 759 | <th class="mxch-leads-col-actions"></th> |
| 698 | 760 | </tr> |
| 699 | 761 | </thead> |
| 700 | 762 | <tbody id="mxch-leads-tbody"> |
| 701 | - <tr><td colspan="6" class="mxch-leads-loading"><span class="spinner is-active"></span></td></tr> | |
| 763 | + <tr><td colspan="7" class="mxch-leads-loading"><span class="spinner is-active"></span></td></tr> | |
| 702 | 764 | </tbody> |
| 703 | 765 | </table> |
| 704 | 766 | </div> |
| 705 | 767 | |
| @@ -771,14 +833,15 @@ | ||
| 771 | 833 | </div> |
| 772 | 834 | |
| 773 | 835 | <div class="mxch-field"> |
| 774 | 836 | <label class="mxch-field-label"><?php esc_html_e('Notification Email', 'mxchat'); ?></label> |
| 775 | - <input type="email" | |
| 837 | + <?php /* type="text", not "email": the browser rejects a comma-separated list outright (plan 2f131a). Validation is server-side in MxChat_Utils. */ ?> | |
| 838 | + <input type="text" | |
| 776 | 839 | name="mxchat_transcripts_options[mxchat_notification_email]" |
| 777 | 840 | class="mxch-input mxchat-autosave-field" |
| 778 | 841 | value="<?php echo esc_attr($email); ?>" |
| 779 | 842 | data-nonce="<?php echo wp_create_nonce('mxchat_autosave_nonce'); ?>"> |
| 780 | - <p class="mxch-field-description"><?php esc_html_e('Email address where notifications will be sent.', 'mxchat'); ?></p> | |
| 843 | + <p class="mxch-field-description"><?php printf(esc_html__('Email address where notifications will be sent. Separate up to %d addresses with commas. Defaults to the site admin email.', 'mxchat'), (int) MxChat_Utils::NOTIFICATION_EMAIL_MAX); ?></p> | |
| 781 | 844 | </div> |
| 782 | 845 | </div> |
| 783 | 846 | </div> |
| 784 | 847 | |
| @@ -850,8 +913,9 @@ | ||
| 850 | 913 | </div> |
| 851 | 914 | <div class="mxch-card-body"> |
| 852 | 915 | <?php |
| 853 | 916 | $auto_delete = isset($options['mxchat_auto_delete_transcripts']) ? $options['mxchat_auto_delete_transcripts'] : 'never'; |
| 917 | + $mxch_custom_retention = isset($options['mxchat_retention_days']) ? (int) $options['mxchat_retention_days'] : 0; | |
| 854 | 918 | ?> |
| 855 | 919 | <div class="mxch-field"> |
| 856 | 920 | <label class="mxch-field-label"><?php esc_html_e('Auto-Delete Old Transcripts', 'mxchat'); ?></label> |
| 857 | 921 | <select name="mxchat_transcripts_options[mxchat_auto_delete_transcripts]" |
| @@ -862,8 +926,76 @@ | ||
| 862 | 926 | <option value="2weeks" <?php selected($auto_delete, '2weeks'); ?>><?php esc_html_e('After 2 Weeks', 'mxchat'); ?></option> |
| 863 | 927 | <option value="1month" <?php selected($auto_delete, '1month'); ?>><?php esc_html_e('After 1 Month', 'mxchat'); ?></option> |
| 864 | 928 | </select> |
| 865 | 929 | <p class="mxch-field-description"><?php esc_html_e('Automatically delete old chat transcripts to manage database size and privacy.', 'mxchat'); ?></p> |
| 930 | + <?php if ($mxch_custom_retention > 0) : ?> | |
| 931 | + <p class="mxch-field-description" id="mxchat-retention-override-note"> | |
| 932 | + <strong><?php | |
| 933 | + printf( | |
| 934 | + /* translators: %d: the custom retention value in days */ | |
| 935 | + esc_html__('Overridden by Custom Retention below: transcripts are deleted after %d days.', 'mxchat'), | |
| 936 | + $mxch_custom_retention | |
| 937 | + ); | |
| 938 | + ?></strong> | |
| 939 | + </p> | |
| 940 | + <?php endif; ?> | |
| 941 | + <?php | |
| 942 | + // Surface the cron's real state next to the setting that | |
| 943 | + // depends on it (plan-bc08a6): a configured retention whose | |
| 944 | + // cleanup event is missing was previously invisible. | |
| 945 | + $mxch_retention_days = isset($options['mxchat_retention_days']) ? (int) $options['mxchat_retention_days'] : 0; | |
| 946 | + if ($auto_delete !== 'never' || $mxch_retention_days > 0) : | |
| 947 | + $mxch_next_cleanup = wp_next_scheduled('mxchat_cleanup_old_transcripts'); | |
| 948 | + ?> | |
| 949 | + <p class="mxch-field-description" id="mxchat-next-cleanup-status"> | |
| 950 | + <?php | |
| 951 | + if ($mxch_next_cleanup) { | |
| 952 | + printf( | |
| 953 | + /* translators: %s: localized date and time of the next scheduled transcript cleanup */ | |
| 954 | + esc_html__('Next cleanup: %s', 'mxchat'), | |
| 955 | + esc_html(wp_date(get_option('date_format') . ' ' . get_option('time_format'), $mxch_next_cleanup)) | |
| 956 | + ); | |
| 957 | + } else { | |
| 958 | + esc_html_e('Next cleanup: not currently scheduled.', 'mxchat'); | |
| 959 | + } | |
| 960 | + ?> | |
| 961 | + </p> | |
| 962 | + <?php endif; ?> | |
| 963 | + </div> | |
| 964 | + | |
| 965 | + <div class="mxch-field"> | |
| 966 | + <label class="mxch-field-label" for="mxchat_retention_days"><?php esc_html_e('Custom Retention (Days)', 'mxchat'); ?></label> | |
| 967 | + <input type="number" | |
| 968 | + id="mxchat_retention_days" | |
| 969 | + name="mxchat_transcripts_options[mxchat_retention_days]" | |
| 970 | + class="mxch-input mxchat-autosave-field" | |
| 971 | + value="<?php echo esc_attr($mxch_custom_retention); ?>" | |
| 972 | + min="0" | |
| 973 | + max="3650" | |
| 974 | + step="1" | |
| 975 | + data-nonce="<?php echo wp_create_nonce('mxchat_autosave_nonce'); ?>"> | |
| 976 | + <p class="mxch-field-description"><?php esc_html_e('Delete transcripts older than this many days (1–3650). When greater than 0 this overrides the dropdown above; set 0 to use the dropdown. Developers can adjust the final value with the mxchat_transcript_retention_days filter.', 'mxchat'); ?></p> | |
| 977 | + </div> | |
| 978 | + </div> | |
| 979 | + </div> | |
| 980 | + | |
| 981 | + <!-- Privacy & Data Requests Card (plan b81e42) --> | |
| 982 | + <div class="mxch-card"> | |
| 983 | + <div class="mxch-card-header"> | |
| 984 | + <h3 class="mxch-card-title"> | |
| 985 | + <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> | |
| 986 | + <?php esc_html_e('Privacy & Data Requests', 'mxchat'); ?> | |
| 987 | + </h3> | |
| 988 | + </div> | |
| 989 | + <div class="mxch-card-body"> | |
| 990 | + <div class="mxch-field"> | |
| 991 | + <p class="mxch-field-description"> | |
| 992 | + <?php esc_html_e('Chat conversations — including captured emails, names, and visitor identifiers — are registered with WordPress\'s built-in privacy tools. When you run a personal data export or erasure request from the Tools menu, MxChat data is included automatically, so honouring a GDPR or CCPA request covers the chatbot with no extra steps.', 'mxchat'); ?> | |
| 993 | + </p> | |
| 994 | + <p> | |
| 995 | + <a href="<?php echo esc_url(admin_url('export-personal-data.php')); ?>" class="mxch-btn mxch-btn-secondary mxch-btn-sm"><?php esc_html_e('Export Personal Data', 'mxchat'); ?></a> | |
| 996 | + <a href="<?php echo esc_url(admin_url('erase-personal-data.php')); ?>" class="mxch-btn mxch-btn-secondary mxch-btn-sm"><?php esc_html_e('Erase Personal Data', 'mxchat'); ?></a> | |
| 997 | + </p> | |
| 866 | 998 | </div> |
| 867 | 999 | </div> |
| 868 | 1000 | </div> |
| 869 | 1001 | </div> |