diff --git a/app/Http/Controllers/HukumController.php b/app/Http/Controllers/HukumController.php index a2a200d..2103a25 100644 --- a/app/Http/Controllers/HukumController.php +++ b/app/Http/Controllers/HukumController.php @@ -2,8 +2,15 @@ namespace App\Http\Controllers; +use App\Http\Requests\HukumRequest; +use App\Models\Hukum; +use App\Models\JenisSanksi; +use App\Models\Penaatan; +use App\Models\Perusahaan; use Illuminate\Http\Request; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Storage; use Inertia\Inertia; class HukumController extends Controller @@ -11,10 +18,116 @@ class HukumController extends Controller public function index() { try { - return Inertia::render('admin/hukum/index_hukum'); + $hukumData = Hukum::with(['perusahaan', 'jenisSanksi', 'penaatan'])->orderBy('created_at', 'desc')->get(); + return Inertia::render('admin/hukum/index_hukum', [ + 'hukumData' => $hukumData, + 'perusahaan' => Perusahaan::all(), + 'jenisSanksi' => JenisSanksi::all(), + 'penaatan' => Penaatan::all(), + ]); } catch (\Exception $e) { - Log::error('Error rendering view: ' . $e->getMessage()); - return back()->with('error', 'Something went wrong.'); + Log::error('Error fetching data: ' . $e->getMessage()); + return back()->with('error', 'Terjadi kesalahan saat memuat data.'); } } + + + public function store(HukumRequest $request) + { + try { + DB::beginTransaction(); + + $data = $request->validated(); + + if ($request->hasFile('SanksiFile')) { + $fileName = time() . '_' . $request->file('SanksiFile')->getClientOriginalName(); + $path = $request->file('SanksiFile')->storeAs('files/hukum/sanksi', $fileName, 'public'); + $data['SanksiFile'] = $path; + } + + if ($request->hasFile('PenaatanFile')) { + $fileName = time() . '_' . $request->file('PenaatanFile')->getClientOriginalName(); + $path = $request->file('PenaatanFile')->storeAs('files/hukum/penaatan', $fileName, 'public'); + $data['PenaatanFile'] = $path; + } + + Hukum::create($data); + + DB::commit(); + + return redirect()->route('admin.hukum.index')->with('success', 'Status Hukum berhasil ditambahkan'); + } catch (\Exception $e) { + DB::rollBack(); + Log::error('Error creating hukum: ' . $e->getMessage()); + return response()->json(['message' => 'Error: ' . $e->getMessage()], 500); + } + } + + public function update(HukumRequest $request, Hukum $hukum) + { + try { + DB::beginTransaction(); + + $data = $request->validated(); + + if ($request->hasFile('SanksiFile')) { + // Delete old file if exists + if ($hukum->SanksiFile && Storage::disk('public')->exists($hukum->SanksiFile)) { + Storage::disk('public')->delete($hukum->SanksiFile); + } + + $fileName = time() . '_' . $request->file('SanksiFile')->getClientOriginalName(); + $path = $request->file('SanksiFile')->storeAs('files/hukum/sanksi', $fileName, 'public'); + $data['SanksiFile'] = $path; + } + + if ($request->hasFile('PenaatanFile')) { + // Delete old file if exists + if ($hukum->PenaatanFile && Storage::disk('public')->exists($hukum->PenaatanFile)) { + Storage::disk('public')->delete($hukum->PenaatanFile); + } + + $fileName = time() . '_' . $request->file('PenaatanFile')->getClientOriginalName(); + $path = $request->file('PenaatanFile')->storeAs('files/hukum/penaatan', $fileName, 'public'); + $data['PenaatanFile'] = $path; + } + + $hukum->update($data); + + DB::commit(); + + return redirect()->route('admin.hukum.index')->with('success', 'Status Hukum berhasil diperbarui'); + } catch (\Exception $e) { + DB::rollBack(); + Log::error('Error updating hukum: ' . $e->getMessage()); + return response()->json(['message' => 'Error: ' . $e->getMessage()], 500); + } + } + + public function destroy(Hukum $hukum) + { + try { + DB::beginTransaction(); + + // Delete file if exists + if ($hukum->SanksiFile && Storage::disk('public')->exists($hukum->SanksiFile)) { + Storage::disk('public')->delete($hukum->SanksiFile); + } + + if ($hukum->PenaatanFile && Storage::disk('public')->exists($hukum->PenaatanFile)) { + Storage::disk('public')->delete($hukum->PenaatanFile); + } + + $hukum->delete(); + + DB::commit(); + + return redirect()->route('admin.hukum.index')->with('success', 'Status Hukum berhasil dihapus'); + } catch (\Exception $e) { + DB::rollBack(); + Log::error('Error deleting hukum: ' . $e->getMessage()); + return response()->json(['message' => 'Error: ' . $e->getMessage()], 500); + } + } + } diff --git a/app/Http/Requests/HukumRequest.php b/app/Http/Requests/HukumRequest.php index 4f351d2..868b2b8 100644 --- a/app/Http/Requests/HukumRequest.php +++ b/app/Http/Requests/HukumRequest.php @@ -22,12 +22,12 @@ class HukumRequest extends FormRequest public function rules(): array { return [ - 'PerusahaanId' => 'nullable|integer|exists:RefPerusahaan,id', - 'JenisSanksiId' => 'nullable|integer|exists:RefJenisSanksi,id', + 'PerusahaanId' => 'nullable|integer', + 'JenisSanksiId' => 'nullable|integer', 'SanksiNumber' => 'nullable|string|max:100', 'SanksiDate' => 'nullable|date', 'SanksiFile' => 'nullable|file|mimes:pdf|max:2048', - 'StatusPenaatan' => 'required|integer|in:1,2,3', + 'PenaatanId' => 'required|integer|in:1,2,3', 'PenaatanNumber' => 'nullable|string|max:100', 'PenaatanDate' => 'nullable|date', 'PenaatanFile' => 'nullable|file|mimes:pdf,jpg,png|max:2048', @@ -46,8 +46,8 @@ class HukumRequest extends FormRequest 'SanksiDate.date' => 'Tanggal SK Sanksi harus berupa format tanggal.', 'SanksiFile.mimes' => 'File Sanksi harus berupa PDF', 'SanksiFile.max' => 'Ukuran file maksimal 2MB.', - 'StatusPenaatan.required'=> 'Status Penaatan wajib diisi.', - 'StatusPenaatan.in' => 'Status Penaatan hanya boleh 1, 2, atau 3.', + 'PenaatanId.required'=> 'Status Penaatan wajib diisi.', + 'PenaatanId.in' => 'Status Penaatan hanya boleh 1, 2, atau 3.', 'PenaatanNumber.max' => 'Nomor SK Penaatan maksimal 100 karakter.', 'PenaatanDate.date' => 'Tanggal SK Penaatan harus berupa format tanggal.', 'PenaatanFile.mimes' => 'File Penaatan harus berupa PDF', diff --git a/app/Models/Hukum.php b/app/Models/Hukum.php index bda379f..6985c8c 100644 --- a/app/Models/Hukum.php +++ b/app/Models/Hukum.php @@ -10,6 +10,7 @@ class Hukum extends Model use HasFactory; protected $table = 'Hukum'; + protected $primaryKey = 'HukumId'; protected $fillable = [ 'PerusahaanId', @@ -17,23 +18,26 @@ class Hukum extends Model 'SanksiNumber', 'SanksiDate', 'SanksiFile', - 'StatusPenaatan', + 'PenaatanId', 'PenaatanNumber', 'PenaatanDate', 'PenaatanFile', - 'IsDeleted', ]; + public $timestamps = true; + public function perusahaan() { return $this->belongsTo(Perusahaan::class, 'PerusahaanId'); } - /** - * Relasi ke tabel jenis sanksi. - */ public function jenisSanksi() { return $this->belongsTo(JenisSanksi::class, 'JenisSanksiId'); } + + public function penaatan() + { + return $this->belongsTo(Penaatan::class, 'PenaatanId'); + } } diff --git a/database/migrations/2025_02_27_140639_remove__status_penaatan_add__penaatan_id.php b/database/migrations/2025_02_27_140639_remove__status_penaatan_add__penaatan_id.php new file mode 100644 index 0000000..f684651 --- /dev/null +++ b/database/migrations/2025_02_27_140639_remove__status_penaatan_add__penaatan_id.php @@ -0,0 +1,42 @@ +dropColumn('StatusPenaatan'); + + // Add PenaatanId column as foreign key + $table->unsignedInteger('PenaatanId')->nullable()->comment('id dari tabel Penaatan untuk mengambil NamaPenaatan'); + $table->foreign('PenaatanId')->references('PenaatanId')->on('Penaatan')->onDelete('set null'); + + // Add index for the new column + $table->index('PenaatanId'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Hukum', function (Blueprint $table) { + // Remove the foreign key constraint and the PenaatanId column + $table->dropForeign(['PenaatanId']); + $table->dropIndex(['PenaatanId']); + $table->dropColumn('PenaatanId'); + + // Add back the StatusPenaatan column with its original properties + $table->unsignedTinyInteger('StatusPenaatan')->default(1)->comment('1=pengawasan, 2=peningkatan sanksi, 3=taat'); + }); + } +}; diff --git a/database/migrations/xxxx_xx_xx_create_hukum_table.php b/database/migrations/xxxx_xx_xx_create_hukum_table.php new file mode 100644 index 0000000..e69de29 diff --git a/resources/js/components/modals/add-sanksi-hukum.tsx b/resources/js/components/modals/add-sanksi-hukum.tsx new file mode 100644 index 0000000..db2d504 --- /dev/null +++ b/resources/js/components/modals/add-sanksi-hukum.tsx @@ -0,0 +1,277 @@ +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogFooter, +} from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import Select from "react-select"; +import { useState, useEffect } from "react"; +import { useForm } from "@inertiajs/react"; +import { useToast } from "@/hooks/use-toast"; + +import { HukumType } from "@/types/perusahaan"; + +interface AddHukumModalProps { + open: boolean; + onClose: () => void; + onSuccess: () => void; + hukumtype: HukumType[]; + perusahaan: { PerusahaanId: number; NamaPerusahaan: string }[]; + jenisSanksi: { JenisSanksiId: number; NamaJenisSanksi: string }[]; + penaatan: { PenaatanId: number; NamaPenaatan: string }[]; + editingData?: HukumType | null; +} + +export function AddHukumModal({ + open, + onClose, + onSuccess, + hukumtype, + perusahaan, + jenisSanksi, + penaatan, + editingData, +}: AddHukumModalProps) { + const { toast } = useToast(); + const [loading, setLoading] = useState(false); + + const { data, setData, post, reset } = useForm<{ + PerusahaanId: string; + JenisSanksiId: string; + SanksiNumber: string; + SanksiDate: string; + SanksiFile: File | null; + PenaatanId: string; + PenaatanNumber: string; + PenaatanDate: string; + PenaatanFile: File | null; + currentSanksiFile?: string; + currentPenaatanFile?: string; + }>({ + PerusahaanId: editingData?.PerusahaanId?.toString() || "", + JenisSanksiId: editingData?.JenisSanksiId?.toString() || "", + SanksiNumber: editingData?.SanksiNumber || "", + SanksiDate: editingData?.SanksiDate || "", + SanksiFile: null, + currentSanksiFile: editingData?.SanksiFile, + PenaatanId: editingData?.PenaatanId?.toString() || "", + PenaatanNumber: editingData?.PenaatanNumber || "", + PenaatanDate: editingData?.PenaatanDate || "", + PenaatanFile: null, + currentPenaatanFile: editingData?.PenaatanFile, + }); + + useEffect(() => { + if (editingData) { + setData({ + PerusahaanId: editingData.PerusahaanId?.toString() || "", + JenisSanksiId: editingData.JenisSanksiId?.toString() || "", + SanksiNumber: editingData.SanksiNumber, + SanksiDate: editingData.SanksiDate, + SanksiFile: null, + currentSanksiFile: editingData.SanksiFile, + PenaatanId: editingData.PenaatanId?.toString() || "", + PenaatanNumber: "", + PenaatanDate: "", + PenaatanFile: null, + currentPenaatanFile: "", + }); + } else { + reset(); + } + }, [editingData, open]); + + const perusahaanOptions = perusahaan.map((p) => ({ + value: p.PerusahaanId.toString(), + label: p.NamaPerusahaan, + })); + + const jenisSanksiOptions = jenisSanksi.map((j) => ({ + value: j.JenisSanksiId.toString(), + label: j.NamaJenisSanksi, + })); + + const penaatanOptions = penaatan.map((j) => ({ + value: j.PenaatanId.toString(), + label: j.NamaPenaatan, + })); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + setLoading(true); + + const formData = new FormData(); + formData.append("PerusahaanId", data.PerusahaanId); + formData.append("JenisSanksiId", data.JenisSanksiId); + formData.append("SanksiNumber", data.SanksiNumber); + formData.append("SanksiDate", data.SanksiDate); + if (data.SanksiFile) formData.append("SanksiFile", data.SanksiFile); + + // Use the selected PenaatanId (no default fallback) + formData.append("PenaatanId", data.PenaatanId); + + // Only include these fields if they have values + if (data.PenaatanNumber) + formData.append("PenaatanNumber", data.PenaatanNumber); + if (data.PenaatanDate) + formData.append("PenaatanDate", data.PenaatanDate); + if (data.PenaatanFile) + formData.append("PenaatanFile", data.PenaatanFile); + + const url = editingData + ? `/admin/hukum/${editingData.HukumId}` + : "/admin/hukum"; + const method = editingData ? post : post; + + method(url, { + data: formData, + forceFormData: true, + onSuccess: () => { + toast({ + title: "Berhasil", + description: editingData + ? "Data berhasil diperbarui" + : "Data berhasil ditambahkan", + variant: "default", + }); + reset(); + setLoading(false); + onSuccess(); + onClose(); + }, + onError: () => { + toast({ + title: "Gagal", + description: "Terjadi kesalahan saat menyimpan data", + variant: "destructive", + }); + setLoading(false); + }, + }); + }; + + return ( + + + + + {editingData ? "Edit" : "Tambah"} Sanksi Administratif + + +
+
+ + j.value === data.JenisSanksiId + )} + onChange={(option) => + setData("JenisSanksiId", option?.value || "") + } + /> + + + + setData("SanksiNumber", e.target.value) + } + /> + + + + setData("SanksiDate", e.target.value) + } + /> + + +
+ + setData( + "SanksiFile", + e.target.files + ? e.target.files[0] + : null + ) + } + /> + {editingData?.SanksiFile && ( +
+ + File saat ini: {editingData.SanksiFile} + + +
+ )} +
+ + + - -
+ + + @@ -226,70 +198,226 @@ export default function HukumIndex() { Jenis SanksiNomor SK SanksiTanggal Sanksi - SK Sanksi + + SK Sanksi + Status Penaatan - Nomor Penaatan - Tanggal Penaatan + Nomor SK Penaatan + Tanggal SK PenaatanSK Penaatan - Aksi - {currentItems.map((hukum, index) => ( - - - {startIndex + index + 1} - - - {hukum.perusahaan?.nama} - - - {hukum.jenisSanksi?.nama} - - - {hukum.SanksiNumber} - - - {hukum.SanksiDate} - - - {hukum.SanksiFile} - - - {hukum.StatusPenaatan} - - - {hukum.PenaatanNumber} - - - {hukum.PenaatanDate} - - - {hukum.PenaatanFile} - - - - + {currentItems?.length > 0 ? ( + currentItems.map((hukum, index) => ( + + + {startIndex + index + 1} + + + + + + + {hukum.jenis_sanksi + ?.NamaJenisSanksi || "-"} + + + {hukum.SanksiNumber || "-"} + + + {hukum.SanksiDate + ? new Date( + hukum.SanksiDate + ).toLocaleDateString( + "id-ID", + { + day: "2-digit", + month: "long", + year: "numeric", + } + ) + : "-"} + + + {hukum.SanksiFile ? ( + + + + ) : ( + "-" + )} + + + + + + {hukum.PenaatanNumber || "-"} + + + {hukum.PenaatanDate + ? new Date( + hukum.PenaatanDate + ).toLocaleDateString( + "id-ID", + { + day: "2-digit", + month: "long", + year: "numeric", + } + ) + : "-"} + + + {hukum.PenaatanFile ? ( + + + + ) : ( + "-" + )} + + + )) + ) : ( + + + Tidak ada data - ))} + )}
+ {/* Pagination */} +
+ + +
+ + {/* Modal for Adding/Editing Hukum */} + setIsModalOpen(false)} + onSuccess={handleSuccess} + hukumtype={hukumData} + perusahaan={perusahaan} + penaatan={penaatan} + jenisSanksi={jenisSanksi} + editingData={editingData} + /> + + {/* Modal for Updating Penaatan */} + setIsPenaatanModalOpen(false)} + onSuccess={() => { + toast({ + title: "Berhasil", + description: "Penaatan diperbarui", + variant: "default", + }); + setIsPenaatanModalOpen(false); + }} + editingData={selectedHukum} + penaatan={penaatan} + /> + + {/* Delete Confirmation Dialog */} + + + + Konfirmasi Hapus + + Apakah anda yakin ingin menghapus data sanksi untuk + perusahaan{" "} + + {deletingData?.perusahaan?.NamaPerusahaan} + + ? +
+ Tindakan ini tidak dapat dibatalkan. +
+
+ + + Batal + + { + e.preventDefault(); + handleDeleteConfirm(); + }} + disabled={isDeleting} + className="bg-red-600 hover:bg-red-700 text-white" + > + {isDeleting ? "Menghapus..." : "Hapus"} + + +
+
+ );