timeout(10)->post("https://api.telegram.org/bot{$token}/sendMessage", [ 'chat_id' => $chatId, 'text' => $message, 'parse_mode' => 'Markdown', ]); } catch (\Exception $e) { \Log::error("Telegram Validasi Error: " . $e->getMessage()); } } /** * MENAMPILKAN DAFTAR DATA (INDEX) */ public function index() { $user = Auth::user(); $query = Validasi::orderBy('created_at', 'desc'); if ($user->role === 'admin' || $user->role === 'super admin') { $dataValidasi = $query->paginate(10); $viewPath = 'Validasi'; } else { $dataValidasi = $query->where('user_id', $user->id)->paginate(10); $viewPath = 'user.validasiuser'; } return view($viewPath, compact('dataValidasi')); } /** * MENYIMPAN DATA BARU (STORE) */ public function store(Request $request) { $user = Auth::user(); // --- PERBAIKAN DI SINI: Tambah Regex agar Nama tidak boleh angka --- $request->validate([ 'nik' => 'required|numeric|digits:16|unique:validasi,nik', 'nama_lengkap' => [ 'required', 'string', 'max:255', 'regex:/^[a-zA-Z\s]*$/' // Hanya huruf dan spasi ], 'tempat_lahir' => 'required|string|max:100', 'tanggal_lahir' => 'required|date', 'jenis_kelamin' => 'required|in:LAKI-LAKI,PEREMPUAN', 'alamat' => 'required|string', 'rt_rw' => 'required|string|max:10', 'desa_kelurahan' => 'required|string|max:100', 'kecamatan' => 'required|string|max:100', 'agama' => 'required|string|max:20', 'status_perkawinan' => 'required|string|max:30', 'pekerjaan' => 'nullable|string|max:100', 'kewarganegaraan' => 'required|string|max:5', 'foto_ktp' => 'required|image|mimes:jpg,jpeg,png|max:2048', ], [ // Custom Message agar user paham kenapa ditolak 'nama_lengkap.regex' => 'Nama lengkap tidak boleh mengandung angka atau simbol!', 'nik.unique' => 'NIK ini sudah terdaftar.', ]); $validasi = new Validasi(); $validasi->fill($request->except('foto_ktp')); $validasi->user_id = $user->id; $validasi->pekerjaan = $request->pekerjaan ?? '-'; $validasi->status = 'MENUNGGU'; $validasi->berlaku_hingga = 'SEUMUR HIDUP'; if ($request->hasFile('foto_ktp')) { $file = $request->file('foto_ktp'); $fileName = $request->nik . '_' . time() . '.' . $file->getClientOriginalExtension(); $file->move(public_path('foto_ktp'), $fileName); $validasi->foto_ktp = $fileName; } $validasi->save(); $msg = "🆕 *DATA VALIDASI BARU*\n\n" . "👤 *Nama:* {$request->nama_lengkap}\n" . "🆔 *NIK:* {$request->nik}\n" . "📍 *Alamat:* {$request->alamat}\n\n" . "--- _Mohon segera diperiksa di Dashboard_ ---"; $this->sendTelegramNotification($msg); return redirect()->back()->with('success', 'Data validasi berhasil dikirim!'); } /** * MENGUBAH DATA (UPDATE) */ public function update(Request $request, $nik) { $validasi = Validasi::where('nik', $nik)->firstOrFail(); $user = Auth::user(); $isAdmin = in_array($user->role, ['admin', 'super admin']); if (!$isAdmin && $validasi->user_id !== $user->id) { abort(403); } if (!$isAdmin && $validasi->status !== 'MENUNGGU') { return redirect()->back()->with('error', 'Data sudah diproses, tidak bisa diubah lagi.'); } // --- PERBAIKAN DI SINI: Tambah Regex di Update juga --- $request->validate([ 'nama_lengkap' => [ 'required', 'string', 'max:255', 'regex:/^[a-zA-Z\s]*$/' ], 'status' => 'nullable|in:MENUNGGU,DISETUJUI,DITOLAK', 'foto_ktp' => 'nullable|image|mimes:jpg,jpeg,png|max:2048', ], [ 'nama_lengkap.regex' => 'Nama lengkap tidak boleh mengandung angka!', ]); $statusLama = $validasi->status; $updateData = $request->except(['foto_ktp', 'nik', 'user_id']); if (!$isAdmin) { unset($updateData['status']); } $validasi->fill($updateData); if ($request->hasFile('foto_ktp')) { if ($validasi->foto_ktp && File::exists(public_path('foto_ktp/' . $validasi->foto_ktp))) { File::delete(public_path('foto_ktp/' . $validasi->foto_ktp)); } $file = $request->file('foto_ktp'); $fileName = $nik . '_' . time() . '.' . $file->getClientOriginalExtension(); $file->move(public_path('foto_ktp'), $fileName); $validasi->foto_ktp = $fileName; } $validasi->save(); if ($isAdmin && $request->has('status') && $request->status !== $statusLama) { $emoji = $request->status === 'DISETUJUI' ? '✅' : '❌'; $msg = "🔔 *UPDATE VALIDASI PENDUDUK*\n\n" . "Halo, *{$validasi->nama_lengkap}*\n" . "{$emoji} *Status Baru:* " . strtoupper($request->status) . "\n" . "⏰ *Waktu:* " . now()->format('d/m/Y H:i') . " WIB"; $this->sendTelegramNotification($msg); } return redirect()->back()->with('success', 'Data berhasil diperbarui.'); } /** * MENGHAPUS DATA (DESTROY) */ public function destroy($nik) { $validasi = Validasi::where('nik', $nik)->firstOrFail(); $user = Auth::user(); $isAdmin = in_array($user->role, ['admin', 'super admin']); if (!$isAdmin && $validasi->user_id !== $user->id) { abort(403); } if (!$isAdmin && $validasi->status !== 'MENUNGGU') { return redirect()->back()->with('error', 'Data sudah diproses, tidak bisa dihapus.'); } if ($validasi->foto_ktp && File::exists(public_path('foto_ktp/' . $validasi->foto_ktp))) { File::delete(public_path('foto_ktp/' . $validasi->foto_ktp)); } $validasi->delete(); return redirect()->back()->with('success', 'Data berhasil dihapus.'); } }