ajaxter-chat 2.0.1 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +119 -128
- package/dist/components/BlockList/index.d.ts +10 -0
- package/dist/components/BlockList/index.js +33 -0
- package/dist/components/CallScreen/index.d.ts +13 -0
- package/dist/components/CallScreen/index.js +48 -0
- package/dist/components/ChatScreen/index.d.ts +10 -3
- package/dist/components/ChatScreen/index.js +142 -57
- package/dist/components/ChatWidget.js +192 -98
- package/dist/components/EmojiPicker/index.d.ts +8 -0
- package/dist/components/EmojiPicker/index.js +18 -0
- package/dist/components/HomeScreen/index.d.ts +2 -3
- package/dist/components/HomeScreen/index.js +25 -41
- package/dist/components/MaintenanceView/index.d.ts +0 -1
- package/dist/components/MaintenanceView/index.js +4 -6
- package/dist/components/RecentChatsScreen/index.d.ts +4 -3
- package/dist/components/RecentChatsScreen/index.js +7 -37
- package/dist/components/Tabs/BottomTabs.d.ts +1 -1
- package/dist/components/Tabs/BottomTabs.js +25 -20
- package/dist/components/TicketScreen/index.d.ts +3 -3
- package/dist/components/TicketScreen/index.js +39 -56
- package/dist/components/UserListScreen/index.d.ts +2 -4
- package/dist/components/UserListScreen/index.js +33 -62
- package/dist/config/index.d.ts +7 -3
- package/dist/config/index.js +28 -25
- package/dist/hooks/useChat.d.ts +8 -3
- package/dist/hooks/useChat.js +22 -18
- package/dist/hooks/useRemoteConfig.d.ts +6 -0
- package/dist/hooks/useRemoteConfig.js +26 -0
- package/dist/hooks/useWebRTC.d.ts +11 -0
- package/dist/hooks/useWebRTC.js +112 -0
- package/dist/index.d.ts +9 -5
- package/dist/index.js +8 -4
- package/dist/types/index.d.ts +62 -21
- package/dist/utils/chat.d.ts +13 -0
- package/dist/utils/chat.js +62 -0
- package/dist/utils/theme.d.ts +3 -1
- package/dist/utils/theme.js +14 -7
- package/package.json +4 -4
- package/public/chatData.json +162 -0
- package/src/components/BlockList/index.tsx +94 -0
- package/src/components/CallScreen/index.tsx +144 -0
- package/src/components/ChatScreen/index.tsx +403 -139
- package/src/components/ChatWidget.tsx +394 -250
- package/src/components/EmojiPicker/index.tsx +48 -0
- package/src/components/HomeScreen/index.tsx +58 -82
- package/src/components/MaintenanceView/index.tsx +6 -9
- package/src/components/RecentChatsScreen/index.tsx +51 -96
- package/src/components/Tabs/BottomTabs.tsx +45 -37
- package/src/components/TicketScreen/index.tsx +87 -133
- package/src/components/UserListScreen/index.tsx +75 -153
- package/src/config/index.ts +32 -26
- package/src/hooks/useChat.ts +31 -14
- package/src/hooks/useRemoteConfig.ts +26 -0
- package/src/hooks/useWebRTC.ts +130 -0
- package/src/index.ts +26 -15
- package/src/types/index.ts +85 -40
- package/src/utils/chat.ts +70 -0
- package/src/utils/theme.ts +18 -7
- package/dist/hooks/useUsers.d.ts +0 -7
- package/dist/hooks/useUsers.js +0 -26
- package/dist/services/userService.d.ts +0 -2
- package/dist/services/userService.js +0 -9
- package/dist/src/components/ChatScreen/index.d.ts +0 -12
- package/dist/src/components/ChatScreen/index.js +0 -83
- package/dist/src/components/ChatWidget.d.ts +0 -4
- package/dist/src/components/ChatWidget.js +0 -141
- package/dist/src/components/HomeScreen/index.d.ts +0 -9
- package/dist/src/components/HomeScreen/index.js +0 -71
- package/dist/src/components/MaintenanceView/index.d.ts +0 -7
- package/dist/src/components/MaintenanceView/index.js +0 -16
- package/dist/src/components/RecentChatsScreen/index.d.ts +0 -16
- package/dist/src/components/RecentChatsScreen/index.js +0 -38
- package/dist/src/components/Tabs/BottomTabs.d.ts +0 -10
- package/dist/src/components/Tabs/BottomTabs.js +0 -29
- package/dist/src/components/TicketScreen/index.d.ts +0 -9
- package/dist/src/components/TicketScreen/index.js +0 -71
- package/dist/src/components/UserListScreen/index.d.ts +0 -13
- package/dist/src/components/UserListScreen/index.js +0 -64
- package/dist/src/config/index.d.ts +0 -3
- package/dist/src/config/index.js +0 -38
- package/dist/src/hooks/useChat.d.ts +0 -8
- package/dist/src/hooks/useChat.js +0 -26
- package/dist/src/hooks/useUsers.d.ts +0 -7
- package/dist/src/hooks/useUsers.js +0 -26
- package/dist/src/index.d.ts +0 -14
- package/dist/src/index.js +0 -13
- package/dist/src/services/userService.d.ts +0 -2
- package/dist/src/services/userService.js +0 -9
- package/dist/src/types/index.d.ts +0 -59
- package/dist/src/types/index.js +0 -1
- package/dist/src/utils/theme.d.ts +0 -3
- package/dist/src/utils/theme.js +0 -13
- package/src/hooks/useUsers.ts +0 -27
- package/src/services/userService.ts +0 -9
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useRef, useEffect } from 'react';
|
|
3
|
-
import { mergeTheme } from '../../utils/theme';
|
|
4
|
-
export const ChatScreen = ({ activeUser, messages, onSend, onBack, onClose, theme, }) => {
|
|
5
|
-
const t = mergeTheme(theme);
|
|
6
|
-
const [text, setText] = useState('');
|
|
7
|
-
const endRef = useRef(null);
|
|
8
|
-
const inputRef = useRef(null);
|
|
9
|
-
useEffect(() => { var _a; (_a = endRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ behavior: 'smooth' }); }, [messages]);
|
|
10
|
-
const handleSend = () => {
|
|
11
|
-
var _a;
|
|
12
|
-
if (!text.trim())
|
|
13
|
-
return;
|
|
14
|
-
onSend(text);
|
|
15
|
-
setText('');
|
|
16
|
-
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
17
|
-
};
|
|
18
|
-
const handleKey = (e) => {
|
|
19
|
-
if (e.key === 'Enter' && !e.shiftKey) {
|
|
20
|
-
e.preventDefault();
|
|
21
|
-
handleSend();
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
const initials = activeUser.name.split(' ').map(n => n[0]).join('').toUpperCase().slice(0, 2);
|
|
25
|
-
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%', animation: 'cw-slideInRight 0.25s ease' }, children: [_jsxs("div", { style: {
|
|
26
|
-
backgroundColor: t.primaryColor,
|
|
27
|
-
padding: '14px 18px',
|
|
28
|
-
display: 'flex',
|
|
29
|
-
alignItems: 'center',
|
|
30
|
-
gap: '10px',
|
|
31
|
-
flexShrink: 0,
|
|
32
|
-
}, children: [_jsx("button", { onClick: onBack, style: iconBtnStyle, children: _jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M19 12H5M5 12L12 19M5 12L12 5", stroke: "#fff", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }), _jsx("div", { style: {
|
|
33
|
-
width: 36, height: 36, borderRadius: '50%',
|
|
34
|
-
backgroundColor: 'rgba(255,255,255,0.25)',
|
|
35
|
-
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
36
|
-
fontWeight: 700, fontSize: '13px', color: '#fff', flexShrink: 0,
|
|
37
|
-
}, children: initials }), _jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [_jsx("div", { style: { fontWeight: 700, fontSize: '14px', color: '#fff', fontFamily: t.fontFamily }, children: activeUser.name }), _jsxs("div", { style: { fontSize: '11px', color: 'rgba(255,255,255,0.8)', display: 'flex', alignItems: 'center', gap: 4 }, children: [_jsx("span", { style: { width: 6, height: 6, borderRadius: '50%', backgroundColor: '#a8f0c6', display: 'inline-block' } }), "Online"] })] }), _jsx("button", { onClick: onClose, style: iconBtnStyle, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M18 6L6 18M6 6l12 12", stroke: "#fff", strokeWidth: "2.5", strokeLinecap: "round" }) }) })] }), _jsxs("div", { style: {
|
|
38
|
-
flex: 1, overflowY: 'auto', padding: '18px 16px',
|
|
39
|
-
display: 'flex', flexDirection: 'column', gap: '10px',
|
|
40
|
-
backgroundColor: '#f7f8fc',
|
|
41
|
-
}, children: [messages.length === 0 && (_jsxs("div", { style: {
|
|
42
|
-
margin: 'auto', textAlign: 'center',
|
|
43
|
-
fontSize: '13px', color: '#b0bec5',
|
|
44
|
-
fontFamily: t.fontFamily,
|
|
45
|
-
}, children: [_jsx("div", { style: { fontSize: '28px', marginBottom: 8 }, children: "\uD83D\uDCAC" }), "Say hi to ", activeUser.name, "!"] })), messages.map(msg => (_jsx(Bubble, { msg: msg, primaryColor: t.primaryColor, font: t.fontFamily }, msg.id))), _jsx("div", { ref: endRef })] }), _jsxs("div", { style: {
|
|
46
|
-
borderTop: '1px solid #eef0f5',
|
|
47
|
-
padding: '10px 14px',
|
|
48
|
-
backgroundColor: '#fff',
|
|
49
|
-
display: 'flex',
|
|
50
|
-
alignItems: 'flex-end',
|
|
51
|
-
gap: '10px',
|
|
52
|
-
flexShrink: 0,
|
|
53
|
-
}, children: [_jsx("textarea", { ref: inputRef, value: text, onChange: e => setText(e.target.value), onKeyDown: handleKey, placeholder: "Type and press [enter]..", rows: 1, style: {
|
|
54
|
-
flex: 1, resize: 'none', border: 'none', outline: 'none',
|
|
55
|
-
fontFamily: t.fontFamily, fontSize: '14px', lineHeight: '1.5',
|
|
56
|
-
maxHeight: '80px', overflowY: 'auto', color: '#1a2332',
|
|
57
|
-
padding: '6px 0', backgroundColor: 'transparent',
|
|
58
|
-
} }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '8px', flexShrink: 0 }, children: [_jsx(IconBtn, { onClick: () => { }, title: "Reaction", children: _jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: [_jsx("path", { d: "M14 9h.01M10 9h.01M12 2a10 10 0 100 20A10 10 0 0012 2zm0 14s-4-1.5-4-4", stroke: "#9aa3af", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("path", { d: "M8 15s1.5 2 4 2 4-2 4-2", stroke: "#9aa3af", strokeWidth: "1.8", strokeLinecap: "round" })] }) }), _jsx(IconBtn, { onClick: () => { }, title: "Attach", children: _jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66L9.41 17.41a2 2 0 01-2.83-2.83l8.49-8.48", stroke: "#9aa3af", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) }), _jsx(IconBtn, { onClick: () => { }, title: "Emoji", children: _jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: [_jsx("circle", { cx: "12", cy: "12", r: "10", stroke: "#9aa3af", strokeWidth: "1.8" }), _jsx("path", { d: "M8 14s1.5 2 4 2 4-2 4-2", stroke: "#9aa3af", strokeWidth: "1.8", strokeLinecap: "round" }), _jsx("line", { x1: "9", y1: "9", x2: "9.01", y2: "9", stroke: "#9aa3af", strokeWidth: "2.5", strokeLinecap: "round" }), _jsx("line", { x1: "15", y1: "9", x2: "15.01", y2: "9", stroke: "#9aa3af", strokeWidth: "2.5", strokeLinecap: "round" })] }) }), text.trim() && (_jsx("button", { onClick: handleSend, style: {
|
|
59
|
-
width: 36, height: 36, borderRadius: '50%',
|
|
60
|
-
backgroundColor: t.primaryColor, border: 'none',
|
|
61
|
-
cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
62
|
-
transition: 'transform 0.15s',
|
|
63
|
-
}, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M22 2L11 13M22 2L15 22L11 13L2 9L22 2Z", stroke: "#fff", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }))] })] })] }));
|
|
64
|
-
};
|
|
65
|
-
const Bubble = ({ msg, primaryColor, font }) => {
|
|
66
|
-
const isMe = msg.senderId === 'me';
|
|
67
|
-
const time = new Date(msg.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
|
68
|
-
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', alignItems: isMe ? 'flex-end' : 'flex-start', gap: 3 }, children: [_jsx("div", { style: {
|
|
69
|
-
maxWidth: '75%', padding: '10px 14px',
|
|
70
|
-
borderRadius: isMe ? '18px 18px 4px 18px' : '18px 18px 18px 4px',
|
|
71
|
-
backgroundColor: isMe ? primaryColor : '#fff',
|
|
72
|
-
color: isMe ? '#fff' : '#1a2332',
|
|
73
|
-
fontSize: '14px', lineHeight: '1.5',
|
|
74
|
-
boxShadow: '0 1px 4px rgba(0,0,0,0.07)',
|
|
75
|
-
fontFamily: font, wordBreak: 'break-word',
|
|
76
|
-
}, children: msg.text }), _jsx("span", { style: { fontSize: '11px', color: '#b0bec5', padding: '0 4px' }, children: time })] }));
|
|
77
|
-
};
|
|
78
|
-
const IconBtn = ({ onClick, title, children }) => (_jsx("button", { onClick: onClick, title: title, style: { background: 'none', border: 'none', cursor: 'pointer', padding: '4px', display: 'flex', alignItems: 'center', borderRadius: '6px' }, onMouseEnter: e => e.currentTarget.style.background = '#f3f4f6', onMouseLeave: e => e.currentTarget.style.background = 'none', children: children }));
|
|
79
|
-
const iconBtnStyle = {
|
|
80
|
-
background: 'rgba(255,255,255,0.2)', border: 'none', borderRadius: '50%',
|
|
81
|
-
width: 34, height: 34, display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
82
|
-
cursor: 'pointer', flexShrink: 0,
|
|
83
|
-
};
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useState, useEffect, useCallback } from 'react';
|
|
4
|
-
import { loadChatConfig, buildUserListUrl } from '../config';
|
|
5
|
-
import { mergeTheme } from '../utils/theme';
|
|
6
|
-
import { useUsers } from '../hooks/useUsers';
|
|
7
|
-
import { useChat } from '../hooks/useChat';
|
|
8
|
-
// Screens
|
|
9
|
-
import { HomeScreen } from './HomeScreen';
|
|
10
|
-
import { UserListScreen } from './UserListScreen';
|
|
11
|
-
import { ChatScreen } from './ChatScreen';
|
|
12
|
-
import { RecentChatsScreen } from './RecentChatsScreen';
|
|
13
|
-
import { TicketScreen } from './TicketScreen';
|
|
14
|
-
import { MaintenanceView } from './MaintenanceView';
|
|
15
|
-
import { BottomTabs } from './Tabs/BottomTabs';
|
|
16
|
-
export const ChatWidget = ({ theme }) => {
|
|
17
|
-
const [isMounted, setIsMounted] = useState(false);
|
|
18
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
19
|
-
const [isMaximized, setIsMaximized] = useState(false);
|
|
20
|
-
const [activeTab, setActiveTab] = useState('home');
|
|
21
|
-
const [screen, setScreen] = useState('home');
|
|
22
|
-
const [userListCtx, setUserListCtx] = useState('support');
|
|
23
|
-
const [tickets, setTickets] = useState([]);
|
|
24
|
-
// SSR guard
|
|
25
|
-
useEffect(() => { setIsMounted(true); }, []);
|
|
26
|
-
const config = loadChatConfig();
|
|
27
|
-
const t = mergeTheme(theme);
|
|
28
|
-
const apiUrl = buildUserListUrl(config);
|
|
29
|
-
// Determine filter based on context
|
|
30
|
-
const filterType = userListCtx === 'support' ? 'developer' : 'user';
|
|
31
|
-
const { users, loading, error } = useUsers(apiUrl, filterType, config.status === 'ACTIVE' && screen === 'user-list');
|
|
32
|
-
const { messages, activeUser, selectUser, sendMessage, clearChat } = useChat();
|
|
33
|
-
// ── Navigation helpers ─────────────────────────────────────────────────────
|
|
34
|
-
const goHome = useCallback(() => { setScreen('home'); setActiveTab('home'); }, []);
|
|
35
|
-
const handleTabChange = useCallback((tab) => {
|
|
36
|
-
setActiveTab(tab);
|
|
37
|
-
if (tab === 'home') {
|
|
38
|
-
setScreen('home');
|
|
39
|
-
}
|
|
40
|
-
if (tab === 'chats') {
|
|
41
|
-
setScreen('recent-chats');
|
|
42
|
-
}
|
|
43
|
-
if (tab === 'tickets') {
|
|
44
|
-
setScreen('tickets');
|
|
45
|
-
}
|
|
46
|
-
}, []);
|
|
47
|
-
const handleCardClick = useCallback((ctx) => {
|
|
48
|
-
if (ctx === 'ticket') {
|
|
49
|
-
setActiveTab('tickets');
|
|
50
|
-
setScreen('tickets');
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
setUserListCtx(ctx);
|
|
54
|
-
setScreen('user-list');
|
|
55
|
-
}
|
|
56
|
-
}, []);
|
|
57
|
-
const handleSelectUser = useCallback((user) => {
|
|
58
|
-
selectUser(user);
|
|
59
|
-
setScreen('chat');
|
|
60
|
-
}, [selectUser]);
|
|
61
|
-
const handleBackFromUserList = useCallback(() => {
|
|
62
|
-
setScreen('home');
|
|
63
|
-
}, []);
|
|
64
|
-
const handleBackFromChat = useCallback(() => {
|
|
65
|
-
clearChat();
|
|
66
|
-
setScreen('user-list');
|
|
67
|
-
}, [clearChat]);
|
|
68
|
-
const handleRaiseTicket = useCallback((title, description) => {
|
|
69
|
-
const t = {
|
|
70
|
-
id: `ticket_${Date.now()}`,
|
|
71
|
-
title,
|
|
72
|
-
description,
|
|
73
|
-
status: 'open',
|
|
74
|
-
priority: 'medium',
|
|
75
|
-
createdAt: new Date(),
|
|
76
|
-
updatedAt: new Date(),
|
|
77
|
-
};
|
|
78
|
-
setTickets(prev => [t, ...prev]);
|
|
79
|
-
}, []);
|
|
80
|
-
// ── Sizing ─────────────────────────────────────────────────────────────────
|
|
81
|
-
const normalW = 380;
|
|
82
|
-
const normalH = 560;
|
|
83
|
-
const maxW = 480;
|
|
84
|
-
const maxH = 720;
|
|
85
|
-
const width = isMaximized ? maxW : normalW;
|
|
86
|
-
const height = isMaximized ? maxH : normalH;
|
|
87
|
-
const posStyle = t.buttonPosition === 'bottom-left'
|
|
88
|
-
? { left: 24, right: 'auto' }
|
|
89
|
-
: { right: 24, left: 'auto' };
|
|
90
|
-
if (!isMounted)
|
|
91
|
-
return null;
|
|
92
|
-
if (config.status === 'DISABLE')
|
|
93
|
-
return null;
|
|
94
|
-
return (_jsxs(_Fragment, { children: [_jsx("style", { children: `
|
|
95
|
-
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700;800&display=swap');
|
|
96
|
-
@keyframes cw-fadeUp {
|
|
97
|
-
from { opacity:0; transform:translateY(10px); }
|
|
98
|
-
to { opacity:1; transform:translateY(0); }
|
|
99
|
-
}
|
|
100
|
-
@keyframes cw-slideInRight {
|
|
101
|
-
from { opacity:0; transform:translateX(18px); }
|
|
102
|
-
to { opacity:1; transform:translateX(0); }
|
|
103
|
-
}
|
|
104
|
-
@keyframes cw-popIn {
|
|
105
|
-
from { opacity:0; transform:scale(0.88) translateY(16px); }
|
|
106
|
-
to { opacity:1; transform:scale(1) translateY(0); }
|
|
107
|
-
}
|
|
108
|
-
.cw-scrollbar::-webkit-scrollbar { width:4px; }
|
|
109
|
-
.cw-scrollbar::-webkit-scrollbar-track { background:transparent; }
|
|
110
|
-
.cw-scrollbar::-webkit-scrollbar-thumb { background:#e0e0e0; border-radius:4px; }
|
|
111
|
-
` }), _jsx("button", { onClick: () => setIsOpen(o => !o), "aria-label": isOpen ? 'Close chat' : t.buttonLabel, style: Object.assign(Object.assign({ position: 'fixed', bottom: 24 }, posStyle), { zIndex: 9999, display: 'flex', alignItems: 'center', gap: 10, padding: isOpen ? '14px' : '13px 22px', backgroundColor: t.buttonColor, color: t.buttonTextColor, border: 'none', borderRadius: 50, cursor: 'pointer', fontFamily: t.fontFamily, fontSize: '15px', fontWeight: 700, boxShadow: `0 8px 28px ${t.buttonColor}55`, transition: 'all 0.3s cubic-bezier(0.34,1.56,0.64,1)', transform: isOpen ? 'scale(0.94)' : 'scale(1)', minWidth: isOpen ? 50 : 'auto', justifyContent: 'center' }), onMouseEnter: e => {
|
|
112
|
-
if (!isOpen) {
|
|
113
|
-
e.currentTarget.style.transform = 'scale(1.06) translateY(-2px)';
|
|
114
|
-
e.currentTarget.style.boxShadow = `0 12px 36px ${t.buttonColor}77`;
|
|
115
|
-
}
|
|
116
|
-
}, onMouseLeave: e => {
|
|
117
|
-
e.currentTarget.style.transform = isOpen ? 'scale(0.94)' : 'scale(1)';
|
|
118
|
-
e.currentTarget.style.boxShadow = `0 8px 28px ${t.buttonColor}55`;
|
|
119
|
-
}, children: isOpen
|
|
120
|
-
? _jsx(CloseIcon, { color: t.buttonTextColor })
|
|
121
|
-
: _jsxs(_Fragment, { children: [_jsx(ChatBubbleIcon, { color: t.buttonTextColor }), _jsx("span", { children: t.buttonLabel })] }) }), isOpen && (_jsxs("div", { style: Object.assign(Object.assign({ position: 'fixed', bottom: 86 }, posStyle), { zIndex: 9998, width,
|
|
122
|
-
height, maxWidth: 'calc(100vw - 32px)', maxHeight: 'calc(100vh - 110px)', backgroundColor: '#fff', borderRadius: t.borderRadius, boxShadow: '0 20px 70px rgba(0,0,0,0.2), 0 6px 20px rgba(0,0,0,0.08)', display: 'flex', flexDirection: 'column', overflow: 'hidden', fontFamily: t.fontFamily, animation: 'cw-popIn 0.3s cubic-bezier(0.34,1.56,0.64,1)', transition: 'width 0.3s ease, height 0.3s ease' }), children: [screen !== 'chat' && (_jsx("button", { onClick: () => setIsMaximized(m => !m), title: isMaximized ? 'Minimize' : 'Maximize', style: {
|
|
123
|
-
position: 'absolute', top: 12, right: 48, zIndex: 10,
|
|
124
|
-
background: 'rgba(255,255,255,0.22)', border: 'none', borderRadius: '50%',
|
|
125
|
-
width: 28, height: 28, display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
126
|
-
cursor: 'pointer', transition: 'background 0.15s',
|
|
127
|
-
}, onMouseEnter: e => e.currentTarget.style.background = 'rgba(255,255,255,0.38)', onMouseLeave: e => e.currentTarget.style.background = 'rgba(255,255,255,0.22)', children: isMaximized
|
|
128
|
-
? _jsx(MinimizeIcon, {})
|
|
129
|
-
: _jsx(MaximizeIcon, {}) })), screen !== 'chat' && (_jsx("button", { onClick: () => setIsOpen(false), title: "Close", style: {
|
|
130
|
-
position: 'absolute', top: 12, right: 12, zIndex: 10,
|
|
131
|
-
background: 'rgba(255,255,255,0.22)', border: 'none', borderRadius: '50%',
|
|
132
|
-
width: 28, height: 28, display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
133
|
-
cursor: 'pointer',
|
|
134
|
-
}, children: _jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M18 6L6 18M6 6l12 12", stroke: "#fff", strokeWidth: "2.5", strokeLinecap: "round" }) }) })), _jsxs("div", { className: "cw-scrollbar", style: { flex: 1, overflow: 'hidden', display: 'flex', flexDirection: 'column' }, children: [config.status === 'MAINTENANCE' && (_jsx(MaintenanceView, { primaryColor: t.primaryColor, fontFamily: t.fontFamily })), config.status === 'ACTIVE' && (_jsxs(_Fragment, { children: [screen === 'home' && (_jsx(HomeScreen, { config: config, theme: theme, onNavigate: handleCardClick })), screen === 'user-list' && (_jsx(UserListScreen, { context: userListCtx, users: users, loading: loading, error: error, theme: theme, onBack: handleBackFromUserList, onSelectUser: handleSelectUser })), screen === 'chat' && activeUser && (_jsx(ChatScreen, { activeUser: activeUser, messages: messages, onSend: sendMessage, onBack: handleBackFromChat, onClose: () => setIsOpen(false), theme: theme })), screen === 'recent-chats' && (_jsx(RecentChatsScreen, { chats: [], theme: theme, onSelectChat: handleSelectUser })), screen === 'tickets' && (_jsx(TicketScreen, { tickets: tickets, theme: theme, onRaiseTicket: handleRaiseTicket }))] }))] }), screen !== 'chat' && screen !== 'user-list' && config.status !== 'MAINTENANCE' && (_jsx(BottomTabs, { active: activeTab, onChange: handleTabChange, primaryColor: t.primaryColor, fontFamily: t.fontFamily }))] }))] }));
|
|
135
|
-
};
|
|
136
|
-
export default ChatWidget;
|
|
137
|
-
// ── Tiny SVG icons ─────────────────────────────────────────────────────────────
|
|
138
|
-
const ChatBubbleIcon = ({ color }) => (_jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
139
|
-
const CloseIcon = ({ color }) => (_jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M18 6L6 18M6 6l12 12", stroke: color, strokeWidth: "2.5", strokeLinecap: "round" }) }));
|
|
140
|
-
const MaximizeIcon = () => (_jsx("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M8 3H5a2 2 0 00-2 2v3M21 8V5a2 2 0 00-2-2h-3M3 16v3a2 2 0 002 2h3M16 21h3a2 2 0 002-2v-3", stroke: "#fff", strokeWidth: "2.2", strokeLinecap: "round" }) }));
|
|
141
|
-
const MinimizeIcon = () => (_jsx("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M8 3v5H3M21 8h-5V3M3 16h5v5M16 21v-5h5", stroke: "#fff", strokeWidth: "2.2", strokeLinecap: "round" }) }));
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { ChatConfig, ChatWidgetTheme, UserListContext } from '../../types';
|
|
3
|
-
interface HomeScreenProps {
|
|
4
|
-
config: ChatConfig;
|
|
5
|
-
theme?: ChatWidgetTheme;
|
|
6
|
-
onNavigate: (ctx: UserListContext | 'ticket') => void;
|
|
7
|
-
}
|
|
8
|
-
export declare const HomeScreen: React.FC<HomeScreenProps>;
|
|
9
|
-
export {};
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { mergeTheme } from '../../utils/theme';
|
|
3
|
-
export const HomeScreen = ({ config, theme, onNavigate }) => {
|
|
4
|
-
const t = mergeTheme(theme);
|
|
5
|
-
const showSupport = config.chatType === 'SUPPORT' || config.chatType === 'BOTH';
|
|
6
|
-
const showConversation = config.chatType === 'CHAT' || config.chatType === 'BOTH';
|
|
7
|
-
const cards = [
|
|
8
|
-
showSupport && {
|
|
9
|
-
key: 'support',
|
|
10
|
-
title: 'Need Support',
|
|
11
|
-
subtitle: 'We typically reply in a few minutes',
|
|
12
|
-
onClick: () => onNavigate('support'),
|
|
13
|
-
},
|
|
14
|
-
showConversation && {
|
|
15
|
-
key: 'conversation',
|
|
16
|
-
title: 'New Conversation',
|
|
17
|
-
subtitle: 'With your colleague',
|
|
18
|
-
onClick: () => onNavigate('conversation'),
|
|
19
|
-
},
|
|
20
|
-
// Raise Ticket is always shown
|
|
21
|
-
{
|
|
22
|
-
key: 'ticket',
|
|
23
|
-
title: 'Raise Ticket',
|
|
24
|
-
subtitle: 'For major changes',
|
|
25
|
-
onClick: () => onNavigate('ticket'),
|
|
26
|
-
},
|
|
27
|
-
].filter(Boolean);
|
|
28
|
-
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%' }, children: [_jsxs("div", { style: {
|
|
29
|
-
backgroundColor: t.primaryColor,
|
|
30
|
-
padding: '32px 24px 40px',
|
|
31
|
-
flexShrink: 0,
|
|
32
|
-
}, children: [_jsx("h1", { style: {
|
|
33
|
-
margin: '0 0 8px',
|
|
34
|
-
fontSize: '28px',
|
|
35
|
-
fontWeight: 800,
|
|
36
|
-
color: '#fff',
|
|
37
|
-
letterSpacing: '-0.03em',
|
|
38
|
-
fontFamily: t.fontFamily,
|
|
39
|
-
}, children: "Hi there \uD83D\uDC4B" }), _jsx("p", { style: { margin: 0, fontSize: '15px', color: 'rgba(255,255,255,0.85)', fontFamily: t.fontFamily }, children: "Need help? start a conversation:" })] }), _jsx("div", { style: {
|
|
40
|
-
flex: 1,
|
|
41
|
-
overflowY: 'auto',
|
|
42
|
-
padding: '0 16px 16px',
|
|
43
|
-
marginTop: '-24px',
|
|
44
|
-
display: 'flex',
|
|
45
|
-
flexDirection: 'column',
|
|
46
|
-
gap: '10px',
|
|
47
|
-
}, children: cards.map((card, i) => (_jsxs("button", { onClick: card.onClick, style: {
|
|
48
|
-
width: '100%',
|
|
49
|
-
background: '#fff',
|
|
50
|
-
border: 'none',
|
|
51
|
-
borderRadius: '14px',
|
|
52
|
-
padding: '18px 20px',
|
|
53
|
-
display: 'flex',
|
|
54
|
-
alignItems: 'center',
|
|
55
|
-
justifyContent: 'space-between',
|
|
56
|
-
cursor: 'pointer',
|
|
57
|
-
textAlign: 'left',
|
|
58
|
-
boxShadow: '0 2px 12px rgba(0,0,0,0.09)',
|
|
59
|
-
transition: 'transform 0.15s ease, box-shadow 0.15s ease',
|
|
60
|
-
animation: `cw-fadeUp 0.35s ease both`,
|
|
61
|
-
animationDelay: `${i * 0.08}s`,
|
|
62
|
-
fontFamily: t.fontFamily,
|
|
63
|
-
}, onMouseEnter: e => {
|
|
64
|
-
e.currentTarget.style.transform = 'translateY(-2px)';
|
|
65
|
-
e.currentTarget.style.boxShadow = '0 6px 20px rgba(0,0,0,0.13)';
|
|
66
|
-
}, onMouseLeave: e => {
|
|
67
|
-
e.currentTarget.style.transform = 'translateY(0)';
|
|
68
|
-
e.currentTarget.style.boxShadow = '0 2px 12px rgba(0,0,0,0.09)';
|
|
69
|
-
}, children: [_jsxs("div", { children: [_jsx("div", { style: { fontWeight: 700, fontSize: '15px', color: '#1a2332', marginBottom: '3px' }, children: card.title }), _jsx("div", { style: { fontSize: '13px', color: '#7b8fa1' }, children: card.subtitle })] }), _jsx(SendArrow, { color: t.primaryColor })] }, card.key))) })] }));
|
|
70
|
-
};
|
|
71
|
-
const SendArrow = ({ color }) => (_jsx("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 }, children: _jsx("path", { d: "M22 2L11 13M22 2L15 22L11 13L2 9L22 2Z", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
export const MaintenanceView = ({ primaryColor, fontFamily }) => (_jsxs("div", { style: {
|
|
3
|
-
display: 'flex', flexDirection: 'column', alignItems: 'center',
|
|
4
|
-
justifyContent: 'center', height: '100%', padding: '32px',
|
|
5
|
-
fontFamily, textAlign: 'center', gap: 16,
|
|
6
|
-
}, children: [_jsx("div", { style: {
|
|
7
|
-
width: 72, height: 72, borderRadius: '50%',
|
|
8
|
-
backgroundColor: `${primaryColor}15`,
|
|
9
|
-
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
10
|
-
}, children: _jsx("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M12 9v4M12 17h.01M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z", stroke: primaryColor, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }), _jsx("h3", { style: { margin: 0, fontSize: '17px', fontWeight: 800, color: '#1a2332', letterSpacing: '-0.02em' }, children: "Under Maintenance" }), _jsx("p", { style: { margin: 0, fontSize: '14px', color: '#7b8fa1', lineHeight: 1.6, maxWidth: 220 }, children: "Chat is under maintenance. We'll be back shortly!" }), _jsxs("span", { style: {
|
|
11
|
-
display: 'inline-flex', alignItems: 'center', gap: 6,
|
|
12
|
-
padding: '6px 14px', borderRadius: 20,
|
|
13
|
-
backgroundColor: '#fff3cd', color: '#856404',
|
|
14
|
-
fontSize: '12px', fontWeight: 700,
|
|
15
|
-
border: '1px solid #ffc10730',
|
|
16
|
-
}, children: [_jsx("span", { style: { width: 6, height: 6, borderRadius: '50%', backgroundColor: '#ffc107', display: 'inline-block' } }), "Temporarily Unavailable"] })] }));
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { ChatUser, ChatWidgetTheme } from '../../types';
|
|
3
|
-
interface RecentChat {
|
|
4
|
-
id: string;
|
|
5
|
-
user: ChatUser;
|
|
6
|
-
lastMessage: string;
|
|
7
|
-
lastTime: Date;
|
|
8
|
-
unread: number;
|
|
9
|
-
}
|
|
10
|
-
interface RecentChatsScreenProps {
|
|
11
|
-
chats: RecentChat[];
|
|
12
|
-
theme?: ChatWidgetTheme;
|
|
13
|
-
onSelectChat: (user: ChatUser) => void;
|
|
14
|
-
}
|
|
15
|
-
export declare const RecentChatsScreen: React.FC<RecentChatsScreenProps>;
|
|
16
|
-
export {};
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { mergeTheme } from '../../utils/theme';
|
|
3
|
-
export const RecentChatsScreen = ({ chats, theme, onSelectChat }) => {
|
|
4
|
-
const t = mergeTheme(theme);
|
|
5
|
-
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%' }, children: [_jsxs("div", { style: {
|
|
6
|
-
backgroundColor: t.primaryColor,
|
|
7
|
-
padding: '20px 20px 24px',
|
|
8
|
-
flexShrink: 0,
|
|
9
|
-
}, children: [_jsx("h2", { style: { margin: 0, fontSize: '20px', fontWeight: 800, color: '#fff', fontFamily: t.fontFamily, letterSpacing: '-0.02em' }, children: "Recent Chats" }), _jsx("p", { style: { margin: '4px 0 0', fontSize: '13px', color: 'rgba(255,255,255,0.8)', fontFamily: t.fontFamily }, children: "Your conversation history" })] }), _jsx("div", { style: { flex: 1, overflowY: 'auto' }, children: chats.length === 0 ? (_jsxs("div", { style: { padding: '50px 24px', textAlign: 'center', fontFamily: t.fontFamily }, children: [_jsx("div", { style: { fontSize: '36px', marginBottom: 12 }, children: "\uD83D\uDCAC" }), _jsx("div", { style: { fontWeight: 700, color: '#1a2332', marginBottom: 6 }, children: "No chats yet" }), _jsx("div", { style: { fontSize: '13px', color: '#7b8fa1' }, children: "Start a conversation from the home tab" })] })) : (chats.map((chat, i) => {
|
|
10
|
-
const initials = chat.user.name.split(' ').map(n => n[0]).join('').toUpperCase().slice(0, 2);
|
|
11
|
-
const avatarColors = ['#1aaa96', '#2563EB', '#7C3AED', '#D97706', '#DC2626'];
|
|
12
|
-
const bg = avatarColors[chat.user.name.charCodeAt(0) % avatarColors.length];
|
|
13
|
-
const timeStr = new Date(chat.lastTime).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
|
14
|
-
return (_jsxs("button", { onClick: () => onSelectChat(chat.user), style: {
|
|
15
|
-
width: '100%', padding: '14px 20px',
|
|
16
|
-
display: 'flex', alignItems: 'center', gap: '14px',
|
|
17
|
-
background: 'transparent', border: 'none',
|
|
18
|
-
borderBottom: '1px solid #f3f4f6',
|
|
19
|
-
cursor: 'pointer', textAlign: 'left',
|
|
20
|
-
fontFamily: t.fontFamily,
|
|
21
|
-
animation: `cw-fadeUp 0.3s ease both`,
|
|
22
|
-
animationDelay: `${i * 0.05}s`,
|
|
23
|
-
transition: 'background 0.15s',
|
|
24
|
-
}, onMouseEnter: e => e.currentTarget.style.background = '#f8fdfc', onMouseLeave: e => e.currentTarget.style.background = 'transparent', children: [_jsxs("div", { style: {
|
|
25
|
-
width: 46, height: 46, borderRadius: '50%', backgroundColor: bg,
|
|
26
|
-
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
27
|
-
color: '#fff', fontWeight: 700, fontSize: '15px', flexShrink: 0,
|
|
28
|
-
position: 'relative',
|
|
29
|
-
}, children: [initials, chat.unread > 0 && (_jsx("span", { style: {
|
|
30
|
-
position: 'absolute', top: -2, right: -2,
|
|
31
|
-
width: 18, height: 18, borderRadius: '50%',
|
|
32
|
-
backgroundColor: '#ff4757', color: '#fff',
|
|
33
|
-
fontSize: '10px', fontWeight: 700,
|
|
34
|
-
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
35
|
-
border: '2px solid #fff',
|
|
36
|
-
}, children: chat.unread }))] }), _jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', marginBottom: 3 }, children: [_jsx("span", { style: { fontWeight: 700, fontSize: '14px', color: '#1a2332' }, children: chat.user.name }), _jsx("span", { style: { fontSize: '11px', color: '#b0bec5' }, children: timeStr })] }), _jsx("div", { style: { fontSize: '13px', color: '#7b8fa1', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, children: chat.lastMessage })] })] }, chat.id));
|
|
37
|
-
})) })] }));
|
|
38
|
-
};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { BottomTab } from '../../types';
|
|
3
|
-
interface BottomTabsProps {
|
|
4
|
-
active: BottomTab;
|
|
5
|
-
onChange: (tab: BottomTab) => void;
|
|
6
|
-
primaryColor: string;
|
|
7
|
-
fontFamily: string;
|
|
8
|
-
}
|
|
9
|
-
export declare const BottomTabs: React.FC<BottomTabsProps>;
|
|
10
|
-
export {};
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
export const BottomTabs = ({ active, onChange, primaryColor, fontFamily }) => {
|
|
3
|
-
const tabs = [
|
|
4
|
-
{ key: 'home', label: 'Home', Icon: HomeIcon },
|
|
5
|
-
{ key: 'chats', label: 'Chats', Icon: ChatsIcon },
|
|
6
|
-
{ key: 'tickets', label: 'Tickets', Icon: TicketsIcon },
|
|
7
|
-
];
|
|
8
|
-
return (_jsx("div", { style: {
|
|
9
|
-
display: 'flex',
|
|
10
|
-
borderTop: '1px solid #eef0f5',
|
|
11
|
-
backgroundColor: '#fff',
|
|
12
|
-
flexShrink: 0,
|
|
13
|
-
}, children: tabs.map(tab => {
|
|
14
|
-
const isActive = active === tab.key;
|
|
15
|
-
return (_jsxs("button", { onClick: () => onChange(tab.key), style: {
|
|
16
|
-
flex: 1, padding: '10px 0 8px',
|
|
17
|
-
display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 3,
|
|
18
|
-
background: 'transparent', border: 'none', cursor: 'pointer',
|
|
19
|
-
fontFamily, fontSize: '10px', fontWeight: isActive ? 700 : 500,
|
|
20
|
-
color: isActive ? primaryColor : '#9aa3af',
|
|
21
|
-
transition: 'color 0.15s',
|
|
22
|
-
borderTop: isActive ? `2px solid ${primaryColor}` : '2px solid transparent',
|
|
23
|
-
}, children: [_jsx(tab.Icon, { active: isActive, color: isActive ? primaryColor : '#b0bec5' }), tab.label] }, tab.key));
|
|
24
|
-
}) }));
|
|
25
|
-
};
|
|
26
|
-
// ── Icons ─────────────────────────────────────────────────────────────────────
|
|
27
|
-
const HomeIcon = ({ active, color }) => (_jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: [_jsx("path", { d: "M3 9.5L12 3l9 6.5V20a1 1 0 01-1 1H4a1 1 0 01-1-1V9.5z", stroke: color, strokeWidth: active ? 2.2 : 1.8, strokeLinecap: "round", strokeLinejoin: "round", fill: active ? `${color}20` : 'none' }), _jsx("path", { d: "M9 21V12h6v9", stroke: color, strokeWidth: active ? 2.2 : 1.8, strokeLinecap: "round", strokeLinejoin: "round" })] }));
|
|
28
|
-
const ChatsIcon = ({ active, color }) => (_jsx("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z", stroke: color, strokeWidth: active ? 2.2 : 1.8, strokeLinecap: "round", strokeLinejoin: "round", fill: active ? `${color}20` : 'none' }) }));
|
|
29
|
-
const TicketsIcon = ({ active, color }) => (_jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: [_jsx("path", { d: "M15 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V9l-4-4z", stroke: color, strokeWidth: active ? 2.2 : 1.8, strokeLinecap: "round", strokeLinejoin: "round", fill: active ? `${color}20` : 'none' }), _jsx("path", { d: "M15 5v4h4M9 13h6M9 17h4", stroke: color, strokeWidth: active ? 2.2 : 1.8, strokeLinecap: "round" })] }));
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { ChatWidgetTheme, Ticket } from '../../types';
|
|
3
|
-
interface TicketScreenProps {
|
|
4
|
-
tickets: Ticket[];
|
|
5
|
-
theme?: ChatWidgetTheme;
|
|
6
|
-
onRaiseTicket: (title: string, description: string) => void;
|
|
7
|
-
}
|
|
8
|
-
export declare const TicketScreen: React.FC<TicketScreenProps>;
|
|
9
|
-
export {};
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
import { mergeTheme } from '../../utils/theme';
|
|
4
|
-
export const TicketScreen = ({ tickets, theme, onRaiseTicket }) => {
|
|
5
|
-
const t = mergeTheme(theme);
|
|
6
|
-
const [showForm, setShowForm] = useState(false);
|
|
7
|
-
const [title, setTitle] = useState('');
|
|
8
|
-
const [desc, setDesc] = useState('');
|
|
9
|
-
const handleSubmit = () => {
|
|
10
|
-
if (!title.trim())
|
|
11
|
-
return;
|
|
12
|
-
onRaiseTicket(title.trim(), desc.trim());
|
|
13
|
-
setTitle('');
|
|
14
|
-
setDesc('');
|
|
15
|
-
setShowForm(false);
|
|
16
|
-
};
|
|
17
|
-
const statusMeta = {
|
|
18
|
-
'open': { label: 'Open', bg: '#e6faf8', color: t.primaryColor },
|
|
19
|
-
'in-progress': { label: 'In Progress', bg: '#fffbeb', color: '#d97706' },
|
|
20
|
-
'resolved': { label: 'Resolved', bg: '#f0fdf4', color: '#16a34a' },
|
|
21
|
-
'closed': { label: 'Closed', bg: '#f3f4f6', color: '#6b7280' },
|
|
22
|
-
};
|
|
23
|
-
const priorityMeta = {
|
|
24
|
-
low: { label: '↓ Low', color: '#6b7280' },
|
|
25
|
-
medium: { label: '→ Medium', color: '#d97706' },
|
|
26
|
-
high: { label: '↑ High', color: '#dc2626' },
|
|
27
|
-
};
|
|
28
|
-
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%' }, children: [_jsx("div", { style: { backgroundColor: t.primaryColor, padding: '20px 20px 24px', flexShrink: 0 }, children: _jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between' }, children: [_jsxs("div", { children: [_jsx("h2", { style: { margin: 0, fontSize: '20px', fontWeight: 800, color: '#fff', fontFamily: t.fontFamily, letterSpacing: '-0.02em' }, children: "Tickets" }), _jsxs("p", { style: { margin: '4px 0 0', fontSize: '13px', color: 'rgba(255,255,255,0.8)', fontFamily: t.fontFamily }, children: [tickets.length, " ticket", tickets.length !== 1 ? 's' : '', " raised"] })] }), _jsx("button", { onClick: () => setShowForm(v => !v), style: {
|
|
29
|
-
background: 'rgba(255,255,255,0.25)', border: 'none', borderRadius: '20px',
|
|
30
|
-
padding: '8px 16px', color: '#fff', fontWeight: 700, fontSize: '13px',
|
|
31
|
-
cursor: 'pointer', fontFamily: t.fontFamily, display: 'flex', alignItems: 'center', gap: 5,
|
|
32
|
-
}, children: showForm ? '✕ Cancel' : '+ New Ticket' })] }) }), showForm && (_jsxs("div", { style: {
|
|
33
|
-
padding: '16px 20px',
|
|
34
|
-
borderBottom: '1px solid #eef0f5',
|
|
35
|
-
backgroundColor: '#fafcff',
|
|
36
|
-
animation: 'cw-fadeUp 0.2s ease',
|
|
37
|
-
flexShrink: 0,
|
|
38
|
-
}, children: [_jsx("input", { placeholder: "Ticket title *", value: title, onChange: e => setTitle(e.target.value), style: {
|
|
39
|
-
width: '100%', padding: '10px 14px', borderRadius: 10,
|
|
40
|
-
border: '1.5px solid #e2e8f0', outline: 'none',
|
|
41
|
-
fontFamily: t.fontFamily, fontSize: '14px', color: '#1a2332',
|
|
42
|
-
marginBottom: 10, boxSizing: 'border-box',
|
|
43
|
-
}, onFocus: e => (e.target.style.borderColor = t.primaryColor), onBlur: e => (e.target.style.borderColor = '#e2e8f0') }), _jsx("textarea", { placeholder: "Describe the issue (optional)", value: desc, onChange: e => setDesc(e.target.value), rows: 3, style: {
|
|
44
|
-
width: '100%', padding: '10px 14px', borderRadius: 10,
|
|
45
|
-
border: '1.5px solid #e2e8f0', outline: 'none', resize: 'none',
|
|
46
|
-
fontFamily: t.fontFamily, fontSize: '14px', color: '#1a2332',
|
|
47
|
-
marginBottom: 10, boxSizing: 'border-box',
|
|
48
|
-
}, onFocus: e => (e.target.style.borderColor = t.primaryColor), onBlur: e => (e.target.style.borderColor = '#e2e8f0') }), _jsx("button", { onClick: handleSubmit, disabled: !title.trim(), style: {
|
|
49
|
-
width: '100%', padding: '11px', borderRadius: 10,
|
|
50
|
-
backgroundColor: title.trim() ? t.primaryColor : '#e2e8f0',
|
|
51
|
-
color: title.trim() ? '#fff' : '#9aa3af',
|
|
52
|
-
border: 'none', cursor: title.trim() ? 'pointer' : 'not-allowed',
|
|
53
|
-
fontWeight: 700, fontSize: '14px', fontFamily: t.fontFamily,
|
|
54
|
-
transition: 'background 0.2s',
|
|
55
|
-
}, children: "Submit Ticket" })] })), _jsx("div", { style: { flex: 1, overflowY: 'auto' }, children: tickets.length === 0 ? (_jsxs("div", { style: { padding: '50px 24px', textAlign: 'center', fontFamily: t.fontFamily }, children: [_jsx("div", { style: { fontSize: '36px', marginBottom: 12 }, children: "\uD83C\uDFAB" }), _jsx("div", { style: { fontWeight: 700, color: '#1a2332', marginBottom: 6 }, children: "No tickets yet" }), _jsx("div", { style: { fontSize: '13px', color: '#7b8fa1' }, children: "Raise a ticket for major issues or changes" })] })) : (tickets.map((ticket, i) => {
|
|
56
|
-
const sm = statusMeta[ticket.status];
|
|
57
|
-
const pm = priorityMeta[ticket.priority];
|
|
58
|
-
const date = new Date(ticket.createdAt).toLocaleDateString([], { month: 'short', day: 'numeric' });
|
|
59
|
-
return (_jsxs("div", { style: {
|
|
60
|
-
padding: '14px 20px',
|
|
61
|
-
borderBottom: '1px solid #f3f4f6',
|
|
62
|
-
fontFamily: t.fontFamily,
|
|
63
|
-
animation: `cw-fadeUp 0.3s ease both`,
|
|
64
|
-
animationDelay: `${i * 0.05}s`,
|
|
65
|
-
}, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 6 }, children: [_jsx("span", { style: { fontWeight: 700, fontSize: '14px', color: '#1a2332', flex: 1, paddingRight: 12 }, children: ticket.title }), _jsx("span", { style: {
|
|
66
|
-
fontSize: '10px', fontWeight: 700, padding: '3px 9px', borderRadius: 20,
|
|
67
|
-
backgroundColor: sm.bg, color: sm.color, whiteSpace: 'nowrap',
|
|
68
|
-
textTransform: 'uppercase', letterSpacing: '0.04em',
|
|
69
|
-
}, children: sm.label })] }), ticket.description && (_jsx("div", { style: { fontSize: '13px', color: '#7b8fa1', marginBottom: 8, lineHeight: 1.5 }, children: ticket.description })), _jsxs("div", { style: { display: 'flex', gap: 12, fontSize: '11px', color: '#b0bec5' }, children: [_jsx("span", { style: { color: pm.color, fontWeight: 600 }, children: pm.label }), _jsxs("span", { children: ["#", ticket.id.slice(-6).toUpperCase()] }), _jsx("span", { children: date })] })] }, ticket.id));
|
|
70
|
-
})) })] }));
|
|
71
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { ChatUser, ChatWidgetTheme, UserListContext } from '../../types';
|
|
3
|
-
interface UserListScreenProps {
|
|
4
|
-
context: UserListContext;
|
|
5
|
-
users: ChatUser[];
|
|
6
|
-
loading: boolean;
|
|
7
|
-
error: string | null;
|
|
8
|
-
theme?: ChatWidgetTheme;
|
|
9
|
-
onBack: () => void;
|
|
10
|
-
onSelectUser: (user: ChatUser) => void;
|
|
11
|
-
}
|
|
12
|
-
export declare const UserListScreen: React.FC<UserListScreenProps>;
|
|
13
|
-
export {};
|