Changeset 3445596
- Timestamp:
- 01/23/2026 01:01:09 PM (4 weeks ago)
- Location:
- convertybot
- Files:
-
- 97 added
- 10 edited
-
tags/1.0.26 (added)
-
tags/1.0.26/LICENSE.txt (added)
-
tags/1.0.26/assets (added)
-
tags/1.0.26/assets/css (added)
-
tags/1.0.26/assets/css/admin-analytics.css (added)
-
tags/1.0.26/assets/css/admin-configuration.css (added)
-
tags/1.0.26/assets/css/admin-conversations.css (added)
-
tags/1.0.26/assets/css/admin-coupons.css (added)
-
tags/1.0.26/assets/css/admin-subscription.css (added)
-
tags/1.0.26/assets/css/admin-visitor-journeys.css (added)
-
tags/1.0.26/assets/css/admin.css (added)
-
tags/1.0.26/assets/css/analytics-comprehensive.css (added)
-
tags/1.0.26/assets/css/analytics-redesigned.css (added)
-
tags/1.0.26/assets/css/chat-modal-fixes.css (added)
-
tags/1.0.26/assets/css/chatbot-improvements.css (added)
-
tags/1.0.26/assets/css/consent-banner.css (added)
-
tags/1.0.26/assets/css/frontend-enhanced.css (added)
-
tags/1.0.26/assets/css/frontend-fixes.css (added)
-
tags/1.0.26/assets/css/frontend-modern.css (added)
-
tags/1.0.26/assets/css/frontend-widget-a11y.css (added)
-
tags/1.0.26/assets/css/frontend.css (added)
-
tags/1.0.26/assets/css/product-cards-inline.css (added)
-
tags/1.0.26/assets/css/products-modal-improved.css (added)
-
tags/1.0.26/assets/css/products-modal.css (added)
-
tags/1.0.26/assets/js (added)
-
tags/1.0.26/assets/js/admin-analytics-dashboard.js (added)
-
tags/1.0.26/assets/js/admin-configuration.js (added)
-
tags/1.0.26/assets/js/admin-conversations.js (added)
-
tags/1.0.26/assets/js/admin-coupons.js (added)
-
tags/1.0.26/assets/js/admin-main.js (added)
-
tags/1.0.26/assets/js/admin-setup-wizard.js (added)
-
tags/1.0.26/assets/js/admin-subscription.js (added)
-
tags/1.0.26/assets/js/admin-visitor-journeys.js (added)
-
tags/1.0.26/assets/js/admin.js (added)
-
tags/1.0.26/assets/js/analytics-comprehensive.js (added)
-
tags/1.0.26/assets/js/analytics-enhanced.js (added)
-
tags/1.0.26/assets/js/analytics-export.js (added)
-
tags/1.0.26/assets/js/analytics-predictive.js (added)
-
tags/1.0.26/assets/js/analytics-redesigned.js (added)
-
tags/1.0.26/assets/js/analytics-segmentation.js (added)
-
tags/1.0.26/assets/js/analytics-websocket.js (added)
-
tags/1.0.26/assets/js/analytics-widgets.js (added)
-
tags/1.0.26/assets/js/chatbot-sounds.js (added)
-
tags/1.0.26/assets/js/consent-banner.js (added)
-
tags/1.0.26/assets/js/coupon-system-enhanced.js (added)
-
tags/1.0.26/assets/js/engagement-tracking-sdk.js (added)
-
tags/1.0.26/assets/js/frontend-enhanced.js (added)
-
tags/1.0.26/assets/js/frontend-fixes.js (added)
-
tags/1.0.26/assets/js/frontend.js (added)
-
tags/1.0.26/assets/js/guest-id-cookie.js (added)
-
tags/1.0.26/assets/js/migration-handler.js (added)
-
tags/1.0.26/assets/js/product-cards-handler.js (added)
-
tags/1.0.26/assets/js/product-showcase-enhanced.js (added)
-
tags/1.0.26/assets/js/service-worker.js (added)
-
tags/1.0.26/assets/js/tracking.js (added)
-
tags/1.0.26/assets/js/vendor (added)
-
tags/1.0.26/assets/js/vendor/chart.min.js (added)
-
tags/1.0.26/assets/js/vendor/handlebars.min.js (added)
-
tags/1.0.26/assets/sounds (added)
-
tags/1.0.26/assets/sounds/README.txt (added)
-
tags/1.0.26/assets/sounds/connect.mp3 (added)
-
tags/1.0.26/assets/sounds/error.mp3 (added)
-
tags/1.0.26/assets/sounds/message.mp3 (added)
-
tags/1.0.26/assets/sounds/notification.mp3 (added)
-
tags/1.0.26/assets/sounds/open.mp3 (added)
-
tags/1.0.26/assets/sounds/send.mp3 (added)
-
tags/1.0.26/convertybot.php (added)
-
tags/1.0.26/includes (added)
-
tags/1.0.26/includes/class-admin.php (added)
-
tags/1.0.26/includes/class-analytics.php (added)
-
tags/1.0.26/includes/class-api.php (added)
-
tags/1.0.26/includes/class-consent-banner.php (added)
-
tags/1.0.26/includes/class-coupon-manager.php (added)
-
tags/1.0.26/includes/class-database.php (added)
-
tags/1.0.26/includes/class-frontend.php (added)
-
tags/1.0.26/includes/class-product-sync.php (added)
-
tags/1.0.26/includes/class-user-profile.php (added)
-
tags/1.0.26/includes/class-user-tracking-enhanced.php (added)
-
tags/1.0.26/includes/class-user-tracking.php (added)
-
tags/1.0.26/languages (added)
-
tags/1.0.26/readme.txt (added)
-
tags/1.0.26/templates (added)
-
tags/1.0.26/templates/admin (added)
-
tags/1.0.26/templates/admin/analytics-comprehensive.php (added)
-
tags/1.0.26/templates/admin/analytics.php (added)
-
tags/1.0.26/templates/admin/configuration-debug.php (added)
-
tags/1.0.26/templates/admin/configuration.php (added)
-
tags/1.0.26/templates/admin/conversations.php (added)
-
tags/1.0.26/templates/admin/coupons.php (added)
-
tags/1.0.26/templates/admin/main.php (added)
-
tags/1.0.26/templates/admin/setup-wizard.php (added)
-
tags/1.0.26/templates/admin/subscription.php (added)
-
tags/1.0.26/templates/admin/visitor-journeys.php (added)
-
tags/1.0.26/templates/frontend (added)
-
tags/1.0.26/templates/frontend/chatbot-widget-enhanced.php (added)
-
tags/1.0.26/templates/frontend/chatbot-widget.php (added)
-
tags/1.0.26/templates/offline.html (added)
-
trunk/assets/css/chat-modal-fixes.css (modified) (2 diffs)
-
trunk/assets/css/chatbot-improvements.css (modified) (11 diffs)
-
trunk/assets/css/consent-banner.css (modified) (1 diff)
-
trunk/assets/css/frontend.css (modified) (3 diffs)
-
trunk/assets/css/product-cards-inline.css (modified) (1 diff)
-
trunk/assets/css/products-modal-improved.css (modified) (3 diffs)
-
trunk/assets/js/frontend.js (modified) (11 diffs)
-
trunk/convertybot.php (modified) (2 diffs)
-
trunk/readme.txt (modified) (3 diffs)
-
trunk/templates/frontend/chatbot-widget.php (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
convertybot/trunk/assets/css/chat-modal-fixes.css
r3437100 r3445596 15 15 #convertybot-chat-button { 16 16 z-index: 999998; 17 } 18 19 /* =================================== 20 HIDE BUTTON WHEN CHAT IS OPEN 21 =================================== */ 22 #convertybot-chat-button.convertybot-hidden { 23 display: none !important; 17 24 } 18 25 … … 33 40 34 41 @media (max-width: 768px) { 35 /* Chat widget adjustments for mobile*/42 /* Widget container - BOTTOM RIGHT CORNER ONLY */ 36 43 #convertybot-widget { 37 bottom: 0 !important; 38 right: 0 !important; 39 left: 0 !important; 40 width: 100% !important; 44 bottom: 10px !important; 45 right: 10px !important; 46 left: auto !important; 47 top: auto !important; 48 width: auto !important; 49 max-width: none !important; 50 height: auto !important; 51 max-height: none !important; 52 } 53 54 /* Chat window - SMALL, BOTTOM RIGHT, NOT FULL WIDTH */ 55 .convertybot-chat-window { 56 position: fixed !important; 57 bottom: 60px !important; 58 right: 10px !important; 59 left: auto !important; /* NOT from left - stay right */ 60 top: auto !important; 61 width: 280px !important; /* Fixed small width */ 62 max-width: 85vw !important; /* Never more than 85% of viewport */ 63 height: 45vh !important; 64 max-height: 320px !important; 65 border-radius: 12px !important; 66 box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2) !important; 67 overflow: hidden !important; 68 } 69 70 /* Chat button - small circle on mobile */ 71 #convertybot-chat-button { 72 width: 44px !important; 73 height: 44px !important; 74 padding: 0 !important; 75 border-radius: 50% !important; 76 } 77 78 /* Hidden button */ 79 #convertybot-chat-button.convertybot-hidden { 80 display: none !important; 81 } 82 83 #convertybot-chat-button .chat-button-text { 84 display: none !important; 85 } 86 87 #convertybot-chat-button svg { 88 width: 18px !important; 89 height: 18px !important; 90 } 91 92 /* Chat header - very compact */ 93 .convertybot-chat-header { 94 padding: 6px 8px !important; 95 } 96 97 .convertybot-chat-header h4 { 98 font-size: 11px !important; 99 } 100 101 .convertybot-header-info { 102 gap: 4px !important; 103 } 104 105 .convertybot-avatar { 106 width: 18px !important; 107 height: 18px !important; 108 } 109 110 .convertybot-avatar svg { 111 width: 10px !important; 112 height: 10px !important; 113 } 114 115 .convertybot-status { 116 font-size: 8px !important; 117 } 118 119 .status-indicator { 120 width: 5px !important; 121 height: 5px !important; 122 } 123 124 .convertybot-minimize { 125 width: 20px !important; 126 height: 20px !important; 127 padding: 3px !important; 128 } 129 130 .convertybot-minimize svg { 131 width: 10px !important; 132 height: 10px !important; 133 } 134 135 /* Messages area - very compact */ 136 .convertybot-chat-messages { 137 padding: 6px !important; 138 } 139 140 .convertybot-message { 141 gap: 4px !important; 142 margin-bottom: 6px !important; 143 } 144 145 .message-avatar { 146 width: 15px !important; 147 height: 15px !important; 148 flex-shrink: 0 !important; 149 border-radius: 50% !important; 150 } 151 152 .message-avatar svg { 153 width: 9px !important; 154 height: 9px !important; 155 } 156 157 .message-content { 158 max-width: calc(100% - 10px) !important; 159 } 160 161 /* IMPORTANT: Use high specificity to override desktop styles */ 162 .convertybot-message.bot .message-bubble, 163 .convertybot-message.user .message-bubble, 164 .message-bubble { 165 padding: 4px 6px !important; 166 font-size: 9px !important; 167 line-height: 1.25 !important; 168 border-radius: 8px !important; 169 word-wrap: break-word !important; 170 overflow-wrap: break-word !important; 171 } 172 173 .convertybot-message .message-bubble strong, 174 .message-bubble strong { 175 font-size: 9px !important; 176 } 177 178 .convertybot-message .message-bubble p, 179 .message-bubble p { 180 font-size: 9px !important; 181 margin: 2px 0 !important; 182 } 183 184 .convertybot-message .message-bubble ul, 185 .message-bubble ul { 186 margin: 2px 0 !important; 187 padding-left: 12px !important; 188 } 189 190 .convertybot-message .message-bubble li, 191 .message-bubble li { 192 font-size: 9px !important; 193 margin: 1px 0 !important; 194 } 195 196 .message-time { 197 font-size: 8px !important; 198 margin-top: 2px !important; 199 } 200 201 /* Input area - very compact */ 202 .convertybot-chat-input { 203 padding: 5px 6px !important; 204 border-top: 1px solid #e0e0e0 !important; 205 } 206 207 .convertybot-chat-input form { 208 gap: 4px !important; 209 display: flex !important; 210 align-items: center !important; 211 } 212 213 .convertybot-chat-input textarea, 214 .convertybot-chat-input input { 215 font-size: 11px !important; 216 padding: 5px 8px !important; 217 min-width: 0 !important; 218 flex: 1 !important; 219 border-radius: 14px !important; 220 min-height: 26px !important; 221 max-height: 50px !important; 222 } 223 224 .convertybot-chat-input button { 225 padding: 5px !important; 226 min-width: 26px !important; 227 width: 26px !important; 228 height: 26px !important; 229 flex-shrink: 0 !important; 230 border-radius: 50% !important; 231 } 232 233 .convertybot-chat-input button svg { 234 width: 12px !important; 235 height: 12px !important; 236 } 237 238 /* Product cards in chat - ultra compact */ 239 .ai-products-inline { 240 padding: 5px !important; 241 margin-top: 5px !important; 242 gap: 4px !important; 243 background: #f5f5f5 !important; 244 border-radius: 6px !important; 245 } 246 247 .ai-product-card-inline { 248 padding: 4px !important; 249 border-radius: 4px !important; 250 } 251 252 .product-inline-content { 253 gap: 4px !important; 254 } 255 256 .product-inline-header { 257 gap: 6px !important; 258 } 259 260 .product-inline-image { 261 width: 30px !important; 262 height: 30px !important; 263 border-radius: 3px !important; 264 } 265 266 .product-inline-title h5 { 267 font-size: 9px !important; 268 line-height: 1.2 !important; 269 } 270 271 /* Show product details on mobile with compact size */ 272 .product-inline-details { 273 display: block !important; 274 padding: 2px 0 !important; 275 } 276 277 .product-inline-rating { 278 display: flex !important; 279 font-size: 8px !important; 280 gap: 2px !important; 281 margin-bottom: 2px !important; 282 } 283 284 .product-inline-rating .stars { 285 font-size: 8px !important; 286 } 287 288 .product-inline-rating .reviews { 289 font-size: 7px !important; 290 } 291 292 .product-inline-description { 293 font-size: 7px !important; 294 line-height: 1.2 !important; 295 -webkit-line-clamp: 1 !important; 296 overflow: hidden !important; 297 text-overflow: ellipsis !important; 298 white-space: nowrap !important; 299 margin: 0 !important; 300 } 301 302 .product-inline-footer { 303 gap: 4px !important; 304 } 305 306 .product-inline-price { 307 font-size: 9px !important; 308 } 309 310 .product-inline-link { 311 padding: 2px 5px !important; 312 font-size: 8px !important; 313 border-radius: 3px !important; 314 } 315 316 .ai-more-products-btn { 317 padding: 4px 8px !important; 318 font-size: 8px !important; 319 border-radius: 8px !important; 320 } 321 322 /* Suggestion chips - ultra compact, no horizontal scroll */ 323 .message-suggestions { 324 display: flex !important; 325 flex-wrap: wrap !important; 326 gap: 2px !important; 327 margin-top: 3px !important; 328 overflow-x: hidden !important; 41 329 max-width: 100% !important; 42 height: 100% !important; 43 max-height: 100vh !important; 44 border-radius: 0 !important; 45 } 46 47 /* Chat button smaller on mobile */ 48 #convertybot-chat-button { 49 width: 56px !important; 50 height: 56px !important; 51 bottom: 16px !important; 52 right: 16px !important; 53 } 54 55 /* Chat header smaller text */ 56 #convertybot-widget .chat-header h3 { 57 font-size: 16px !important; 58 } 59 60 /* Messages smaller text */ 61 #convertybot-widget .message-text { 62 font-size: 14px !important; 63 line-height: 1.4 !important; 64 } 65 66 /* Input area adjustments */ 67 #convertybot-widget .chat-input-area { 68 padding: 10px !important; 69 } 70 71 #convertybot-widget .chat-input { 72 font-size: 14px !important; 73 padding: 10px 12px !important; 74 } 75 76 #convertybot-widget .send-button { 77 padding: 10px 16px !important; 78 font-size: 14px !important; 79 } 80 81 /* Product cards in chat - smaller */ 82 #convertybot-widget .product-card { 83 font-size: 12px !important; 84 } 85 86 #convertybot-widget .product-card h5 { 87 font-size: 13px !important; 88 } 89 90 #convertybot-widget .product-card .price { 91 font-size: 14px !important; 92 } 93 } 94 95 /* Small phones */ 96 @media (max-width: 480px) { 97 /* Even smaller button */ 98 #convertybot-chat-button { 99 width: 50px !important; 100 height: 50px !important; 101 bottom: 12px !important; 102 right: 12px !important; 103 } 104 105 /* Smaller text */ 106 #convertybot-widget .message-text { 107 font-size: 13px !important; 108 } 109 110 #convertybot-widget .chat-input { 111 font-size: 13px !important; 330 } 331 332 .suggestion-chip { 333 font-size: 7px !important; 334 padding: 2px 4px !important; 335 border-radius: 6px !important; 336 white-space: nowrap !important; 337 flex-shrink: 1 !important; 338 max-width: 80px !important; 339 overflow: hidden !important; 340 text-overflow: ellipsis !important; 341 } 342 343 /* Coupon cards - ultra compact */ 344 .ai-coupons-container { 345 margin-top: 5px !important; 346 gap: 4px !important; 347 } 348 349 .ai-coupon-card { 350 padding: 5px !important; 351 } 352 353 .coupon-badge { 354 font-size: 8px !important; 355 padding: 2px 4px !important; 356 } 357 358 .coupon-title { 359 font-size: 10px !important; 360 } 361 362 .coupon-description { 363 font-size: 8px !important; 364 } 365 366 .coupon-code { 367 font-size: 9px !important; 368 } 369 370 .coupon-copy-btn { 371 padding: 3px 6px !important; 372 font-size: 8px !important; 373 } 374 } 375 376 /* Small phones - even more compact */ 377 @media (max-width: 380px) { 378 .convertybot-chat-window { 379 width: 260px !important; 380 height: 40vh !important; 381 max-height: 280px !important; 382 bottom: 55px !important; 383 } 384 385 .convertybot-message.bot .message-bubble, 386 .convertybot-message.user .message-bubble, 387 .message-bubble { 388 font-size: 9px !important; 389 padding: 4px 6px !important; 390 } 391 392 .product-inline-image { 393 width: 25px !important; 394 height: 25px !important; 395 } 396 397 .product-inline-title h5 { 398 font-size: 8px !important; 399 } 400 401 .convertybot-chat-input textarea, 402 .convertybot-chat-input input { 403 font-size: 10px !important; 112 404 } 113 405 } -
convertybot/trunk/assets/css/chatbot-improvements.css
r3437100 r3445596 11 11 visibility: hidden !important; 12 12 opacity: 0 !important; 13 pointer-events: none !important; 14 width: 0 !important; 15 height: 0 !important; 16 overflow: hidden !important; 17 position: absolute !important; 18 left: -9999px !important; 13 19 } 14 20 … … 17 23 visibility: visible !important; 18 24 opacity: 1 !important; 25 } 26 27 /* ====================== 28 AUTO-HIDE BUTTON WHEN CHAT IS OPEN 29 Multiple CSS solutions for maximum compatibility 30 ====================== */ 31 /* Solution 1: When chat window has visible class */ 32 #convertybot-widget:has(#convertybot-chat-window.convertybot-visible) #convertybot-chat-button { 33 display: none !important; 34 visibility: hidden !important; 35 opacity: 0 !important; 36 pointer-events: none !important; 37 width: 0 !important; 38 height: 0 !important; 39 position: absolute !important; 40 left: -9999px !important; 41 } 42 43 /* Solution 2: When chat window has inline display flex */ 44 #convertybot-widget:has(#convertybot-chat-window[style*="flex"]) #convertybot-chat-button { 45 display: none !important; 46 visibility: hidden !important; 47 opacity: 0 !important; 48 pointer-events: none !important; 49 width: 0 !important; 50 height: 0 !important; 51 position: absolute !important; 52 left: -9999px !important; 53 } 54 55 /* Solution 3: When widget has data-chat-open attribute */ 56 #convertybot-widget[data-chat-open="true"] #convertybot-chat-button { 57 display: none !important; 58 visibility: hidden !important; 59 opacity: 0 !important; 60 pointer-events: none !important; 61 width: 0 !important; 62 height: 0 !important; 63 position: absolute !important; 64 left: -9999px !important; 19 65 } 20 66 … … 110 156 .convertybot-message.bot { 111 157 display: block !important; 112 margin-bottom: 5px !important;113 margin-left: 1 6px !important;158 margin-bottom: 8px !important; 159 margin-left: 18px !important; 114 160 position: relative !important; 115 161 } 116 162 117 163 .convertybot-message.bot .message-avatar { 118 width: 2 1px !important;119 height: 2 1px !important;164 width: 24px !important; 165 height: 24px !important; 120 166 border-radius: 50% !important; 121 167 background: var(--convertybot-gradient, linear-gradient(135deg, #040404 0%, #2a2a2a 100%)) !important; … … 123 169 align-items: center !important; 124 170 justify-content: center !important; 125 box-shadow: 0 2px 8px rgba(4, 4, 4, 0.3) !important;171 box-shadow: 0 2px 6px rgba(4, 4, 4, 0.3) !important; 126 172 position: absolute !important; 127 173 top: 0 !important; 128 left: -1 2px !important;174 left: -14px !important; 129 175 z-index: 2 !important; 130 176 border: 2px solid white !important; … … 132 178 133 179 .convertybot-message.bot .message-avatar svg { 134 width: 1 6px !important;135 height: 1 6px !important;180 width: 14px !important; 181 height: 14px !important; 136 182 color: white !important; 137 183 } … … 162 208 .convertybot-message.user { 163 209 display: block !important; 164 margin-bottom: 5px !important;165 margin-right: 1 6px !important;210 margin-bottom: 8px !important; 211 margin-right: 18px !important; 166 212 margin-left: auto !important; 167 213 position: relative !important; … … 170 216 171 217 .convertybot-message.user .message-avatar { 172 width: 2 0px !important;173 height: 2 0px !important;218 width: 24px !important; 219 height: 24px !important; 174 220 border-radius: 50% !important; 175 221 background: linear-gradient(135deg, #00b894 0%, #00cec9 100%) !important; … … 177 223 align-items: center !important; 178 224 justify-content: center !important; 179 box-shadow: 0 2px 8px rgba(0, 184, 148, 0.3) !important;225 box-shadow: 0 2px 6px rgba(0, 184, 148, 0.3) !important; 180 226 position: absolute !important; 181 227 top: 0 !important; 182 right: -1 2px !important;228 right: -14px !important; 183 229 z-index: 2 !important; 184 230 border: 2px solid white !important; … … 186 232 187 233 .convertybot-message.user .message-avatar svg { 188 width: 1 5px !important;189 height: 1 5px !important;234 width: 14px !important; 235 height: 14px !important; 190 236 fill: white !important; 191 237 } … … 541 587 height: 650px !important; 542 588 max-height: calc(100vh - 120px) !important; 543 display: flex !important;544 589 flex-direction: column !important; 590 } 591 592 /* Only show as flex when visible class is added */ 593 .convertybot-chat-window.convertybot-visible { 594 display: flex !important; 545 595 } 546 596 … … 565 615 566 616 /* ====================== 567 RESPONSIVE 568 ====================== */ 569 @media (max-width: 480px) { 617 RESPONSIVE - MOBILE 768px 618 ====================== */ 619 @media (max-width: 768px) { 620 /* CRITICAL: Force 10px font on mobile - this file loads LAST so these rules win */ 621 .convertybot-message.bot .message-bubble { 622 font-size: 10px !important; 623 line-height: 1.3 !important; 624 padding: 5px 8px !important; 625 padding-left: 14px !important; 626 } 627 628 .convertybot-message.user .message-bubble { 629 font-size: 10px !important; 630 line-height: 1.3 !important; 631 padding: 5px 8px !important; 632 padding-right: 14px !important; 633 } 634 570 635 .convertybot-message.bot .message-content, 571 636 .convertybot-message.user .message-content { 572 max-width: calc(100% - 38px) !important; 573 } 574 575 .convertybot-message.bot .message-avatar, 637 max-width: calc(100% - 10px) !important; 638 } 639 640 .convertybot-message.bot { 641 margin-left: 12px !important; 642 } 643 644 .convertybot-message.user { 645 margin-right: 12px !important; 646 } 647 648 .convertybot-message.bot .message-avatar { 649 width: 15px !important; 650 height: 15px !important; 651 left: -10px !important; 652 border-width: 1px !important; 653 } 654 576 655 .convertybot-message.user .message-avatar { 577 width: 28px !important; 578 height: 28px !important; 656 width: 15px !important; 657 height: 15px !important; 658 right: -11px !important; 659 border-width: 1px !important; 660 } 661 662 .convertybot-message.bot .message-avatar svg, 663 .convertybot-message.user .message-avatar svg { 664 width: 9px !important; 665 height: 9px !important; 579 666 } 580 667 581 668 .suggestion-chip { 582 font-size: 12px !important; 583 padding: 6px 12px !important; 584 } 585 } 669 font-size: 8px !important; 670 padding: 3px 6px !important; 671 } 672 673 } 674 675 /* ====================== 676 RESPONSIVE - SMALL PHONES 480px 677 ====================== */ 678 @media (max-width: 480px) { 679 .convertybot-message.bot .message-bubble, 680 .convertybot-message.user .message-bubble { 681 font-size: 10px !important; 682 padding: 5px 8px !important; 683 } 684 } 685 686 /* Hide button when chat is open */ 687 #convertybot-chat-button.convertybot-hidden { 688 display: none !important; 689 } -
convertybot/trunk/assets/css/consent-banner.css
r3437100 r3445596 289 289 } 290 290 291 /* Mobile Responsive */291 /* Mobile Responsive - NOT full screen */ 292 292 @media (max-width: 640px) { 293 .ai-consent-banner { 294 padding: 15px !important; 295 } 296 297 .ai-consent-overlay { 298 background: rgba(0, 0, 0, 0.5) !important; 299 } 300 293 301 .ai-consent-modal { 294 max-width: 100%; 295 width: 100%; 296 height: 100%; 297 max-height: 100%; 298 border-radius: 0; 302 max-width: 300px !important; 303 width: calc(100% - 30px) !important; 304 height: auto !important; 305 max-height: 70vh !important; 306 border-radius: 12px !important; 307 margin: auto !important; 299 308 } 300 309 301 310 .ai-consent-header { 302 padding: 20px 20px 15px;311 padding: 12px 14px 10px !important; 303 312 } 304 313 305 314 .ai-consent-header h2 { 306 font-size: 20px; 315 font-size: 14px !important; 316 margin-bottom: 6px !important; 307 317 } 308 318 309 319 .ai-consent-header p { 310 font-size: 13px; 320 font-size: 10px !important; 321 line-height: 1.4 !important; 311 322 } 312 323 313 324 .ai-consent-body { 314 padding: 15px 20px; 325 padding: 10px 12px !important; 326 max-height: 30vh !important; 327 overflow-y: auto !important; 328 } 329 330 .ai-consent-category { 331 margin-bottom: 10px !important; 332 padding-bottom: 10px !important; 333 } 334 335 .ai-consent-category-header { 336 gap: 10px !important; 337 } 338 339 .ai-consent-category-info h3 { 340 font-size: 12px !important; 341 margin-bottom: 4px !important; 342 } 343 344 .ai-consent-category-info p { 345 font-size: 10px !important; 346 line-height: 1.3 !important; 347 } 348 349 .ai-consent-switch { 350 width: 40px !important; 351 height: 20px !important; 352 } 353 354 .ai-consent-slider:before { 355 height: 16px !important; 356 width: 16px !important; 357 left: 2px !important; 358 bottom: 2px !important; 359 } 360 361 .ai-consent-switch input:checked + .ai-consent-slider:before { 362 transform: translateX(20px) !important; 315 363 } 316 364 317 365 .ai-consent-footer { 318 padding: 15px 20px; 366 padding: 10px 12px !important; 367 } 368 369 .ai-consent-links { 370 gap: 8px !important; 371 margin-bottom: 10px !important; 372 } 373 374 .ai-consent-links a { 375 font-size: 10px !important; 319 376 } 320 377 321 378 .ai-consent-actions { 322 flex-direction: column; 379 flex-direction: row !important; 380 flex-wrap: wrap !important; 381 gap: 4px !important; 382 justify-content: center !important; 323 383 } 324 384 325 385 .ai-consent-btn { 326 width: 100%; 327 } 328 329 .ai-consent-links { 330 flex-direction: column; 331 gap: 10px; 332 align-items: center; 386 padding: 5px 6px !important; 387 font-size: 8px !important; 388 flex: 1 1 auto !important; 389 min-width: 55px !important; 390 max-width: 90px !important; 391 white-space: nowrap !important; 392 overflow: hidden !important; 393 text-overflow: ellipsis !important; 394 } 395 396 .ai-consent-btn-reject { 397 flex: 0 1 auto !important; 398 } 399 400 .ai-consent-btn-custom { 401 flex: 1 1 auto !important; 402 } 403 404 .ai-consent-btn-accept { 405 flex: 1.5 1 auto !important; 333 406 } 334 407 335 408 .ai-consent-settings-btn { 336 bottom: 10px; 337 left: 10px; 338 font-size: 12px; 339 padding: 8px 12px; 409 bottom: 8px !important; 410 left: 8px !important; 411 font-size: 10px !important; 412 padding: 6px 10px !important; 413 } 414 } 415 416 /* Very small phones */ 417 @media (max-width: 380px) { 418 .ai-consent-modal { 419 max-width: 260px !important; 420 max-height: 65vh !important; 421 } 422 423 .ai-consent-header h2 { 424 font-size: 13px !important; 425 } 426 427 .ai-consent-header p { 428 font-size: 9px !important; 429 } 430 431 .ai-consent-category-info h3 { 432 font-size: 11px !important; 433 } 434 435 .ai-consent-category-info p { 436 font-size: 9px !important; 437 } 438 439 .ai-consent-btn { 440 font-size: 7px !important; 441 padding: 4px 5px !important; 442 min-width: 45px !important; 443 max-width: 75px !important; 340 444 } 341 445 } -
convertybot/trunk/assets/css/frontend.css
r3444997 r3445596 8 8 bottom: 20px; 9 9 right: 20px; 10 left: auto; 11 top: auto; 10 12 z-index: 999999; 11 13 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; … … 408 410 /* Mobile Responsive */ 409 411 @media (max-width: 480px) { 412 /* Widget container - ensure bottom right on mobile */ 413 .convertybot-widget { 414 bottom: 15px !important; 415 right: 15px !important; 416 left: auto !important; 417 top: auto !important; 418 } 419 420 /* Chat window - NOT full screen, leave some margin to see the site */ 410 421 .convertybot-chat-window { 411 width: 100%; 412 height: 100%; 413 bottom: 0; 414 right: 0; 415 border-radius: 0; 422 width: calc(100% - 20px); 423 height: 70vh; 424 max-height: 500px; 425 bottom: 70px; 426 right: 10px; 427 left: 10px; 428 border-radius: 16px; 416 429 position: fixed; 417 430 } 418 431 432 /* Smaller header on mobile */ 433 .convertybot-chat-header { 434 padding: 12px 14px; 435 } 436 437 .convertybot-chat-header h4 { 438 font-size: 14px; 439 } 440 441 /* Smaller messages on mobile */ 442 .convertybot-chat-messages { 443 padding: 12px; 444 } 445 446 .message-bubble { 447 padding: 8px 12px; 448 font-size: 14px; 449 } 450 451 .message-avatar svg { 452 width: 16px; 453 height: 16px; 454 } 455 456 /* Smaller input area on mobile */ 457 .convertybot-chat-input { 458 padding: 10px; 459 } 460 461 .convertybot-chat-input input { 462 padding: 10px 12px; 463 font-size: 14px; 464 } 465 466 .convertybot-chat-input button { 467 padding: 10px; 468 } 469 470 /* Chat button - fixed position bottom right */ 419 471 .convertybot-chat-button { 420 bottom: 10px; 421 right: 10px; 472 bottom: 15px !important; 473 right: 15px !important; 474 left: auto !important; 475 top: auto !important; 476 width: 50px; 477 height: 50px; 478 font-size: 12px; 479 } 480 481 .convertybot-chat-button svg { 482 width: 22px; 483 height: 22px; 484 } 485 486 /* Hide button text on mobile if any */ 487 .convertybot-chat-button span { 488 display: none; 489 } 490 491 /* Suggestions smaller on mobile */ 492 .suggestion-chip { 493 padding: 5px 10px; 494 font-size: 12px; 422 495 } 423 496 } … … 845 918 } 846 919 847 /* Mobile responsive */920 /* Mobile responsive - product modal */ 848 921 @media (max-width: 480px) { 849 .product-inline-content {850 flex-direction: column;851 }852 853 .product-inline-image {854 width: 100%;855 height: 120px;856 }857 858 922 .ai-products-modal .modal-content { 859 923 width: 95%; 924 max-height: 80vh; 860 925 margin: 10px; 861 926 } 862 927 863 928 .ai-products-modal .products-grid { 864 929 grid-template-columns: 1fr; 930 gap: 12px; 931 } 932 933 .modal-product-card img { 934 height: 150px; 935 } 936 937 .modal-product-info { 938 padding: 12px; 939 } 940 941 .modal-product-info h4 { 942 font-size: 14px; 943 } 944 945 .btn-view-product-modal { 946 padding: 10px 16px; 947 font-size: 13px; 865 948 } 866 949 } -
convertybot/trunk/assets/css/product-cards-inline.css
r3444997 r3445596 161 161 /* Mobile responsiveness */ 162 162 @media (max-width: 480px) { 163 .ai-products-inline { 164 padding: 10px; 165 gap: 10px; 166 } 167 168 .ai-product-card-inline { 169 padding: 10px; 170 } 171 172 /* Keep horizontal layout on mobile, just smaller */ 163 173 .product-inline-content { 164 174 flex-direction: column; 165 } 166 175 gap: 8px; 176 } 177 178 .product-inline-header { 179 flex-direction: row; 180 gap: 10px; 181 } 182 167 183 .product-inline-image { 168 width: 100%; 169 height: 150px; 170 } 171 } 184 width: 50px; 185 height: 50px; 186 flex-shrink: 0; 187 } 188 189 .product-inline-title h5 { 190 font-size: 13px; 191 line-height: 1.3; 192 } 193 194 .product-inline-description { 195 font-size: 12px; 196 -webkit-line-clamp: 2; 197 } 198 199 .product-inline-price { 200 font-size: 14px; 201 } 202 203 .product-inline-link { 204 padding: 5px 10px; 205 font-size: 12px; 206 } 207 208 .ai-more-products-btn { 209 padding: 8px 16px; 210 font-size: 11px; 211 } 212 } -
convertybot/trunk/assets/css/products-modal-improved.css
r3437100 r3445596 49 49 } 50 50 51 /* Header */ 52 .ai-products-modal-header { 51 /* Header - gradient with white text (consistent across all devices) */ 52 .ai-products-modal-header, 53 .ai-products-modal .modal-header { 53 54 display: flex; 54 55 justify-content: space-between; 55 56 align-items: center; 56 57 padding: 16px 20px; 57 border-bottom: 1px solid #e0e0e0; 58 background: #f8f9fa; 59 } 60 61 .ai-products-modal-header h3 { 58 border-bottom: none; 59 background: linear-gradient(135deg, var(--convertybot-primary, #007cba) 0%, #005a8a 100%); 60 color: white; 61 border-radius: 12px 12px 0 0; 62 } 63 64 .ai-products-modal-header h3, 65 .ai-products-modal .modal-header h3 { 62 66 margin: 0; 63 67 font-size: 18px; 64 68 font-weight: 600; 65 color: #333; 66 } 67 68 /* Close Button */ 69 .ai-products-modal-close { 70 background: none; 69 color: white; 70 } 71 72 /* Close Button - white to match gradient header */ 73 .ai-products-modal-close, 74 .ai-products-modal .modal-close { 75 background: rgba(255, 255, 255, 0.2); 71 76 border: none; 72 77 font-size: 24px; 73 color: #999;78 color: white; 74 79 cursor: pointer; 75 80 padding: 0; … … 83 88 } 84 89 85 .ai-products-modal-close:hover { 86 background: #e0e0e0; 87 color: #333; 90 .ai-products-modal-close:hover, 91 .ai-products-modal .modal-close:hover { 92 background: rgba(255, 255, 255, 0.4); 93 color: white; 88 94 } 89 95 … … 247 253 248 254 @media (max-width: 768px) { 249 /* Modal takes full screen on mobile */ 255 /* Modal overlay - centered with padding */ 256 .ai-products-modal { 257 padding: 20px !important; 258 align-items: center !important; 259 justify-content: center !important; 260 } 261 262 /* Modal content - NOT full screen, centered with margins */ 250 263 .ai-products-modal .modal-content { 251 max-width: 100%; 252 max-height: 100vh; 253 width: 100%; 254 height: 100%; 255 border-radius: 0; 256 margin: 0; 257 } 258 259 /* Header - smaller on mobile */ 264 max-width: 320px !important; 265 width: calc(100% - 40px) !important; 266 max-height: 70vh !important; 267 height: auto !important; 268 border-radius: 12px !important; 269 margin: auto !important; 270 box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3) !important; 271 } 272 273 /* Header - proper styling with gradient and WHITE text */ 274 .ai-products-modal .modal-header, 260 275 .ai-products-modal-header { 261 padding: 12px 16px; 262 } 263 276 padding: 10px 12px !important; 277 background: linear-gradient(135deg, var(--convertybot-primary, #007cba) 0%, #005a8a 100%) !important; 278 color: white !important; 279 border-radius: 12px 12px 0 0 !important; 280 } 281 282 .ai-products-modal .modal-header h3, 264 283 .ai-products-modal-header h3 { 265 font-size: 16px; 266 } 267 284 font-size: 12px !important; 285 color: white !important; 286 margin: 0 !important; 287 font-weight: 600 !important; 288 } 289 290 .ai-products-modal .modal-close, 268 291 .ai-products-modal-close { 269 font-size: 22px; 270 width: 28px; 271 height: 28px; 272 } 273 274 /* Body - less padding */ 292 font-size: 18px !important; 293 width: 24px !important; 294 height: 24px !important; 295 color: white !important; 296 background: rgba(255, 255, 255, 0.2) !important; 297 border-radius: 50% !important; 298 display: flex !important; 299 align-items: center !important; 300 justify-content: center !important; 301 } 302 303 /* Body - compact */ 304 .ai-products-modal .modal-body, 275 305 .ai-products-modal-body { 276 padding: 12px; 306 padding: 8px !important; 307 max-height: 50vh !important; 308 overflow-y: auto !important; 309 background: #f8f9fa !important; 277 310 } 278 311 279 312 /* Single column on mobile */ 280 .ai-products-grid { 281 grid-template-columns: 1fr; 282 gap: 12px; 283 } 284 285 /* Smaller product cards on mobile */ 286 .ai-product-card-modal { 287 display: flex; 288 flex-direction: row; 289 min-height: 120px; 290 } 291 292 .ai-product-card-modal img { 293 width: 120px; 294 height: 120px; 295 flex-shrink: 0; 296 border-bottom: none; 297 border-right: 1px solid #e0e0e0; 298 } 299 300 .ai-product-info { 301 padding: 10px; 302 flex: 1; 303 } 304 305 .ai-product-info h4 { 306 font-size: 13px; 307 -webkit-line-clamp: 2; 308 min-height: auto; 309 margin-bottom: 6px; 310 } 311 312 .ai-product-rating { 313 margin-bottom: 6px; 314 font-size: 11px; 315 } 316 317 .ai-product-rating .stars { 318 font-size: 12px; 319 } 320 321 .ai-product-description { 322 font-size: 11px; 323 -webkit-line-clamp: 2; 324 margin-bottom: 8px; 325 } 326 327 .ai-product-price { 328 font-size: 14px; 329 margin-bottom: 8px; 330 } 331 332 .ai-product-btn { 333 padding: 6px 10px; 334 font-size: 12px; 313 .ai-products-grid, 314 .products-grid { 315 grid-template-columns: 1fr !important; 316 gap: 6px !important; 317 } 318 319 /* Compact product cards - horizontal layout */ 320 .ai-product-card-modal, 321 .modal-product-card { 322 display: flex !important; 323 flex-direction: row !important; 324 min-height: 60px !important; 325 padding: 0 !important; 326 background: white !important; 327 border-radius: 6px !important; 328 overflow: hidden !important; 329 } 330 331 .ai-product-card-modal img, 332 .modal-product-card img { 333 width: 55px !important; 334 height: 55px !important; 335 flex-shrink: 0 !important; 336 border-bottom: none !important; 337 border-right: 1px solid #e0e0e0 !important; 338 border-radius: 0 !important; 339 object-fit: cover !important; 340 } 341 342 .ai-product-info, 343 .modal-product-card .product-info { 344 padding: 5px 6px !important; 345 flex: 1 !important; 346 display: flex !important; 347 flex-direction: column !important; 348 justify-content: center !important; 349 gap: 2px !important; 350 } 351 352 .ai-product-info h4, 353 .modal-product-card .product-info h5 { 354 font-size: 10px !important; 355 -webkit-line-clamp: 1 !important; 356 min-height: auto !important; 357 margin: 0 0 2px 0 !important; 358 line-height: 1.2 !important; 359 overflow: hidden !important; 360 text-overflow: ellipsis !important; 361 white-space: nowrap !important; 362 } 363 364 /* Show rating on mobile with smaller size */ 365 .ai-product-rating, 366 .modal-product-card .product-rating { 367 display: flex !important; 368 font-size: 8px !important; 369 gap: 2px !important; 370 margin-bottom: 3px !important; 371 } 372 373 .ai-product-rating .stars, 374 .modal-product-card .product-rating .stars { 375 font-size: 9px !important; 376 letter-spacing: 0 !important; 377 } 378 379 .ai-product-rating span:last-child, 380 .modal-product-card .product-rating .reviews { 381 font-size: 7px !important; 382 } 383 384 /* Show description on mobile with smaller size */ 385 .ai-product-description, 386 .modal-product-card .product-description { 387 display: -webkit-box !important; 388 font-size: 8px !important; 389 line-height: 1.2 !important; 390 -webkit-line-clamp: 2 !important; 391 -webkit-box-orient: vertical !important; 392 overflow: hidden !important; 393 margin-bottom: 4px !important; 394 } 395 396 .ai-product-price, 397 .modal-product-card .price { 398 font-size: 10px !important; 399 margin: 0 !important; 400 color: #e74c3c !important; 401 font-weight: bold !important; 402 } 403 404 .ai-product-btn, 405 .btn-view-product-modal { 406 padding: 3px 6px !important; 407 font-size: 8px !important; 408 border-radius: 3px !important; 409 margin-top: 2px !important; 410 display: inline-block !important; 411 width: auto !important; 335 412 } 336 413 337 414 /* Show More Button */ 338 .ai-show-more-btn { 339 font-size: 13px; 340 padding: 10px 20px; 341 margin-top: 12px; 415 .ai-show-more-btn, 416 .modal-show-more { 417 font-size: 10px !important; 418 padding: 6px 12px !important; 419 margin-top: 8px !important; 342 420 } 343 421 } 344 422 345 423 /* Small phones */ 346 @media (max-width: 480px) { 347 .ai-product-card-modal img { 348 width: 100px; 349 height: 100px; 350 } 351 352 .ai-product-info h4 { 353 font-size: 12px; 354 } 355 356 .ai-product-price { 357 font-size: 13px; 358 } 359 360 .ai-product-btn { 361 font-size: 11px; 362 padding: 5px 8px; 424 @media (max-width: 380px) { 425 .ai-products-modal .modal-content { 426 max-width: 280px !important; 427 max-height: 65vh !important; 428 } 429 430 .ai-product-card-modal img, 431 .modal-product-card img { 432 width: 45px !important; 433 height: 45px !important; 434 } 435 436 .ai-product-info h4, 437 .modal-product-card .product-info h5 { 438 font-size: 9px !important; 439 } 440 441 .ai-product-price, 442 .modal-product-card .price { 443 font-size: 9px !important; 444 } 445 446 .ai-product-btn, 447 .btn-view-product-modal { 448 font-size: 7px !important; 449 padding: 2px 4px !important; 363 450 } 364 451 } -
convertybot/trunk/assets/js/frontend.js
r3444997 r3445596 68 68 const hasExistingSession = this.loadSession(); 69 69 70 // Handle autoOpen setting 71 if (convertyBotConfig.autoOpen) { 72 $('#convertybot-widget').attr('data-chat-open', 'true'); 73 $('#convertybot-chat-button').addClass('convertybot-hidden').hide(); 74 $('#convertybot-chat-window').addClass('convertybot-visible').css('display', 'flex'); 75 this.isOpen = true; 76 } else { 77 $('#convertybot-chat-button').show(); 78 } 79 70 80 // Show the widget 71 81 $('#convertybot-widget').show(); … … 78 88 this.createNewLocalSession(); 79 89 } 80 90 81 91 // Bind events 82 92 this.bindEvents(); 83 84 // Auto-open if configured93 94 // Auto-open: focus input after a short delay (chat is already open) 85 95 if (convertyBotConfig.autoOpen) { 86 96 setTimeout(() => { 87 this.openChat(); 88 }, 2000); 97 $('#convertybot-message-input').focus(); 98 this.trackEvent('chat_opened'); 99 }, 500); 89 100 } 90 101 … … 383 394 openChat: function() { 384 395 console.log('Opening chat...'); 396 const widget = $('#convertybot-widget'); 385 397 const chatWindow = $('#convertybot-chat-window'); 386 398 const chatButton = $('#convertybot-chat-button'); 387 399 388 // Use both class and direct style for reliability 389 chatWindow.removeClass('convertybot-hidden').addClass('convertybot-visible'); 390 chatWindow.css('display', 'flex'); 391 chatButton.addClass('convertybot-hidden').removeClass('convertybot-visible'); 392 chatButton.css('display', 'none'); 400 // Set data attribute for CSS targeting 401 widget.attr('data-chat-open', 'true'); 402 403 // Show chat window 404 chatWindow.addClass('convertybot-visible').css('display', 'flex'); 405 406 // Hide button 407 chatButton.addClass('convertybot-hidden').hide(); 393 408 394 409 this.isOpen = true; … … 401 416 // Track event 402 417 this.trackEvent('chat_opened'); 403 console.log('Chat opened, button hidden');404 418 }, 405 419 … … 407 421 closeChat: function() { 408 422 console.log('Closing chat...'); 423 const widget = $('#convertybot-widget'); 409 424 const chatWindow = $('#convertybot-chat-window'); 410 425 const chatButton = $('#convertybot-chat-button'); 411 426 412 // Use both class and direct style for reliability 413 chatWindow.addClass('convertybot-hidden').removeClass('convertybot-visible'); 414 chatWindow.css('display', 'none'); 415 chatButton.removeClass('convertybot-hidden').addClass('convertybot-visible'); 416 chatButton.css('display', 'flex'); 427 // Remove data attribute 428 widget.attr('data-chat-open', 'false'); 429 430 // Hide chat window 431 chatWindow.removeClass('convertybot-visible').css('display', 'none'); 432 433 // Show button 434 chatButton.removeClass('convertybot-hidden').show(); 417 435 418 436 this.isOpen = false; … … 651 669 this.messageHistory.push(historyItem); 652 670 this.saveSession(); 653 654 // Scroll to bottom 655 messagesContainer.scrollTop(messagesContainer[0].scrollHeight); 671 672 // Scroll behavior: for bot messages, scroll to the START of the message so user can read from beginning 673 const lastAddedMessage = messagesContainer.find('.convertybot-message').last(); 674 if (type === 'bot' && lastAddedMessage.length) { 675 // Scroll to the top of the new bot message 676 const messageTop = lastAddedMessage[0].offsetTop - 10; // 10px padding 677 messagesContainer.scrollTop(messageTop); 678 } else { 679 // For user messages, scroll to bottom as usual 680 messagesContainer.scrollTop(messagesContainer[0].scrollHeight); 681 } 656 682 657 683 // Play sound if enabled … … 729 755 </div> 730 756 <div class="product-inline-footer"> 731 <div class="product-inline-price">${product.price_html || product.price || 'Prix sur demande'}</div>757 <div class="product-inline-price">${product.price_html || this.formatPrice(product.price)}</div> 732 758 <a href="${product.url || '#'}" class="product-inline-link" target="_blank" rel="noopener noreferrer"> 733 759 ${convertyBotConfig.viewProductText || 'Voir le produit'} … … 760 786 // Append products HTML INSIDE the message bubble 761 787 messageBubble.append(productsHtml); 762 788 763 789 // Hide the separate products container 764 790 $('#convertybot-products').hide(); 765 766 // Scroll to show new content791 792 // Scroll to the START of the bot message so user can read from beginning 767 793 const messagesContainer = $('#convertybot-chat-messages'); 768 messagesContainer.scrollTop(messagesContainer[0].scrollHeight); 794 const lastBotMsg = messagesContainer.find('.convertybot-message.bot').last(); 795 if (lastBotMsg.length) { 796 const messageTop = lastBotMsg[0].offsetTop - 10; // 10px padding 797 messagesContainer.scrollTop(messageTop); 798 } 769 799 }, 770 800 … … 797 827 </div> 798 828 ` : '<div class="product-rating"><span class="stars">★★★★☆</span> <span class="reviews">(Pas encore d\'avis)</span></div>'} 799 <div class="price">${product.price_html || product.price || 'Prix sur demande'}</div>829 <div class="price">${product.price_html || this.formatPrice(product.price)}</div> 800 830 <div class="product-description">${product.shortDescription || product.description ? this.escapeHtml(product.shortDescription || product.description) : 'Excellent produit recommandé pour vous'}</div> 801 831 <div class="product-actions"> … … 1026 1056 }, 1027 1057 1058 // Format price with currency symbol (fix EUR120 -> 120,00 €) 1059 formatPrice: function(priceData) { 1060 // If already HTML formatted (from WooCommerce), use it 1061 if (typeof priceData === 'string' && (priceData.includes('<span') || priceData.includes('€') || priceData.includes('$'))) { 1062 return priceData; 1063 } 1064 1065 // Extract numeric value from string like "EUR120" or "120" or "120.00" 1066 let numericPrice = priceData; 1067 if (typeof priceData === 'string') { 1068 // Remove currency codes (EUR, USD, etc.) and extract number 1069 numericPrice = priceData.replace(/[A-Z]{3}/gi, '').replace(/[^\d.,]/g, '').trim(); 1070 } 1071 1072 // Parse the number 1073 const price = parseFloat(numericPrice); 1074 if (isNaN(price)) { 1075 return priceData || 'Prix sur demande'; 1076 } 1077 1078 // Format with locale (French style: 120,00 €) 1079 const currencySymbol = convertyBotConfig.currencySymbol || '€'; 1080 const formattedNumber = price.toLocaleString('fr-FR', { 1081 minimumFractionDigits: 2, 1082 maximumFractionDigits: 2 1083 }); 1084 1085 // Return price with symbol after (European style) 1086 return `${formattedNumber} ${currencySymbol}`; 1087 }, 1088 1028 1089 // Format markdown to HTML (safe - escapes HTML first, then converts markdown) 1029 1090 formatMarkdown: function(text) { 1030 if (!text) return ''; 1031 1032 // First escape HTML to prevent XSS 1033 let formatted = this.escapeHtml(text); 1034 1035 // Convert markdown to HTML (order matters!) 1036 1037 // 1. Bold: **text** or __text__ (must be before italic) 1038 formatted = formatted.replace(/\*\*([^*]+?)\*\*/g, '<strong>$1</strong>'); 1039 formatted = formatted.replace(/__([^_]+?)__/g, '<strong>$1</strong>'); 1040 1041 // 2. Italic: *text* or _text_ (simple version, browser compatible) 1042 // Only match single * or _ that are not part of ** or __ 1043 formatted = formatted.replace(/(?:^|[^*])\*([^*\n]+?)\*(?:[^*]|$)/g, function(match, content) { 1044 // Preserve the characters before and after if they exist 1045 const before = match.charAt(0) === '*' ? '' : match.charAt(0); 1046 const after = match.charAt(match.length - 1) === '*' ? '' : match.charAt(match.length - 1); 1047 return before + '<em>' + content + '</em>' + after; 1048 }); 1049 1050 // 3. Inline code: `code` 1051 formatted = formatted.replace(/`([^`]+?)`/g, '<code>$1</code>'); 1052 1053 // 4. Bullet lists: lines starting with - or * (before line breaks conversion) 1054 // Split by newlines, process, then rejoin 1055 const lines = formatted.split('\n'); 1056 let inList = false; 1057 const processedLines = []; 1058 1059 for (let i = 0; i < lines.length; i++) { 1060 const line = lines[i]; 1061 const listMatch = line.match(/^[\-\*]\s+(.+)$/); 1062 1063 if (listMatch) { 1064 if (!inList) { 1065 processedLines.push('<ul>'); 1066 inList = true; 1091 try { 1092 if (!text) return ''; 1093 if (typeof text !== 'string') { 1094 text = String(text); 1095 } 1096 1097 // First escape HTML to prevent XSS 1098 let formatted = this.escapeHtml(text); 1099 1100 // Convert markdown to HTML (order matters!) 1101 1102 // 1. Bold: **text** or __text__ (must be before italic) 1103 formatted = formatted.replace(/\*\*([^*]+?)\*\*/g, '<strong>$1</strong>'); 1104 formatted = formatted.replace(/__([^_]+?)__/g, '<strong>$1</strong>'); 1105 1106 // 2. Italic: *text* (after bold conversion, remaining single * are italic) 1107 // Since ** is already converted to <strong>, remaining *text* patterns are italic 1108 formatted = formatted.replace(/\*([^*\n]+?)\*/g, '<em>$1</em>'); 1109 1110 // 3. Inline code: `code` 1111 formatted = formatted.replace(/`([^`]+?)`/g, '<code>$1</code>'); 1112 1113 // 4. Bullet lists: lines starting with - or * (before line breaks conversion) 1114 const lines = formatted.split('\n'); 1115 let inList = false; 1116 const processedLines = []; 1117 1118 for (let i = 0; i < lines.length; i++) { 1119 const line = lines[i]; 1120 const listMatch = line.match(/^[\-\*]\s+(.+)$/); 1121 1122 if (listMatch) { 1123 if (!inList) { 1124 processedLines.push('<ul>'); 1125 inList = true; 1126 } 1127 processedLines.push('<li>' + listMatch[1] + '</li>'); 1128 } else { 1129 if (inList) { 1130 processedLines.push('</ul>'); 1131 inList = false; 1132 } 1133 processedLines.push(line); 1067 1134 } 1068 processedLines.push('<li>' + listMatch[1] + '</li>'); 1069 } else { 1070 if (inList) { 1071 processedLines.push('</ul>'); 1072 inList = false; 1073 } 1074 processedLines.push(line); 1075 } 1076 } 1077 1078 if (inList) { 1079 processedLines.push('</ul>'); 1080 } 1081 1082 formatted = processedLines.join('\n'); 1083 1084 // 5. Line breaks: \n to <br> (but not inside lists) 1085 formatted = formatted.replace(/\n(?!<\/?[uo]l|<\/?li)/g, '<br>'); 1086 formatted = formatted.replace(/\n/g, ''); 1087 1088 return formatted; 1135 } 1136 1137 if (inList) { 1138 processedLines.push('</ul>'); 1139 } 1140 1141 formatted = processedLines.join('\n'); 1142 1143 // 5. Line breaks: \n to <br> (but not inside lists) 1144 formatted = formatted.replace(/\n(?!<\/?[uo]l|<\/?li)/g, '<br>'); 1145 formatted = formatted.replace(/\n/g, ''); 1146 1147 return formatted; 1148 } catch (error) { 1149 console.error('formatMarkdown error:', error); 1150 // Fallback: just escape HTML and convert newlines 1151 return this.escapeHtml(text).replace(/\n/g, '<br>'); 1152 } 1089 1153 }, 1090 1154 … … 1252 1316 } 1253 1317 1254 // Remove or replace problematic characters 1318 // Remove problematic control characters BUT PRESERVE newlines (\n = \u000A) and tabs (\t = \u0009) 1319 // Control chars: \u0000-\u0008, \u000B-\u000C, \u000E-\u001F, \u007F-\u009F 1255 1320 return content 1256 .replace(/[\u0000-\u001F\u007F-\u009F]/g, '') // Remove control characters 1257 .replace(/\u2028/g, ' ') // Replace line separator 1258 .replace(/\u2029/g, ' ') // Replace paragraph separator 1321 .replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]/g, '') // Remove control chars except \t, \n, \r 1322 .replace(/\r\n/g, '\n') // Normalize Windows line endings 1323 .replace(/\r/g, '\n') // Normalize old Mac line endings 1324 .replace(/\u2028/g, '\n') // Replace line separator with newline 1325 .replace(/\u2029/g, '\n\n') // Replace paragraph separator with double newline 1259 1326 .trim(); 1260 1327 }, -
convertybot/trunk/convertybot.php
r3444997 r3445596 3 3 * Plugin Name: ConvertyBot 4 4 * Description: An intelligent AI-powered sales assistant for WooCommerce that helps visitors discover products, provides personalized recommendations, and generates dynamic discount codes to boost sales. 5 * Version: 1.0. 165 * Version: 1.0.21 6 6 * Author: ConvertyBot, 2wstechnologies Team 7 7 * Author URI: https://convertybot.com … … 42 42 43 43 // Define plugin constants 44 define('CONVERTYBOT_VERSION', '1.0. 16');44 define('CONVERTYBOT_VERSION', '1.0.26'); 45 45 define('CONVERTYBOT_PLUGIN_URL', plugin_dir_url(__FILE__)); 46 46 define('CONVERTYBOT_PLUGIN_PATH', plugin_dir_path(__FILE__)); -
convertybot/trunk/readme.txt
r3444997 r3445596 6 6 Tested up to: 6.9 7 7 Requires PHP: 7.2 8 Stable tag: 1.0. 168 Stable tag: 1.0.26 9 9 License: GPLv2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 249 249 == Changelog == 250 250 251 = 1.0.26 = 252 * FIXED: Chat window not closing when minimize button clicked 253 * FIXED: Removed CSS rule that was preventing chat from hiding (display: flex !important) 254 * IMPROVED: Chat visibility now properly controlled by .convertybot-visible class 255 256 = 1.0.25 = 257 * FIXED: Page load performance issues caused by aggressive JavaScript 258 * REMOVED: MutationObserver and multiple timeout watchers that slowed page load 259 * SIMPLIFIED: Button show/hide logic using standard jQuery methods 260 261 = 1.0.24 = 262 * FIXED: Chat button visibility improvements 263 * ADDED: Global function for button hiding 264 265 = 1.0.23 = 266 * FIXED: Mobile font size (10px) for chat messages now properly applied 267 * FIXED: Mobile avatar positioning (bot: left -10px, user: right -11px) 268 * IMPROVED: CSS specificity for mobile styles in chatbot-improvements.css 269 270 = 1.0.22 = 271 * ADDED: Inline styles in PHP template for mobile responsiveness 272 * IMPROVED: Button hiding mechanism 273 274 = 1.0.21 = 275 * IMPROVED: Mobile responsive design - smaller, more compact chat interface 276 * FIXED: Message text size reduced to 12px for better mobile readability 277 * FIXED: Suggestion chips font size optimized for mobile (10px) 278 * FIXED: Chat button visibility issue on initial page load with auto-open 279 * FIXED: Cookie consent banner button text overflow on mobile 280 * IMPROVED: Better user experience on small screens 281 282 = 1.0.20 = 283 * FIXED: Auto-scroll now scrolls to the START of bot messages (not the end) 284 * FIXED: Currency format display (EUR120 now shows as 120,00 €) 285 * IMPROVED: Price formatting with proper locale support 286 * FIXED: Suggestion chips no longer require horizontal scroll on mobile 287 * IMPROVED: Cookie consent banner mobile layout 288 289 = 1.0.19 = 290 * IMPROVED: Mobile responsive chat window - positioned in bottom-right corner 291 * IMPROVED: Products modal with margins and centered layout on mobile 292 * IMPROVED: Cookie consent banner compact design for mobile 293 * FIXED: Chat window no longer covers full screen on mobile devices 294 * REDUCED: All mobile element sizes for better UX 295 296 = 1.0.18 = 297 * FIXED: Message formatting preserved after page navigation 298 * FIXED: Bot message HTML/CSS formatting no longer lost on reload 299 * FIXED: Newline characters preserved in sanitizeMessageContent() 300 301 = 1.0.17 = 302 * FIXED: Sender name in support emails 303 * FIXED: Last occurrence of old plugin name updated to ConvertyBot 304 * IMPROVED: Brand consistency across all plugin files 305 306 = 1.0.16 = 307 * NEW: Tax inclusion in payment sessions 308 * FIXED: Deleted customer ID handling for subscription retry 309 * FIXED: Z-index problems in modals for plugin interfaces 310 * ADDED: Confirmation dialogs before subscription upgrade/downgrade 311 312 = 1.0.15 = 313 * NEW: Usage tracking for monthly conversations and API calls 314 * IMPROVED: Plugin ready for marketplace submission 315 * FIXED: Various UI/UX improvements 316 251 317 = 1.0.14 = 252 318 * Full WordPress Plugin Check compliance … … 294 360 == Upgrade Notice == 295 361 362 = 1.0.26 = 363 Critical fix - Chat window can now be properly closed/minimized. Also fixes mobile font sizes and avatar positioning. 364 365 = 1.0.21 = 366 Mobile experience update - Significantly improved mobile responsive design with smaller, more compact chat interface. Recommended for all users with mobile visitors. 367 368 = 1.0.20 = 369 UX improvements - Better auto-scroll behavior and proper currency formatting. Recommended update. 370 371 = 1.0.19 = 372 Major mobile responsive update - Chat window and modals now properly sized for mobile devices. 373 296 374 = 1.0.14 = 297 375 WordPress Plugin Check compliance update - Recommended for all users. Includes security improvements and internationalization enhancements. -
convertybot/trunk/templates/frontend/chatbot-widget.php
r3437100 r3445596 10 10 11 11 $options = get_option('convertybot_options', array()); 12 $auto_open = !empty($options['auto_open']); 12 13 ?> 13 14 14 15 <!-- ConvertyBot Widget --> 15 <div id="convertybot-widget" class="convertybot-widget" style="display: none;" >16 <!-- Modern Chat Button - ->17 <div id="convertybot-chat-button" class="convertybot-chat-button ">16 <div id="convertybot-widget" class="convertybot-widget" style="display: none;"<?php echo $auto_open ? ' data-chat-open="true"' : ''; ?>> 17 <!-- Modern Chat Button - Hidden initially if auto_open is enabled --> 18 <div id="convertybot-chat-button" class="convertybot-chat-button<?php echo $auto_open ? ' convertybot-hidden' : ''; ?>" <?php echo $auto_open ? 'style="display: none !important; visibility: hidden !important; opacity: 0 !important; width: 0 !important; height: 0 !important;"' : ''; ?>> 18 19 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 19 20 <path d="m3 21 1.9-5.7a8.5 8.5 0 1 1 3.8 3.8z"/> … … 22 23 <span class="convertybot-badge" style="display: none;">0</span> 23 24 </div> 24 25 <!-- Chat Window - ->26 <div id="convertybot-chat-window" class="convertybot-chat-window " style="display: none;">25 26 <!-- Chat Window - Shown initially if auto_open is enabled --> 27 <div id="convertybot-chat-window" class="convertybot-chat-window<?php echo $auto_open ? ' convertybot-visible' : ''; ?>" style="display: <?php echo $auto_open ? 'flex' : 'none'; ?>;"> 27 28 <!-- Header --> 28 29 <div class="convertybot-chat-header"> … … 126 127 <div class="modal-content" onclick="event.stopPropagation()"> 127 128 <div class="modal-header"> 128 <h3><?php e sc_html_e('All Recommended Products', 'convertybot'); ?></h3>129 <button class="modal-close" onclick="ConvertyBotChat.closeProductsModal()" >×</button>129 <h3><?php echo esc_html__('Tous les produits recommandés', 'convertybot'); ?></h3> 130 <button class="modal-close" onclick="ConvertyBotChat.closeProductsModal()" aria-label="<?php esc_attr_e('Fermer', 'convertybot'); ?>">×</button> 130 131 </div> 131 132 <div class="modal-body">
Note: See TracChangeset
for help on using the changeset viewer.