diff --git a/app/resources/js/components/support/JivoWidget.vue b/app/resources/js/components/support/JivoWidget.vue
new file mode 100644
index 00000000..6f558ed0
--- /dev/null
+++ b/app/resources/js/components/support/JivoWidget.vue
@@ -0,0 +1,30 @@
+
+
+
+
+
+
diff --git a/app/resources/js/layouts/AppLayout.vue b/app/resources/js/layouts/AppLayout.vue
index 4d1e8fd9..e25064a6 100644
--- a/app/resources/js/layouts/AppLayout.vue
+++ b/app/resources/js/layouts/AppLayout.vue
@@ -20,6 +20,7 @@ import AppSidebar from '../components/layout/AppSidebar.vue';
import AppTopbar from '../components/layout/AppTopbar.vue';
import DevIndexBadge from '../components/DevIndexBadge.vue';
import CommandPalette from '../components/layout/CommandPalette.vue';
+import JivoWidget from '../components/support/JivoWidget.vue';
import BalanceFrozenBanner from '../components/billing/BalanceFrozenBanner.vue';
import ImpersonationSessionBanner from '../components/admin/ImpersonationSessionBanner.vue';
@@ -88,6 +89,7 @@ usePolling(loadBalanceStatus, { intervalMs: POLLING_REMINDERS_INTERVAL_MS, enabl
+
diff --git a/app/resources/js/vite-env.d.ts b/app/resources/js/vite-env.d.ts
index 53911541..68901b6d 100644
--- a/app/resources/js/vite-env.d.ts
+++ b/app/resources/js/vite-env.d.ts
@@ -2,6 +2,7 @@
interface ImportMetaEnv {
readonly VITE_YANDEX_SMARTCAPTCHA_SITEKEY?: string;
+ readonly VITE_JIVO_WIDGET_ID?: string;
}
interface ImportMeta {
diff --git a/app/tests/Frontend/JivoWidget.spec.ts b/app/tests/Frontend/JivoWidget.spec.ts
new file mode 100644
index 00000000..98a7a6f7
--- /dev/null
+++ b/app/tests/Frontend/JivoWidget.spec.ts
@@ -0,0 +1,27 @@
+import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
+import { mount } from '@vue/test-utils';
+import JivoWidget from '../../resources/js/components/support/JivoWidget.vue';
+
+beforeEach(() => {
+ document.querySelectorAll('#jivosite-widget-js').forEach((n) => n.remove());
+});
+
+afterEach(() => {
+ vi.unstubAllEnvs();
+});
+
+describe('JivoWidget', () => {
+ it('подгружает скрипт Jivo, когда задан VITE_JIVO_WIDGET_ID', () => {
+ vi.stubEnv('VITE_JIVO_WIDGET_ID', 'abc123');
+ mount(JivoWidget);
+ const script = document.getElementById('jivosite-widget-js') as HTMLScriptElement | null;
+ expect(script).not.toBeNull();
+ expect(script?.src).toContain('code.jivosite.com/widget/abc123');
+ });
+
+ it('ничего не грузит, когда ключ пуст (виджет спит)', () => {
+ vi.stubEnv('VITE_JIVO_WIDGET_ID', '');
+ mount(JivoWidget);
+ expect(document.getElementById('jivosite-widget-js')).toBeNull();
+ });
+});