Feat: Create a Service for Download Proof and make it reusable

This commit is contained in:
Sallu9007
2025-05-11 15:41:58 +05:30
parent c224497740
commit 6e634eda5a
4 changed files with 141 additions and 58 deletions

View File

@@ -6,6 +6,7 @@ use Illuminate\Http\Request;
use Yajra\DataTables\Facades\DataTables;
use App\Models\ActivitiesAttended;
use Illuminate\Support\Facades\Storage;
use App\Services\ProofDownloadService;
class ActivitiesAttendedController extends Controller
{
@@ -113,7 +114,7 @@ class ActivitiesAttendedController extends Controller
return response()->json(['success' => 'Record deleted successfully']);
}
public function downloadProofs(Request $request)
public function downloadProofs(Request $request, ProofDownloadService $proofDownloadService)
{
// Validate the request
$request->validate([
@@ -122,62 +123,14 @@ class ActivitiesAttendedController extends Controller
$ids = json_decode($request->input('ids'));
if (empty($ids)) {
return back()->with('error', 'No items selected');
}
$result = $proofDownloadService->downloadProofs(ActivitiesAttended::class, $ids);
// Get the records with proofs
$responses = ActivitiesAttended::whereIn('id', $ids)
->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');
if (isset($result['error'])) {
return back()->with('error', $result['error']);
}
// 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)

View 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,
];
}
}

View 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>

View File

@@ -139,12 +139,10 @@
</div>
</div>
</div>
<button id="download-proofs" class="btn btn-success ms-2" disabled>
<i class="fas fa-download me-1"></i> Download Proofs
</button>
<!-- Include the reusable download-proofs component -->
<x-download-proofs :route="route('activitiesAttended.downloadProofs')" />
</div>
<!-- Table -->
<div class="table-responsive">
<table id="responses-table" class="table table-striped table-hover">
@@ -265,7 +263,6 @@
</div>
</div>
@endif
@endsection
@section('scripts')