feat(stationmgmt): add CSV import and export buttons for station management
This commit is contained in:
35
src/app/Exports/StationExport.php
Normal file
35
src/app/Exports/StationExport.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exports;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Maatwebsite\Excel\Concerns\FromCollection;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
|
||||
class StationExport implements FromCollection, WithHeadings
|
||||
{
|
||||
public function collection()
|
||||
{
|
||||
return DB::table('station')
|
||||
->select('stationid', 'name', 'district', 'lng', 'lat', 'mainriverbasin', 'subriverbasin', 'rainfall', 'waterlevel', 'siren', 'cctv_link')
|
||||
->orderBy('stationid')
|
||||
->get();
|
||||
}
|
||||
|
||||
public function headings(): array
|
||||
{
|
||||
return [
|
||||
'Station ID',
|
||||
'Name',
|
||||
'District',
|
||||
'Longitude',
|
||||
'Latitude',
|
||||
'Main River Basin',
|
||||
'Sub River Basin',
|
||||
'Rainfall',
|
||||
'Water Level',
|
||||
'Siren',
|
||||
'CCTV Link',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,9 @@ use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Rules\Password;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use App\Exports\StationExport;
|
||||
use App\Imports\StationImport;
|
||||
|
||||
class AdminController extends Controller
|
||||
{
|
||||
@@ -271,4 +274,33 @@ class AdminController extends Controller
|
||||
return redirect()->back()->with('success',__('toast.userdeleted'));
|
||||
}
|
||||
|
||||
// Function Export Stations to CSV
|
||||
public function exportStations()
|
||||
{
|
||||
return Excel::download(new StationExport, 'stations.csv', \Maatwebsite\Excel\Excel::CSV);
|
||||
}
|
||||
|
||||
// Function Import Stations from CSV
|
||||
public function importStations(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'csv_file' => 'required|file|mimes:csv,txt|max:10240',
|
||||
]);
|
||||
|
||||
try {
|
||||
Excel::import(new StationImport, $request->file('csv_file'));
|
||||
return redirect()->route('stationmanagement')->with('success', __('toast.stationsimported'));
|
||||
} catch (\Maatwebsite\Excel\Validators\ValidationException $e) {
|
||||
$failures = $e->failures();
|
||||
$firstError = collect($failures)->first();
|
||||
$msg = $firstError
|
||||
? "Row {$firstError->row()}: {$firstError->errors()[0]}"
|
||||
: __('toast.error');
|
||||
return redirect()->route('stationmanagement')->with('error', $msg);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Station CSV import failed', ['error' => $e->getMessage()]);
|
||||
return redirect()->route('stationmanagement')->with('error', __('toast.error'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
37
src/app/Imports/StationImport.php
Normal file
37
src/app/Imports/StationImport.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Imports;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Maatwebsite\Excel\Concerns\ToCollection;
|
||||
use Illuminate\Support\Collection;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadingRow;
|
||||
|
||||
class StationImport implements ToCollection, WithHeadingRow
|
||||
{
|
||||
public function collection(Collection $rows)
|
||||
{
|
||||
foreach ($rows as $row) {
|
||||
$stationid = $row['station_id'] ?? $row['stationid'] ?? null;
|
||||
if (!$stationid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('station')->updateOrInsert(
|
||||
['stationid' => $stationid],
|
||||
[
|
||||
'name' => $row['name'] ?? '',
|
||||
'district' => $row['district'] ?? '',
|
||||
'lng' => is_numeric($row['longitude'] ?? null) ? $row['longitude'] : 0,
|
||||
'lat' => is_numeric($row['latitude'] ?? null) ? $row['latitude'] : 0,
|
||||
'mainriverbasin' => $row['main_river_basin'] ?? $row['mainriverbasin'] ?? '',
|
||||
'subriverbasin' => $row['sub_river_basin'] ?? $row['subriverbasin'] ?? '',
|
||||
'rainfall' => intval($row['rainfall'] ?? 0),
|
||||
'waterlevel' => intval($row['water_level'] ?? $row['waterlevel'] ?? 0),
|
||||
'siren' => intval($row['siren'] ?? 0),
|
||||
'cctv_link' => $row['cctv_link'] ?? null,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,6 +94,9 @@
|
||||
'nohistorysiren' => 'Tiada Data Sejarah Siren',
|
||||
'nocurrentsiren' => 'Tiada siren aktif sejak 7 hari lalu',
|
||||
'nodataavailable' => 'Tiada Data Tersedia',
|
||||
'dailyrainfall' => 'Hujan Harian',
|
||||
'importcsv' => 'Import CSV',
|
||||
'exportcsv' => 'Eksport CSV',
|
||||
|
||||
//Form
|
||||
'selectstation' => 'Pilih Stesen',
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
'passwordupdated' => 'Kata laluan berjaya dikemaskini',
|
||||
'stationdeleted' => 'Stesen berjaya dipadam',
|
||||
'userdeleted' => 'Pengguna berjaya dipadam',
|
||||
'linksupdated' => 'Pautan CCTV berjaya dikemaskini',
|
||||
'stationsimported' => 'Stesen berjaya diimport',
|
||||
];
|
||||
|
||||
|
||||
|
||||
@@ -91,6 +91,9 @@
|
||||
'nohistorysiren' => 'No Siren History Data',
|
||||
'nocurrentsiren' => 'No siren triggered for the past 7 days',
|
||||
'nodataavailable' => 'No Data Avaiable',
|
||||
'dailyrainfall' => 'Daily Rainfall',
|
||||
'importcsv' => 'Import CSV',
|
||||
'exportcsv' => 'Export CSV',
|
||||
|
||||
//Form
|
||||
'selectstation' => 'Select Station',
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
'passwordupdated' => 'Password updated succesfully',
|
||||
'stationdeleted' => 'Station deleted succesfully',
|
||||
'userdeleted' => 'User deleted successfully',
|
||||
'linksupdated' => 'CCTV link updated successfully',
|
||||
'stationsimported' => 'Stations imported successfully',
|
||||
];
|
||||
|
||||
|
||||
|
||||
@@ -60,8 +60,11 @@
|
||||
|
||||
</div>
|
||||
<div class="button-export d-flex justify-content-around m-3">
|
||||
<button type="button" class="btn btn-outline-primary btn-sm ms-auto" data-bs-toggle="modal"
|
||||
<button type="button" class="btn btn-outline-primary btn-sm" data-bs-toggle="modal"
|
||||
data-bs-target="#addModal">@lang('messages.addstation')</button>
|
||||
<button type="button" class="btn btn-outline-success btn-sm" data-bs-toggle="modal"
|
||||
data-bs-target="#importModal">@lang('messages.importcsv')</button>
|
||||
<a href="{{ route('stationmanagement.export.csv') }}" class="btn btn-outline-info btn-sm">@lang('messages.exportcsv')</a>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
@@ -343,10 +346,33 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Import CSV Modal -->
|
||||
<div class="modal fade" id="importModal" tabindex="-1" aria-labelledby="importModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<form method="POST" action="{{ route('stationmanagement.import.csv') }}" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<div class="modal-header bg-success text-white">
|
||||
<h5 class="modal-title" id="importModalLabel">@lang('messages.importcsv')</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="csv_file">CSV File</label>
|
||||
<input type="file" class="form-control" name="csv_file" id="csv_file" accept=".csv,.txt" required>
|
||||
<div class="form-text">Columns: Station ID, Name, District, Longitude, Latitude, Main River Basin, Sub River Basin, Rainfall (0/1), Water Level (0/1), Siren (0/1), CCTV Link</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer border-0">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">@lang('messages.cancel')</button>
|
||||
<button type="submit" class="btn btn-success">@lang('messages.importcsv')</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
@endsection
|
||||
@@ -74,6 +74,13 @@ Route::middleware(['admin'])->group(function () {
|
||||
Route::post('/stationmanagement/{stationid}/update',[App\Http\Controllers\AdminController::class, 'updateStation'])->name('stationmanagement.update');
|
||||
Route::delete('/stationmanagement/{stationid}/delete',[App\Http\Controllers\AdminController::class, 'deleteStation'])->name('stationmanagement.delete');
|
||||
|
||||
// CCTV Link Management
|
||||
Route::post('/cctv/{stationid}/update',[App\Http\Controllers\cctvController::class, 'updateCctvLink'])->name('cctv.update');
|
||||
|
||||
// Station CSV Import/Export
|
||||
Route::get('/stationmanagement/export-csv',[App\Http\Controllers\AdminController::class, 'exportStations'])->name('stationmanagement.export.csv');
|
||||
Route::post('/stationmanagement/import-csv',[App\Http\Controllers\AdminController::class, 'importStations'])->name('stationmanagement.import.csv');
|
||||
|
||||
// User Management
|
||||
Route::get('/usermgmt',[App\Http\Controllers\AdminController::class, 'userDisplay'])->name('usermgmt');
|
||||
Route::post('/usermgmt/store',[App\Http\Controllers\AdminController::class, 'storeUser'])->name('usermgmt.store');
|
||||
|
||||
Reference in New Issue
Block a user