update database
This commit is contained in:
@@ -628,7 +628,7 @@ p {
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
background: var(--primary-blue);
|
||||
/*background: var(--primary-blue);*/
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
@@ -918,6 +918,7 @@ p {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
white-space: nowrap;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.btn-complaint:hover {
|
||||
@@ -1158,6 +1159,15 @@ p {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
/*.order-card {
|
||||
background: var(--white);
|
||||
border-radius: 12px;
|
||||
box-shadow: var(--shadow-light);
|
||||
display: flex;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}*/
|
||||
|
||||
.order-card {
|
||||
background: var(--white);
|
||||
border-radius: 12px;
|
||||
@@ -1165,6 +1175,13 @@ p {
|
||||
display: flex;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.order-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-medium);
|
||||
}
|
||||
|
||||
.order-status-indicator {
|
||||
@@ -2106,3 +2123,130 @@ p {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@keyframes rotate {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* ===========================
|
||||
PRODUCT ACTIONS STYLES
|
||||
=========================== */
|
||||
|
||||
.product-actions {
|
||||
/*display: flex;*/
|
||||
gap: 6px;
|
||||
margin-top: 8px;
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.btn-360 {
|
||||
flex: 1;
|
||||
font-size: 11px;
|
||||
padding: 6px 8px;
|
||||
border: 1px solid var(--primary-blue);
|
||||
background: transparent;
|
||||
color: var(--primary-blue);
|
||||
border-radius: 6px;
|
||||
transition: all 0.3s ease;
|
||||
width: 100%;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.btn-360:hover {
|
||||
background: var(--primary-blue);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-add-cart {
|
||||
flex: 2;
|
||||
font-size: 11px;
|
||||
padding: 6px 8px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* ===========================
|
||||
SHARE MODAL STYLES
|
||||
=========================== */
|
||||
|
||||
|
||||
/*Thêm*/
|
||||
|
||||
/* New Quote Status Badges */
|
||||
.status-badge.negotiating {
|
||||
background: #ff9800; /* Orange */
|
||||
}
|
||||
|
||||
.status-badge.finalized {
|
||||
background: var(--success-color); /* Green */
|
||||
}
|
||||
|
||||
.status-badge.converted {
|
||||
background: #9c27b0; /* Purple */
|
||||
}
|
||||
|
||||
/* Quote Request Card Styles */
|
||||
.quote-request-card {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.quote-request-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-medium);
|
||||
}
|
||||
|
||||
.quote-request-card.negotiating .quote-request-status-indicator {
|
||||
background: #ff9800;
|
||||
}
|
||||
|
||||
.quote-request-card.finalized .quote-request-status-indicator {
|
||||
background: var(--success-color);
|
||||
}
|
||||
|
||||
.quote-request-card.converted .quote-request-status-indicator {
|
||||
background: #9c27b0;
|
||||
}
|
||||
|
||||
.quote-request-card.sent .quote-request-status-indicator {
|
||||
background: var(--primary-blue);
|
||||
}
|
||||
|
||||
.quote-request-card.cancelled .quote-request-status-indicator {
|
||||
background: var(--text-light);
|
||||
}
|
||||
|
||||
|
||||
/* Quick Info Grid */
|
||||
.quick-info {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
padding: 12px;
|
||||
background: var(--background-gray);
|
||||
border-radius: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.info-icon {
|
||||
font-size: 20px;
|
||||
color: var(--primary-blue);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 11px;
|
||||
color: var(--text-light);
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: var(--text-dark);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Thanh toán - EuroTile Worker</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<!--<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>
|
||||
|
||||
760
html/design-request-create.html
Normal file
760
html/design-request-create.html
Normal file
@@ -0,0 +1,760 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="vi">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Tạo Yêu cầu Thiết kế - 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">
|
||||
<style>
|
||||
.form-container {
|
||||
max-width: 480px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background: #f8fafc;
|
||||
min-height: calc(100vh - 120px);
|
||||
}
|
||||
|
||||
.form-card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: block;
|
||||
font-weight: 600;
|
||||
color: #374151;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.required {
|
||||
color: #ef4444;
|
||||
}
|
||||
|
||||
.form-input,
|
||||
.form-textarea,
|
||||
.form-select {
|
||||
width: 100%;
|
||||
padding: 12px 16px;
|
||||
border: 2px solid #e5e7eb;
|
||||
border-radius: 8px;
|
||||
font-size: 16px;
|
||||
transition: all 0.3s ease;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.form-input:focus,
|
||||
.form-textarea:focus,
|
||||
.form-select:focus {
|
||||
outline: none;
|
||||
border-color: #2563eb;
|
||||
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
height: 100px;
|
||||
resize: vertical;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.file-upload-area {
|
||||
border: 2px dashed #d1d5db;
|
||||
border-radius: 8px;
|
||||
padding: 24px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
background: #f9fafb;
|
||||
}
|
||||
|
||||
.file-upload-area:hover {
|
||||
border-color: #2563eb;
|
||||
background: #eff6ff;
|
||||
}
|
||||
|
||||
.file-upload-area.drag-over {
|
||||
border-color: #2563eb;
|
||||
background: #eff6ff;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
font-size: 32px;
|
||||
color: #9ca3af;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.upload-text {
|
||||
color: #6b7280;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.upload-hint {
|
||||
font-size: 12px;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.file-preview {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12px;
|
||||
background: #f3f4f6;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.file-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: #2563eb;
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
margin-right: 12px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.file-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
font-size: 14px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.file-size {
|
||||
color: #6b7280;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.file-remove {
|
||||
background: #ef4444;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
flex: 1;
|
||||
padding: 14px 20px;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
border: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.4);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: white;
|
||||
color: #374151;
|
||||
border: 2px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
border-color: #2563eb;
|
||||
color: #2563eb;
|
||||
}
|
||||
|
||||
.progress-steps {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.step {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
background: #e5e7eb;
|
||||
color: #6b7280;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 600;
|
||||
margin: 0 8px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.step.active {
|
||||
background: #2563eb;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.step.completed {
|
||||
background: #10b981;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.step::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: -24px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 16px;
|
||||
height: 2px;
|
||||
background: #e5e7eb;
|
||||
}
|
||||
|
||||
.step:last-child::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.step.completed::after {
|
||||
background: #10b981;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: #ef4444;
|
||||
font-size: 12px;
|
||||
margin-top: 4px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.toast {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: #10b981;
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||
z-index: 1000;
|
||||
display: none;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.toast.show {
|
||||
display: flex;
|
||||
animation: slideDown 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes slideDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-50%) translateY(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(-50%) translateY(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-wrapper">
|
||||
<!-- Header -->
|
||||
<div class="header">
|
||||
<a href="nha-mau.html" class="back-button">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Tạo yêu cầu thiết kế mới</h1>
|
||||
<div style="width: 32px;"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-container">
|
||||
<!-- Progress Steps -->
|
||||
<div class="progress-steps">
|
||||
<div class="step active">1</div>
|
||||
<div class="step">2</div>
|
||||
<div class="step">3</div>
|
||||
</div>
|
||||
|
||||
<!-- Form -->
|
||||
<form id="design-request-form" onsubmit="submitForm(event)">
|
||||
<!-- Basic Information -->
|
||||
<div class="form-card">
|
||||
<h3 style="font-weight: 700; font-size: 18px; color: #1f2937; margin-bottom: 20px; display: flex; align-items: center; gap: 8px;">
|
||||
<i class="fas fa-info-circle" style="color: #2563eb;"></i>
|
||||
Thông tin cơ bản
|
||||
</h3>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">
|
||||
Tên dự án/Khách hàng <span class="required">*</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-input"
|
||||
id="project-name"
|
||||
placeholder="VD: Thiết kế nhà anh Minh - Quận 7"
|
||||
required>
|
||||
<div class="error-message" id="project-name-error">Vui lòng nhập tên dự án</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">
|
||||
Diện tích (m²) <span class="required">*</span>
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
class="form-input"
|
||||
id="project-area"
|
||||
placeholder="VD: 120"
|
||||
min="1"
|
||||
required>
|
||||
<div class="error-message" id="project-area-error">Vui lòng nhập diện tích hợp lệ</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">
|
||||
Phong cách mong muốn <span class="required">*</span>
|
||||
</label>
|
||||
<select class="form-select" id="project-style" required>
|
||||
<option value="">-- Chọn phong cách --</option>
|
||||
<option value="hien-dai">Hiện đại</option>
|
||||
<option value="toi-gian">Tối giản</option>
|
||||
<option value="co-dien">Cổ điển</option>
|
||||
<option value="scandinavian">Scandinavian</option>
|
||||
<option value="industrial">Industrial</option>
|
||||
<option value="tropical">Tropical</option>
|
||||
<option value="luxury">Luxury</option>
|
||||
<option value="khac">Khác (ghi rõ trong ghi chú)</option>
|
||||
</select>
|
||||
<div class="error-message" id="project-style-error">Vui lòng chọn phong cách</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">
|
||||
Ngân sách dự kiến
|
||||
</label>
|
||||
<select class="form-select" id="project-budget">
|
||||
<option value="">-- Chọn ngân sách --</option>
|
||||
<option value="duoi-100tr">Dưới 100 triệu</option>
|
||||
<option value="100-300tr">100 - 300 triệu</option>
|
||||
<option value="300-500tr">300 - 500 triệu</option>
|
||||
<option value="500tr-1ty">500 triệu - 1 tỷ</option>
|
||||
<option value="tren-1ty">Trên 1 tỷ</option>
|
||||
<option value="trao-doi">Trao đổi trực tiếp</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Detailed Requirements -->
|
||||
<div class="form-card">
|
||||
<h3 style="font-weight: 700; font-size: 18px; color: #1f2937; margin-bottom: 20px; display: flex; align-items: center; gap: 8px;">
|
||||
<i class="fas fa-edit" style="color: #2563eb;"></i>
|
||||
Yêu cầu chi tiết
|
||||
</h3>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">
|
||||
Ghi chú chi tiết <span class="required">*</span>
|
||||
</label>
|
||||
<textarea
|
||||
class="form-textarea"
|
||||
id="project-notes"
|
||||
placeholder="Mô tả chi tiết về yêu cầu thiết kế, số phòng, công năng sử dụng, sở thích cá nhân..."
|
||||
required></textarea>
|
||||
<div class="error-message" id="project-notes-error">Vui lòng mô tả yêu cầu chi tiết</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">
|
||||
Thông tin liên hệ
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-input"
|
||||
id="contact-info"
|
||||
placeholder="Số điện thoại, email hoặc địa chỉ (tùy chọn)">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- File Upload -->
|
||||
<div class="form-card">
|
||||
<h3 style="font-weight: 700; font-size: 18px; color: #1f2937; margin-bottom: 20px; display: flex; align-items: center; gap: 8px;">
|
||||
<i class="fas fa-cloud-upload-alt" style="color: #2563eb;"></i>
|
||||
Đính kèm tài liệu
|
||||
</h3>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">
|
||||
Đính kèm mặt bằng/Ảnh hiện trạng
|
||||
</label>
|
||||
|
||||
<div class="file-upload-area" onclick="document.getElementById('file-input').click()">
|
||||
<input
|
||||
type="file"
|
||||
id="file-input"
|
||||
multiple
|
||||
accept="image/*,.pdf,.dwg,.jpg,.jpeg,.png"
|
||||
style="display: none;"
|
||||
onchange="handleFileSelect(event)">
|
||||
|
||||
<div class="upload-icon">
|
||||
<i class="fas fa-cloud-upload-alt"></i>
|
||||
</div>
|
||||
<div class="upload-text">
|
||||
Nhấn để chọn file hoặc kéo thả vào đây
|
||||
</div>
|
||||
<div class="upload-hint">
|
||||
Hỗ trợ: JPG, PNG, PDF, DWG (Tối đa 10MB mỗi file)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="file-preview" id="file-preview">
|
||||
<!-- File previews will be inserted here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Form Actions -->
|
||||
<div class="form-actions">
|
||||
<button type="button" class="btn btn-secondary" onclick="saveDraft()">
|
||||
<i class="fas fa-save"></i>
|
||||
Lưu nháp
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-paper-plane"></i>
|
||||
Gửi yêu cầu
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Bottom Navigation -->
|
||||
<!--<div class="bottom-nav">
|
||||
<a href="index.html" class="nav-item">
|
||||
<i class="fas fa-home"></i>
|
||||
<span>Trang chủ</span>
|
||||
</a>
|
||||
<a href="loyalty.html" class="nav-item">
|
||||
<i class="fas fa-star"></i>
|
||||
<span>Hội viên</span>
|
||||
</a>
|
||||
<a href="promotions.html" class="nav-item">
|
||||
<i class="fas fa-tags"></i>
|
||||
<span>Khuyến mãi</span>
|
||||
</a>
|
||||
<a href="notifications.html" class="nav-item">
|
||||
<i class="fas fa-bell"></i>
|
||||
<span>Thông báo</span>
|
||||
</a>
|
||||
<a href="account.html" class="nav-item active">
|
||||
<i class="fas fa-user"></i>
|
||||
<span>Cài đặt</span>
|
||||
</a>
|
||||
</div>-->
|
||||
</div>
|
||||
|
||||
<!-- Toast Notification -->
|
||||
<div class="toast" id="toast">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
<span id="toast-message">Thành công!</span>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let selectedFiles = [];
|
||||
let currentStep = 1;
|
||||
|
||||
// File upload handling
|
||||
function handleFileSelect(event) {
|
||||
const files = Array.from(event.target.files);
|
||||
|
||||
files.forEach(file => {
|
||||
if (validateFile(file)) {
|
||||
selectedFiles.push(file);
|
||||
addFilePreview(file);
|
||||
}
|
||||
});
|
||||
|
||||
// Clear input to allow re-selecting same file
|
||||
event.target.value = '';
|
||||
}
|
||||
|
||||
function validateFile(file) {
|
||||
const maxSize = 10 * 1024 * 1024; // 10MB
|
||||
const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'application/pdf'];
|
||||
|
||||
if (file.size > maxSize) {
|
||||
showToast('File quá lớn. Vui lòng chọn file dưới 10MB', 'error');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!allowedTypes.includes(file.type) && !file.name.toLowerCase().endsWith('.dwg')) {
|
||||
showToast('Định dạng file không được hỗ trợ', 'error');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function addFilePreview(file) {
|
||||
const preview = document.getElementById('file-preview');
|
||||
const fileItem = document.createElement('div');
|
||||
fileItem.className = 'file-item';
|
||||
|
||||
const fileIcon = getFileIcon(file.type, file.name);
|
||||
const fileSize = formatFileSize(file.size);
|
||||
|
||||
fileItem.innerHTML = `
|
||||
<div class="file-icon">
|
||||
<i class="${fileIcon}"></i>
|
||||
</div>
|
||||
<div class="file-info">
|
||||
<div class="file-name">${file.name}</div>
|
||||
<div class="file-size">${fileSize}</div>
|
||||
</div>
|
||||
<button type="button" class="file-remove" onclick="removeFile(${selectedFiles.length - 1}, this)">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
`;
|
||||
|
||||
preview.appendChild(fileItem);
|
||||
}
|
||||
|
||||
function getFileIcon(type, name) {
|
||||
if (type.startsWith('image/')) return 'fas fa-image';
|
||||
if (type === 'application/pdf') return 'fas fa-file-pdf';
|
||||
if (name.toLowerCase().endsWith('.dwg')) return 'fas fa-drafting-compass';
|
||||
return 'fas fa-file';
|
||||
}
|
||||
|
||||
function formatFileSize(bytes) {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
const k = 1024;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
function removeFile(index, button) {
|
||||
selectedFiles.splice(index, 1);
|
||||
button.parentElement.remove();
|
||||
|
||||
// Update indices for remaining files
|
||||
updateFileIndices();
|
||||
}
|
||||
|
||||
function updateFileIndices() {
|
||||
const fileItems = document.querySelectorAll('.file-remove');
|
||||
fileItems.forEach((button, index) => {
|
||||
button.onclick = () => removeFile(index, button);
|
||||
});
|
||||
}
|
||||
|
||||
// Drag and drop handling
|
||||
const uploadArea = document.querySelector('.file-upload-area');
|
||||
|
||||
uploadArea.addEventListener('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
uploadArea.classList.add('drag-over');
|
||||
});
|
||||
|
||||
uploadArea.addEventListener('dragleave', () => {
|
||||
uploadArea.classList.remove('drag-over');
|
||||
});
|
||||
|
||||
uploadArea.addEventListener('drop', (e) => {
|
||||
e.preventDefault();
|
||||
uploadArea.classList.remove('drag-over');
|
||||
|
||||
const files = Array.from(e.dataTransfer.files);
|
||||
files.forEach(file => {
|
||||
if (validateFile(file)) {
|
||||
selectedFiles.push(file);
|
||||
addFilePreview(file);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Form validation and submission
|
||||
function validateForm() {
|
||||
let isValid = true;
|
||||
|
||||
// Clear previous errors
|
||||
document.querySelectorAll('.error-message').forEach(el => {
|
||||
el.style.display = 'none';
|
||||
});
|
||||
|
||||
// Validate required fields
|
||||
const requiredFields = [
|
||||
{ id: 'project-name', message: 'Vui lòng nhập tên dự án' },
|
||||
{ id: 'project-area', message: 'Vui lòng nhập diện tích hợp lệ' },
|
||||
{ id: 'project-style', message: 'Vui lòng chọn phong cách' },
|
||||
{ id: 'project-notes', message: 'Vui lòng mô tả yêu cầu chi tiết' }
|
||||
];
|
||||
|
||||
requiredFields.forEach(field => {
|
||||
const input = document.getElementById(field.id);
|
||||
const error = document.getElementById(field.id + '-error');
|
||||
|
||||
if (!input.value.trim()) {
|
||||
error.textContent = field.message;
|
||||
error.style.display = 'block';
|
||||
input.style.borderColor = '#ef4444';
|
||||
isValid = false;
|
||||
} else {
|
||||
input.style.borderColor = '#e5e7eb';
|
||||
}
|
||||
});
|
||||
|
||||
// Validate area is a positive number
|
||||
const area = document.getElementById('project-area');
|
||||
if (area.value && (isNaN(area.value) || parseFloat(area.value) <= 0)) {
|
||||
const error = document.getElementById('project-area-error');
|
||||
error.textContent = 'Diện tích phải là số dương';
|
||||
error.style.display = 'block';
|
||||
area.style.borderColor = '#ef4444';
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
function submitForm(event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (!validateForm()) {
|
||||
showToast('Vui lòng kiểm tra lại thông tin', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Simulate form submission
|
||||
const submitButton = event.target.querySelector('button[type="submit"]');
|
||||
const originalText = submitButton.innerHTML;
|
||||
|
||||
submitButton.disabled = true;
|
||||
submitButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Đang gửi...';
|
||||
|
||||
setTimeout(() => {
|
||||
// Generate random request ID
|
||||
const requestId = 'YC' + Math.random().toString().substr(2, 6).toUpperCase();
|
||||
|
||||
// Store request data (in real app, send to backend)
|
||||
const requestData = {
|
||||
id: requestId,
|
||||
name: document.getElementById('project-name').value,
|
||||
area: document.getElementById('project-area').value,
|
||||
style: document.getElementById('project-style').value,
|
||||
budget: document.getElementById('project-budget').value,
|
||||
notes: document.getElementById('project-notes').value,
|
||||
contact: document.getElementById('contact-info').value,
|
||||
files: selectedFiles.map(f => f.name),
|
||||
status: 'pending',
|
||||
createdAt: new Date().toISOString()
|
||||
};
|
||||
|
||||
localStorage.setItem('newDesignRequest', JSON.stringify(requestData));
|
||||
|
||||
showToast('Yêu cầu thiết kế đã được gửi thành công!');
|
||||
|
||||
// Redirect after delay
|
||||
setTimeout(() => {
|
||||
window.location.href = `design-request-detail.html?id=${requestId}`;
|
||||
}, 1500);
|
||||
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
function saveDraft() {
|
||||
const draftData = {
|
||||
name: document.getElementById('project-name').value,
|
||||
area: document.getElementById('project-area').value,
|
||||
style: document.getElementById('project-style').value,
|
||||
budget: document.getElementById('project-budget').value,
|
||||
notes: document.getElementById('project-notes').value,
|
||||
contact: document.getElementById('contact-info').value,
|
||||
files: selectedFiles.map(f => f.name)
|
||||
};
|
||||
|
||||
localStorage.setItem('designRequestDraft', JSON.stringify(draftData));
|
||||
showToast('Đã lưu nháp thành công!');
|
||||
}
|
||||
|
||||
function showToast(message, type = 'success') {
|
||||
const toast = document.getElementById('toast');
|
||||
const toastMessage = document.getElementById('toast-message');
|
||||
|
||||
toastMessage.textContent = message;
|
||||
|
||||
if (type === 'error') {
|
||||
toast.style.background = '#ef4444';
|
||||
} else {
|
||||
toast.style.background = '#10b981';
|
||||
}
|
||||
|
||||
toast.classList.add('show');
|
||||
|
||||
setTimeout(() => {
|
||||
toast.classList.remove('show');
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// Load draft on page load
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const draft = localStorage.getItem('designRequestDraft');
|
||||
if (draft) {
|
||||
try {
|
||||
const draftData = JSON.parse(draft);
|
||||
|
||||
if (confirm('Có bản nháp đã lưu. Bạn có muốn khôi phục không?')) {
|
||||
Object.keys(draftData).forEach(key => {
|
||||
if (key !== 'files') {
|
||||
const input = document.getElementById('project-' + key) || document.getElementById('contact-info');
|
||||
if (input && draftData[key]) {
|
||||
input.value = draftData[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Clear draft after loading
|
||||
localStorage.removeItem('designRequestDraft');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error loading draft:', e);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
738
html/design-request-detail.html
Normal file
738
html/design-request-detail.html
Normal file
@@ -0,0 +1,738 @@
|
||||
<!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 Yêu cầu Thiết kế - 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">
|
||||
<style>
|
||||
.detail-container {
|
||||
max-width: 480px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background: #f8fafc;
|
||||
min-height: calc(100vh - 120px);
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.request-header {
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.request-id {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.request-date {
|
||||
color: #6b7280;
|
||||
font-size: 14px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
padding: 8px 16px;
|
||||
border-radius: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.status-pending {
|
||||
background: #fef3c7;
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.status-designing {
|
||||
background: #e0e7ff;
|
||||
color: #3730a3;
|
||||
}
|
||||
|
||||
.status-completed {
|
||||
background: #d1fae5;
|
||||
color: #065f46;
|
||||
}
|
||||
|
||||
.info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 16px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
text-align: center;
|
||||
padding: 16px 12px;
|
||||
background: #f8fafc;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.detail-section {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.section-content {
|
||||
color: #4b5563;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.timeline {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.timeline-item {
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.timeline-item::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 40px;
|
||||
bottom: -20px;
|
||||
width: 2px;
|
||||
background: #e5e7eb;
|
||||
}
|
||||
|
||||
.timeline-item:last-child::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.timeline-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
margin-right: 16px;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.timeline-icon.pending {
|
||||
background: #fef3c7;
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.timeline-icon.designing {
|
||||
background: #e0e7ff;
|
||||
color: #3730a3;
|
||||
}
|
||||
|
||||
.timeline-icon.completed {
|
||||
background: #d1fae5;
|
||||
color: #065f46;
|
||||
}
|
||||
|
||||
.timeline-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.timeline-title {
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.timeline-description {
|
||||
color: #6b7280;
|
||||
font-size: 14px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.timeline-date {
|
||||
color: #9ca3af;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.completion-highlight {
|
||||
background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);
|
||||
border: 2px solid #10b981;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.completion-title {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #065f46;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.view-design-btn {
|
||||
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
margin: 0 auto;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.view-design-btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.4);
|
||||
}
|
||||
|
||||
.files-list {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12px;
|
||||
background: #f3f4f6;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.file-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: #2563eb;
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
margin-right: 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.file-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
flex: 1;
|
||||
padding: 12px 16px;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
border: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.4);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: white;
|
||||
color: #374151;
|
||||
border: 2px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
border-color: #2563eb;
|
||||
color: #2563eb;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.info-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
text-align: left;
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-wrapper">
|
||||
<!-- Header -->
|
||||
<div class="header">
|
||||
<a href="nha-mau.html" class="back-button">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Chi tiết Yêu cầu</h1>
|
||||
<button class="icon-button" onclick="shareRequest()">
|
||||
<i class="fas fa-share-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="detail-container">
|
||||
<!-- Request Header -->
|
||||
<div class="detail-card">
|
||||
<div class="request-header">
|
||||
<h2 class="request-id" id="request-id">#YC001</h2>
|
||||
<div class="request-date" id="request-date">Ngày gửi: 20/10/2024</div>
|
||||
<span class="status-badge" id="status-badge">Hoàn thành</span>
|
||||
</div>
|
||||
|
||||
<!-- Project Info Grid -->
|
||||
<div class="info-grid">
|
||||
<div class="info-item">
|
||||
<div class="info-label">Diện tích</div>
|
||||
<div class="info-value" id="project-area">120m²</div>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<div class="info-label">Phong cách</div>
|
||||
<div class="info-value" id="project-style">Hiện đại</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-grid">
|
||||
<div class="info-item">
|
||||
<div class="info-label">Ngân sách</div>
|
||||
<div class="info-value" id="project-budget">300-500 triệu</div>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<div class="info-label">Trạng thái</div>
|
||||
<div class="info-value" id="project-status">Đã hoàn thành</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Completion Highlight (only show if completed) -->
|
||||
<div class="completion-highlight" id="completion-highlight">
|
||||
<h3 class="completion-title">🎉 Thiết kế đã hoàn thành!</h3>
|
||||
<p style="color: #065f46; margin-bottom: 16px;">
|
||||
Thiết kế 3D của bạn đã sẵn sàng để xem
|
||||
</p>
|
||||
<button class="view-design-btn" onclick="viewDesign3D()">
|
||||
<i class="fas fa-cube"></i>
|
||||
Xem Link Thiết kế 3D
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Project Details -->
|
||||
<div class="detail-card">
|
||||
<div class="detail-section">
|
||||
<h3 class="section-title">
|
||||
<i class="fas fa-info-circle" style="color: #2563eb;"></i>
|
||||
Thông tin dự án
|
||||
</h3>
|
||||
<div class="section-content">
|
||||
<p><strong>Tên dự án:</strong> <span id="project-name">Thiết kế nhà phố 3 tầng - Anh Minh (Quận 7)</span></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<h3 class="section-title">
|
||||
<i class="fas fa-edit" style="color: #2563eb;"></i>
|
||||
Mô tả yêu cầu
|
||||
</h3>
|
||||
<div class="section-content" id="project-description">
|
||||
Thiết kế nhà phố 3 tầng phong cách hiện đại với 4 phòng ngủ, 3 phòng tắm, phòng khách rộng rãi và khu bếp mở.
|
||||
Ưu tiên sử dụng gạch men màu sáng để tạo cảm giác thoáng đãng. Tầng 1: garage, phòng khách, bếp.
|
||||
Tầng 2: 2 phòng ngủ, 2 phòng tắm. Tầng 3: phòng ngủ master, phòng làm việc, sân thượng.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<h3 class="section-title">
|
||||
<i class="fas fa-phone" style="color: #2563eb;"></i>
|
||||
Thông tin liên hệ
|
||||
</h3>
|
||||
<div class="section-content" id="contact-info">
|
||||
SĐT: 0901234567 | Email: minh.nguyen@email.com
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<h3 class="section-title">
|
||||
<i class="fas fa-paperclip" style="color: #2563eb;"></i>
|
||||
Tài liệu đính kèm
|
||||
</h3>
|
||||
<div class="files-list" id="files-list">
|
||||
<div class="file-item">
|
||||
<div class="file-icon">
|
||||
<i class="fas fa-image"></i>
|
||||
</div>
|
||||
<div class="file-info">
|
||||
<div class="file-name">mat-bang-hien-tai.jpg</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="file-item">
|
||||
<div class="file-icon">
|
||||
<i class="fas fa-drafting-compass"></i>
|
||||
</div>
|
||||
<div class="file-info">
|
||||
<div class="file-name">ban-ve-kien-truc.dwg</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Status Timeline -->
|
||||
<div class="detail-card">
|
||||
<h3 class="section-title">
|
||||
<i class="fas fa-history" style="color: #2563eb;"></i>
|
||||
Lịch sử trạng thái
|
||||
</h3>
|
||||
|
||||
<div class="timeline">
|
||||
<div class="timeline-item">
|
||||
<div class="timeline-icon completed">
|
||||
<i class="fas fa-check"></i>
|
||||
</div>
|
||||
<div class="timeline-content">
|
||||
<div class="timeline-title">Thiết kế hoàn thành</div>
|
||||
<div class="timeline-description">File thiết kế 3D đã được gửi đến khách hàng</div>
|
||||
<div class="timeline-date">25/10/2024 - 14:30</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="timeline-item">
|
||||
<div class="timeline-icon designing">
|
||||
<i class="fas fa-drafting-compass"></i>
|
||||
</div>
|
||||
<div class="timeline-content">
|
||||
<div class="timeline-title">Bắt đầu thiết kế</div>
|
||||
<div class="timeline-description">KTS Nguyễn Văn An đã nhận và bắt đầu thiết kế</div>
|
||||
<div class="timeline-date">22/10/2024 - 09:00</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="timeline-item">
|
||||
<div class="timeline-icon pending">
|
||||
<i class="fas fa-clock"></i>
|
||||
</div>
|
||||
<div class="timeline-content">
|
||||
<div class="timeline-title">Tiếp nhận yêu cầu</div>
|
||||
<div class="timeline-description">Yêu cầu thiết kế đã được tiếp nhận và xem xét</div>
|
||||
<div class="timeline-date">20/10/2024 - 16:45</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="timeline-item">
|
||||
<div class="timeline-icon pending">
|
||||
<i class="fas fa-paper-plane"></i>
|
||||
</div>
|
||||
<div class="timeline-content">
|
||||
<div class="timeline-title">Gửi yêu cầu</div>
|
||||
<div class="timeline-description">Yêu cầu thiết kế đã được gửi thành công</div>
|
||||
<div class="timeline-date">20/10/2024 - 16:30</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="action-buttons">
|
||||
<button class="btn btn-secondary" onclick="editRequest()">
|
||||
<i class="fas fa-edit"></i>
|
||||
Chỉnh sửa
|
||||
</button>
|
||||
<button class="btn btn-primary" onclick="contactSupport()">
|
||||
<i class="fas fa-comments"></i>
|
||||
Liên hệ
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom Navigation -->
|
||||
<!--<div class="bottom-nav">
|
||||
<a href="index.html" class="nav-item">
|
||||
<i class="fas fa-home"></i>
|
||||
<span>Trang chủ</span>
|
||||
</a>
|
||||
<a href="loyalty.html" class="nav-item">
|
||||
<i class="fas fa-star"></i>
|
||||
<span>Hội viên</span>
|
||||
</a>
|
||||
<a href="promotions.html" class="nav-item">
|
||||
<i class="fas fa-tags"></i>
|
||||
<span>Khuyến mãi</span>
|
||||
</a>
|
||||
<a href="notifications.html" class="nav-item">
|
||||
<i class="fas fa-bell"></i>
|
||||
<span>Thông báo</span>
|
||||
</a>
|
||||
<a href="account.html" class="nav-item active">
|
||||
<i class="fas fa-user"></i>
|
||||
<span>Cài đặt</span>
|
||||
</a>
|
||||
</div>-->
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Request data mapping
|
||||
const requestDatabase = {
|
||||
'YC001': {
|
||||
id: 'YC001',
|
||||
name: 'Thiết kế nhà phố 3 tầng - Anh Minh (Quận 7)',
|
||||
area: '120m²',
|
||||
style: 'Hiện đại',
|
||||
budget: '300-500 triệu',
|
||||
status: 'completed',
|
||||
statusText: 'Đã hoàn thành',
|
||||
description: 'Thiết kế nhà phố 3 tầng phong cách hiện đại với 4 phòng ngủ, 3 phòng tắm, phòng khách rộng rãi và khu bếp mở. Ưu tiên sử dụng gạch men màu sáng để tạo cảm giác thoáng đãng. Tầng 1: garage, phòng khách, bếp. Tầng 2: 2 phòng ngủ, 2 phòng tắm. Tầng 3: phòng ngủ master, phòng làm việc, sân thượng.',
|
||||
contact: 'SĐT: 0901234567 | Email: minh.nguyen@email.com',
|
||||
createdDate: '20/10/2024',
|
||||
files: ['mat-bang-hien-tai.jpg', 'ban-ve-kien-truc.dwg'],
|
||||
designLink: 'https://example.com/3d-design/YC001'
|
||||
},
|
||||
'YC002': {
|
||||
id: 'YC002',
|
||||
name: 'Cải tạo căn hộ chung cư - Chị Lan (Quận 2)',
|
||||
area: '85m²',
|
||||
style: 'Scandinavian',
|
||||
budget: '100-300 triệu',
|
||||
status: 'designing',
|
||||
statusText: 'Đang thiết kế',
|
||||
description: 'Cải tạo căn hộ chung cư 3PN theo phong cách Scandinavian. Tối ưu không gian lưu trữ, sử dụng gạch men màu sáng và gỗ tự nhiên.',
|
||||
contact: 'SĐT: 0987654321',
|
||||
createdDate: '25/10/2024',
|
||||
files: ['hinh-anh-hien-trang.jpg'],
|
||||
designLink: null
|
||||
},
|
||||
'YC003': {
|
||||
id: 'YC003',
|
||||
name: 'Thiết kế biệt thự 2 tầng - Anh Đức (Bình Dương)',
|
||||
area: '200m²',
|
||||
style: 'Luxury',
|
||||
budget: 'Trên 1 tỷ',
|
||||
status: 'pending',
|
||||
statusText: 'Chờ tiếp nhận',
|
||||
description: 'Thiết kế biệt thự 2 tầng phong cách luxury với hồ bơi và sân vườn. 5 phòng ngủ, 4 phòng tắm, phòng giải trí và garage 2 xe.',
|
||||
contact: 'SĐT: 0923456789 | Email: duc.le@gmail.com',
|
||||
createdDate: '28/10/2024',
|
||||
files: ['mat-bang-dat.pdf', 'y-tuong-thiet-ke.jpg'],
|
||||
designLink: null
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize page
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const requestId = urlParams.get('id') || 'YC001';
|
||||
|
||||
loadRequestDetail(requestId);
|
||||
});
|
||||
|
||||
function loadRequestDetail(requestId) {
|
||||
const request = requestDatabase[requestId];
|
||||
if (!request) {
|
||||
// Try to load from localStorage (for newly created requests)
|
||||
const newRequest = localStorage.getItem('newDesignRequest');
|
||||
if (newRequest) {
|
||||
const requestData = JSON.parse(newRequest);
|
||||
if (requestData.id === requestId) {
|
||||
loadRequestData(requestData);
|
||||
localStorage.removeItem('newDesignRequest');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to default
|
||||
loadRequestData(requestDatabase['YC001']);
|
||||
return;
|
||||
}
|
||||
|
||||
loadRequestData(request);
|
||||
}
|
||||
|
||||
function loadRequestData(request) {
|
||||
// Update basic info
|
||||
document.getElementById('request-id').textContent = '#' + request.id;
|
||||
document.getElementById('request-date').textContent = 'Ngày gửi: ' + request.createdDate;
|
||||
document.getElementById('project-name').textContent = request.name;
|
||||
document.getElementById('project-area').textContent = request.area;
|
||||
document.getElementById('project-style').textContent = request.style;
|
||||
document.getElementById('project-budget').textContent = request.budget;
|
||||
document.getElementById('project-status').textContent = request.statusText;
|
||||
document.getElementById('project-description').textContent = request.description;
|
||||
document.getElementById('contact-info').textContent = request.contact;
|
||||
|
||||
// Update status badge
|
||||
const statusBadge = document.getElementById('status-badge');
|
||||
statusBadge.textContent = request.statusText;
|
||||
statusBadge.className = `status-badge status-${request.status}`;
|
||||
|
||||
// Show completion highlight if completed
|
||||
const completionHighlight = document.getElementById('completion-highlight');
|
||||
if (request.status === 'completed') {
|
||||
completionHighlight.style.display = 'block';
|
||||
} else {
|
||||
completionHighlight.style.display = 'none';
|
||||
}
|
||||
|
||||
// Update files list
|
||||
updateFilesList(request.files);
|
||||
|
||||
// Update page title
|
||||
document.title = `${request.id} - Chi tiết Yêu cầu Thiết kế`;
|
||||
|
||||
// Store design link for later use
|
||||
window.currentDesignLink = request.designLink;
|
||||
}
|
||||
|
||||
function updateFilesList(files) {
|
||||
const filesList = document.getElementById('files-list');
|
||||
|
||||
if (!files || files.length === 0) {
|
||||
filesList.innerHTML = '<p style="color: #6b7280; font-style: italic;">Không có tài liệu đính kèm</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
filesList.innerHTML = files.map(fileName => {
|
||||
const fileIcon = getFileIcon(fileName);
|
||||
return `
|
||||
<div class="file-item">
|
||||
<div class="file-icon">
|
||||
<i class="${fileIcon}"></i>
|
||||
</div>
|
||||
<div class="file-info">
|
||||
<div class="file-name">${fileName}</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function getFileIcon(fileName) {
|
||||
const extension = fileName.toLowerCase().split('.').pop();
|
||||
|
||||
if (['jpg', 'jpeg', 'png', 'gif'].includes(extension)) return 'fas fa-image';
|
||||
if (extension === 'pdf') return 'fas fa-file-pdf';
|
||||
if (extension === 'dwg') return 'fas fa-drafting-compass';
|
||||
if (['doc', 'docx'].includes(extension)) return 'fas fa-file-word';
|
||||
return 'fas fa-file';
|
||||
}
|
||||
|
||||
function viewDesign3D() {
|
||||
if (window.currentDesignLink) {
|
||||
// In real app, open the 3D design viewer
|
||||
window.open(window.currentDesignLink, '_blank');
|
||||
} else {
|
||||
// For demo, show alert
|
||||
alert('Mở trình xem thiết kế 3D...\n\nTrong ứng dụng thực tế, đây sẽ mở link thiết kế 3D của bạn.');
|
||||
}
|
||||
}
|
||||
|
||||
function editRequest() {
|
||||
const requestId = document.getElementById('request-id').textContent.replace('#', '');
|
||||
// In real app, navigate to edit form with pre-filled data
|
||||
alert(`Chỉnh sửa yêu cầu ${requestId}\n\nChức năng này sẽ mở form chỉnh sửa với dữ liệu đã điền sẵn.`);
|
||||
}
|
||||
|
||||
function contactSupport() {
|
||||
// In real app, open chat or contact form
|
||||
if (confirm('Liên hệ hỗ trợ về yêu cầu thiết kế này?')) {
|
||||
// Navigate to chat or contact form
|
||||
window.location.href = 'chat-list.html';
|
||||
}
|
||||
}
|
||||
|
||||
function shareRequest() {
|
||||
const requestId = document.getElementById('request-id').textContent;
|
||||
const requestName = document.getElementById('project-name').textContent;
|
||||
|
||||
if (navigator.share) {
|
||||
navigator.share({
|
||||
title: `Yêu cầu thiết kế ${requestId}`,
|
||||
text: requestName,
|
||||
url: window.location.href
|
||||
}).catch(console.error);
|
||||
} else {
|
||||
// Fallback: copy URL to clipboard
|
||||
navigator.clipboard.writeText(window.location.href).then(() => {
|
||||
showToast('Đã sao chép link chia sẻ!');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function showToast(message) {
|
||||
const toast = document.createElement('div');
|
||||
toast.className = 'fixed top-20 left-1/2 transform -translate-x-1/2 bg-green-500 text-white px-4 py-2 rounded-lg z-50 transition-all duration-300';
|
||||
toast.textContent = message;
|
||||
document.body.appendChild(toast);
|
||||
|
||||
setTimeout(() => {
|
||||
toast.style.opacity = '0';
|
||||
setTimeout(() => {
|
||||
if (document.body.contains(toast)) {
|
||||
document.body.removeChild(toast);
|
||||
}
|
||||
}, 300);
|
||||
}, 2000);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
116
html/favorites.html
Normal file
116
html/favorites.html
Normal file
@@ -0,0 +1,116 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="vi">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Yêu thích - 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="index.html" class="back-button">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Yêu thích</h1>
|
||||
<a href="cart.html" class="back-button" style="position: relative;">
|
||||
<i class="fas fa-shopping-cart"></i>
|
||||
<span class="badge">3</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<!-- Search Bar -->
|
||||
<!--<div class="search-bar">
|
||||
<i class="fas fa-search search-icon"></i>
|
||||
<input type="text" class="search-input" placeholder="Tìm kiếm sản phẩm...">
|
||||
</div>-->
|
||||
|
||||
<!-- Filter Pills -->
|
||||
<div class="filter-container">
|
||||
<button class="filter-pill active">Tất cả</button>
|
||||
<button class="filter-pill">Gạch lát nền</button>
|
||||
<button class="filter-pill">Gạch ốp tường</button>
|
||||
<button class="filter-pill">Gạch trang trí</button>
|
||||
<button class="filter-pill">Gạch ngoài trời</button>
|
||||
<button class="filter-pill">Phụ kiện</button>
|
||||
</div>
|
||||
|
||||
<!-- Product Grid -->
|
||||
<div class="product-grid">
|
||||
<!-- Product 1 -->
|
||||
<div class="product-card">
|
||||
<img src="https://www.eurotile.vn/pictures/catalog/product/0-gachkholon/cat-tuong/CAT-S01G-1.jpg" alt="Gạch men" class="product-image" onclick="window.location.href='product-detail.html'">
|
||||
<div class="product-info">
|
||||
<div class="product-name" onclick="window.location.href='product-detail.html'">Gạch Cát Tường 1200x1200</div>
|
||||
<div class="product-price">450.000đ/m²</div>
|
||||
<div class="product-actions">
|
||||
<button class="btn btn-primary btn-sm btn-add-cart">
|
||||
<i class="fas fa-cart-plus"></i> Thêm vào giỏ
|
||||
</button>
|
||||
<button class="btn btn-secondary btn-sm btn-360" onclick="window.location.href='https://design.eurotile.vn/pub/tool/panorama/show?obsPlanId=3FO3H1VE59R5&locale=en_US&_gl=1*1udzqeo*_gcl_au*MTI3NjIxMzY1NS4xNzU5NzE2Mjg5'">
|
||||
<i class="fas fa-cube"></i> Phối cảnh 360°
|
||||
</button>
|
||||
</div>
|
||||
<!--<button class="btn btn-primary btn-sm btn-block">
|
||||
<i class="fas fa-cart-plus"></i> Thêm vào giỏ
|
||||
</button>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Product 5 -->
|
||||
<div class="product-card">
|
||||
<img src="https://images.unsplash.com/photo-1615874694520-474822394e73?w=300&h=300&fit=crop" alt="Gạch ceramic" class="product-image">
|
||||
<div class="product-info">
|
||||
<div class="product-name">Gạch ceramic chống trượt</div>
|
||||
<div class="product-price">380.000đ/m²</div>
|
||||
<button class="btn btn-primary btn-sm btn-block">
|
||||
<i class="fas fa-cart-plus"></i> Thêm vào giỏ
|
||||
</button>
|
||||
<button class="btn btn-secondary btn-sm btn-360" onclick="window.location.href='https://design.eurotile.vn/pub/tool/panorama/show?obsPlanId=3FO3H1VE59R5&locale=en_US&_gl=1*1udzqeo*_gcl_au*MTI3NjIxMzY1NS4xNzU5NzE2Mjg5'">
|
||||
<i class="fas fa-cube"></i> Phối cảnh 360°
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Product 3 -->
|
||||
<div class="product-card">
|
||||
<img src="https://images.unsplash.com/photo-1615971677499-5467cbab01c0?w=300&h=300&fit=crop" alt="Gạch mosaic" class="product-image">
|
||||
<div class="product-info">
|
||||
<div class="product-name">Gạch mosaic trang trí</div>
|
||||
<div class="product-price">320.000đ/m²</div>
|
||||
<button class="btn btn-primary btn-sm btn-block">
|
||||
<i class="fas fa-cart-plus"></i> Thêm vào giỏ
|
||||
</button>
|
||||
<button class="btn btn-secondary btn-sm btn-360" onclick="window.location.href='https://design.eurotile.vn/pub/tool/panorama/show?obsPlanId=3FO3H1VE59R5&locale=en_US&_gl=1*1udzqeo*_gcl_au*MTI3NjIxMzY1NS4xNzU5NzE2Mjg5'">
|
||||
<i class="fas fa-cube"></i> Phối cảnh 360°
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Product 4 -->
|
||||
<div class="product-card">
|
||||
<img src="https://images.unsplash.com/photo-1600566753190-17f0baa2a6c3?w=300&h=300&fit=crop" alt="Gạch 3D" class="product-image">
|
||||
<div class="product-info">
|
||||
<div class="product-name">Gạch 3D họa tiết</div>
|
||||
<div class="product-price">750.000đ/m²</div>
|
||||
<button class="btn btn-primary btn-sm btn-block">
|
||||
<i class="fas fa-cart-plus"></i> Thêm vào giỏ
|
||||
</button>
|
||||
<button class="btn btn-secondary btn-sm btn-360" onclick="window.location.href='https://design.eurotile.vn/pub/tool/panorama/show?obsPlanId=3FO3H1VE59R5&locale=en_US&_gl=1*1udzqeo*_gcl_au*MTI3NjIxMzY1NS4xNzU5NzE2Mjg5'">
|
||||
<i class="fas fa-cube"></i> Phối cảnh 360°
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,741 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="vi">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Trang chủ - 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">
|
||||
<style>
|
||||
/* Policy Modal Styles */
|
||||
.policy-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 1rem;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.policy-modal.show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.policy-modal-content {
|
||||
background: white;
|
||||
border-radius: 1.5rem;
|
||||
max-width: 480px;
|
||||
width: 100%;
|
||||
max-height: 90vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
transform: scale(0.9) translateY(50px);
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.policy-modal.show .policy-modal-content {
|
||||
transform: scale(1) translateY(0);
|
||||
}
|
||||
|
||||
.policy-header {
|
||||
background: linear-gradient(135deg, #2563eb, #1d4ed8);
|
||||
color: white;
|
||||
padding: 2rem 1.5rem 1.5rem;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.policy-header::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 20px;
|
||||
background: white;
|
||||
border-radius: 20px 20px 0 0;
|
||||
}
|
||||
|
||||
.policy-icon {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 1rem;
|
||||
animation: bounce 2s infinite;
|
||||
}
|
||||
|
||||
.policy-icon i {
|
||||
font-size: 2rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
0%, 20%, 50%, 80%, 100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
40% {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
60% {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
}
|
||||
|
||||
.policy-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.policy-subtitle {
|
||||
font-size: 1rem;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.policy-body {
|
||||
flex: 1;
|
||||
padding: 1.5rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.welcome-text {
|
||||
font-size: 1rem;
|
||||
color: #1e293b;
|
||||
text-align: center;
|
||||
margin-bottom: 1.5rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.benefits-section {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.benefits-title {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.benefits-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.benefit-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 1rem;
|
||||
padding: 0.75rem;
|
||||
margin-bottom: 0.5rem;
|
||||
background: #f8fafc;
|
||||
border-radius: 0.75rem;
|
||||
border-left: 4px solid #2563eb;
|
||||
}
|
||||
|
||||
.benefit-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: linear-gradient(135deg, #2563eb, #1d4ed8);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
flex-shrink: 0;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.benefit-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.benefit-title {
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.benefit-desc {
|
||||
font-size: 0.875rem;
|
||||
color: #64748b;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.policy-footer {
|
||||
padding: 1.5rem;
|
||||
border-top: 1px solid #e2e8f0;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.policy-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.policy-accept-btn {
|
||||
background: linear-gradient(135deg, #2563eb, #1d4ed8);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 1rem;
|
||||
border-radius: 0.75rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.policy-accept-btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 15px rgba(37, 99, 235, 0.3);
|
||||
}
|
||||
|
||||
.policy-note {
|
||||
font-size: 0.75rem;
|
||||
color: #64748b;
|
||||
text-align: center;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.policy-modal {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.policy-header {
|
||||
padding: 1.5rem 1rem 1rem;
|
||||
}
|
||||
|
||||
.policy-title {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.policy-body {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.policy-footer {
|
||||
padding: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* News Section Styles */
|
||||
.news-slider-container {
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.news-slider-wrapper {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.news-card {
|
||||
flex-shrink: 0;
|
||||
width: 280px;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
border: 1px solid #e2e8f0;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.news-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.news-image {
|
||||
width: 100%;
|
||||
height: 140px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.news-content {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.news-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
line-height: 1.3;
|
||||
margin-bottom: 6px;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.news-desc {
|
||||
font-size: 12px;
|
||||
color: #64748b;
|
||||
line-height: 1.4;
|
||||
margin-bottom: 8px;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.news-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 11px;
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.news-meta span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-wrapper">
|
||||
<div class="container">
|
||||
<!-- Member Card Diamond -->
|
||||
<div class="member-card member-card-diamond">
|
||||
<div class="d-flex justify-between align-center">
|
||||
<div>
|
||||
<h3 style="color: white; font-size: 24px; margin-bottom: 4px;">EUROTILE</h3>
|
||||
<p style="color: rgba(255,255,255,0.9); font-size: 11px;">ARCHITECT MEMBERSHIP</p>
|
||||
</div>
|
||||
<div style="text-align: right;">
|
||||
<p style="color: rgba(255,255,255,0.8); font-size: 11px;">Valid through</p>
|
||||
<p style="color: white; font-size: 14px; font-weight: 500;">31/12/2021</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-between align-center" style="margin-top: auto;">
|
||||
<div>
|
||||
<p style="color: white; font-size: 18px; font-weight: 600; margin-bottom: 4px;">La Nguyen Quynh</p>
|
||||
<p style="color: rgba(255,255,255,0.9); font-size: 12px;">CLASS: <span style="font-weight: 600;">DIAMOND</span></p>
|
||||
<p style="color: rgba(255,255,255,0.9); font-size: 12px;">Points: <span style="font-weight: 600;">9750</span></p>
|
||||
</div>
|
||||
<div style="background: white; padding: 8px; border-radius: 8px;">
|
||||
<img src="https://api.qrserver.com/v1/create-qr-code/?size=60x60&data=0983441099" alt="QR Code" style="width: 60px; height: 60px;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Promotions Section -->
|
||||
<div class="mb-3">
|
||||
<h2>Chương trình ưu đãi</h2>
|
||||
<div class="slider-container">
|
||||
<div class="slider-wrapper">
|
||||
<div class="slider-item">
|
||||
<img src="https://images.unsplash.com/photo-1615971677499-5467cbab01c0?w=280&h=140&fit=crop" alt="Khuyến mãi 1">
|
||||
<div style="padding: 12px; background: white;">
|
||||
<h3 style="font-size: 14px;">Mua công nhắc - Khuyến mãi cảng lớn</h3>
|
||||
<p class="text-small text-muted">Giảm đến 30% cho đơn hàng từ 10 triệu</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="slider-item">
|
||||
<img src="https://images.unsplash.com/photo-1600607687644-aac4c3eac7f4?w=280&h=140&fit=crop" alt="Khuyến mãi 2">
|
||||
<div style="padding: 12px; background: white;">
|
||||
<h3 style="font-size: 14px;">Keo chà ron tặng kèm</h3>
|
||||
<p class="text-small text-muted">Mua gạch Eurotile tặng keo chà ron cao cấp</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="slider-item">
|
||||
<img src="https://images.unsplash.com/photo-1565538420870-da08ff96a207?w=280&h=140&fit=crop" alt="Khuyến mãi 3">
|
||||
<div style="padding: 12px; background: white;">
|
||||
<h3 style="font-size: 14px;">Ưu đãi đặc biệt thành viên VIP</h3>
|
||||
<p class="text-small text-muted">Chiết khấu thêm 5% cho thành viên Diamond</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- News Section -->
|
||||
<div class="mb-3">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
|
||||
<h2>Tin tức & Chuyên môn</h2>
|
||||
<a href="news-list.html" style="color: #2563eb; font-size: 14px; text-decoration: none; font-weight: 500;">
|
||||
Xem tất cả <i class="fas fa-arrow-right" style="margin-left: 4px;"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="news-slider-container">
|
||||
<div class="news-slider-wrapper">
|
||||
<div class="news-card">
|
||||
<img src="https://images.unsplash.com/photo-1503387762-592deb58ef4e?w=280&h=140&fit=crop" alt="Tin tức 1" class="news-image">
|
||||
<div class="news-content">
|
||||
<h3 class="news-title">5 xu hướng gạch men phòng tắm được ưa chuộng năm 2024</h3>
|
||||
<p class="news-desc">Khám phá những mẫu gạch men hiện đại, sang trọng cho không gian phòng tắm.</p>
|
||||
<div class="news-meta">
|
||||
<span><i class="fas fa-calendar"></i> 15/11/2024</span>
|
||||
<span><i class="fas fa-eye"></i> 2.3K lượt xem</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="news-card">
|
||||
<img src="https://images.unsplash.com/photo-1586023492125-27b2c045efd7?w=280&h=140&fit=crop" alt="Tin tức 2" class="news-image">
|
||||
<div class="news-content">
|
||||
<h3 class="news-title">Hướng dẫn thi công gạch granite 60x60 chuyên nghiệp</h3>
|
||||
<p class="news-desc">Quy trình thi công chi tiết từ A-Z cho thầy thợ xây dựng.</p>
|
||||
<div class="news-meta">
|
||||
<span><i class="fas fa-calendar"></i> 12/11/2024</span>
|
||||
<span><i class="fas fa-eye"></i> 1.8K lượt xem</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="news-card">
|
||||
<img src="https://images.unsplash.com/photo-1560448204-e02f11c3d0e2?w=280&h=140&fit=crop" alt="Tin tức 3" class="news-image">
|
||||
<div class="news-content">
|
||||
<h3 class="news-title">Bảng giá gạch men cao cấp mới nhất tháng 11/2024</h3>
|
||||
<p class="news-desc">Cập nhật bảng giá chi tiết các dòng sản phẩm gạch men nhập khẩu.</p>
|
||||
<div class="news-meta">
|
||||
<span><i class="fas fa-calendar"></i> 10/11/2024</span>
|
||||
<span><i class="fas fa-eye"></i> 3.1K lượt xem</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Products & Cart Section -->
|
||||
<div class="card">
|
||||
<h3 class="card-title">Sản phẩm & Giỏ hàng</h3>
|
||||
<div class="feature-grid">
|
||||
<a href="products.html" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-th-large"></i>
|
||||
</div>
|
||||
<div class="feature-title">Sản phẩm</div>
|
||||
</a>
|
||||
<a href="cart.html" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-shopping-cart"></i>
|
||||
</div>
|
||||
<div class="feature-title">Giỏ hàng</div>
|
||||
<span class="badge">3</span>
|
||||
</a>
|
||||
<a href="#" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-heart"></i>
|
||||
</div>
|
||||
<div class="feature-title">Yêu thích</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Loyalty Section -->
|
||||
<div class="card">
|
||||
<h3 class="card-title">Khách hàng thân thiết</h3>
|
||||
<div class="feature-grid">
|
||||
<a href="loyalty-rewards.html" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-gift"></i>
|
||||
</div>
|
||||
<div class="feature-title">Đổi quà</div>
|
||||
</a>
|
||||
<a href="points-history.html" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-history"></i>
|
||||
</div>
|
||||
<div class="feature-title">Lịch sử điểm</div>
|
||||
</a>
|
||||
<a href="#" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-user-plus"></i>
|
||||
</div>
|
||||
<div class="feature-title">Giới thiệu bạn</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Orders & Payment Section -->
|
||||
<div class="card">
|
||||
<h3 class="card-title">Yêu cầu báo giá & báo giá</h3>
|
||||
<div class="grid grid-2">
|
||||
<a href="#" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-file-alt"></i>
|
||||
</div>
|
||||
<div class="feature-title">Yêu cầu báo giá</div>
|
||||
</a>
|
||||
<a href="#" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-file-invoice"></i>
|
||||
</div>
|
||||
<div class="feature-title">Báo giá</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Orders & Payment Section -->
|
||||
<div class="card">
|
||||
<h3 class="card-title">Đơn hàng & thanh toán</h3>
|
||||
<div class="grid grid-2">
|
||||
<a href="#" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-box"></i>
|
||||
</div>
|
||||
<div class="feature-title">Đơn hàng</div>
|
||||
</a>
|
||||
<a href="#" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-credit-card"></i>
|
||||
</div>
|
||||
<div class="feature-title">Thanh toán</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Collaboration & Reports Section -->
|
||||
<div class="card">
|
||||
<h3 class="card-title">Công trình, hợp đồng & báo cáo</h3>
|
||||
<div class="feature-grid">
|
||||
<a href="#" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-building"></i>
|
||||
</div>
|
||||
<div class="feature-title">Công trình</div>
|
||||
</a>
|
||||
<a href="#" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-handshake"></i>
|
||||
</div>
|
||||
<div class="feature-title">Hợp đồng</div>
|
||||
</a>
|
||||
<a href="#" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-chart-line"></i>
|
||||
</div>
|
||||
<div class="feature-title">Tổng quan</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Floating Action Button -->
|
||||
<button class="fab">
|
||||
<i class="fas fa-comments"></i>
|
||||
</button>
|
||||
|
||||
<!-- Bottom Navigation -->
|
||||
<div class="bottom-nav">
|
||||
<a href="index.html" class="nav-item active">
|
||||
<i class="fas fa-home nav-icon"></i>
|
||||
<span class="nav-label">Trang chủ</span>
|
||||
</a>
|
||||
<a href="loyalty.html" class="nav-item">
|
||||
<i class="fas fa-crown nav-icon"></i>
|
||||
<span class="nav-label">Hội viên</span>
|
||||
</a>
|
||||
<a href="promotions.html" class="nav-item">
|
||||
<i class="fas fa-tags nav-icon"></i>
|
||||
<span class="nav-label">Khuyến mãi</span>
|
||||
</a>
|
||||
<a href="notifications.html" class="nav-item">
|
||||
<i class="fas fa-bell nav-icon"></i>
|
||||
<span class="nav-label">Thông báo</span>
|
||||
<span class="badge">5</span>
|
||||
</a>
|
||||
<a href="account.html" class="nav-item">
|
||||
<i class="fas fa-user nav-icon"></i>
|
||||
<span class="nav-label">Cài đặt</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Policy Modal -->
|
||||
<div id="policyModal" class="policy-modal">
|
||||
<div class="policy-modal-content">
|
||||
<!-- Header -->
|
||||
<div class="policy-header">
|
||||
<div class="policy-icon">
|
||||
<i class="fas fa-hands-helping"></i>
|
||||
</div>
|
||||
<h2 class="policy-title">Chào mừng bạn đến với Worker App!</h2>
|
||||
<p class="policy-subtitle">Nền tảng hỗ trợ chuyên nghiệp dành cho thầu thợ & kiến trúc sư</p>
|
||||
</div>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="policy-body">
|
||||
<p class="welcome-text">
|
||||
Cảm ơn bạn đã tham gia cộng đồng Worker App! Chúng tôi cam kết mang đến những quyền lợi tốt nhất
|
||||
và hỗ trợ bạn thành công trong mọi dự án.
|
||||
</p>
|
||||
|
||||
<!-- Benefits Section -->
|
||||
<div class="benefits-section">
|
||||
<h3 class="benefits-title">
|
||||
<i class="fas fa-star"></i>
|
||||
Quyền lợi đặc biệt của bạn
|
||||
</h3>
|
||||
|
||||
<ul class="benefits-list">
|
||||
<li class="benefit-item">
|
||||
<div class="benefit-icon">
|
||||
<i class="fas fa-percentage"></i>
|
||||
</div>
|
||||
<div class="benefit-content">
|
||||
<div class="benefit-title">Chiết khấu độc quyền</div>
|
||||
<div class="benefit-desc">Giảm giá đến 20% cho tất cả sản phẩm, tăng theo hạng thành viên</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="benefit-item">
|
||||
<div class="benefit-icon">
|
||||
<i class="fas fa-coins"></i>
|
||||
</div>
|
||||
<div class="benefit-content">
|
||||
<div class="benefit-title">Tích điểm thưởng</div>
|
||||
<div class="benefit-desc">Nhận 1 điểm cho mỗi 100k chi tiêu, đổi điểm lấy quà hấp dẫn</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="benefit-item">
|
||||
<div class="benefit-icon">
|
||||
<i class="fas fa-shipping-fast"></i>
|
||||
</div>
|
||||
<div class="benefit-content">
|
||||
<div class="benefit-title">Giao hàng ưu tiên</div>
|
||||
<div class="benefit-desc">Miễn phí vận chuyển cho đơn từ 5 triệu, giao hàng nhanh trong 24h</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="benefit-item">
|
||||
<div class="benefit-icon">
|
||||
<i class="fas fa-user-tie"></i>
|
||||
</div>
|
||||
<div class="benefit-content">
|
||||
<div class="benefit-title">Tư vấn chuyên nghiệp</div>
|
||||
<div class="benefit-desc">Hỗ trợ thiết kế 3D miễn phí, tư vấn kỹ thuật 24/7</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="benefit-item">
|
||||
<div class="benefit-icon">
|
||||
<i class="fas fa-calendar-star"></i>
|
||||
</div>
|
||||
<div class="benefit-content">
|
||||
<div class="benefit-title">Sự kiện độc quyền</div>
|
||||
<div class="benefit-desc">Tham gia hội thảo, workshop và các sự kiện ngành chỉ dành cho thành viên</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="benefit-item">
|
||||
<div class="benefit-icon">
|
||||
<i class="fas fa-gift"></i>
|
||||
</div>
|
||||
<div class="benefit-content">
|
||||
<div class="benefit-title">Quà tặng sinh nhật</div>
|
||||
<div class="benefit-desc">Voucher và điểm thưởng đặc biệt vào dịp sinh nhật</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Important Note -->
|
||||
<div style="background: #fef3c7; border: 1px solid #f59e0b; border-radius: 0.75rem; padding: 1rem; margin-top: 1rem;">
|
||||
<div style="display: flex; align-items: flex-start; gap: 0.75rem;">
|
||||
<i class="fas fa-exclamation-triangle" style="color: #f59e0b; margin-top: 0.25rem;"></i>
|
||||
<div>
|
||||
<div style="font-weight: 600; color: #92400e; margin-bottom: 0.5rem;">Điều khoản sử dụng</div>
|
||||
<div style="font-size: 0.875rem; color: #92400e; line-height: 1.4;">
|
||||
Bằng cách sử dụng ứng dụng, bạn đồng ý với các điều khoản dịch vụ và chính sách bảo mật của chúng tôi.
|
||||
Các quyền lợi có thể thay đổi theo thời gian.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="policy-footer">
|
||||
<div class="policy-actions">
|
||||
<button class="policy-accept-btn" onclick="closePolicyModal()">
|
||||
<i class="fas fa-check"></i>
|
||||
Tôi đã đọc và đồng ý
|
||||
</button>
|
||||
<p class="policy-note">
|
||||
Bằng cách nhấn "Đồng ý", bạn xác nhận đã đọc và hiểu các điều khoản trên.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Show policy modal on page load (for demo purposes)
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Check if user has seen the policy before
|
||||
const hasSeenPolicy = localStorage.getItem('hasSeenPolicy');
|
||||
|
||||
if (!hasSeenPolicy) {
|
||||
setTimeout(() => {
|
||||
showPolicyModal();
|
||||
}, 1000); // Show after 1 second for better UX
|
||||
}
|
||||
});
|
||||
|
||||
function showPolicyModal() {
|
||||
const modal = document.getElementById('policyModal');
|
||||
modal.classList.add('show');
|
||||
document.body.style.overflow = 'hidden'; // Prevent background scrolling
|
||||
}
|
||||
|
||||
function closePolicyModal() {
|
||||
const modal = document.getElementById('policyModal');
|
||||
modal.classList.remove('show');
|
||||
document.body.style.overflow = ''; // Restore scrolling
|
||||
|
||||
// Remember that user has seen the policy
|
||||
localStorage.setItem('hasSeenPolicy', 'true');
|
||||
}
|
||||
|
||||
// Close modal when clicking outside
|
||||
document.getElementById('policyModal').addEventListener('click', function(e) {
|
||||
if (e.target === this) {
|
||||
closePolicyModal();
|
||||
}
|
||||
});
|
||||
|
||||
// Temporary function to show modal for testing (remove in production)
|
||||
function testShowModal() {
|
||||
localStorage.removeItem('hasSeenPolicy');
|
||||
showPolicyModal();
|
||||
}
|
||||
|
||||
// Add a way to show modal again for testing
|
||||
// Double-click on the member card to show modal again
|
||||
document.querySelector('.member-card').addEventListener('dblclick', function() {
|
||||
showPolicyModal();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -95,6 +95,12 @@
|
||||
<div class="card">
|
||||
<h3 class="card-title">Khách hàng thân thiết</h3>
|
||||
<div class="feature-grid">
|
||||
<a href="points-record.html" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-plus-circle"></i>
|
||||
</div>
|
||||
<div class="feature-title">Ghi nhận điểm</div>
|
||||
</a>
|
||||
<a href="loyalty-rewards.html" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-gift"></i>
|
||||
@@ -107,17 +113,17 @@
|
||||
</div>
|
||||
<div class="feature-title">Lịch sử điểm</div>
|
||||
</a>
|
||||
<a href="referral.html" class="feature-item">
|
||||
<!--<a href="referral.html" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-user-plus"></i>
|
||||
</div>
|
||||
<div class="feature-title">Giới thiệu bạn</div>
|
||||
</a>
|
||||
</a>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Orders & Payment Section -->
|
||||
<div class="card">
|
||||
<!--<div class="card">
|
||||
<h3 class="card-title">Yêu cầu báo giá & báo giá</h3>
|
||||
<div class="grid grid-2">
|
||||
<a href="quotes-list.html" class="feature-item">
|
||||
@@ -133,12 +139,18 @@
|
||||
<div class="feature-title">Báo giá</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>-->
|
||||
|
||||
<!-- Orders & Payment Section -->
|
||||
<div class="card">
|
||||
<h3 class="card-title">Đơn hàng & thanh toán</h3>
|
||||
<div class="grid grid-2">
|
||||
<div class="feature-grid">
|
||||
<a href="quotes-list.html" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-file-alt"></i>
|
||||
</div>
|
||||
<div class="feature-title">Yêu cầu báo giá</div>
|
||||
</a>
|
||||
<a href="orders.html" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-box"></i>
|
||||
@@ -147,7 +159,7 @@
|
||||
</a>
|
||||
<a href="payments.html" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-credit-card"></i>
|
||||
<i class="fas fa-file-invoice-dollar"></i>
|
||||
</div>
|
||||
<div class="feature-title">Thanh toán</div>
|
||||
</a>
|
||||
@@ -182,7 +194,7 @@
|
||||
<div class="card">
|
||||
<h3 class="card-title">Nhà mẫu, dự án & tin tức</h3>
|
||||
<div class="feature-grid">
|
||||
<a href="nha-mau-list.html" class="feature-item">
|
||||
<a href="nha-mau.html" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<!--<i class="fas fa-building"></i>-->
|
||||
<i class="fa-solid fa-house-chimney"></i>
|
||||
@@ -198,7 +210,7 @@
|
||||
</a>
|
||||
<a href="news-list.html" class="feature-item">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-chart-line"></i>
|
||||
<i class="fa-solid fa-newspaper"></i>
|
||||
</div>
|
||||
<div class="feature-title">Tin tức</div>
|
||||
</a>
|
||||
|
||||
757
html/my-gift-detail.html
Normal file
757
html/my-gift-detail.html
Normal file
@@ -0,0 +1,757 @@
|
||||
<!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 Quà tặng - 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">
|
||||
<style>
|
||||
.gift-detail-container {
|
||||
min-height: calc(100vh - 120px);
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.gift-card {
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
padding: 30px 20px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.gift-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
|
||||
}
|
||||
|
||||
.gift-icon {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 20px;
|
||||
color: white;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.gift-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
color: #2d3748;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.gift-description {
|
||||
color: #718096;
|
||||
margin-bottom: 20px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.voucher-code-section {
|
||||
background: #f7fafc;
|
||||
border: 2px dashed #e2e8f0;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.voucher-code {
|
||||
font-size: 2rem;
|
||||
font-weight: 800;
|
||||
color: #2d3748;
|
||||
font-family: 'Courier New', monospace;
|
||||
letter-spacing: 2px;
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
padding: 10px 20px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.copy-button:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.qr-code-section {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.qr-code-container {
|
||||
background: #f8f9fa;
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin: 15px 0;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.qr-code-placeholder {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background: #ffffff;
|
||||
border: 2px dashed #dee2e6;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
color: #6c757d;
|
||||
font-size: 0.9rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.qr-code-placeholder i {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 10px;
|
||||
color: #adb5bd;
|
||||
}
|
||||
|
||||
.gift-info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 15px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
background: #f8f9fa;
|
||||
padding: 15px;
|
||||
border-radius: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 0.8rem;
|
||||
color: #6c757d;
|
||||
margin-bottom: 5px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-weight: 700;
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
display: inline-block;
|
||||
padding: 6px 12px;
|
||||
border-radius: 20px;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.status-valid {
|
||||
background: #d4edda;
|
||||
color: #155724;
|
||||
}
|
||||
|
||||
.status-used {
|
||||
background: #d1ecf1;
|
||||
color: #0c5460;
|
||||
}
|
||||
|
||||
.status-expired {
|
||||
background: #f8d7da;
|
||||
color: #721c24;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.btn-use {
|
||||
flex: 1;
|
||||
background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
padding: 15px;
|
||||
font-weight: 600;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-use:hover:not(:disabled) {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 5px 15px rgba(40, 167, 69, 0.4);
|
||||
}
|
||||
|
||||
.btn-use:disabled {
|
||||
background: #6c757d;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-share {
|
||||
background: #ffffff;
|
||||
color: #667eea;
|
||||
border: 2px solid #667eea;
|
||||
border-radius: 12px;
|
||||
padding: 15px 20px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-share:hover {
|
||||
background: #667eea;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.terms-section {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
margin-top: 20px;
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.terms-title {
|
||||
font-weight: 700;
|
||||
color: #2d3748;
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.terms-list {
|
||||
color: #4a5568;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.terms-list li {
|
||||
margin-bottom: 8px;
|
||||
padding-left: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.terms-list li::before {
|
||||
content: '•';
|
||||
color: #667eea;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.usage-history {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
margin-top: 20px;
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.history-title {
|
||||
font-weight: 700;
|
||||
color: #2d3748;
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.history-empty {
|
||||
text-align: center;
|
||||
color: #9ca3af;
|
||||
padding: 20px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.toast {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: #28a745;
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||
z-index: 1000;
|
||||
display: none;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.toast.show {
|
||||
display: flex;
|
||||
animation: slideDown 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes slideDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-50%) translateY(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(-50%) translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.gift-detail-container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.gift-card {
|
||||
padding: 20px 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.voucher-code {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.qr-code-placeholder {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.gift-info-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-wrapper">
|
||||
<!-- Header -->
|
||||
<div class="header">
|
||||
<a href="my-gifts.html" class="back-button">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Chi tiết Quà tặng</h1>
|
||||
<button class="icon-button" onclick="shareGift()">
|
||||
<i class="fas fa-share-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="gift-detail-container">
|
||||
<!-- Gift Card -->
|
||||
<div class="gift-card">
|
||||
<div class="gift-icon">
|
||||
<i class="fas fa-gift" id="giftIcon"></i>
|
||||
</div>
|
||||
|
||||
<div class="status-badge" id="statusBadge">
|
||||
Còn hạn sử dụng
|
||||
</div>
|
||||
|
||||
<h2 class="gift-title" id="giftTitle">
|
||||
Voucher giảm 100.000đ
|
||||
</h2>
|
||||
|
||||
<p class="gift-description" id="giftDescription">
|
||||
Áp dụng cho đơn hàng từ 2.000.000đ
|
||||
</p>
|
||||
|
||||
<!-- Voucher Code Section -->
|
||||
<div class="voucher-code-section">
|
||||
<div class="voucher-code" id="voucherCode">
|
||||
SAVE100K
|
||||
</div>
|
||||
<button class="copy-button" onclick="copyVoucherCode()">
|
||||
<i class="fas fa-copy"></i>
|
||||
Sao chép mã
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Gift Info Grid -->
|
||||
<div class="gift-info-grid">
|
||||
<div class="info-item">
|
||||
<div class="info-label">Hạn sử dụng</div>
|
||||
<div class="info-value" id="expiryDate">31/12/2023</div>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<div class="info-label">Giá trị</div>
|
||||
<div class="info-value" id="giftValue">100.000đ</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="action-buttons">
|
||||
<button class="btn-use" id="useButton" onclick="useGift()">
|
||||
<i class="fas fa-check"></i>
|
||||
Sử dụng ngay
|
||||
</button>
|
||||
<button class="btn-share" onclick="shareGift()">
|
||||
<i class="fas fa-share-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- QR Code Section -->
|
||||
<div class="qr-code-section">
|
||||
<h3 style="font-weight: 700; color: #2d3748; margin-bottom: 15px; text-align: center;">
|
||||
<i class="fas fa-qrcode"></i>
|
||||
Mã QR Code
|
||||
</h3>
|
||||
<p style="color: #6c757d; font-size: 0.9rem; margin-bottom: 15px;">
|
||||
Đưa mã QR này cho nhân viên để quét tại cửa hàng
|
||||
</p>
|
||||
|
||||
<div class="qr-code-container">
|
||||
<div class="qr-code-placeholder" id="qrCodePlaceholder">
|
||||
<i class="fas fa-qrcode"></i>
|
||||
<div>Mã QR Code</div>
|
||||
<div style="font-size: 0.8rem;" id="qrCodeValue">SAVE100K</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p style="color: #6c757d; font-size: 0.8rem; margin-top: 10px;">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
Mã QR sẽ tự động cập nhật khi bạn sử dụng voucher
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Terms and Conditions -->
|
||||
<div class="terms-section">
|
||||
<h3 class="terms-title">
|
||||
<i class="fas fa-list-check"></i>
|
||||
Điều kiện sử dụng
|
||||
</h3>
|
||||
<ul class="terms-list" id="termsList">
|
||||
<li>Áp dụng cho đơn hàng từ 2.000.000đ</li>
|
||||
<li>Không áp dụng cùng với khuyến mãi khác</li>
|
||||
<li>Chỉ sử dụng 1 lần duy nhất</li>
|
||||
<li>Không hoàn trả hoặc đổi thành tiền mặt</li>
|
||||
<li>Có thể sử dụng cho cả mua hàng online và offline</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Usage History -->
|
||||
<div class="usage-history">
|
||||
<h3 class="history-title">
|
||||
<i class="fas fa-history"></i>
|
||||
Lịch sử sử dụng
|
||||
</h3>
|
||||
<div class="history-empty" id="usageHistory">
|
||||
Chưa có lịch sử sử dụng
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Toast Notification -->
|
||||
<div class="toast" id="toast">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
<span id="toastMessage">Đã sao chép mã voucher!</span>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Gift data mapping
|
||||
const giftDatabase = {
|
||||
'SAVE100K': {
|
||||
name: 'Voucher giảm 100.000đ',
|
||||
description: 'Áp dụng cho đơn hàng từ 2.000.000đ',
|
||||
icon: 'fas fa-percentage',
|
||||
value: '100.000đ',
|
||||
expiry: '31/12/2023',
|
||||
minOrder: '2.000.000đ',
|
||||
terms: [
|
||||
'Áp dụng cho đơn hàng từ 2.000.000đ',
|
||||
'Không áp dụng cùng với khuyến mãi khác',
|
||||
'Chỉ sử dụng 1 lần duy nhất',
|
||||
'Không hoàn trả hoặc đổi thành tiền mặt',
|
||||
'Có thể sử dụng cho cả mua hàng online và offline'
|
||||
]
|
||||
},
|
||||
'FREECERAMIC': {
|
||||
name: 'Gạch ceramic miễn phí',
|
||||
description: '1m² gạch ceramic 30x30 cao cấp',
|
||||
icon: 'fas fa-gift',
|
||||
value: '1m²',
|
||||
expiry: '15/01/2024',
|
||||
minOrder: 'Không có',
|
||||
terms: [
|
||||
'Áp dụng cho gạch ceramic 30x30 cao cấp',
|
||||
'Tối đa 1m² mỗi voucher',
|
||||
'Chỉ sử dụng 1 lần duy nhất',
|
||||
'Phải đến cửa hàng để nhận hàng',
|
||||
'Không áp dụng cùng với khuyến mãi khác'
|
||||
]
|
||||
},
|
||||
'FREEDESIGN': {
|
||||
name: 'Tư vấn thiết kế miễn phí',
|
||||
description: 'Dịch vụ tư vấn thiết kế chuyên nghiệp',
|
||||
icon: 'fas fa-star',
|
||||
value: 'Miễn phí',
|
||||
expiry: '28/02/2024',
|
||||
minOrder: 'Không có',
|
||||
terms: [
|
||||
'Dịch vụ tư vấn thiết kế chuyên nghiệp',
|
||||
'Thời gian tư vấn: 60 phút',
|
||||
'Đặt lịch hẹn trước 24h',
|
||||
'Áp dụng cho dự án từ 20m² trở lên',
|
||||
'Bao gồm bản vẽ 2D cơ bản'
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize page with gift data
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const savedGift = localStorage.getItem('selectedGift');
|
||||
if (savedGift) {
|
||||
const giftData = JSON.parse(savedGift);
|
||||
loadGiftDetails(giftData.code, giftData.status);
|
||||
} else {
|
||||
// Fallback to default gift
|
||||
loadGiftDetails('SAVE100K', 'valid');
|
||||
}
|
||||
});
|
||||
|
||||
function loadGiftDetails(giftCode, status) {
|
||||
const gift = giftDatabase[giftCode];
|
||||
if (!gift) return;
|
||||
|
||||
// Update gift information
|
||||
document.getElementById('giftTitle').textContent = gift.name;
|
||||
document.getElementById('giftDescription').textContent = gift.description;
|
||||
document.getElementById('voucherCode').textContent = giftCode;
|
||||
document.getElementById('qrCodeValue').textContent = giftCode;
|
||||
document.getElementById('giftValue').textContent = gift.value;
|
||||
document.getElementById('expiryDate').textContent = gift.expiry;
|
||||
|
||||
// Update icon
|
||||
const iconElement = document.getElementById('giftIcon');
|
||||
iconElement.className = gift.icon;
|
||||
|
||||
// Update status
|
||||
const statusBadge = document.getElementById('statusBadge');
|
||||
const useButton = document.getElementById('useButton');
|
||||
|
||||
switch(status) {
|
||||
case 'valid':
|
||||
statusBadge.textContent = 'Còn hạn sử dụng';
|
||||
statusBadge.className = 'status-badge status-valid';
|
||||
useButton.disabled = false;
|
||||
useButton.innerHTML = '<i class="fas fa-check"></i> Sử dụng ngay';
|
||||
break;
|
||||
case 'used':
|
||||
statusBadge.textContent = 'Đã sử dụng';
|
||||
statusBadge.className = 'status-badge status-used';
|
||||
useButton.disabled = true;
|
||||
useButton.innerHTML = '<i class="fas fa-check-circle"></i> Đã sử dụng';
|
||||
updateUsageHistory();
|
||||
break;
|
||||
case 'expired':
|
||||
statusBadge.textContent = 'Đã hết hạn';
|
||||
statusBadge.className = 'status-badge status-expired';
|
||||
useButton.disabled = true;
|
||||
useButton.innerHTML = '<i class="fas fa-times-circle"></i> Hết hạn';
|
||||
break;
|
||||
}
|
||||
|
||||
// Update terms
|
||||
const termsList = document.getElementById('termsList');
|
||||
termsList.innerHTML = '';
|
||||
gift.terms.forEach(term => {
|
||||
const li = document.createElement('li');
|
||||
li.textContent = term;
|
||||
termsList.appendChild(li);
|
||||
});
|
||||
|
||||
// Generate QR code placeholder (in a real app, this would be an actual QR code)
|
||||
generateQRCodePlaceholder(giftCode);
|
||||
}
|
||||
|
||||
function generateQRCodePlaceholder(code) {
|
||||
const qrPlaceholder = document.getElementById('qrCodePlaceholder');
|
||||
// In a real application, you would integrate with a QR code library
|
||||
// For now, we'll create a styled placeholder
|
||||
qrPlaceholder.innerHTML = `
|
||||
<div style="
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(45deg, #f8f9fa 25%, transparent 25%, transparent 75%, #f8f9fa 75%, #f8f9fa),
|
||||
linear-gradient(45deg, #f8f9fa 25%, transparent 25%, transparent 75%, #f8f9fa 75%, #f8f9fa);
|
||||
background-size: 10px 10px;
|
||||
background-position: 0 0, 5px 5px;
|
||||
border: 2px solid #333;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
">
|
||||
<i class="fas fa-qrcode" style="font-size: 2rem; margin-bottom: 10px;"></i>
|
||||
<div style="font-size: 0.8rem;">${code}</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function copyVoucherCode() {
|
||||
const voucherCode = document.getElementById('voucherCode').textContent;
|
||||
|
||||
// Copy to clipboard
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
navigator.clipboard.writeText(voucherCode).then(() => {
|
||||
showToast('Đã sao chép mã voucher!');
|
||||
}).catch(() => {
|
||||
fallbackCopyTextToClipboard(voucherCode);
|
||||
});
|
||||
} else {
|
||||
fallbackCopyTextToClipboard(voucherCode);
|
||||
}
|
||||
}
|
||||
|
||||
function fallbackCopyTextToClipboard(text) {
|
||||
const textArea = document.createElement("textarea");
|
||||
textArea.value = text;
|
||||
textArea.style.top = "0";
|
||||
textArea.style.left = "0";
|
||||
textArea.style.position = "fixed";
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
|
||||
try {
|
||||
document.execCommand('copy');
|
||||
showToast('Đã sao chép mã voucher!');
|
||||
} catch (err) {
|
||||
showToast('Không thể sao chép. Vui lòng sao chép thủ công.', 'error');
|
||||
}
|
||||
|
||||
document.body.removeChild(textArea);
|
||||
}
|
||||
|
||||
function useGift() {
|
||||
const useButton = document.getElementById('useButton');
|
||||
if (useButton.disabled) return;
|
||||
|
||||
// Confirm usage
|
||||
if (confirm('Bạn có chắc chắn muốn sử dụng voucher này? Hành động này không thể hoàn tác.')) {
|
||||
// Update gift status to used
|
||||
const giftCode = document.getElementById('voucherCode').textContent;
|
||||
|
||||
// Update localStorage
|
||||
const giftData = {
|
||||
code: giftCode,
|
||||
name: document.getElementById('giftTitle').textContent,
|
||||
status: 'used'
|
||||
};
|
||||
localStorage.setItem('selectedGift', JSON.stringify(giftData));
|
||||
|
||||
// Reload page with used status
|
||||
loadGiftDetails(giftCode, 'used');
|
||||
|
||||
showToast('Voucher đã được sử dụng thành công!');
|
||||
|
||||
// Redirect to store or cart page after 2 seconds
|
||||
setTimeout(() => {
|
||||
window.location.href = 'cart.html';
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
function shareGift() {
|
||||
const giftName = document.getElementById('giftTitle').textContent;
|
||||
const giftCode = document.getElementById('voucherCode').textContent;
|
||||
const shareText = `Xem voucher ${giftName} - Mã: ${giftCode}`;
|
||||
|
||||
if (navigator.share) {
|
||||
navigator.share({
|
||||
title: giftName,
|
||||
text: shareText,
|
||||
url: window.location.href,
|
||||
}).catch((error) => {
|
||||
console.log('Error sharing:', error);
|
||||
fallbackShare(shareText);
|
||||
});
|
||||
} else {
|
||||
fallbackShare(shareText);
|
||||
}
|
||||
}
|
||||
|
||||
function fallbackShare(text) {
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
showToast('Đã sao chép thông tin để chia sẻ!');
|
||||
});
|
||||
} else {
|
||||
showToast('Sao chép thủ công: ' + text);
|
||||
}
|
||||
}
|
||||
|
||||
function updateUsageHistory() {
|
||||
const historyElement = document.getElementById('usageHistory');
|
||||
const currentDate = new Date().toLocaleDateString('vi-VN');
|
||||
historyElement.innerHTML = `
|
||||
<div style="text-align: left; color: #4a5568;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; padding: 10px 0; border-bottom: 1px solid #e2e8f0;">
|
||||
<div>
|
||||
<div style="font-weight: 600;">Đã sử dụng voucher</div>
|
||||
<div style="font-size: 0.8rem; color: #718096;">Đơn hàng #DH${Date.now().toString().slice(-6)}</div>
|
||||
</div>
|
||||
<div style="text-align: right;">
|
||||
<div style="color: #28a745; font-weight: 600;">${currentDate}</div>
|
||||
<div style="font-size: 0.8rem; color: #718096;">Thành công</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function showToast(message, type = 'success') {
|
||||
const toast = document.getElementById('toast');
|
||||
const toastMessage = document.getElementById('toastMessage');
|
||||
|
||||
toastMessage.textContent = message;
|
||||
|
||||
if (type === 'error') {
|
||||
toast.style.background = '#dc3545';
|
||||
} else {
|
||||
toast.style.background = '#28a745';
|
||||
}
|
||||
|
||||
toast.classList.add('show');
|
||||
|
||||
setTimeout(() => {
|
||||
toast.classList.remove('show');
|
||||
}, 3000);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -50,7 +50,7 @@
|
||||
</div>
|
||||
<div class="gift-actions">
|
||||
<button class="btn btn-primary btn-sm">Sử dụng</button>
|
||||
<button class="btn btn-secondary btn-sm">Chi tiết</button>
|
||||
<button class="btn btn-secondary btn-sm" onclick="viewGiftDetail('SAVE100K', 'Voucher giảm 100.000đ', 'valid')">Chi tiết</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
</div>
|
||||
<div class="gift-actions">
|
||||
<button class="btn btn-primary btn-sm">Sử dụng</button>
|
||||
<button class="btn btn-secondary btn-sm">Chi tiết</button>
|
||||
<button class="btn btn-secondary btn-sm" onclick="viewGiftDetail('FREECERAMIC', 'Gạch ceramic miễn phí', 'valid')">Chi tiết</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -169,12 +169,13 @@
|
||||
</div>
|
||||
<div class="gift-actions">
|
||||
<button class="btn btn-primary btn-sm">Sử dụng</button>
|
||||
<button class="btn btn-secondary btn-sm">Chi tiết</button>
|
||||
<button class="btn btn-secondary btn-sm" onclick="viewGiftDetail('FREEDESIGN', 'Tư vấn thiết kế miễn phí', 'valid')">Chi tiết</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function filterGifts(status) {
|
||||
@@ -195,6 +196,19 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function viewGiftDetail(giftCode, giftName, status) {
|
||||
// Store gift data in localStorage for the detail page
|
||||
const giftData = {
|
||||
code: giftCode,
|
||||
name: giftName,
|
||||
status: status
|
||||
};
|
||||
localStorage.setItem('selectedGift', JSON.stringify(giftData));
|
||||
|
||||
// Navigate to gift detail page
|
||||
window.location.href = 'my-gift-detail.html';
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
794
html/nha-mau-360-detail.html
Normal file
794
html/nha-mau-360-detail.html
Normal file
@@ -0,0 +1,794 @@
|
||||
<!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 Nhà mẫu - 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">
|
||||
<style>
|
||||
/* 360 View Container */
|
||||
.view-360-container {
|
||||
/*margin: 16px;*/
|
||||
background: var(--white);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-medium);
|
||||
}
|
||||
|
||||
/* 360 Preview Card */
|
||||
.view-360-preview {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.view-360-preview:hover {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
.view-360-preview::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: url('https://images.unsplash.com/photo-1600585154340-be6161a56a0c?w=800&h=600&fit=crop') center/cover;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.view-360-content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
text-align: center;
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
.view-360-icon {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
margin: 0 auto 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 50%;
|
||||
border: 3px solid var(--white);
|
||||
position: relative;
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
70% {
|
||||
box-shadow: 0 0 0 20px rgba(255, 255, 255, 0);
|
||||
}
|
||||
100% {
|
||||
box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.view-360-icon svg {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
fill: var(--white);
|
||||
}
|
||||
|
||||
.view-360-text {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
text-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.view-360-subtitle {
|
||||
font-size: 14px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.view-360-button {
|
||||
margin-top: 20px;
|
||||
padding: 12px 32px;
|
||||
background: var(--white);
|
||||
color: var(--primary-blue);
|
||||
border: none;
|
||||
border-radius: 24px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.view-360-button:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(0,0,0,0.2);
|
||||
}
|
||||
.webview-container {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
background: #f3f4f6;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 24px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.webview-iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.webview-placeholder {
|
||||
text-align: center;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.webview-placeholder i {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 12px;
|
||||
color: #d1d5db;
|
||||
}
|
||||
|
||||
.project-info {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin-bottom: 24px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.project-title {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.project-specs {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 16px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.spec-item {
|
||||
text-align: center;
|
||||
padding: 16px 12px;
|
||||
background: #f8fafc;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.spec-label {
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.spec-value {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.gallery-section {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.gallery-title {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
margin-bottom: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.gallery-scroll {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
overflow-x: auto;
|
||||
padding-bottom: 8px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.gallery-item {
|
||||
flex-shrink: 0;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.gallery-item:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.gallery-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.lightbox {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.9);
|
||||
z-index: 1000;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.lightbox.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.lightbox-content {
|
||||
position: relative;
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
}
|
||||
|
||||
.lightbox-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.lightbox-caption {
|
||||
position: absolute;
|
||||
bottom: -50px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
color: white;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.lightbox-close {
|
||||
position: absolute;
|
||||
top: -50px;
|
||||
right: 0;
|
||||
background: none;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 32px;
|
||||
cursor: pointer;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.lightbox-nav {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: rgba(255,255,255,0.2);
|
||||
border: none;
|
||||
color: white;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.lightbox-nav:hover {
|
||||
background: rgba(255,255,255,0.3);
|
||||
}
|
||||
|
||||
.lightbox-prev {
|
||||
left: -70px;
|
||||
}
|
||||
|
||||
.lightbox-next {
|
||||
right: -70px;
|
||||
}
|
||||
|
||||
.lightbox-counter {
|
||||
position: absolute;
|
||||
top: -50px;
|
||||
left: 0;
|
||||
color: white;
|
||||
font-size: 16px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.loading-state {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 200px;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 4px solid #f3f4f6;
|
||||
border-top: 4px solid #2563eb;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.project-specs {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.spec-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
text-align: left;
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.spec-value {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.gallery-item {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.lightbox-nav {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.lightbox-prev {
|
||||
left: -50px;
|
||||
}
|
||||
|
||||
.lightbox-next {
|
||||
right: -50px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-wrapper">
|
||||
<!-- Header -->
|
||||
<div class="header">
|
||||
<a href="nha-mau.html" class="back-button">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Chi tiết Nhà mẫu</h1>
|
||||
<button class="icon-button" onclick="shareModel()">
|
||||
<i class="fas fa-share-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="container" >
|
||||
<!-- 360° View Container -->
|
||||
<div class="view-360-container">
|
||||
<!-- 360° Preview/Launch Card -->
|
||||
<div class="view-360-preview" onclick="window.location.href='https://vr.house3d.com/web/panorama-player/H00179549'">
|
||||
<div class="view-360-content">
|
||||
<div class="view-360-icon">
|
||||
<!-- Custom 360° SVG Icon -->
|
||||
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
||||
<g stroke="currentColor" stroke-width="3" fill="none">
|
||||
<!-- Circular arrow -->
|
||||
<path d="M 80 50 A 30 30 0 1 1 50 20" />
|
||||
<polygon points="48,15 48,25 58,20" fill="currentColor"/>
|
||||
|
||||
<!-- 360° text -->
|
||||
<text x="50" y="50" text-anchor="middle" dominant-baseline="middle"
|
||||
font-family="Roboto, sans-serif" font-size="20" fill="currentColor">
|
||||
360°
|
||||
</text>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="view-360-text">Xem nhà mẫu 360°</div>
|
||||
<div class="view-360-subtitle">Trải nghiệm không gian thực tế ảo</div>
|
||||
<button class="view-360-button">
|
||||
<i class="fas fa-play"></i>
|
||||
Bắt đầu tham quan
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 360° WebView Container -->
|
||||
<!--<div class="webview-container" id="webview-container">-->
|
||||
<!-- Loading State -->
|
||||
<!--<div class="loading-state" id="loading-state">
|
||||
<div class="spinner"></div>
|
||||
<span>Đang tải mô hình 360°...</span>
|
||||
</div>-->
|
||||
|
||||
<!-- Placeholder for 360° iframe -->
|
||||
<!--<iframe
|
||||
id="webview-iframe"
|
||||
class="webview-iframe"
|
||||
src="about:blank"
|
||||
title="Mô hình 360° Nhà mẫu"
|
||||
style="display: none;">
|
||||
</iframe>-->
|
||||
|
||||
<!-- Fallback placeholder -->
|
||||
<!--<div class="webview-placeholder" id="webview-placeholder" style="display: none;">
|
||||
<i class="fas fa-cube"></i>
|
||||
<h3>Mô hình 360°</h3>
|
||||
<p>Đang tải trình xem 3D...</p>
|
||||
</div>
|
||||
</div>-->
|
||||
|
||||
<!-- Project Information -->
|
||||
<div class="project-info">
|
||||
<h2 class="project-title" id="project-title">Căn hộ Studio</h2>
|
||||
|
||||
<div class="project-specs">
|
||||
<div class="spec-item">
|
||||
<div class="spec-label">Diện tích</div>
|
||||
<div class="spec-value" id="project-area">35m²</div>
|
||||
</div>
|
||||
<div class="spec-item">
|
||||
<div class="spec-label">Địa điểm</div>
|
||||
<div class="spec-value" id="project-location">Quận 7</div>
|
||||
</div>
|
||||
<div class="spec-item">
|
||||
<div class="spec-label">Phong cách</div>
|
||||
<div class="spec-value" id="project-style">Hiện đại</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="color: #4b5563; line-height: 1.6;" id="project-description">
|
||||
Thiết kế hiện đại cho căn hộ studio 35m², tối ưu không gian sống với gạch men cao cấp và màu sắc hài hòa.
|
||||
Sử dụng gạch granite nhập khẩu cho khu vực phòng khách và gạch ceramic chống thấm cho khu vực ẩm ướt.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image Gallery -->
|
||||
<div class="gallery-section">
|
||||
<h3 class="gallery-title">
|
||||
<i class="fas fa-images"></i>
|
||||
Thư viện Hình ảnh
|
||||
</h3>
|
||||
|
||||
<div class="gallery-scroll" id="gallery-scroll">
|
||||
<div class="gallery-item" onclick="openLightbox(0)">
|
||||
<img src="https://images.unsplash.com/photo-1600596542815-ffad4c1539a9?w=200&h=200&fit=crop"
|
||||
alt="Phối cảnh tổng thể"
|
||||
class="gallery-image">
|
||||
</div>
|
||||
<div class="gallery-item" onclick="openLightbox(1)">
|
||||
<img src="https://center.eurotile.vn/data/eurotileData/design/202009/23/4/main_img.jpg"
|
||||
alt="Khu vực phòng khách"
|
||||
class="gallery-image">
|
||||
</div>
|
||||
<div class="gallery-item" onclick="openLightbox(2)">
|
||||
<img src="https://center.eurotile.vn/data/eurotileData/design/202009/23/4/project_img_1.jpg?v=1"
|
||||
alt="Phòng ngủ chính"
|
||||
class="gallery-image">
|
||||
</div>
|
||||
<div class="gallery-item" onclick="openLightbox(3)">
|
||||
<img src="https://center.eurotile.vn/data/eurotileData/design/202009/23/4/project_img_0.jpg?v=1"
|
||||
alt="Khu vực bếp"
|
||||
class="gallery-image">
|
||||
</div>
|
||||
<div class="gallery-item" onclick="openLightbox(4)">
|
||||
<img src="https://images.unsplash.com/photo-1620626011761-996317b8d101?w=200&h=200&fit=crop"
|
||||
alt="Phòng tắm hiện đại"
|
||||
class="Phòng">
|
||||
</div>
|
||||
<div class="gallery-item" onclick="openLightbox(5)">
|
||||
<img src="https://center.eurotile.vn/data/eurotileData/design/202009/23/4/project_img_3.jpg?v=1"
|
||||
alt="Khu vực bàn ăn"
|
||||
class="gallery-image">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom Navigation -->
|
||||
<!--<div class="bottom-nav">
|
||||
<a href="index.html" class="nav-item">
|
||||
<i class="fas fa-home"></i>
|
||||
<span>Trang chủ</span>
|
||||
</a>
|
||||
<a href="loyalty.html" class="nav-item">
|
||||
<i class="fas fa-star"></i>
|
||||
<span>Hội viên</span>
|
||||
</a>
|
||||
<a href="promotions.html" class="nav-item">
|
||||
<i class="fas fa-tags"></i>
|
||||
<span>Khuyến mãi</span>
|
||||
</a>
|
||||
<a href="notifications.html" class="nav-item">
|
||||
<i class="fas fa-bell"></i>
|
||||
<span>Thông báo</span>
|
||||
</a>
|
||||
<a href="account.html" class="nav-item active">
|
||||
<i class="fas fa-user"></i>
|
||||
<span>Cài đặt</span>
|
||||
</a>
|
||||
</div>-->
|
||||
</div>
|
||||
|
||||
<!-- Lightbox Modal -->
|
||||
<div class="lightbox" id="lightbox">
|
||||
<div class="lightbox-content">
|
||||
<button class="lightbox-close" onclick="closeLightbox()">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
|
||||
<div class="lightbox-counter" id="lightbox-counter">1 / 6</div>
|
||||
|
||||
<img id="lightbox-image" class="lightbox-image" src="" alt="">
|
||||
|
||||
<div class="lightbox-caption" id="lightbox-caption">
|
||||
Phối cảnh tổng thể căn hộ studio với thiết kế hiện đại
|
||||
</div>
|
||||
|
||||
<button class="lightbox-nav lightbox-prev" onclick="prevImage()">
|
||||
<i class="fas fa-chevron-left"></i>
|
||||
</button>
|
||||
|
||||
<button class="lightbox-nav lightbox-next" onclick="nextImage()">
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Gallery data
|
||||
const galleryData = [
|
||||
{
|
||||
src: "https://images.unsplash.com/photo-1600596542815-ffad4c1539a9?w=800&h=600&fit=crop",
|
||||
caption: "Phối cảnh tổng thể căn hộ studio với thiết kế hiện đại"
|
||||
},
|
||||
{
|
||||
src: "https://center.eurotile.vn/data/eurotileData/design/202009/23/4/main_img.jpg",
|
||||
caption: "Khu vực phòng khách với gạch granite cao cấp"
|
||||
},
|
||||
{
|
||||
src: "https://center.eurotile.vn/data/eurotileData/design/202009/23/4/project_img_1.jpg?v=1",
|
||||
caption: "Phòng ngủ chính với gạch ceramic màu trung tính"
|
||||
},
|
||||
{
|
||||
src: "https://center.eurotile.vn/data/eurotileData/design/202009/23/4/project_img_0.jpg?v=1",
|
||||
caption: "Khu vực bếp với gạch mosaic điểm nhấn"
|
||||
},
|
||||
{
|
||||
src: "https://images.unsplash.com/photo-1620626011761-996317b8d101?w=200&h=200&fit=crop",
|
||||
caption: "Phòng tắm hiện đại với gạch chống thấm cao cấp"
|
||||
},
|
||||
{
|
||||
src: "https://center.eurotile.vn/data/eurotileData/design/202009/23/4/project_img_3.jpg?v=1",
|
||||
caption: "Khu vực bàn ăn ấm cúng"
|
||||
}
|
||||
];
|
||||
|
||||
let currentImageIndex = 0;
|
||||
|
||||
// Project data mapping
|
||||
const projectData = {
|
||||
'studio-apartment': {
|
||||
title: 'Căn hộ Studio',
|
||||
area: '35m²',
|
||||
location: 'Quận 7',
|
||||
style: 'Hiện đại',
|
||||
description: 'Thiết kế hiện đại cho căn hộ studio 35m², tối ưu không gian sống với gạch men cao cấp và màu sắc hài hòa. Sử dụng gạch granite nhập khẩu cho khu vực phòng khách và gạch ceramic chống thấm cho khu vực ẩm ướt.',
|
||||
iframe360: 'https://example.com/360-viewer/studio-apartment' // placeholder URL
|
||||
},
|
||||
'modern-villa': {
|
||||
title: 'Biệt thự Hiện đại',
|
||||
area: '250m²',
|
||||
location: 'Quận 2',
|
||||
style: 'Hiện đại',
|
||||
description: 'Biệt thự 3 tầng với phong cách kiến trúc hiện đại, sử dụng gạch granite và ceramic premium tạo điểm nhấn cho từng không gian sống.',
|
||||
iframe360: 'https://example.com/360-viewer/modern-villa'
|
||||
},
|
||||
'minimalist-house': {
|
||||
title: 'Nhà phố Tối giản',
|
||||
area: '120m²',
|
||||
location: 'Quận 10',
|
||||
style: 'Tối giản',
|
||||
description: 'Nhà phố 4x15m với thiết kế tối giản, tận dụng ánh sáng tự nhiên và gạch men màu trung tính để tạo không gian sống thoáng đãng.',
|
||||
iframe360: 'https://example.com/360-viewer/minimalist-house'
|
||||
},
|
||||
'luxury-condo': {
|
||||
title: 'Chung cư Cao cấp',
|
||||
area: '85m²',
|
||||
location: 'Quận 1',
|
||||
style: 'Sang trọng',
|
||||
description: 'Căn hộ 3PN với nội thất sang trọng, sử dụng gạch marble và ceramic cao cấp nhập khẩu Italy để tạo điểm nhấn đẳng cấp.',
|
||||
iframe360: 'https://example.com/360-viewer/luxury-condo'
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize page with project data
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const projectId = urlParams.get('id') || 'studio-apartment';
|
||||
|
||||
loadProjectData(projectId);
|
||||
simulateIframeLoading();
|
||||
});
|
||||
|
||||
function loadProjectData(projectId) {
|
||||
const project = projectData[projectId];
|
||||
if (!project) return;
|
||||
|
||||
document.getElementById('project-title').textContent = project.title;
|
||||
document.getElementById('project-area').textContent = project.area;
|
||||
document.getElementById('project-location').textContent = project.location;
|
||||
document.getElementById('project-style').textContent = project.style;
|
||||
document.getElementById('project-description').textContent = project.description;
|
||||
|
||||
// Update page title
|
||||
document.title = `${project.title} - Chi tiết Nhà mẫu`;
|
||||
}
|
||||
|
||||
function simulateIframeLoading() {
|
||||
const loadingState = document.getElementById('loading-state');
|
||||
const iframe = document.getElementById('webview-iframe');
|
||||
const placeholder = document.getElementById('webview-placeholder');
|
||||
|
||||
// Simulate loading time
|
||||
setTimeout(() => {
|
||||
loadingState.style.display = 'none';
|
||||
|
||||
// In a real app, you would load the actual 360° URL
|
||||
// For demo, we'll show a placeholder
|
||||
placeholder.style.display = 'flex';
|
||||
|
||||
// Uncomment below to load actual iframe in production:
|
||||
// iframe.src = project.iframe360;
|
||||
// iframe.style.display = 'block';
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
function openLightbox(index) {
|
||||
currentImageIndex = index;
|
||||
const lightbox = document.getElementById('lightbox');
|
||||
const image = document.getElementById('lightbox-image');
|
||||
const caption = document.getElementById('lightbox-caption');
|
||||
const counter = document.getElementById('lightbox-counter');
|
||||
|
||||
image.src = galleryData[index].src;
|
||||
caption.textContent = galleryData[index].caption;
|
||||
counter.textContent = `${index + 1} / ${galleryData.length}`;
|
||||
|
||||
lightbox.classList.add('active');
|
||||
document.body.style.overflow = 'hidden'; // Prevent background scroll
|
||||
}
|
||||
|
||||
function closeLightbox() {
|
||||
const lightbox = document.getElementById('lightbox');
|
||||
lightbox.classList.remove('active');
|
||||
document.body.style.overflow = 'auto'; // Restore scroll
|
||||
}
|
||||
|
||||
function nextImage() {
|
||||
currentImageIndex = (currentImageIndex + 1) % galleryData.length;
|
||||
updateLightboxImage();
|
||||
}
|
||||
|
||||
function prevImage() {
|
||||
currentImageIndex = (currentImageIndex - 1 + galleryData.length) % galleryData.length;
|
||||
updateLightboxImage();
|
||||
}
|
||||
|
||||
function updateLightboxImage() {
|
||||
const image = document.getElementById('lightbox-image');
|
||||
const caption = document.getElementById('lightbox-caption');
|
||||
const counter = document.getElementById('lightbox-counter');
|
||||
|
||||
image.src = galleryData[currentImageIndex].src;
|
||||
caption.textContent = galleryData[currentImageIndex].caption;
|
||||
counter.textContent = `${currentImageIndex + 1} / ${galleryData.length}`;
|
||||
}
|
||||
|
||||
function shareModel() {
|
||||
const projectTitle = document.getElementById('project-title').textContent;
|
||||
|
||||
if (navigator.share) {
|
||||
navigator.share({
|
||||
title: projectTitle,
|
||||
text: `Xem mô hình 360° ${projectTitle}`,
|
||||
url: window.location.href
|
||||
}).catch(console.error);
|
||||
} else {
|
||||
// Fallback: copy URL to clipboard
|
||||
navigator.clipboard.writeText(window.location.href).then(() => {
|
||||
showToast('Đã sao chép link chia sẻ!');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function showToast(message) {
|
||||
const toast = document.createElement('div');
|
||||
toast.className = 'fixed top-20 left-1/2 transform -translate-x-1/2 bg-green-500 text-white px-4 py-2 rounded-lg z-50 transition-all duration-300';
|
||||
toast.textContent = message;
|
||||
document.body.appendChild(toast);
|
||||
|
||||
setTimeout(() => {
|
||||
toast.style.opacity = '0';
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(toast);
|
||||
}, 300);
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
// Close lightbox with Escape key
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape' && document.getElementById('lightbox').classList.contains('active')) {
|
||||
closeLightbox();
|
||||
}
|
||||
});
|
||||
|
||||
// Close lightbox by clicking background
|
||||
document.getElementById('lightbox').addEventListener('click', function(e) {
|
||||
if (e.target === this) {
|
||||
closeLightbox();
|
||||
}
|
||||
});
|
||||
|
||||
// Keyboard navigation in lightbox
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (document.getElementById('lightbox').classList.contains('active')) {
|
||||
if (e.key === 'ArrowLeft') {
|
||||
prevImage();
|
||||
} else if (e.key === 'ArrowRight') {
|
||||
nextImage();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
167
html/nha-mau-create.html
Normal file
167
html/nha-mau-create.html
Normal file
@@ -0,0 +1,167 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="vi">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Tạo nhà mẫu mới - 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="nha-mau-list.html" class="back-button">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Tạo nhà mẫu mới</h1>
|
||||
<div style="width: 32px;"></div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<!-- Project Creation Form -->
|
||||
<div class="form-container">
|
||||
<div class="card">
|
||||
<h3 class="card-title mb-3">Thông tin nhà mẫu</h3>
|
||||
|
||||
<form id="projectForm">
|
||||
<!-- Project Name -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Tên nhà mẫu *</label>
|
||||
<input type="text" class="form-input" placeholder="Nhập tên nhà mẫu" required>
|
||||
</div>
|
||||
|
||||
<!-- Project Owner -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Tên chủ đầu tư *</label>
|
||||
<input type="text" class="form-input" placeholder="Nhập tên chủ đầu tư" required>
|
||||
</div>
|
||||
|
||||
<!-- Contact Information -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Số điện thoại liên hệ *</label>
|
||||
<input type="tel" class="form-input" placeholder="Nhập số điện thoại" required>
|
||||
</div>
|
||||
|
||||
<!-- Address -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Địa chỉ nhà mẫu *</label>
|
||||
<input type="text" class="form-input" placeholder="Nhập địa chỉ chi tiết" required>
|
||||
</div>
|
||||
|
||||
<!-- Province/City -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Tỉnh/Thành phố *</label>
|
||||
<select class="form-select" required>
|
||||
<option value="">Chọn tỉnh/thành phố</option>
|
||||
<option value="hcm">TP. Hồ Chí Minh</option>
|
||||
<option value="hanoi">Hà Nội</option>
|
||||
<option value="danang">Đà Nẵng</option>
|
||||
<option value="binhduong">Bình Dương</option>
|
||||
<option value="dongnai">Đồng Nai</option>
|
||||
<option value="cantho">Cần Thơ</option>
|
||||
<option value="other">Khác</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- District -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Quận/Huyện</label>
|
||||
<input type="text" class="form-input" placeholder="Nhập quận/huyện">
|
||||
</div>
|
||||
|
||||
<!-- Project Type -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Loại nhà mẫu *</label>
|
||||
<select class="form-select" required>
|
||||
<option value="">Chọn loại nhà mẫu</option>
|
||||
<option value="villa">Villa</option>
|
||||
<option value="apartment">Chung cư</option>
|
||||
<option value="office">Văn phòng</option>
|
||||
<option value="commercial">Thương mại</option>
|
||||
<option value="resort">Resort/Khách sạn</option>
|
||||
<option value="house">Nhà phố</option>
|
||||
<option value="other">Khác</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Area -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Diện tích (m²)</label>
|
||||
<input type="number" class="form-input" placeholder="Nhập diện tích">
|
||||
</div>
|
||||
|
||||
<!-- Start Date -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Ngày bắt đầu *</label>
|
||||
<input type="date" class="form-input" required>
|
||||
</div>
|
||||
|
||||
<!-- Expected End Date -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Ngày dự kiến hoàn thành</label>
|
||||
<input type="date" class="form-input">
|
||||
</div>
|
||||
|
||||
<!-- Budget -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Ngân sách dự kiến (VND)</label>
|
||||
<input type="number" class="form-input" placeholder="Nhập ngân sách">
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Mô tả chi tiết</label>
|
||||
<textarea class="form-textarea" rows="4" placeholder="Nhập mô tả chi tiết về nhà mẫu"></textarea>
|
||||
</div>
|
||||
|
||||
<!-- Notes -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Ghi chú</label>
|
||||
<textarea class="form-textarea" rows="3" placeholder="Ghi chú thêm (nếu có)"></textarea>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="form-actions">
|
||||
<button type="button" class="btn btn-secondary" onclick="history.back()">
|
||||
Hủy bỏ
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary" onclick="saveProject()">
|
||||
<i class="fas fa-save"></i>
|
||||
Lưu nhà mẫu
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function saveProject() {
|
||||
const form = document.getElementById('projectForm');
|
||||
|
||||
if (form.checkValidity()) {
|
||||
// Show success message
|
||||
alert('Nhà mẫu đã được tạo thành công!');
|
||||
|
||||
// Redirect to projects list
|
||||
window.location.href = 'nha-mau-list.html';
|
||||
} else {
|
||||
// Show validation errors
|
||||
form.reportValidity();
|
||||
}
|
||||
}
|
||||
|
||||
// Set today's date as default start date
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
const startDateInput = document.querySelector('input[type="date"]');
|
||||
if (startDateInput) {
|
||||
startDateInput.value = today;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -415,13 +415,14 @@
|
||||
<!-- Header -->
|
||||
<header class="header">
|
||||
<div class="header-content">
|
||||
<button class="back-button" onclick="goBack()">
|
||||
<button class="back-button" onclick="window.location.href='index.html'">
|
||||
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</button>
|
||||
<h1 class="header-title">Quản lý Nhà mẫu</h1>
|
||||
<button class="add-button" onclick="createNewNhaMau()">
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
<button class="back-button" onclick="window.location.href='nha-mau-create.html'">
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -578,9 +579,9 @@
|
||||
</div>
|
||||
|
||||
<!-- Floating Create Button -->
|
||||
<button class="floating-create-btn" onclick="createNewNhaMau()">
|
||||
<!--<button class="floating-create-btn" onclick="createNewNhaMau()">
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
</button>-->
|
||||
|
||||
<script>
|
||||
function goBack() {
|
||||
|
||||
481
html/nha-mau.html
Normal file
481
html/nha-mau.html
Normal file
@@ -0,0 +1,481 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="vi">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Nhà mẫu - 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">
|
||||
<style>
|
||||
.tab-navigation {
|
||||
background: white;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
display: flex;
|
||||
position: sticky;
|
||||
top: 60px;
|
||||
z-index: 40;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
padding: 16px 12px;
|
||||
text-align: center;
|
||||
background: none;
|
||||
border: none;
|
||||
font-weight: 600;
|
||||
color: #64748b;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
border-bottom: 3px solid transparent;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
color: #004980;
|
||||
border-bottom-color: #004980;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
display: none;
|
||||
padding: 20px;
|
||||
min-height: calc(100vh - 140px);
|
||||
}
|
||||
|
||||
.tab-content.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.library-card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
||||
margin-bottom: 20px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.library-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.12);
|
||||
}
|
||||
|
||||
.library-image {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
object-fit: cover;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.image-overlay {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
background: rgba(37, 99, 235, 0.9);
|
||||
color: white;
|
||||
padding: 6px 12px;
|
||||
border-radius: 16px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.library-content {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.library-title {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.library-date {
|
||||
color: #6b7280;
|
||||
font-size: 14px;
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.library-description {
|
||||
color: #4b5563;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.request-card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.request-card:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.request-header {
|
||||
display: flex;
|
||||
justify-content: between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.request-code {
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.request-date {
|
||||
color: #6b7280;
|
||||
font-size: 14px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
padding: 6px 12px;
|
||||
border-radius: 20px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.status-pending {
|
||||
background: #fef3c7;
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.status-designing {
|
||||
background: #e0e7ff;
|
||||
color: #3730a3;
|
||||
}
|
||||
|
||||
.status-completed {
|
||||
background: #d1fae5;
|
||||
color: #065f46;
|
||||
}
|
||||
|
||||
.fab {
|
||||
position: fixed;
|
||||
bottom: 90px;
|
||||
right: 20px;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%);
|
||||
border-radius: 50%;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4px 16px rgba(37, 99, 235, 0.4);
|
||||
transition: all 0.3s ease;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.fab:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 24px rgba(37, 99, 235, 0.5);
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.empty-state i {
|
||||
font-size: 48px;
|
||||
margin-bottom: 20px;
|
||||
color: #d1d5db;
|
||||
}
|
||||
|
||||
.empty-state h3 {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #374151;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.empty-state p {
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.tab-content {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.library-content {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.request-card {
|
||||
padding: 15px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-wrapper">
|
||||
<!-- Header -->
|
||||
<div class="header">
|
||||
<a href="index.html" class="back-button">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Nhà mẫu</h1>
|
||||
<div style="width: 32px;"></div>
|
||||
</div>
|
||||
|
||||
<!-- Tab Navigation -->
|
||||
<div class="tab-navigation">
|
||||
<button class="tab-item active" onclick="switchTab('library')">
|
||||
Thư viện mẫu
|
||||
</button>
|
||||
<button class="tab-item" onclick="switchTab('requests')">
|
||||
Yêu cầu thiết kế
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Tab 1: Thư viện Mẫu -->
|
||||
<div class="tab-content active" id="library-tab">
|
||||
<div class="library-list">
|
||||
<!-- Library Item 1 -->
|
||||
<div class="library-card" >
|
||||
<div style="position: relative;" onclick="viewLibraryDetail('studio-apartment')">
|
||||
<img src="https://images.unsplash.com/photo-1600596542815-ffad4c1539a9?w=800&h=200&fit=crop"
|
||||
alt="Căn hộ Studio"
|
||||
class="library-image">
|
||||
<div class="image-overlay" onclick="window.location.href='https://vr.house3d.com/web/panorama-player/H00179549'">Xem 360°</div>
|
||||
</div>
|
||||
<div class="library-content" onclick="viewLibraryDetail('studio-apartment')">
|
||||
<h3 class="library-title">Căn hộ Studio</h3>
|
||||
<div class="library-date">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<span>Ngày đăng: 15/11/2024</span>
|
||||
</div>
|
||||
<p class="library-description">
|
||||
Thiết kế hiện đại cho căn hộ studio 35m², tối ưu không gian sống với gạch men cao cấp và màu sắc hài hòa.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Library Item 2 -->
|
||||
<div class="library-card" onclick="viewLibraryDetail('modern-villa')">
|
||||
<div style="position: relative;">
|
||||
<img src="https://images.unsplash.com/photo-1570129477492-45c003edd2be?w=800&h=200&fit=crop"
|
||||
alt="Biệt thự Hiện đại"
|
||||
class="library-image">
|
||||
<div class="image-overlay">Xem 360°</div>
|
||||
</div>
|
||||
<div class="library-content">
|
||||
<h3 class="library-title">Biệt thự Hiện đại</h3>
|
||||
<div class="library-date">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<span>Ngày đăng: 12/11/2024</span>
|
||||
</div>
|
||||
<p class="library-description">
|
||||
Biệt thự 3 tầng với phong cách kiến trúc hiện đại, sử dụng gạch granite và ceramic premium tạo điểm nhấn.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Library Item 3 -->
|
||||
<div class="library-card" onclick="viewLibraryDetail('minimalist-house')">
|
||||
<div style="position: relative;">
|
||||
<img src="https://images.unsplash.com/photo-1562663474-6cbb3eaa4d14?w=800&h=200&fit=crop"
|
||||
alt="Nhà phố Tối giản"
|
||||
class="library-image">
|
||||
<div class="image-overlay">Xem 360°</div>
|
||||
</div>
|
||||
<div class="library-content">
|
||||
<h3 class="library-title">Nhà phố Tối giản</h3>
|
||||
<div class="library-date">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<span>Ngày đăng: 08/11/2024</span>
|
||||
</div>
|
||||
<p class="library-description">
|
||||
Nhà phố 4x15m với thiết kế tối giản, tận dụng ánh sáng tự nhiên và gạch men màu trung tính.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Library Item 4 -->
|
||||
<div class="library-card" onclick="viewLibraryDetail('luxury-condo')">
|
||||
<div style="position: relative;">
|
||||
<img src="https://images.unsplash.com/photo-1600607687939-ce8a6c25118c?w=800&h=200&fit=crop"
|
||||
alt="Chung cư Cao cấp"
|
||||
class="library-image">
|
||||
<div class="image-overlay">Xem 360°</div>
|
||||
</div>
|
||||
<div class="library-content">
|
||||
<h3 class="library-title">Chung cư Cao cấp</h3>
|
||||
<div class="library-date">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<span>Ngày đăng: 05/11/2024</span>
|
||||
</div>
|
||||
<p class="library-description">
|
||||
Căn hộ 3PN với nội thất sang trọng, sử dụng gạch marble và ceramic cao cấp nhập khẩu Italy.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab 2: Yêu cầu Thiết kế -->
|
||||
<div class="tab-content" id="requests-tab">
|
||||
<div class="requests-list">
|
||||
<!-- Request Item 1 -->
|
||||
<div class="request-card" onclick="viewRequestDetail('YC001')">
|
||||
<div class="request-header">
|
||||
<div class="request-code">Mã yêu cầu: #YC001</div>
|
||||
<span class="status-badge status-completed">Hoàn thành</span>
|
||||
</div>
|
||||
<div class="request-date">Ngày gửi: 20/10/2024</div>
|
||||
<div style="color: #374151; font-size: 14px;">
|
||||
Thiết kế nhà phố 3 tầng - Anh Minh (Quận 7)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Request Item 2 -->
|
||||
<div class="request-card" onclick="viewRequestDetail('YC002')">
|
||||
<div class="request-header">
|
||||
<div class="request-code">Mã yêu cầu: #YC002</div>
|
||||
<span class="status-badge status-designing">Đang thiết kế</span>
|
||||
</div>
|
||||
<div class="request-date">Ngày gửi: 25/10/2024</div>
|
||||
<div style="color: #374151; font-size: 14px;">
|
||||
Cải tạo căn hộ chung cư - Chị Lan (Quận 2)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Request Item 3 -->
|
||||
<div class="request-card" onclick="viewRequestDetail('YC003')">
|
||||
<div class="request-header">
|
||||
<div class="request-code">Mã yêu cầu: #YC003</div>
|
||||
<span class="status-badge status-pending">Chờ tiếp nhận</span>
|
||||
</div>
|
||||
<div class="request-date">Ngày gửi: 28/10/2024</div>
|
||||
<div style="color: #374151; font-size: 14px;">
|
||||
Thiết kế biệt thự 2 tầng - Anh Đức (Bình Dương)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Request Item 4 -->
|
||||
<div class="request-card" onclick="viewRequestDetail('YC004')">
|
||||
<div class="request-header">
|
||||
<div class="request-code">Mã yêu cầu: #YC004</div>
|
||||
<span class="status-badge status-pending">Chờ tiếp nhận</span>
|
||||
</div>
|
||||
<div class="request-date">Ngày gửi: 01/11/2024</div>
|
||||
<div style="color: #374151; font-size: 14px;">
|
||||
Thiết kế cửa hàng kinh doanh - Chị Mai (Quận 1)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Empty state when no requests (hidden by default) -->
|
||||
<div class="empty-state" id="empty-requests" style="display: none;">
|
||||
<i class="fas fa-drafting-compass"></i>
|
||||
<h3>Chưa có yêu cầu thiết kế</h3>
|
||||
<p>Tạo yêu cầu thiết kế đầu tiên để nhận tư vấn từ đội ngũ chuyên gia</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom Navigation -->
|
||||
<!--<div class="bottom-nav">
|
||||
<a href="index.html" class="nav-item">
|
||||
<i class="fas fa-home"></i>
|
||||
<span>Trang chủ</span>
|
||||
</a>
|
||||
<a href="loyalty.html" class="nav-item">
|
||||
<i class="fas fa-star"></i>
|
||||
<span>Hội viên</span>
|
||||
</a>
|
||||
<a href="promotions.html" class="nav-item">
|
||||
<i class="fas fa-tags"></i>
|
||||
<span>Khuyến mãi</span>
|
||||
</a>
|
||||
<a href="notifications.html" class="nav-item">
|
||||
<i class="fas fa-bell"></i>
|
||||
<span>Thông báo</span>
|
||||
</a>
|
||||
<a href="account.html" class="nav-item active">
|
||||
<i class="fas fa-user"></i>
|
||||
<span>Cài đặt</span>
|
||||
</a>
|
||||
</div>-->
|
||||
|
||||
<!-- Floating Action Button (only show on Requests tab) -->
|
||||
<button class="fab" id="fab-button" style="display: none;" onclick="createNewRequest()">
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function switchTab(tab) {
|
||||
// Update tab navigation
|
||||
document.querySelectorAll('.tab-item').forEach(item => {
|
||||
item.classList.remove('active');
|
||||
});
|
||||
event.target.classList.add('active');
|
||||
|
||||
// Update tab content
|
||||
document.querySelectorAll('.tab-content').forEach(content => {
|
||||
content.classList.remove('active');
|
||||
});
|
||||
document.getElementById(tab + '-tab').classList.add('active');
|
||||
|
||||
// Show/hide FAB based on tab
|
||||
const fab = document.getElementById('fab-button');
|
||||
if (tab === 'requests') {
|
||||
fab.style.display = 'block';
|
||||
} else {
|
||||
fab.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function viewLibraryDetail(modelId) {
|
||||
// Navigate to 360° detail page
|
||||
window.location.href = `nha-mau-360-detail.html?id=${modelId}`;
|
||||
}
|
||||
|
||||
function viewRequestDetail(requestId) {
|
||||
// Navigate to request detail page
|
||||
window.location.href = `design-request-detail.html?id=${requestId}`;
|
||||
}
|
||||
|
||||
function createNewRequest() {
|
||||
// Navigate to create new request page
|
||||
window.location.href = 'design-request-create.html';
|
||||
}
|
||||
|
||||
// Initialize page
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Set default state
|
||||
switchTab('library');
|
||||
|
||||
// Add animation to cards
|
||||
const cards = document.querySelectorAll('.library-card, .request-card');
|
||||
cards.forEach((card, index) => {
|
||||
card.style.opacity = '0';
|
||||
card.style.transform = 'translateY(20px)';
|
||||
card.style.transition = 'all 0.5s ease';
|
||||
|
||||
setTimeout(() => {
|
||||
card.style.opacity = '1';
|
||||
card.style.transform = 'translateY(0)';
|
||||
}, index * 100);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Order Item 2 - Completed -->
|
||||
<div class="order-card completed" onclick="viewOrderDetail('DH001233')">
|
||||
<div class="order-card completed">
|
||||
<div class="order-status-indicator"></div>
|
||||
<div class="order-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
@@ -81,7 +81,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Order Item 3 - Shipping -->
|
||||
<div class="order-card shipping" onclick="viewOrderDetail('DH001232')">
|
||||
<div class="order-card shipping">
|
||||
<div class="order-status-indicator"></div>
|
||||
<div class="order-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
@@ -101,7 +101,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Order Item 4 - Pending -->
|
||||
<div class="order-card pending" onclick="viewOrderDetail('DH001231')">
|
||||
<div class="order-card pending">
|
||||
<div class="order-status-indicator"></div>
|
||||
<div class="order-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
@@ -121,7 +121,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Order Item 5 - Cancelled -->
|
||||
<div class="order-card cancelled" onclick="viewOrderDetail('DH001230')">
|
||||
<div class="order-card cancelled">
|
||||
<div class="order-status-indicator"></div>
|
||||
<div class="order-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
@@ -142,35 +142,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom Navigation -->
|
||||
<div class="bottom-nav">
|
||||
<a href="index.html" class="nav-item active">
|
||||
<i class="fas fa-home"></i>
|
||||
<span>Trang chủ</span>
|
||||
</a>
|
||||
<a href="loyalty.html" class="nav-item">
|
||||
<i class="fas fa-star"></i>
|
||||
<span>Hội viên</span>
|
||||
</a>
|
||||
<a href="promotions.html" class="nav-item">
|
||||
<i class="fas fa-tags"></i>
|
||||
<span>Khuyến mãi</span>
|
||||
</a>
|
||||
<a href="notifications.html" class="nav-item">
|
||||
<i class="fas fa-bell"></i>
|
||||
<span>Thông báo</span>
|
||||
</a>
|
||||
<a href="account.html" class="nav-item">
|
||||
<i class="fas fa-user"></i>
|
||||
<span>Cài đặt</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function viewOrderDetail(orderId) {
|
||||
window.location.href = `order-detail.html?id=${orderId}`;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -29,13 +29,23 @@
|
||||
</div>
|
||||
|
||||
<!-- Status Filters -->
|
||||
<div class="tab-nav mb-3">
|
||||
<!--<div class="tab-nav mb-3">
|
||||
<button class="tab-item active">Tất cả</button>
|
||||
<button class="tab-item">Chờ xác nhận</button>
|
||||
<button class="tab-item">Đang xử lý</button>
|
||||
<button class="tab-item">Đang giao</button>
|
||||
<button class="tab-item">Hoàn thành</button>
|
||||
<button class="tab-item">Đã hủy</button>
|
||||
</div>-->
|
||||
<!-- Filter Pills -->
|
||||
<div class="filter-container">
|
||||
<button class="filter-pill active">Tất cả</button>
|
||||
<button class="filter-pill">Chờ xác nhận</button>
|
||||
<button class="filter-pill">Gạch ốp tường</button>
|
||||
<button class="filter-pill">Đang xử lý</button>
|
||||
<button class="filter-pill">Đang giao</button>
|
||||
<button class="filter-pill">Hoàn thành</button>
|
||||
<button class="filter-pill">Đã hủy</button>
|
||||
</div>
|
||||
|
||||
<!-- Orders List -->
|
||||
@@ -50,18 +60,18 @@
|
||||
</div>
|
||||
|
||||
<div class="order-details">
|
||||
<p class="order-date">Ngày đặt: 03/08/2023</p>
|
||||
<p class="order-customer">Khách hàng: Nguyễn Văn A</p>
|
||||
<p class="order-date">Ngày đặt: 03/08/2025</p>
|
||||
<p class="order-customer">Ngày giao: 06/08/2025</p>
|
||||
<p class="order-customer">Địa chỉ: Quận 7, HCM</p>
|
||||
<p class="order-status-text">
|
||||
<span class="status-badge processing">Đang xử lý</span>
|
||||
</p>
|
||||
<p class="order-note">Gạch granite 60x60 - Số lượng: 50m²</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Order Item 2 - Completed -->
|
||||
<div class="order-card completed">
|
||||
<div class="order-card completed" onclick="viewOrderDetail('DH001233')">
|
||||
<div class="order-status-indicator"></div>
|
||||
<div class="order-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
@@ -70,18 +80,18 @@
|
||||
</div>
|
||||
|
||||
<div class="order-details">
|
||||
<p class="order-date">Ngày đặt: 02/08/2023</p>
|
||||
<p class="order-customer">Khách hàng: Trần Thị B</p>
|
||||
<p class="order-date">Ngày đặt: 24/06/2025</p>
|
||||
<p class="order-customer">Ngày giao: 27/06/202</p>
|
||||
<p class="order-customer">Địa chỉ: Thủ Dầu Một, Bình Dương</p>
|
||||
<p class="order-status-text">
|
||||
<span class="status-badge completed">Hoàn thành</span>
|
||||
</p>
|
||||
<p class="order-note">Gạch ceramic 30x30 - Số lượng: 80m²</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Order Item 3 - Shipping -->
|
||||
<div class="order-card shipping">
|
||||
<div class="order-card shipping" onclick="viewOrderDetail('DH001232')">
|
||||
<div class="order-status-indicator"></div>
|
||||
<div class="order-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
@@ -90,18 +100,18 @@
|
||||
</div>
|
||||
|
||||
<div class="order-details">
|
||||
<p class="order-date">Ngày đặt: 01/08/2023</p>
|
||||
<p class="order-customer">Khách hàng: Lê Văn C</p>
|
||||
<p class="order-date">Ngày đặt: 01/03/2025</p>
|
||||
<p class="order-customer">Ngày giao: 05/03/2025</p>
|
||||
<p class="order-customer">Địa chỉ: Cầu Giấy, Hà Nội</p>
|
||||
<p class="order-status-text">
|
||||
<span class="status-badge shipping">Đang giao</span>
|
||||
</p>
|
||||
<p class="order-note">Gạch porcelain 80x80 - Số lượng: 100m²</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Order Item 4 - Pending -->
|
||||
<div class="order-card pending">
|
||||
<div class="order-card pending" onclick="viewOrderDetail('DH001231')">
|
||||
<div class="order-status-indicator"></div>
|
||||
<div class="order-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
@@ -110,18 +120,18 @@
|
||||
</div>
|
||||
|
||||
<div class="order-details">
|
||||
<p class="order-date">Ngày đặt: 31/07/2023</p>
|
||||
<p class="order-customer">Khách hàng: Phạm Thị D</p>
|
||||
<p class="order-date">Ngày đặt: 08/11/2024</p>
|
||||
<p class="order-customer">Ngày giao: 12/11/2024</p>
|
||||
<p class="order-customer">Địa chỉ: Thủ Đức, HCM</p>
|
||||
<p class="order-status-text">
|
||||
<span class="status-badge pending">Chờ xác nhận</span>
|
||||
</p>
|
||||
<p class="order-note">Gạch mosaic 25x25 - Số lượng: 40m²</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Order Item 5 - Cancelled -->
|
||||
<div class="order-card cancelled">
|
||||
<div class="order-card cancelled" onclick="viewOrderDetail('DH001230')">
|
||||
<div class="order-status-indicator"></div>
|
||||
<div class="order-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
@@ -130,19 +140,47 @@
|
||||
</div>
|
||||
|
||||
<div class="order-details">
|
||||
<p class="order-date">Ngày đặt: 30/07/2023</p>
|
||||
<p class="order-customer">Khách hàng: Hoàng Văn E</p>
|
||||
<p class="order-date">Ngày đặt: 30/07/2024</p>
|
||||
<p class="order-customer">Ngày giao: 04/08/2024</p>
|
||||
<p class="order-customer">Địa chỉ: Rạch Giá, Kiên Giang</p>
|
||||
<p class="order-status-text">
|
||||
<span class="status-badge cancelled">Đã hủy</span>
|
||||
</p>
|
||||
<p class="order-note">Gạch terrazzo 40x40 - Số lượng: 20m²</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Bottom Navigation -->
|
||||
<!-- <div class="bottom-nav">
|
||||
<a href="index.html" class="nav-item active">
|
||||
<i class="fas fa-home"></i>
|
||||
<span>Trang chủ</span>
|
||||
</a>
|
||||
<a href="loyalty.html" class="nav-item">
|
||||
<i class="fas fa-star"></i>
|
||||
<span>Hội viên</span>
|
||||
</a>
|
||||
<a href="promotions.html" class="nav-item">
|
||||
<i class="fas fa-tags"></i>
|
||||
<span>Khuyến mãi</span>
|
||||
</a>
|
||||
<a href="notifications.html" class="nav-item">
|
||||
<i class="fas fa-bell"></i>
|
||||
<span>Thông báo</span>
|
||||
</a>
|
||||
<a href="account.html" class="nav-item">
|
||||
<i class="fas fa-user"></i>
|
||||
<span>Cài đặt</span>
|
||||
</a>
|
||||
</div>-->
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function viewOrderDetail(orderId) {
|
||||
window.location.href = `order-detail.html?id=${orderId}`;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
733
html/payment-detail.html
Normal file
733
html/payment-detail.html
Normal file
@@ -0,0 +1,733 @@
|
||||
<!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 Hóa đơn - 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">
|
||||
<style>
|
||||
.detail-container {
|
||||
max-width: 480px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background: #f8fafc;
|
||||
min-height: calc(100vh - 120px);
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.invoice-header {
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.invoice-id {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.invoice-date {
|
||||
color: #6b7280;
|
||||
font-size: 14px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
padding: 8px 16px;
|
||||
border-radius: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.status-overdue {
|
||||
background: #fee2e2;
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
.status-unpaid {
|
||||
background: #fef3c7;
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.status-paid {
|
||||
background: #d1fae5;
|
||||
color: #065f46;
|
||||
}
|
||||
|
||||
.status-partial {
|
||||
background: #e0e7ff;
|
||||
color: #3730a3;
|
||||
}
|
||||
|
||||
.payment-summary {
|
||||
background: #f8fafc;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.summary-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.summary-row:last-child {
|
||||
margin-bottom: 0;
|
||||
padding-top: 12px;
|
||||
border-top: 2px solid #e5e7eb;
|
||||
font-weight: 700;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.remaining-amount {
|
||||
color: #dc2626;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
margin-bottom: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.product-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 16px;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.product-image {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: #f3f4f6;
|
||||
border-radius: 8px;
|
||||
margin-right: 16px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.product-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
margin-bottom: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.product-sku {
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.product-details {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.product-quantity {
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.product-price {
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.payment-history {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.history-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.history-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: #d1fae5;
|
||||
color: #065f46;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 16px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.history-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.history-title {
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.history-details {
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.history-date {
|
||||
font-size: 12px;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.history-amount {
|
||||
text-align: right;
|
||||
font-weight: 600;
|
||||
color: #065f46;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
flex: 1;
|
||||
padding: 14px 20px;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
border: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.4);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: white;
|
||||
color: #374151;
|
||||
border: 2px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
border-color: #2563eb;
|
||||
color: #2563eb;
|
||||
}
|
||||
|
||||
.btn-download {
|
||||
background: #f3f4f6;
|
||||
color: #374151;
|
||||
border: 1px solid #d1d5db;
|
||||
}
|
||||
|
||||
.btn-download:hover {
|
||||
background: #e5e7eb;
|
||||
}
|
||||
|
||||
.download-section {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-history {
|
||||
text-align: center;
|
||||
padding: 40px 20px;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.empty-history i {
|
||||
font-size: 32px;
|
||||
margin-bottom: 12px;
|
||||
color: #d1d5db;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.detail-container {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.product-details {
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.summary-row {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.summary-row:last-child {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-wrapper">
|
||||
<!-- Header -->
|
||||
<div class="header">
|
||||
<a href="payments.html" class="back-button">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Chi tiết Hóa đơn</h1>
|
||||
<button class="icon-button" onclick="shareInvoice()">
|
||||
<i class="fas fa-share-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="detail-container">
|
||||
<!-- Invoice Header -->
|
||||
<div class="detail-card">
|
||||
<div class="invoice-header">
|
||||
<h2 class="invoice-id" id="invoice-id">#INV001</h2>
|
||||
<div class="invoice-date" id="invoice-date">Đơn hàng: #SO001 | Ngày đặt: 15/10/2024</div>
|
||||
<span class="status-badge" id="status-badge">Quá hạn</span>
|
||||
</div>
|
||||
|
||||
<!-- Payment Summary -->
|
||||
<div class="payment-summary">
|
||||
<div class="summary-row">
|
||||
<span>Tổng tiền hóa đơn:</span>
|
||||
<span id="total-amount">85.000.000đ</span>
|
||||
</div>
|
||||
<div class="summary-row">
|
||||
<span>Đã thanh toán:</span>
|
||||
<span id="paid-amount">25.000.000đ</span>
|
||||
</div>
|
||||
<div class="summary-row">
|
||||
<span>Còn lại:</span>
|
||||
<span class="remaining-amount" id="remaining-amount">60.000.000đ</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Customer Info -->
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 20px;">
|
||||
<div>
|
||||
<div style="font-size: 12px; color: #6b7280; margin-bottom: 4px;">Ngày đặt hàng</div>
|
||||
<div style="font-weight: 600;" id="order-date">15/10/2024</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size: 12px; color: #6b7280; margin-bottom: 4px;">Hạn thanh toán</div>
|
||||
<div style="font-weight: 600; color: #dc2626;" id="due-date">30/10/2024</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="padding: 16px; background: #f8fafc; border-radius: 8px;">
|
||||
<div style="font-size: 14px; font-weight: 600; margin-bottom: 8px;">Thông tin khách hàng</div>
|
||||
<div style="font-size: 14px; color: #4b5563;" id="customer-info">
|
||||
Công ty TNHH Xây Dựng Minh An<br>
|
||||
Địa chỉ: 123 Nguyễn Văn Linh, Quận 7, TP.HCM<br>
|
||||
SĐT: 0901234567 | Email: contact@minhan.com
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Product Details -->
|
||||
<div class="detail-card">
|
||||
<h3 class="section-title">
|
||||
<i class="fas fa-box" style="color: #2563eb;"></i>
|
||||
Danh sách sản phẩm
|
||||
</h3>
|
||||
|
||||
<div class="products-list" id="products-list">
|
||||
<div class="product-item">
|
||||
<div class="product-image">
|
||||
<i class="fas fa-image"></i>
|
||||
</div>
|
||||
<div class="product-info">
|
||||
<div class="product-name">Gạch Granite Eurotile Premium 60x60</div>
|
||||
<div class="product-sku">SKU: GT-PR-6060-001</div>
|
||||
<div class="product-details">
|
||||
<span class="product-quantity">Số lượng: 150 m²</span>
|
||||
<span class="product-price">450.000đ/m²</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="product-item">
|
||||
<div class="product-image">
|
||||
<i class="fas fa-image"></i>
|
||||
</div>
|
||||
<div class="product-info">
|
||||
<div class="product-name">Gạch Ceramic Cao Cấp 30x60</div>
|
||||
<div class="product-sku">SKU: CE-CC-3060-002</div>
|
||||
<div class="product-details">
|
||||
<span class="product-quantity">Số lượng: 80 m²</span>
|
||||
<span class="product-price">280.000đ/m²</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="product-item">
|
||||
<div class="product-image">
|
||||
<i class="fas fa-image"></i>
|
||||
</div>
|
||||
<div class="product-info">
|
||||
<div class="product-name">Keo dán gạch chuyên dụng</div>
|
||||
<div class="product-sku">SKU: KD-CD-001</div>
|
||||
<div class="product-details">
|
||||
<span class="product-quantity">Số lượng: 20 bao</span>
|
||||
<span class="product-price">85.000đ/bao</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Payment History -->
|
||||
<div class="detail-card">
|
||||
<h3 class="section-title">
|
||||
<i class="fas fa-history" style="color: #2563eb;"></i>
|
||||
Lịch sử thanh toán
|
||||
</h3>
|
||||
|
||||
<div class="payment-history" id="payment-history">
|
||||
<div class="history-item">
|
||||
<div class="history-icon">
|
||||
<i class="fas fa-check"></i>
|
||||
</div>
|
||||
<div class="history-content">
|
||||
<div class="history-title">Thanh toán lần 1</div>
|
||||
<div class="history-details">Chuyển khoản | Ref: TK20241020001</div>
|
||||
<div class="history-date">20/10/2024 - 14:30</div>
|
||||
</div>
|
||||
<div class="history-amount">25.000.000đ</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Download Section -->
|
||||
<div class="detail-card download-section">
|
||||
<h3 class="section-title">
|
||||
<i class="fas fa-download" style="color: #2563eb;"></i>
|
||||
Tải chứng từ
|
||||
</h3>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px;">
|
||||
<button class="btn btn-download" onclick="downloadPDF('invoice')">
|
||||
<i class="fas fa-file-pdf"></i>
|
||||
Hóa đơn PDF
|
||||
</button>
|
||||
<button class="btn btn-download" onclick="downloadPDF('receipt')">
|
||||
<i class="fas fa-receipt"></i>
|
||||
Phiếu thu PDF
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="action-buttons">
|
||||
<button class="btn btn-secondary" onclick="contactSupport()">
|
||||
<i class="fas fa-comments"></i>
|
||||
Liên hệ hỗ trợ
|
||||
</button>
|
||||
<button class="btn btn-primary" onclick="makePayment()" id="pay-button">
|
||||
<i class="fas fa-credit-card"></i>
|
||||
Thanh toán
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Invoice data mapping
|
||||
const invoiceDatabase = {
|
||||
'INV001': {
|
||||
id: 'INV001',
|
||||
orderId: 'SO001',
|
||||
orderDate: '15/10/2024',
|
||||
dueDate: '30/10/2024',
|
||||
status: 'overdue',
|
||||
statusText: 'Quá hạn',
|
||||
totalAmount: 85000000,
|
||||
paidAmount: 25000000,
|
||||
remainingAmount: 60000000,
|
||||
customer: {
|
||||
name: 'Công ty TNHH Xây Dựng Minh An',
|
||||
address: '123 Nguyễn Văn Linh, Quận 7, TP.HCM',
|
||||
phone: '0901234567',
|
||||
email: 'contact@minhan.com'
|
||||
},
|
||||
products: [
|
||||
{
|
||||
name: 'Gạch Granite Eurotile Premium 60x60',
|
||||
sku: 'GT-PR-6060-001',
|
||||
quantity: 150,
|
||||
unit: 'm²',
|
||||
price: 450000
|
||||
},
|
||||
{
|
||||
name: 'Gạch Ceramic Cao Cấp 30x60',
|
||||
sku: 'CE-CC-3060-002',
|
||||
quantity: 80,
|
||||
unit: 'm²',
|
||||
price: 280000
|
||||
},
|
||||
{
|
||||
name: 'Keo dán gạch chuyên dụng',
|
||||
sku: 'KD-CD-001',
|
||||
quantity: 20,
|
||||
unit: 'bao',
|
||||
price: 85000
|
||||
}
|
||||
],
|
||||
paymentHistory: [
|
||||
{
|
||||
date: '20/10/2024',
|
||||
time: '14:30',
|
||||
amount: 25000000,
|
||||
method: 'Chuyển khoản',
|
||||
reference: 'TK20241020001',
|
||||
title: 'Thanh toán lần 1'
|
||||
}
|
||||
]
|
||||
},
|
||||
'INV002': {
|
||||
id: 'INV002',
|
||||
orderId: 'SO002',
|
||||
orderDate: '25/10/2024',
|
||||
dueDate: '09/11/2024',
|
||||
status: 'unpaid',
|
||||
statusText: 'Chưa thanh toán',
|
||||
totalAmount: 42500000,
|
||||
paidAmount: 0,
|
||||
remainingAmount: 42500000,
|
||||
customer: {
|
||||
name: 'Anh Nguyễn Văn Minh',
|
||||
address: '456 Lê Văn Việt, Quận 9, TP.HCM',
|
||||
phone: '0987654321',
|
||||
email: 'minh.nguyen@email.com'
|
||||
},
|
||||
paymentHistory: []
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize page
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const invoiceId = urlParams.get('id') || 'INV001';
|
||||
|
||||
loadInvoiceDetail(invoiceId);
|
||||
});
|
||||
|
||||
function loadInvoiceDetail(invoiceId) {
|
||||
const invoice = invoiceDatabase[invoiceId];
|
||||
if (!invoice) return;
|
||||
|
||||
// Update basic info
|
||||
document.getElementById('invoice-id').textContent = '#' + invoice.id;
|
||||
document.getElementById('invoice-date').textContent = `Đơn hàng: #${invoice.orderId} | Ngày đặt: ${invoice.orderDate}`;
|
||||
document.getElementById('order-date').textContent = invoice.orderDate;
|
||||
document.getElementById('due-date').textContent = invoice.dueDate;
|
||||
|
||||
// Update amounts
|
||||
document.getElementById('total-amount').textContent = formatCurrency(invoice.totalAmount);
|
||||
document.getElementById('paid-amount').textContent = formatCurrency(invoice.paidAmount);
|
||||
document.getElementById('remaining-amount').textContent = formatCurrency(invoice.remainingAmount);
|
||||
|
||||
// Update status
|
||||
const statusBadge = document.getElementById('status-badge');
|
||||
statusBadge.textContent = invoice.statusText;
|
||||
statusBadge.className = `status-badge status-${invoice.status}`;
|
||||
|
||||
// Update customer info
|
||||
const customerInfo = document.getElementById('customer-info');
|
||||
customerInfo.innerHTML = `
|
||||
${invoice.customer.name}<br>
|
||||
Địa chỉ: ${invoice.customer.address}<br>
|
||||
SĐT: ${invoice.customer.phone} | Email: ${invoice.customer.email}
|
||||
`;
|
||||
|
||||
// Update products
|
||||
if (invoice.products) {
|
||||
updateProductsList(invoice.products);
|
||||
}
|
||||
|
||||
// Update payment history
|
||||
updatePaymentHistory(invoice.paymentHistory);
|
||||
|
||||
// Update pay button
|
||||
const payButton = document.getElementById('pay-button');
|
||||
if (invoice.remainingAmount <= 0) {
|
||||
payButton.innerHTML = '<i class="fas fa-check-circle"></i> Đã hoàn tất';
|
||||
payButton.className = 'btn btn-success';
|
||||
payButton.style.background = '#10b981';
|
||||
payButton.disabled = true;
|
||||
}
|
||||
|
||||
// Update page title
|
||||
document.title = `${invoice.id} - Chi tiết Hóa đơn`;
|
||||
}
|
||||
|
||||
function updateProductsList(products) {
|
||||
const productsList = document.getElementById('products-list');
|
||||
|
||||
if (!products || products.length === 0) {
|
||||
productsList.innerHTML = '<p style="text-align: center; color: #6b7280;">Không có sản phẩm</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
productsList.innerHTML = products.map(product => `
|
||||
<div class="product-item">
|
||||
<div class="product-image">
|
||||
<i class="fas fa-image"></i>
|
||||
</div>
|
||||
<div class="product-info">
|
||||
<div class="product-name">${product.name}</div>
|
||||
<div class="product-sku">SKU: ${product.sku}</div>
|
||||
<div class="product-details">
|
||||
<span class="product-quantity">Số lượng: ${product.quantity} ${product.unit}</span>
|
||||
<span class="product-price">${formatCurrency(product.price)}/${product.unit}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function updatePaymentHistory(history) {
|
||||
const historyContainer = document.getElementById('payment-history');
|
||||
|
||||
if (!history || history.length === 0) {
|
||||
historyContainer.innerHTML = `
|
||||
<div class="empty-history">
|
||||
<i class="fas fa-receipt"></i>
|
||||
<h4>Chưa có lịch sử thanh toán</h4>
|
||||
<p>Hóa đơn này chưa được thanh toán</p>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
historyContainer.innerHTML = history.map((payment, index) => `
|
||||
<div class="history-item">
|
||||
<div class="history-icon">
|
||||
<i class="fas fa-check"></i>
|
||||
</div>
|
||||
<div class="history-content">
|
||||
<div class="history-title">${payment.title}</div>
|
||||
<div class="history-details">${payment.method} | Ref: ${payment.reference}</div>
|
||||
<div class="history-date">${payment.date} - ${payment.time}</div>
|
||||
</div>
|
||||
<div class="history-amount">${formatCurrency(payment.amount)}</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function makePayment() {
|
||||
// In real app, open payment modal or navigate to payment gateway
|
||||
alert('Mở cổng thanh toán...\n\nTrong ứng dụng thực tế, đây sẽ chuyển đến trang thanh toán hoặc mở ví điện tử.');
|
||||
}
|
||||
|
||||
function contactSupport() {
|
||||
// Navigate to support chat
|
||||
if (confirm('Liên hệ hỗ trợ về hóa đơn này?')) {
|
||||
window.location.href = 'chat-list.html';
|
||||
}
|
||||
}
|
||||
|
||||
function downloadPDF(type) {
|
||||
const invoiceId = document.getElementById('invoice-id').textContent.replace('#', '');
|
||||
|
||||
// Simulate PDF download
|
||||
const filename = type === 'invoice' ? `Hoa-don-${invoiceId}.pdf` : `Phieu-thu-${invoiceId}.pdf`;
|
||||
|
||||
// In real app, this would trigger actual PDF download
|
||||
alert(`Đang tải ${filename}...\n\nTrong ứng dụng thực tế, file PDF sẽ được tải về thiết bị.`);
|
||||
}
|
||||
|
||||
function shareInvoice() {
|
||||
const invoiceId = document.getElementById('invoice-id').textContent;
|
||||
|
||||
if (navigator.share) {
|
||||
navigator.share({
|
||||
title: `Hóa đơn ${invoiceId}`,
|
||||
text: `Chi tiết hóa đơn ${invoiceId}`,
|
||||
url: window.location.href
|
||||
}).catch(console.error);
|
||||
} else {
|
||||
// Fallback: copy URL to clipboard
|
||||
navigator.clipboard.writeText(window.location.href).then(() => {
|
||||
showToast('Đã sao chép link chia sẻ!');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function showToast(message) {
|
||||
const toast = document.createElement('div');
|
||||
toast.className = 'fixed top-20 left-1/2 transform -translate-x-1/2 bg-green-500 text-white px-4 py-2 rounded-lg z-50 transition-all duration-300';
|
||||
toast.textContent = message;
|
||||
document.body.appendChild(toast);
|
||||
|
||||
setTimeout(() => {
|
||||
toast.style.opacity = '0';
|
||||
setTimeout(() => {
|
||||
if (document.body.contains(toast)) {
|
||||
document.body.removeChild(toast);
|
||||
}
|
||||
}, 300);
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
function formatCurrency(amount) {
|
||||
return new Intl.NumberFormat('vi-VN', {
|
||||
style: 'currency',
|
||||
currency: 'VND',
|
||||
minimumFractionDigits: 0
|
||||
}).format(amount);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3,10 +3,267 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Danh sách thanh toán - EuroTile Worker</title>
|
||||
<title>Thanh toán - 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">
|
||||
<style>
|
||||
.payments-container {
|
||||
max-width: 480px;
|
||||
margin: 0 auto;
|
||||
background: #f8fafc;
|
||||
min-height: calc(100vh - 120px);
|
||||
}
|
||||
|
||||
.tab-filters {
|
||||
background: white;
|
||||
display: flex;
|
||||
position: sticky;
|
||||
top: 60px;
|
||||
z-index: 40;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.filter-tab {
|
||||
/*flex: 1;*/
|
||||
padding: 12px 8px;
|
||||
text-align: center;
|
||||
background: none;
|
||||
border: none;
|
||||
font-weight: 600;
|
||||
color: #64748b;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
border-bottom: 3px solid transparent;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.filter-tab.active {
|
||||
color: #2563eb;
|
||||
border-bottom-color: #2563eb;
|
||||
}
|
||||
|
||||
.payments-list {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.invoice-card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.invoice-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.12);
|
||||
}
|
||||
|
||||
.invoice-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.invoice-codes {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.invoice-id {
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.order-id {
|
||||
font-size: 14px;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.invoice-total {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.total-amount {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.invoice-details {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 8px 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
color: #1f2937;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.overdue {
|
||||
color: #dc2626 !important;
|
||||
}
|
||||
|
||||
.payment-summary {
|
||||
background: #f8fafc;
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.payment-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.payment-row:last-child {
|
||||
margin-bottom: 0;
|
||||
padding-top: 8px;
|
||||
border-top: 1px solid #e2e8f0;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.remaining-amount {
|
||||
color: #dc2626 !important;
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
|
||||
.invoice-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 8px 16px;
|
||||
border-radius: 6px;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
border: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.4);
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
background: #10b981;
|
||||
color: white;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
padding: 6px 12px;
|
||||
border-radius: 20px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.status-unpaid {
|
||||
background: #fef3c7;
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.status-overdue {
|
||||
background: #fee2e2;
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
.status-paid {
|
||||
background: #d1fae5;
|
||||
color: #065f46;
|
||||
}
|
||||
|
||||
.status-partial {
|
||||
background: #e0e7ff;
|
||||
color: #3730a3;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.empty-state i {
|
||||
font-size: 48px;
|
||||
margin-bottom: 20px;
|
||||
color: #d1d5db;
|
||||
}
|
||||
|
||||
.empty-state h3 {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #374151;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.empty-state p {
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.payments-list {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.invoice-card {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.invoice-details {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.invoice-actions {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.btn {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-wrapper">
|
||||
@@ -15,132 +272,362 @@
|
||||
<a href="index.html" class="back-button">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Danh sách thanh toán</h1>
|
||||
<button class="back-button">
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
<h1 class="header-title">Thanh toán</h1>
|
||||
<div style="width: 32px;"></div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<!-- Search Bar -->
|
||||
<div class="search-bar">
|
||||
<i class="fas fa-search search-icon"></i>
|
||||
<input type="text" class="search-input" placeholder="Mã phiếu thanh toán">
|
||||
</div>
|
||||
|
||||
<!-- Filter Section -->
|
||||
<div class="card mb-3">
|
||||
<div class="d-flex justify-between align-center">
|
||||
<h3 class="card-title">Bộ lọc</h3>
|
||||
<i class="fas fa-filter" style="color: var(--primary-blue);"></i>
|
||||
</div>
|
||||
<div class="payments-container">
|
||||
<!-- Filter Pills -->
|
||||
<!--<div class="filter-container">
|
||||
<button class="filter-pill active" onclick="filterInvoices('all')">>Tất cả</button>
|
||||
<button class="filter-pill" onclick="filterInvoices('unpaid')">Chưa thanh toán</button>
|
||||
<button class="filter-pill" onclick="filterInvoices('overdue')">Quá hạn</button>
|
||||
<button class="filter-pill" onclick="filterInvoices('paid')">Đã thanh toán</button>
|
||||
</div>-->
|
||||
<!-- Tab Filters -->
|
||||
<div class="tab-filters">
|
||||
<button class="filter-tab active" onclick="filterInvoices('all')">
|
||||
Tất cả
|
||||
</button>
|
||||
<button class="filter-tab" onclick="filterInvoices('unpaid')">
|
||||
Chưa thanh toán
|
||||
</button>
|
||||
<button class="filter-tab" onclick="filterInvoices('overdue')">
|
||||
Quá hạn
|
||||
</button>
|
||||
<button class="filter-tab" onclick="filterInvoices('paid')">
|
||||
Đã thanh toán
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Payments List -->
|
||||
<div class="payments-list">
|
||||
<!-- Payment Item 1 - Processing -->
|
||||
<div class="payment-card processing">
|
||||
<div class="payment-status-indicator"></div>
|
||||
<div class="payment-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
<h4 class="payment-id">#212221</h4>
|
||||
<span class="payment-amount">12.900.000 VND</span>
|
||||
<div class="payments-list" id="payments-list">
|
||||
<!-- Invoice Card 1 - Overdue -->
|
||||
<div class="invoice-card" data-status="overdue" onclick="viewInvoiceDetail('INV001')">
|
||||
<div class="invoice-header">
|
||||
<div class="invoice-codes">
|
||||
<span class="invoice-id">Mã hóa đơn: #INV001</span>
|
||||
<span class="order-id">Đơn hàng: #SO001</span>
|
||||
</div>
|
||||
|
||||
<div class="payment-details">
|
||||
<p class="payment-time">Thời gian: 03/08/2023</p>
|
||||
<p class="payment-status-text">
|
||||
<span class="status-badge processing">Đang xử lý</span>
|
||||
</p>
|
||||
<p class="payment-store">Cửa hàng: CH Thủ Đức</p>
|
||||
<p class="payment-note">Ghi chú: 21347 TT Đơn hàng 54970</p>
|
||||
<span class="status-badge status-overdue">Quá hạn</span>
|
||||
</div>
|
||||
|
||||
<div class="invoice-details">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Ngày đặt:</span>
|
||||
<span class="detail-value">15/10/2024</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Hạn TT:</span>
|
||||
<span class="detail-value overdue">30/10/2024</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="payment-summary">
|
||||
<div class="payment-row">
|
||||
<span>Tổng tiền:</span>
|
||||
<span>85.000.000đ</span>
|
||||
</div>
|
||||
<div class="payment-row">
|
||||
<span>Đã thanh toán:</span>
|
||||
<span>25.000.000đ</span>
|
||||
</div>
|
||||
<div class="payment-row">
|
||||
<span>Còn lại:</span>
|
||||
<span class="remaining-amount">60.000.000đ</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="invoice-actions">
|
||||
<button class="btn btn-primary" onclick="event.stopPropagation(); payInvoice('INV001')">
|
||||
<i class="fas fa-credit-card"></i>
|
||||
Thanh toán
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Payment Item 2 - Completed -->
|
||||
<div class="payment-card completed">
|
||||
<div class="payment-status-indicator"></div>
|
||||
<div class="payment-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
<h4 class="payment-id">#212221</h4>
|
||||
<span class="payment-amount">12.900.000 VND</span>
|
||||
<!-- Invoice Card 2 - Unpaid -->
|
||||
<div class="invoice-card" data-status="unpaid" onclick="viewInvoiceDetail('INV002')">
|
||||
<div class="invoice-header">
|
||||
<div class="invoice-codes">
|
||||
<span class="invoice-id">Mã hóa đơn: #INV002</span>
|
||||
<span class="order-id">Đơn hàng: #SO002</span>
|
||||
</div>
|
||||
|
||||
<div class="payment-details">
|
||||
<p class="payment-time">Thời gian: 03/08/2023</p>
|
||||
<p class="payment-status-text">
|
||||
<span class="status-badge completed">Hoàn thành</span>
|
||||
</p>
|
||||
<p class="payment-store">Cửa hàng: CH Thủ Đức</p>
|
||||
<p class="payment-note">Ghi chú: 21347 TT Đơn hàng 54970</p>
|
||||
<span class="status-badge status-unpaid">Chưa thanh toán</span>
|
||||
</div>
|
||||
|
||||
<div class="invoice-details">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Ngày đặt:</span>
|
||||
<span class="detail-value">25/10/2024</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Hạn TT:</span>
|
||||
<span class="detail-value">09/11/2024</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="payment-summary">
|
||||
<div class="payment-row">
|
||||
<span>Tổng tiền:</span>
|
||||
<span>42.500.000đ</span>
|
||||
</div>
|
||||
<div class="payment-row">
|
||||
<span>Đã thanh toán:</span>
|
||||
<span>0đ</span>
|
||||
</div>
|
||||
<div class="payment-row">
|
||||
<span>Còn lại:</span>
|
||||
<span class="remaining-amount">42.500.000đ</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="invoice-actions">
|
||||
<button class="btn btn-primary" onclick="event.stopPropagation(); payInvoice('INV002')">
|
||||
<i class="fas fa-credit-card"></i>
|
||||
Thanh toán
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Payment Item 3 - Processing -->
|
||||
<div class="payment-card processing">
|
||||
<div class="payment-status-indicator"></div>
|
||||
<div class="payment-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
<h4 class="payment-id">#212220</h4>
|
||||
<span class="payment-amount">8.500.000 VND</span>
|
||||
<!-- Invoice Card 3 - Partial Payment -->
|
||||
<div class="invoice-card" data-status="unpaid" onclick="viewInvoiceDetail('INV003')">
|
||||
<div class="invoice-header">
|
||||
<div class="invoice-codes">
|
||||
<span class="invoice-id">Mã hóa đơn: #INV003</span>
|
||||
<span class="order-id">Đơn hàng: #SO003</span>
|
||||
</div>
|
||||
|
||||
<div class="payment-details">
|
||||
<p class="payment-time">Thời gian: 02/08/2023</p>
|
||||
<p class="payment-status-text">
|
||||
<span class="status-badge processing">Đang xử lý</span>
|
||||
</p>
|
||||
<p class="payment-store">Cửa hàng: CH Bình Dương</p>
|
||||
<p class="payment-note">Ghi chú: 21346 TT Đơn hàng 54969</p>
|
||||
<span class="status-badge status-partial">Thanh toán 1 phần</span>
|
||||
</div>
|
||||
|
||||
<div class="invoice-details">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Ngày đặt:</span>
|
||||
<span class="detail-value">20/10/2024</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Hạn TT:</span>
|
||||
<span class="detail-value">04/11/2024</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="payment-summary">
|
||||
<div class="payment-row">
|
||||
<span>Tổng tiền:</span>
|
||||
<span>150.000.000đ</span>
|
||||
</div>
|
||||
<div class="payment-row">
|
||||
<span>Đã thanh toán:</span>
|
||||
<span>75.000.000đ</span>
|
||||
</div>
|
||||
<div class="payment-row">
|
||||
<span>Còn lại:</span>
|
||||
<span class="remaining-amount">75.000.000đ</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="invoice-actions">
|
||||
<button class="btn btn-primary" onclick="event.stopPropagation(); payInvoice('INV003')">
|
||||
<i class="fas fa-credit-card"></i>
|
||||
Thanh toán
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Payment Item 4 - Completed -->
|
||||
<div class="payment-card completed">
|
||||
<div class="payment-status-indicator"></div>
|
||||
<div class="payment-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
<h4 class="payment-id">#212219</h4>
|
||||
<span class="payment-amount">15.200.000 VND</span>
|
||||
<!-- Invoice Card 4 - Paid -->
|
||||
<div class="invoice-card" data-status="paid" onclick="viewInvoiceDetail('INV004')">
|
||||
<div class="invoice-header">
|
||||
<div class="invoice-codes">
|
||||
<span class="invoice-id">Mã hóa đơn: #INV004</span>
|
||||
<span class="order-id">Đơn hàng: #SO004</span>
|
||||
</div>
|
||||
|
||||
<div class="payment-details">
|
||||
<p class="payment-time">Thời gian: 01/08/2023</p>
|
||||
<p class="payment-status-text">
|
||||
<span class="status-badge completed">Hoàn thành</span>
|
||||
</p>
|
||||
<p class="payment-store">Cửa hàng: CH Thủ Đức</p>
|
||||
<p class="payment-note">Ghi chú: 21345 TT Đơn hàng 54968</p>
|
||||
<span class="status-badge status-paid">Đã hoàn tất</span>
|
||||
</div>
|
||||
|
||||
<div class="invoice-details">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Ngày đặt:</span>
|
||||
<span class="detail-value">10/10/2024</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Hạn TT:</span>
|
||||
<span class="detail-value">25/10/2024</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="payment-summary">
|
||||
<div class="payment-row">
|
||||
<span>Tổng tiền:</span>
|
||||
<span>32.800.000đ</span>
|
||||
</div>
|
||||
<div class="payment-row">
|
||||
<span>Đã thanh toán:</span>
|
||||
<span>32.800.000đ</span>
|
||||
</div>
|
||||
<div class="payment-row">
|
||||
<span>Còn lại:</span>
|
||||
<span>0đ</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="invoice-actions">
|
||||
<button class="btn btn-success">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
Đã hoàn tất
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Payment Item 5 - Processing -->
|
||||
<div class="payment-card processing">
|
||||
<div class="payment-status-indicator"></div>
|
||||
<div class="payment-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
<h4 class="payment-id">#212218</h4>
|
||||
<span class="payment-amount">6.750.000 VND</span>
|
||||
<!-- Invoice Card 5 - Overdue -->
|
||||
<div class="invoice-card" data-status="overdue" onclick="viewInvoiceDetail('INV005')">
|
||||
<div class="invoice-header">
|
||||
<div class="invoice-codes">
|
||||
<span class="invoice-id">Mã hóa đơn: #INV005</span>
|
||||
<span class="order-id">Đơn hàng: #SO005</span>
|
||||
</div>
|
||||
|
||||
<div class="payment-details">
|
||||
<p class="payment-time">Thời gian: 31/07/2023</p>
|
||||
<p class="payment-status-text">
|
||||
<span class="status-badge processing">Đang xử lý</span>
|
||||
</p>
|
||||
<p class="payment-store">Cửa hàng: CH Gò Vấp</p>
|
||||
<p class="payment-note">Ghi chú: 21344 TT Đơn hàng 54967</p>
|
||||
<span class="status-badge status-overdue">Quá hạn</span>
|
||||
</div>
|
||||
|
||||
<div class="invoice-details">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Ngày đặt:</span>
|
||||
<span class="detail-value">05/10/2024</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Hạn TT:</span>
|
||||
<span class="detail-value overdue">20/10/2024</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="payment-summary">
|
||||
<div class="payment-row">
|
||||
<span>Tổng tiền:</span>
|
||||
<span>95.300.000đ</span>
|
||||
</div>
|
||||
<div class="payment-row">
|
||||
<span>Đã thanh toán:</span>
|
||||
<span>0đ</span>
|
||||
</div>
|
||||
<div class="payment-row">
|
||||
<span>Còn lại:</span>
|
||||
<span class="remaining-amount">95.300.000đ</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="invoice-actions">
|
||||
<button class="btn btn-primary" onclick="event.stopPropagation(); payInvoice('INV005')">
|
||||
<i class="fas fa-credit-card"></i>
|
||||
Thanh toán
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function filterInvoices(status) {
|
||||
// Update active tab
|
||||
document.querySelectorAll('.filter-tab').forEach(tab => {
|
||||
tab.classList.remove('active');
|
||||
});
|
||||
event.target.classList.add('active');
|
||||
|
||||
// Filter invoice cards
|
||||
const cards = document.querySelectorAll('.invoice-card');
|
||||
cards.forEach(card => {
|
||||
const cardStatus = card.getAttribute('data-status');
|
||||
|
||||
if (status === 'all') {
|
||||
card.style.display = 'block';
|
||||
} else if (status === 'unpaid') {
|
||||
// Show cards that are not fully paid (unpaid, overdue, partial)
|
||||
card.style.display = cardStatus !== 'paid' ? 'block' : 'none';
|
||||
} else {
|
||||
card.style.display = cardStatus === status ? 'block' : 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// Show empty state if no results
|
||||
const visibleCards = Array.from(cards).filter(card => card.style.display !== 'none');
|
||||
if (visibleCards.length === 0) {
|
||||
showEmptyState(status);
|
||||
} else {
|
||||
hideEmptyState();
|
||||
}
|
||||
}
|
||||
|
||||
function showEmptyState(filterType) {
|
||||
const existingEmptyState = document.querySelector('.empty-state');
|
||||
if (existingEmptyState) {
|
||||
existingEmptyState.remove();
|
||||
}
|
||||
|
||||
const paymentsList = document.getElementById('payments-list');
|
||||
const emptyState = document.createElement('div');
|
||||
emptyState.className = 'empty-state';
|
||||
|
||||
let message = '';
|
||||
switch(filterType) {
|
||||
case 'unpaid':
|
||||
message = 'Không có hóa đơn chưa thanh toán';
|
||||
break;
|
||||
case 'overdue':
|
||||
message = 'Không có hóa đơn quá hạn';
|
||||
break;
|
||||
case 'paid':
|
||||
message = 'Không có hóa đơn đã thanh toán';
|
||||
break;
|
||||
default:
|
||||
message = 'Không có hóa đơn nào';
|
||||
}
|
||||
|
||||
emptyState.innerHTML = `
|
||||
<i class="fas fa-file-invoice"></i>
|
||||
<h3>${message}</h3>
|
||||
<p>Hiện tại không có hóa đơn nào trong danh mục này</p>
|
||||
`;
|
||||
|
||||
paymentsList.appendChild(emptyState);
|
||||
}
|
||||
|
||||
function hideEmptyState() {
|
||||
const existingEmptyState = document.querySelector('.empty-state');
|
||||
if (existingEmptyState) {
|
||||
existingEmptyState.remove();
|
||||
}
|
||||
}
|
||||
|
||||
function viewInvoiceDetail(invoiceId) {
|
||||
// Navigate to invoice detail page
|
||||
window.location.href = `payment-detail.html?id=${invoiceId}`;
|
||||
}
|
||||
|
||||
function payInvoice(invoiceId) {
|
||||
// In real app, open payment modal or navigate to payment page
|
||||
alert(`Mở trang thanh toán cho hóa đơn ${invoiceId}`);
|
||||
}
|
||||
|
||||
// Initialize page
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Set default filter to 'all'
|
||||
filterInvoices('all');
|
||||
|
||||
// Add animation to cards
|
||||
const cards = document.querySelectorAll('.invoice-card');
|
||||
cards.forEach((card, index) => {
|
||||
card.style.opacity = '0';
|
||||
card.style.transform = 'translateY(20px)';
|
||||
card.style.transition = 'all 0.5s ease';
|
||||
|
||||
setTimeout(() => {
|
||||
card.style.opacity = '1';
|
||||
card.style.transform = 'translateY(0)';
|
||||
}, index * 100);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
632
html/point-complaint.html
Normal file
632
html/point-complaint.html
Normal file
@@ -0,0 +1,632 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="vi">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Khiếu nại Giao dịch điểm - 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="points-history.html" class="back-button">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Khiếu nại Giao dịch điểm</h1>
|
||||
</div>
|
||||
|
||||
<div class="complaint-content">
|
||||
<!-- Transaction Info Card -->
|
||||
<div class="transaction-info-card">
|
||||
<h3><i class="fas fa-receipt"></i> Thông tin giao dịch</h3>
|
||||
<div class="transaction-details">
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">Mã giao dịch:</span>
|
||||
<span class="detail-value" id="transactionId">TXN123456</span>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">Loại giao dịch:</span>
|
||||
<span class="detail-value" id="transactionTitle">Mua hàng tại cửa hàng</span>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">Ngày giao dịch:</span>
|
||||
<span class="detail-value" id="transactionDate">22/09/2023 17:23:18</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Complaint Form -->
|
||||
<div class="complaint-form-card">
|
||||
<h3><i class="fas fa-edit"></i> Nội dung khiếu nại</h3>
|
||||
|
||||
<form id="complaintForm">
|
||||
<!-- Complaint Type -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Lý do khiếu nại *</label>
|
||||
<div class="complaint-types">
|
||||
<label class="complaint-type-option">
|
||||
<input type="radio" name="complaintType" value="incorrect-points" required>
|
||||
<span class="radio-custom"></span>
|
||||
<div class="option-content">
|
||||
<div class="option-title">Số điểm không chính xác</div>
|
||||
<div class="option-description">Số điểm được cộng/trừ không đúng</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="complaint-type-option">
|
||||
<input type="radio" name="complaintType" value="wrong-transaction" required>
|
||||
<span class="radio-custom"></span>
|
||||
<div class="option-content">
|
||||
<div class="option-title">Giao dịch không phải của tôi</div>
|
||||
<div class="option-description">Tôi không thực hiện giao dịch này</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="complaint-type-option">
|
||||
<input type="radio" name="complaintType" value="missing-points" required>
|
||||
<span class="radio-custom"></span>
|
||||
<div class="option-content">
|
||||
<div class="option-title">Thiếu điểm thưởng</div>
|
||||
<div class="option-description">Không nhận được điểm sau giao dịch</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="complaint-type-option">
|
||||
<input type="radio" name="complaintType" value="other" required>
|
||||
<span class="radio-custom"></span>
|
||||
<div class="option-content">
|
||||
<div class="option-title">Lý do khác</div>
|
||||
<div class="option-description">Vấn đề khác liên quan đến giao dịch</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Detailed Description -->
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="complaintContent">Mô tả chi tiết vấn đề *</label>
|
||||
<textarea
|
||||
id="complaintContent"
|
||||
class="form-textarea"
|
||||
rows="5"
|
||||
placeholder="Vui lòng mô tả chi tiết vấn đề bạn gặp phải với giao dịch này. Thông tin càng chi tiết sẽ giúp chúng tôi xử lý nhanh chóng hơn."
|
||||
required></textarea>
|
||||
<div class="form-help">Tối thiểu 20 ký tự</div>
|
||||
</div>
|
||||
|
||||
<!-- Evidence Upload -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Ảnh minh chứng (tùy chọn)</label>
|
||||
<div class="evidence-upload-section">
|
||||
<div class="upload-area" onclick="document.getElementById('evidenceFiles').click()">
|
||||
<div class="upload-placeholder">
|
||||
<i class="fas fa-camera"></i>
|
||||
<div class="upload-text">
|
||||
<div class="upload-title">Tải ảnh minh chứng</div>
|
||||
<div class="upload-subtitle">Hóa đơn, ảnh chụp màn hình...</div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="file" id="evidenceFiles" multiple accept="image/*" style="display: none;" onchange="handleFileUpload(this)">
|
||||
</div>
|
||||
<div class="uploaded-files" id="uploadedFiles"></div>
|
||||
</div>
|
||||
<div class="form-help">Tối đa 5 ảnh, mỗi ảnh không quá 10MB</div>
|
||||
</div>
|
||||
|
||||
<!-- Contact Info -->
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="contactPhone">Số điện thoại liên hệ</label>
|
||||
<input
|
||||
type="tel"
|
||||
id="contactPhone"
|
||||
class="form-input"
|
||||
placeholder="0901234567"
|
||||
value="0901234567">
|
||||
<div class="form-help">Để nhận thông báo kết quả xử lý</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Policy Notice -->
|
||||
<div class="policy-notice">
|
||||
<div class="notice-content">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
<div class="notice-text">
|
||||
<div class="notice-title">Lưu ý quan trọng</div>
|
||||
<ul class="notice-list">
|
||||
<li>Khiếu nại sẽ được xử lý trong vòng 3-5 ngày làm việc</li>
|
||||
<li>Vui lòng cung cấp thông tin chính xác và đầy đủ</li>
|
||||
<li>Chúng tôi có thể liên hệ để xác minh thông tin</li>
|
||||
<li>Kết quả sẽ được thông báo qua SMS và email</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<div class="submit-container">
|
||||
<button class="submit-btn" onclick="submitComplaint()">
|
||||
<i class="fas fa-paper-plane"></i>
|
||||
Gửi Khiếu nại
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.complaint-content {
|
||||
padding: 0 0 100px 0;
|
||||
}
|
||||
|
||||
/* Transaction Info Card */
|
||||
.transaction-info-card,
|
||||
.complaint-form-card {
|
||||
background: var(--white);
|
||||
margin: 16px;
|
||||
padding: 20px;
|
||||
border-radius: 12px;
|
||||
box-shadow: var(--shadow-light);
|
||||
}
|
||||
|
||||
.transaction-info-card h3,
|
||||
.complaint-form-card h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--text-dark);
|
||||
margin: 0 0 16px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.transaction-details {
|
||||
background: var(--background-gray);
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.detail-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.detail-row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
color: var(--text-light);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
font-weight: 600;
|
||||
color: var(--text-dark);
|
||||
text-align: right;
|
||||
flex: 1;
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
/* Complaint Types */
|
||||
.complaint-types {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.complaint-type-option {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
padding: 16px;
|
||||
border: 2px solid var(--border-color);
|
||||
border-radius: 12px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.complaint-type-option:hover {
|
||||
border-color: var(--primary-blue);
|
||||
background: var(--background-gray);
|
||||
}
|
||||
|
||||
.complaint-type-option input[type="radio"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.radio-custom {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid var(--border-color);
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
margin-top: 2px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.complaint-type-option input[type="radio"]:checked + .radio-custom {
|
||||
border-color: var(--primary-blue);
|
||||
}
|
||||
|
||||
.complaint-type-option input[type="radio"]:checked + .radio-custom::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: var(--primary-blue);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.option-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.option-title {
|
||||
font-weight: 600;
|
||||
color: var(--text-dark);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.option-description {
|
||||
font-size: 13px;
|
||||
color: var(--text-light);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* Evidence Upload */
|
||||
.evidence-upload-section {
|
||||
border: 2px dashed var(--border-color);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.upload-area {
|
||||
padding: 24px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.upload-area:hover {
|
||||
background: var(--background-gray);
|
||||
border-color: var(--primary-blue);
|
||||
}
|
||||
|
||||
.upload-placeholder {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.upload-placeholder i {
|
||||
font-size: 32px;
|
||||
color: var(--primary-blue);
|
||||
}
|
||||
|
||||
.upload-title {
|
||||
font-weight: 600;
|
||||
color: var(--text-dark);
|
||||
}
|
||||
|
||||
.upload-subtitle {
|
||||
font-size: 13px;
|
||||
color: var(--text-light);
|
||||
}
|
||||
|
||||
.uploaded-files {
|
||||
border-top: 1px solid var(--border-color);
|
||||
background: var(--background-gray);
|
||||
}
|
||||
|
||||
.uploaded-file {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.uploaded-file:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.file-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.file-thumbnail {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 6px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
font-weight: 500;
|
||||
color: var(--text-dark);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.file-size {
|
||||
font-size: 12px;
|
||||
color: var(--text-light);
|
||||
}
|
||||
|
||||
.file-remove {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: none;
|
||||
background: var(--danger-color);
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.file-remove:hover {
|
||||
background: #c62828;
|
||||
}
|
||||
|
||||
/* Policy Notice */
|
||||
.policy-notice {
|
||||
background: linear-gradient(135deg, #fff3e0, #ffeaa7);
|
||||
border: 1px solid #ffb74d;
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
margin: 16px;
|
||||
}
|
||||
|
||||
.notice-content {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.notice-content i {
|
||||
color: #f57c00;
|
||||
font-size: 20px;
|
||||
flex-shrink: 0;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.notice-title {
|
||||
font-weight: 600;
|
||||
color: #e65100;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.notice-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.notice-list li {
|
||||
font-size: 13px;
|
||||
color: #bf360c;
|
||||
margin-bottom: 4px;
|
||||
padding-left: 16px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.notice-list li::before {
|
||||
content: '•';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: #f57c00;
|
||||
}
|
||||
|
||||
/* Submit Container */
|
||||
.submit-container {
|
||||
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;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
background: var(--primary-blue);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
padding: 14px 20px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.submit-btn:hover {
|
||||
background: var(--light-blue);
|
||||
}
|
||||
|
||||
.submit-btn:disabled {
|
||||
background: var(--text-light);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Mobile Responsiveness */
|
||||
@media (max-width: 480px) {
|
||||
.transaction-info-card,
|
||||
.complaint-form-card,
|
||||
.policy-notice {
|
||||
margin: 12px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.detail-row {
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
text-align: left;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.complaint-type-option {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.upload-placeholder i {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
let uploadedFiles = [];
|
||||
|
||||
// Initialize page with transaction details from URL
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const transactionId = urlParams.get('id') || 'TXN123456';
|
||||
const transactionTitle = urlParams.get('title') || 'Mua hàng tại cửa hàng';
|
||||
const transactionDate = urlParams.get('date') || '22/09/2023 17:23:18';
|
||||
|
||||
document.getElementById('transactionId').textContent = transactionId;
|
||||
document.getElementById('transactionTitle').textContent = transactionTitle;
|
||||
document.getElementById('transactionDate').textContent = transactionDate;
|
||||
|
||||
// Update page title
|
||||
document.title = `Khiếu nại ${transactionId} - EuroTile Worker`;
|
||||
});
|
||||
|
||||
function handleFileUpload(input) {
|
||||
const files = Array.from(input.files);
|
||||
|
||||
files.forEach(file => {
|
||||
if (uploadedFiles.length >= 5) {
|
||||
alert('Tối đa 5 ảnh được phép tải lên');
|
||||
return;
|
||||
}
|
||||
|
||||
if (file.size > 10 * 1024 * 1024) {
|
||||
alert(`File ${file.name} quá lớn. Vui lòng chọn file nhỏ hơn 10MB.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!file.type.startsWith('image/')) {
|
||||
alert(`File ${file.name} không phải là ảnh hợp lệ.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const fileData = {
|
||||
id: Date.now() + Math.random(),
|
||||
file: file,
|
||||
name: file.name,
|
||||
size: formatFileSize(file.size),
|
||||
thumbnail: URL.createObjectURL(file)
|
||||
};
|
||||
|
||||
uploadedFiles.push(fileData);
|
||||
renderUploadedFiles();
|
||||
});
|
||||
|
||||
// Clear input
|
||||
input.value = '';
|
||||
}
|
||||
|
||||
function renderUploadedFiles() {
|
||||
const container = document.getElementById('uploadedFiles');
|
||||
|
||||
if (uploadedFiles.length === 0) {
|
||||
container.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
const filesHtml = uploadedFiles.map(file => `
|
||||
<div class="uploaded-file">
|
||||
<div class="file-info">
|
||||
<img src="${file.thumbnail}" alt="${file.name}" class="file-thumbnail">
|
||||
<div>
|
||||
<div class="file-name">${file.name}</div>
|
||||
<div class="file-size">${file.size}</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="file-remove" onclick="removeFile(${file.id})">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
container.innerHTML = filesHtml;
|
||||
}
|
||||
|
||||
function removeFile(fileId) {
|
||||
const fileIndex = uploadedFiles.findIndex(f => f.id === fileId);
|
||||
if (fileIndex > -1) {
|
||||
URL.revokeObjectURL(uploadedFiles[fileIndex].thumbnail);
|
||||
uploadedFiles.splice(fileIndex, 1);
|
||||
renderUploadedFiles();
|
||||
}
|
||||
}
|
||||
|
||||
function formatFileSize(bytes) {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
const k = 1024;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
function submitComplaint() {
|
||||
// Validate form
|
||||
const form = document.getElementById('complaintForm');
|
||||
if (!form.checkValidity()) {
|
||||
form.reportValidity();
|
||||
return;
|
||||
}
|
||||
|
||||
const complaintContent = document.getElementById('complaintContent').value.trim();
|
||||
if (complaintContent.length < 20) {
|
||||
alert('Vui lòng mô tả chi tiết hơn (tối thiểu 20 ký tự)');
|
||||
document.getElementById('complaintContent').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get form data
|
||||
const formData = new FormData(form);
|
||||
const complaintType = formData.get('complaintType');
|
||||
const contactPhone = document.getElementById('contactPhone').value;
|
||||
|
||||
// Show loading state
|
||||
const submitBtn = document.querySelector('.submit-btn');
|
||||
const originalContent = submitBtn.innerHTML;
|
||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Đang gửi...';
|
||||
submitBtn.disabled = true;
|
||||
|
||||
// Simulate API call
|
||||
setTimeout(() => {
|
||||
alert('Khiếu nại đã được gửi thành công!\\n\\nMã khiếu nại: KN' + Date.now() + '\\nChúng tôi sẽ xử lý và phản hồi trong vòng 3-5 ngày làm việc.\\n\\nThông báo kết quả sẽ được gửi qua SMS: ' + contactPhone);
|
||||
|
||||
// Navigate back to points history
|
||||
window.location.href = 'points-history.html';
|
||||
}, 2000);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -47,7 +47,7 @@
|
||||
Giao dịch: 100.000.000 VND
|
||||
</p>
|
||||
</div>
|
||||
<button class="btn-complaint">
|
||||
<button class="btn-complaint" onclick="openComplaint(this)">
|
||||
Khiếu nại
|
||||
</button>
|
||||
</div>
|
||||
@@ -74,7 +74,7 @@
|
||||
Giao dịch: 200.000.000 VND
|
||||
</p>
|
||||
</div>
|
||||
<button class="btn-complaint">
|
||||
<button class="btn-complaint" onclick="openComplaint(this)">
|
||||
Khiếu nại
|
||||
</button>
|
||||
</div>
|
||||
@@ -98,7 +98,7 @@
|
||||
Thời gian: 20/09/2023 17:23:18
|
||||
</p>
|
||||
</div>
|
||||
<button class="btn-complaint">
|
||||
<button class="btn-complaint" onclick="openComplaint(this)">
|
||||
Khiếu nại
|
||||
</button>
|
||||
</div>
|
||||
@@ -122,7 +122,7 @@
|
||||
Thời gian: 19/09/2023 17:23:18
|
||||
</p>
|
||||
</div>
|
||||
<button class="btn-complaint">
|
||||
<button class="btn-complaint" onclick="openComplaint(this)">
|
||||
Khiếu nại
|
||||
</button>
|
||||
</div>
|
||||
@@ -146,7 +146,7 @@
|
||||
Thời gian: 10/09/2023 17:23:18
|
||||
</p>
|
||||
</div>
|
||||
<button class="btn-complaint">
|
||||
<button class="btn-complaint" onclick="openComplaint(this)">
|
||||
Khiếu nại
|
||||
</button>
|
||||
</div>
|
||||
@@ -170,7 +170,7 @@
|
||||
Thời gian: 19/09/2023 17:23:18
|
||||
</p>
|
||||
</div>
|
||||
<button class="btn-complaint">
|
||||
<button class="btn-complaint" onclick="openComplaint(this)">
|
||||
Khiếu nại
|
||||
</button>
|
||||
</div>
|
||||
@@ -185,5 +185,26 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function openComplaint(buttonElement) {
|
||||
// Get transaction info from the card
|
||||
const card = buttonElement.closest('.card');
|
||||
const transactionTitle = card.querySelector('h4').textContent.trim();
|
||||
const transactionDate = card.querySelector('.text-muted').textContent.replace('Thời gian: ', '').trim();
|
||||
|
||||
// Generate a transaction ID (in real app this would be from data attributes)
|
||||
const transactionId = 'TXN' + Math.floor(Math.random() * 1000000);
|
||||
|
||||
// Navigate to complaint page with transaction details
|
||||
const params = new URLSearchParams({
|
||||
id: transactionId,
|
||||
title: transactionTitle,
|
||||
date: transactionDate
|
||||
});
|
||||
|
||||
window.location.href = `point-complaint.html?${params.toString()}`;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -370,7 +370,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Store Location -->
|
||||
<div class="form-group">
|
||||
<!--<div class="form-group">
|
||||
<label class="form-label required">Cửa hàng mua</label>
|
||||
<select class="form-input form-select" id="storeLocation" required onchange="validateForm()">
|
||||
<option value="">Chọn cửa hàng</option>
|
||||
@@ -383,7 +383,7 @@
|
||||
<option value="danang-haichau">Đà Nẵng - Hải Châu</option>
|
||||
<option value="other">Cửa hàng khác</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>-->
|
||||
|
||||
<!-- Other Store -->
|
||||
<div class="form-group" id="otherStoreGroup" style="display: none;">
|
||||
|
||||
1195
html/product-detail.html
Normal file
1195
html/product-detail.html
Normal file
File diff suppressed because it is too large
Load Diff
537
html/product-view-360.html
Normal file
537
html/product-view-360.html
Normal file
@@ -0,0 +1,537 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="vi">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Xem 360° - Gạch Eurotile MỘC LAM E03 - 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="product-detail.html" class="back-button">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Xem 360° - Gạch Eurotile MỘC LAM E03</h1>
|
||||
<div class="header-actions">
|
||||
<button class="header-action-btn" onclick="shareProduct360()">
|
||||
<i class="fas fa-share"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="view-360-content">
|
||||
<!-- 360° Viewer Container -->
|
||||
<div class="viewer-360-container">
|
||||
<!-- Placeholder Image -->
|
||||
<div class="viewer-360-main">
|
||||
<!--<img id="product360Image"
|
||||
src="https://placehold.co/600x600/F5F5F5/005B9A/png?text=Gạch+Eurotile+MỘC+LAM+E03+360°"
|
||||
alt="Gạch Eurotile MỘC LAM E03 - Xem 360°">-->
|
||||
|
||||
<!-- Nhúng link VR360 -->
|
||||
<iframe
|
||||
src="https://design.eurotile.vn/pub/tool/panorama/show?obsPlanId=3FO3H1VE59R5&locale=en_US&_gl=1*1udzqeo*_gcl_au*MTI3NjIxMzY1NS4xNzU5NzE2Mjg5"
|
||||
width="100%"
|
||||
height="600"
|
||||
style="border: none; border-radius: 12px;"
|
||||
allowfullscreen>
|
||||
</iframe>
|
||||
|
||||
<!-- 360° Indicator -->
|
||||
<div class="rotation-indicator">
|
||||
<i class="fas fa-sync-alt"></i>
|
||||
<span>Vuốt để xoay 360°</span>
|
||||
</div>
|
||||
|
||||
<!-- Touch/Mouse Overlay -->
|
||||
<div class="viewer-overlay"
|
||||
ontouchstart="startRotation(event)"
|
||||
ontouchmove="rotateProduct(event)"
|
||||
ontouchend="endRotation()"
|
||||
onmousedown="startRotation(event)"
|
||||
onmousemove="rotateProduct(event)"
|
||||
onmouseup="endRotation()"
|
||||
onmouseleave="endRotation()">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Controls -->
|
||||
<div class="viewer-controls">
|
||||
<button class="control-btn" onclick="autoRotate()" id="autoRotateBtn">
|
||||
<i class="fas fa-play"></i>
|
||||
<span>Tự động xoay</span>
|
||||
</button>
|
||||
<button class="control-btn" onclick="resetView()">
|
||||
<i class="fas fa-redo"></i>
|
||||
<span>Đặt lại</span>
|
||||
</button>
|
||||
<button class="control-btn" onclick="toggleFullscreen()">
|
||||
<i class="fas fa-expand"></i>
|
||||
<span>Toàn màn hình</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Product Info Summary -->
|
||||
<div class="product-info-360">
|
||||
<div class="product-name-360">Gạch Eurotile MỘC LAM E03</div>
|
||||
<div class="product-price-360">
|
||||
<span class="price-current">285.000 VND/m²</span>
|
||||
<span class="price-original">320.000 VND/m²</span>
|
||||
</div>
|
||||
<div class="product-dimensions">Kích thước: 60cm x 60cm</div>
|
||||
</div>
|
||||
|
||||
<!-- Instructions -->
|
||||
<div class="instructions-card">
|
||||
<h3><i class="fas fa-info-circle"></i> Hướng dẫn sử dụng</h3>
|
||||
<ul>
|
||||
<li><i class="fas fa-hand-pointer"></i> Vuốt trái/phải để xoay sản phẩm 360°</li>
|
||||
<li><i class="fas fa-play"></i> Nhấn "Tự động xoay" để xem tự động</li>
|
||||
<li><i class="fas fa-expand"></i> Chế độ toàn màn hình để xem chi tiết hơn</li>
|
||||
<li><i class="fas fa-redo"></i> Đặt lại để quay về góc nhìn ban đầu</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Bar -->
|
||||
<div class="action-bar-360">
|
||||
<button class="btn-back" onclick="goBackToProduct()">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
Quay lại sản phẩm
|
||||
</button>
|
||||
<button class="btn-add-cart" onclick="addToCartFrom360()">
|
||||
<i class="fas fa-shopping-cart"></i>
|
||||
Thêm vào giỏ
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.view-360-content {
|
||||
padding: 0 0 100px 0;
|
||||
}
|
||||
|
||||
.viewer-360-container {
|
||||
background: var(--white);
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
border-radius: 0 0 16px 16px;
|
||||
box-shadow: var(--shadow-medium);
|
||||
}
|
||||
|
||||
.viewer-360-main {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
aspect-ratio: 1;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
background: #f8f9fa;
|
||||
}
|
||||
|
||||
.viewer-360-main img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.rotation-indicator {
|
||||
position: absolute;
|
||||
bottom: 12px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
color: white;
|
||||
padding: 8px 16px;
|
||||
border-radius: 20px;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
animation: fadeInOut 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.rotation-indicator i {
|
||||
animation: rotate 2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes fadeInOut {
|
||||
0%, 100% { opacity: 0.7; }
|
||||
50% { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.viewer-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
cursor: grab;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.viewer-overlay:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.viewer-controls {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
margin-top: 20px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.control-btn {
|
||||
background: var(--primary-blue);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
padding: 8px 16px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
transition: all 0.3s ease;
|
||||
min-width: 100px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.control-btn:hover {
|
||||
background: var(--light-blue);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.control-btn.active {
|
||||
background: var(--success-color);
|
||||
}
|
||||
|
||||
.product-info-360 {
|
||||
background: var(--white);
|
||||
margin: 16px;
|
||||
padding: 16px;
|
||||
border-radius: 12px;
|
||||
box-shadow: var(--shadow-light);
|
||||
}
|
||||
|
||||
.product-name-360 {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--text-dark);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.product-price-360 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.price-current {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: var(--danger-color);
|
||||
}
|
||||
|
||||
.price-original {
|
||||
font-size: 14px;
|
||||
color: var(--text-light);
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.product-dimensions {
|
||||
font-size: 14px;
|
||||
color: var(--text-light);
|
||||
}
|
||||
|
||||
.instructions-card {
|
||||
background: var(--white);
|
||||
margin: 16px;
|
||||
padding: 16px;
|
||||
border-radius: 12px;
|
||||
box-shadow: var(--shadow-light);
|
||||
}
|
||||
|
||||
.instructions-card h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--text-dark);
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.instructions-card ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.instructions-card li {
|
||||
font-size: 14px;
|
||||
color: var(--text-light);
|
||||
margin-bottom: 8px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.instructions-card li i {
|
||||
color: var(--primary-blue);
|
||||
margin-top: 2px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.action-bar-360 {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: var(--white);
|
||||
padding: 16px;
|
||||
box-shadow: 0 -4px 15px rgba(0, 0, 0, 0.1);
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.btn-back {
|
||||
flex: 1;
|
||||
background: var(--border-color);
|
||||
color: var(--text-dark);
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
padding: 12px 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-back:hover {
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
.btn-add-cart {
|
||||
flex: 2;
|
||||
background: var(--primary-blue);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
padding: 12px 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-add-cart:hover {
|
||||
background: var(--light-blue);
|
||||
}
|
||||
|
||||
/* Mobile Responsiveness */
|
||||
@media (max-width: 480px) {
|
||||
.viewer-360-container {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.viewer-controls {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.control-btn {
|
||||
font-size: 11px;
|
||||
padding: 6px 12px;
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.instructions-card {
|
||||
margin: 12px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.product-info-360 {
|
||||
margin: 12px;
|
||||
padding: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
let isRotating = false;
|
||||
let startX = 0;
|
||||
let currentRotation = 0;
|
||||
let autoRotateInterval = null;
|
||||
let isAutoRotating = false;
|
||||
|
||||
// Mock 360° images array (in a real app, these would be actual 360° view frames)
|
||||
const rotation360Images = [
|
||||
"https://placehold.co/600x600/F5F5F5/005B9A/png?text=Góc+0°",
|
||||
"https://placehold.co/600x600/F0F0F0/005B9A/png?text=Góc+45°",
|
||||
"https://placehold.co/600x600/EEEEEE/005B9A/png?text=Góc+90°",
|
||||
"https://placehold.co/600x600/EBEBEB/005B9A/png?text=Góc+135°",
|
||||
"https://placehold.co/600x600/E8E8E8/005B9A/png?text=Góc+180°",
|
||||
"https://placehold.co/600x600/E5E5E5/005B9A/png?text=Góc+225°",
|
||||
"https://placehold.co/600x600/E2E2E2/005B9A/png?text=Góc+270°",
|
||||
"https://placehold.co/600x600/DFDFDF/005B9A/png?text=Góc+315°"
|
||||
];
|
||||
|
||||
function startRotation(event) {
|
||||
isRotating = true;
|
||||
startX = event.type.includes('touch') ? event.touches[0].clientX : event.clientX;
|
||||
stopAutoRotate();
|
||||
}
|
||||
|
||||
function rotateProduct(event) {
|
||||
if (!isRotating) return;
|
||||
|
||||
event.preventDefault();
|
||||
const currentX = event.type.includes('touch') ? event.touches[0].clientX : event.clientX;
|
||||
const deltaX = currentX - startX;
|
||||
|
||||
// Calculate rotation based on movement
|
||||
const rotationSensitivity = 2;
|
||||
const newRotation = currentRotation + (deltaX / rotationSensitivity);
|
||||
|
||||
// Update image based on rotation
|
||||
const imageIndex = Math.floor((newRotation % 360) / 45) % rotation360Images.length;
|
||||
const normalizedIndex = imageIndex < 0 ? rotation360Images.length + imageIndex : imageIndex;
|
||||
|
||||
document.getElementById('product360Image').src = rotation360Images[normalizedIndex];
|
||||
|
||||
startX = currentX;
|
||||
currentRotation = newRotation;
|
||||
}
|
||||
|
||||
function endRotation() {
|
||||
isRotating = false;
|
||||
}
|
||||
|
||||
function autoRotate() {
|
||||
const btn = document.getElementById('autoRotateBtn');
|
||||
|
||||
if (isAutoRotating) {
|
||||
stopAutoRotate();
|
||||
} else {
|
||||
startAutoRotate();
|
||||
}
|
||||
}
|
||||
|
||||
function startAutoRotate() {
|
||||
isAutoRotating = true;
|
||||
const btn = document.getElementById('autoRotateBtn');
|
||||
btn.classList.add('active');
|
||||
btn.innerHTML = '<i class="fas fa-pause"></i><span>Dừng xoay</span>';
|
||||
|
||||
let imageIndex = 0;
|
||||
autoRotateInterval = setInterval(() => {
|
||||
document.getElementById('product360Image').src = rotation360Images[imageIndex];
|
||||
imageIndex = (imageIndex + 1) % rotation360Images.length;
|
||||
}, 500); // Change image every 500ms
|
||||
}
|
||||
|
||||
function stopAutoRotate() {
|
||||
if (autoRotateInterval) {
|
||||
clearInterval(autoRotateInterval);
|
||||
autoRotateInterval = null;
|
||||
}
|
||||
isAutoRotating = false;
|
||||
const btn = document.getElementById('autoRotateBtn');
|
||||
btn.classList.remove('active');
|
||||
btn.innerHTML = '<i class="fas fa-play"></i><span>Tự động xoay</span>';
|
||||
}
|
||||
|
||||
function resetView() {
|
||||
currentRotation = 0;
|
||||
document.getElementById('product360Image').src = rotation360Images[0];
|
||||
stopAutoRotate();
|
||||
}
|
||||
|
||||
function toggleFullscreen() {
|
||||
const element = document.querySelector('.viewer-360-container');
|
||||
|
||||
if (!document.fullscreenElement) {
|
||||
element.requestFullscreen().catch(err => {
|
||||
console.log('Fullscreen not supported:', err);
|
||||
// Fallback for mobile
|
||||
element.style.position = 'fixed';
|
||||
element.style.top = '0';
|
||||
element.style.left = '0';
|
||||
element.style.right = '0';
|
||||
element.style.bottom = '0';
|
||||
element.style.zIndex = '9999';
|
||||
element.style.background = '#000';
|
||||
});
|
||||
} else {
|
||||
document.exitFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
function shareProduct360() {
|
||||
if (navigator.share) {
|
||||
navigator.share({
|
||||
title: 'Xem 360° - Gạch Eurotile MỘC LAM E03',
|
||||
text: 'Xem sản phẩm gạch granite 360° này!',
|
||||
url: window.location.href
|
||||
});
|
||||
} else {
|
||||
navigator.clipboard.writeText(window.location.href);
|
||||
alert('Đã sao chép link xem 360°!');
|
||||
}
|
||||
}
|
||||
|
||||
function goBackToProduct() {
|
||||
window.location.href = 'product-detail.html';
|
||||
}
|
||||
|
||||
function addToCartFrom360() {
|
||||
alert('Đã thêm 1 m² gạch Eurotile MỘC LAM E03 vào giỏ hàng!');
|
||||
// In a real app, this would update the cart
|
||||
}
|
||||
|
||||
// Clean up intervals when page is unloaded
|
||||
window.addEventListener('beforeunload', () => {
|
||||
stopAutoRotate();
|
||||
});
|
||||
|
||||
// Handle fullscreen changes
|
||||
document.addEventListener('fullscreenchange', () => {
|
||||
const element = document.querySelector('.viewer-360-container');
|
||||
if (!document.fullscreenElement) {
|
||||
// Reset styles when exiting fullscreen
|
||||
element.style.position = '';
|
||||
element.style.top = '';
|
||||
element.style.left = '';
|
||||
element.style.right = '';
|
||||
element.style.bottom = '';
|
||||
element.style.zIndex = '';
|
||||
element.style.background = '';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
550
html/products-page-redesign.html
Normal file
550
html/products-page-redesign.html
Normal file
@@ -0,0 +1,550 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="vi">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Sản phẩm - EuroTile Worker</title>
|
||||
<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">
|
||||
<style>
|
||||
/* Custom styles for product cards */
|
||||
.product-card {
|
||||
background: var(--white);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-light);
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.product-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-medium);
|
||||
}
|
||||
|
||||
.product-image-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding-bottom: 100%; /* 1:1 Aspect Ratio */
|
||||
overflow: hidden;
|
||||
background: var(--background-gray);
|
||||
}
|
||||
|
||||
.product-image {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.product-card:hover .product-image {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.product-badge {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
padding: 4px 8px;
|
||||
background: var(--danger-color);
|
||||
color: var(--white);
|
||||
border-radius: 12px;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.product-info {
|
||||
padding: 12px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--text-dark);
|
||||
margin-bottom: 6px;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
line-height: 1.4;
|
||||
min-height: 40px;
|
||||
}
|
||||
|
||||
.product-price {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: var(--primary-blue);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.product-price-old {
|
||||
font-size: 13px;
|
||||
color: var(--text-light);
|
||||
text-decoration: line-through;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
/* Product Actions - Horizontal Layout */
|
||||
.product-actions {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.btn-360 {
|
||||
flex: 0 0 auto;
|
||||
padding: 8px 12px !important;
|
||||
background: var(--background-gray) !important;
|
||||
color: var(--text-dark) !important;
|
||||
border: 1px solid var(--border-color) !important;
|
||||
border-radius: 8px;
|
||||
font-size: 12px !important;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.btn-360:hover {
|
||||
background: var(--white) !important;
|
||||
border-color: var(--primary-blue) !important;
|
||||
color: var(--primary-blue) !important;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.btn-360 i {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.btn-add-cart {
|
||||
flex: 1;
|
||||
padding: 8px 12px !important;
|
||||
background: var(--primary-blue) !important;
|
||||
color: var(--white) !important;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 12px !important;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.btn-add-cart:hover {
|
||||
background: var(--light-blue) !important;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(0, 91, 154, 0.3);
|
||||
}
|
||||
|
||||
.btn-add-cart i {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Search Bar Enhancements */
|
||||
.search-bar {
|
||||
background: var(--white);
|
||||
border-radius: 12px;
|
||||
padding: 12px 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-shadow: var(--shadow-light);
|
||||
margin-bottom: 16px;
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-size: 14px;
|
||||
color: var(--text-dark);
|
||||
background: transparent;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
color: var(--primary-blue);
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
/* Filter Pills Enhancement */
|
||||
.filter-container {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
overflow-x: auto;
|
||||
padding: 4px 0;
|
||||
margin-bottom: 16px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.filter-pill {
|
||||
padding: 8px 16px;
|
||||
background: var(--white);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 20px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--text-dark);
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.filter-pill:hover {
|
||||
background: var(--background-gray);
|
||||
}
|
||||
|
||||
.filter-pill.active {
|
||||
background: var(--primary-blue);
|
||||
color: var(--white);
|
||||
border-color: var(--primary-blue);
|
||||
}
|
||||
|
||||
/* Product Grid */
|
||||
.product-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 12px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
/* Load More Button */
|
||||
.load-more-container {
|
||||
text-align: center;
|
||||
padding: 16px 0;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.btn-load-more {
|
||||
padding: 12px 32px;
|
||||
background: var(--white);
|
||||
color: var(--primary-blue);
|
||||
border: 2px solid var(--primary-blue);
|
||||
border-radius: 24px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.btn-load-more:hover {
|
||||
background: var(--primary-blue);
|
||||
color: var(--white);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-medium);
|
||||
}
|
||||
|
||||
/* Header Enhancement */
|
||||
.header {
|
||||
background: var(--white);
|
||||
padding: 16px;
|
||||
box-shadow: var(--shadow-light);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.cart-button {
|
||||
position: relative;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: var(--text-dark);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cart-badge {
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
right: -4px;
|
||||
background: var(--danger-color);
|
||||
color: var(--white);
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
padding: 2px 6px;
|
||||
border-radius: 10px;
|
||||
min-width: 18px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 360px) {
|
||||
.product-actions {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.btn-360 {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.product-grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-wrapper">
|
||||
<!-- Header -->
|
||||
<div class="header">
|
||||
<a href="index.html" class="back-button">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Sản phẩm</h1>
|
||||
<a href="cart.html" class="cart-button">
|
||||
<i class="fas fa-shopping-cart"></i>
|
||||
<span class="cart-badge">3</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<!-- Search Bar -->
|
||||
<div class="search-bar">
|
||||
<i class="fas fa-search search-icon"></i>
|
||||
<input type="text" class="search-input" placeholder="Tìm kiếm sản phẩm...">
|
||||
</div>
|
||||
|
||||
<!-- Filter Pills -->
|
||||
<div class="filter-container">
|
||||
<button class="filter-pill active" onclick="filterProducts('all')">Tất cả</button>
|
||||
<button class="filter-pill" onclick="filterProducts('floor')">Gạch lát nền</button>
|
||||
<button class="filter-pill" onclick="filterProducts('wall')">Gạch ốp tường</button>
|
||||
<button class="filter-pill" onclick="filterProducts('decorative')">Gạch trang trí</button>
|
||||
<button class="filter-pill" onclick="filterProducts('outdoor')">Gạch ngoài trời</button>
|
||||
<button class="filter-pill" onclick="filterProducts('accessories')">Phụ kiện</button>
|
||||
</div>
|
||||
|
||||
<!-- Product Grid -->
|
||||
<div class="product-grid">
|
||||
<!-- Product 1 -->
|
||||
<div class="product-card">
|
||||
<div class="product-image-container" onclick="window.location.href='product-detail.html'">
|
||||
<img src="https://images.unsplash.com/photo-1615971677499-5467cbab01c0?w=300&h=300&fit=crop" alt="Gạch men" class="product-image">
|
||||
<span class="product-badge">-10%</span>
|
||||
</div>
|
||||
<div class="product-info">
|
||||
<div class="product-name">Gạch men cao cấp 60x60</div>
|
||||
<div class="product-price">
|
||||
450.000đ/m²
|
||||
<span class="product-price-old">500.000đ</span>
|
||||
</div>
|
||||
<div class="product-actions">
|
||||
<button class="btn-360" onclick="event.stopPropagation(); view360('#')">
|
||||
<i class="fas fa-cube"></i>
|
||||
<span>360°</span>
|
||||
</button>
|
||||
<button class="btn-add-cart" onclick="event.stopPropagation(); addToCart('Product 1')">
|
||||
<i class="fas fa-cart-plus"></i>
|
||||
<span>Thêm vào giỏ</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Product 2 -->
|
||||
<div class="product-card">
|
||||
<div class="product-image-container" onclick="window.location.href='product-detail.html'">
|
||||
<img src="https://images.unsplash.com/photo-1565193566173-7a0ee3dbe261?w=300&h=300&fit=crop" alt="Gạch granite" class="product-image">
|
||||
</div>
|
||||
<div class="product-info">
|
||||
<div class="product-name">Gạch granite nhập khẩu</div>
|
||||
<div class="product-price">680.000đ/m²</div>
|
||||
<div class="product-actions">
|
||||
<button class="btn-360" onclick="event.stopPropagation(); view360('#')">
|
||||
<i class="fas fa-cube"></i>
|
||||
<span>360°</span>
|
||||
</button>
|
||||
<button class="btn-add-cart" onclick="event.stopPropagation(); addToCart('Product 2')">
|
||||
<i class="fas fa-cart-plus"></i>
|
||||
<span>Thêm vào giỏ</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Product 3 -->
|
||||
<div class="product-card">
|
||||
<div class="product-image-container" onclick="window.location.href='product-detail.html'">
|
||||
<img src="https://images.unsplash.com/photo-1600607687644-aac4c3eac7f4?w=300&h=300&fit=crop" alt="Gạch mosaic" class="product-image">
|
||||
<span class="product-badge">Mới</span>
|
||||
</div>
|
||||
<div class="product-info">
|
||||
<div class="product-name">Gạch mosaic trang trí</div>
|
||||
<div class="product-price">320.000đ/m²</div>
|
||||
<div class="product-actions">
|
||||
<button class="btn-360" onclick="event.stopPropagation(); view360('#')">
|
||||
<i class="fas fa-cube"></i>
|
||||
<span>360°</span>
|
||||
</button>
|
||||
<button class="btn-add-cart" onclick="event.stopPropagation(); addToCart('Product 3')">
|
||||
<i class="fas fa-cart-plus"></i>
|
||||
<span>Thêm vào giỏ</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Product 4 -->
|
||||
<div class="product-card">
|
||||
<div class="product-image-container" onclick="window.location.href='product-detail.html'">
|
||||
<img src="https://images.unsplash.com/photo-1600566753190-17f0baa2a6c3?w=300&h=300&fit=crop" alt="Gạch 3D" class="product-image">
|
||||
</div>
|
||||
<div class="product-info">
|
||||
<div class="product-name">Gạch 3D họa tiết độc đáo</div>
|
||||
<div class="product-price">750.000đ/m²</div>
|
||||
<div class="product-actions">
|
||||
<button class="btn-360" onclick="event.stopPropagation(); view360('#')">
|
||||
<i class="fas fa-cube"></i>
|
||||
<span>360°</span>
|
||||
</button>
|
||||
<button class="btn-add-cart" onclick="event.stopPropagation(); addToCart('Product 4')">
|
||||
<i class="fas fa-cart-plus"></i>
|
||||
<span>Thêm vào giỏ</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Product 5 -->
|
||||
<div class="product-card">
|
||||
<div class="product-image-container" onclick="window.location.href='product-detail.html'">
|
||||
<img src="https://images.unsplash.com/photo-1615874694520-474822394e73?w=300&h=300&fit=crop" alt="Gạch ceramic" class="product-image">
|
||||
<span class="product-badge">-15%</span>
|
||||
</div>
|
||||
<div class="product-info">
|
||||
<div class="product-name">Gạch ceramic chống trượt</div>
|
||||
<div class="product-price">
|
||||
380.000đ/m²
|
||||
<span class="product-price-old">447.000đ</span>
|
||||
</div>
|
||||
<div class="product-actions">
|
||||
<button class="btn-360" onclick="event.stopPropagation(); view360('#')">
|
||||
<i class="fas fa-cube"></i>
|
||||
<span>360°</span>
|
||||
</button>
|
||||
<button class="btn-add-cart" onclick="event.stopPropagation(); addToCart('Product 5')">
|
||||
<i class="fas fa-cart-plus"></i>
|
||||
<span>Thêm vào giỏ</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Product 6 -->
|
||||
<div class="product-card">
|
||||
<div class="product-image-container" onclick="window.location.href='product-detail.html'">
|
||||
<img src="https://images.unsplash.com/photo-1564013799919-ab600027ffc6?w=300&h=300&fit=crop" alt="Gạch terrazzo" class="product-image">
|
||||
</div>
|
||||
<div class="product-info">
|
||||
<div class="product-name">Gạch terrazzo đá mài cao cấp</div>
|
||||
<div class="product-price">890.000đ/m²</div>
|
||||
<div class="product-actions">
|
||||
<button class="btn-360" onclick="event.stopPropagation(); view360('#')">
|
||||
<i class="fas fa-cube"></i>
|
||||
<span>360°</span>
|
||||
</button>
|
||||
<button class="btn-add-cart" onclick="event.stopPropagation(); addToCart('Product 6')">
|
||||
<i class="fas fa-cart-plus"></i>
|
||||
<span>Thêm vào giỏ</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Load More -->
|
||||
<div class="load-more-container">
|
||||
<button class="btn-load-more" onclick="loadMore()">
|
||||
<i class="fas fa-sync-alt"></i>
|
||||
<span>Tải thêm sản phẩm</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// View 360 function
|
||||
function view360(url) {
|
||||
console.log('Opening 360 view:', url);
|
||||
// In real app, this would open 360 view modal or page
|
||||
alert('Xem sản phẩm 360°');
|
||||
}
|
||||
|
||||
// Add to cart function
|
||||
function addToCart(productName) {
|
||||
console.log('Adding to cart:', productName);
|
||||
// Update cart badge
|
||||
const badge = document.querySelector('.cart-badge');
|
||||
const currentCount = parseInt(badge.textContent);
|
||||
badge.textContent = currentCount + 1;
|
||||
|
||||
// Show feedback
|
||||
alert('Đã thêm sản phẩm vào giỏ hàng!');
|
||||
}
|
||||
|
||||
// Filter products
|
||||
function filterProducts(category) {
|
||||
// Update active pill
|
||||
document.querySelectorAll('.filter-pill').forEach(pill => {
|
||||
pill.classList.remove('active');
|
||||
});
|
||||
event.target.classList.add('active');
|
||||
|
||||
// In real app, this would filter the product grid
|
||||
console.log('Filtering by:', category);
|
||||
}
|
||||
|
||||
// Load more products
|
||||
function loadMore() {
|
||||
console.log('Loading more products...');
|
||||
// In real app, this would load additional products
|
||||
alert('Đang tải thêm sản phẩm...');
|
||||
}
|
||||
|
||||
// Search functionality
|
||||
document.querySelector('.search-input').addEventListener('input', function(e) {
|
||||
const searchTerm = e.target.value.toLowerCase();
|
||||
console.log('Searching for:', searchTerm);
|
||||
// In real app, this would filter products based on search
|
||||
});
|
||||
|
||||
// Prevent card click when clicking buttons
|
||||
document.querySelectorAll('.product-actions button').forEach(button => {
|
||||
button.addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -43,13 +43,21 @@
|
||||
<div class="product-grid">
|
||||
<!-- Product 1 -->
|
||||
<div class="product-card">
|
||||
<img src="https://images.unsplash.com/photo-1615971677499-5467cbab01c0?w=300&h=300&fit=crop" alt="Gạch men" class="product-image">
|
||||
<img src="https://www.eurotile.vn/pictures/catalog/product/0-gachkholon/cat-tuong/CAT-S01G-1.jpg" alt="Gạch men" class="product-image" onclick="window.location.href='product-detail.html'">
|
||||
<div class="product-info">
|
||||
<div class="product-name">Gạch men cao cấp 60x60</div>
|
||||
<div class="product-name" onclick="window.location.href='product-detail.html'">Gạch Cát Tường 1200x1200</div>
|
||||
<div class="product-price">450.000đ/m²</div>
|
||||
<button class="btn btn-primary btn-sm btn-block">
|
||||
<div class="product-actions">
|
||||
<button class="btn btn-primary btn-sm btn-add-cart">
|
||||
<i class="fas fa-cart-plus"></i> Thêm vào giỏ
|
||||
</button>
|
||||
<button class="btn btn-secondary btn-sm btn-360" onclick="window.location.href='https://design.eurotile.vn/pub/tool/panorama/show?obsPlanId=3FO3H1VE59R5&locale=en_US&_gl=1*1udzqeo*_gcl_au*MTI3NjIxMzY1NS4xNzU5NzE2Mjg5'">
|
||||
<i class="fas fa-cube"></i> Phối cảnh 360°
|
||||
</button>
|
||||
</div>
|
||||
<!--<button class="btn btn-primary btn-sm btn-block">
|
||||
<i class="fas fa-cart-plus"></i> Thêm vào giỏ
|
||||
</button>
|
||||
</button>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -62,18 +70,25 @@
|
||||
<button class="btn btn-primary btn-sm btn-block">
|
||||
<i class="fas fa-cart-plus"></i> Thêm vào giỏ
|
||||
</button>
|
||||
<button class="btn btn-secondary btn-sm btn-360" onclick="window.location.href='https://design.eurotile.vn/pub/tool/panorama/show?obsPlanId=3FO3H1VE59R&locale=en_US&_gl=1*1udzqeo*_gcl_au*MTI3NjIxMzY1NS4xNzU5NzE2Mjg5'">
|
||||
<i class="fas fa-cube"></i> Phối cảnh 360°
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Product 3 -->
|
||||
<div class="product-card">
|
||||
<img src="https://images.unsplash.com/photo-1600607687644-aac4c3eac7f4?w=300&h=300&fit=crop" alt="Gạch mosaic" class="product-image">
|
||||
<img src="https://images.unsplash.com/photo-1615971677499-5467cbab01c0?w=300&h=300&fit=crop" alt="Gạch mosaic" class="product-image">
|
||||
<div class="product-info">
|
||||
<div class="product-name">Gạch mosaic trang trí</div>
|
||||
<div class="product-price">320.000đ/m²</div>
|
||||
<button class="btn btn-primary btn-sm btn-block">
|
||||
<i class="fas fa-cart-plus"></i> Thêm vào giỏ
|
||||
</button>
|
||||
<button class="btn btn-secondary btn-sm btn-360" onclick="window.location.href='https://design.eurotile.vn/pub/tool/panorama/show?obsPlanId=3FO3H1VE59R5&locale=en_US&_gl=1*1udzqeo*_gcl_au*MTI3NjIxMzY1NS4xNzU5NzE2Mjg5'">
|
||||
<i class="fas fa-cube"></i> Phối cảnh 360°
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -86,6 +101,9 @@
|
||||
<button class="btn btn-primary btn-sm btn-block">
|
||||
<i class="fas fa-cart-plus"></i> Thêm vào giỏ
|
||||
</button>
|
||||
<button class="btn btn-secondary btn-sm btn-360" onclick="window.location.href='https://design.eurotile.vn/pub/tool/panorama/show?obsPlanId=3FO3H1VE59R5&locale=en_US&_gl=1*1udzqeo*_gcl_au*MTI3NjIxMzY1NS4xNzU5NzE2Mjg5'">
|
||||
<i class="fas fa-cube"></i> Phối cảnh 360°
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -98,6 +116,9 @@
|
||||
<button class="btn btn-primary btn-sm btn-block">
|
||||
<i class="fas fa-cart-plus"></i> Thêm vào giỏ
|
||||
</button>
|
||||
<button class="btn btn-secondary btn-sm btn-360" onclick="window.location.href='https://design.eurotile.vn/pub/tool/panorama/show?obsPlanId=3FO3H1VE59R5&locale=en_US&_gl=1*1udzqeo*_gcl_au*MTI3NjIxMzY1NS4xNzU5NzE2Mjg5'">
|
||||
<i class="fas fa-cube"></i> Phối cảnh 360°
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
289
html/project-submission-list.html
Normal file
289
html/project-submission-list.html
Normal file
@@ -0,0 +1,289 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="vi">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Danh sách Dự án - 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="index.html" class="back-button">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Danh sách Dự án</h1>
|
||||
<button class="back-button" onclick="createNewProject()">
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<!-- Search Bar -->
|
||||
<div class="search-bar">
|
||||
<i class="fas fa-search search-icon"></i>
|
||||
<input type="text" class="search-input" placeholder="Mã dự án hoặc tên dự án" id="searchInput" onkeyup="filterProjects()">
|
||||
</div>
|
||||
|
||||
<!-- Status Filters -->
|
||||
<div class="tab-nav mb-3">
|
||||
<button class="tab-item active" data-status="">Tất cả</button>
|
||||
<button class="tab-item" data-status="pending">Chờ duyệt</button>
|
||||
<button class="tab-item" data-status="approved">Đã duyệt</button>
|
||||
<button class="tab-item" data-status="rejected">Bị từ chối</button>
|
||||
</div>
|
||||
|
||||
<!-- Projects List -->
|
||||
<div class="orders-list" id="projectsList">
|
||||
<!-- Projects will be populated by JavaScript -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom Navigation -->
|
||||
<div class="bottom-nav">
|
||||
<a href="index.html" class="nav-item">
|
||||
<i class="fas fa-home"></i>
|
||||
<span>Trang chủ</span>
|
||||
</a>
|
||||
<a href="loyalty.html" class="nav-item">
|
||||
<i class="fas fa-star"></i>
|
||||
<span>Hội viên</span>
|
||||
</a>
|
||||
<a href="promotions.html" class="nav-item">
|
||||
<i class="fas fa-tags"></i>
|
||||
<span>Khuyến mãi</span>
|
||||
</a>
|
||||
<a href="notifications.html" class="nav-item">
|
||||
<i class="fas fa-bell"></i>
|
||||
<span>Thông báo</span>
|
||||
</a>
|
||||
<a href="account.html" class="nav-item active">
|
||||
<i class="fas fa-user"></i>
|
||||
<span>Cài đặt</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Sample project data
|
||||
const projectsData = [
|
||||
{
|
||||
id: 'DA001',
|
||||
name: 'Chung cư Vinhomes Grand Park - Block A1',
|
||||
type: 'residential',
|
||||
customer: 'Công ty TNHH Vingroup',
|
||||
status: 'approved',
|
||||
submittedDate: '2023-11-15',
|
||||
approvedDate: '2023-11-20',
|
||||
area: '2,500m²',
|
||||
budget: '850,000,000',
|
||||
progress: 75,
|
||||
description: 'Gạch granite cao cấp cho khu vực lobby và hành lang'
|
||||
},
|
||||
{
|
||||
id: 'DA002',
|
||||
name: 'Trung tâm thương mại Bitexco',
|
||||
type: 'commercial',
|
||||
customer: 'Tập đoàn Bitexco',
|
||||
status: 'pending',
|
||||
submittedDate: '2023-11-25',
|
||||
area: '8,000m²',
|
||||
budget: '2,200,000,000',
|
||||
progress: 25,
|
||||
description: 'Gạch porcelain 80x80 cho sảnh chính và khu mua sắm'
|
||||
},
|
||||
{
|
||||
id: 'DA003',
|
||||
name: 'Biệt thự sinh thái Ecopark',
|
||||
type: 'residential',
|
||||
customer: 'Ecopark Group',
|
||||
status: 'approved',
|
||||
submittedDate: '2023-10-10',
|
||||
approvedDate: '2023-10-15',
|
||||
completedDate: '2023-11-30',
|
||||
area: '1,200m²',
|
||||
budget: '420,000,000',
|
||||
progress: 100,
|
||||
description: 'Gạch ceramic vân gỗ cho khu vực phòng khách và sân vườn'
|
||||
},
|
||||
{
|
||||
id: 'DA004',
|
||||
name: 'Nhà xưởng sản xuất ABC',
|
||||
type: 'industrial',
|
||||
customer: 'Công ty TNHH ABC Manufacturing',
|
||||
status: 'rejected',
|
||||
submittedDate: '2023-11-20',
|
||||
rejectedDate: '2023-11-28',
|
||||
area: '5,000m²',
|
||||
budget: '1,500,000,000',
|
||||
progress: 0,
|
||||
rejectionReason: 'Thiếu giấy phép xây dựng và báo cáo tác động môi trường',
|
||||
description: 'Gạch chống trơn cho khu vực sản xuất và kho bãi'
|
||||
},
|
||||
{
|
||||
id: 'DA005',
|
||||
name: 'Khách sạn 5 sao Diamond Plaza',
|
||||
type: 'commercial',
|
||||
customer: 'Diamond Hospitality Group',
|
||||
status: 'pending',
|
||||
submittedDate: '2023-12-01',
|
||||
area: '12,000m²',
|
||||
budget: '5,800,000,000',
|
||||
progress: 10,
|
||||
description: 'Gạch marble tự nhiên cho lobby và phòng suite'
|
||||
},
|
||||
{
|
||||
id: 'DA006',
|
||||
name: 'Khu đô thị thông minh Smart City',
|
||||
type: 'residential',
|
||||
customer: 'Smart City Development',
|
||||
status: 'approved',
|
||||
submittedDate: '2023-11-10',
|
||||
approvedDate: '2023-11-18',
|
||||
area: '25,000m²',
|
||||
budget: '8,500,000,000',
|
||||
progress: 45,
|
||||
description: 'Gạch granite và ceramic cho toàn bộ khu vực công cộng'
|
||||
}
|
||||
];
|
||||
|
||||
let filteredProjects = [...projectsData];
|
||||
let currentFilter = '';
|
||||
|
||||
// Initialize page
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
setupTabNavigation();
|
||||
renderProjects();
|
||||
});
|
||||
|
||||
function setupTabNavigation() {
|
||||
const tabItems = document.querySelectorAll('.tab-item');
|
||||
|
||||
tabItems.forEach(tab => {
|
||||
tab.addEventListener('click', function() {
|
||||
// Remove active class from all tabs
|
||||
tabItems.forEach(t => t.classList.remove('active'));
|
||||
|
||||
// Add active class to clicked tab
|
||||
this.classList.add('active');
|
||||
|
||||
// Update current filter
|
||||
currentFilter = this.dataset.status || '';
|
||||
|
||||
// Filter and render projects
|
||||
filterProjects();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function renderProjects() {
|
||||
const container = document.getElementById('projectsList');
|
||||
|
||||
if (filteredProjects.length === 0) {
|
||||
container.innerHTML = `
|
||||
<div class="empty-state text-center py-16">
|
||||
<i class="fas fa-folder-open text-4xl text-gray-300 mb-4"></i>
|
||||
<h3 class="text-lg font-semibold text-gray-600 mb-2">Không có dự án nào</h3>
|
||||
<p class="text-gray-500">Không tìm thấy dự án phù hợp với bộ lọc hiện tại</p>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = filteredProjects.map(project => `
|
||||
<div class="order-card ${project.status}" onclick="viewProjectDetail('${project.id}')">
|
||||
<div class="order-status-indicator"></div>
|
||||
<div class="order-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
<h4 class="order-id">#${project.id}</h4>
|
||||
<span class="order-amount">${formatCurrency(project.budget)}</span>
|
||||
</div>
|
||||
|
||||
<div class="order-details">
|
||||
<p class="order-date">Ngày nộp: ${formatDate(project.submittedDate)}</p>
|
||||
<p class="order-customer">Khách hàng: ${project.customer}</p>
|
||||
<p class="order-status-text">
|
||||
<span class="status-badge ${project.status}">${getStatusText(project.status)}</span>
|
||||
${project.status === 'approved' || project.status === 'completed' ? `
|
||||
<span class="ml-2 text-xs text-gray-500">${project.progress}% hoàn thành</span>
|
||||
` : ''}
|
||||
</p>
|
||||
<p class="order-note">${project.name} - Diện tích: ${project.area}</p>
|
||||
${project.description ? `
|
||||
<p class="text-xs text-gray-600 mt-1">${project.description}</p>
|
||||
` : ''}
|
||||
${project.status === 'rejected' && project.rejectionReason ? `
|
||||
<p class="text-xs text-red-600 mt-2 bg-red-50 p-2 rounded">
|
||||
<i class="fas fa-exclamation-triangle mr-1"></i>
|
||||
${project.rejectionReason}
|
||||
</p>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function getStatusText(status) {
|
||||
const statusMap = {
|
||||
'pending': 'Chờ duyệt',
|
||||
'reviewing': 'Đang xem xét',
|
||||
'approved': 'Đã duyệt',
|
||||
'rejected': 'Bị từ chối',
|
||||
'completed': 'Hoàn thành'
|
||||
};
|
||||
return statusMap[status] || status;
|
||||
}
|
||||
|
||||
function filterProjects() {
|
||||
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
|
||||
|
||||
filteredProjects = projectsData.filter(project => {
|
||||
// Status filter
|
||||
if (currentFilter && project.status !== currentFilter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Search filter
|
||||
if (searchTerm) {
|
||||
const searchableText = `${project.name} ${project.id} ${project.customer}`.toLowerCase();
|
||||
if (!searchableText.includes(searchTerm)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
renderProjects();
|
||||
}
|
||||
|
||||
function viewProjectDetail(projectId) {
|
||||
// Navigate to project detail page
|
||||
localStorage.setItem('selectedProjectId', projectId);
|
||||
window.location.href = 'project-submission-detail.html';
|
||||
}
|
||||
|
||||
function createNewProject() {
|
||||
// Navigate to new project creation page
|
||||
window.location.href = 'project-submission.html';
|
||||
}
|
||||
|
||||
// Utility functions
|
||||
function formatCurrency(amount) {
|
||||
const num = typeof amount === 'string' ? parseInt(amount) : amount;
|
||||
return new Intl.NumberFormat('vi-VN', {
|
||||
style: 'currency',
|
||||
currency: 'VND',
|
||||
minimumFractionDigits: 0
|
||||
}).format(num);
|
||||
}
|
||||
|
||||
function formatDate(dateString) {
|
||||
const date = new Date(dateString);
|
||||
return date.toLocaleDateString('vi-VN');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
996
html/quote-detail.html
Normal file
996
html/quote-detail.html
Normal file
@@ -0,0 +1,996 @@
|
||||
<!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"e=${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"e=${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>
|
||||
@@ -38,8 +38,8 @@
|
||||
|
||||
<!-- Quote Requests List -->
|
||||
<div class="quote-requests-list">
|
||||
<!-- Quote Request 1 - New -->
|
||||
<div class="quote-request-card new">
|
||||
<!-- Quote Request 1 - Đang đàm phán -->
|
||||
<div class="quote-request-card negotiating" onclick="viewQuoteDetail('YC001234')">
|
||||
<div class="quote-request-status-indicator"></div>
|
||||
<div class="quote-request-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
@@ -51,15 +51,15 @@
|
||||
<p class="quote-request-project">Dự án: Villa Thủ Đức - Giai đoạn 2</p>
|
||||
<p class="quote-request-items">5 sản phẩm - Diện tích: 200m²</p>
|
||||
<p class="quote-request-status-text">
|
||||
<span class="status-badge new">Mới tạo</span>
|
||||
<span class="status-badge negotiating">Đang đàm phán</span>
|
||||
</p>
|
||||
<p class="quote-request-note">Yêu cầu báo giá cho gạch granite cao cấp</p>
|
||||
<p class="quote-request-note">Khách hàng yêu cầu giảm giá 5%</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quote Request 2 - Waiting Response -->
|
||||
<div class="quote-request-card waiting">
|
||||
<!-- Quote Request 2 - Đã chốt -->
|
||||
<div class="quote-request-card finalized" onclick="viewQuoteDetail('YC001233')">
|
||||
<div class="quote-request-status-indicator"></div>
|
||||
<div class="quote-request-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
@@ -71,15 +71,15 @@
|
||||
<p class="quote-request-project">Dự án: Chung cư Landmark Center</p>
|
||||
<p class="quote-request-items">8 sản phẩm - Diện tích: 500m²</p>
|
||||
<p class="quote-request-status-text">
|
||||
<span class="status-badge waiting">Chờ phản hồi</span>
|
||||
<span class="status-badge finalized">Đã chốt</span>
|
||||
</p>
|
||||
<p class="quote-request-note">Báo giá cho sảnh chính và hành lang</p>
|
||||
<p class="quote-request-note">Tổng giá trị: 125.500.000 VND</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quote Request 3 - Has Quote -->
|
||||
<div class="quote-request-card quoted">
|
||||
<!-- Quote Request 3 - Đã thành đơn hàng -->
|
||||
<div class="quote-request-card converted" onclick="viewQuoteDetail('YC001232')">
|
||||
<div class="quote-request-status-indicator"></div>
|
||||
<div class="quote-request-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
@@ -91,15 +91,15 @@
|
||||
<p class="quote-request-project">Dự án: Nhà phố Bình Thạnh</p>
|
||||
<p class="quote-request-items">3 sản phẩm - Diện tích: 120m²</p>
|
||||
<p class="quote-request-status-text">
|
||||
<span class="status-badge quoted">Đã có báo giá</span>
|
||||
<span class="status-badge converted">Đã thành đơn hàng</span>
|
||||
</p>
|
||||
<p class="quote-request-note">Tổng giá trị: 28.900.000 VND</p>
|
||||
<p class="quote-request-note">Mã đơn hàng: #DH005432</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quote Request 4 - New -->
|
||||
<div class="quote-request-card new">
|
||||
<!-- Quote Request 4 - Đã gửi -->
|
||||
<div class="quote-request-card sent" onclick="viewQuoteDetail('YC001231')">
|
||||
<div class="quote-request-status-indicator"></div>
|
||||
<div class="quote-request-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
@@ -111,15 +111,15 @@
|
||||
<p class="quote-request-project">Dự án: Văn phòng Quận 7</p>
|
||||
<p class="quote-request-items">4 sản phẩm - Diện tích: 300m²</p>
|
||||
<p class="quote-request-status-text">
|
||||
<span class="status-badge new">Mới tạo</span>
|
||||
<span class="status-badge sent">Đã gửi</span>
|
||||
</p>
|
||||
<p class="quote-request-note">Gạch porcelain cho khu vực làm việc</p>
|
||||
<p class="quote-request-note">Chờ khách hàng phản hồi</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quote Request 5 - Waiting Response -->
|
||||
<div class="quote-request-card waiting">
|
||||
<!-- Quote Request 5 - Chờ duyệt -->
|
||||
<div class="quote-request-card pending" onclick="viewQuoteDetail('YC001230')">
|
||||
<div class="quote-request-status-indicator"></div>
|
||||
<div class="quote-request-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
@@ -131,12 +131,32 @@
|
||||
<p class="quote-request-project">Dự án: Resort Vũng Tàu</p>
|
||||
<p class="quote-request-items">12 sản phẩm - Diện tích: 800m²</p>
|
||||
<p class="quote-request-status-text">
|
||||
<span class="status-badge waiting">Chờ phản hồi</span>
|
||||
<span class="status-badge pending">Chờ duyệt</span>
|
||||
</p>
|
||||
<p class="quote-request-note">Yêu cầu báo giá cho khu vực pool và spa</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quote Request 6 - Đã hủy -->
|
||||
<div class="quote-request-card cancelled" onclick="viewQuoteDetail('YC001229')">
|
||||
<div class="quote-request-status-indicator"></div>
|
||||
<div class="quote-request-content">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
<h4 class="quote-request-id">#YC001229</h4>
|
||||
<span class="quote-request-date">25/07/2023</span>
|
||||
</div>
|
||||
|
||||
<div class="quote-request-details">
|
||||
<p class="quote-request-project">Dự án: Showroom Quận 1</p>
|
||||
<p class="quote-request-items">6 sản phẩm - Diện tích: 250m²</p>
|
||||
<p class="quote-request-status-text">
|
||||
<span class="status-badge cancelled">Đã hủy</span>
|
||||
</p>
|
||||
<p class="quote-request-note">Khách hàng hủy dự án</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -167,7 +187,13 @@
|
||||
<i class="fas fa-user"></i>
|
||||
<span>Cài đặt</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>-->
|
||||
</div>-->
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function viewQuoteDetail(quoteId) {
|
||||
window.location.href = `quote-detail.html?id=${quoteId}`;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
919
html/receivables-management.html
Normal file
919
html/receivables-management.html
Normal file
@@ -0,0 +1,919 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="vi">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Quản lý Công nợ - EuroTile Dealer</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">
|
||||
<style>
|
||||
.receivables-container {
|
||||
min-height: calc(100vh - 120px);
|
||||
background: #f8f9fa;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.summary-cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 15px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.summary-card {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
color: white;
|
||||
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.2);
|
||||
}
|
||||
|
||||
.summary-card.warning {
|
||||
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
||||
}
|
||||
|
||||
.summary-card.success {
|
||||
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
||||
}
|
||||
|
||||
.summary-title {
|
||||
font-size: 0.9rem;
|
||||
opacity: 0.9;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.summary-amount {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.summary-detail {
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.8;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.filter-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-weight: 600;
|
||||
color: #374151;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.filter-select,
|
||||
.filter-input {
|
||||
padding: 10px 12px;
|
||||
border: 2px solid #e5e7eb;
|
||||
border-radius: 8px;
|
||||
font-size: 0.9rem;
|
||||
transition: border-color 0.3s ease;
|
||||
}
|
||||
|
||||
.filter-select:focus,
|
||||
.filter-input:focus {
|
||||
outline: none;
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
.receivables-list {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.receivable-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid #f3f4f6;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.receivable-item:hover {
|
||||
background: #f9fafb;
|
||||
}
|
||||
|
||||
.receivable-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.customer-avatar {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: 1.2rem;
|
||||
margin-right: 15px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.receivable-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.customer-name {
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
margin-bottom: 5px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.order-details {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.order-id {
|
||||
color: #6b7280;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.order-date {
|
||||
color: #9ca3af;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.payment-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.overdue-badge {
|
||||
background: #fee2e2;
|
||||
color: #dc2626;
|
||||
padding: 4px 8px;
|
||||
border-radius: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.due-soon-badge {
|
||||
background: #fef3c7;
|
||||
color: #d97706;
|
||||
padding: 4px 8px;
|
||||
border-radius: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.receivable-amount {
|
||||
text-align: right;
|
||||
margin-left: 15px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.amount-value {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.amount-overdue {
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
.amount-due-soon {
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.due-date {
|
||||
font-size: 0.8rem;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-left: 15px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.btn-action {
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-remind {
|
||||
background: #eff6ff;
|
||||
color: #1d4ed8;
|
||||
}
|
||||
|
||||
.btn-remind:hover {
|
||||
background: #dbeafe;
|
||||
}
|
||||
|
||||
.btn-collect {
|
||||
background: #f0fdf4;
|
||||
color: #16a34a;
|
||||
}
|
||||
|
||||
.btn-collect:hover {
|
||||
background: #dcfce7;
|
||||
}
|
||||
|
||||
.btn-view {
|
||||
background: #f3f4f6;
|
||||
color: #374151;
|
||||
}
|
||||
|
||||
.btn-view:hover {
|
||||
background: #e5e7eb;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.empty-state i {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 20px;
|
||||
color: #d1d5db;
|
||||
}
|
||||
|
||||
.floating-action {
|
||||
position: fixed;
|
||||
bottom: 90px;
|
||||
right: 20px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-size: 1.5rem;
|
||||
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.floating-action:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 12px 35px rgba(102, 126, 234, 0.5);
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.5);
|
||||
z-index: 1000;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.modal.show {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 20px 20px 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1.5rem;
|
||||
color: #6b7280;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: block;
|
||||
font-weight: 600;
|
||||
color: #374151;
|
||||
margin-bottom: 8px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.form-input,
|
||||
.form-select,
|
||||
.form-textarea {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: 2px solid #e5e7eb;
|
||||
border-radius: 8px;
|
||||
font-size: 0.9rem;
|
||||
transition: border-color 0.3s ease;
|
||||
}
|
||||
|
||||
.form-input:focus,
|
||||
.form-select:focus,
|
||||
.form-textarea:focus {
|
||||
outline: none;
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
height: 100px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.modal-actions {
|
||||
padding: 0 20px 20px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
padding: 12px 20px;
|
||||
background: #f3f4f6;
|
||||
color: #374151;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn-submit {
|
||||
padding: 12px 20px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.receivables-container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.summary-cards {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.receivable-item {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.order-details {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.btn-action {
|
||||
font-size: 0.75rem;
|
||||
padding: 6px 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-wrapper">
|
||||
<!-- Header -->
|
||||
<div class="header">
|
||||
<a href="index.html" class="back-button">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Quản lý Công nợ</h1>
|
||||
<button class="icon-button" onclick="exportReceivables()">
|
||||
<i class="fas fa-download"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="receivables-container">
|
||||
<!-- Summary Cards -->
|
||||
<div class="summary-cards">
|
||||
<div class="summary-card">
|
||||
<div class="summary-title">Tổng công nợ</div>
|
||||
<div class="summary-amount">892.500.000đ</div>
|
||||
<div class="summary-detail">
|
||||
<i class="fas fa-users"></i>
|
||||
<span>45 khách hàng</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="summary-card warning">
|
||||
<div class="summary-title">Quá hạn thanh toán</div>
|
||||
<div class="summary-amount">156.000.000đ</div>
|
||||
<div class="summary-detail">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
<span>12 đơn hàng</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="summary-card success">
|
||||
<div class="summary-title">Sắp đến hạn</div>
|
||||
<div class="summary-amount">234.750.000đ</div>
|
||||
<div class="summary-detail">
|
||||
<i class="fas fa-clock"></i>
|
||||
<span>18 đơn hàng (7 ngày tới)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter Section -->
|
||||
<div class="filter-section">
|
||||
<div class="filter-row">
|
||||
<div class="filter-group">
|
||||
<label class="filter-label">Trạng thái</label>
|
||||
<select class="filter-select" id="statusFilter" onchange="filterReceivables()">
|
||||
<option value="">Tất cả</option>
|
||||
<option value="overdue">Quá hạn</option>
|
||||
<option value="due-soon">Sắp đến hạn</option>
|
||||
<option value="normal">Bình thường</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="filter-group">
|
||||
<label class="filter-label">Khoảng tiền</label>
|
||||
<select class="filter-select" id="amountFilter" onchange="filterReceivables()">
|
||||
<option value="">Tất cả</option>
|
||||
<option value="small">Dưới 10 triệu</option>
|
||||
<option value="medium">10 - 50 triệu</option>
|
||||
<option value="large">Trên 50 triệu</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="filter-group">
|
||||
<label class="filter-label">Tìm kiếm khách hàng</label>
|
||||
<input type="text" class="filter-input" id="searchInput" placeholder="Tên hoặc mã đơn hàng..." onkeyup="filterReceivables()">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Receivables List -->
|
||||
<div class="receivables-list" id="receivablesList">
|
||||
<!-- Receivable Items will be populated by JavaScript -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom Navigation -->
|
||||
<div class="bottom-nav">
|
||||
<a href="index.html" class="nav-item">
|
||||
<i class="fas fa-home"></i>
|
||||
<span>Trang chủ</span>
|
||||
</a>
|
||||
<a href="loyalty.html" class="nav-item">
|
||||
<i class="fas fa-star"></i>
|
||||
<span>Hội viên</span>
|
||||
</a>
|
||||
<a href="promotions.html" class="nav-item">
|
||||
<i class="fas fa-tags"></i>
|
||||
<span>Khuyến mãi</span>
|
||||
</a>
|
||||
<a href="notifications.html" class="nav-item">
|
||||
<i class="fas fa-bell"></i>
|
||||
<span>Thông báo</span>
|
||||
</a>
|
||||
<a href="account.html" class="nav-item active">
|
||||
<i class="fas fa-user"></i>
|
||||
<span>Cài đặt</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Floating Action Button -->
|
||||
<div class="floating-action" onclick="openAddReceivableModal()">
|
||||
<i class="fas fa-plus"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Reminder Modal -->
|
||||
<div class="modal" id="reminderModal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Gửi nhắc nợ</h3>
|
||||
<button class="modal-close" onclick="closeModal('reminderModal')">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Khách hàng</label>
|
||||
<input type="text" class="form-input" id="reminderCustomer" readonly>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Số tiền nợ</label>
|
||||
<input type="text" class="form-input" id="reminderAmount" readonly>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Phương thức nhắc nhở</label>
|
||||
<select class="form-select" id="reminderMethod">
|
||||
<option value="sms">Tin nhắn SMS</option>
|
||||
<option value="call">Gọi điện thoại</option>
|
||||
<option value="email">Email</option>
|
||||
<option value="visit">Đến thăm trực tiếp</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Nội dung nhắc nhở</label>
|
||||
<textarea class="form-textarea" id="reminderMessage" placeholder="Nhập nội dung nhắc nở...">Kính chào anh/chị,
|
||||
|
||||
EuroTile xin nhắc nhở về việc thanh toán công nợ đơn hàng. Vui lòng liên hệ với chúng tôi để sắp xếp thanh toán.
|
||||
|
||||
Xin cảm ơn!</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button class="btn-cancel" onclick="closeModal('reminderModal')">Hủy</button>
|
||||
<button class="btn-submit" onclick="sendReminder()">Gửi nhắc nhở</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Collection Modal -->
|
||||
<div class="modal" id="collectionModal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Thu tiền</h3>
|
||||
<button class="modal-close" onclick="closeModal('collectionModal')">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Khách hàng</label>
|
||||
<input type="text" class="form-input" id="collectionCustomer" readonly>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Tổng số tiền nợ</label>
|
||||
<input type="text" class="form-input" id="collectionTotalAmount" readonly>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Số tiền thu</label>
|
||||
<input type="number" class="form-input" id="collectionAmount" placeholder="Nhập số tiền thu được...">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Phương thức thanh toán</label>
|
||||
<select class="form-select" id="paymentMethod">
|
||||
<option value="cash">Tiền mặt</option>
|
||||
<option value="transfer">Chuyển khoản</option>
|
||||
<option value="check">Séc</option>
|
||||
<option value="card">Thẻ tín dụng</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Ghi chú</label>
|
||||
<textarea class="form-textarea" id="collectionNote" placeholder="Ghi chú về việc thu tiền..."></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button class="btn-cancel" onclick="closeModal('collectionModal')">Hủy</button>
|
||||
<button class="btn-submit" onclick="recordPayment()">Ghi nhận thanh toán</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Sample receivables data
|
||||
const receivablesData = [
|
||||
{
|
||||
id: 'DH001234',
|
||||
customer: 'Công ty TNHH Xây dựng Minh An',
|
||||
customerCode: 'KH001',
|
||||
phone: '0912345678',
|
||||
orderDate: '2023-10-15',
|
||||
dueDate: '2023-11-15',
|
||||
amount: 85000000,
|
||||
status: 'overdue',
|
||||
daysOverdue: 15
|
||||
},
|
||||
{
|
||||
id: 'DH001235',
|
||||
customer: 'Anh Nguyễn Văn Hùng',
|
||||
customerCode: 'KH002',
|
||||
phone: '0987654321',
|
||||
orderDate: '2023-11-20',
|
||||
dueDate: '2023-12-20',
|
||||
amount: 25750000,
|
||||
status: 'due-soon',
|
||||
daysOverdue: 0
|
||||
},
|
||||
{
|
||||
id: 'DH001236',
|
||||
customer: 'Chị Trần Thị Mai',
|
||||
customerCode: 'KH003',
|
||||
phone: '0923456789',
|
||||
orderDate: '2023-11-25',
|
||||
dueDate: '2023-12-25',
|
||||
amount: 12500000,
|
||||
status: 'normal',
|
||||
daysOverdue: 0
|
||||
},
|
||||
{
|
||||
id: 'DH001237',
|
||||
customer: 'Công ty CP Đầu tư Bất động sản ABC',
|
||||
customerCode: 'KH004',
|
||||
phone: '0945678912',
|
||||
orderDate: '2023-10-10',
|
||||
dueDate: '2023-11-10',
|
||||
amount: 156000000,
|
||||
status: 'overdue',
|
||||
daysOverdue: 20
|
||||
},
|
||||
{
|
||||
id: 'DH001238',
|
||||
customer: 'Anh Lê Minh Tuấn',
|
||||
customerCode: 'KH005',
|
||||
phone: '0934567890',
|
||||
orderDate: '2023-11-28',
|
||||
dueDate: '2023-12-28',
|
||||
amount: 18900000,
|
||||
status: 'due-soon',
|
||||
daysOverdue: 0
|
||||
}
|
||||
];
|
||||
|
||||
let filteredReceivables = [...receivablesData];
|
||||
|
||||
// Initialize page
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
renderReceivables();
|
||||
});
|
||||
|
||||
function renderReceivables() {
|
||||
const container = document.getElementById('receivablesList');
|
||||
|
||||
if (filteredReceivables.length === 0) {
|
||||
container.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-receipt"></i>
|
||||
<h3>Không có công nợ nào</h3>
|
||||
<p>Không tìm thấy công nợ phù hợp với bộ lọc hiện tại</p>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = filteredReceivables.map(receivable => `
|
||||
<div class="receivable-item" onclick="viewReceivableDetail('${receivable.id}')">
|
||||
<div class="customer-avatar">
|
||||
${receivable.customer.charAt(0).toUpperCase()}
|
||||
</div>
|
||||
|
||||
<div class="receivable-info">
|
||||
<div class="customer-name">${receivable.customer}</div>
|
||||
<div class="order-details">
|
||||
<span class="order-id">Đơn hàng: ${receivable.id}</span>
|
||||
<span class="order-date">Ngày đặt: ${formatDate(receivable.orderDate)}</span>
|
||||
</div>
|
||||
<div class="payment-info">
|
||||
${getStatusBadge(receivable.status, receivable.daysOverdue)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="receivable-amount">
|
||||
<div class="amount-value ${getAmountClass(receivable.status)}">
|
||||
${formatCurrency(receivable.amount)}
|
||||
</div>
|
||||
<div class="due-date">Hạn: ${formatDate(receivable.dueDate)}</div>
|
||||
</div>
|
||||
|
||||
<div class="action-buttons">
|
||||
<button class="btn-action btn-remind" onclick="event.stopPropagation(); openReminderModal('${receivable.id}')">
|
||||
<i class="fas fa-bell"></i>
|
||||
</button>
|
||||
<button class="btn-action btn-collect" onclick="event.stopPropagation(); openCollectionModal('${receivable.id}')">
|
||||
<i class="fas fa-money-bill-wave"></i>
|
||||
</button>
|
||||
<button class="btn-action btn-view" onclick="event.stopPropagation(); viewReceivableDetail('${receivable.id}')">
|
||||
<i class="fas fa-eye"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function getStatusBadge(status, daysOverdue) {
|
||||
switch(status) {
|
||||
case 'overdue':
|
||||
return `<span class="overdue-badge">Quá hạn ${daysOverdue} ngày</span>`;
|
||||
case 'due-soon':
|
||||
return `<span class="due-soon-badge">Sắp đến hạn</span>`;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function getAmountClass(status) {
|
||||
switch(status) {
|
||||
case 'overdue':
|
||||
return 'amount-overdue';
|
||||
case 'due-soon':
|
||||
return 'amount-due-soon';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function filterReceivables() {
|
||||
const statusFilter = document.getElementById('statusFilter').value;
|
||||
const amountFilter = document.getElementById('amountFilter').value;
|
||||
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
|
||||
|
||||
filteredReceivables = receivablesData.filter(receivable => {
|
||||
// Status filter
|
||||
if (statusFilter && receivable.status !== statusFilter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Amount filter
|
||||
if (amountFilter) {
|
||||
const amount = receivable.amount;
|
||||
if (amountFilter === 'small' && amount >= 10000000) return false;
|
||||
if (amountFilter === 'medium' && (amount < 10000000 || amount > 50000000)) return false;
|
||||
if (amountFilter === 'large' && amount <= 50000000) return false;
|
||||
}
|
||||
|
||||
// Search filter
|
||||
if (searchTerm) {
|
||||
const searchableText = `${receivable.customer} ${receivable.id}`.toLowerCase();
|
||||
if (!searchableText.includes(searchTerm)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
renderReceivables();
|
||||
}
|
||||
|
||||
function openReminderModal(receivableId) {
|
||||
const receivable = receivablesData.find(r => r.id === receivableId);
|
||||
if (!receivable) return;
|
||||
|
||||
document.getElementById('reminderCustomer').value = receivable.customer;
|
||||
document.getElementById('reminderAmount').value = formatCurrency(receivable.amount);
|
||||
document.getElementById('reminderModal').classList.add('show');
|
||||
}
|
||||
|
||||
function openCollectionModal(receivableId) {
|
||||
const receivable = receivablesData.find(r => r.id === receivableId);
|
||||
if (!receivable) return;
|
||||
|
||||
document.getElementById('collectionCustomer').value = receivable.customer;
|
||||
document.getElementById('collectionTotalAmount').value = formatCurrency(receivable.amount);
|
||||
document.getElementById('collectionAmount').value = '';
|
||||
document.getElementById('collectionModal').classList.add('show');
|
||||
}
|
||||
|
||||
function closeModal(modalId) {
|
||||
document.getElementById(modalId).classList.remove('show');
|
||||
}
|
||||
|
||||
function sendReminder() {
|
||||
const method = document.getElementById('reminderMethod').value;
|
||||
const message = document.getElementById('reminderMessage').value;
|
||||
|
||||
if (!message.trim()) {
|
||||
alert('Vui lòng nhập nội dung nhắc nhở');
|
||||
return;
|
||||
}
|
||||
|
||||
// Simulate sending reminder
|
||||
alert('Đã gửi nhắc nhở thành công!');
|
||||
closeModal('reminderModal');
|
||||
}
|
||||
|
||||
function recordPayment() {
|
||||
const amount = document.getElementById('collectionAmount').value;
|
||||
const method = document.getElementById('paymentMethod').value;
|
||||
|
||||
if (!amount || amount <= 0) {
|
||||
alert('Vui lòng nhập số tiền hợp lệ');
|
||||
return;
|
||||
}
|
||||
|
||||
// Simulate recording payment
|
||||
alert('Đã ghi nhận thanh toán thành công!');
|
||||
closeModal('collectionModal');
|
||||
|
||||
// Refresh the list (in a real app, this would update the backend)
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function viewReceivableDetail(receivableId) {
|
||||
// Navigate to receivable detail page
|
||||
alert(`Xem chi tiết công nợ ${receivableId}`);
|
||||
}
|
||||
|
||||
function openAddReceivableModal() {
|
||||
alert('Chức năng thêm công nợ mới sẽ được phát triển');
|
||||
}
|
||||
|
||||
function exportReceivables() {
|
||||
// Simulate export functionality
|
||||
alert('Đang xuất báo cáo công nợ...');
|
||||
}
|
||||
|
||||
// Utility functions
|
||||
function formatCurrency(amount) {
|
||||
return new Intl.NumberFormat('vi-VN', {
|
||||
style: 'currency',
|
||||
currency: 'VND',
|
||||
minimumFractionDigits: 0
|
||||
}).format(amount);
|
||||
}
|
||||
|
||||
function formatDate(dateString) {
|
||||
const date = new Date(dateString);
|
||||
return date.toLocaleDateString('vi-VN');
|
||||
}
|
||||
|
||||
// Close modals when clicking outside
|
||||
window.onclick = function(event) {
|
||||
const modals = document.querySelectorAll('.modal');
|
||||
modals.forEach(modal => {
|
||||
if (event.target === modal) {
|
||||
modal.classList.remove('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
425
html/vr360-viewer-section.html
Normal file
425
html/vr360-viewer-section.html
Normal file
@@ -0,0 +1,425 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="vi">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Nhà mẫu 360° - EuroTile Worker</title>
|
||||
<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">
|
||||
<style>
|
||||
/* VR360 Container Styles */
|
||||
.vr360-section {
|
||||
background: var(--white);
|
||||
padding: 16px;
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.vr360-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
box-shadow: var(--shadow-medium);
|
||||
}
|
||||
|
||||
/* Option 1: Click to View Style */
|
||||
.vr360-preview {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 48px 24px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
text-decoration: none;
|
||||
color: var(--white);
|
||||
position: relative;
|
||||
background: linear-gradient(135deg, rgba(0, 91, 154, 0.9) 0%, rgba(56, 182, 255, 0.9) 100%);
|
||||
}
|
||||
|
||||
.vr360-preview:hover {
|
||||
transform: scale(1.02);
|
||||
box-shadow: 0 10px 30px rgba(0, 91, 154, 0.3);
|
||||
}
|
||||
|
||||
.vr360-icon-wrapper {
|
||||
position: relative;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.vr360-icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.vr360-icon::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 3px solid rgba(255, 255, 255, 0.4);
|
||||
border-radius: 50%;
|
||||
animation: pulse360 2s infinite;
|
||||
}
|
||||
|
||||
.vr360-icon::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 120%;
|
||||
height: 120%;
|
||||
border: 2px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 50%;
|
||||
animation: pulse360 2s infinite 0.5s;
|
||||
}
|
||||
|
||||
.vr360-icon .main-icon {
|
||||
font-size: 36px;
|
||||
color: var(--white);
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.vr360-arrow {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.vr360-arrow svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
animation: rotate360 4s linear infinite;
|
||||
}
|
||||
|
||||
.vr360-title {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
color: var(--white);
|
||||
margin-bottom: 8px;
|
||||
text-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.vr360-subtitle {
|
||||
font-size: 14px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.vr360-button {
|
||||
padding: 12px 32px;
|
||||
background: var(--white);
|
||||
color: var(--primary-blue);
|
||||
border-radius: 24px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.vr360-preview:hover .vr360-button {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
/* Option 2: Embedded iFrame Style */
|
||||
.vr360-embed {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding-bottom: 75%; /* 4:3 Aspect Ratio */
|
||||
background: var(--background-gray);
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.vr360-iframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.vr360-loading {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
text-align: center;
|
||||
color: var(--text-light);
|
||||
}
|
||||
|
||||
.vr360-loading .spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 3px solid var(--border-color);
|
||||
border-top-color: var(--primary-blue);
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin: 0 auto 12px;
|
||||
}
|
||||
|
||||
/* Toggle Switch for View Options */
|
||||
.view-options {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.view-option-btn {
|
||||
padding: 8px 16px;
|
||||
background: var(--white);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 20px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--text-dark);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.view-option-btn.active {
|
||||
background: var(--primary-blue);
|
||||
color: var(--white);
|
||||
border-color: var(--primary-blue);
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes pulse360 {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.3);
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1.6);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotate360 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fullscreen Button */
|
||||
.vr360-fullscreen-btn {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
color: var(--white);
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.vr360-fullscreen-btn:hover {
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-wrapper">
|
||||
<!-- Header -->
|
||||
<div class="header">
|
||||
<a href="index.html" class="back-button">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Nhà mẫu 360°</h1>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<!-- View Options Toggle -->
|
||||
<div class="view-options">
|
||||
<button class="view-option-btn active" onclick="showPreview()">
|
||||
<i class="fas fa-image"></i> Xem trước
|
||||
</button>
|
||||
<button class="view-option-btn" onclick="showEmbed()">
|
||||
<i class="fas fa-play"></i> Xem trực tiếp
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- VR360 Section -->
|
||||
<div class="vr360-section">
|
||||
<!-- Option 1: Preview with Link -->
|
||||
<div id="previewMode" class="vr360-container">
|
||||
<a href="https://vr.house3d.com/web/panorama-player/H00179549"
|
||||
target="_blank"
|
||||
class="vr360-preview">
|
||||
<div class="vr360-icon-wrapper">
|
||||
<div class="vr360-icon">
|
||||
<span class="main-icon">360°</span>
|
||||
</div>
|
||||
<div class="vr360-arrow">
|
||||
<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="60" cy="60" r="50" fill="none" stroke="rgba(255,255,255,0.3)" stroke-width="2" stroke-dasharray="10 5"/>
|
||||
<path d="M 60 15 L 65 20 M 65 20 L 60 25" stroke="rgba(255,255,255,0.8)" stroke-width="2" fill="none" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<h2 class="vr360-title">360°</h2>
|
||||
<p class="vr360-subtitle">Khám phá không gian nhà mẫu toàn cảnh</p>
|
||||
<div class="vr360-button">
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
<span>Mở chế độ xem 360°</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Option 2: Embedded iFrame (Hidden by default) -->
|
||||
<div id="embedMode" class="vr360-container" style="display: none;">
|
||||
<div class="vr360-embed">
|
||||
<div class="vr360-loading" id="loadingState">
|
||||
<div class="spinner"></div>
|
||||
<span>Đang tải mô hình 360°...</span>
|
||||
</div>
|
||||
<iframe
|
||||
id="vr360iframe"
|
||||
class="vr360-iframe"
|
||||
src=""
|
||||
title="Mô hình 360° Nhà mẫu"
|
||||
allowfullscreen
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
onload="hideLoading()"
|
||||
style="display: none;">
|
||||
</iframe>
|
||||
<button class="vr360-fullscreen-btn" onclick="goFullscreen()">
|
||||
<i class="fas fa-expand"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Additional Info -->
|
||||
<div class="card">
|
||||
<h3 class="card-title">Về nhà mẫu này</h3>
|
||||
<p style="color: var(--text-light); font-size: 14px; line-height: 1.6;">
|
||||
Trải nghiệm không gian sống hiện đại với công nghệ xem 360°.
|
||||
Di chuyển chuột hoặc vuốt màn hình để khám phá mọi góc nhìn của căn nhà.
|
||||
</p>
|
||||
<ul style="padding-left: 20px; margin-top: 12px;">
|
||||
<li style="color: var(--text-light); font-size: 14px; margin-bottom: 8px;">
|
||||
<i class="fas fa-mouse" style="color: var(--primary-blue); margin-right: 8px;"></i>
|
||||
Kéo chuột để xoay góc nhìn
|
||||
</li>
|
||||
<li style="color: var(--text-light); font-size: 14px; margin-bottom: 8px;">
|
||||
<i class="fas fa-search-plus" style="color: var(--primary-blue); margin-right: 8px;"></i>
|
||||
Scroll để zoom in/out
|
||||
</li>
|
||||
<li style="color: var(--text-light); font-size: 14px;">
|
||||
<i class="fas fa-hand-point-up" style="color: var(--primary-blue); margin-right: 8px;"></i>
|
||||
Click vào các điểm nóng để di chuyển
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const VR360_URL = "https://vr.house3d.com/web/panorama-player/H00179549";
|
||||
|
||||
// Show preview mode
|
||||
function showPreview() {
|
||||
document.getElementById('previewMode').style.display = 'block';
|
||||
document.getElementById('embedMode').style.display = 'none';
|
||||
|
||||
// Update buttons
|
||||
document.querySelectorAll('.view-option-btn').forEach(btn => {
|
||||
btn.classList.remove('active');
|
||||
});
|
||||
event.target.classList.add('active');
|
||||
|
||||
// Clear iframe src to stop loading
|
||||
document.getElementById('vr360iframe').src = '';
|
||||
}
|
||||
|
||||
// Show embedded mode
|
||||
function showEmbed() {
|
||||
document.getElementById('previewMode').style.display = 'none';
|
||||
document.getElementById('embedMode').style.display = 'block';
|
||||
|
||||
// Update buttons
|
||||
document.querySelectorAll('.view-option-btn').forEach(btn => {
|
||||
btn.classList.remove('active');
|
||||
});
|
||||
event.target.classList.add('active');
|
||||
|
||||
// Load iframe
|
||||
const iframe = document.getElementById('vr360iframe');
|
||||
if (!iframe.src) {
|
||||
iframe.src = VR360_URL;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide loading state when iframe loads
|
||||
function hideLoading() {
|
||||
document.getElementById('loadingState').style.display = 'none';
|
||||
document.getElementById('vr360iframe').style.display = 'block';
|
||||
}
|
||||
|
||||
// Fullscreen function
|
||||
function goFullscreen() {
|
||||
const container = document.getElementById('embedMode');
|
||||
if (container.requestFullscreen) {
|
||||
container.requestFullscreen();
|
||||
} else if (container.webkitRequestFullscreen) {
|
||||
container.webkitRequestFullscreen();
|
||||
} else if (container.mozRequestFullScreen) {
|
||||
container.mozRequestFullScreen();
|
||||
} else if (container.msRequestFullscreen) {
|
||||
container.msRequestFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
// Optional: Auto-load embed after delay
|
||||
// setTimeout(() => {
|
||||
// if (window.innerWidth > 768) {
|
||||
// showEmbed();
|
||||
// }
|
||||
// }, 2000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user