Files
worker/html/quote-detail.html
2025-10-24 11:31:48 +07:00

996 lines
33 KiB
HTML

<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chi tiết báo giá #YC001234 - 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">
<!-- Header -->
<div class="header">
<a href="quotes-list.html" class="back-button">
<i class="fas fa-arrow-left"></i>
</a>
<h1 class="header-title">Chi tiết báo giá</h1>
<div class="header-actions">
<button class="header-action-btn" onclick="shareQuote()">
<i class="fas fa-share"></i>
</button>
<button class="header-action-btn" onclick="printQuote()">
<i class="fas fa-print"></i>
</button>
</div>
</div>
<div class="quote-detail-content">
<!-- Status Card -->
<div class="quote-status-card">
<div class="quote-header-info">
<h2 class="quote-number">#YC001234</h2>
<span class="current-quote-status negotiating" id="currentStatus">Đang đàm phán</span>
</div>
<div class="quote-basic-info">
<div class="info-row">
<span class="info-label">Dự án:</span>
<span class="info-value">Villa Thủ Đức - Giai đoạn 2</span>
</div>
<div class="info-row">
<span class="info-label">Khách hàng:</span>
<span class="info-value">Nguyễn Văn A - 0901234567</span>
</div>
<div class="info-row">
<span class="info-label">Ngày tạo:</span>
<span class="info-value">05/08/2023</span>
</div>
</div>
</div>
<!-- Tab Navigation -->
<div class="quote-tabs-section">
<div class="quote-tab-navigation">
<button class="quote-tab-button active" onclick="switchQuoteTab('details', this)">
<i class="fas fa-list"></i>
Chi tiết báo giá
</button>
<button class="quote-tab-button" onclick="switchQuoteTab('history', this)">
<i class="fas fa-history"></i>
Lịch sử trao đổi
</button>
</div>
<!-- Tab 1: Chi tiết báo giá -->
<div class="quote-tab-content active" id="details">
<div class="quote-products-section">
<h3>Danh sách sản phẩm</h3>
<!-- Product Item 1 -->
<div class="quote-product-item">
<div class="product-image">
<img src="https://placehold.co/60x60/F5F5F5/005B9A/png?text=G1" alt="Gạch granite">
</div>
<div class="product-details">
<h4 class="product-name">Gạch granite Eurotile 60x60</h4>
<div class="product-specs">
<span class="spec">SKU: ET-GR-001</span>
<span class="spec">Màu: Xám nhạt</span>
</div>
</div>
<div class="product-quantity">
<span class="qty-label">Số lượng:</span>
<span class="qty-value">100 m²</span>
</div>
<div class="product-pricing">
<div class="unit-price">285.000đ/m²</div>
<div class="total-price">28.500.000đ</div>
</div>
</div>
<!-- Product Item 2 -->
<div class="quote-product-item">
<div class="product-image">
<img src="https://placehold.co/60x60/E8E8E8/005B9A/png?text=G2" alt="Gạch ceramic">
</div>
<div class="product-details">
<h4 class="product-name">Gạch ceramic Vasta 30x60</h4>
<div class="product-specs">
<span class="spec">SKU: VS-CR-002</span>
<span class="spec">Màu: Trắng sữa</span>
</div>
</div>
<div class="product-quantity">
<span class="qty-label">Số lượng:</span>
<span class="qty-value">80 m²</span>
</div>
<div class="product-pricing">
<div class="unit-price">180.000đ/m²</div>
<div class="total-price">14.400.000đ</div>
</div>
</div>
<!-- Product Item 3 -->
<div class="quote-product-item">
<div class="product-image">
<img src="https://placehold.co/60x60/DDDDDD/005B9A/png?text=G3" alt="Gạch mosaic">
</div>
<div class="product-details">
<h4 class="product-name">Gạch mosaic trang trí</h4>
<div class="product-specs">
<span class="spec">SKU: ET-MS-003</span>
<span class="spec">Màu: Đa sắc</span>
</div>
</div>
<div class="product-quantity">
<span class="qty-label">Số lượng:</span>
<span class="qty-value">20 m²</span>
</div>
<div class="product-pricing">
<div class="unit-price">450.000đ/m²</div>
<div class="total-price">9.000.000đ</div>
</div>
</div>
</div>
<!-- Quote Summary -->
<div class="quote-summary">
<div class="summary-row">
<span class="summary-label">Tạm tính:</span>
<span class="summary-value">51.900.000đ</span>
</div>
<div class="summary-row">
<span class="summary-label">Chiết khấu:</span>
<span class="summary-value discount">-2.595.000đ (5%)</span>
</div>
<div class="summary-row">
<span class="summary-label">Phí vận chuyển:</span>
<span class="summary-value">500.000đ</span>
</div>
<div class="summary-row total">
<span class="summary-label">Tổng cộng:</span>
<span class="summary-value">49.805.000đ</span>
</div>
</div>
<!-- Terms & Conditions -->
<div class="quote-terms">
<h4>Điều khoản & Điều kiện</h4>
<ul>
<li>Báo giá có hiệu lực trong 30 ngày</li>
<li>Thanh toán: 50% đặt cọc, 50% khi giao hàng</li>
<li>Thời gian giao hàng: 7-10 ngày làm việc</li>
<li>Bảo hành sản phẩm: 15 năm</li>
</ul>
</div>
</div>
<!-- Tab 2: Lịch sử trao đổi -->
<div class="quote-tab-content" id="history">
<div class="timeline-history">
<div class="timeline-item completed">
<div class="timeline-icon">
<i class="fas fa-plus"></i>
</div>
<div class="timeline-content">
<div class="timeline-title">Yêu cầu báo giá được tạo</div>
<div class="timeline-date">05/08/2023 - 09:00</div>
<div class="timeline-description">Khách hàng Nguyễn Văn A tạo yêu cầu báo giá</div>
</div>
</div>
<div class="timeline-item completed">
<div class="timeline-icon">
<i class="fas fa-paper-plane"></i>
</div>
<div class="timeline-content">
<div class="timeline-title">Báo giá được gửi</div>
<div class="timeline-date">05/08/2023 - 14:30</div>
<div class="timeline-description">Báo giá gốc: 51.900.000đ gửi cho khách hàng</div>
</div>
</div>
<div class="timeline-item active">
<div class="timeline-icon">
<i class="fas fa-handshake"></i>
</div>
<div class="timeline-content">
<div class="timeline-title">Đàm phán giá</div>
<div class="timeline-date">06/08/2023 - 10:15</div>
<div class="timeline-description">Khách hàng yêu cầu giảm giá 5%. Đang thương lượng.</div>
<button class="timeline-chat-btn" onclick="openQuoteChat()">
<i class="fas fa-comments"></i>
Xem cuộc trò chuyện
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Dynamic Action Buttons -->
<div class="quote-actions" id="quoteActions">
<!-- Actions for status: Đang đàm phán -->
<div class="action-group negotiating" style="display: flex;">
<button class="action-btn secondary" onclick="requestQuoteChat()">
<i class="fas fa-comments"></i>
Trao đổi về báo giá
</button>
<button class="action-btn primary" onclick="finalizeQuote()">
<i class="fas fa-handshake"></i>
Chốt báo giá
</button>
</div>
<!-- Actions for status: Đã gửi (Hidden by default) -->
<div class="action-group sent" style="display: none;">
<button class="action-btn secondary" onclick="requestQuoteChat()">
<i class="fas fa-comments"></i>
Trao đổi về báo giá
</button>
<button class="action-btn secondary" onclick="requestModification()">
<i class="fas fa-edit"></i>
Yêu cầu sửa đổi
</button>
</div>
<!-- Actions for status: Đã chốt (Hidden by default) -->
<div class="action-group finalized" style="display: none;">
<button class="action-btn primary large" onclick="createOrderFromQuote()">
<i class="fas fa-shopping-cart"></i>
TẠO ĐƠN HÀNG TỪ BÁO GIÁ
</button>
</div>
</div>
</div>
<!-- Modification Request Modal -->
<div class="modal-overlay" id="modificationModal" style="display: none;">
<div class="modal-content">
<div class="modal-header">
<h3>Yêu cầu sửa đổi báo giá</h3>
<button class="modal-close" onclick="closeModificationModal()">
<i class="fas fa-times"></i>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label class="form-label">Nội dung yêu cầu thay đổi *</label>
<textarea class="form-textarea" rows="4" placeholder="Vui lòng mô tả chi tiết những thay đổi bạn muốn..." id="modificationContent"></textarea>
</div>
<div class="form-group">
<label class="form-label">Đính kèm file (tùy chọn)</label>
<div class="file-upload-area" onclick="document.getElementById('modificationFile').click()">
<i class="fas fa-cloud-upload-alt"></i>
<span>Nhấn để tải file đính kèm</span>
</div>
<input type="file" id="modificationFile" style="display: none;" multiple>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" onclick="closeModificationModal()">Hủy</button>
<button class="btn btn-primary" onclick="submitModificationRequest()">Gửi yêu cầu</button>
</div>
</div>
</div>
<style>
.quote-detail-content {
padding: 0 0 100px 0;
}
/* Quote Status Card */
.quote-status-card {
background: var(--white);
margin: 16px;
padding: 20px;
border-radius: 12px;
box-shadow: var(--shadow-light);
}
.quote-header-info {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.quote-number {
font-size: 20px;
font-weight: 700;
color: var(--primary-blue);
margin: 0;
}
.current-quote-status {
padding: 6px 16px;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
color: white;
}
.current-quote-status.pending {
background: var(--warning-color);
}
.current-quote-status.sent {
background: var(--primary-blue);
}
.current-quote-status.negotiating {
background: #ff9800;
}
.current-quote-status.finalized {
background: var(--success-color);
}
.current-quote-status.cancelled {
background: var(--text-light);
}
.current-quote-status.converted {
background: #9c27b0;
}
.quote-basic-info {
display: flex;
flex-direction: column;
gap: 8px;
}
.info-row {
display: flex;
justify-content: space-between;
}
.info-label {
color: var(--text-light);
font-size: 14px;
}
.info-value {
font-weight: 500;
color: var(--text-dark);
text-align: right;
flex: 1;
margin-left: 12px;
}
/* Tab Navigation */
.quote-tabs-section {
background: var(--white);
margin: 0 16px 16px 16px;
border-radius: 12px;
box-shadow: var(--shadow-light);
overflow: hidden;
}
.quote-tab-navigation {
display: flex;
border-bottom: 1px solid var(--border-color);
}
.quote-tab-button {
flex: 1;
padding: 16px 12px;
border: none;
background: none;
font-size: 14px;
font-weight: 500;
color: var(--text-light);
cursor: pointer;
position: relative;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
.quote-tab-button.active {
color: var(--primary-blue);
font-weight: 600;
}
.quote-tab-button.active::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 2px;
background: var(--primary-blue);
}
.quote-tab-content {
display: none;
padding: 20px;
}
.quote-tab-content.active {
display: block;
}
/* Quote Products Section */
.quote-products-section h3 {
font-size: 16px;
font-weight: 600;
color: var(--text-dark);
margin: 0 0 16px 0;
}
.quote-product-item {
display: grid;
grid-template-columns: 60px 1fr auto auto;
gap: 12px;
align-items: center;
padding: 12px;
border: 1px solid var(--border-color);
border-radius: 8px;
margin-bottom: 12px;
}
.product-image img {
width: 60px;
height: 60px;
object-fit: cover;
border-radius: 6px;
}
.product-details {
min-width: 0;
}
.product-name {
font-size: 14px;
font-weight: 600;
color: var(--text-dark);
margin: 0 0 4px 0;
line-height: 1.3;
}
.product-specs {
display: flex;
flex-direction: column;
gap: 2px;
}
.spec {
font-size: 12px;
color: var(--text-light);
}
.product-quantity {
text-align: center;
}
.qty-label {
display: block;
font-size: 11px;
color: var(--text-light);
margin-bottom: 2px;
}
.qty-value {
font-size: 14px;
font-weight: 600;
color: var(--text-dark);
}
.product-pricing {
text-align: right;
}
.unit-price {
display: block;
font-size: 12px;
color: var(--text-light);
margin-bottom: 2px;
}
.total-price {
font-size: 14px;
font-weight: 700;
color: var(--primary-blue);
}
/* Quote Summary */
.quote-summary {
margin-top: 20px;
padding: 16px;
background: var(--background-gray);
border-radius: 8px;
}
.summary-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.summary-row:last-child {
margin-bottom: 0;
}
.summary-row.total {
border-top: 1px solid var(--border-color);
padding-top: 8px;
margin-top: 8px;
}
.summary-label {
color: var(--text-light);
}
.summary-row.total .summary-label {
font-weight: 600;
color: var(--text-dark);
}
.summary-value {
font-weight: 500;
color: var(--text-dark);
}
.summary-value.discount {
color: var(--success-color);
}
.summary-row.total .summary-value {
font-weight: 700;
font-size: 16px;
color: var(--danger-color);
}
/* Quote Terms */
.quote-terms {
margin-top: 20px;
}
.quote-terms h4 {
font-size: 14px;
font-weight: 600;
color: var(--text-dark);
margin: 0 0 12px 0;
}
.quote-terms ul {
list-style: none;
margin: 0;
padding: 0;
}
.quote-terms li {
font-size: 13px;
color: var(--text-dark);
margin-bottom: 6px;
padding-left: 16px;
position: relative;
}
.quote-terms li::before {
content: '•';
position: absolute;
left: 0;
color: var(--primary-blue);
}
/* Timeline History */
.timeline-history {
position: relative;
}
.timeline-history::before {
content: '';
position: absolute;
left: 12px;
top: 0;
bottom: 0;
width: 2px;
background: var(--border-color);
}
.timeline-item {
position: relative;
padding-left: 40px;
margin-bottom: 20px;
}
.timeline-item:last-child {
margin-bottom: 0;
}
.timeline-icon {
position: absolute;
left: 0;
top: 0;
width: 24px;
height: 24px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
background: var(--border-color);
color: var(--text-light);
}
.timeline-item.completed .timeline-icon {
background: var(--success-color);
color: white;
}
.timeline-item.active .timeline-icon {
background: var(--primary-blue);
color: white;
}
.timeline-title {
font-weight: 600;
color: var(--text-dark);
font-size: 14px;
}
.timeline-date {
color: var(--text-light);
font-size: 12px;
margin: 2px 0 4px 0;
}
.timeline-description {
color: var(--text-dark);
font-size: 13px;
line-height: 1.4;
}
.timeline-chat-btn {
background: var(--primary-blue);
color: white;
border: none;
border-radius: 6px;
padding: 6px 12px;
font-size: 12px;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
gap: 4px;
margin-top: 8px;
transition: all 0.3s ease;
}
.timeline-chat-btn:hover {
background: var(--light-blue);
}
/* Action Buttons */
.quote-actions {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: var(--white);
padding: 16px;
box-shadow: 0 -4px 15px rgba(0, 0, 0, 0.1);
z-index: 100;
}
.action-group {
display: flex;
gap: 12px;
}
.action-btn {
flex: 1;
padding: 12px 16px;
border: none;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
transition: all 0.3s ease;
}
.action-btn.secondary {
background: var(--border-color);
color: var(--text-dark);
border: 1px solid var(--border-color);
}
.action-btn.secondary:hover {
background: #ddd;
}
.action-btn.primary {
background: var(--primary-blue);
color: white;
}
.action-btn.primary:hover {
background: var(--light-blue);
}
.action-btn.large {
font-size: 16px;
padding: 16px 20px;
font-weight: 700;
}
/* Modal Styles */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal-content {
background: var(--white);
border-radius: 12px;
width: 90%;
max-width: 500px;
max-height: 90vh;
overflow: hidden;
}
.modal-header {
padding: 20px;
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
}
.modal-header h3 {
font-size: 18px;
font-weight: 600;
color: var(--text-dark);
margin: 0;
}
.modal-close {
width: 32px;
height: 32px;
border-radius: 50%;
border: none;
background: var(--background-gray);
color: var(--text-dark);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.modal-body {
padding: 20px;
max-height: 60vh;
overflow-y: auto;
}
.modal-footer {
padding: 16px 20px;
border-top: 1px solid var(--border-color);
display: flex;
gap: 12px;
justify-content: flex-end;
}
.file-upload-area {
border: 2px dashed var(--border-color);
border-radius: 8px;
padding: 20px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.file-upload-area:hover {
border-color: var(--primary-blue);
background: var(--background-gray);
}
.file-upload-area i {
font-size: 24px;
color: var(--primary-blue);
margin-bottom: 8px;
display: block;
}
/* Mobile Responsiveness */
@media (max-width: 480px) {
.quote-status-card,
.quote-tabs-section {
margin: 12px;
}
.quote-product-item {
grid-template-columns: 50px 1fr;
grid-template-rows: auto auto;
gap: 8px;
}
.product-quantity {
grid-column: 1;
grid-row: 2;
text-align: left;
font-size: 12px;
}
.product-pricing {
grid-column: 2;
grid-row: 2;
text-align: right;
}
.info-row {
flex-direction: column;
gap: 4px;
}
.info-value {
text-align: left;
margin-left: 0;
}
.action-btn {
font-size: 13px;
padding: 10px 12px;
}
}
</style>
<script>
// Get quote ID from URL
const urlParams = new URLSearchParams(window.location.search);
const quoteId = urlParams.get('id') || 'YC001234';
// Simulate different quote statuses for demo
const quoteStatuses = {
'YC001234': 'negotiating',
'YC001233': 'finalized',
'YC001232': 'converted',
'YC001231': 'sent',
'YC001230': 'pending',
'YC001229': 'cancelled'
};
const currentStatus = quoteStatuses[quoteId] || 'negotiating';
function switchQuoteTab(tabName, button) {
// Update tab buttons
document.querySelectorAll('.quote-tab-button').forEach(t => t.classList.remove('active'));
button.classList.add('active');
// Update tab content
document.querySelectorAll('.quote-tab-content').forEach(c => c.classList.remove('active'));
document.getElementById(tabName).classList.add('active');
}
function updateQuoteStatus(newStatus) {
// Update status display
const statusElement = document.getElementById('currentStatus');
const statusText = {
'pending': 'Chờ duyệt',
'sent': 'Đã gửi',
'negotiating': 'Đang đàm phán',
'finalized': 'Đã chốt',
'cancelled': 'Đã hủy',
'converted': 'Đã thành đơn hàng'
};
statusElement.textContent = statusText[newStatus];
statusElement.className = `current-quote-status ${newStatus}`;
// Update action buttons
document.querySelectorAll('.action-group').forEach(group => {
group.style.display = 'none';
});
const targetGroup = document.querySelector(`.action-group.${newStatus}`);
if (targetGroup) {
targetGroup.style.display = 'flex';
}
}
function requestQuoteChat() {
// Navigate to chat with quote context
window.location.href = `chat-detail.html?id=conv001&quote=${quoteId}`;
}
function requestModification() {
document.getElementById('modificationModal').style.display = 'flex';
}
function closeModificationModal() {
document.getElementById('modificationModal').style.display = 'none';
}
function submitModificationRequest() {
const content = document.getElementById('modificationContent').value.trim();
if (!content) {
alert('Vui lòng nhập nội dung yêu cầu thay đổi');
return;
}
alert('Yêu cầu sửa đổi đã được gửi thành công!\\nChúng tôi sẽ phản hồi trong vòng 24h.');
closeModificationModal();
updateQuoteStatus('negotiating');
}
function finalizeQuote() {
if (confirm('Xác nhận chốt báo giá này?\\nSau khi chốt, báo giá có thể được chuyển thành đơn hàng.')) {
alert('Báo giá đã được chốt thành công!\\nBây giờ bạn có thể tạo đơn hàng từ báo giá này.');
updateQuoteStatus('finalized');
}
}
function createOrderFromQuote() {
if (confirm('Tạo đơn hàng từ báo giá này?\\nTất cả sản phẩm sẽ được thêm vào giỏ hàng với giá đã thỏa thuận.')) {
// Clear existing cart and add quote items
localStorage.setItem('cartFromQuote', JSON.stringify({
quoteId: quoteId,
items: [
{ id: 'ET-GR-001', name: 'Gạch granite Eurotile 60x60', price: 285000, quantity: 100 },
{ id: 'VS-CR-002', name: 'Gạch ceramic Vasta 30x60', price: 180000, quantity: 80 },
{ id: 'ET-MS-003', name: 'Gạch mosaic trang trí', price: 450000, quantity: 20 }
]
}));
// Update quote status to converted
updateQuoteStatus('converted');
// Navigate to cart
setTimeout(() => {
window.location.href = 'cart.html';
}, 1000);
}
}
function openQuoteChat() {
window.location.href = `chat-detail.html?id=conv001&quote=${quoteId}`;
}
function shareQuote() {
if (navigator.share) {
navigator.share({
title: `Báo giá ${quoteId}`,
text: 'Xem chi tiết báo giá này',
url: window.location.href
});
} else {
navigator.clipboard.writeText(window.location.href);
alert('Đã sao chép link báo giá!');
}
}
function printQuote() {
window.print();
}
// Initialize page based on current status
document.addEventListener('DOMContentLoaded', function() {
updateQuoteStatus(currentStatus);
// Update page title
document.title = `Chi tiết báo giá ${quoteId} - EuroTile Worker`;
document.querySelector('.quote-number').textContent = `#${quoteId}`;
});
</script>
</body>
</html>