Commit Graph
57 Commits
Author SHA1 Message Date
ogrechkoandClaude Sonnet 5 cda92de9d2 Mobile-responsive admin nav/thread header, real dark theme pass
Nav overflowed the viewport on phones (confirmed via screenshot) — header
now wraps, nav row scrolls horizontally instead of pushing user/theme/
logout off-screen, ticket-thread's status/assignee selects stack full-width
below the subject on narrow screens.

Dark theme got a real pass instead of reusing near-identical values:
deeper/richer surfaces, punchier accent (#8b5cf6, matches the already-
validated dark chart-1), a subtle violet glow behind the page, and a
dark-appropriate card shadow (inset highlight + soft shadow — the flat
black shadow from light mode was invisible on a dark surface).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QcXH24ky6zjk2UyK5oZUPH
2026-07-26 15:10:57 +00:00
ogrechkoandClaude Sonnet 5 9f1413f0b9 Design overhaul, stats page, internal notes
Design: Onest+Unbounded font pairing (Cyrillic-verified, replacing plain
Golos Text), manual light/dark toggle wired to the data-theme cascade
already built in MVP-1, refreshed palette + new chart-mark tokens
(CVD-validated via the dataviz skill's validator), colored avatar
initials, per-channel colored badges, favicon, nicer empty states.

Stats: /stats page — status/channel breakdown, 14-day ticket volume,
avg first-response time, per-agent open-ticket workload. Colors and
chart forms follow the dataviz skill's procedure (categorical order
re-stepped to clear the CVD adjacency check in both themes).

Internal notes: messages.visibility ("public"/"internal") column.
Agent-only notes never reach customer-facing reads (getTicketForCustomer)
or the customer SSE stream (/api/portal/events, reused by the widget) —
fixed at both the initial-fetch and live-delivery layers.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QcXH24ky6zjk2UyK5oZUPH
2026-07-26 14:38:52 +00:00
ogrechkoandClaude Sonnet 5 4efce5f307 Add embeddable chat widget for websites
Reuses the existing portal-token/SSE mechanism (customers.portalToken,
/api/portal/events) for anonymous widget visitors instead of building a
parallel auth system. Public API: session bootstrap + messages endpoint,
both scoped by a non-secret siteKey with optional origin allowlist.
Embeddable script (public/widget.js) is a small self-contained vanilla JS
file: floating button + iframe kept mounted for a live SSE connection,
with a postMessage bridge for the unread badge. Admin UI at
Settings -> Виджет manages sites and shows the embed snippet.

Also generalized recordTelegramInboundMessage -> recordChatInboundMessage
(channel param) since Telegram and the widget need the identical
find-or-create-open-ticket heuristic.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QcXH24ky6zjk2UyK5oZUPH
2026-07-26 13:34:08 +00:00
ogrechkoandClaude Sonnet 5 59e6c32d79 Fix IMAP idle loop: react to 'exists' event, not idle() resolution
client.idle() resolves on re-idle/connection events, not per new message —
new mail is signaled via the 'exists' event while IDLE is active. The
previous loop awaited idle() expecting it to return per message, so new
mail was only ever caught on the very first pass. Also made unseen-message
processing resilient to a message vanishing between search and fetch
(handle one UID at a time, each in its own try/catch) and added logging
to make the pipeline observable.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QcXH24ky6zjk2UyK5oZUPH
2026-07-26 13:11:21 +00:00
ogrechkoandClaude Sonnet 5 7e62ed739b Add email channel: IMAP IDLE inbound, SMTP outbound, thread matching
Inbound mail on support@top-sysops.ru creates/updates tickets in realtime
(IMAP IDLE, not polling). Replies thread via In-Reply-To/References against
stored Message-IDs, falling back to the customer's open ticket. Mailbox
credentials configured and encrypted via Settings -> Почта, same pattern as
the Telegram channel. TLS verification is opt-in-skippable per mailbox
(mail.top-sysops.ru's cert is currently expired; LAN-only server).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QcXH24ky6zjk2UyK5oZUPH
2026-07-26 13:01:21 +00:00
ogrechkoandClaude Sonnet 5 cf0b6cf58e MVP-1: helpdesk core with dashboard, Telegram channel, customer portal
Next.js 16 + Drizzle/SQLite (matching ~/project-claude conventions), SSE-based
realtime updates, admin dashboard with status columns, ticket thread view,
Telegram long-polling integration (inbound + outbound), token-based customer
portal, Docker Compose packaging.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QcXH24ky6zjk2UyK5oZUPH
2026-07-26 12:40:56 +00:00
ogrechko 888b7b82ba Initial commit 2026-07-26 11:44:15 +00:00