diff --git a/apps/customer-operations/src/pages/SupportInboxPage.tsx b/apps/customer-operations/src/pages/SupportInboxPage.tsx
index 5ed4ff4e..cdc5204c 100644
--- a/apps/customer-operations/src/pages/SupportInboxPage.tsx
+++ b/apps/customer-operations/src/pages/SupportInboxPage.tsx
@@ -1,7 +1,8 @@
import { CocCard, CocMetric } from '../components/CocCard'
-import { CocEmpty, CocError, CocLoading, StatusBadge, formatDate } from '../components/CocDataStates'
+import { CocEmpty, CocLoading, StatusBadge, formatDate } from '../components/CocDataStates'
import { CocPageFrame } from '../components/CocPageFrame'
import { getCollection, useCocApi } from '../lib/coc-api'
+import { CocServiceBanner } from '../lib/coc-status'
type InboxItem = {
id?: string
@@ -29,7 +30,7 @@ export default function SupportInboxPage() {
description="Unified omni-channel inbox. AI agents triage every item first; only exceptions surface for a human (RULE-003, RULE-004)."
>
{isLoading ?
diff --git a/apps/customer-operations/src/pages/TicketCenterPage.tsx b/apps/customer-operations/src/pages/TicketCenterPage.tsx
index a076f3cf..92352ee4 100644
--- a/apps/customer-operations/src/pages/TicketCenterPage.tsx
+++ b/apps/customer-operations/src/pages/TicketCenterPage.tsx
@@ -1,8 +1,9 @@
import { useMemo, useState } from 'react'
import { CocCard, CocMetric } from '../components/CocCard'
-import { CocEmpty, CocError, CocLoading, StatusBadge, formatDate } from '../components/CocDataStates'
+import { CocEmpty, CocLoading, StatusBadge, formatDate } from '../components/CocDataStates'
import { CocPageFrame } from '../components/CocPageFrame'
import { getCollection, useCocApi } from '../lib/coc-api'
+import { CocServiceBanner } from '../lib/coc-status'
type Ticket = {
id?: string
@@ -43,7 +44,7 @@ export default function TicketCenterPage() {
description="Full lifecycle management for every customer ticket, from AI auto-resolution through human closure."
>
{isLoading ?
: null}
- {!isLoading && error ?
: null}
+
diff --git a/apps/customer-operations/vitest.config.ts b/apps/customer-operations/vitest.config.ts
new file mode 100644
index 00000000..6632f781
--- /dev/null
+++ b/apps/customer-operations/vitest.config.ts
@@ -0,0 +1,13 @@
+import { defineConfig } from 'vitest/config'
+
+/**
+ * Unit tests live under src/ and run in the default (node) environment.
+ * The Playwright E2E suite under e2e/ is excluded — it is run separately via
+ * `npm run e2e` (playwright test), not by vitest.
+ */
+export default defineConfig({
+ test: {
+ include: ['src/**/*.{test,spec}.{ts,tsx}'],
+ exclude: ['e2e/**', 'node_modules/**', 'dist/**'],
+ },
+})
diff --git a/package-lock.json b/package-lock.json
index c3d7b774..53951e13 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -538,6 +538,7 @@
"react-router-dom": "^6.30.4"
},
"devDependencies": {
+ "@playwright/test": "^1.49.1",
"@types/react": "^18.3.0",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.2.0",
@@ -7476,6 +7477,22 @@
"node": ">=14"
}
},
+ "node_modules/@playwright/test": {
+ "version": "1.49.1",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.1.tgz",
+ "integrity": "sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "playwright": "1.49.1"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@prisma/instrumentation": {
"version": "5.22.0",
"resolved": "https://registry.npmjs.org/@prisma/instrumentation/-/instrumentation-5.22.0.tgz",
@@ -20652,6 +20669,53 @@
"node": ">=4"
}
},
+ "node_modules/playwright": {
+ "version": "1.49.1",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.1.tgz",
+ "integrity": "sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "playwright-core": "1.49.1"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.2"
+ }
+ },
+ "node_modules/playwright-core": {
+ "version": "1.49.1",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.1.tgz",
+ "integrity": "sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "playwright-core": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/playwright/node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
"node_modules/plist": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz",