Feat: Create a Service for Download Proof and make it reusable
This commit is contained in:
@@ -6,6 +6,7 @@ use Illuminate\Http\Request;
|
|||||||
use Yajra\DataTables\Facades\DataTables;
|
use Yajra\DataTables\Facades\DataTables;
|
||||||
use App\Models\ActivitiesAttended;
|
use App\Models\ActivitiesAttended;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use App\Services\ProofDownloadService;
|
||||||
|
|
||||||
class ActivitiesAttendedController extends Controller
|
class ActivitiesAttendedController extends Controller
|
||||||
{
|
{
|
||||||
@@ -113,7 +114,7 @@ class ActivitiesAttendedController extends Controller
|
|||||||
return response()->json(['success' => 'Record deleted successfully']);
|
return response()->json(['success' => 'Record deleted successfully']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function downloadProofs(Request $request)
|
public function downloadProofs(Request $request, ProofDownloadService $proofDownloadService)
|
||||||
{
|
{
|
||||||
// Validate the request
|
// Validate the request
|
||||||
$request->validate([
|
$request->validate([
|
||||||
@@ -122,62 +123,14 @@ class ActivitiesAttendedController extends Controller
|
|||||||
|
|
||||||
$ids = json_decode($request->input('ids'));
|
$ids = json_decode($request->input('ids'));
|
||||||
|
|
||||||
if (empty($ids)) {
|
$result = $proofDownloadService->downloadProofs(ActivitiesAttended::class, $ids);
|
||||||
return back()->with('error', 'No items selected');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the records with proofs
|
if (isset($result['error'])) {
|
||||||
$responses = ActivitiesAttended::whereIn('id', $ids)
|
return back()->with('error', $result['error']);
|
||||||
->whereNotNull('proof')
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if ($responses->isEmpty()) {
|
|
||||||
return back()->with('error', 'No valid proofs found');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a temporary zip file
|
|
||||||
$zipFileName = 'proofs_' . time() . '.zip';
|
|
||||||
$zipFilePath = storage_path('app/public/temp/' . $zipFileName);
|
|
||||||
|
|
||||||
// Ensure the temp directory exists
|
|
||||||
if (!Storage::disk('public')->exists('temp')) {
|
|
||||||
Storage::disk('public')->makeDirectory('temp');
|
|
||||||
}
|
|
||||||
|
|
||||||
$zip = new \ZipArchive();
|
|
||||||
|
|
||||||
if ($zip->open($zipFilePath, \ZipArchive::CREATE) !== TRUE) {
|
|
||||||
return back()->with('error', 'Could not create zip file');
|
|
||||||
}
|
|
||||||
|
|
||||||
$fileCount = 0;
|
|
||||||
|
|
||||||
foreach ($responses as $response) {
|
|
||||||
if (Storage::disk('public')->exists($response->proof)) {
|
|
||||||
$fileContent = Storage::disk('public')->get($response->proof);
|
|
||||||
|
|
||||||
// Get original filename from path
|
|
||||||
$originalName = basename($response->proof);
|
|
||||||
|
|
||||||
// Add file to the zip with a prefix to avoid duplicate names
|
|
||||||
$fileNameInZip = $response->id . '_' . $originalName;
|
|
||||||
$zip->addFromString($fileNameInZip, $fileContent);
|
|
||||||
$fileCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$zip->close();
|
|
||||||
|
|
||||||
if ($fileCount === 0) {
|
|
||||||
// Delete the empty zip file
|
|
||||||
if (file_exists($zipFilePath)) {
|
|
||||||
unlink($zipFilePath);
|
|
||||||
}
|
|
||||||
return back()->with('error', 'No files found to download');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the zip file as a download
|
// Return the zip file as a download
|
||||||
return response()->download($zipFilePath, $zipFileName)->deleteFileAfterSend(true);
|
return response()->download($result['filePath'], $result['fileName'])->deleteFileAfterSend(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getActivitiesAttendedResponses(Request $request)
|
public function getActivitiesAttendedResponses(Request $request)
|
||||||
|
|||||||
81
app/Services/ProofDownloadService.php
Normal file
81
app/Services/ProofDownloadService.php
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use ZipArchive;
|
||||||
|
|
||||||
|
class ProofDownloadService
|
||||||
|
{
|
||||||
|
public function downloadProofs($model, $ids, $filePathColumn = 'proof')
|
||||||
|
{
|
||||||
|
// Validate IDs
|
||||||
|
if (empty($ids)) {
|
||||||
|
return [
|
||||||
|
'error' => 'No items selected',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch records with proofs
|
||||||
|
$responses = $model::whereIn('id', $ids)
|
||||||
|
->whereNotNull($filePathColumn)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
if ($responses->isEmpty()) {
|
||||||
|
return [
|
||||||
|
'error' => 'No valid proofs found',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary zip file
|
||||||
|
$zipFileName = 'proofs_' . time() . '.zip';
|
||||||
|
$zipFilePath = storage_path('app/public/temp/' . $zipFileName);
|
||||||
|
|
||||||
|
// Ensure the temp directory exists
|
||||||
|
if (!Storage::disk('public')->exists('temp')) {
|
||||||
|
Storage::disk('public')->makeDirectory('temp');
|
||||||
|
}
|
||||||
|
|
||||||
|
$zip = new ZipArchive();
|
||||||
|
|
||||||
|
if ($zip->open($zipFilePath, ZipArchive::CREATE) !== true) {
|
||||||
|
return [
|
||||||
|
'error' => 'Could not create zip file',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$fileCount = 0;
|
||||||
|
|
||||||
|
foreach ($responses as $response) {
|
||||||
|
if (Storage::disk('public')->exists($response->$filePathColumn)) {
|
||||||
|
$fileContent = Storage::disk('public')->get($response->$filePathColumn);
|
||||||
|
|
||||||
|
// Get original filename from path
|
||||||
|
$originalName = basename($response->$filePathColumn);
|
||||||
|
|
||||||
|
// Add file to the zip with a prefix to avoid duplicate names
|
||||||
|
$fileNameInZip = $response->id . '_' . $originalName;
|
||||||
|
$zip->addFromString($fileNameInZip, $fileContent);
|
||||||
|
$fileCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$zip->close();
|
||||||
|
|
||||||
|
if ($fileCount === 0) {
|
||||||
|
// Delete the empty zip file
|
||||||
|
if (file_exists($zipFilePath)) {
|
||||||
|
unlink($zipFilePath);
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
'error' => 'No files found to download',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'success' => true,
|
||||||
|
'filePath' => $zipFilePath,
|
||||||
|
'fileName' => $zipFileName,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
52
resources/views/components/download-proofs.blade.php
Normal file
52
resources/views/components/download-proofs.blade.php
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<div>
|
||||||
|
<!-- Download Proofs Button -->
|
||||||
|
<button id="download-proofs" class="btn btn-success" disabled>
|
||||||
|
<i class="fas fa-download me-1"></i> Download Proofs
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
const downloadProofsButton = document.getElementById('download-proofs');
|
||||||
|
|
||||||
|
downloadProofsButton.addEventListener('click', function () {
|
||||||
|
const selectedIds = [];
|
||||||
|
|
||||||
|
// Collect selected row IDs
|
||||||
|
document.querySelectorAll('.row-checkbox:checked').forEach(function (checkbox) {
|
||||||
|
selectedIds.push(checkbox.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (selectedIds.length > 0) {
|
||||||
|
const form = document.createElement('form');
|
||||||
|
form.method = 'POST';
|
||||||
|
form.action = "{{ $route }}";
|
||||||
|
|
||||||
|
const csrfInput = document.createElement('input');
|
||||||
|
csrfInput.type = 'hidden';
|
||||||
|
csrfInput.name = '_token';
|
||||||
|
csrfInput.value = "{{ csrf_token() }}";
|
||||||
|
form.appendChild(csrfInput);
|
||||||
|
|
||||||
|
const idsInput = document.createElement('input');
|
||||||
|
idsInput.type = 'hidden';
|
||||||
|
idsInput.name = 'ids';
|
||||||
|
idsInput.value = JSON.stringify(selectedIds);
|
||||||
|
form.appendChild(idsInput);
|
||||||
|
|
||||||
|
document.body.appendChild(form);
|
||||||
|
form.submit();
|
||||||
|
} else {
|
||||||
|
alert('No rows selected');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Enable/disable button based on row selection
|
||||||
|
document.querySelectorAll('.row-checkbox').forEach(function (checkbox) {
|
||||||
|
checkbox.addEventListener('change', function () {
|
||||||
|
const selectedRows = document.querySelectorAll('.row-checkbox:checked').length;
|
||||||
|
downloadProofsButton.disabled = selectedRows === 0;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
@@ -139,12 +139,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button id="download-proofs" class="btn btn-success ms-2" disabled>
|
<!-- Include the reusable download-proofs component -->
|
||||||
<i class="fas fa-download me-1"></i> Download Proofs
|
<x-download-proofs :route="route('activitiesAttended.downloadProofs')" />
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!-- Table -->
|
<!-- Table -->
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table id="responses-table" class="table table-striped table-hover">
|
<table id="responses-table" class="table table-striped table-hover">
|
||||||
@@ -265,7 +263,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('scripts')
|
@section('scripts')
|
||||||
|
|||||||
Reference in New Issue
Block a user