diff --git a/app/Exports/ExportDataSarana.php b/app/Exports/ExportDataSarana.php new file mode 100644 index 000000000..5a2cb2b51 --- /dev/null +++ b/app/Exports/ExportDataSarana.php @@ -0,0 +1,82 @@ +data = $data; + $this->author = $author; + } + + public function collection() + { + return $this->data->map(function ($item) { + return [ + $item->id, + $item->desa->nama ?? '-', + $item->nama, + $item->jumlah, + $item->kategori, + $item->keterangan, + ]; + }); + } + + public function headings(): array + { + return [ + ['Laporan Data Sarana'], + [''], + ['ID', 'Desa', 'Nama Sarana', 'Jumlah', 'Kategori', 'Keterangan'], + ]; + } + + public function styles(Worksheet $sheet) + { + return [ + 1 => ['font' => ['bold' => true, 'size' => 14]], + 3 => ['font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']]], + ]; + } + + public function registerEvents(): array + { + return [ + AfterSheet::class => function (AfterSheet $event) { + $sheet = $event->sheet->getDelegate(); + + $sheet->mergeCells('A1:F1'); + $sheet->getStyle('A1')->getAlignment()->setHorizontal('center'); + + $sheet->setCellValue('A2', 'Nama: ' . $this->author); + $sheet->setCellValue('F2', 'Tanggal: ' . date('d-m-Y')); + + $sheet->getStyle('A2')->getAlignment()->setHorizontal('left'); + $sheet->getStyle('F2')->getAlignment()->setHorizontal('right'); + + $sheet->getStyle('A3:F3')->getFill() + ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID) + ->getStartColor()->setARGB('4CAF50'); + + $lastRow = $sheet->getHighestRow(); + $sheet->getStyle("A3:F{$lastRow}") + ->getBorders() + ->getAllBorders() + ->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); + }, + ]; + } +} diff --git a/app/Http/Controllers/Data/DataSaranaController.php b/app/Http/Controllers/Data/DataSaranaController.php new file mode 100644 index 000000000..236d443bc --- /dev/null +++ b/app/Http/Controllers/Data/DataSaranaController.php @@ -0,0 +1,169 @@ +desa_id) { + $query->where('desa_id', $request->desa_id); + } + if ($request->kategori) { + $query->where('kategori', $request->kategori); + } + + return datatables()->of($query) + ->addColumn('desa', function ($row) { + return $row->desa ? $row->desa->nama : '-'; + }) + ->addColumn('aksi', function ($row) { + $editUrl = route('data.data-sarana.edit', $row->id); + $deleteUrl = route('data.data-sarana.destroy', $row->id); + + return view('data.data_sarana.partials.action', compact('editUrl', 'deleteUrl'))->render(); + }) + ->rawColumns(['aksi']) + ->make(true); + } + + + public function create() + { + $page_title = "Tambah Sarana"; + $page_description = "Form tambah data sarana"; + + $desas = DataDesa::all(); + return view('data.data_sarana.create', compact('page_title', 'page_description', 'desas')); + } + + public function store(Request $request) + { + try { + $request->validate([ + 'desa_id' => 'required|integer:desa_id', + 'nama' => 'required|string|max:255', + 'jumlah' => 'required|integer|min:0', + 'kategori' => 'required|string|max:100', + 'keterangan' => 'required|string:max:255', + ]); + DataSarana::create($request->all()); + } catch (\Exception $e) { + report($e); + return back()->withInput()->with('error', 'Data Sarana gagal disimpan!'); + } + return redirect()->route('data.data-sarana.index')->with('success', 'Data Sarana berhasil disimpan!'); + } + + public function edit($id) + { + $page_title = 'Edit Data Sarana'; + $page_description = 'Ubah informasi sarana desa'; + + $sarana = DataSarana::findOrFail($id); + $desas = DataDesa::all(); + + return view('data.data_sarana.edit', compact('page_title', 'page_description', 'sarana', 'desas')); + } + + public function update(Request $request, $id) + { + try { + $request->validate([ + 'desa_id' => 'required|integer:desa_id', + 'nama' => 'required|string|max:255', + 'jumlah' => 'required|integer|min:0', + 'kategori' => 'required|string|max:100', + 'keterangan' => 'required|string:max:255', + ]); + $sarana = DataSarana::findOrFail($id); + $sarana->update($request->all()); + } catch (\Exception $e) { + report($e); + return back()->withInput()->with('error', 'Data Sarana gagal diperbarui'); + } + return redirect()->route('data.data-sarana.index')->with('success', 'Data Sarana berhasil diperbarui'); + } + + public function destroy($id) + { + try { + $sarana = DataSarana::findOrFail($id); + $sarana->delete(); + } catch (\Exception $e) { + report($e); + return back()->withInput()->with('error', 'Data Sarana gagal dihapus'); + } + return redirect()->route('data.data-sarana.index')->with('success', 'Data Sarana berhasil dihapus'); + } + + public function export() + { + try { + $search = request('search'); + $kategori = request('kategori'); + $startDate = request('start_date'); + $endDate = request('end_date'); + + $data = \App\Models\DataSarana::with('desa') + ->when($search, fn($q) => $q->where('nama', 'like', "%$search%")) + ->when($kategori, fn($q) => $q->where('kategori', $kategori)) + ->when($startDate, fn($q) => $q->whereDate('created_at', '>=', $startDate)) + ->when($endDate, fn($q) => $q->whereDate('created_at', '<=', $endDate)) + ->latest('id') + ->get(); + + return Excel::download(new ExportDataSarana($data, 'Admin Desa'), 'data_sarana.xlsx'); + } catch (\Exception $e) { + report($e); + return back()->withInput()->with('error', 'Data Sarana gagal dihapus'); + } + } + + public function import() + { + $page_title = "Import Sarana"; + $page_description = "Upload data sarana"; + + $desas = DataDesa::all(); + + return view('data.data_sarana.import', compact('page_title', 'page_description', 'desas')); + } + + public function importExcel(Request $request) + { + try { + $request->validate([ + 'file' => 'required|mimes:xlsx,xls,csv' + ]); + Excel::import(new ImportDataSarana, $request->file('file')); + } catch (\Exception $e) { + report($e); + return back()->withInput()->with('error', 'Data Sarana gagal diimport'); + } + return redirect()->route('data.data-sarana.index')->with('success', 'Data Sarana berhasil diimport'); + } + +} diff --git a/app/Http/Controllers/Data/DataUmumController.php b/app/Http/Controllers/Data/DataUmumController.php index be9f7d6c4..c916a65bc 100644 --- a/app/Http/Controllers/Data/DataUmumController.php +++ b/app/Http/Controllers/Data/DataUmumController.php @@ -36,6 +36,7 @@ use App\Models\DataUmum; use Illuminate\Http\Request; use Illuminate\Http\Response; +use Illuminate\Support\Facades\DB; class DataUmumController extends Controller { @@ -51,7 +52,12 @@ public function index() $page_title = 'Data Umum'; $page_description = 'Ubah Data Umum'; - return view('data.data_umum.edit', compact('page_title', 'page_description', 'data_umum', 'luas_wilayah')); + $rekapKategori = DB::table('das_data_sarana') + ->select('kategori', DB::raw('SUM(jumlah) as total')) + ->groupBy('kategori') + ->pluck('total', 'kategori'); + + return view('data.data_umum.edit', compact('page_title', 'page_description', 'data_umum', 'luas_wilayah', 'rekapKategori')); } /** diff --git a/app/Imports/ImportDataSarana.php b/app/Imports/ImportDataSarana.php new file mode 100644 index 000000000..c026fb43c --- /dev/null +++ b/app/Imports/ImportDataSarana.php @@ -0,0 +1,31 @@ +exists()) { + return null; + } + + return new DataSarana([ + 'desa_id' => $row['desa_id'], + 'nama' => $row['nama'], + 'jumlah' => $row['jumlah'], + 'kategori' => $row['kategori'], + 'keterangan' => $row['keterangan'], + ]); + } +} diff --git a/app/Models/DataDesa.php b/app/Models/DataDesa.php index 832b2695e..81fe0fb20 100644 --- a/app/Models/DataDesa.php +++ b/app/Models/DataDesa.php @@ -181,4 +181,9 @@ public function pembangunan() { return $this->hasMany(Pembangunan::class, 'desa_id', 'desa_id'); } + + public function saranas() + { + return $this->hasMany(DataSarana::class, 'desa_id', 'id'); + } } diff --git a/app/Models/DataSarana.php b/app/Models/DataSarana.php new file mode 100644 index 000000000..73604472e --- /dev/null +++ b/app/Models/DataSarana.php @@ -0,0 +1,20 @@ +belongsTo(DataDesa::class, 'desa_id', 'id'); + } +} diff --git a/database/factories/DataSaranaFactory.php b/database/factories/DataSaranaFactory.php new file mode 100644 index 000000000..110edf463 --- /dev/null +++ b/database/factories/DataSaranaFactory.php @@ -0,0 +1,27 @@ + DataDesa::factory(), // otomatis buat desa baru + 'nama' => $this->faker->word, + 'jumlah' => $this->faker->numberBetween(1, 100), + 'kategori' => $this->faker->randomElement([ + 'puskesmas','puskesmas_pembantu','posyandu','pondok_bersalin', + 'paud','sd','smp','sma', + 'masjid_besar','mushola','gereja','pasar','balai_pertemuan' + ]), + 'keterangan' => $this->faker->sentence, + ]; + } +} diff --git a/database/migrations/2025_09_23_115608_create_saranas_table.php b/database/migrations/2025_09_23_115608_create_saranas_table.php new file mode 100644 index 000000000..eecb7a36b --- /dev/null +++ b/database/migrations/2025_09_23_115608_create_saranas_table.php @@ -0,0 +1,36 @@ +bigIncrements('id'); + + $table->unsignedInteger('desa_id'); + $table->foreign('desa_id')->references('id')->on('das_data_desa')->onDelete('cascade'); + + $table->string('kategori', 191); + $table->string('nama', 191)->nullable(); + $table->integer('jumlah')->default(0); + $table->text('keterangan')->nullable(); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('das_data_sarana'); + } +}; diff --git a/database/seeders/DasDataSaranaTableSeeder.php b/database/seeders/DasDataSaranaTableSeeder.php new file mode 100644 index 000000000..fcdc0c90c --- /dev/null +++ b/database/seeders/DasDataSaranaTableSeeder.php @@ -0,0 +1,60 @@ +delete(); + DB::statement('ALTER TABLE das_data_desa AUTO_INCREMENT = 1'); // reset id + + DB::table('das_data_desa')->insert([ + 'id' => 1, + 'profil_id' => 1, + 'desa_id' => 1333222, + 'nama' => 'Desa Contoh', + 'sebutan_desa' => 'Desa', + 'website' => 'https://desa-contoh.id', + 'path' => json_encode(['desa-contoh']), // ✅ JSON valid + 'luas_wilayah' => 1234, + 'created_at' => now(), + 'updated_at' => now(), + ]); + + // Untuk das_data_sarana bisa truncate karena hanya referensi ke desa_id + DB::table('das_data_sarana')->truncate(); + + DB::table('das_data_sarana')->insert([ + [ + 'id' => 2, + 'desa_id' => 1, + 'kategori' => 'puskesmas', + 'nama' => 'Puskesmas', + 'jumlah' => 1, + 'keterangan' => 'Puskesmas induk di pusat desa', + 'created_at' => now(), + 'updated_at' => now(), + ], + [ + 'id' => 3, + 'desa_id' => 1, + 'kategori' => 'masjid_besar', + 'nama' => 'Masjid', + 'jumlah' => 7, + 'keterangan' => null, + 'created_at' => now(), + 'updated_at' => now(), + ], + ]); + } +} diff --git a/resources/views/data/data_sarana/create.blade.php b/resources/views/data/data_sarana/create.blade.php new file mode 100644 index 000000000..1b436eaa2 --- /dev/null +++ b/resources/views/data/data_sarana/create.blade.php @@ -0,0 +1,99 @@ +@extends('layouts.dashboard_template') + +@section('content') +
+

{{ $page_title }}

+ {{ $page_description }} +
+ +
+
+
+

Tambah Data Sarana

+
+
+
+ @csrf + + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+
+ + Kembali + + +
+
+ +
+
+
+
+@endsection diff --git a/resources/views/data/data_sarana/edit.blade.php b/resources/views/data/data_sarana/edit.blade.php new file mode 100644 index 000000000..a49b8bc72 --- /dev/null +++ b/resources/views/data/data_sarana/edit.blade.php @@ -0,0 +1,103 @@ +@extends('layouts.dashboard_template') + +@section('content') +
+

{{ $page_title }}

+ {{ $page_description }} +
+ +
+
+
+

Edit Data Sarana

+
+
+
+ @csrf + @method('PUT') + + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+
+ + Kembali + + +
+
+
+
+
+
+@endsection diff --git a/resources/views/data/data_sarana/import.blade.php b/resources/views/data/data_sarana/import.blade.php new file mode 100644 index 000000000..4f851c8ae --- /dev/null +++ b/resources/views/data/data_sarana/import.blade.php @@ -0,0 +1,170 @@ +@extends('layouts.dashboard_template') + +@section('content') +
+

{{ $page_title }}

+ {{ $page_description }} +
+ +
+
+
+

Import Data Sarana

+
+
+
+ @csrf +
+ +
+ + +
+
+ +
+ + + +

Contoh Format Import Excel

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
desa_idnamajumlahkategoriketerangan
1Posyandu Melati3puskesmasBangunan permanen
2PAUD Tunas Bangsa2paudKondisi baik
3Pasar1pasarPerlu perbaikan pagar
+

List Kategori Data Sarana

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KategoriSub KategoriValue (Untuk kategori import)
Sarana KesehatanPuskesmaspuskesmas
Puskesmas Pembantupuskesmas_pembantu
Posyanduposyandu
Pondok Bersalinpondok_bersalin
Sarana PendidikanPAUD/Sederajatpaud
SD/Sederajatsd
SMP/Sederajatsmp
SMA/Sederajatsma
Sarana UmumMasjid Besarmasjid_besar
Musholamushola
Gerejagereja
Pasarpasar
Balai Pertemuanbalai_pertemuan
+ +

List Id Desa

+ + + + + + + + + @forelse($desas as $desa) + + + + + @empty + + + + @endforelse + +
IDNama Desa
{{ $desa->id }}{{ $desa->nama }}
Belum ada data desa
+
+
+
+@endsection diff --git a/resources/views/data/data_sarana/index.blade.php b/resources/views/data/data_sarana/index.blade.php new file mode 100644 index 000000000..9dd5e76c4 --- /dev/null +++ b/resources/views/data/data_sarana/index.blade.php @@ -0,0 +1,125 @@ +@extends('layouts.dashboard_template') + +@section('content') +
+

+ {{ $page_title ?? 'Page Title' }} + {{ $page_description ?? '' }} +

+ +
+ +
+ @include('partials.flash_message') + +
+
+
+
+ +
+ +
+ +
+ + + + + Import + + + Export + + + Tambah + +
+
+ +
+
+ + + + + + + + + + +
AksiNama SaranaJumlahKategoriDesa
+
+
+
+
+@endsection + +@include('partials.asset_datatables') + +@push('scripts') + +@include('forms.datatable-vertical') +@include('forms.delete-modal') +@endpush diff --git a/resources/views/data/data_sarana/partials/action.blade.php b/resources/views/data/data_sarana/partials/action.blade.php new file mode 100644 index 000000000..780fa61e9 --- /dev/null +++ b/resources/views/data/data_sarana/partials/action.blade.php @@ -0,0 +1,18 @@ + +
+ + + + +
+
+ @csrf + @method('DELETE') + +
+
+
\ No newline at end of file diff --git a/resources/views/data/data_umum/form_edit.blade.php b/resources/views/data/data_umum/form_edit.blade.php index 73c48b5cd..bf2594475 100644 --- a/resources/views/data/data_umum/form_edit.blade.php +++ b/resources/views/data/data_umum/form_edit.blade.php @@ -94,7 +94,8 @@
- {!! Form::number('jml_puskesmas', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} + {{-- {!! Form::number('jml_puskesmas', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} --}} +
@@ -102,7 +103,8 @@
- {!! Form::number('jml_puskesmas_pembantu', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} + {{-- {!! Form::number('jml_puskesmas_pembantu', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} --}} +
@@ -110,7 +112,8 @@
- {!! Form::number('jml_posyandu', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} + {{-- {!! Form::number('jml_posyandu', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} --}} +
@@ -118,7 +121,8 @@
- {!! Form::number('jml_pondok_bersalin', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} + {{-- {!! Form::number('jml_pondok_bersalin', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} --}} +
@@ -128,7 +132,8 @@
- {!! Form::number('jml_paud', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} + {{-- {!! Form::number('jml_paud', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} --}} +
@@ -136,7 +141,8 @@
- {!! Form::number('jml_sd', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} + {{-- {!! Form::number('jml_sd', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} --}} +
@@ -144,7 +150,8 @@
- {!! Form::number('jml_smp', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} + {{-- {!! Form::number('jml_smp', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} --}} +
@@ -152,7 +159,8 @@
- {!! Form::number('jml_sma', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} + {{-- {!! Form::number('jml_sma', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} --}} +
@@ -162,7 +170,8 @@
- {!! Form::number('jml_masjid_besar', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} + {{-- {!! Form::number('jml_masjid_besar', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} --}} +
@@ -170,7 +179,8 @@
- {!! Form::number('jml_mushola', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} + {{-- {!! Form::number('jml_mushola', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} --}} +
@@ -178,7 +188,8 @@
- {!! Form::number('jml_gereja', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} + {{-- {!! Form::number('jml_gereja', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} --}} +
@@ -186,7 +197,8 @@
- {!! Form::number('jml_pasar', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} + {{-- {!! Form::number('jml_pasar', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} --}} +
@@ -194,7 +206,8 @@
- {!! Form::number('jml_balai_pertemuan', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} + {{-- {!! Form::number('jml_balai_pertemuan', null, ['placeholder' => '0', 'class' => 'form-control', 'required', 'style' => 'text-align:right;']) !!} --}} +
diff --git a/resources/views/layouts/fragments/sidebar.blade.php b/resources/views/layouts/fragments/sidebar.blade.php index 22afbc22a..7dc04a89f 100644 --- a/resources/views/layouts/fragments/sidebar.blade.php +++ b/resources/views/layouts/fragments/sidebar.blade.php @@ -136,7 +136,7 @@