fixing perusahaan
parent
0562099ca0
commit
08c45c61ca
64
.env.example
64
.env.example
|
@ -1,64 +0,0 @@
|
||||||
APP_NAME=Laravel
|
|
||||||
APP_ENV=local
|
|
||||||
APP_KEY=
|
|
||||||
APP_DEBUG=true
|
|
||||||
APP_TIMEZONE=UTC
|
|
||||||
APP_URL=http://localhost
|
|
||||||
|
|
||||||
APP_LOCALE=en
|
|
||||||
APP_FALLBACK_LOCALE=en
|
|
||||||
APP_FAKER_LOCALE=en_US
|
|
||||||
|
|
||||||
APP_MAINTENANCE_DRIVER=file
|
|
||||||
APP_MAINTENANCE_STORE=database
|
|
||||||
|
|
||||||
BCRYPT_ROUNDS=12
|
|
||||||
|
|
||||||
LOG_CHANNEL=stack
|
|
||||||
LOG_STACK=single
|
|
||||||
LOG_DEPRECATIONS_CHANNEL=null
|
|
||||||
LOG_LEVEL=debug
|
|
||||||
|
|
||||||
DB_CONNECTION=sqlite
|
|
||||||
# DB_HOST=127.0.0.1
|
|
||||||
# DB_PORT=3306
|
|
||||||
# DB_DATABASE=laravel
|
|
||||||
# DB_USERNAME=root
|
|
||||||
# DB_PASSWORD=
|
|
||||||
|
|
||||||
SESSION_DRIVER=database
|
|
||||||
SESSION_LIFETIME=120
|
|
||||||
SESSION_ENCRYPT=false
|
|
||||||
SESSION_PATH=/
|
|
||||||
SESSION_DOMAIN=null
|
|
||||||
|
|
||||||
BROADCAST_CONNECTION=log
|
|
||||||
FILESYSTEM_DISK=local
|
|
||||||
QUEUE_CONNECTION=database
|
|
||||||
|
|
||||||
CACHE_STORE=database
|
|
||||||
CACHE_PREFIX=
|
|
||||||
|
|
||||||
MEMCACHED_HOST=127.0.0.1
|
|
||||||
|
|
||||||
REDIS_CLIENT=phpredis
|
|
||||||
REDIS_HOST=127.0.0.1
|
|
||||||
REDIS_PASSWORD=null
|
|
||||||
REDIS_PORT=6379
|
|
||||||
|
|
||||||
MAIL_MAILER=log
|
|
||||||
MAIL_HOST=127.0.0.1
|
|
||||||
MAIL_PORT=2525
|
|
||||||
MAIL_USERNAME=null
|
|
||||||
MAIL_PASSWORD=null
|
|
||||||
MAIL_ENCRYPTION=null
|
|
||||||
MAIL_FROM_ADDRESS="hello@example.com"
|
|
||||||
MAIL_FROM_NAME="${APP_NAME}"
|
|
||||||
|
|
||||||
AWS_ACCESS_KEY_ID=
|
|
||||||
AWS_SECRET_ACCESS_KEY=
|
|
||||||
AWS_DEFAULT_REGION=us-east-1
|
|
||||||
AWS_BUCKET=
|
|
||||||
AWS_USE_PATH_STYLE_ENDPOINT=false
|
|
||||||
|
|
||||||
VITE_APP_NAME="${APP_NAME}"
|
|
|
@ -63,4 +63,17 @@ class JenisKegiatanController extends Controller
|
||||||
return back()->with('error', 'Something went wrong.');
|
return back()->with('error', 'Something went wrong.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getAll()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$jeniskegiatan = JenisKegiatan::where('IsPublish', true)
|
||||||
|
->select('JenisKegiatanId', 'NamaJenisKegiatan')
|
||||||
|
->get();
|
||||||
|
return response()->json($jeniskegiatan);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Error fetching all Jenis Kegiatan: ' . $e->getMessage());
|
||||||
|
return response()->json(['error' => 'Something went wrong'], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Inertia\Inertia;
|
||||||
|
|
||||||
|
class PelaporanALController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return Inertia::render('admin/pelaporan/AL/index_AL');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Error rendering view: ' . $e->getMessage());
|
||||||
|
return back()->with('error', 'Something went wrong.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,178 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Perusahaan;
|
||||||
|
use App\Models\JenisKegiatan;
|
||||||
|
use App\Http\Requests\PerusahaanRequest;
|
||||||
|
use App\Models\JenisDokIL;
|
||||||
|
use App\Models\Kabupaten;
|
||||||
|
use App\Models\Kecamatan;
|
||||||
|
use App\Models\Kelurahan;
|
||||||
|
use App\Models\Verifikator;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Inertia\Inertia;
|
||||||
|
use Illuminate\Support\Facades\Session;
|
||||||
|
|
||||||
|
class PerusahaanController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$perusahaan = Perusahaan::with('jenisKegiatan', 'kelurahan.kecamatan.kabupaten', 'verifikator', 'jenisDokIL')->get();
|
||||||
|
return Inertia::render('admin/perusahaan/index_perusahaan', [
|
||||||
|
'perusahaan' => $perusahaan,
|
||||||
|
'jenisKegiatan' => JenisKegiatan::all(),
|
||||||
|
'jenisDokIL' => JenisDokIL::all(),
|
||||||
|
'verifikator' => Verifikator::all(),
|
||||||
|
'kabupaten' => Kabupaten::all(),
|
||||||
|
'kecamatan' => Kecamatan::all(),
|
||||||
|
'kelurahan' => Kelurahan::all(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Error fetching data: ' . $e->getMessage());
|
||||||
|
return back()->with('error', 'Terjadi kesalahan saat memuat data.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// public function store(Request $request)
|
||||||
|
// {
|
||||||
|
// $request->validate([
|
||||||
|
// 'ILDokumen' => 'required|file|mimes:pdf|max:20480',
|
||||||
|
// ]);
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// return DB::transaction(function () use ($request) {
|
||||||
|
// if ($request->hasFile('ILDokumen')) {
|
||||||
|
// $file = $request->file('ILDokumen');
|
||||||
|
// $fileName = time() . '_' . $file->getClientOriginalName();
|
||||||
|
|
||||||
|
// if (!Storage::exists('public/files/il')) {
|
||||||
|
// Storage::makeDirectory('public/files/il');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// $path = $file->storeAs('files/il', $fileName, 'public');
|
||||||
|
|
||||||
|
// $request->merge(['ILDokumen' => $path]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// $perusahaan = Perusahaan::create($request->all());
|
||||||
|
|
||||||
|
// return response()->json([
|
||||||
|
// 'message' => 'Perusahaan berhasil ditambahkan',
|
||||||
|
// 'data' => $perusahaan
|
||||||
|
// ]);
|
||||||
|
// });
|
||||||
|
// } catch (\Exception $e) {
|
||||||
|
// if (isset($path) && Storage::exists($path)) {
|
||||||
|
// Storage::delete($path);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return response()->json([
|
||||||
|
// 'message' => 'Error: ' . $e->getMessage()
|
||||||
|
// ], 500);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'NomorInduk' => 'required|string|unique:Perusahaan',
|
||||||
|
'NamaPerusahaan' => 'required|string',
|
||||||
|
'JenisKegiatanId' => 'required|string',
|
||||||
|
'VerifikatorId' => 'required|string',
|
||||||
|
'KelurahanId' => 'required|string',
|
||||||
|
'Email' => 'required|email',
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
$data = $request->all();
|
||||||
|
|
||||||
|
if ($request->hasFile('ILDokumen')) {
|
||||||
|
$file = $request->file('ILDokumen');
|
||||||
|
|
||||||
|
if (!$file->isValid()) {
|
||||||
|
throw new \Exception('Invalid PDF file');
|
||||||
|
}
|
||||||
|
|
||||||
|
$fileName = time() . '_' . $file->getClientOriginalName();
|
||||||
|
$path = $file->storeAs('files/il', $fileName, 'public');
|
||||||
|
|
||||||
|
if ($path === false) {
|
||||||
|
throw new \Exception('Failed to store PDF file');
|
||||||
|
}
|
||||||
|
|
||||||
|
$data['ILDokumen'] = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert boolean string to actual boolean
|
||||||
|
$data['IsPublish'] = filter_var($request->input('IsPublish'), FILTER_VALIDATE_BOOLEAN);
|
||||||
|
$data['ReportLocked'] = filter_var($request->input('ReportLocked'), FILTER_VALIDATE_BOOLEAN);
|
||||||
|
|
||||||
|
$perusahaan = Perusahaan::create($data);
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->route('admin.perusahaan.index')
|
||||||
|
->with('success', 'Perusahaan berhasil ditambahkan');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
|
||||||
|
if (isset($path) && Storage::disk('public')->exists($path)) {
|
||||||
|
Storage::disk('public')->delete($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::error('Error creating perusahaan: ' . $e->getMessage());
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Error: ' . $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(Perusahaan $perusahaan): JsonResponse
|
||||||
|
{
|
||||||
|
$perusahaan->load([
|
||||||
|
'JenisKegiatan',
|
||||||
|
'Kelurahan',
|
||||||
|
'JenisDokIL',
|
||||||
|
'Verifikator',
|
||||||
|
'Kawasan'
|
||||||
|
]);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'success',
|
||||||
|
'data' => $perusahaan
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(PerusahaanRequest $request, Perusahaan $perusahaan): JsonResponse
|
||||||
|
{
|
||||||
|
$perusahaan->update($request->validated());
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'Data perusahaan berhasil diperbarui',
|
||||||
|
'data' => $perusahaan
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(Perusahaan $perusahaan): JsonResponse
|
||||||
|
{
|
||||||
|
$perusahaan->delete();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'Data perusahaan berhasil dihapus'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -95,41 +95,52 @@ class PostController extends Controller
|
||||||
|
|
||||||
public function edit(Post $post)
|
public function edit(Post $post)
|
||||||
{
|
{
|
||||||
|
// Debug the image path
|
||||||
|
Log::info('Image path:', ['path' => $post->ImagePost]);
|
||||||
|
|
||||||
return Inertia::render('admin/post/edit_post', [
|
return Inertia::render('admin/post/edit_post', [
|
||||||
'post' => $post,
|
'posting' => [
|
||||||
|
...$post->toArray(),
|
||||||
|
'ImagePost' => $post->ImagePost ? '/storage/' . $post->ImagePost : null,
|
||||||
|
],
|
||||||
'kategori' => Kategori::all(),
|
'kategori' => Kategori::all(),
|
||||||
'subkategori' => SubKategori::where('KategoriId', $post->KategoriId)->get(),
|
'subkategori' => SubKategori::all(),
|
||||||
|
'existingPosts' => Post::where('PostId', '!=', $post->PostId)
|
||||||
|
->select('JudulPost', 'KategoriId')
|
||||||
|
->get()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(PostRequest $request, Post $post)
|
public function update(PostRequest $request, Post $post)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$data = array_filter($request->validated(), function($value) {
|
DB::beginTransaction();
|
||||||
return $value !== null;
|
$data = $request->validated();
|
||||||
});
|
|
||||||
|
|
||||||
|
// Only update image if new one is uploaded
|
||||||
if ($request->hasFile('ImagePost')) {
|
if ($request->hasFile('ImagePost')) {
|
||||||
|
// Delete old image if exists
|
||||||
if ($post->ImagePost && Storage::disk('public')->exists($post->ImagePost)) {
|
if ($post->ImagePost && Storage::disk('public')->exists($post->ImagePost)) {
|
||||||
Storage::disk('public')->delete($post->ImagePost);
|
Storage::disk('public')->delete($post->ImagePost);
|
||||||
}
|
}
|
||||||
$data['ImagePost'] = $request->file('ImagePost')->store('images/posts', 'public');
|
$data['ImagePost'] = $request->file('ImagePost')->store('images/posts', 'public');
|
||||||
|
} else {
|
||||||
|
// Keep existing image if no new one uploaded
|
||||||
|
unset($data['ImagePost']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($data['IsPublish'])) {
|
$data['IsPublish'] = $request->boolean('IsPublish');
|
||||||
$data['IsPublish'] = (bool) $data['IsPublish'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$post->update($data);
|
$post->update($data);
|
||||||
|
|
||||||
return redirect()
|
DB::commit();
|
||||||
->route('admin.post.index')
|
return redirect()->route('admin.post.index')->with('success', 'Post berhasil diperbarui.');
|
||||||
->with('success', 'Post berhasil diperbarui.');
|
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
Log::error('Error updating Post: ' . $e->getMessage());
|
Log::error('Error updating Post: ' . $e->getMessage());
|
||||||
return back()->with('error', 'Terjadi kesalahan saat memperbarui post.');
|
return back()->with('error', 'Terjadi kesalahan saat memperbarui post.');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy(Post $post)
|
public function destroy(Post $post)
|
||||||
|
|
|
@ -23,7 +23,6 @@ class JenisDokILRequest extends FormRequest
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'NamaJenisDokIL' => 'required|string|max:255',
|
'NamaJenisDokIL' => 'required|string|max:255',
|
||||||
'KodeJenisDokIL' => 'required|string|max:20',
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class PerusahaanRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'NomorInduk' => ['string'],
|
||||||
|
'JenisKegiatanId' => ['required', 'integer'],
|
||||||
|
'NamaPerusahaan' => ['required', 'string'],
|
||||||
|
'Alamat' => ['string'],
|
||||||
|
'KelurahanId' => ['required', 'integer'],
|
||||||
|
'KodePos' => ['string'],
|
||||||
|
'Telepon' => ['string'],
|
||||||
|
'Fax' => ['string'],
|
||||||
|
'Email' => ['required', 'string'],
|
||||||
|
'Lintang' => ['string'],
|
||||||
|
'Bujur' => ['string'],
|
||||||
|
'CPNama' => ['string'],
|
||||||
|
'CPTelepon' => ['string'],
|
||||||
|
'ILNomor' => ['string'],
|
||||||
|
'ILTanggal' => ['string'],
|
||||||
|
'JenisDokILId' => ['integer'],
|
||||||
|
'VerifikatorId' => ['required', 'integer'],
|
||||||
|
'IsPublish' => ['required', 'boolean'],
|
||||||
|
'ILDokumen' => ['string'],
|
||||||
|
'Kawasan' => ['string'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,6 @@ class JenisDokIL extends Model
|
||||||
protected $table = 'JenisDokIL';
|
protected $table = 'JenisDokIL';
|
||||||
protected $primaryKey = 'JenisDokILId';
|
protected $primaryKey = 'JenisDokILId';
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'KodeJenisDokIL',
|
|
||||||
'NamaJenisDokIL'
|
'NamaJenisDokIL'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,4 +21,9 @@ class JenisKegiatan extends Model
|
||||||
'IsPublish',
|
'IsPublish',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function Perusahaan()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Perusahaan::class, 'JenisKegiatanId');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +2,20 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
class Perusahaan extends Model
|
class Perusahaan extends Model
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
protected $table = 'Perusahaan';
|
protected $table = 'Perusahaan';
|
||||||
protected $primaryKey = 'PerusahaanId';
|
protected $primaryKey = 'PerusahaanId';
|
||||||
|
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'NomorInduk',
|
'NomorInduk',
|
||||||
'JenisKegiatanId',
|
'JenisKegiatanId',
|
||||||
'NamaPerusahaan',
|
'NamaPerusahaan',
|
||||||
'Alamat',
|
'Alamat',
|
||||||
|
@ -28,57 +32,67 @@ class Perusahaan extends Model
|
||||||
'ILTanggal',
|
'ILTanggal',
|
||||||
'JenisDokILId',
|
'JenisDokILId',
|
||||||
'VerifikatorId',
|
'VerifikatorId',
|
||||||
'ReportLocked',
|
|
||||||
'IsPublish',
|
'IsPublish',
|
||||||
'ILDokumen',
|
'ILDokumen',
|
||||||
'ILPdlNomor',
|
'ReportLocked'
|
||||||
'ILPdlJenis',
|
|
||||||
'DocPdlOrig',
|
|
||||||
'DocPdlHash',
|
|
||||||
'DocPdlPath',
|
|
||||||
'ILPdlTanggal',
|
|
||||||
'Kawasan'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'ReportLocked' => 'boolean',
|
'ReportLocked' => 'boolean',
|
||||||
'IsPublish' => 'boolean',
|
'IsPublish' => 'boolean',
|
||||||
'ILPdlTanggal' => 'date',
|
'JenisKegiatanId' => 'integer',
|
||||||
|
'VerifikatorId' => 'integer',
|
||||||
|
'KelurahanId' => 'integer',
|
||||||
];
|
];
|
||||||
|
|
||||||
// Relationship with JenisKegiatan
|
public function jenisKegiatan()
|
||||||
public function jenisKegiatan(): BelongsTo
|
|
||||||
{
|
{
|
||||||
return $this->belongsTo(JenisKegiatan::class, 'JenisKegiatanId', 'JenisKegiatanId');
|
return $this->belongsTo(JenisKegiatan::class, 'JenisKegiatanId', 'JenisKegiatanId');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relationship with Kelurahan
|
protected $with = ['JenisKegiatan', 'Kelurahan'];
|
||||||
public function kelurahan(): BelongsTo
|
|
||||||
|
public function kelurahan()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Kelurahan::class, 'KelurahanId', 'KelurahanId');
|
return $this->belongsTo(Kelurahan::class, 'KelurahanId', 'KelurahanId');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function kecamatan()
|
||||||
|
{
|
||||||
|
return $this->hasOneThrough(
|
||||||
|
Kecamatan::class,
|
||||||
|
Kelurahan::class,
|
||||||
|
'KelurahanId', // Foreign key di tabel Kelurahan
|
||||||
|
'KecamatanId', // Foreign key di tabel Kecamatan
|
||||||
|
'KelurahanId', // Foreign key di tabel Perusahaan
|
||||||
|
'KecamatanId' // Foreign key di tabel Kelurahan
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function kabupaten()
|
||||||
|
{
|
||||||
|
return $this->hasOneThrough(
|
||||||
|
Kabupaten::class,
|
||||||
|
Kecamatan::class,
|
||||||
|
'KecamatanId', // Foreign key di tabel Kecamatan
|
||||||
|
'KabupatenId', // Foreign key di tabel Kabupaten
|
||||||
|
'KelurahanId', // Foreign key di tabel Perusahaan
|
||||||
|
'KabupatenId' // Foreign key di tabel Kecamatan
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function verifikator()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Verifikator::class, 'VerifikatorId');
|
||||||
|
}
|
||||||
// Relationship with JenisDokIL
|
// Relationship with JenisDokIL
|
||||||
public function jenisDokIL(): BelongsTo
|
public function jenisDokIL()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(JenisDokIL::class, 'JenisDokILId', 'JenisDokILId');
|
return $this->belongsTo(JenisDokIL::class, 'JenisDokILId', 'JenisDokILId');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relationship with JenisDokIL for PDL
|
|
||||||
public function jenisDokILPdl(): BelongsTo
|
|
||||||
{
|
|
||||||
return $this->belongsTo(JenisDokIL::class, 'ILPdlJenis', 'JenisDokILId');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Relationship with Verifikator
|
|
||||||
public function verifikator(): BelongsTo
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Verifikator::class, 'VerifikatorId', 'VerifikatorId');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Self-referential relationship for Kawasan
|
|
||||||
public function kawasan(): BelongsTo
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Perusahaan::class, 'Kawasan', 'PerusahaanId');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ return new class extends Migration
|
||||||
Schema::create('users', function (Blueprint $table) {
|
Schema::create('users', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->string('name');
|
$table->string('name');
|
||||||
|
$table->string('username')->unique();
|
||||||
$table->string('email')->unique();
|
$table->string('email')->unique();
|
||||||
$table->timestamp('email_verified_at')->nullable();
|
$table->timestamp('email_verified_at')->nullable();
|
||||||
$table->string('password');
|
$table->string('password');
|
||||||
|
|
|
@ -13,7 +13,7 @@ return new class extends Migration
|
||||||
{
|
{
|
||||||
Schema::create('Kategori', function (Blueprint $table) {
|
Schema::create('Kategori', function (Blueprint $table) {
|
||||||
$table->id('KategoriId');
|
$table->id('KategoriId');
|
||||||
$table->string('NamaKategori')->unique();
|
$table->string('NamaKategori');
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
return new class extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*/
|
|
||||||
public function up(): void
|
|
||||||
{
|
|
||||||
Schema::table('users', function (Blueprint $table) {
|
|
||||||
$table->string('username')->unique()->after('name');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*/
|
|
||||||
public function down(): void
|
|
||||||
{
|
|
||||||
Schema::table('users', function (Blueprint $table) {
|
|
||||||
$table->dropColumn('username');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -19,6 +19,7 @@ return new class extends Migration
|
||||||
$table->string('SlugPost');
|
$table->string('SlugPost');
|
||||||
$table->text('DescPost');
|
$table->text('DescPost');
|
||||||
$table->string('ImagePost')->nullable();
|
$table->string('ImagePost')->nullable();
|
||||||
|
$table->boolean('IsPublish')->default(1);
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
return new class extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*/
|
|
||||||
public function up(): void
|
|
||||||
{
|
|
||||||
Schema::table('Post', function (Blueprint $table) {
|
|
||||||
$table->boolean('IsPublish')->default(0);
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*/
|
|
||||||
public function down(): void
|
|
||||||
{
|
|
||||||
Schema::table('Post', function (Blueprint $table) {
|
|
||||||
$table->dropColumn('IsPublish');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -11,10 +11,11 @@ return new class extends Migration
|
||||||
*/
|
*/
|
||||||
public function up(): void
|
public function up(): void
|
||||||
{
|
{
|
||||||
Schema::create('historykegiatan', function (Blueprint $table) {
|
Schema::create('HistoryKegiatan', function (Blueprint $table) {
|
||||||
$table->id('HistoryKegiatanId');
|
$table->id('HistoryKegiatanId');
|
||||||
$table->string('NamaHistoryKegiatan');
|
$table->string('NamaHistoryKegiatan');
|
||||||
$table->boolean('IsPublish')->default(0);
|
$table->boolean('IsPublish')->default(1);
|
||||||
|
$table->softDeletes();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -24,6 +25,6 @@ return new class extends Migration
|
||||||
*/
|
*/
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
Schema::dropIfExists('historykegiatan');
|
Schema::dropIfExists('HistoryKegiatan');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,10 +11,11 @@ return new class extends Migration
|
||||||
*/
|
*/
|
||||||
public function up(): void
|
public function up(): void
|
||||||
{
|
{
|
||||||
Schema::create('jeniskegiatan', function (Blueprint $table) {
|
Schema::create('JenisKegiatan', function (Blueprint $table) {
|
||||||
$table->id('JenisKegiatanId');
|
$table->id('JenisKegiatanId');
|
||||||
$table->string('NamaJenisKegiatan');
|
$table->string('NamaJenisKegiatan');
|
||||||
$table->boolean('IsPublish')->default(0);
|
$table->boolean('IsPublish')->default(1);
|
||||||
|
$table->softDeletes();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -24,6 +25,6 @@ return new class extends Migration
|
||||||
*/
|
*/
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
Schema::dropIfExists('jeniskegiatan');
|
Schema::dropIfExists('JenisKegiatan');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
return new class extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*/
|
|
||||||
public function up(): void
|
|
||||||
{
|
|
||||||
Schema::table('JenisKegiatan', function (Blueprint $table) {
|
|
||||||
$table->softDeletes()->after('IsPublish');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*/
|
|
||||||
public function down(): void
|
|
||||||
{
|
|
||||||
Schema::table('JenisKegiatan', function (Blueprint $table) {
|
|
||||||
$table->dropSoftDeletes();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,28 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
return new class extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*/
|
|
||||||
public function up(): void
|
|
||||||
{
|
|
||||||
Schema::table('HistoryKegiatan', function (Blueprint $table) {
|
|
||||||
$table->softDeletes()->after('IsPublish');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*/
|
|
||||||
public function down(): void
|
|
||||||
{
|
|
||||||
Schema::table('HistoryKegiatan', function (Blueprint $table) {
|
|
||||||
$table->dropSoftDeletes();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,28 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
return new class extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*/
|
|
||||||
public function up(): void
|
|
||||||
{
|
|
||||||
Schema::table('Kategori', function (Blueprint $table) {
|
|
||||||
$table->dropUnique(['NamaKategori']);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*/
|
|
||||||
public function down(): void
|
|
||||||
{
|
|
||||||
Schema::table('Kategori', function (Blueprint $table) {
|
|
||||||
$table->unique('NamaKategori');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -30,22 +30,13 @@ return new class extends Migration
|
||||||
$table->string('CPTelepon')->nullable();
|
$table->string('CPTelepon')->nullable();
|
||||||
$table->string('ILNomor')->nullable();
|
$table->string('ILNomor')->nullable();
|
||||||
$table->string('ILTanggal')->nullable();
|
$table->string('ILTanggal')->nullable();
|
||||||
|
$table->string('ILDokumen')->nullable();
|
||||||
$table->unsignedBigInteger('JenisDokILId');
|
$table->unsignedBigInteger('JenisDokILId');
|
||||||
$table->foreign('JenisDokILId')->references('JenisDokILId')->on('JenisDokIL')->onDelete('cascade');
|
$table->foreign('JenisDokILId')->references('JenisDokILId')->on('JenisDokIL')->onDelete('cascade');
|
||||||
$table->unsignedBigInteger('VerifikatorId');
|
$table->unsignedBigInteger('VerifikatorId');
|
||||||
$table->foreign('VerifikatorId')->references('VerifikatorId')->on('Verifikator')->onDelete('cascade');
|
$table->foreign('VerifikatorId')->references('VerifikatorId')->on('Verifikator')->onDelete('cascade');
|
||||||
$table->boolean('ReportLocked')->default(1);
|
$table->boolean('ReportLocked')->default(1);
|
||||||
$table->boolean('IsPublish')->default(0);
|
$table->boolean('IsPublish')->default(1);
|
||||||
$table->string('ILDokumen')->nullable();
|
|
||||||
$table->string('ILPdlNomor')->default('n')->comment('Dok IL versi PDL');
|
|
||||||
$table->unsignedInteger('ILPdlJenis')->nullable()->comment('id dari refjenisdokil');
|
|
||||||
$table->foreign('ILPdlJenis')->references('JenisDokILId')->on('JenisDokIL')->onDelete('set null');
|
|
||||||
$table->string('DocPdlOrig')->nullable()->comment('nama file original');
|
|
||||||
$table->string('DocPdlHash')->nullable()->comment('nama file hash');
|
|
||||||
$table->string('DocPdlPath')->nullable()->comment('upload path');
|
|
||||||
$table->date('ILPdlTanggal')->nullable();
|
|
||||||
$table->unsignedInteger('Kawasan')->nullable()->comment('id dari perusahaan, digunakan utk pengelola kawasan');
|
|
||||||
$table->foreign('Kawasan')->references('PerusahaanId')->on('Perusahaan')->onDelete('set null');
|
|
||||||
|
|
||||||
|
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
|
@ -13,7 +13,6 @@ return new class extends Migration
|
||||||
{
|
{
|
||||||
Schema::create('JenisDokIL', function (Blueprint $table) {
|
Schema::create('JenisDokIL', function (Blueprint $table) {
|
||||||
$table->id('JenisDokILId');
|
$table->id('JenisDokILId');
|
||||||
$table->string('KodeJenisDokIL')->unique();
|
|
||||||
$table->string('NamaJenisDokIL');
|
$table->string('NamaJenisDokIL');
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,6 +16,7 @@ return new class extends Migration
|
||||||
$table->string('NamaUnitKerja');
|
$table->string('NamaUnitKerja');
|
||||||
$table->string('NamaKepala');
|
$table->string('NamaKepala');
|
||||||
$table->string('NIP');
|
$table->string('NIP');
|
||||||
|
$table->softDeletes();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "DLH-SKL",
|
"name": "skl2025",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
@ -8,6 +8,7 @@
|
||||||
"@iconify/react": "^5.2.0",
|
"@iconify/react": "^5.2.0",
|
||||||
"@radix-ui/react-alert-dialog": "^1.0.5",
|
"@radix-ui/react-alert-dialog": "^1.0.5",
|
||||||
"@radix-ui/react-avatar": "^1.1.1",
|
"@radix-ui/react-avatar": "^1.1.1",
|
||||||
|
"@radix-ui/react-checkbox": "^1.1.4",
|
||||||
"@radix-ui/react-collapsible": "^1.1.1",
|
"@radix-ui/react-collapsible": "^1.1.1",
|
||||||
"@radix-ui/react-dialog": "^1.1.6",
|
"@radix-ui/react-dialog": "^1.1.6",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.2",
|
"@radix-ui/react-dropdown-menu": "^2.1.2",
|
||||||
|
@ -1240,6 +1241,77 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-checkbox": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-wP0CPAHq+P5I4INKe3hJrIa1WoNqqrejzW+zoU0rOvo1b9gDEJJFl2rYfO1PYJUQCc2H1WZxIJmyv9BS8i5fLw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/primitive": "1.1.1",
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.1",
|
||||||
|
"@radix-ui/react-context": "1.1.1",
|
||||||
|
"@radix-ui/react-presence": "1.1.2",
|
||||||
|
"@radix-ui/react-primitive": "2.0.2",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
||||||
|
"@radix-ui/react-use-previous": "1.1.0",
|
||||||
|
"@radix-ui/react-use-size": "1.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-primitive": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-slot": "1.1.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-slot": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-collapsible": {
|
"node_modules/@radix-ui/react-collapsible": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.2.tgz",
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
"@iconify/react": "^5.2.0",
|
"@iconify/react": "^5.2.0",
|
||||||
"@radix-ui/react-alert-dialog": "^1.0.5",
|
"@radix-ui/react-alert-dialog": "^1.0.5",
|
||||||
"@radix-ui/react-avatar": "^1.1.1",
|
"@radix-ui/react-avatar": "^1.1.1",
|
||||||
|
"@radix-ui/react-checkbox": "^1.1.4",
|
||||||
"@radix-ui/react-collapsible": "^1.1.1",
|
"@radix-ui/react-collapsible": "^1.1.1",
|
||||||
"@radix-ui/react-dialog": "^1.1.6",
|
"@radix-ui/react-dialog": "^1.1.6",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.2",
|
"@radix-ui/react-dropdown-menu": "^2.1.2",
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
"use client";
|
import { useState } from "react";
|
||||||
|
import { TrendingUp, BarChart2 } from "lucide-react";
|
||||||
import { TrendingUp } from "lucide-react";
|
import {
|
||||||
import { Bar, BarChart, CartesianGrid, XAxis } from "recharts";
|
Bar,
|
||||||
|
BarChart,
|
||||||
|
CartesianGrid,
|
||||||
|
XAxis,
|
||||||
|
YAxis,
|
||||||
|
ResponsiveContainer,
|
||||||
|
} from "recharts";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
CardDescription,
|
CardDescription,
|
||||||
CardFooter,
|
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/ui/card";
|
||||||
|
@ -17,10 +21,11 @@ import {
|
||||||
ChartTooltip,
|
ChartTooltip,
|
||||||
ChartTooltipContent,
|
ChartTooltipContent,
|
||||||
} from "@/components/ui/chart";
|
} from "@/components/ui/chart";
|
||||||
|
|
||||||
const chartData = [
|
const chartData = [
|
||||||
{ month: "Genset", desktop: 186 },
|
{ month: "Genset", desktop: 186, color: "#22c55e" },
|
||||||
{ month: "Boiler", desktop: 305 },
|
{ month: "Boiler", desktop: 305, color: "#16a34a" },
|
||||||
{ month: "Proses", desktop: 237 },
|
{ month: "Proses", desktop: 237, color: "#15803d" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const chartConfig = {
|
const chartConfig = {
|
||||||
|
@ -31,40 +36,151 @@ const chartConfig = {
|
||||||
} satisfies ChartConfig;
|
} satisfies ChartConfig;
|
||||||
|
|
||||||
export function ChartCard() {
|
export function ChartCard() {
|
||||||
|
const [activeIndex, setActiveIndex] = useState<number | null>(null);
|
||||||
|
|
||||||
|
const handleMouseEnter = (index: number) => {
|
||||||
|
setActiveIndex(index);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMouseLeave = () => {
|
||||||
|
setActiveIndex(null);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card className="relative overflow-hidden transition-all duration-300 hover:shadow-lg">
|
||||||
<CardHeader>
|
<div className="absolute inset-0 bg-gradient-to-br from-green-50/30 to-transparent dark:from-green-950/30" />
|
||||||
<CardTitle>Sumber Emisi</CardTitle>
|
|
||||||
{/* <CardDescription>January - June 2024</CardDescription> */}
|
<CardHeader className="relative">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<BarChart2 className="h-6 w-6 text-green-600" />
|
||||||
|
<CardTitle className="text-xl font-bold">
|
||||||
|
Sumber Emisi
|
||||||
|
</CardTitle>
|
||||||
|
</div>
|
||||||
|
<CardDescription className="text-sm text-green-600 font-medium">
|
||||||
|
Total Emisi per Sumber
|
||||||
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
|
||||||
<ChartContainer config={chartConfig}>
|
<CardContent className="relative pb-6">
|
||||||
<BarChart accessibilityLayer data={chartData}>
|
<div className="h-[300px] w-full">
|
||||||
<CartesianGrid vertical={false} />
|
<ResponsiveContainer width="100%" height="100%">
|
||||||
<XAxis
|
<BarChart data={chartData}>
|
||||||
dataKey="month"
|
<defs>
|
||||||
tickLine={false}
|
{chartData.map((entry, index) => (
|
||||||
tickMargin={10}
|
<linearGradient
|
||||||
axisLine={false}
|
key={`gradient-${index}`}
|
||||||
// tickFormatter={(value) => value.slice(0, 3)}
|
id={`barGradient-${index}`}
|
||||||
/>
|
x1="0"
|
||||||
<ChartTooltip
|
y1="0"
|
||||||
cursor={false}
|
x2="0"
|
||||||
content={<ChartTooltipContent hideLabel />}
|
y2="1"
|
||||||
/>
|
>
|
||||||
<Bar dataKey="desktop" fill="#53a946" radius={8} />
|
<stop
|
||||||
</BarChart>
|
offset="0%"
|
||||||
</ChartContainer>
|
stopColor={entry.color}
|
||||||
|
stopOpacity={0.8}
|
||||||
|
/>
|
||||||
|
<stop
|
||||||
|
offset="100%"
|
||||||
|
stopColor={entry.color}
|
||||||
|
stopOpacity={0.3}
|
||||||
|
/>
|
||||||
|
</linearGradient>
|
||||||
|
))}
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<CartesianGrid
|
||||||
|
vertical={false}
|
||||||
|
stroke="#e5e7eb"
|
||||||
|
strokeDasharray="4 4"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<XAxis
|
||||||
|
dataKey="month"
|
||||||
|
tickLine={false}
|
||||||
|
axisLine={false}
|
||||||
|
tick={{ fill: "#6b7280", fontSize: 12 }}
|
||||||
|
tickMargin={12}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<YAxis
|
||||||
|
axisLine={false}
|
||||||
|
tickLine={false}
|
||||||
|
tick={{ fill: "#6b7280", fontSize: 12 }}
|
||||||
|
tickMargin={8}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ChartTooltip
|
||||||
|
cursor={false}
|
||||||
|
content={({ active, payload }) => {
|
||||||
|
if (active && payload && payload.length) {
|
||||||
|
return (
|
||||||
|
<div className="rounded-lg bg-white p-3 shadow-lg border border-green-100 backdrop-blur-sm">
|
||||||
|
<p className="font-medium text-green-800">
|
||||||
|
{payload[0].payload.month}
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-green-600">
|
||||||
|
{payload[0].value} ton CO₂
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Bar
|
||||||
|
dataKey="desktop"
|
||||||
|
radius={[8, 8, 0, 0]}
|
||||||
|
onMouseEnter={(data, index) =>
|
||||||
|
handleMouseEnter(index)
|
||||||
|
}
|
||||||
|
onMouseLeave={handleMouseLeave}
|
||||||
|
>
|
||||||
|
{chartData.map((entry, index) => (
|
||||||
|
<rect
|
||||||
|
key={`bar-${index}`}
|
||||||
|
fill={`url(#barGradient-${index})`}
|
||||||
|
className={`transition-all duration-300 ${
|
||||||
|
activeIndex === index
|
||||||
|
? "opacity-100 scale-y-105"
|
||||||
|
: activeIndex === null
|
||||||
|
? "opacity-90"
|
||||||
|
: "opacity-50"
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Bar>
|
||||||
|
</BarChart>
|
||||||
|
</ResponsiveContainer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-6 flex justify-between items-center px-4">
|
||||||
|
{chartData.map((item, index) => (
|
||||||
|
<div
|
||||||
|
key={item.month}
|
||||||
|
className="flex flex-col items-center gap-2"
|
||||||
|
onMouseEnter={() => handleMouseEnter(index)}
|
||||||
|
onMouseLeave={handleMouseLeave}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={`h-3 w-3 rounded-full transition-all duration-300 ${
|
||||||
|
activeIndex === index
|
||||||
|
? "scale-150"
|
||||||
|
: activeIndex === null
|
||||||
|
? "scale-100"
|
||||||
|
: "scale-75 opacity-50"
|
||||||
|
}`}
|
||||||
|
style={{ backgroundColor: item.color }}
|
||||||
|
/>
|
||||||
|
<span className="text-sm font-medium text-gray-600">
|
||||||
|
{item.month}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
{/* <CardFooter className="flex-col items-start gap-2 text-sm">
|
|
||||||
<div className="flex gap-2 font-medium leading-none">
|
|
||||||
Trending up by 5.2% this month{" "}
|
|
||||||
<TrendingUp className="h-4 w-4" />
|
|
||||||
</div>
|
|
||||||
<div className="leading-none text-muted-foreground">
|
|
||||||
Showing total visitors for the last 6 months
|
|
||||||
</div>
|
|
||||||
</CardFooter> */}
|
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ const AnnouncementSection = ({ posts }: CardPengumumanProps) => {
|
||||||
{/* List of Announcements */}
|
{/* List of Announcements */}
|
||||||
{posts.length > 1 && (
|
{posts.length > 1 && (
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
{posts.slice(1).map((post) => (
|
{posts.slice(1, 4).map((post) => (
|
||||||
<Card key={post.PostId} className="p-4">
|
<Card key={post.PostId} className="p-4">
|
||||||
<img
|
<img
|
||||||
src={`/storage/${post.ImagePost}`}
|
src={`/storage/${post.ImagePost}`}
|
||||||
|
|
|
@ -38,7 +38,7 @@ const SearchDialog: React.FC = () => {
|
||||||
<DialogContent className="bg-white text-black p-6 rounded-lg w-[90%] max-w-md">
|
<DialogContent className="bg-white text-black p-6 rounded-lg w-[90%] max-w-md">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle className="text-lg font-bold text-center">
|
<DialogTitle className="text-lg font-bold text-center">
|
||||||
Search
|
Ketik Pencarianmu di sini...
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<form
|
<form
|
||||||
|
|
|
@ -55,7 +55,7 @@ const UndanganSection = ({ undangan }: CardUndanganProps) => {
|
||||||
|
|
||||||
{/* List of Announcements */}
|
{/* List of Announcements */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
{undangan.map((item) => (
|
{undangan.slice(0, 3).map((item) => (
|
||||||
<Card key={item.PostId} className="md:p-4">
|
<Card key={item.PostId} className="md:p-4">
|
||||||
<img
|
<img
|
||||||
src={`/storage/${item.ImagePost}`}
|
src={`/storage/${item.ImagePost}`}
|
||||||
|
|
|
@ -0,0 +1,812 @@
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import Select from "react-select";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { Calendar } from "@/components/ui/calendar";
|
||||||
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
} from "@/components/ui/popover";
|
||||||
|
import { format } from "date-fns";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import {
|
||||||
|
Calendar as CalendarIcon,
|
||||||
|
FileText,
|
||||||
|
Hotel,
|
||||||
|
LocateFixed,
|
||||||
|
MapPinned,
|
||||||
|
UsersRound,
|
||||||
|
Verified,
|
||||||
|
VerifiedIcon,
|
||||||
|
} from "lucide-react";
|
||||||
|
import { Separator } from "../ui/separator";
|
||||||
|
import { Textarea } from "../ui/textarea";
|
||||||
|
|
||||||
|
import {
|
||||||
|
JenisDokIL,
|
||||||
|
JenisKegiatan,
|
||||||
|
Verifikator,
|
||||||
|
Kabupaten,
|
||||||
|
Kecamatan,
|
||||||
|
Kelurahan,
|
||||||
|
Perusahaan,
|
||||||
|
Kawasan,
|
||||||
|
} from "@/types/perusahaan";
|
||||||
|
import { useForm, usePage } from "@inertiajs/react";
|
||||||
|
import { useToast } from "@/hooks/use-toast";
|
||||||
|
|
||||||
|
interface FormDataType {
|
||||||
|
NomorInduk: string;
|
||||||
|
JenisKegiatanId: string;
|
||||||
|
NamaPerusahaan: string;
|
||||||
|
Alamat: string;
|
||||||
|
KelurahanId: string;
|
||||||
|
KodePos: string;
|
||||||
|
Telepon: string;
|
||||||
|
Fax: string;
|
||||||
|
Email: string;
|
||||||
|
Lintang: string;
|
||||||
|
Bujur: string;
|
||||||
|
CPNama: string;
|
||||||
|
CPTelepon: string;
|
||||||
|
JenisDokILId: string;
|
||||||
|
VerifikatorId: string;
|
||||||
|
IsPublish: boolean;
|
||||||
|
ILNomor: string;
|
||||||
|
ILTanggal: string;
|
||||||
|
ILDokumen: File | null;
|
||||||
|
ReportLocked: true;
|
||||||
|
PerusahaanId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// interface ExistingPerusahaan {
|
||||||
|
// NamaPerusahaan: string;
|
||||||
|
// PerusahaanId: string;
|
||||||
|
// }
|
||||||
|
|
||||||
|
interface ExistingInduk {
|
||||||
|
NomorInduk: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AddPerusahaanModalProps {
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
onSuccess: () => void;
|
||||||
|
jenisKegiatan: JenisKegiatan[];
|
||||||
|
jenisDokIL: JenisDokIL[];
|
||||||
|
verifikator: Verifikator[];
|
||||||
|
kabupaten: Kabupaten[];
|
||||||
|
kecamatan: Kecamatan[];
|
||||||
|
kelurahan: Kelurahan[];
|
||||||
|
perusahaan: Perusahaan[];
|
||||||
|
// kawasan: Kawasan[];
|
||||||
|
// existingPerusahaan: ExistingPerusahaan[];
|
||||||
|
// existingInduk: ExistingInduk[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AddPerusahaanModal({
|
||||||
|
open,
|
||||||
|
onClose,
|
||||||
|
onSuccess,
|
||||||
|
jenisKegiatan,
|
||||||
|
jenisDokIL,
|
||||||
|
verifikator,
|
||||||
|
kabupaten,
|
||||||
|
kecamatan,
|
||||||
|
kelurahan,
|
||||||
|
perusahaan,
|
||||||
|
}: // existingPerusahaan,
|
||||||
|
// existingInduk,
|
||||||
|
// kawasan,
|
||||||
|
AddPerusahaanModalProps) {
|
||||||
|
const { toast } = useToast();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [date, setDate] = useState<Date>();
|
||||||
|
const { data, setData, post, reset } = useForm({
|
||||||
|
NomorInduk: "",
|
||||||
|
PerusahaanId: "",
|
||||||
|
JenisKegiatanId: "",
|
||||||
|
NamaPerusahaan: "",
|
||||||
|
Alamat: "",
|
||||||
|
KelurahanId: "",
|
||||||
|
KodePos: "",
|
||||||
|
Telepon: "",
|
||||||
|
Fax: "",
|
||||||
|
Email: "",
|
||||||
|
Lintang: "",
|
||||||
|
Bujur: "",
|
||||||
|
CPNama: "",
|
||||||
|
CPTelepon: "",
|
||||||
|
JenisDokILId: "",
|
||||||
|
VerifikatorId: "",
|
||||||
|
IsPublish: true,
|
||||||
|
ILDokumen: null as File | null,
|
||||||
|
ILNomor: "",
|
||||||
|
ILTanggal: "",
|
||||||
|
ReportLocked: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [selectedKabupaten, setSelectedKabupaten] = useState<{
|
||||||
|
value: number;
|
||||||
|
label: string;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
|
const [selectedKecamatan, setSelectedKecamatan] = useState<{
|
||||||
|
value: number;
|
||||||
|
label: string;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
|
const [selectedKelurahan, setSelectedKelurahan] = useState<{
|
||||||
|
value: number;
|
||||||
|
label: string;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
|
const [selectedPerusahaan, setSelectedPerusahaan] = useState<{
|
||||||
|
value: number;
|
||||||
|
label: string;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
|
const jenisKegiatanOptions = jenisKegiatan.map((jk) => ({
|
||||||
|
value: jk.JenisKegiatanId,
|
||||||
|
label: jk.NamaJenisKegiatan,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const jenisDokILOptions = jenisDokIL.map((jdi) => ({
|
||||||
|
value: jdi.JenisDokILId,
|
||||||
|
label: jdi.NamaJenisDokIL,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const verifikatorOptions = verifikator.map((v) => ({
|
||||||
|
value: v.VerifikatorId,
|
||||||
|
label: v.NamaUnitKerja,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const kabupatenOptions = kabupaten.map((k) => ({
|
||||||
|
value: k.KabupatenId,
|
||||||
|
label: k.NamaKabupaten,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const perusahaanOptions = perusahaan.map((per) => ({
|
||||||
|
value: per.PerusahaanId,
|
||||||
|
label: per.PerusahaanId,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const kecamatanOptions = kecamatan
|
||||||
|
.filter(
|
||||||
|
(kec) =>
|
||||||
|
selectedKabupaten && kec.KabupatenId === selectedKabupaten.value
|
||||||
|
)
|
||||||
|
.map((kec) => ({
|
||||||
|
value: kec.KecamatanId,
|
||||||
|
label: kec.NamaKecamatan,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const kelurahanOptions = kelurahan
|
||||||
|
.filter(
|
||||||
|
(kel) =>
|
||||||
|
selectedKecamatan && kel.KecamatanId === selectedKecamatan.value
|
||||||
|
)
|
||||||
|
.map((kel) => ({
|
||||||
|
value: kel.KelurahanId,
|
||||||
|
label: kel.NamaKelurahan,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const [showAlert, setShowAlert] = useState(false);
|
||||||
|
const [errors, setErrors] = useState<Record<string, string>>({});
|
||||||
|
|
||||||
|
const validateForm = () => {
|
||||||
|
const newErrors: Record<string, string> = {};
|
||||||
|
|
||||||
|
// const titleExists = existingPerusahaan.some(
|
||||||
|
// (perus) =>
|
||||||
|
// perus.PerusahaanId.toLowerCase() ===
|
||||||
|
// data.PerusahaanId.toLowerCase()
|
||||||
|
// );
|
||||||
|
|
||||||
|
// const indukExists = existingInduk.some(
|
||||||
|
// (induk) =>
|
||||||
|
// induk.NomorInduk.toLowerCase() === data.NomorInduk.toLowerCase()
|
||||||
|
// );
|
||||||
|
|
||||||
|
// if (indukExists) {
|
||||||
|
// setShowAlert(true);
|
||||||
|
// newErrors.NomorInduk = "Nomor Induk sudah ada";
|
||||||
|
// // Auto-hide alert after 5 seconds
|
||||||
|
// setTimeout(() => setShowAlert(false), 5000);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (titleExists) {
|
||||||
|
// setShowAlert(true);
|
||||||
|
// newErrors.NamaPerusahaan = "Nama Perusahaan sudah ada";
|
||||||
|
// // Auto-hide alert after 5 seconds
|
||||||
|
// setTimeout(() => setShowAlert(false), 5000);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!data.PerusahaanId) {
|
||||||
|
// newErrors.PerusahaanId = "Perusahaan harus diisi";
|
||||||
|
// }
|
||||||
|
if (!data.JenisKegiatanId) {
|
||||||
|
newErrors.JenisKegiatanId = "Jenis Kegiatan harus dipilih";
|
||||||
|
}
|
||||||
|
if (!data.VerifikatorId) {
|
||||||
|
newErrors.VerifikatorId = "Admin harus dipilih";
|
||||||
|
}
|
||||||
|
if (!data.Email) {
|
||||||
|
newErrors.Email = "Email harus diisi";
|
||||||
|
}
|
||||||
|
|
||||||
|
setErrors(newErrors);
|
||||||
|
return Object.keys(newErrors).length === 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (!validateForm()) {
|
||||||
|
toast({
|
||||||
|
title: "Validasi Gagal",
|
||||||
|
description: "Silakan periksa kembali form anda",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
|
formData.append("NomorInduk", data.NomorInduk);
|
||||||
|
formData.append("JenisKegiatanId", data.JenisKegiatanId);
|
||||||
|
formData.append("VerifikatorId", data.VerifikatorId);
|
||||||
|
formData.append("KelurahanId", data.KelurahanId);
|
||||||
|
formData.append("NamaPerusahaan", data.NamaPerusahaan);
|
||||||
|
formData.append("Alamat", data.Alamat);
|
||||||
|
formData.append("KodePos", data.KodePos);
|
||||||
|
formData.append("Telepon", data.Telepon);
|
||||||
|
formData.append("Fax", data.Fax);
|
||||||
|
formData.append("Email", data.Email);
|
||||||
|
formData.append("Lintang", data.Lintang);
|
||||||
|
formData.append("Bujur", data.Bujur);
|
||||||
|
formData.append("CPNama", data.CPNama);
|
||||||
|
formData.append("CPTelepon", data.CPTelepon);
|
||||||
|
formData.append("JenisDokILId", data.JenisDokILId);
|
||||||
|
formData.append("IsPublish", data.IsPublish.toString());
|
||||||
|
formData.append("ILNomor", data.ILNomor);
|
||||||
|
formData.append("ILTanggal", data.ILTanggal);
|
||||||
|
formData.append("ReportLocked", data.ReportLocked.toString());
|
||||||
|
|
||||||
|
if (data.ILDokumen) {
|
||||||
|
formData.append("ILDokumen", data.ILDokumen);
|
||||||
|
}
|
||||||
|
|
||||||
|
post("/admin/perusahaan", {
|
||||||
|
data: formData,
|
||||||
|
forceFormData: true,
|
||||||
|
onSuccess: (response) => {
|
||||||
|
toast({
|
||||||
|
title: "Berhasil",
|
||||||
|
description: "Perusahaan berhasil ditambahkan",
|
||||||
|
variant: "default",
|
||||||
|
});
|
||||||
|
reset();
|
||||||
|
onSuccess();
|
||||||
|
onClose();
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
console.error("Error:", error);
|
||||||
|
toast({
|
||||||
|
title: "Gagal",
|
||||||
|
description:
|
||||||
|
"Terjadi kesalahan saat menambahkan perusahaan",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onOpenChange={onClose}>
|
||||||
|
<DialogContent className="max-w-4xl max-h-[90vh] overflow-y-auto">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Tambah Perusahaan Baru</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Masukkan informasi perusahaan yang akan ditambahkan ke
|
||||||
|
dalam sistem.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<form onSubmit={handleSubmit} className="space-y-6">
|
||||||
|
<div className="flex flex-row gap-6">
|
||||||
|
{/* Sisi Kiri */}
|
||||||
|
<div className="w-1/2">
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex flex-row bg-green-200 px-2 py-1 rounded w-fit gap-2 items-center">
|
||||||
|
<Hotel size={16} />
|
||||||
|
<h3 className="text-sm ">
|
||||||
|
Data Perusahaan
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="NomorInduk">
|
||||||
|
Nomor Induk
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
id="NomorInduk"
|
||||||
|
value={data.NomorInduk}
|
||||||
|
onChange={(e) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
NomorInduk: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{errors.NomorInduk && (
|
||||||
|
<p className="text-red-500 text-sm">
|
||||||
|
{errors.NomorInduk}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="NamaPerusahaan">
|
||||||
|
Nama Perusahaan *
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
id="NamaPerusahaan"
|
||||||
|
required
|
||||||
|
value={data.NamaPerusahaan}
|
||||||
|
onChange={(e) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
NamaPerusahaan: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{errors.PerusahaanId && (
|
||||||
|
<p className="text-red-500 text-sm">
|
||||||
|
{errors.PerusahaanId}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="NamaPerusahaan">
|
||||||
|
Jenis Kegiatan *
|
||||||
|
</Label>
|
||||||
|
<Select
|
||||||
|
id="JenisKegiatanId"
|
||||||
|
options={jenisKegiatanOptions}
|
||||||
|
required
|
||||||
|
placeholder="Pilih Jenis Kegiatan"
|
||||||
|
onChange={(option) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
JenisKegiatanId:
|
||||||
|
option?.value?.toString() ||
|
||||||
|
"",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{errors.JenisKegiatanId && (
|
||||||
|
<p className="text-red-500 text-sm">
|
||||||
|
{errors.JenisKegiatanId}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="NamaUnitKerja">
|
||||||
|
Admin *
|
||||||
|
</Label>
|
||||||
|
<Select
|
||||||
|
id="VerifikatorId"
|
||||||
|
options={verifikatorOptions}
|
||||||
|
required
|
||||||
|
placeholder="Pilih Admin"
|
||||||
|
onChange={(option) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
VerifikatorId:
|
||||||
|
option?.value?.toString() ||
|
||||||
|
"",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{errors.VerifikatorId && (
|
||||||
|
<p className="text-red-500 text-sm">
|
||||||
|
{errors.VerifikatorId}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="PerusahaanId">
|
||||||
|
Pengelola Kawasan
|
||||||
|
</Label>
|
||||||
|
<Select
|
||||||
|
id="PerusahaanId"
|
||||||
|
options={perusahaanOptions}
|
||||||
|
placeholder="Pilih Pengelola Kawasan"
|
||||||
|
onChange={(option) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
PerusahaanId:
|
||||||
|
option?.value?.toString() ||
|
||||||
|
"",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Separator />
|
||||||
|
|
||||||
|
{/* Kontak Person */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex flex-row bg-green-200 px-2 py-1 rounded w-fit gap-2 items-center">
|
||||||
|
<UsersRound size={16} />
|
||||||
|
<h3 className="text-sm ">
|
||||||
|
Kontak Person
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="CPNama">Nama</Label>
|
||||||
|
<Input
|
||||||
|
id="CPNama"
|
||||||
|
value={data.CPNama}
|
||||||
|
onChange={(e) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
CPNama: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="CPTelepon">
|
||||||
|
Telepon
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
id="CPTelepon"
|
||||||
|
value={data.CPTelepon}
|
||||||
|
onChange={(e) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
CPTelepon: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Separator className="space-y-4" />
|
||||||
|
|
||||||
|
{/* Dokumen Izin */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex flex-row bg-green-200 px-2 py-1 rounded w-fit gap-2 items-center">
|
||||||
|
<FileText size={16} />
|
||||||
|
<h3 className="text-sm ">
|
||||||
|
Dokumen Izin
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="ILNomor">Nomor</Label>
|
||||||
|
<Input
|
||||||
|
id="ILNomor"
|
||||||
|
value={data.ILNomor}
|
||||||
|
onChange={(e) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
ILNomor: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="ILTanggal">
|
||||||
|
Tanggal
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
id="ILTanggal"
|
||||||
|
type="date"
|
||||||
|
value={data.ILTanggal}
|
||||||
|
onChange={(e) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
ILTanggal: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="JenisDokILId">
|
||||||
|
Jenis Dokumen
|
||||||
|
</Label>
|
||||||
|
<Select
|
||||||
|
id="JenisDokILId"
|
||||||
|
options={jenisDokILOptions}
|
||||||
|
placeholder="Pilih Jenis Dokumen"
|
||||||
|
onChange={(option) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
JenisDokILId:
|
||||||
|
option?.value?.toString() ||
|
||||||
|
"",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="ILDokumen">
|
||||||
|
Unggah Dokumen
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
id="ILDokumen"
|
||||||
|
type="file"
|
||||||
|
accept="pdf"
|
||||||
|
onChange={(e) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
ILDokumen: e.target.files
|
||||||
|
? e.target.files[0]
|
||||||
|
: null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Sisi Kanan */}
|
||||||
|
<div className="w-1/2">
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex flex-row bg-green-200 px-2 py-1 rounded w-fit gap-2 items-center">
|
||||||
|
<MapPinned size={16} />
|
||||||
|
<h3 className="text-sm ">
|
||||||
|
Alamat Perusahaan
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="KelurahanId">
|
||||||
|
Kabupaten/Kota *
|
||||||
|
</Label>
|
||||||
|
<Select
|
||||||
|
id="KabupatenId"
|
||||||
|
options={kabupatenOptions}
|
||||||
|
value={selectedKabupaten}
|
||||||
|
onChange={(value) => {
|
||||||
|
setSelectedKabupaten(value);
|
||||||
|
setSelectedKecamatan(null);
|
||||||
|
setSelectedKelurahan(null);
|
||||||
|
}}
|
||||||
|
placeholder="Pilih Kabupaten/Kota"
|
||||||
|
isSearchable
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="KelurahanId">
|
||||||
|
Kecamatan *
|
||||||
|
</Label>
|
||||||
|
<Select
|
||||||
|
id="KecamatanId"
|
||||||
|
options={kecamatanOptions}
|
||||||
|
value={selectedKecamatan}
|
||||||
|
onChange={(value) => {
|
||||||
|
setSelectedKecamatan(value);
|
||||||
|
setSelectedKelurahan(null);
|
||||||
|
}}
|
||||||
|
placeholder="Pilih Kecamatan"
|
||||||
|
isSearchable
|
||||||
|
isDisabled={!selectedKabupaten}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="KelurahanId">
|
||||||
|
Kelurahan *
|
||||||
|
</Label>
|
||||||
|
<Select
|
||||||
|
id="KelurahanId"
|
||||||
|
options={kelurahanOptions}
|
||||||
|
value={selectedKelurahan}
|
||||||
|
onChange={(value) => {
|
||||||
|
setSelectedKelurahan(value);
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
KelurahanId:
|
||||||
|
value?.value?.toString() ||
|
||||||
|
"",
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
placeholder="Pilih Kelurahan"
|
||||||
|
isSearchable
|
||||||
|
isDisabled={!selectedKecamatan}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="Alamat">Alamat</Label>
|
||||||
|
<Textarea
|
||||||
|
id="Alamat"
|
||||||
|
value={data.Alamat}
|
||||||
|
onChange={(e) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
Alamat: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="KodePos">Kode Pos</Label>
|
||||||
|
<Input
|
||||||
|
id="KodePos"
|
||||||
|
value={data.KodePos}
|
||||||
|
onChange={(e) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
KodePos: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="Telepon">Telepon</Label>
|
||||||
|
<Input
|
||||||
|
id="Telepon"
|
||||||
|
value={data.Telepon}
|
||||||
|
onChange={(e) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
Telepon: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="Fax">Fax</Label>
|
||||||
|
<Input
|
||||||
|
id="Fax"
|
||||||
|
value={data.Fax}
|
||||||
|
onChange={(e) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
Fax: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="Email">Email *</Label>
|
||||||
|
<Input
|
||||||
|
id="Email"
|
||||||
|
type="email"
|
||||||
|
required
|
||||||
|
value={data.Email}
|
||||||
|
onChange={(e) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
Email: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Separator className="space-y-4" />
|
||||||
|
|
||||||
|
{/* Kontak dan Koordinat */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex flex-row bg-green-200 px-2 py-1 rounded w-fit gap-2 items-center">
|
||||||
|
<LocateFixed size={16} />
|
||||||
|
<h3 className="text-sm ">Koordinat</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="Lintang">Lintang</Label>
|
||||||
|
<Input
|
||||||
|
id="Lintang"
|
||||||
|
value={data.Lintang}
|
||||||
|
onChange={(e) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
Lintang: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="Bujur">Bujur</Label>
|
||||||
|
<Input
|
||||||
|
id="Bujur"
|
||||||
|
value={data.Bujur}
|
||||||
|
onChange={(e) =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
Bujur: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Separator className="space-y-4" />
|
||||||
|
|
||||||
|
<div className="flex flex-row bg-green-200 px-2 py-1 rounded w-fit gap-2 items-center">
|
||||||
|
<VerifiedIcon size={16} />
|
||||||
|
<h3 className="text-sm">Status</h3>
|
||||||
|
</div>
|
||||||
|
<div className="flex space-x-4">
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<Checkbox
|
||||||
|
id="IsPublishActive"
|
||||||
|
checked={data.IsPublish === true}
|
||||||
|
onCheckedChange={() =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
IsPublish: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Label htmlFor="IsPublishActive">
|
||||||
|
Aktif
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<Checkbox
|
||||||
|
id="IsPublishInactive"
|
||||||
|
checked={data.IsPublish === false}
|
||||||
|
onCheckedChange={() =>
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
IsPublish: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Label htmlFor="IsPublishInactive">
|
||||||
|
Non Aktif
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Separator className="space-y-4" />
|
||||||
|
|
||||||
|
<DialogFooter>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
onClick={onClose}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
Batal
|
||||||
|
</Button>
|
||||||
|
<Button type="submit" disabled={loading}>
|
||||||
|
{loading ? "Menyimpan..." : "Simpan"}
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</form>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
import * as React from "react"
|
||||||
|
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
|
||||||
|
import { Check } from "lucide-react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
const Checkbox = React.forwardRef<
|
||||||
|
React.ElementRef<typeof CheckboxPrimitive.Root>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<CheckboxPrimitive.Root
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<CheckboxPrimitive.Indicator
|
||||||
|
className={cn("flex items-center justify-center text-current")}
|
||||||
|
>
|
||||||
|
<Check className="h-4 w-4" />
|
||||||
|
</CheckboxPrimitive.Indicator>
|
||||||
|
</CheckboxPrimitive.Root>
|
||||||
|
))
|
||||||
|
Checkbox.displayName = CheckboxPrimitive.Root.displayName
|
||||||
|
|
||||||
|
export { Checkbox }
|
|
@ -0,0 +1,135 @@
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { FileUp, X } from "lucide-react";
|
||||||
|
|
||||||
|
interface UploadDocProps {
|
||||||
|
isOpen: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
onUpload: (file: File) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const UploadDoc = ({ isOpen, onClose, onUpload }: UploadDocProps) => {
|
||||||
|
const [selectedFile, setSelectedFile] = useState<File | null>(null);
|
||||||
|
const [dragActive, setDragActive] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const handleDrag = (e: React.DragEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
if (e.type === "dragenter" || e.type === "dragover") {
|
||||||
|
setDragActive(true);
|
||||||
|
} else if (e.type === "dragleave") {
|
||||||
|
setDragActive(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDrop = (e: React.DragEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
setDragActive(false);
|
||||||
|
|
||||||
|
const file = e.dataTransfer.files[0];
|
||||||
|
if (file && file.type === "application/pdf") {
|
||||||
|
setSelectedFile(file);
|
||||||
|
} else {
|
||||||
|
alert("Hanya file PDF yang diperbolehkan");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const file = e.target.files?.[0];
|
||||||
|
if (file && file.type === "application/pdf") {
|
||||||
|
setSelectedFile(file);
|
||||||
|
} else {
|
||||||
|
alert("Hanya file PDF yang diperbolehkan");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUpload = () => {
|
||||||
|
if (selectedFile) {
|
||||||
|
onUpload(selectedFile);
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={isOpen} onOpenChange={onClose}>
|
||||||
|
<DialogContent className="sm:max-w-md">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Lampiran *</DialogTitle>
|
||||||
|
<div className="flex flex-row items-center">
|
||||||
|
<div className="h-8 w-[3px] bg-gray-300 mr-2" />
|
||||||
|
<small>
|
||||||
|
Silahkan unggah dokumen Anda dengan drag & drop
|
||||||
|
semua berkas atau klik pada kotak ini. Ukuran file
|
||||||
|
tidak boleh melebihi 20 MB.
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</DialogHeader>
|
||||||
|
<div
|
||||||
|
className={`mt-4 p-6 border-2 border-dashed rounded-lg text-center ${
|
||||||
|
dragActive
|
||||||
|
? "border-teal-500 bg-teal-50"
|
||||||
|
: "border-gray-300"
|
||||||
|
}`}
|
||||||
|
onDragEnter={handleDrag}
|
||||||
|
onDragLeave={handleDrag}
|
||||||
|
onDragOver={handleDrag}
|
||||||
|
onDrop={handleDrop}
|
||||||
|
>
|
||||||
|
<FileUp className="mx-auto h-12 w-12 text-gray-400" />
|
||||||
|
<div className="mt-4">
|
||||||
|
<p className="text-sm text-gray-600">
|
||||||
|
Drag and drop file PDF di sini atau
|
||||||
|
</p>
|
||||||
|
<label className="mt-2 cursor-pointer">
|
||||||
|
<Input
|
||||||
|
type="file"
|
||||||
|
accept=".pdf"
|
||||||
|
className="hidden"
|
||||||
|
onChange={handleFileChange}
|
||||||
|
/>
|
||||||
|
<span className="text-teal-600 hover:text-teal-500">
|
||||||
|
Pilih file
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{selectedFile && (
|
||||||
|
<div className="mt-4 p-2 bg-gray-50 rounded flex items-center justify-between">
|
||||||
|
<span className="text-sm text-gray-600">
|
||||||
|
{selectedFile.name}
|
||||||
|
</span>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => setSelectedFile(null)}
|
||||||
|
>
|
||||||
|
<X className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="mt-4 flex justify-end gap-3">
|
||||||
|
<Button variant="outline" onClick={onClose}>
|
||||||
|
Batal
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={handleUpload}
|
||||||
|
disabled={!selectedFile}
|
||||||
|
className="bg-teal-600 hover:bg-teal-700"
|
||||||
|
>
|
||||||
|
Unggah
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UploadDoc;
|
|
@ -14,6 +14,7 @@ import {
|
||||||
BreadcrumbPage,
|
BreadcrumbPage,
|
||||||
} from "@/components/ui/breadcrumb";
|
} from "@/components/ui/breadcrumb";
|
||||||
import AppearanceDropdown from "@/components/appearance-dropdown";
|
import AppearanceDropdown from "@/components/appearance-dropdown";
|
||||||
|
import { Toaster } from "@/components/ui/toaster";
|
||||||
|
|
||||||
export default function AuthenticatedLayout({
|
export default function AuthenticatedLayout({
|
||||||
header,
|
header,
|
||||||
|
@ -48,6 +49,7 @@ export default function AuthenticatedLayout({
|
||||||
|
|
||||||
<main className="p-4 md:pt-0 h-full w-full max-w-full overflow-x-hidden">
|
<main className="p-4 md:pt-0 h-full w-full max-w-full overflow-x-hidden">
|
||||||
{children}
|
{children}
|
||||||
|
<Toaster />
|
||||||
</main>
|
</main>
|
||||||
<footer className="text-sm p-4 text-center bg-background border-t">
|
<footer className="text-sm p-4 text-center bg-background border-t">
|
||||||
© Copyright {new Date().getFullYear()} Bidang Tata
|
© Copyright {new Date().getFullYear()} Bidang Tata
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import React from "react";
|
||||||
|
import { Head, Link } from "@inertiajs/react";
|
||||||
|
import "../../css/app.css";
|
||||||
|
|
||||||
|
const NotFound = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head title="Not Found" />
|
||||||
|
<div className="flex flex-col items-center justify-center h-screen bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-white">
|
||||||
|
<h1 className="text-6xl font-bold">404</h1>
|
||||||
|
<p className="text-lg mt-4">
|
||||||
|
Oops! Halaman yang kamu cari tidak ditemukan.
|
||||||
|
</p>
|
||||||
|
<Link
|
||||||
|
href="/dashboard"
|
||||||
|
className="mt-6 px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition"
|
||||||
|
>
|
||||||
|
Kembali ke Dashboard
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NotFound;
|
|
@ -43,7 +43,6 @@ import {
|
||||||
|
|
||||||
interface JenisDokIL {
|
interface JenisDokIL {
|
||||||
JenisDokILId: number | null;
|
JenisDokILId: number | null;
|
||||||
KodeJenisDokIL: string;
|
|
||||||
NamaJenisDokIL: string;
|
NamaJenisDokIL: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +60,6 @@ export default function JenisDokILIndex({
|
||||||
reset,
|
reset,
|
||||||
} = useForm<JenisDokIL>({
|
} = useForm<JenisDokIL>({
|
||||||
JenisDokILId: null,
|
JenisDokILId: null,
|
||||||
KodeJenisDokIL: "",
|
|
||||||
NamaJenisDokIL: "",
|
NamaJenisDokIL: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -79,14 +77,8 @@ export default function JenisDokILIndex({
|
||||||
let filtered = jenisdokil;
|
let filtered = jenisdokil;
|
||||||
|
|
||||||
if (search) {
|
if (search) {
|
||||||
filtered = filtered.filter(
|
filtered = filtered.filter((item) =>
|
||||||
(item) =>
|
item.NamaJenisDokIL.toLowerCase().includes(search.toLowerCase())
|
||||||
item.KodeJenisDokIL.toLowerCase().includes(
|
|
||||||
search.toLowerCase()
|
|
||||||
) ||
|
|
||||||
item.NamaJenisDokIL.toLowerCase().includes(
|
|
||||||
search.toLowerCase()
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,21 +219,6 @@ export default function JenisDokILIndex({
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="space-y-4"
|
className="space-y-4"
|
||||||
>
|
>
|
||||||
<div className="space-y-2">
|
|
||||||
<label>
|
|
||||||
Kode Jenis Dokumen
|
|
||||||
</label>
|
|
||||||
<Input
|
|
||||||
value={data.KodeJenisDokIL}
|
|
||||||
onChange={(e) =>
|
|
||||||
setData(
|
|
||||||
"KodeJenisDokIL",
|
|
||||||
e.target.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
placeholder="Masukkan kode jenis dokumen"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<label>
|
<label>
|
||||||
Nama Jenis Dokumen
|
Nama Jenis Dokumen
|
||||||
|
@ -275,7 +252,6 @@ export default function JenisDokILIndex({
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead>No</TableHead>
|
<TableHead>No</TableHead>
|
||||||
<TableHead>Kode</TableHead>
|
|
||||||
<TableHead>Nama Jenis Dokumen</TableHead>
|
<TableHead>Nama Jenis Dokumen</TableHead>
|
||||||
<TableHead>Aksi</TableHead>
|
<TableHead>Aksi</TableHead>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
@ -286,9 +262,6 @@ export default function JenisDokILIndex({
|
||||||
<TableCell>
|
<TableCell>
|
||||||
{startIndex + index + 1}
|
{startIndex + index + 1}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
|
||||||
{item.KodeJenisDokIL}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>
|
<TableCell>
|
||||||
{item.NamaJenisDokIL}
|
{item.NamaJenisDokIL}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
|
@ -0,0 +1,367 @@
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { CircleHelp, FileDown, Printer } from "lucide-react";
|
||||||
|
import AuthenticatedLayout from "@/layouts/authenticated-layout";
|
||||||
|
import { Head } from "@inertiajs/react";
|
||||||
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from "@/components/ui/tooltip";
|
||||||
|
import UploadDoc from "@/components/upload_doc";
|
||||||
|
|
||||||
|
interface PelaporanALFormProps {
|
||||||
|
onSubmit: (data: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PelaporanALForm = ({ onSubmit }: PelaporanALFormProps) => {
|
||||||
|
const [isConnected, setIsConnected] = useState<boolean | null>(null);
|
||||||
|
const [isUploadModalOpen, setIsUploadModalOpen] = useState(false);
|
||||||
|
const [uploadedFile, setUploadedFile] = useState<File | null>(null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AuthenticatedLayout header="Pelaporan Air Limbah">
|
||||||
|
<Head title="Pelaporan Air Limbah" />
|
||||||
|
<div className="p-4 space-y-6">
|
||||||
|
<Card className="shadow-lg">
|
||||||
|
<CardHeader className="bg-[#166534] text-white rounded-t-lg">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<div>
|
||||||
|
<CardTitle className="text-xl">
|
||||||
|
Laporan Pengelolaan Air Limbah - Ujicoba
|
||||||
|
</CardTitle>
|
||||||
|
<p className="text-sm opacity-90">
|
||||||
|
Tahun 2025 - Periode Triwulan 1
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => window.history.back()}
|
||||||
|
>
|
||||||
|
Kembali
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => window.print()}
|
||||||
|
>
|
||||||
|
<Printer />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => {
|
||||||
|
// Add PDF download logic here
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FileDown />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="p-6">
|
||||||
|
<div className="space-y-6">
|
||||||
|
{/* Header Section */}
|
||||||
|
<div className="flex justify-between items-center gap-4 mb-6">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<h2>Tersambung IPAL Komunal:</h2>
|
||||||
|
<div className="flex flex-row gap-3">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
id="tersambung"
|
||||||
|
name="connection"
|
||||||
|
className="w-4 h-4 text-teal-600"
|
||||||
|
onChange={() =>
|
||||||
|
setIsConnected(true)
|
||||||
|
}
|
||||||
|
checked={isConnected === true}
|
||||||
|
/>
|
||||||
|
<Label htmlFor="tersambung">
|
||||||
|
Ya
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
id="tidak"
|
||||||
|
name="connection"
|
||||||
|
className="w-4 h-4 text-teal-600"
|
||||||
|
onChange={() =>
|
||||||
|
setIsConnected(false)
|
||||||
|
}
|
||||||
|
checked={isConnected === false}
|
||||||
|
/>
|
||||||
|
<Label htmlFor="tidak">Tidak</Label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{isConnected && (
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<h2>
|
||||||
|
Lampiran
|
||||||
|
<span className="text-red-600">
|
||||||
|
*
|
||||||
|
</span>{" "}
|
||||||
|
:
|
||||||
|
</h2>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="w-48"
|
||||||
|
onClick={() =>
|
||||||
|
setIsUploadModalOpen(true)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{uploadedFile
|
||||||
|
? uploadedFile.name
|
||||||
|
: "Unggah Surat Kerjasama"}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<UploadDoc
|
||||||
|
isOpen={isUploadModalOpen}
|
||||||
|
onClose={() => setIsUploadModalOpen(false)}
|
||||||
|
onUpload={(file) => {
|
||||||
|
setUploadedFile(file);
|
||||||
|
// Handle the file upload logic here
|
||||||
|
console.log("File uploaded:", file);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Main Form Table */}
|
||||||
|
<div className="border rounded-lg overflow-hidden">
|
||||||
|
<table className="w-full">
|
||||||
|
<thead>
|
||||||
|
<tr className="bg-[#166534] text-white">
|
||||||
|
<th className="p-3 text-left w-16">
|
||||||
|
No
|
||||||
|
</th>
|
||||||
|
<th className="p-3 text-left">
|
||||||
|
Komponen
|
||||||
|
</th>
|
||||||
|
<th className="p-3 text-left w-32">
|
||||||
|
Hasil
|
||||||
|
</th>
|
||||||
|
<th className="p-3 text-left w-24">
|
||||||
|
Nilai
|
||||||
|
</th>
|
||||||
|
<th className="p-3 text-left w-32">
|
||||||
|
Lampiran
|
||||||
|
</th>
|
||||||
|
<th className="p-3 text-left w-32">
|
||||||
|
Verifikasi
|
||||||
|
</th>
|
||||||
|
<th className="p-3 text-left w-32">
|
||||||
|
Keterangan
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{/* Section 1 */}
|
||||||
|
<tr className="bg-teal-50">
|
||||||
|
<td className="p-3">I</td>
|
||||||
|
<td
|
||||||
|
className="p-3 font-medium"
|
||||||
|
colSpan={1}
|
||||||
|
>
|
||||||
|
Nilai tingkat ketaatan
|
||||||
|
pengelolaan air limbah (IKLl)
|
||||||
|
(%)
|
||||||
|
</td>
|
||||||
|
<td className="p-3"></td>
|
||||||
|
<td className="p-3">100</td>
|
||||||
|
<td className="p-3"></td>
|
||||||
|
<td className="p-3"></td>
|
||||||
|
<td className="p-3"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{/* Technical Requirements */}
|
||||||
|
{[
|
||||||
|
"Instalasi pengolah air limbah",
|
||||||
|
"Flowmeter",
|
||||||
|
"Titik pengambilan sampel",
|
||||||
|
"Saluran air limbah & air hujan terpisah",
|
||||||
|
"Izin pembuangan air limbah",
|
||||||
|
].map((item, index) => (
|
||||||
|
<tr
|
||||||
|
key={index}
|
||||||
|
className="border-t"
|
||||||
|
>
|
||||||
|
<td className="p-3">
|
||||||
|
A{index + 1}
|
||||||
|
</td>
|
||||||
|
<td className="p-3">
|
||||||
|
<div className="flex justify-between items-center w-full">
|
||||||
|
<div>{item}</div>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger>
|
||||||
|
<CircleHelp className="text-teal-600 w-5 h-5" />
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>
|
||||||
|
Deskripsi
|
||||||
|
untuk {item}
|
||||||
|
</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="p-3">
|
||||||
|
{" "}
|
||||||
|
<Select>
|
||||||
|
<SelectTrigger className="w-24">
|
||||||
|
<SelectValue placeholder="Ada" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="ada">
|
||||||
|
Ada
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="tidak">
|
||||||
|
Tidak Ada
|
||||||
|
</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</td>
|
||||||
|
<td className="p-3">100</td>
|
||||||
|
<td className="p-3"></td>
|
||||||
|
<td className="p-3"></td>
|
||||||
|
<td className="p-3"></td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{/* Implementation Section */}
|
||||||
|
{[
|
||||||
|
{
|
||||||
|
name: "Pengujian air limbah",
|
||||||
|
hasAttachment: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Pemenuhan baku mutu air limbah",
|
||||||
|
hasAttachment: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Pelaksanaan dan pemutusan wewenang",
|
||||||
|
hasSelect: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Pembuatan neraca air",
|
||||||
|
hasSelect: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Sertifikasi kompetensi",
|
||||||
|
hasSelect: true,
|
||||||
|
},
|
||||||
|
].map((item, index) => (
|
||||||
|
<tr
|
||||||
|
key={index}
|
||||||
|
className="border-t"
|
||||||
|
>
|
||||||
|
<td className="p-3">
|
||||||
|
A{index + 6}
|
||||||
|
</td>
|
||||||
|
<td className="p-3">
|
||||||
|
<div className="flex justify-between items-center w-full">
|
||||||
|
<div>{item.name}</div>
|
||||||
|
<CircleHelp className="text-teal-600 w-5 h-5" />
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="p-3">
|
||||||
|
<Select>
|
||||||
|
<SelectTrigger className="w-24">
|
||||||
|
<SelectValue placeholder="Ada" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="ada">
|
||||||
|
Ada
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="tidak">
|
||||||
|
Tidak Ada
|
||||||
|
</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</td>
|
||||||
|
<td className="p-3">100</td>
|
||||||
|
<td className="p-3">
|
||||||
|
{item.hasAttachment && (
|
||||||
|
<span className="text-teal-600">
|
||||||
|
Data...
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="p-3"></td>
|
||||||
|
<td className="p-3"></td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Notes Section */}
|
||||||
|
<div className="bg-gray-50 p-6 rounded-lg border border-gray-200 mt-6">
|
||||||
|
<h2 className="text-lg font-semibold mb-3 text-gray-800">
|
||||||
|
Catatan
|
||||||
|
</h2>
|
||||||
|
<Textarea
|
||||||
|
placeholder="Tambahkan catatan atau komentar tambahan di sini..."
|
||||||
|
className="min-h-[100px] bg-white"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Agreement & Submit Section */}
|
||||||
|
<div className="mt-8 space-y-6">
|
||||||
|
<div className="flex items-start gap-3 p-4 bg-green-50 rounded-lg border border-teal-200">
|
||||||
|
<Checkbox id="agreement" className="mt-1" />
|
||||||
|
<Label
|
||||||
|
htmlFor="agreement"
|
||||||
|
className="text-sm leading-relaxed text-gray-700"
|
||||||
|
>
|
||||||
|
Dengan mencentang ini, kami menyatakan
|
||||||
|
bahwa laporan ini telah disusun
|
||||||
|
berdasarkan ketentuan peraturan yang
|
||||||
|
berlaku dan kami bersedia bertanggung
|
||||||
|
jawab atas kebenaran data-data yang kami
|
||||||
|
kirimkan sesuai dengan fakta dilapangan.
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex justify-end gap-4">
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="hover:bg-gray-100"
|
||||||
|
>
|
||||||
|
Simpan Draft
|
||||||
|
</Button>
|
||||||
|
<Button className="bg-[#166534] hover:bg-green-700 transition-colors px-8">
|
||||||
|
Kirim Laporan
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</AuthenticatedLayout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PelaporanALForm;
|
|
@ -1,5 +1,5 @@
|
||||||
import AuthenticatedLayout from "@/layouts/authenticated-layout";
|
import AuthenticatedLayout from "@/layouts/authenticated-layout";
|
||||||
import { Head } from "@inertiajs/react";
|
import { Head, Link } from "@inertiajs/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import {
|
import {
|
||||||
|
@ -288,12 +288,16 @@ export default function PelaporanIndex() {
|
||||||
>
|
>
|
||||||
00.00
|
00.00
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell
|
<TableCell
|
||||||
colSpan={1}
|
colSpan={1}
|
||||||
className="text-center text-muted-foreground border-r border-l bg-red-100 text-red-700"
|
className="text-center text-muted-foreground border-r border-l bg-red-100 text-red-700"
|
||||||
>
|
>
|
||||||
00.00
|
<Link href="/admin/pelaporan/al">
|
||||||
|
00.00
|
||||||
|
</Link>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell
|
<TableCell
|
||||||
colSpan={1}
|
colSpan={1}
|
||||||
className="text-center text-muted-foreground border-r border-l bg-red-100 text-red-700"
|
className="text-center text-muted-foreground border-r border-l bg-red-100 text-red-700"
|
||||||
|
|
|
@ -0,0 +1,637 @@
|
||||||
|
import AuthenticatedLayout from "@/layouts/authenticated-layout";
|
||||||
|
import { Head } from "@inertiajs/react";
|
||||||
|
import React from "react";
|
||||||
|
import { useState } from "react";
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from "@/components/ui/table";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import {
|
||||||
|
BadgeCheck,
|
||||||
|
ChevronLeft,
|
||||||
|
ChevronRight,
|
||||||
|
ChevronUp,
|
||||||
|
Download,
|
||||||
|
FileText,
|
||||||
|
Key,
|
||||||
|
LockKeyhole,
|
||||||
|
Plus,
|
||||||
|
Search,
|
||||||
|
TouchpadOff,
|
||||||
|
Upload,
|
||||||
|
} from "lucide-react";
|
||||||
|
|
||||||
|
import Select from "react-select";
|
||||||
|
import { AddPerusahaanModal } from "@/components/modals/add-perusahaan-modal";
|
||||||
|
import {
|
||||||
|
Perusahaan,
|
||||||
|
JenisDokIL,
|
||||||
|
JenisKegiatan,
|
||||||
|
Verifikator,
|
||||||
|
Kabupaten,
|
||||||
|
Kecamatan,
|
||||||
|
Kelurahan,
|
||||||
|
Kawasan,
|
||||||
|
} from "@/types/perusahaan";
|
||||||
|
|
||||||
|
export default function PerusahaanIndex({
|
||||||
|
perusahaan,
|
||||||
|
jenisKegiatan,
|
||||||
|
jenisDokIL,
|
||||||
|
verifikator,
|
||||||
|
kabupaten,
|
||||||
|
kecamatan,
|
||||||
|
kelurahan,
|
||||||
|
}: {
|
||||||
|
perusahaan: Perusahaan[];
|
||||||
|
jenisKegiatan: JenisKegiatan[];
|
||||||
|
jenisDokIL: JenisDokIL[];
|
||||||
|
verifikator: Verifikator[];
|
||||||
|
kabupaten: Kabupaten[];
|
||||||
|
kecamatan: Kecamatan[];
|
||||||
|
kelurahan: Kelurahan[];
|
||||||
|
}) {
|
||||||
|
console.log("Perusahaan data:", perusahaan);
|
||||||
|
// console.log("Jenis Kegiatan data:", jenisKegiatan);
|
||||||
|
// console.log("Jenis Dok IL data:", jenisDokIL);
|
||||||
|
// console.log("Verifikator data:", verifikator);
|
||||||
|
// console.log("Kabupaten data:", kabupaten);
|
||||||
|
// console.log("Kecamatan data:", kecamatan);
|
||||||
|
// console.log("Kelurahan data:", kelurahan);
|
||||||
|
|
||||||
|
const [year, setYear] = useState<string>("2025");
|
||||||
|
const [quarter, setQuarter] = useState<string>("Triwulan 1");
|
||||||
|
|
||||||
|
const [selectedJenisKegiatan, setSelectedJenisKegiatan] = useState<{
|
||||||
|
value: string;
|
||||||
|
label: string;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
|
const [selectedJenisDokIL, setSelectedJenisDokIL] = useState<{
|
||||||
|
value: string;
|
||||||
|
label: string;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
|
const [selectedVerifikator, setSelectedVerifikator] = useState<{
|
||||||
|
value: string;
|
||||||
|
label: string;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
|
const [selectedKabupaten, setSelectedKabupaten] = useState<{
|
||||||
|
value: number;
|
||||||
|
label: string;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
|
const [selectedKecamatan, setSelectedKecamatan] = useState<{
|
||||||
|
value: number;
|
||||||
|
label: string;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
|
const [selectedKelurahan, setSelectedKelurahan] = useState<{
|
||||||
|
value: number;
|
||||||
|
label: string;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
|
const jenisKegiatanOptions = jenisKegiatan.map((jk) => ({
|
||||||
|
value: jk.JenisKegiatanId.toString(),
|
||||||
|
label: jk.NamaJenisKegiatan,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const jenisDokILOptions = jenisDokIL.map((jdi) => ({
|
||||||
|
value: jdi.JenisDokILId.toString(),
|
||||||
|
label: jdi.NamaJenisDokIL,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const verifikatorOptions = verifikator.map((v) => ({
|
||||||
|
value: v.VerifikatorId.toString(),
|
||||||
|
label: v.NamaUnitKerja,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const kabupatenOptions = kabupaten.map((k) => ({
|
||||||
|
value: k.KabupatenId,
|
||||||
|
label: k.NamaKabupaten,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const kecamatanOptions = kecamatan
|
||||||
|
.filter(
|
||||||
|
(kec) =>
|
||||||
|
selectedKabupaten && kec.KabupatenId === selectedKabupaten.value
|
||||||
|
)
|
||||||
|
.map((kec) => ({
|
||||||
|
value: kec.KecamatanId,
|
||||||
|
label: kec.NamaKecamatan,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const kelurahanOptions = kelurahan
|
||||||
|
.filter(
|
||||||
|
(kel) =>
|
||||||
|
selectedKecamatan && kel.KecamatanId === selectedKecamatan.value
|
||||||
|
)
|
||||||
|
.map((kel) => ({
|
||||||
|
value: kel.KelurahanId,
|
||||||
|
label: kel.NamaKelurahan,
|
||||||
|
}));
|
||||||
|
|
||||||
|
// const companyOptions = [
|
||||||
|
// { value: "PT Ajinomoto Indonesia", label: "PT Ajinomoto Indonesia" },
|
||||||
|
// { value: "PT Unilever Indonesia", label: "PT Unilever Indonesia" },
|
||||||
|
// {
|
||||||
|
// value: "PT Indofood Sukses Makmur",
|
||||||
|
// label: "PT Indofood Sukses Makmur",
|
||||||
|
// },
|
||||||
|
// { value: "PT Mayora Indah", label: "PT Mayora Indah" },
|
||||||
|
// ];
|
||||||
|
|
||||||
|
type CompanyOption = {
|
||||||
|
value: string;
|
||||||
|
label: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const companyOptions: CompanyOption[] = perusahaan.map((c) => ({
|
||||||
|
value: c.PerusahaanId.toString(),
|
||||||
|
label: c.NamaPerusahaan,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const [company, setCompany] = useState<CompanyOption | null>(
|
||||||
|
companyOptions[0]
|
||||||
|
);
|
||||||
|
const [showAddModal, setShowAddModal] = useState(false);
|
||||||
|
|
||||||
|
const handleSuccess = () => {
|
||||||
|
// Refresh data
|
||||||
|
window.location.reload();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Color coding helper
|
||||||
|
const getStatusColor = (status: string) => {
|
||||||
|
switch (status) {
|
||||||
|
case "belum":
|
||||||
|
return "bg-red-100 text-red-800";
|
||||||
|
case "pending":
|
||||||
|
return "bg-gray-100 text-gray-800";
|
||||||
|
case "siap":
|
||||||
|
return "bg-orange-100 text-orange-800";
|
||||||
|
case "selesai":
|
||||||
|
return "bg-green-100 text-green-800";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<AuthenticatedLayout header={"Daftar Perusahaan"}>
|
||||||
|
<Head title="Daftar Perusahaan" />
|
||||||
|
|
||||||
|
<AddPerusahaanModal
|
||||||
|
open={showAddModal}
|
||||||
|
onClose={() => setShowAddModal(false)}
|
||||||
|
onSuccess={handleSuccess}
|
||||||
|
jenisKegiatan={jenisKegiatan}
|
||||||
|
jenisDokIL={jenisDokIL}
|
||||||
|
verifikator={verifikator}
|
||||||
|
kabupaten={kabupaten}
|
||||||
|
kecamatan={kecamatan}
|
||||||
|
kelurahan={kelurahan}
|
||||||
|
perusahaan={perusahaan}
|
||||||
|
// existingPerusahaan={perusahaan.map(p => ({...p, PerusahaanId: p.PerusahaanId.toString()}))}
|
||||||
|
// existingInduk={[]}
|
||||||
|
// kawasan={kawasan}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Filter Section */}
|
||||||
|
<div className="bg-white p-6 rounded-lg shadow-sm mb-6">
|
||||||
|
<div className="flex flex-col md:flex-row md:gap-6 py-4">
|
||||||
|
<div className="w-1/2">
|
||||||
|
<h2 className="text-lg font-semibold mb-4 text-gray-800">
|
||||||
|
Filter Pencarian
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/2">
|
||||||
|
<div className="flex md:mt-0 md:justify-end">
|
||||||
|
<Button
|
||||||
|
className="bg-blue-600 hover:bg-blue-950 text-white"
|
||||||
|
onClick={() => setShowAddModal(true)}
|
||||||
|
>
|
||||||
|
<Plus className="w-4 h-4 mr-2" />
|
||||||
|
Tambah Perusahaan
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||||
|
{/* Left Column */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="grid grid-cols-3 items-center gap-4">
|
||||||
|
<label className="text-sm font-medium text-gray-700">
|
||||||
|
Perusahaan
|
||||||
|
</label>
|
||||||
|
<div className="col-span-2">
|
||||||
|
<Select
|
||||||
|
options={companyOptions}
|
||||||
|
value={company}
|
||||||
|
onChange={setCompany}
|
||||||
|
placeholder="Pilih Perusahaan"
|
||||||
|
isSearchable
|
||||||
|
className="w-full"
|
||||||
|
isClearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-3 items-center gap-4">
|
||||||
|
<label className="text-sm font-medium text-gray-700">
|
||||||
|
Kabupaten/Kota
|
||||||
|
</label>
|
||||||
|
<div className="col-span-2">
|
||||||
|
<Select
|
||||||
|
options={kabupatenOptions}
|
||||||
|
value={selectedKabupaten}
|
||||||
|
onChange={(value) => {
|
||||||
|
setSelectedKabupaten(value);
|
||||||
|
setSelectedKecamatan(null);
|
||||||
|
setSelectedKelurahan(null);
|
||||||
|
}}
|
||||||
|
placeholder="Pilih Kabupaten/Kota"
|
||||||
|
isSearchable
|
||||||
|
className="w-full"
|
||||||
|
isClearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-3 items-center gap-4">
|
||||||
|
<label className="text-sm font-medium text-gray-700">
|
||||||
|
Kecamatan
|
||||||
|
</label>
|
||||||
|
<div className="col-span-2">
|
||||||
|
<Select
|
||||||
|
options={kecamatanOptions}
|
||||||
|
value={selectedKecamatan}
|
||||||
|
onChange={(value) => {
|
||||||
|
setSelectedKecamatan(value);
|
||||||
|
setSelectedKelurahan(null);
|
||||||
|
}}
|
||||||
|
placeholder="Pilih Kecamatan"
|
||||||
|
isSearchable
|
||||||
|
className="w-full"
|
||||||
|
isClearable
|
||||||
|
isDisabled={!selectedKabupaten}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-3 items-center gap-4">
|
||||||
|
<label className="text-sm font-medium text-gray-700">
|
||||||
|
Kelurahan
|
||||||
|
</label>
|
||||||
|
<div className="col-span-2">
|
||||||
|
<Select
|
||||||
|
options={kelurahanOptions}
|
||||||
|
value={selectedKelurahan}
|
||||||
|
onChange={setSelectedKelurahan}
|
||||||
|
placeholder="Pilih Kelurahan"
|
||||||
|
isSearchable
|
||||||
|
className="w-full"
|
||||||
|
isClearable
|
||||||
|
isDisabled={!selectedKecamatan}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right Column */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="grid grid-cols-3 items-center gap-4">
|
||||||
|
<label className="text-sm font-medium text-gray-700">
|
||||||
|
Jenis Kegiatan
|
||||||
|
</label>
|
||||||
|
<div className="col-span-2">
|
||||||
|
<Select
|
||||||
|
options={jenisKegiatanOptions}
|
||||||
|
value={selectedJenisKegiatan}
|
||||||
|
onChange={setSelectedJenisKegiatan}
|
||||||
|
placeholder="Pilih Jenis Kegiatan"
|
||||||
|
isSearchable
|
||||||
|
className="w-full"
|
||||||
|
isClearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-3 items-center gap-4">
|
||||||
|
<label className="text-sm font-medium text-gray-700">
|
||||||
|
Admin
|
||||||
|
</label>
|
||||||
|
<div className="col-span-2">
|
||||||
|
<Select
|
||||||
|
options={verifikatorOptions}
|
||||||
|
value={selectedVerifikator}
|
||||||
|
onChange={setSelectedVerifikator}
|
||||||
|
placeholder="Pilih Admin"
|
||||||
|
isSearchable
|
||||||
|
className="w-full"
|
||||||
|
isClearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-3 items-center gap-4">
|
||||||
|
<label className="text-sm font-medium text-gray-700">
|
||||||
|
Jenis Izin
|
||||||
|
</label>
|
||||||
|
<div className="col-span-2">
|
||||||
|
<Select
|
||||||
|
options={jenisDokILOptions}
|
||||||
|
value={selectedJenisDokIL}
|
||||||
|
onChange={setSelectedJenisDokIL}
|
||||||
|
placeholder="Pilih Jenis Izin"
|
||||||
|
isSearchable
|
||||||
|
className="w-full"
|
||||||
|
isClearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex justify-end mt-6">
|
||||||
|
<Button className="bg-green-600 hover:bg-green-700 text-white">
|
||||||
|
<Search className="w-4 h-4 mr-2" />
|
||||||
|
Cari
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Table Section */}
|
||||||
|
<div className="w-full overflow-x-auto">
|
||||||
|
<Table className="min-w-[1000px] border-collapse">
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow className="border-b border-t bg-green-800">
|
||||||
|
<TableHead
|
||||||
|
rowSpan={2}
|
||||||
|
className="w-[50px] border-r border-l text-white"
|
||||||
|
>
|
||||||
|
No.
|
||||||
|
</TableHead>
|
||||||
|
<TableHead
|
||||||
|
rowSpan={2}
|
||||||
|
className="border-r text-center text-white"
|
||||||
|
>
|
||||||
|
Nama Perusahaan
|
||||||
|
</TableHead>
|
||||||
|
<TableHead
|
||||||
|
rowSpan={2}
|
||||||
|
className="border-r text-center text-white"
|
||||||
|
>
|
||||||
|
Jenis Kegiatan
|
||||||
|
</TableHead>
|
||||||
|
<TableHead
|
||||||
|
rowSpan={2}
|
||||||
|
className="border-r text-center text-white"
|
||||||
|
>
|
||||||
|
Alamat
|
||||||
|
</TableHead>
|
||||||
|
<TableHead
|
||||||
|
rowSpan={2}
|
||||||
|
className="border-r text-center text-white"
|
||||||
|
>
|
||||||
|
Kelurahan
|
||||||
|
</TableHead>
|
||||||
|
<TableHead
|
||||||
|
rowSpan={2}
|
||||||
|
className="border-r text-center text-white"
|
||||||
|
>
|
||||||
|
Kecamatan
|
||||||
|
</TableHead>
|
||||||
|
<TableHead
|
||||||
|
rowSpan={2}
|
||||||
|
className="border-r text-center text-white"
|
||||||
|
>
|
||||||
|
Kota
|
||||||
|
</TableHead>
|
||||||
|
<TableHead
|
||||||
|
rowSpan={2}
|
||||||
|
className="border-r text-center text-white"
|
||||||
|
>
|
||||||
|
Kode Pos
|
||||||
|
</TableHead>
|
||||||
|
<TableHead
|
||||||
|
rowSpan={2}
|
||||||
|
className="border-r text-center text-white"
|
||||||
|
>
|
||||||
|
Telp
|
||||||
|
</TableHead>
|
||||||
|
<TableHead
|
||||||
|
rowSpan={2}
|
||||||
|
className="border-r text-center text-white"
|
||||||
|
>
|
||||||
|
Fax
|
||||||
|
</TableHead>
|
||||||
|
<TableHead
|
||||||
|
rowSpan={2}
|
||||||
|
className="border-r text-center text-white"
|
||||||
|
>
|
||||||
|
Email
|
||||||
|
</TableHead>
|
||||||
|
<TableHead
|
||||||
|
className="border-r text-center text-white"
|
||||||
|
colSpan={2}
|
||||||
|
>
|
||||||
|
Koordinat
|
||||||
|
</TableHead>
|
||||||
|
<TableHead
|
||||||
|
className="border-r text-center text-white"
|
||||||
|
colSpan={2}
|
||||||
|
>
|
||||||
|
Kontak Person
|
||||||
|
</TableHead>
|
||||||
|
<TableHead
|
||||||
|
className="border-r text-center text-white"
|
||||||
|
rowSpan={2}
|
||||||
|
>
|
||||||
|
Admin
|
||||||
|
</TableHead>
|
||||||
|
<TableHead
|
||||||
|
className="border-r text-center text-white"
|
||||||
|
colSpan={4}
|
||||||
|
>
|
||||||
|
Dokumen Izin / Persetujuan Lingkungan Bidang
|
||||||
|
Tata Lingkungan
|
||||||
|
</TableHead>
|
||||||
|
|
||||||
|
<TableHead
|
||||||
|
rowSpan={2}
|
||||||
|
className="border-r text-center text-white"
|
||||||
|
>
|
||||||
|
Status Laporan
|
||||||
|
</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow className="border-b bg-green-600">
|
||||||
|
<TableHead className="text-center border-r text-white">
|
||||||
|
Lintang
|
||||||
|
</TableHead>
|
||||||
|
<TableHead className="text-center border-r text-white">
|
||||||
|
Bujur
|
||||||
|
</TableHead>
|
||||||
|
<TableHead className="text-center border-r text-white">
|
||||||
|
Nama
|
||||||
|
</TableHead>
|
||||||
|
<TableHead className="text-center border-r text-white">
|
||||||
|
Telepon
|
||||||
|
</TableHead>
|
||||||
|
<TableHead className="text-center border-r text-white">
|
||||||
|
Nomor
|
||||||
|
</TableHead>
|
||||||
|
<TableHead className="text-center border-r text-white">
|
||||||
|
Tanggal
|
||||||
|
</TableHead>
|
||||||
|
<TableHead className="text-center border-r text-white">
|
||||||
|
Jenis
|
||||||
|
</TableHead>
|
||||||
|
<TableHead className="text-center border-r text-white">
|
||||||
|
Dok
|
||||||
|
</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody className="border-b">
|
||||||
|
{perusahaan.length === 0 ? (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell
|
||||||
|
colSpan={20}
|
||||||
|
className="text-center py-4"
|
||||||
|
>
|
||||||
|
Tidak ada data perusahaan
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
) : (
|
||||||
|
perusahaan.map((item, index) => {
|
||||||
|
// Add console log to debug each perusahaan item
|
||||||
|
// console.log(
|
||||||
|
// "Perusahaan item:",
|
||||||
|
// item.verifikator
|
||||||
|
// );
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow
|
||||||
|
key={item.PerusahaanId}
|
||||||
|
className="border-b"
|
||||||
|
>
|
||||||
|
<TableCell className="text-center border-r border-l">
|
||||||
|
{index + 1}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.NamaPerusahaan || "N/A"}
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.jenis_kegiatan
|
||||||
|
?.NamaJenisKegiatan || "N/A"}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.Alamat}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.kelurahan?.NamaKelurahan ||
|
||||||
|
"N/A"}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.kelurahan?.kecamatan
|
||||||
|
?.NamaKecamatan || "N/A"}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.kelurahan?.kecamatan
|
||||||
|
?.kabupaten?.NamaKabupaten ||
|
||||||
|
"N/A"}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.KodePos}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.Telepon}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.Fax}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.Email}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.Lintang}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.Bujur}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.CPNama}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.CPTelepon}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.verifikator?.NamaUnitKerja ??
|
||||||
|
"N/A"}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.ILNomor || "N/A"}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.ILTanggal
|
||||||
|
? new Date(
|
||||||
|
item.ILTanggal
|
||||||
|
).toLocaleDateString("en-GB")
|
||||||
|
: "N/A"}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.jenis_dok_i_l
|
||||||
|
?.NamaJenisDokIL || "N/A"}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
{item.ILDokumen ? (
|
||||||
|
<a
|
||||||
|
href={`/storage/${item.ILDokumen}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<FileText className="w-4 h-4 text-green-600 hover:text-green-800" />
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center justify-center">
|
||||||
|
<TouchpadOff className="w-4 h-4" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-center border-r">
|
||||||
|
<div className="flex items-center justify-center">
|
||||||
|
{item.ReportLocked ? (
|
||||||
|
<LockKeyhole className="w-4 h-4 text-red-700" />
|
||||||
|
) : (
|
||||||
|
<Key className="w-4 h-4 text-green-700" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
{/* Pagination */}
|
||||||
|
<div className="mt-4 flex items-center gap-2 justify-end">
|
||||||
|
<Button variant="outline" size="icon">
|
||||||
|
<ChevronLeft className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
<Button variant="outline" size="icon">
|
||||||
|
<ChevronRight className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</AuthenticatedLayout>
|
||||||
|
);
|
||||||
|
}
|
|
@ -214,7 +214,7 @@ export default function VerifikatorIndex({
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Plus className="h-4 w-4 mr-2" />
|
<Plus className="h-4 w-4 mr-2" />
|
||||||
Tambah Verifikator
|
Tambah Dinas
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
|
|
||||||
|
|
|
@ -5,120 +5,177 @@ import {
|
||||||
Building,
|
Building,
|
||||||
School,
|
School,
|
||||||
Skull,
|
Skull,
|
||||||
TestTubeDiagonalIcon,
|
|
||||||
UsersRound,
|
UsersRound,
|
||||||
Waves,
|
Waves,
|
||||||
|
TrendingUp,
|
||||||
|
ArrowUpRight,
|
||||||
|
ArrowDownRight,
|
||||||
|
Activity,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import StatsCard from "@/components/Dashboard/DashCard";
|
import StatsCard from "@/components/Dashboard/DashCard";
|
||||||
import CerobongCard from "@/components/Dashboard/CerobongCard";
|
|
||||||
import { ChartCard } from "@/components/Dashboard/ChartCard";
|
import { ChartCard } from "@/components/Dashboard/ChartCard";
|
||||||
|
import { Card } from "@/components/ui/card";
|
||||||
|
|
||||||
export default function Dashboard() {
|
export default function Dashboard() {
|
||||||
return (
|
return (
|
||||||
<AuthenticatedLayout header="Dashboard">
|
<AuthenticatedLayout header="Dashboard">
|
||||||
<Head title="Dashboard" />
|
<Head title="Dashboard" />
|
||||||
|
|
||||||
<div className="flex flex-1 flex-col gap-4 h-full">
|
<div className="flex flex-1 flex-col gap-6 h-full p-6">
|
||||||
<DatePickerWithRange />
|
{/* Top Section */}
|
||||||
<div className="grid gap-4 md:grid-cols-5 items-center w-full">
|
<div className="flex justify-between items-center gap-4 flex-wrap">
|
||||||
<StatsCard
|
<div className="space-y-1">
|
||||||
title="Total Laporan Perusahaan"
|
<h2 className="text-2xl font-bold tracking-tight">
|
||||||
icon={<School size={24} />}
|
Dashboard Overview
|
||||||
value={1305}
|
</h2>
|
||||||
fromColor="from-[#E6F9FF]"
|
{/* <p className="text-muted-foreground">
|
||||||
toColor=""
|
Detailed monitoring and analytics of environmental
|
||||||
/>
|
metrics
|
||||||
<StatsCard
|
</p> */}
|
||||||
title="Jumlah Perusahaan"
|
</div>
|
||||||
icon={<Building size={24} />}
|
<DatePickerWithRange />
|
||||||
value={1305}
|
|
||||||
fromColor="from-[#F7E9FF]"
|
|
||||||
toColor=""
|
|
||||||
/>
|
|
||||||
<StatsCard
|
|
||||||
title="Jumlah Verifikator"
|
|
||||||
icon={<UsersRound size={24} />}
|
|
||||||
value={1305}
|
|
||||||
fromColor="from-[#F7E9FF]"
|
|
||||||
toColor=""
|
|
||||||
/>
|
|
||||||
<StatsCard
|
|
||||||
title="Air Limbah"
|
|
||||||
icon={<Waves size={24} />}
|
|
||||||
value={1305}
|
|
||||||
fromColor="from-[#F7E9FF]"
|
|
||||||
toColor="#fffff"
|
|
||||||
/>
|
|
||||||
<StatsCard
|
|
||||||
title="Limbah B3"
|
|
||||||
icon={<Skull size={24} />}
|
|
||||||
value={1305}
|
|
||||||
fromColor="from-[#F7E9FF]"
|
|
||||||
toColor="#fffff"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col items-stretch space-y-0 border-b p-0 sm:flex-row mt-8">
|
{/* Stats Cards Grid */}
|
||||||
<div className="flex flex-1 flex-col justify-center gap-1 px-6 py-5 sm:py-6">
|
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-5">
|
||||||
<div className="font-semibold leading-none tracking-tight">
|
<Card className="relative overflow-hidden group transition-all hover:shadow-lg">
|
||||||
Total Cerobong per hari ini
|
<div className="absolute inset-0 bg-gradient-to-br from-blue-50 to-transparent opacity-50 group-hover:opacity-70 transition-opacity" />
|
||||||
|
<div className="p-6 relative">
|
||||||
|
<div className="flex justify-between items-start">
|
||||||
|
<div className="p-2 bg-blue-100 rounded-lg">
|
||||||
|
<School className="h-5 w-5 text-blue-600" />
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center text-sm text-green-600">
|
||||||
|
<TrendingUp className="h-4 w-4 mr-1" />
|
||||||
|
+12.5%
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mt-4">
|
||||||
|
<h3 className="text-sm font-medium text-muted-foreground">
|
||||||
|
Total Laporan
|
||||||
|
</h3>
|
||||||
|
<p className="text-2xl font-bold">1,305</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm text-muted-foreground">
|
</Card>
|
||||||
Senin, 03 Feb 2025
|
|
||||||
|
<Card className="relative overflow-hidden group transition-all hover:shadow-lg">
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-br from-purple-50 to-transparent opacity-50 group-hover:opacity-70 transition-opacity" />
|
||||||
|
<div className="p-6 relative">
|
||||||
|
<div className="flex justify-between items-start">
|
||||||
|
<div className="p-2 bg-purple-100 rounded-lg">
|
||||||
|
<Building className="h-5 w-5 text-purple-600" />
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center text-sm text-green-600">
|
||||||
|
<TrendingUp className="h-4 w-4 mr-1" />
|
||||||
|
+8.2%
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mt-4">
|
||||||
|
<h3 className="text-sm font-medium text-muted-foreground">
|
||||||
|
Jumlah Perusahaan
|
||||||
|
</h3>
|
||||||
|
<p className="text-2xl font-bold">847</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Card>
|
||||||
<div className="flex">
|
|
||||||
<button
|
<Card className="relative overflow-hidden group transition-all hover:shadow-lg">
|
||||||
data-active="true"
|
<div className="absolute inset-0 bg-gradient-to-br from-green-50 to-transparent opacity-50 group-hover:opacity-70 transition-opacity" />
|
||||||
className="flex flex-1 flex-col justify-center gap-1 border-t px-6 py-4 text-left even:border-l data-[active=true]:bg-muted/50 sm:border-l sm:border-t-0 sm:px-8 sm:py-6"
|
<div className="p-6 relative">
|
||||||
>
|
<div className="flex justify-between items-start">
|
||||||
<span className="text-xs text-muted-foreground">
|
<div className="p-2 bg-green-100 rounded-lg">
|
||||||
Seluruh Perusahaan
|
<UsersRound className="h-5 w-5 text-green-600" />
|
||||||
</span>
|
</div>
|
||||||
<span className="text-lg font-bold leading-none sm:text-3xl">
|
<div className="flex items-center text-sm text-red-600">
|
||||||
2336
|
<ArrowDownRight className="h-4 w-4 mr-1" />
|
||||||
</span>
|
-3.1%
|
||||||
</button>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="mt-4">
|
||||||
<div className="w-full">
|
<h3 className="text-sm font-medium text-muted-foreground">
|
||||||
<ChartCard />
|
Jumlah Verifikator
|
||||||
|
</h3>
|
||||||
|
<p className="text-2xl font-bold">124</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card className="relative overflow-hidden group transition-all hover:shadow-lg">
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-br from-cyan-50 to-transparent opacity-50 group-hover:opacity-70 transition-opacity" />
|
||||||
|
<div className="p-6 relative">
|
||||||
|
<div className="flex justify-between items-start">
|
||||||
|
<div className="p-2 bg-cyan-100 rounded-lg">
|
||||||
|
<Waves className="h-5 w-5 text-cyan-600" />
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center text-sm text-green-600">
|
||||||
|
<ArrowUpRight className="h-4 w-4 mr-1" />
|
||||||
|
+5.7%
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mt-4">
|
||||||
|
<h3 className="text-sm font-medium text-muted-foreground">
|
||||||
|
Air Limbah
|
||||||
|
</h3>
|
||||||
|
<p className="text-2xl font-bold">2,431</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card className="relative overflow-hidden group transition-all hover:shadow-lg">
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-br from-red-50 to-transparent opacity-50 group-hover:opacity-70 transition-opacity" />
|
||||||
|
<div className="p-6 relative">
|
||||||
|
<div className="flex justify-between items-start">
|
||||||
|
<div className="p-2 bg-red-100 rounded-lg">
|
||||||
|
<Skull className="h-5 w-5 text-red-600" />
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center text-sm text-red-600">
|
||||||
|
<ArrowDownRight className="h-4 w-4 mr-1" />
|
||||||
|
-2.3%
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mt-4">
|
||||||
|
<h3 className="text-sm font-medium text-muted-foreground">
|
||||||
|
Limbah B3
|
||||||
|
</h3>
|
||||||
|
<p className="text-2xl font-bold">567</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* <div className="flex flex-1 flex-col gap-4 h-full mt-4">
|
{/* Cerobong Stats Section */}
|
||||||
<div>
|
<Card className="relative overflow-hidden">
|
||||||
<h2>Total Cerobong per hari ini</h2>
|
<div className="absolute inset-0 bg-gradient-to-br from-orange-50/50 to-transparent" />
|
||||||
<span>Senin, 03 Feb 2025</span>
|
<div className="relative p-6">
|
||||||
</div>
|
<div className="flex items-center justify-between">
|
||||||
<div className="grid gap-4 md:grid-cols-4 items-center w-full">
|
<div className="flex items-center gap-3">
|
||||||
<CerobongCard
|
<div className="p-2 bg-orange-100 rounded-lg">
|
||||||
title="Seluruh Perusahaan"
|
<Activity className="h-5 w-5 text-orange-600" />
|
||||||
value={1305}
|
</div>
|
||||||
fromColor="from-[#F7E9FF]"
|
<div>
|
||||||
toColor="#fffff"
|
<h3 className="text-xl font-semibold">
|
||||||
/>
|
Total Cerobong
|
||||||
<CardChart />
|
</h3>
|
||||||
</div>
|
<p className="text-sm text-muted-foreground">
|
||||||
</div> */}
|
Update terakhir: Senin, 03 Feb 2025
|
||||||
|
</p>
|
||||||
{/* <div className="flex-row mt-5">
|
</div>
|
||||||
<div className="w-1/3 gap-4 md:grid-cols-3 items-center">
|
</div>
|
||||||
<div className="flex flex-row gap-4 h-full">
|
<div className="text-right">
|
||||||
<div className="flex flex-col">
|
<p className="text-3xl font-bold">2,336</p>
|
||||||
<h2>Total Cerobong per hari ini</h2>
|
<div className="flex items-center justify-end gap-1 text-sm text-green-600 mt-1">
|
||||||
<span>Senin, 03 Feb 2025</span>
|
<span>Seluruh Perusahaan</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-2/3 gap-4 md:grid-cols-3 items-center mt-3 ">
|
</Card>
|
||||||
<CerobongCard
|
|
||||||
title="Jumlah Perusahaan"
|
{/* Chart Section */}
|
||||||
value={1305}
|
<div className="w-full">
|
||||||
fromColor="from-[#F7E9FF]"
|
<ChartCard />
|
||||||
toColor=""
|
</div>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div> */}
|
|
||||||
</div>
|
</div>
|
||||||
</AuthenticatedLayout>
|
</AuthenticatedLayout>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
export interface Perusahaan {
|
||||||
|
[x: string]: any;
|
||||||
|
PerusahaanId: number;
|
||||||
|
NamaPerusahaan: string;
|
||||||
|
Alamat: string;
|
||||||
|
KodePos: string;
|
||||||
|
Telepon: string;
|
||||||
|
Fax: string;
|
||||||
|
Email: string;
|
||||||
|
Lintang: string;
|
||||||
|
Bujur: string;
|
||||||
|
CPNama: string;
|
||||||
|
CPTelepon: string;
|
||||||
|
ILNomor: string;
|
||||||
|
ILTanggal: string;
|
||||||
|
ILDokumen: string;
|
||||||
|
ReportLocked: boolean;
|
||||||
|
JenisKegiatan: {
|
||||||
|
NamaJenisKegiatan: string;
|
||||||
|
};
|
||||||
|
Kelurahan: {
|
||||||
|
NamaKelurahan: string;
|
||||||
|
Kecamatan: {
|
||||||
|
NamaKecamatan: string;
|
||||||
|
Kabupaten: {
|
||||||
|
NamaKabupaten: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
Verifikator: {
|
||||||
|
NamaUnitKerja: string;
|
||||||
|
};
|
||||||
|
JenisDokIL: {
|
||||||
|
NamaJenisDokIL: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FormDataType {
|
||||||
|
NomorInduk: string;
|
||||||
|
JenisKegiatanId: string;
|
||||||
|
NamaPerusahaan: string;
|
||||||
|
Alamat: string;
|
||||||
|
KelurahanId: string;
|
||||||
|
KodePos: string;
|
||||||
|
Telepon: string;
|
||||||
|
Fax: string;
|
||||||
|
Email: string;
|
||||||
|
Lintang: string;
|
||||||
|
Bujur: string;
|
||||||
|
CPNama: string;
|
||||||
|
CPTelepon: string;
|
||||||
|
JenisDokILId: string;
|
||||||
|
VerifikatorId: string;
|
||||||
|
IsPublish: boolean;
|
||||||
|
ILNomor: string;
|
||||||
|
ILTanggal: string;
|
||||||
|
ILDokumen: File | null;
|
||||||
|
ReportLocked: true;
|
||||||
|
PerusahaanId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Kawasan {
|
||||||
|
PerusahaanId: number;
|
||||||
|
NamaPerusahaan: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface JenisDokIL {
|
||||||
|
JenisDokILId: number;
|
||||||
|
NamaJenisDokIL: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface JenisKegiatan {
|
||||||
|
JenisKegiatanId: number;
|
||||||
|
NamaJenisKegiatan: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Verifikator {
|
||||||
|
VerifikatorId: number;
|
||||||
|
NamaUnitKerja: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Kabupaten {
|
||||||
|
KabupatenId: number;
|
||||||
|
NamaKabupaten: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Kecamatan {
|
||||||
|
KecamatanId: number;
|
||||||
|
NamaKecamatan: string;
|
||||||
|
KabupatenId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Kelurahan {
|
||||||
|
KelurahanId: number;
|
||||||
|
NamaKelurahan: string;
|
||||||
|
KecamatanId: number;
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Http\Controllers\CategoryController;
|
use App\Http\Controllers\CategoryController;
|
||||||
|
use App\Http\Controllers\DaftarPerusahaanController;
|
||||||
use App\Http\Controllers\HistoryKegiatanController;
|
use App\Http\Controllers\HistoryKegiatanController;
|
||||||
use App\Http\Controllers\HomeController;
|
use App\Http\Controllers\HomeController;
|
||||||
use App\Http\Controllers\HukumController;
|
use App\Http\Controllers\HukumController;
|
||||||
|
@ -9,9 +10,11 @@ use App\Http\Controllers\JenisKegiatanController;
|
||||||
use App\Http\Controllers\JenisSanksiController;
|
use App\Http\Controllers\JenisSanksiController;
|
||||||
use App\Http\Controllers\KategoriController;
|
use App\Http\Controllers\KategoriController;
|
||||||
use App\Http\Controllers\MenuController;
|
use App\Http\Controllers\MenuController;
|
||||||
|
use App\Http\Controllers\PelaporanALController;
|
||||||
use App\Http\Controllers\PelaporanController;
|
use App\Http\Controllers\PelaporanController;
|
||||||
use App\Http\Controllers\PengumumanController;
|
use App\Http\Controllers\PengumumanController;
|
||||||
use App\Http\Controllers\PeraturanController;
|
use App\Http\Controllers\PeraturanController;
|
||||||
|
use App\Http\Controllers\PerusahaanController;
|
||||||
use App\Http\Controllers\PostController;
|
use App\Http\Controllers\PostController;
|
||||||
use App\Http\Controllers\ProfileController;
|
use App\Http\Controllers\ProfileController;
|
||||||
use App\Http\Controllers\RefCategoryController;
|
use App\Http\Controllers\RefCategoryController;
|
||||||
|
@ -37,7 +40,17 @@ Route::get('/', [HomeController::class, 'index'])->name('home');
|
||||||
// });
|
// });
|
||||||
|
|
||||||
Route::fallback(function () {
|
Route::fallback(function () {
|
||||||
return Inertia::render('404');
|
$path = request()->path();
|
||||||
|
|
||||||
|
if (str_starts_with($path, 'admin')) {
|
||||||
|
return Inertia::render('404Admin', [
|
||||||
|
'backUrl' => route('dashboard')
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Inertia::render('404', [
|
||||||
|
'backUrl' => route('home')
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::get('/pengumuman', [PengumumanController::class, 'index'])->name('pengumuman');
|
Route::get('/pengumuman', [PengumumanController::class, 'index'])->name('pengumuman');
|
||||||
|
@ -122,6 +135,10 @@ Route::middleware(['auth'])->prefix('admin')->group(function () {
|
||||||
Route::get('/pelaporan', [PelaporanController::class, 'index'])->name('admin.pelaporan.index');
|
Route::get('/pelaporan', [PelaporanController::class, 'index'])->name('admin.pelaporan.index');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Route::middleware(['auth'])->prefix('admin')->group(function () {
|
||||||
|
Route::get('/pelaporan/al', [PelaporanALController::class, 'index'])->name('admin.pelaporanAL.index');
|
||||||
|
});
|
||||||
|
|
||||||
Route::middleware(['auth'])->prefix('admin')->group(function () {
|
Route::middleware(['auth'])->prefix('admin')->group(function () {
|
||||||
Route::get('/verifikasi', [VerifPelaporanController::class, 'index'])->name('admin.verifikasi.index');
|
Route::get('/verifikasi', [VerifPelaporanController::class, 'index'])->name('admin.verifikasi.index');
|
||||||
});
|
});
|
||||||
|
@ -135,8 +152,17 @@ Route::middleware(['auth'])->prefix('admin')->group(function () {
|
||||||
Route::get('/post/add', [PostController::class, 'create'])->name('admin.post.create');
|
Route::get('/post/add', [PostController::class, 'create'])->name('admin.post.create');
|
||||||
Route::post('/post', [PostController::class, 'store'])->name('admin.post.store');
|
Route::post('/post', [PostController::class, 'store'])->name('admin.post.store');
|
||||||
Route::get('/post/{post}', [PostController::class, 'edit'])->name('admin.post.edit');
|
Route::get('/post/{post}', [PostController::class, 'edit'])->name('admin.post.edit');
|
||||||
Route::put('/post/{post}', [PostController::class, 'update'])->name('admin.post.update');
|
Route::post('/post/{post}', [PostController::class, 'update'])->name('admin.post.update');
|
||||||
Route::delete('/post/{post}', [PostController::class, 'destroy'])->name('admin.post.destroy');
|
Route::delete('/post/{post}', [PostController::class, 'destroy'])->name('admin.post.destroy');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Route::middleware(['auth'])->prefix('admin')->group(function () {
|
||||||
|
Route::get('/perusahaan', [PerusahaanController::class, 'index'])->name('admin.perusahaan.index');
|
||||||
|
Route::get('/perusahaan/add', [PerusahaanController::class, 'create'])->name('admin.perusahaan.create');
|
||||||
|
Route::post('/perusahaan', [PerusahaanController::class, 'store'])->name('admin.perusahaan.store');
|
||||||
|
Route::get('/perusahaan/{perusahaan}', [PerusahaanController::class, 'edit'])->name('admin.perusahaan.edit');
|
||||||
|
Route::post('/perusahaan/{perusahaan}', [PerusahaanController::class, 'update'])->name('admin.perusahaan.update');
|
||||||
|
Route::delete('/perusahaan/{perusahaan}', [PerusahaanController::class, 'destroy'])->name('admin.perusahaan.destroy');
|
||||||
|
});
|
||||||
|
|
||||||
require __DIR__.'/auth.php';
|
require __DIR__.'/auth.php';
|
||||||
|
|
Loading…
Reference in New Issue