1344 lines
46 KiB
HTML
1344 lines
46 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="vi">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Trò chuyện với Nguyễn Văn A - EuroTile Worker</title>
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<link rel="stylesheet" href="assets/css/style.css">
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
</head>
|
|
<body>
|
|
<div class="page-wrapper chat-wrapper">
|
|
<!-- Chat Header -->
|
|
<div class="chat-header">
|
|
<div class="chat-header-left">
|
|
<a href="chat-list.html" class="back-button">
|
|
<i class="fas fa-arrow-left"></i>
|
|
</a>
|
|
<div class="contact-info" onclick="viewContactProfile()">
|
|
<div class="contact-avatar">
|
|
<img src="https://placehold.co/40x40/FFE4B5/8B4513/png?text=NA" alt="Nguyễn Văn A" id="contactAvatar">
|
|
<div class="online-status online" id="onlineStatus"></div>
|
|
</div>
|
|
<div class="contact-details">
|
|
<h3 class="contact-name" id="contactName">Nguyễn Văn A</h3>
|
|
<div class="contact-status" id="contactStatus">Đang hoạt động</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="chat-header-actions">
|
|
<button class="chat-action-btn" onclick="makeCall()" title="Gọi điện">
|
|
<i class="fas fa-phone"></i>
|
|
</button>
|
|
<button class="chat-action-btn" onclick="videoCall()" title="Gọi video">
|
|
<i class="fas fa-video"></i>
|
|
</button>
|
|
<button class="chat-action-btn" onclick="showChatMenu()" title="Thêm">
|
|
<i class="fas fa-ellipsis-v"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Chat Messages Container -->
|
|
<div class="chat-messages-container" id="messagesContainer">
|
|
<div class="messages-wrapper">
|
|
|
|
<!-- Date Separator -->
|
|
<div class="date-separator">
|
|
<span>Hôm nay</span>
|
|
</div>
|
|
|
|
<!-- Message 1 - Received -->
|
|
<div class="message-item received">
|
|
<div class="message-avatar">
|
|
<img src="https://placehold.co/32x32/FFE4B5/8B4513/png?text=NA" alt="Nguyễn Văn A">
|
|
</div>
|
|
<div class="message-content">
|
|
<div class="message-bubble">
|
|
<p>Chào bạn! Tôi đang quan tâm đến dự án nhà ở 3 tầng. Có thể tư vấn cho tôi về các loại gạch phù hợp không?</p>
|
|
</div>
|
|
<div class="message-info">
|
|
<span class="message-time">09:30</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Message 2 - Sent -->
|
|
<div class="message-item sent">
|
|
<div class="message-content">
|
|
<div class="message-bubble">
|
|
<p>Chào anh! Tôi rất vui được hỗ trợ anh về dự án nhà ở. Anh có thể cho tôi biết diện tích và phong cách thiết kế anh mong muốn không?</p>
|
|
</div>
|
|
<div class="message-info">
|
|
<span class="message-time">09:32</span>
|
|
<i class="fas fa-check-double message-status delivered"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Message 3 - Received with Images -->
|
|
<div class="message-item received">
|
|
<div class="message-avatar">
|
|
<img src="https://placehold.co/32x32/FFE4B5/8B4513/png?text=NA" alt="Nguyễn Văn A">
|
|
</div>
|
|
<div class="message-content">
|
|
<div class="message-bubble">
|
|
<p>Đây là hình ảnh mặt bằng nhà tôi đang xây:</p>
|
|
<div class="message-images">
|
|
<div class="message-image" onclick="viewImageFullscreen('https://placehold.co/300x200/F5F5F5/333/png?text=Mặt+bằng+tầng+1')">
|
|
<img src="https://placehold.co/300x200/F5F5F5/333/png?text=Mặt+bằng+tầng+1" alt="Mặt bằng tầng 1">
|
|
<div class="image-overlay">
|
|
<i class="fas fa-expand"></i>
|
|
</div>
|
|
</div>
|
|
<div class="message-image" onclick="viewImageFullscreen('https://placehold.co/300x200/E8E8E8/333/png?text=Mặt+bằng+tầng+2')">
|
|
<img src="https://placehold.co/300x200/E8E8E8/333/png?text=Mặt+bằng+tầng+2" alt="Mặt bằng tầng 2">
|
|
<div class="image-overlay">
|
|
<i class="fas fa-expand"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="message-info">
|
|
<span class="message-time">10:15</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Message 4 - Sent with Product -->
|
|
<div class="message-item sent">
|
|
<div class="message-content">
|
|
<div class="message-bubble">
|
|
<p>Cảm ơn anh đã chia sẻ! Dựa vào mặt bằng, tôi nghĩ anh nên xem qua những sản phẩm này:</p>
|
|
<div class="shared-product" onclick="viewProduct('ET-ML-E03')">
|
|
<img src="https://placehold.co/60x60/F5F5F5/005B9A/png?text=Gạch" alt="Gạch Eurotile MỘC LAM E03">
|
|
<div class="product-info">
|
|
<h4>Gạch Eurotile MỘC LAM E03</h4>
|
|
<p>Kích thước: 60x60cm</p>
|
|
<div class="product-price">285.000đ/m²</div>
|
|
</div>
|
|
<i class="fas fa-external-link-alt"></i>
|
|
</div>
|
|
</div>
|
|
<div class="message-info">
|
|
<span class="message-time">10:18</span>
|
|
<i class="fas fa-check-double message-status read"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Message 5 - Received -->
|
|
<div class="message-item received">
|
|
<div class="message-avatar">
|
|
<img src="https://placehold.co/32x32/FFE4B5/8B4513/png?text=NA" alt="Nguyễn Văn A">
|
|
</div>
|
|
<div class="message-content">
|
|
<div class="message-bubble">
|
|
<p>Sản phẩm này trông rất đẹp! Có thể xem thêm hình ảnh thực tế không? Và giá này đã bao gồm phí lắp đặt chưa?</p>
|
|
</div>
|
|
<div class="message-info">
|
|
<span class="message-time">11:45</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Message 6 - Sent with Voice -->
|
|
<div class="message-item sent">
|
|
<div class="message-content">
|
|
<div class="message-bubble voice-message">
|
|
<div class="voice-player">
|
|
<button class="voice-play-btn" onclick="playVoiceMessage(this)">
|
|
<i class="fas fa-play"></i>
|
|
</button>
|
|
<div class="voice-waveform">
|
|
<div class="voice-progress"></div>
|
|
</div>
|
|
<span class="voice-duration">0:45</span>
|
|
</div>
|
|
</div>
|
|
<div class="message-info">
|
|
<span class="message-time">11:47</span>
|
|
<i class="fas fa-check-double message-status delivered"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Message 7 - System Message -->
|
|
<div class="system-message">
|
|
<i class="fas fa-info-circle"></i>
|
|
<span>Bạn đã chia sẻ liên hệ với khách hàng</span>
|
|
</div>
|
|
|
|
<!-- Message 8 - Received (Latest) -->
|
|
<div class="message-item received">
|
|
<div class="message-avatar">
|
|
<img src="https://placehold.co/32x32/FFE4B5/8B4513/png?text=NA" alt="Nguyễn Văn A">
|
|
</div>
|
|
<div class="message-content">
|
|
<div class="message-bubble">
|
|
<p>Cảm ơn bạn rất nhiều! Tin nhắn thoại rất hữu ích. Khi nào có thể đến showroom để xem trực tiếp?</p>
|
|
</div>
|
|
<div class="message-info">
|
|
<span class="message-time">14:30</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Typing Indicator -->
|
|
<div class="typing-indicator" id="typingIndicator" style="display: none;">
|
|
<div class="message-avatar">
|
|
<img src="https://placehold.co/32x32/FFE4B5/8B4513/png?text=NA" alt="">
|
|
</div>
|
|
<div class="typing-bubble">
|
|
<div class="typing-dots">
|
|
<span></span>
|
|
<span></span>
|
|
<span></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Chat Input Area -->
|
|
<div class="chat-input-container">
|
|
<!-- Quick Actions (Hidden by default) -->
|
|
<div class="quick-actions" id="quickActions" style="display: none;">
|
|
<button class="quick-action-btn" onclick="shareLocation()">
|
|
<i class="fas fa-map-marker-alt"></i>
|
|
<span>Vị trí</span>
|
|
</button>
|
|
<button class="quick-action-btn" onclick="shareContact()">
|
|
<i class="fas fa-user"></i>
|
|
<span>Liên hệ</span>
|
|
</button>
|
|
<button class="quick-action-btn" onclick="shareProduct()">
|
|
<i class="fas fa-box"></i>
|
|
<span>Sản phẩm</span>
|
|
</button>
|
|
<button class="quick-action-btn" onclick="shareDocument()">
|
|
<i class="fas fa-file"></i>
|
|
<span>Tài liệu</span>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Main Input Area -->
|
|
<div class="input-area">
|
|
<button class="input-action-btn" onclick="toggleQuickActions()" id="attachBtn">
|
|
<i class="fas fa-plus"></i>
|
|
</button>
|
|
|
|
<div class="message-input-wrapper">
|
|
<input type="text"
|
|
class="message-input"
|
|
placeholder="Nhập tin nhắn..."
|
|
id="messageInput"
|
|
maxlength="1000">
|
|
<button class="emoji-btn" onclick="toggleEmoji()">
|
|
<i class="fas fa-smile"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Voice/Send Button -->
|
|
<button class="send-voice-btn" id="sendVoiceBtn" onmousedown="startVoiceRecording()" onmouseup="stopVoiceRecording()" ontouchstart="startVoiceRecording()" ontouchend="stopVoiceRecording()">
|
|
<i class="fas fa-microphone" id="sendVoiceIcon"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Voice Recording Indicator -->
|
|
<div class="voice-recording" id="voiceRecording" style="display: none;">
|
|
<div class="recording-animation">
|
|
<i class="fas fa-microphone"></i>
|
|
<div class="recording-dots">
|
|
<span></span>
|
|
<span></span>
|
|
<span></span>
|
|
</div>
|
|
</div>
|
|
<span class="recording-text">Đang ghi âm... Thả để gửi</span>
|
|
<button class="cancel-recording" onclick="cancelVoiceRecording()">
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Image Fullscreen Modal -->
|
|
<div class="image-modal" id="imageModal" onclick="closeImageModal()">
|
|
<div class="image-modal-content">
|
|
<img id="modalImage" src="" alt="">
|
|
<button class="image-modal-close" onclick="closeImageModal()">
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.chat-wrapper {
|
|
height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
background: var(--background-gray);
|
|
}
|
|
|
|
/* Chat Header */
|
|
.chat-header {
|
|
background: var(--white);
|
|
padding: 12px 16px;
|
|
border-bottom: 1px solid var(--border-color);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 100;
|
|
}
|
|
|
|
.chat-header-left {
|
|
display: flex;
|
|
align-items: center;
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.contact-info {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-left: 12px;
|
|
cursor: pointer;
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.contact-avatar {
|
|
position: relative;
|
|
margin-right: 12px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.contact-avatar img {
|
|
width: 40px;
|
|
height: 40px;
|
|
border-radius: 50%;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.online-status {
|
|
position: absolute;
|
|
bottom: 0;
|
|
right: 0;
|
|
width: 12px;
|
|
height: 12px;
|
|
border-radius: 50%;
|
|
border: 2px solid var(--white);
|
|
}
|
|
|
|
.online-status.online {
|
|
background: var(--success-color);
|
|
}
|
|
|
|
.online-status.away {
|
|
background: var(--warning-color);
|
|
}
|
|
|
|
.online-status.offline {
|
|
background: var(--text-light);
|
|
}
|
|
|
|
.contact-details {
|
|
min-width: 0;
|
|
flex: 1;
|
|
}
|
|
|
|
.contact-name {
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
color: var(--text-dark);
|
|
margin: 0;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.contact-status {
|
|
font-size: 12px;
|
|
color: var(--text-light);
|
|
}
|
|
|
|
.chat-header-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.chat-action-btn {
|
|
width: 40px;
|
|
height: 40px;
|
|
border-radius: 50%;
|
|
border: none;
|
|
background: var(--background-gray);
|
|
color: var(--text-dark);
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.chat-action-btn:hover {
|
|
background: var(--border-color);
|
|
}
|
|
|
|
/* Messages Container */
|
|
.chat-messages-container {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding: 16px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.messages-wrapper {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
}
|
|
|
|
/* Date Separator */
|
|
.date-separator {
|
|
text-align: center;
|
|
margin: 16px 0;
|
|
}
|
|
|
|
.date-separator span {
|
|
background: var(--white);
|
|
color: var(--text-light);
|
|
padding: 6px 16px;
|
|
border-radius: 12px;
|
|
font-size: 12px;
|
|
box-shadow: var(--shadow-light);
|
|
}
|
|
|
|
/* Message Items */
|
|
.message-item {
|
|
display: flex;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.message-item.received {
|
|
justify-content: flex-start;
|
|
}
|
|
|
|
.message-item.sent {
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
.message-avatar {
|
|
width: 32px;
|
|
height: 32px;
|
|
margin-right: 8px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.message-avatar img {
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 50%;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.message-content {
|
|
max-width: 75%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.message-item.sent .message-content {
|
|
align-items: flex-end;
|
|
}
|
|
|
|
.message-bubble {
|
|
background: var(--white);
|
|
padding: 12px 16px;
|
|
border-radius: 18px;
|
|
box-shadow: var(--shadow-light);
|
|
position: relative;
|
|
}
|
|
|
|
.message-item.sent .message-bubble {
|
|
background: var(--primary-blue);
|
|
color: white;
|
|
}
|
|
|
|
.message-bubble p {
|
|
margin: 0;
|
|
line-height: 1.4;
|
|
word-wrap: break-word;
|
|
}
|
|
|
|
.message-info {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
margin-top: 4px;
|
|
font-size: 11px;
|
|
color: var(--text-light);
|
|
}
|
|
|
|
.message-item.sent .message-info {
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
.message-status.delivered {
|
|
color: var(--primary-blue);
|
|
}
|
|
|
|
.message-status.read {
|
|
color: var(--success-color);
|
|
}
|
|
|
|
/* Message Images */
|
|
.message-images {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
|
gap: 8px;
|
|
margin-top: 8px;
|
|
}
|
|
|
|
.message-image {
|
|
position: relative;
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.message-image img {
|
|
width: 100%;
|
|
height: auto;
|
|
display: block;
|
|
}
|
|
|
|
.image-overlay {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0, 0, 0, 0.3);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: white;
|
|
opacity: 0;
|
|
transition: opacity 0.3s ease;
|
|
}
|
|
|
|
.message-image:hover .image-overlay {
|
|
opacity: 1;
|
|
}
|
|
|
|
/* Shared Product */
|
|
.shared-product {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
padding: 12px;
|
|
border-radius: 12px;
|
|
margin-top: 8px;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.message-item.received .shared-product {
|
|
background: var(--background-gray);
|
|
}
|
|
|
|
.shared-product:hover {
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.shared-product img {
|
|
width: 60px;
|
|
height: 60px;
|
|
border-radius: 8px;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.shared-product .product-info {
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.shared-product h4 {
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
margin: 0 0 4px 0;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.shared-product p {
|
|
font-size: 12px;
|
|
opacity: 0.8;
|
|
margin: 0 0 4px 0;
|
|
}
|
|
|
|
.product-price {
|
|
font-size: 14px;
|
|
font-weight: 700;
|
|
color: var(--danger-color);
|
|
}
|
|
|
|
.message-item.sent .product-price {
|
|
color: #ffeb3b;
|
|
}
|
|
|
|
/* Voice Message */
|
|
.voice-message {
|
|
min-width: 200px;
|
|
}
|
|
|
|
.voice-player {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
}
|
|
|
|
.voice-play-btn {
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: 50%;
|
|
border: none;
|
|
background: rgba(255, 255, 255, 0.2);
|
|
color: inherit;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.voice-waveform {
|
|
flex: 1;
|
|
height: 20px;
|
|
background: rgba(255, 255, 255, 0.2);
|
|
border-radius: 10px;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.voice-progress {
|
|
height: 100%;
|
|
background: rgba(255, 255, 255, 0.4);
|
|
border-radius: 10px;
|
|
width: 30%;
|
|
transition: width 0.3s ease;
|
|
}
|
|
|
|
.voice-duration {
|
|
font-size: 12px;
|
|
opacity: 0.8;
|
|
}
|
|
|
|
/* System Message */
|
|
.system-message {
|
|
text-align: center;
|
|
padding: 8px 16px;
|
|
background: rgba(255, 255, 255, 0.8);
|
|
border-radius: 12px;
|
|
font-size: 12px;
|
|
color: var(--text-light);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 8px;
|
|
margin: 16px auto;
|
|
max-width: 300px;
|
|
}
|
|
|
|
/* Typing Indicator */
|
|
.typing-indicator {
|
|
display: flex;
|
|
align-items: flex-end;
|
|
opacity: 0.7;
|
|
}
|
|
|
|
.typing-bubble {
|
|
background: var(--white);
|
|
padding: 12px 16px;
|
|
border-radius: 18px;
|
|
box-shadow: var(--shadow-light);
|
|
}
|
|
|
|
.typing-dots {
|
|
display: flex;
|
|
gap: 4px;
|
|
}
|
|
|
|
.typing-dots span {
|
|
width: 6px;
|
|
height: 6px;
|
|
border-radius: 50%;
|
|
background: var(--text-light);
|
|
animation: typing 1.4s infinite ease-in-out;
|
|
}
|
|
|
|
.typing-dots span:nth-child(1) { animation-delay: -0.32s; }
|
|
.typing-dots span:nth-child(2) { animation-delay: -0.16s; }
|
|
|
|
@keyframes typing {
|
|
0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; }
|
|
40% { transform: scale(1); opacity: 1; }
|
|
}
|
|
|
|
/* Chat Input */
|
|
.chat-input-container {
|
|
background: var(--white);
|
|
border-top: 1px solid var(--border-color);
|
|
position: sticky;
|
|
bottom: 0;
|
|
}
|
|
|
|
.quick-actions {
|
|
display: flex;
|
|
gap: 12px;
|
|
padding: 12px 16px;
|
|
border-bottom: 1px solid var(--border-color);
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.quick-action-btn {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 4px;
|
|
padding: 8px 12px;
|
|
border: none;
|
|
background: var(--background-gray);
|
|
border-radius: 8px;
|
|
cursor: pointer;
|
|
min-width: 60px;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.quick-action-btn:hover {
|
|
background: var(--border-color);
|
|
}
|
|
|
|
.quick-action-btn i {
|
|
font-size: 18px;
|
|
color: var(--primary-blue);
|
|
}
|
|
|
|
.quick-action-btn span {
|
|
font-size: 11px;
|
|
color: var(--text-dark);
|
|
}
|
|
|
|
.input-area {
|
|
display: flex;
|
|
align-items: flex-end;
|
|
padding: 12px 16px;
|
|
gap: 8px;
|
|
}
|
|
|
|
.input-action-btn {
|
|
width: 40px;
|
|
height: 40px;
|
|
border-radius: 50%;
|
|
border: none;
|
|
background: var(--background-gray);
|
|
color: var(--text-dark);
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.input-action-btn:hover {
|
|
background: var(--border-color);
|
|
}
|
|
|
|
.message-input-wrapper {
|
|
flex: 1;
|
|
position: relative;
|
|
background: var(--background-gray);
|
|
border-radius: 20px;
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 8px 12px;
|
|
}
|
|
|
|
.message-input {
|
|
flex: 1;
|
|
border: none;
|
|
background: none;
|
|
outline: none;
|
|
font-size: 14px;
|
|
color: var(--text-dark);
|
|
resize: none;
|
|
max-height: 100px;
|
|
}
|
|
|
|
.emoji-btn {
|
|
width: 30px;
|
|
height: 30px;
|
|
border: none;
|
|
background: none;
|
|
color: var(--text-light);
|
|
cursor: pointer;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.send-voice-btn {
|
|
width: 40px;
|
|
height: 40px;
|
|
border-radius: 50%;
|
|
border: none;
|
|
background: var(--primary-blue);
|
|
color: white;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.send-voice-btn:hover {
|
|
background: var(--light-blue);
|
|
}
|
|
|
|
.send-voice-btn.recording {
|
|
background: var(--danger-color);
|
|
animation: pulse 1s infinite;
|
|
}
|
|
|
|
@keyframes pulse {
|
|
0% { transform: scale(1); }
|
|
50% { transform: scale(1.05); }
|
|
100% { transform: scale(1); }
|
|
}
|
|
|
|
/* Voice Recording */
|
|
.voice-recording {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 16px;
|
|
background: var(--danger-color);
|
|
color: white;
|
|
}
|
|
|
|
.recording-animation {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
}
|
|
|
|
.recording-animation i {
|
|
font-size: 20px;
|
|
animation: pulse 1s infinite;
|
|
}
|
|
|
|
.recording-dots {
|
|
display: flex;
|
|
gap: 4px;
|
|
}
|
|
|
|
.recording-dots span {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
background: white;
|
|
animation: recording 1.4s infinite ease-in-out;
|
|
}
|
|
|
|
.recording-dots span:nth-child(1) { animation-delay: -0.32s; }
|
|
.recording-dots span:nth-child(2) { animation-delay: -0.16s; }
|
|
|
|
@keyframes recording {
|
|
0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; }
|
|
40% { transform: scale(1); opacity: 1; }
|
|
}
|
|
|
|
.cancel-recording {
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: 50%;
|
|
border: 2px solid white;
|
|
background: none;
|
|
color: white;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
/* Image Modal */
|
|
.image-modal {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0, 0, 0, 0.9);
|
|
display: none;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 1000;
|
|
}
|
|
|
|
.image-modal.show {
|
|
display: flex;
|
|
}
|
|
|
|
.image-modal-content {
|
|
position: relative;
|
|
max-width: 90%;
|
|
max-height: 90%;
|
|
}
|
|
|
|
.image-modal-content img {
|
|
width: 100%;
|
|
height: auto;
|
|
border-radius: 8px;
|
|
}
|
|
|
|
.image-modal-close {
|
|
position: absolute;
|
|
top: 16px;
|
|
right: 16px;
|
|
width: 40px;
|
|
height: 40px;
|
|
border-radius: 50%;
|
|
border: none;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
color: white;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
/* Mobile Responsiveness */
|
|
@media (max-width: 480px) {
|
|
.message-content {
|
|
max-width: 85%;
|
|
}
|
|
|
|
.chat-header {
|
|
padding: 8px 12px;
|
|
}
|
|
|
|
.contact-name {
|
|
font-size: 15px;
|
|
}
|
|
|
|
.message-bubble {
|
|
padding: 10px 14px;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
let isRecording = false;
|
|
let recordingStartTime = 0;
|
|
|
|
// Get conversation info from URL
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const conversationId = urlParams.get('id') || 'conv001';
|
|
|
|
// Initialize chat based on conversation ID
|
|
function initializeChat() {
|
|
// This would typically load conversation data from an API
|
|
const conversations = {
|
|
'conv001': {
|
|
name: 'Nguyễn Văn A',
|
|
avatar: 'https://placehold.co/40x40/FFE4B5/8B4513/png?text=NA',
|
|
status: 'Đang hoạt động',
|
|
online: 'online'
|
|
},
|
|
'conv002': {
|
|
name: 'Trần Thị B',
|
|
avatar: 'https://placehold.co/40x40/E6E6FA/483D8B/png?text=TTB',
|
|
status: '2 giờ trước',
|
|
online: 'away'
|
|
},
|
|
'support001': {
|
|
name: 'Hỗ trợ kỹ thuật',
|
|
avatar: 'fas fa-headset',
|
|
status: 'Đang hoạt động',
|
|
online: 'online'
|
|
}
|
|
};
|
|
|
|
const conv = conversations[conversationId] || conversations['conv001'];
|
|
|
|
document.title = `Trò chuyện với ${conv.name} - EuroTile Worker`;
|
|
document.getElementById('contactName').textContent = conv.name;
|
|
document.getElementById('contactStatus').textContent = conv.status;
|
|
document.getElementById('onlineStatus').className = `online-status ${conv.online}`;
|
|
|
|
if (conv.avatar.startsWith('fas')) {
|
|
document.getElementById('contactAvatar').innerHTML = `<i class="${conv.avatar}"></i>`;
|
|
} else {
|
|
document.getElementById('contactAvatar').src = conv.avatar;
|
|
}
|
|
|
|
// Check if we're sharing a product
|
|
checkProductSharing();
|
|
}
|
|
|
|
function checkProductSharing() {
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const isSharing = urlParams.get('share') === 'true';
|
|
|
|
if (isSharing) {
|
|
const productId = urlParams.get('product');
|
|
const productName = urlParams.get('name');
|
|
const productPrice = urlParams.get('price');
|
|
|
|
if (productId && productName && productPrice) {
|
|
setTimeout(() => {
|
|
sendSharedProduct(productId, decodeURIComponent(productName), decodeURIComponent(productPrice));
|
|
}, 500);
|
|
}
|
|
}
|
|
}
|
|
|
|
function sendSharedProduct(productId, productName, productPrice) {
|
|
const messagesContainer = document.querySelector('.messages-wrapper');
|
|
const messageDiv = document.createElement('div');
|
|
messageDiv.className = 'message-item sent';
|
|
|
|
const now = new Date();
|
|
const timeStr = now.getHours().toString().padStart(2, '0') + ':' +
|
|
now.getMinutes().toString().padStart(2, '0');
|
|
|
|
messageDiv.innerHTML = `
|
|
<div class="message-content">
|
|
<div class="message-bubble">
|
|
<p>Tôi muốn chia sẻ sản phẩm này với bạn:</p>
|
|
<div class="shared-product" onclick="viewProduct('${productId}')">
|
|
<img src="https://placehold.co/60x60/F5F5F5/005B9A/png?text=Gạch" alt="${productName}">
|
|
<div class="product-info">
|
|
<h4>${productName}</h4>
|
|
<p>Kích thước: 60x60cm</p>
|
|
<div class="product-price">${productPrice}</div>
|
|
</div>
|
|
<i class="fas fa-external-link-alt"></i>
|
|
</div>
|
|
</div>
|
|
<div class="message-info">
|
|
<span class="message-time">${timeStr}</span>
|
|
<i class="fas fa-check-double message-status delivered"></i>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
messagesContainer.appendChild(messageDiv);
|
|
scrollToBottom();
|
|
|
|
// Simulate customer response after a delay
|
|
setTimeout(() => {
|
|
showTypingIndicator();
|
|
setTimeout(() => {
|
|
hideTypingIndicator();
|
|
addMessageToChat('Cảm ơn bạn đã chia sẻ! Sản phẩm này trông rất tốt. Có thể cho tôi biết thêm thông tin không?', 'received');
|
|
}, 2000);
|
|
}, 1000);
|
|
}
|
|
|
|
function toggleQuickActions() {
|
|
const quickActions = document.getElementById('quickActions');
|
|
const attachBtn = document.getElementById('attachBtn');
|
|
|
|
if (quickActions.style.display === 'none') {
|
|
quickActions.style.display = 'flex';
|
|
attachBtn.innerHTML = '<i class="fas fa-times"></i>';
|
|
} else {
|
|
quickActions.style.display = 'none';
|
|
attachBtn.innerHTML = '<i class="fas fa-plus"></i>';
|
|
}
|
|
}
|
|
|
|
function toggleEmoji() {
|
|
// In a real app, this would show emoji picker
|
|
alert('Emoji picker sẽ được triển khai trong phiên bản tiếp theo.');
|
|
}
|
|
|
|
function sendMessage() {
|
|
const input = document.getElementById('messageInput');
|
|
const message = input.value.trim();
|
|
|
|
if (message) {
|
|
// Add message to chat (in a real app, this would send to server)
|
|
addMessageToChat(message, 'sent');
|
|
input.value = '';
|
|
|
|
// Simulate typing indicator and response
|
|
showTypingIndicator();
|
|
setTimeout(() => {
|
|
hideTypingIndicator();
|
|
addMessageToChat('Cảm ơn bạn! Tôi sẽ phản hồi sớm nhất có thể.', 'received');
|
|
}, 2000);
|
|
}
|
|
}
|
|
|
|
function addMessageToChat(text, type) {
|
|
const messagesContainer = document.querySelector('.messages-wrapper');
|
|
const messageDiv = document.createElement('div');
|
|
messageDiv.className = `message-item ${type}`;
|
|
|
|
const now = new Date();
|
|
const timeStr = now.getHours().toString().padStart(2, '0') + ':' +
|
|
now.getMinutes().toString().padStart(2, '0');
|
|
|
|
if (type === 'received') {
|
|
messageDiv.innerHTML = `
|
|
<div class="message-avatar">
|
|
<img src="https://placehold.co/32x32/FFE4B5/8B4513/png?text=NA" alt="">
|
|
</div>
|
|
<div class="message-content">
|
|
<div class="message-bubble">
|
|
<p>${text}</p>
|
|
</div>
|
|
<div class="message-info">
|
|
<span class="message-time">${timeStr}</span>
|
|
</div>
|
|
</div>
|
|
`;
|
|
} else {
|
|
messageDiv.innerHTML = `
|
|
<div class="message-content">
|
|
<div class="message-bubble">
|
|
<p>${text}</p>
|
|
</div>
|
|
<div class="message-info">
|
|
<span class="message-time">${timeStr}</span>
|
|
<i class="fas fa-check-double message-status delivered"></i>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Remove typing indicator if present
|
|
const typingIndicator = document.getElementById('typingIndicator');
|
|
if (typingIndicator.style.display !== 'none') {
|
|
typingIndicator.remove();
|
|
}
|
|
|
|
messagesContainer.appendChild(messageDiv);
|
|
scrollToBottom();
|
|
}
|
|
|
|
function showTypingIndicator() {
|
|
const indicator = document.getElementById('typingIndicator');
|
|
indicator.style.display = 'flex';
|
|
scrollToBottom();
|
|
}
|
|
|
|
function hideTypingIndicator() {
|
|
const indicator = document.getElementById('typingIndicator');
|
|
indicator.style.display = 'none';
|
|
}
|
|
|
|
function scrollToBottom() {
|
|
const container = document.getElementById('messagesContainer');
|
|
container.scrollTop = container.scrollHeight;
|
|
}
|
|
|
|
function startVoiceRecording() {
|
|
if (!isRecording) {
|
|
isRecording = true;
|
|
recordingStartTime = Date.now();
|
|
|
|
document.getElementById('voiceRecording').style.display = 'flex';
|
|
document.getElementById('sendVoiceBtn').classList.add('recording');
|
|
document.getElementById('sendVoiceIcon').className = 'fas fa-stop';
|
|
|
|
// Hide quick actions if open
|
|
document.getElementById('quickActions').style.display = 'none';
|
|
document.getElementById('attachBtn').innerHTML = '<i class="fas fa-plus"></i>';
|
|
}
|
|
}
|
|
|
|
function stopVoiceRecording() {
|
|
if (isRecording) {
|
|
const recordingDuration = Math.floor((Date.now() - recordingStartTime) / 1000);
|
|
|
|
if (recordingDuration > 1) { // Minimum 1 second
|
|
// Send voice message
|
|
addVoiceMessageToChat(recordingDuration);
|
|
}
|
|
|
|
cancelVoiceRecording();
|
|
}
|
|
}
|
|
|
|
function cancelVoiceRecording() {
|
|
isRecording = false;
|
|
document.getElementById('voiceRecording').style.display = 'none';
|
|
document.getElementById('sendVoiceBtn').classList.remove('recording');
|
|
document.getElementById('sendVoiceIcon').className = 'fas fa-microphone';
|
|
}
|
|
|
|
function addVoiceMessageToChat(duration) {
|
|
const messagesContainer = document.querySelector('.messages-wrapper');
|
|
const messageDiv = document.createElement('div');
|
|
messageDiv.className = 'message-item sent';
|
|
|
|
const now = new Date();
|
|
const timeStr = now.getHours().toString().padStart(2, '0') + ':' +
|
|
now.getMinutes().toString().padStart(2, '0');
|
|
|
|
const minutes = Math.floor(duration / 60);
|
|
const seconds = duration % 60;
|
|
const durationStr = `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
|
|
|
messageDiv.innerHTML = `
|
|
<div class="message-content">
|
|
<div class="message-bubble voice-message">
|
|
<div class="voice-player">
|
|
<button class="voice-play-btn" onclick="playVoiceMessage(this)">
|
|
<i class="fas fa-play"></i>
|
|
</button>
|
|
<div class="voice-waveform">
|
|
<div class="voice-progress"></div>
|
|
</div>
|
|
<span class="voice-duration">${durationStr}</span>
|
|
</div>
|
|
</div>
|
|
<div class="message-info">
|
|
<span class="message-time">${timeStr}</span>
|
|
<i class="fas fa-check-double message-status delivered"></i>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
messagesContainer.appendChild(messageDiv);
|
|
scrollToBottom();
|
|
}
|
|
|
|
function playVoiceMessage(button) {
|
|
const icon = button.querySelector('i');
|
|
const progress = button.parentElement.querySelector('.voice-progress');
|
|
|
|
if (icon.classList.contains('fa-play')) {
|
|
icon.className = 'fas fa-pause';
|
|
// Simulate playing animation
|
|
let width = 0;
|
|
const interval = setInterval(() => {
|
|
width += 2;
|
|
progress.style.width = width + '%';
|
|
if (width >= 100) {
|
|
clearInterval(interval);
|
|
icon.className = 'fas fa-play';
|
|
progress.style.width = '0%';
|
|
}
|
|
}, 100);
|
|
} else {
|
|
icon.className = 'fas fa-play';
|
|
progress.style.width = '0%';
|
|
}
|
|
}
|
|
|
|
function viewImageFullscreen(src) {
|
|
const modal = document.getElementById('imageModal');
|
|
const modalImage = document.getElementById('modalImage');
|
|
|
|
modalImage.src = src;
|
|
modal.classList.add('show');
|
|
}
|
|
|
|
function closeImageModal() {
|
|
const modal = document.getElementById('imageModal');
|
|
modal.classList.remove('show');
|
|
}
|
|
|
|
function viewProduct(productId) {
|
|
window.location.href = `product-detail.html?id=${productId}`;
|
|
}
|
|
|
|
function viewContactProfile() {
|
|
// In a real app, this would show contact profile
|
|
alert('Thông tin chi tiết về khách hàng sẽ được triển khai trong phiên bản tiếp theo.');
|
|
}
|
|
|
|
function makeCall() {
|
|
if (confirm('Gọi điện cho khách hàng?')) {
|
|
// In a real app, this would initiate a call
|
|
alert('Đang kết nối cuộc gọi...');
|
|
}
|
|
}
|
|
|
|
function videoCall() {
|
|
if (confirm('Bắt đầu cuộc gọi video?')) {
|
|
// In a real app, this would start video call
|
|
alert('Đang kết nối cuộc gọi video...');
|
|
}
|
|
}
|
|
|
|
function showChatMenu() {
|
|
// In a real app, this would show chat options menu
|
|
alert('Menu tùy chọn chat sẽ được triển khai trong phiên bản tiếp theo.');
|
|
}
|
|
|
|
// Quick Actions
|
|
function shareLocation() {
|
|
alert('Chức năng chia sẻ vị trí sẽ được triển khai trong phiên bản tiếp theo.');
|
|
}
|
|
|
|
function shareContact() {
|
|
alert('Chức năng chia sẻ liên hệ sẽ được triển khai trong phiên bản tiếp theo.');
|
|
}
|
|
|
|
function shareProduct() {
|
|
// Navigate to products page with sharing mode
|
|
window.location.href = 'products.html?mode=share&chat=' + conversationId;
|
|
}
|
|
|
|
function shareDocument() {
|
|
alert('Chức năng chia sẻ tài liệu sẽ được triển khai trong phiên bản tiếp theo.');
|
|
}
|
|
|
|
// Event Listeners
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
initializeChat();
|
|
|
|
const messageInput = document.getElementById('messageInput');
|
|
const sendBtn = document.getElementById('sendVoiceBtn');
|
|
|
|
messageInput.addEventListener('input', function() {
|
|
if (this.value.trim()) {
|
|
sendBtn.innerHTML = '<i class="fas fa-paper-plane"></i>';
|
|
sendBtn.onclick = sendMessage;
|
|
} else {
|
|
sendBtn.innerHTML = '<i class="fas fa-microphone"></i>';
|
|
sendBtn.onclick = null;
|
|
sendBtn.onmousedown = startVoiceRecording;
|
|
sendBtn.onmouseup = stopVoiceRecording;
|
|
}
|
|
});
|
|
|
|
messageInput.addEventListener('keypress', function(e) {
|
|
if (e.key === 'Enter') {
|
|
sendMessage();
|
|
}
|
|
});
|
|
|
|
// Auto-scroll to bottom
|
|
scrollToBottom();
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |