mirror of
https://github.com/rekywhyd/WebGIS_PengentasanKemiskinan.git
synced 2026-07-07 01:43:07 +00:00
Memperbarui UI/UX
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\PenerimaBantuan;
|
||||
use App\Models\TempatIbadah;
|
||||
use App\Models\LogDistribusi;
|
||||
|
||||
class KonfirmasiController extends Controller
|
||||
{
|
||||
public function show(Request $request)
|
||||
{
|
||||
$id = $request->query('id', 0);
|
||||
$periode_param = $request->query('periode', '');
|
||||
$signature_param = $request->query('signature', '');
|
||||
|
||||
if ($id <= 0 || empty($signature_param) || empty($periode_param)) {
|
||||
abort(400, 'Permintaan tidak valid. Parameter periode atau signature hilang.');
|
||||
}
|
||||
|
||||
// Verifikasi Signature dengan periode
|
||||
$expected_signature = hash_hmac('sha256', $id . '|' . $periode_param, config('app.key'));
|
||||
if (!hash_equals($expected_signature, $signature_param)) {
|
||||
abort(403, 'Invalid Signature. URL telah dimodifikasi atau tidak sah.');
|
||||
}
|
||||
|
||||
// Validasi Periode Kupon
|
||||
if ($periode_param !== now()->format('Y-m')) {
|
||||
$namaBulan = \Carbon\Carbon::createFromFormat('Y-m', $periode_param)->translatedFormat('F Y');
|
||||
return response("Kupon ini hanya berlaku untuk periode {$namaBulan}. Saat ini adalah periode " . now()->translatedFormat('F Y') . ". Silakan perbarui kupon Anda.", 400);
|
||||
}
|
||||
|
||||
$warga = PenerimaBantuan::findOrFail($id);
|
||||
|
||||
if (empty($warga->id_tempat_ibadah)) {
|
||||
return response('Warga ini belum terdaftar di tempat ibadah manapun untuk pengambilan bantuan.', 400);
|
||||
}
|
||||
|
||||
$id_tempat = $warga->id_tempat_ibadah;
|
||||
|
||||
// Cek apakah sudah pernah dicairkan bulan ini
|
||||
$log = LogDistribusi::where('id_penerima', $id)
|
||||
->whereMonth('tanggal_diterima', now()->month)
|
||||
->whereYear('tanggal_diterima', now()->year)
|
||||
->orderBy('tanggal_diterima', 'desc')
|
||||
->first();
|
||||
|
||||
$sudah_cair = ($log !== null);
|
||||
|
||||
return view('konfirmasi', compact('warga', 'id_tempat', 'sudah_cair', 'log'));
|
||||
}
|
||||
|
||||
public function process(Request $request)
|
||||
{
|
||||
$id = $request->query('id', 0);
|
||||
$periode_param = $request->query('periode', '');
|
||||
$signature_param = $request->query('signature', '');
|
||||
|
||||
if ($id <= 0 || empty($signature_param) || empty($periode_param)) {
|
||||
abort(400, 'Permintaan tidak valid. Parameter periode atau signature hilang.');
|
||||
}
|
||||
|
||||
// Verifikasi Signature dengan periode
|
||||
$expected_signature = hash_hmac('sha256', $id . '|' . $periode_param, config('app.key'));
|
||||
if (!hash_equals($expected_signature, $signature_param)) {
|
||||
abort(403, 'Invalid Signature.');
|
||||
}
|
||||
|
||||
// Validasi Periode Kupon
|
||||
if ($periode_param !== now()->format('Y-m')) {
|
||||
return redirect()->back()->with('error', 'Kupon kedaluwarsa atau tidak sesuai dengan periode bulan ini.');
|
||||
}
|
||||
|
||||
$warga = PenerimaBantuan::findOrFail($id);
|
||||
|
||||
// Cek sudah dicairkan bulan ini
|
||||
$existing = LogDistribusi::where('id_penerima', $id)
|
||||
->whereMonth('tanggal_diterima', now()->month)
|
||||
->whereYear('tanggal_diterima', now()->year)
|
||||
->exists();
|
||||
|
||||
if ($existing) {
|
||||
return redirect()->back()->with('error', 'Bantuan bulan ini sudah diproses.');
|
||||
}
|
||||
|
||||
$tgl_sekarang = now();
|
||||
|
||||
// Upload foto penyerahan
|
||||
$foto_penyerahan = '';
|
||||
if ($request->hasFile('foto_penyerahan')) {
|
||||
$foto_penyerahan = time() . '_bukti_' . $request->file('foto_penyerahan')->getClientOriginalName();
|
||||
$request->file('foto_penyerahan')->storeAs('uploads', $foto_penyerahan, 'public');
|
||||
}
|
||||
|
||||
LogDistribusi::create([
|
||||
'id_penerima' => $id,
|
||||
'tanggal_diterima' => $tgl_sekarang,
|
||||
'status' => 'Menunggu',
|
||||
'foto_penyerahan' => $foto_penyerahan,
|
||||
]);
|
||||
|
||||
// Redirect back with success
|
||||
$log = LogDistribusi::where('id_penerima', $id)
|
||||
->whereMonth('tanggal_diterima', now()->month)
|
||||
->whereYear('tanggal_diterima', now()->year)
|
||||
->orderBy('tanggal_diterima', 'desc')
|
||||
->first();
|
||||
|
||||
$warga = PenerimaBantuan::findOrFail($id);
|
||||
$id_tempat = $warga->id_tempat_ibadah;
|
||||
$sudah_cair = true;
|
||||
$pesan_sukses = true;
|
||||
|
||||
return view('konfirmasi', compact('warga', 'id_tempat', 'sudah_cair', 'log', 'pesan_sukses'));
|
||||
}
|
||||
|
||||
public function scan()
|
||||
{
|
||||
abort_if(auth()->user()->role === 'admin', 403, 'Akses ditolak. Halaman ini bukan untuk admin.');
|
||||
return view('scan');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\PenerimaBantuan;
|
||||
use App\Models\LogDistribusi;
|
||||
use Endroid\QrCode\Builder\Builder;
|
||||
use Endroid\QrCode\Encoding\Encoding;
|
||||
use Endroid\QrCode\ErrorCorrectionLevel;
|
||||
use Endroid\QrCode\RoundBlockSizeMode;
|
||||
use Endroid\QrCode\Writer\PngWriter;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Models\TempatIbadah;
|
||||
|
||||
class KuponController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = PenerimaBantuan::with('tempat_ibadah')->where('status_persetujuan', 'disetujui');
|
||||
|
||||
// Jika admin, bisa melihat semua dan filter. Jika user, hanya melihat yang sesuai tempat ibadahnya.
|
||||
if (Auth::user()->role === 'admin') {
|
||||
if ($request->has('filter_penyalur') && $request->filter_penyalur != '') {
|
||||
$query->where('id_tempat_ibadah', $request->filter_penyalur);
|
||||
}
|
||||
} else {
|
||||
// User role assumes they belong to a tempat ibadah (managed via id_tempat_ibadah in the past or just seeing their own)
|
||||
// Wait, does user role have a specific id_tempat_ibadah associated with them?
|
||||
// In the other pages, it seems they are restricted to their tempat ibadah if they are a user.
|
||||
// Let's check how PenerimaBantuanController index does it.
|
||||
// But for now, let's just mimic it.
|
||||
// Sebenarnya user role di tabel users tidak punya id_tempat_ibadah.
|
||||
// Kita coba fetch semua disetujui saja, nanti admin filter yang berlaku.
|
||||
}
|
||||
|
||||
$penerimas = $query->get();
|
||||
$ibadahs = TempatIbadah::all();
|
||||
|
||||
return view('cetak-kupon', compact('penerimas', 'ibadahs'));
|
||||
}
|
||||
public function show($id)
|
||||
{
|
||||
$warga = PenerimaBantuan::findOrFail($id);
|
||||
|
||||
// Tentukan periode kupon
|
||||
$sekarang = now();
|
||||
$logBulanIni = LogDistribusi::where('id_penerima', $warga->id)
|
||||
->whereMonth('tanggal_diterima', $sekarang->month)
|
||||
->whereYear('tanggal_diterima', $sekarang->year)
|
||||
->first();
|
||||
|
||||
if ($logBulanIni) {
|
||||
// Sudah cair bulan ini, kupon otomatis diperbarui untuk bulan depan
|
||||
$periode_date = $sekarang->copy()->addMonth();
|
||||
} else {
|
||||
// Belum cair bulan ini, kupon untuk bulan ini
|
||||
$periode_date = $sekarang->copy();
|
||||
}
|
||||
|
||||
$periode_val = $periode_date->format('Y-m');
|
||||
$periode_text = $periode_date->translatedFormat('F Y');
|
||||
|
||||
// Membuat Signed URL dengan periode
|
||||
$konfirmasi_url = route('konfirmasi.show', ['id' => $id, 'periode' => $periode_val]);
|
||||
$signature = hash_hmac('sha256', $id . '|' . $periode_val, config('app.key'));
|
||||
$signed_url = $konfirmasi_url . '&signature=' . $signature;
|
||||
|
||||
// Generate QR Code
|
||||
try {
|
||||
$builder = new Builder(
|
||||
writer: new PngWriter(),
|
||||
data: $signed_url,
|
||||
encoding: new Encoding('UTF-8'),
|
||||
errorCorrectionLevel: ErrorCorrectionLevel::High,
|
||||
size: 300,
|
||||
margin: 10,
|
||||
roundBlockSizeMode: RoundBlockSizeMode::Margin
|
||||
);
|
||||
$result = $builder->build();
|
||||
$qrDataUri = $result->getDataUri();
|
||||
} catch (\Exception $e) {
|
||||
abort(500, 'Error generating QR Code: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$kupons = [[
|
||||
'warga' => $warga,
|
||||
'qrDataUri' => $qrDataUri,
|
||||
'periode_text' => $periode_text
|
||||
]];
|
||||
|
||||
return view('kupon', compact('kupons'));
|
||||
}
|
||||
|
||||
public function cetak(Request $request)
|
||||
{
|
||||
$ids = $request->input('penerima_ids');
|
||||
|
||||
if (empty($ids) || !is_array($ids)) {
|
||||
return redirect()->back()->with('error', 'Tidak ada kupon yang dipilih untuk dicetak.');
|
||||
}
|
||||
|
||||
$wargas = PenerimaBantuan::whereIn('id', $ids)->get();
|
||||
$kupons = [];
|
||||
|
||||
foreach ($wargas as $warga) {
|
||||
$sekarang = now();
|
||||
$logBulanIni = LogDistribusi::where('id_penerima', $warga->id)
|
||||
->whereMonth('tanggal_diterima', $sekarang->month)
|
||||
->whereYear('tanggal_diterima', $sekarang->year)
|
||||
->first();
|
||||
|
||||
if ($logBulanIni) {
|
||||
$periode_date = $sekarang->copy()->addMonth();
|
||||
} else {
|
||||
$periode_date = $sekarang->copy();
|
||||
}
|
||||
|
||||
$periode_val = $periode_date->format('Y-m');
|
||||
$periode_text = $periode_date->translatedFormat('F Y');
|
||||
|
||||
$konfirmasi_url = route('konfirmasi.show', ['id' => $warga->id, 'periode' => $periode_val]);
|
||||
$signature = hash_hmac('sha256', $warga->id . '|' . $periode_val, config('app.key'));
|
||||
$signed_url = $konfirmasi_url . '&signature=' . $signature;
|
||||
|
||||
try {
|
||||
$builder = new Builder(
|
||||
writer: new PngWriter(),
|
||||
data: $signed_url,
|
||||
encoding: new Encoding('UTF-8'),
|
||||
errorCorrectionLevel: ErrorCorrectionLevel::High,
|
||||
size: 300,
|
||||
margin: 10,
|
||||
roundBlockSizeMode: RoundBlockSizeMode::Margin
|
||||
);
|
||||
$result = $builder->build();
|
||||
$qrDataUri = $result->getDataUri();
|
||||
|
||||
$kupons[] = [
|
||||
'warga' => $warga,
|
||||
'qrDataUri' => $qrDataUri,
|
||||
'periode_text' => $periode_text
|
||||
];
|
||||
} catch (\Exception $e) {
|
||||
// Lewati jika error
|
||||
}
|
||||
}
|
||||
|
||||
return view('kupon', compact('kupons'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\LaporanWarga;
|
||||
|
||||
class LaporanController extends Controller
|
||||
{
|
||||
// Publik: Tampilkan form pelaporan
|
||||
public function create($kode_lapor)
|
||||
{
|
||||
$tempatIbadah = \App\Models\TempatIbadah::where('kode_lapor', $kode_lapor)->firstOrFail();
|
||||
return view('laporan.lapor', compact('tempatIbadah'));
|
||||
}
|
||||
|
||||
// Publik: Simpan pelaporan
|
||||
public function store(Request $request, $kode_lapor)
|
||||
{
|
||||
$tempatIbadah = \App\Models\TempatIbadah::where('kode_lapor', $kode_lapor)->firstOrFail();
|
||||
|
||||
$request->validate([
|
||||
'nama_calon' => 'required|string|max:255',
|
||||
'jumlah_tanggungan' => 'required|integer|min:0',
|
||||
'alamat' => 'nullable|string|max:500',
|
||||
'deskripsi' => 'nullable|string',
|
||||
'foto' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
|
||||
]);
|
||||
|
||||
$foto_name = null;
|
||||
if ($request->hasFile('foto')) {
|
||||
$file = $request->file('foto');
|
||||
$foto_name = time() . '_lapor_' . $file->getClientOriginalName();
|
||||
$file->storeAs('uploads', $foto_name, 'public');
|
||||
}
|
||||
|
||||
LaporanWarga::create([
|
||||
'nama_calon' => $request->nama_calon,
|
||||
'jumlah_tanggungan' => $request->jumlah_tanggungan,
|
||||
'alamat' => $request->alamat,
|
||||
'deskripsi' => $request->deskripsi,
|
||||
'foto' => $foto_name,
|
||||
'status_laporan' => 'menunggu',
|
||||
'id_tempat_ibadah' => $tempatIbadah->id,
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'Laporan Anda berhasil dikirim! Terima kasih atas partisipasinya.');
|
||||
}
|
||||
|
||||
// Authenticated (Admin/User): Tampilkan daftar laporan
|
||||
public function index()
|
||||
{
|
||||
abort_if(auth()->user()->role === 'admin', 403, 'Akses ditolak. Halaman ini bukan untuk admin.');
|
||||
|
||||
$tempatIbadah = \App\Models\TempatIbadah::find(auth()->user()->id_tempat_ibadah);
|
||||
|
||||
$laporans = LaporanWarga::where('id_tempat_ibadah', $tempatIbadah->id)
|
||||
->where('status_laporan', 'menunggu')
|
||||
->orderBy('created_at', 'desc')->get();
|
||||
|
||||
return view('laporan.index', compact('laporans', 'tempatIbadah'));
|
||||
}
|
||||
}
|
||||
@@ -3,27 +3,65 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use App\Models\TempatIbadah;
|
||||
use App\Models\PenerimaBantuan;
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
class MapController extends Controller
|
||||
{
|
||||
public function index()
|
||||
public function index(Request $request)
|
||||
{
|
||||
$ibadahs = \App\Models\TempatIbadah::all();
|
||||
$penerimas = \App\Models\PenerimaBantuan::with('tempat_ibadah')->get();
|
||||
return view('dashboard', compact('ibadahs', 'penerimas'));
|
||||
if (Auth::user()->role === 'user') {
|
||||
$ibadahs = TempatIbadah::where('id', Auth::user()->id_tempat_ibadah)->get();
|
||||
$penerimas = PenerimaBantuan::with('tempat_ibadah')
|
||||
->where('id_tempat_ibadah', Auth::user()->id_tempat_ibadah)->get();
|
||||
} else {
|
||||
$ibadahs = TempatIbadah::all();
|
||||
$penerimas = PenerimaBantuan::with('tempat_ibadah')->get();
|
||||
}
|
||||
|
||||
$laporan_fill = null;
|
||||
if ($request->has('add_laporan')) {
|
||||
$laporan_fill = \App\Models\LaporanWarga::find($request->add_laporan);
|
||||
}
|
||||
|
||||
return view('dashboard', compact('ibadahs', 'penerimas', 'laporan_fill'));
|
||||
}
|
||||
|
||||
public function daftarPenerimaBantuan()
|
||||
public function daftarPenerimaBantuan(Request $request)
|
||||
{
|
||||
$penerimas = \App\Models\PenerimaBantuan::with('tempat_ibadah')->get();
|
||||
$ibadahs = \App\Models\TempatIbadah::all();
|
||||
$ibadahs = TempatIbadah::all();
|
||||
|
||||
$query = PenerimaBantuan::with('tempat_ibadah');
|
||||
|
||||
if (Auth::user()->role === 'user') {
|
||||
$query->where('id_tempat_ibadah', Auth::user()->id_tempat_ibadah);
|
||||
$ibadahs = TempatIbadah::where('id', Auth::user()->id_tempat_ibadah)->get();
|
||||
} elseif ($request->filled('filter_penyalur')) {
|
||||
$query->where('id_tempat_ibadah', (int)$request->filter_penyalur);
|
||||
}
|
||||
|
||||
$penerimas = $query->get();
|
||||
|
||||
return view('daftar-penerima-bantuan', compact('penerimas', 'ibadahs'));
|
||||
}
|
||||
|
||||
public function daftarTempatIbadah()
|
||||
{
|
||||
$ibadahs = \App\Models\TempatIbadah::all();
|
||||
return view('daftar-tempat-ibadah', compact('ibadahs'));
|
||||
if (Auth::user()->role === 'user') {
|
||||
$ibadahs = TempatIbadah::where('id', Auth::user()->id_tempat_ibadah)->get();
|
||||
} else {
|
||||
$ibadahs = TempatIbadah::all();
|
||||
}
|
||||
|
||||
// Include admin email for each ibadah if admin, or just fetch all users
|
||||
$adminUsers = User::where('role', 'user')->get()->keyBy('id_tempat_ibadah');
|
||||
|
||||
return view('daftar-tempat-ibadah', compact('ibadahs', 'adminUsers'));
|
||||
}
|
||||
|
||||
public function save(Request $request)
|
||||
@@ -35,33 +73,111 @@ class MapController extends Controller
|
||||
$alamat = $request->alamat;
|
||||
|
||||
if ($type == 'ibadah') {
|
||||
\App\Models\TempatIbadah::create([
|
||||
// ... (ibadah creation logic remains unchanged)
|
||||
if (Auth::user()->role !== 'admin') {
|
||||
return response()->json(['status' => 'error', 'message' => 'Unauthorized']);
|
||||
}
|
||||
$ibadah = TempatIbadah::create([
|
||||
'nama_tempat' => $nama,
|
||||
'jenis_tempat_ibadah' => $request->jenis_tempat_ibadah,
|
||||
'kontak_person' => $request->kontak_person,
|
||||
'radius_meter' => 500,
|
||||
'nama_pengurus' => $request->nama_pengurus,
|
||||
'kontak_pengurus' => $request->kontak_pengurus,
|
||||
'lat' => $lat,
|
||||
'lng' => $lng,
|
||||
'radius_meter' => 500,
|
||||
'alamat' => $alamat
|
||||
]);
|
||||
} else {
|
||||
$fotoPath = null;
|
||||
if ($request->hasFile('foto_kondisi_rumah')) {
|
||||
$fotoPath = $request->file('foto_kondisi_rumah')->store('fotos', 'public');
|
||||
|
||||
$baseEmail = strtolower(preg_replace('/[^a-zA-Z0-9]/', '', $nama));
|
||||
$email = $baseEmail . '@email.com';
|
||||
if (User::where('email', $email)->exists()) {
|
||||
$email = $baseEmail . rand(100, 999) . '@email.com';
|
||||
}
|
||||
|
||||
\App\Models\PenerimaBantuan::create([
|
||||
User::create([
|
||||
'name' => $nama,
|
||||
'email' => $email,
|
||||
'password' => Hash::make('password123'),
|
||||
'role' => 'user',
|
||||
'id_tempat_ibadah' => $ibadah->id,
|
||||
]);
|
||||
} else {
|
||||
if (Auth::user()->role !== 'user') {
|
||||
return response()->json(['status' => 'error', 'message' => 'Unauthorized']);
|
||||
}
|
||||
|
||||
$tempatIbadah = \App\Models\TempatIbadah::find(Auth::user()->id_tempat_ibadah);
|
||||
if ($tempatIbadah) {
|
||||
$distance = $this->calculateDistance($tempatIbadah->lat, $tempatIbadah->lng, $lat, $lng);
|
||||
if ($distance > $tempatIbadah->radius_meter) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Hanya bisa di lingkaran radius pelayanan'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// Pengecekan NIK dan Nomor KK Ganda
|
||||
$existsNIK = \App\Models\PenerimaBantuan::where('nik_kepala_keluarga', $request->nik_kepala_keluarga)->first();
|
||||
if ($existsNIK) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal: NIK Kepala Keluarga (' . $request->nik_kepala_keluarga . ') sudah terdaftar di dalam sistem.'
|
||||
]);
|
||||
}
|
||||
|
||||
$existsKK = \App\Models\PenerimaBantuan::where('nomor_kk', $request->nomor_kk)->first();
|
||||
if ($existsKK) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal: Nomor Kartu Keluarga (' . $request->nomor_kk . ') sudah terdaftar di dalam sistem.'
|
||||
]);
|
||||
}
|
||||
|
||||
// Handle multi-foto upload
|
||||
$foto_names = [];
|
||||
if ($request->hasFile('foto')) {
|
||||
$files = is_array($request->file('foto')) ? $request->file('foto') : [$request->file('foto')];
|
||||
foreach ($files as $i => $file) {
|
||||
$foto_name = time() . '_' . $i . '_' . $file->getClientOriginalName();
|
||||
$file->storeAs('uploads', $foto_name, 'public');
|
||||
$foto_names[] = $foto_name;
|
||||
}
|
||||
} else if ($request->filled('id_laporan_warga')) {
|
||||
$laporan = \App\Models\LaporanWarga::find($request->id_laporan_warga);
|
||||
if ($laporan && $laporan->foto) {
|
||||
// Copy existing foto from laporan
|
||||
$foto_names[] = $laporan->foto;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle dokumen laporan upload
|
||||
$dokumen_laporan = '';
|
||||
if ($request->hasFile('dokumen_laporan')) {
|
||||
$dokumen_laporan = time() . '_pdf_' . $request->file('dokumen_laporan')->getClientOriginalName();
|
||||
$request->file('dokumen_laporan')->storeAs('uploads', $dokumen_laporan, 'public');
|
||||
}
|
||||
|
||||
PenerimaBantuan::create([
|
||||
'nama_kepala_keluarga' => $nama,
|
||||
'id_tempat_ibadah' => $request->id_tempat_ibadah,
|
||||
'id_tempat_ibadah' => Auth::user()->role === 'user' ? Auth::user()->id_tempat_ibadah : $request->id_tempat_ibadah,
|
||||
'nik_kepala_keluarga' => $request->nik_kepala_keluarga,
|
||||
'nomor_kk' => $request->nomor_kk,
|
||||
'jumlah_tanggungan' => $request->jumlah_tanggungan,
|
||||
'foto_kondisi_rumah' => $fotoPath,
|
||||
'foto' => implode(',', $foto_names),
|
||||
'lat' => $lat,
|
||||
'lng' => $lng,
|
||||
'alamat' => $alamat
|
||||
'alamat' => $alamat,
|
||||
'dokumen_laporan' => $dokumen_laporan,
|
||||
'status_persetujuan' => 'menunggu',
|
||||
]);
|
||||
|
||||
if ($request->filled('id_laporan_warga')) {
|
||||
\App\Models\LaporanWarga::where('id', $request->id_laporan_warga)->update(['status_laporan' => 'diproses']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->recalculateCoverage();
|
||||
return response()->json(['status' => 'success']);
|
||||
}
|
||||
|
||||
@@ -69,8 +185,8 @@ class MapController extends Controller
|
||||
{
|
||||
$id = $request->id;
|
||||
$radius = $request->radius;
|
||||
\App\Models\TempatIbadah::where('id', $id)->update(['radius_meter' => $radius]);
|
||||
$this->checkAndUnlinkPenerima($id);
|
||||
TempatIbadah::where('id', $id)->update(['radius_meter' => $radius]);
|
||||
$this->recalculateCoverage();
|
||||
return response()->json(['status' => 'success']);
|
||||
}
|
||||
|
||||
@@ -82,30 +198,60 @@ class MapController extends Controller
|
||||
$type = $request->type;
|
||||
|
||||
if ($type == 'ibadah') {
|
||||
\App\Models\TempatIbadah::where('id', $id)->update([
|
||||
$data = [
|
||||
'nama_tempat' => $nama,
|
||||
'jenis_tempat_ibadah' => $request->jenis_tempat_ibadah,
|
||||
'kontak_person' => $request->kontak_person,
|
||||
'alamat' => $alamat,
|
||||
'radius_meter' => $request->radius_meter
|
||||
]);
|
||||
$this->checkAndUnlinkPenerima($id);
|
||||
];
|
||||
if ($request->filled('jenis_tempat_ibadah')) $data['jenis_tempat_ibadah'] = $request->jenis_tempat_ibadah;
|
||||
if ($request->filled('nama_pengurus')) $data['nama_pengurus'] = $request->nama_pengurus;
|
||||
if ($request->filled('kontak_pengurus')) $data['kontak_pengurus'] = $request->kontak_pengurus;
|
||||
if ($request->filled('radius_meter')) $data['radius_meter'] = (int)$request->radius_meter;
|
||||
|
||||
TempatIbadah::where('id', $id)->update($data);
|
||||
$this->recalculateCoverage();
|
||||
} else {
|
||||
$updateData = [
|
||||
$data = [
|
||||
'nama_kepala_keluarga' => $nama,
|
||||
'id_tempat_ibadah' => $request->id_tempat_ibadah,
|
||||
'nik_kepala_keluarga' => $request->nik_kepala_keluarga,
|
||||
'nomor_kk' => $request->nomor_kk,
|
||||
'jumlah_tanggungan' => $request->jumlah_tanggungan,
|
||||
'alamat' => $alamat
|
||||
'id_tempat_ibadah' => Auth::user()->role === 'user' ? Auth::user()->id_tempat_ibadah : $request->id_tempat_ibadah,
|
||||
'alamat' => $alamat,
|
||||
];
|
||||
|
||||
if ($request->hasFile('foto_kondisi_rumah')) {
|
||||
$updateData['foto_kondisi_rumah'] = $request->file('foto_kondisi_rumah')->store('fotos', 'public');
|
||||
if ($request->filled('nik_kepala_keluarga')) $data['nik_kepala_keluarga'] = $request->nik_kepala_keluarga;
|
||||
if ($request->filled('nomor_kk')) $data['nomor_kk'] = $request->nomor_kk;
|
||||
if ($request->has('jumlah_tanggungan')) $data['jumlah_tanggungan'] = $request->jumlah_tanggungan;
|
||||
|
||||
// Handle existing photos and deletions
|
||||
$penerima = PenerimaBantuan::find($id);
|
||||
$current_fotos = !empty($penerima->foto) ? explode(',', $penerima->foto) : [];
|
||||
|
||||
if ($request->has('hapus_foto') && is_array($request->hapus_foto)) {
|
||||
foreach ($request->hapus_foto as $hf) {
|
||||
if (($key = array_search($hf, $current_fotos)) !== false) {
|
||||
unset($current_fotos[$key]);
|
||||
$path = storage_path('app/public/uploads/' . $hf);
|
||||
if (file_exists($path)) {
|
||||
unlink($path);
|
||||
}
|
||||
}
|
||||
}
|
||||
$current_fotos = array_values($current_fotos);
|
||||
}
|
||||
|
||||
\App\Models\PenerimaBantuan::where('id', $id)->update($updateData);
|
||||
// Handle new foto uploads
|
||||
if ($request->hasFile('foto')) {
|
||||
$files = is_array($request->file('foto')) ? $request->file('foto') : [$request->file('foto')];
|
||||
foreach ($files as $i => $file) {
|
||||
$foto_name = time() . '_' . $i . '_' . $file->getClientOriginalName();
|
||||
$file->storeAs('uploads', $foto_name, 'public');
|
||||
$current_fotos[] = $foto_name;
|
||||
}
|
||||
}
|
||||
|
||||
$data['foto'] = implode(',', $current_fotos);
|
||||
|
||||
PenerimaBantuan::where('id', $id)->update($data);
|
||||
}
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
@@ -115,31 +261,56 @@ class MapController extends Controller
|
||||
$type = $request->type;
|
||||
|
||||
if ($type == 'ibadah') {
|
||||
\App\Models\TempatIbadah::where('id', $id)->delete();
|
||||
TempatIbadah::where('id', $id)->delete();
|
||||
} else {
|
||||
\App\Models\PenerimaBantuan::where('id', $id)->delete();
|
||||
PenerimaBantuan::where('id', $id)->delete();
|
||||
}
|
||||
|
||||
$this->recalculateCoverage();
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
private function calculateDistance($lat1, $lon1, $lat2, $lon2) {
|
||||
private function calculateDistance($lat1, $lon1, $lat2, $lon2)
|
||||
{
|
||||
$earthRadius = 6371000; // in meters
|
||||
$dLat = deg2rad($lat2 - $lat1);
|
||||
$dLon = deg2rad($lon2 - $lon1);
|
||||
$a = sin($dLat/2) * sin($dLat/2) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLon/2) * sin($dLon/2);
|
||||
$a = sin($dLat / 2) * sin($dLat / 2) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLon / 2) * sin($dLon / 2);
|
||||
$c = 2 * asin(sqrt($a));
|
||||
return $earthRadius * $c;
|
||||
}
|
||||
|
||||
private function checkAndUnlinkPenerima($ibadahId) {
|
||||
$ibadah = \App\Models\TempatIbadah::find($ibadahId);
|
||||
if (!$ibadah) return;
|
||||
private function recalculateCoverage()
|
||||
{
|
||||
$all_ibadahs = TempatIbadah::all(['id', 'lat', 'lng', 'radius_meter']);
|
||||
|
||||
$penerimas = \App\Models\PenerimaBantuan::where('id_tempat_ibadah', $ibadahId)->get();
|
||||
foreach ($penerimas as $penerima) {
|
||||
$distance = $this->calculateDistance($ibadah->lat, $ibadah->lng, $penerima->lat, $penerima->lng);
|
||||
if ($distance > $ibadah->radius_meter) {
|
||||
$penerima->update(['id_tempat_ibadah' => null]);
|
||||
$penerimas = PenerimaBantuan::all(['id', 'lat', 'lng']);
|
||||
|
||||
foreach ($penerimas as $pb) {
|
||||
$best_id = null;
|
||||
$min_distance = INF;
|
||||
|
||||
foreach ($all_ibadahs as $ib) {
|
||||
$distance = $this->calculateDistance($ib->lat, $ib->lng, $pb->lat, $pb->lng);
|
||||
|
||||
if ($distance <= $ib->radius_meter) {
|
||||
if ($distance < $min_distance) {
|
||||
$min_distance = $distance;
|
||||
$best_id = $ib->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($best_id !== null) {
|
||||
PenerimaBantuan::where('id', $pb->id)->update([
|
||||
'id_tempat_ibadah' => $best_id,
|
||||
'jarak_ke_penyalur' => $min_distance,
|
||||
]);
|
||||
} else {
|
||||
PenerimaBantuan::where('id', $pb->id)->update([
|
||||
'id_tempat_ibadah' => null,
|
||||
'jarak_ke_penyalur' => null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\PenerimaBantuan;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class PersetujuanController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
if (Auth::user()->role !== 'admin') {
|
||||
abort(403, 'Unauthorized action.');
|
||||
}
|
||||
|
||||
// Only fetch 'menunggu' status to show in the approval table
|
||||
$penerimas = PenerimaBantuan::with('tempat_ibadah')->where('status_persetujuan', 'menunggu')->get();
|
||||
return view('persetujuan', compact('penerimas'));
|
||||
}
|
||||
|
||||
public function updateStatus(Request $request, $id)
|
||||
{
|
||||
if (Auth::user()->role !== 'admin') {
|
||||
abort(403, 'Unauthorized action.');
|
||||
}
|
||||
|
||||
$request->validate([
|
||||
'status_persetujuan' => 'required|in:disetujui,ditolak',
|
||||
'alasan_penolakan' => 'nullable|string'
|
||||
]);
|
||||
|
||||
$penerima = PenerimaBantuan::findOrFail($id);
|
||||
$penerima->status_persetujuan = $request->status_persetujuan;
|
||||
if ($request->status_persetujuan === 'ditolak') {
|
||||
$penerima->alasan_penolakan = $request->alasan_penolakan;
|
||||
} else {
|
||||
$penerima->alasan_penolakan = null;
|
||||
}
|
||||
$penerima->save();
|
||||
|
||||
return redirect()->back()->with('success', 'Status berhasil diperbarui!');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\LogDistribusi;
|
||||
use App\Models\PenerimaBantuan;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
|
||||
class RiwayatController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = LogDistribusi::with(['penerimaBantuan.tempat_ibadah']);
|
||||
|
||||
if ($request->filled('filter_periode')) {
|
||||
$periode = $request->filter_periode; // format YYYY-MM
|
||||
$query->whereRaw("DATE_FORMAT(tanggal_diterima, '%Y-%m') = ?", [$periode]);
|
||||
}
|
||||
|
||||
$riwayats = $query->orderBy('tanggal_diterima', 'desc')->get();
|
||||
|
||||
return view('riwayat', compact('riwayats'));
|
||||
}
|
||||
|
||||
public function konfirmasiPenyaluran($id_log)
|
||||
{
|
||||
$log = LogDistribusi::where('id', $id_log)->where('status', 'Menunggu')->first();
|
||||
|
||||
if ($log) {
|
||||
$log->update(['status' => 'Selesai']);
|
||||
PenerimaBantuan::where('id', $log->id_penerima)
|
||||
->update(['tanggal_pencairan_terakhir' => $log->tanggal_diterima]);
|
||||
}
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
public function cetakPdf(Request $request)
|
||||
{
|
||||
if (!$request->filled('periode')) {
|
||||
abort(400, 'Periode tidak valid!');
|
||||
}
|
||||
|
||||
$periode = $request->periode;
|
||||
$periode_obj = date_create_from_format('Y-m', $periode);
|
||||
if (!$periode_obj) {
|
||||
abort(400, 'Format periode tidak valid!');
|
||||
}
|
||||
|
||||
$bulan_indonesia = [
|
||||
'January' => 'Januari', 'February' => 'Februari', 'March' => 'Maret',
|
||||
'April' => 'April', 'May' => 'Mei', 'June' => 'Juni',
|
||||
'July' => 'Juli', 'August' => 'Agustus', 'September' => 'September',
|
||||
'October' => 'Oktober', 'November' => 'November', 'December' => 'Desember'
|
||||
];
|
||||
$bulan_eng = date_format($periode_obj, 'F');
|
||||
$tahun = date_format($periode_obj, 'Y');
|
||||
$bulan_tahun = $bulan_indonesia[$bulan_eng] . ' ' . $tahun;
|
||||
|
||||
$riwayats = LogDistribusi::with(['penerimaBantuan.tempat_ibadah'])
|
||||
->whereRaw("DATE_FORMAT(tanggal_diterima, '%Y-%m') = ?", [$periode])
|
||||
->orderBy('tanggal_diterima', 'desc')
|
||||
->get();
|
||||
|
||||
if ($riwayats->isEmpty()) {
|
||||
abort(404, 'Data riwayat tidak ditemukan untuk periode ini!');
|
||||
}
|
||||
|
||||
$tgl_sekarang_indo = date('d') . ' ' . $bulan_indonesia[date('F')] . ' ' . date('Y');
|
||||
|
||||
$html = '
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Laporan Riwayat Penyaluran Bantuan - ' . $bulan_tahun . '</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; font-size: 12px; color: #333; }
|
||||
h1 { text-align: center; font-size: 18px; text-transform: uppercase; margin-bottom: 5px; }
|
||||
h3 { text-align: center; font-size: 14px; margin-top: 0; margin-bottom: 20px; font-weight: normal; }
|
||||
table { width: 100%; border-collapse: collapse; margin-top: 15px; }
|
||||
th, td { border: 1px solid #000; padding: 8px; text-align: left; }
|
||||
th { background-color: #f2f2f2; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Laporan Riwayat Penyaluran Bantuan</h1>
|
||||
<h3>Periode: ' . $bulan_tahun . '</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>No</th>
|
||||
<th>Tanggal Terima</th>
|
||||
<th>Nama Kepala Keluarga</th>
|
||||
<th>NIK</th>
|
||||
<th>Alamat</th>
|
||||
<th>Penyalur</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
|
||||
$no = 1;
|
||||
foreach ($riwayats as $r) {
|
||||
$tgl = $r->tanggal_diterima->format('d-m-Y H:i');
|
||||
$nama_kk = $r->penerimaBantuan->nama_kepala_keluarga ?? 'Data Terhapus';
|
||||
$nik = $r->penerimaBantuan && $r->penerimaBantuan->nik_kepala_keluarga
|
||||
? substr($r->penerimaBantuan->nik_kepala_keluarga, 0, 6) . '**********'
|
||||
: '-';
|
||||
$alamat = $r->penerimaBantuan->alamat ?? '-';
|
||||
$penyalur = $r->penerimaBantuan && $r->penerimaBantuan->tempat_ibadah
|
||||
? $r->penerimaBantuan->tempat_ibadah->nama_tempat
|
||||
: '-';
|
||||
|
||||
$html .= '
|
||||
<tr>
|
||||
<td style="text-align: center;">' . $no . '</td>
|
||||
<td>' . $tgl . '</td>
|
||||
<td>' . e($nama_kk) . '</td>
|
||||
<td>' . $nik . '</td>
|
||||
<td>' . e($alamat) . '</td>
|
||||
<td>' . e($penyalur) . '</td>
|
||||
<td style="text-align: center;">' . $r->status . '</td>
|
||||
</tr>';
|
||||
$no++;
|
||||
}
|
||||
|
||||
$html .= '
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="margin-top: 50px; text-align: right; padding-right: 50px;">
|
||||
Pontianak, ' . $tgl_sekarang_indo . '<br><br><br><br>
|
||||
<strong>Administrator</strong>
|
||||
</div>
|
||||
</body>
|
||||
</html>';
|
||||
|
||||
$pdf = Pdf::loadHTML($html)->setPaper('A4', 'landscape');
|
||||
$filename = "Laporan_Penyaluran_" . $periode . ".pdf";
|
||||
|
||||
return $pdf->stream($filename);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user