248 lines
13 KiB
PHP
248 lines
13 KiB
PHP
@extends('layouts.app')
|
|
|
|
@section('title', 'Lịch sử chuyển đổi')
|
|
|
|
@section('content')
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<!-- Bulk Action Header -->
|
|
<div class="mb-3 d-flex align-items-center justify-content-between">
|
|
<div>
|
|
<p class="m-0 text-muted small">Chọn các dòng cần xóa hoặc quản lý link</p>
|
|
</div>
|
|
<div>
|
|
<button type="button" id="btn-bulk-delete" class="btn btn-danger btn-sm d-none shadow-sm fw-bold" onclick="submitBulkDelete()">
|
|
<i class="bi bi-trash3-fill me-1"></i> Xóa mục đã chọn (<span id="select-count">0</span>)
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card shadow-sm">
|
|
<div class="card-body table-responsive p-0">
|
|
<table class="table table-hover align-middle text-nowrap">
|
|
<thead>
|
|
<tr>
|
|
<th style="width: 40px;" class="px-3">
|
|
<input type="checkbox" id="select-all" class="form-check-input">
|
|
</th>
|
|
<th>Thời gian</th>
|
|
<th>Kênh Zalo</th>
|
|
<th>Khách hàng</th>
|
|
<th>Link gốc</th>
|
|
<th>Link rút gọn</th>
|
|
<th>Lượt click</th>
|
|
<th>Trạng thái</th>
|
|
<th class="text-end px-3">Hành động</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@forelse($histories as $history)
|
|
<tr>
|
|
<td class="px-3">
|
|
<input type="checkbox" value="{{ $history->id }}" class="form-check-input history-checkbox">
|
|
</td>
|
|
<td>{{ $history->created_at->format('H:i:s d/m/Y') }}</td>
|
|
<td>
|
|
@if($history->zalo_thread_id)
|
|
<div class="d-flex align-items-center gap-3">
|
|
<div>
|
|
<span class="d-block fw-bold text-primary" title="Thread ID: {{ $history->zalo_thread_id }}">
|
|
<i class="bi bi-chat-dots-fill me-1"></i> {{ $history->zalo_chat_name ?? 'Nhóm Zalo' }}
|
|
</span>
|
|
<small class="text-muted" style="font-size: 0.75rem;">ID: {{ $history->zalo_thread_id }}</small>
|
|
</div>
|
|
<div>
|
|
<form action="{{ route('zalo_channels.quick_toggle') }}" method="POST" class="d-inline">
|
|
@csrf
|
|
<input type="hidden" name="thread_id" value="{{ $history->zalo_thread_id }}">
|
|
<input type="hidden" name="name" value="{{ $history->zalo_chat_name }}">
|
|
@if(in_array($history->zalo_thread_id, $allowedThreadIds))
|
|
<button type="submit" class="btn btn-danger btn-sm py-0 px-2 fw-bold text-white shadow-sm" style="font-size: 0.75rem;" title="Ngắt kết nối Bot với nhóm này">
|
|
<i class="bi bi-slash-circle-fill"></i> Chặn
|
|
</button>
|
|
@else
|
|
<button type="submit" class="btn btn-success btn-sm py-0 px-2 fw-bold text-white shadow-sm" style="font-size: 0.75rem;" title="Cho phép Bot phản hồi nhóm này">
|
|
<i class="bi bi-check-circle-fill"></i> Cho phép
|
|
</button>
|
|
@endif
|
|
</form>
|
|
</div>
|
|
</div>
|
|
@else
|
|
<span class="badge text-bg-secondary px-2"><i class="bi bi-globe me-1"></i> Web Rút Gọn</span>
|
|
@endif
|
|
</td>
|
|
<td>
|
|
@if($history->customer_name || $history->customer_phone)
|
|
<span class="d-block fw-bold text-dark">{{ $history->customer_name ?: 'Ẩn danh' }}</span>
|
|
@if($history->customer_phone)
|
|
<small class="text-muted"><i class="bi bi-telephone-fill me-1" style="font-size: 0.7rem;"></i>{{ $history->customer_phone }}</small>
|
|
@endif
|
|
@else
|
|
<span class="text-muted">-</span>
|
|
@endif
|
|
</td>
|
|
<td>
|
|
<a href="{{ $history->original_url }}" target="_blank" class="text-truncate d-inline-block" style="max-width: 250px;" title="{{ $history->original_url }}">{{ $history->original_url }}</a>
|
|
</td>
|
|
<td>
|
|
@if($history->code)
|
|
@php
|
|
$domainSetting = app(\App\Services\SettingService::class)->get('short_link_domain');
|
|
if ($domainSetting) {
|
|
$shortUrl = rtrim($domainSetting, '/') . '/aff/s/' . $history->code;
|
|
} else {
|
|
$shortUrl = route('short_link.redirect', ['code' => $history->code]);
|
|
}
|
|
@endphp
|
|
<div class="d-inline-flex align-items-center gap-2">
|
|
<a href="{{ $shortUrl }}" target="_blank" class="fw-bold text-success">{{ $shortUrl }}</a>
|
|
<button type="button" onclick="copyToClipboard('{{ $shortUrl }}', this)" class="btn btn-outline-primary btn-sm py-0 px-1 border-0" title="Copy Link">
|
|
<i class="bi bi-clipboard"></i>
|
|
</button>
|
|
</div>
|
|
@elseif($history->affiliate_url)
|
|
<a href="{{ $history->affiliate_url }}" target="_blank" class="text-truncate d-inline-block" style="max-width: 250px;">{{ $history->affiliate_url }}</a>
|
|
@else
|
|
<span class="text-muted">-</span>
|
|
@endif
|
|
</td>
|
|
<td>
|
|
<span class="badge text-bg-info px-2 py-1 text-white" style="font-weight: 600;"><i class="bi bi-eye-fill me-1"></i> {{ number_format($history->clicks) }}</span>
|
|
</td>
|
|
<td>
|
|
@if($history->status === 'success')
|
|
<span class="badge text-bg-success"><i class="bi bi-check-circle me-1"></i> Thành công</span>
|
|
@elseif($history->zalo_thread_id && $history->status === 'failed' && str_contains($history->error_message, 'restricted'))
|
|
<span class="badge text-bg-warning text-dark" title="{{ $history->error_message }}"><i class="bi bi-slash-circle me-1"></i> Bị chặn (Whitelist)</span>
|
|
@else
|
|
<span class="badge text-bg-danger" title="{{ $history->error_message }}"><i class="bi bi-exclamation-triangle me-1"></i> Thất bại</span>
|
|
@endif
|
|
</td>
|
|
<td class="text-end px-3">
|
|
<button type="button" onclick="deleteSingle({{ $history->id }})" class="btn btn-outline-danger btn-sm py-1 px-2 border-0" title="Xóa lịch sử">
|
|
<i class="bi bi-trash"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
@empty
|
|
<tr>
|
|
<td colspan="9" class="text-center py-4 text-muted">Không tìm thấy lịch sử nào.</td>
|
|
</tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
@if($histories->hasPages())
|
|
<div class="card-footer clearfix bg-light">
|
|
{{ $histories->links() }}
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Hidden Bulk & Single Delete Forms -->
|
|
<form id="bulk-delete-form" action="{{ route('history.bulk_destroy') }}" method="POST" style="display:none;">
|
|
@csrf
|
|
@method('DELETE')
|
|
</form>
|
|
|
|
<form id="single-delete-form" method="POST" style="display:none;">
|
|
@csrf
|
|
@method('DELETE')
|
|
</form>
|
|
@endsection
|
|
|
|
@push('scripts')
|
|
<script>
|
|
const selectAllCheckbox = document.getElementById('select-all');
|
|
const checkboxes = document.querySelectorAll('.history-checkbox');
|
|
const bulkDeleteBtn = document.getElementById('btn-bulk-delete');
|
|
const selectCountSpan = document.getElementById('select-count');
|
|
const bulkDeleteForm = document.getElementById('bulk-delete-form');
|
|
const singleDeleteForm = document.getElementById('single-delete-form');
|
|
|
|
// Toggle select all checkboxes
|
|
if (selectAllCheckbox) {
|
|
selectAllCheckbox.addEventListener('change', function() {
|
|
checkboxes.forEach(cb => {
|
|
cb.checked = this.checked;
|
|
});
|
|
updateBulkDeleteButton();
|
|
});
|
|
}
|
|
|
|
// Toggle single checkbox
|
|
checkboxes.forEach(cb => {
|
|
cb.addEventListener('change', function() {
|
|
if (!this.checked) {
|
|
selectAllCheckbox.checked = false;
|
|
} else {
|
|
const allChecked = Array.from(checkboxes).every(c => c.checked);
|
|
selectAllCheckbox.checked = allChecked;
|
|
}
|
|
updateBulkDeleteButton();
|
|
});
|
|
});
|
|
|
|
// Update bulk action button visibility
|
|
function updateBulkDeleteButton() {
|
|
const checkedCount = Array.from(checkboxes).filter(c => c.checked).length;
|
|
if (selectCountSpan) selectCountSpan.textContent = checkedCount;
|
|
|
|
if (checkedCount > 0) {
|
|
bulkDeleteBtn.classList.remove('d-none');
|
|
} else {
|
|
bulkDeleteBtn.classList.add('d-none');
|
|
}
|
|
}
|
|
|
|
// Trigger Bulk Delete Submit (append checked IDs dynamically)
|
|
function submitBulkDelete() {
|
|
const checkedBoxes = Array.from(checkboxes).filter(c => c.checked);
|
|
if (checkedBoxes.length === 0) return;
|
|
|
|
if (confirm(`Bạn có chắc chắn muốn xóa ${checkedBoxes.length} lịch sử đã chọn không?`)) {
|
|
// Remove old dynamic ID inputs from form if any
|
|
const existingInputs = bulkDeleteForm.querySelectorAll('input[name="ids[]"]');
|
|
existingInputs.forEach(input => input.remove());
|
|
|
|
// Create and append dynamic input fields for each checked item ID
|
|
checkedBoxes.forEach(cb => {
|
|
const hiddenInput = document.createElement('input');
|
|
hiddenInput.type = 'hidden';
|
|
hiddenInput.name = 'ids[]';
|
|
hiddenInput.value = cb.value;
|
|
bulkDeleteForm.appendChild(hiddenInput);
|
|
});
|
|
|
|
bulkDeleteForm.submit();
|
|
}
|
|
}
|
|
|
|
// Trigger Single Delete
|
|
function deleteSingle(id) {
|
|
if (confirm('Bạn có chắc muốn xóa lịch sử chuyển đổi này không?')) {
|
|
singleDeleteForm.action = `/history/${id}`;
|
|
singleDeleteForm.submit();
|
|
}
|
|
}
|
|
|
|
// Clipboard copy helper
|
|
function copyToClipboard(text, button) {
|
|
navigator.clipboard.writeText(text).then(() => {
|
|
const icon = button.querySelector('i');
|
|
icon.className = 'bi bi-check-lg';
|
|
button.className = 'btn btn-success btn-sm py-0 px-1 border-0';
|
|
setTimeout(() => {
|
|
icon.className = 'bi bi-clipboard';
|
|
button.className = 'btn btn-outline-primary btn-sm py-0 px-1 border-0';
|
|
}, 1500);
|
|
}).catch(err => {
|
|
console.error('Không thể copy link:', err);
|
|
});
|
|
}
|
|
</script>
|
|
@endpush
|