Merge branch 'main' of https://git.probindo.com/Probindo/database-pertani-web
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
<div class="card-body">
|
||||
<!-- Logo -->
|
||||
<div class="app-brand justify-content-center mb-6">
|
||||
<a href="{{ route('dashboard.produktivitas') }}" class="app-brand-link">
|
||||
<a href="{{ route('dashboard.summary') }}" class="app-brand-link">
|
||||
<span class="app-brand-logo demo">
|
||||
<span class="text-primary">
|
||||
<svg width="32" height="24" viewBox="0 0 32 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
@props(['title', 'mainCount', 'icon', 'color' => 'primary', 'subLabel1', 'subCount1', 'subLabel2', 'subCount2'])
|
||||
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body p-3">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
<div>
|
||||
<p class="text-muted fw-medium mb-1 small text-uppercase">{{ $title }}</p>
|
||||
<h3 class="mb-0 fw-bold text-secondary">{{ number_format($mainCount, 0, ',', '.') }}</h3>
|
||||
</div>
|
||||
<div class="badge bg-label-{{ $color }} p-2 rounded">
|
||||
<i class="ti tabler-{{ $icon }}" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-lighter rounded p-2 mt-auto">
|
||||
<div class="row text-center gx-0">
|
||||
<div class="col-6 border-end">
|
||||
<span class="text-muted d-block" style="font-size: 0.75rem;">{{ $subLabel1 }}</span>
|
||||
<span class="fw-semibold text-dark small">{{ number_format($subCount1, 0, ',', '.') }}</span>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<span class="text-muted d-block" style="font-size: 0.75rem;">{{ $subLabel2 }}</span>
|
||||
<span class="fw-semibold text-dark small">{{ number_format($subCount2, 0, ',', '.') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,50 @@
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-12 col-sm-6 col-xl-3">
|
||||
<x-wilayah-card
|
||||
title="TOTAL PROVINSI"
|
||||
:mainCount="$totalProvinsi"
|
||||
icon="map-pin"
|
||||
color="primary"
|
||||
subLabel1="Data Aktif"
|
||||
:subCount1="$provinsiAktif"
|
||||
subLabel2="Data Kosong"
|
||||
:subCount2="$provinsiKosong"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6 col-xl-3">
|
||||
<x-wilayah-card
|
||||
title="Kabupaten & Kota"
|
||||
mainCount="{{ $totalKabKota }}"
|
||||
icon="building-skyscraper"
|
||||
color="info"
|
||||
subLabel1="Kabupaten"
|
||||
subCount1="{{ $totalKabupaten }}"
|
||||
subLabel2="Kota"
|
||||
subCount2="{{ $totalKota }}"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6 col-xl-3">
|
||||
<x-wilayah-card
|
||||
title="TOTAL KECAMATAN"
|
||||
:mainCount="$totalKecamatan"
|
||||
icon="map-pin"
|
||||
color="warning"
|
||||
subLabel1="Zona Perdesaan"
|
||||
:subCount1="$kecamatanPerdesaan"
|
||||
subLabel2="Zona Perkotaan"
|
||||
:subCount2="$kecamatanPerkotaan"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6 col-xl-3">
|
||||
<x-wilayah-card
|
||||
title="DESA & KELURAHAN"
|
||||
:mainCount="$totalDesaKelurahan"
|
||||
icon="home-2"
|
||||
color="success"
|
||||
subLabel1="Terpetakan"
|
||||
:subCount1="$terpetakan"
|
||||
subLabel2="Blm Pemetaan"
|
||||
:subCount2="$belumTerpetakan"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -18,6 +18,12 @@
|
||||
<input type="text" class="form-control" id="add-program-nama" name="nama" placeholder="Cth: Program Pertanian" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-program-nama-singkat">Nama Singkat<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="add-program-nama-singkat" name="nama_singkat" placeholder="Cth: PP" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-program-subdomain">Sub Domain<span class="text-danger">*</span></label>
|
||||
@@ -51,12 +57,14 @@
|
||||
rules: {
|
||||
nama: { required: true },
|
||||
sub_domain: { required: true },
|
||||
tahun: { required: true }
|
||||
tahun: { required: true },
|
||||
nama_singkat: { required: true }
|
||||
},
|
||||
messages: {
|
||||
nama: { required: "Nama program wajib diisi" },
|
||||
sub_domain: { required: "Subdomain wajib diisi" },
|
||||
tahun: { required: "Tahun wajib diisi" }
|
||||
tahun: { required: "Tahun wajib diisi" },
|
||||
nama_singkat: { required: "Nama singkat wajib diisi" }
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
|
||||
@@ -19,6 +19,12 @@
|
||||
<input type="text" class="form-control" id="add-program-nama" name="nama" placeholder="Cth: Program Pertanian" value="{{ old('nama', $program->nama) }}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-program-nama-singkat">Nama Singkat<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="add-program-nama-singkat" name="nama_singkat" placeholder="Cth: PP" value="{{ old('nama_singkat', $program->nama_singkat) }}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-program-subdomain">Sub Domain<span class="text-danger">*</span></label>
|
||||
@@ -56,12 +62,14 @@
|
||||
rules: {
|
||||
nama: { required: true },
|
||||
sub_domain: { required: true },
|
||||
tahun: { required: true }
|
||||
tahun: { required: true },
|
||||
nama_singkat: { required: true }
|
||||
},
|
||||
messages: {
|
||||
nama: { required: "Nama program wajib diisi" },
|
||||
sub_domain: { required: "Subdomain wajib diisi" },
|
||||
tahun: { required: "Tahun wajib diisi" }
|
||||
tahun: { required: "Tahun wajib diisi" },
|
||||
nama_singkat: { required: "Nama singkat wajib diisi" }
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
|
||||
@@ -17,6 +17,12 @@
|
||||
<input type="text" class="form-control" id="add-program-nama" name="nama" placeholder="Cth: Program Pertanian" value="{{ old('nama', $program->nama) }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-program-nama-singkat">Nama Singkat<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="add-program-nama-singkat" name="nama_singkat" placeholder="Cth: PP" value="{{ old('nama_singkat', $program->nama_singkat) }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-program-subdomain">Sub Domain<span class="text-danger">*</span></label>
|
||||
|
||||
@@ -1,619 +0,0 @@
|
||||
@extends('layout.main')
|
||||
|
||||
@push('style')
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
||||
<style>
|
||||
body { background-color: #f8faf9; font-family: 'Public Sans', sans-serif; }
|
||||
|
||||
.card { border: none; border-radius: 15px; box-shadow: 0 4px 20px rgba(0,0,0,0.05); }
|
||||
|
||||
/* Map Container */
|
||||
#map { height: 600px; width: 100%; border-radius: 15px; }
|
||||
|
||||
/* Sidebar Mini Stats */
|
||||
.stat-card-mini { transition: all 0.3s ease; border-left: 5px solid transparent; }
|
||||
.stat-card-mini:hover { transform: translateX(5px); border-left-color: var(--agri-green); }
|
||||
|
||||
/* Map Switcher Manual */
|
||||
.map-controls-custom {
|
||||
position: absolute; top: 20px; right: 20px; z-index: 1000;
|
||||
background: white; padding: 5px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
/* Table Styling */
|
||||
.table thead th { background-color: #f8f9fa; text-transform: uppercase; font-size: 11px; letter-spacing: 1px; }
|
||||
.avatar-label { width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; border-radius: 10px; font-weight: bold; }
|
||||
|
||||
.leaflet-tooltip.leaflet-modern-tooltip {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
padding: 0;
|
||||
color: #333;
|
||||
font-family: 'Public Sans', sans-serif; /* Pastikan font dashboard Anda */
|
||||
}
|
||||
|
||||
/* Menghilangkan panah kecil di bawah tooltip */
|
||||
.leaflet-modern-tooltip:before {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
/* 2. Gaya untuk Modern Map Card kita */
|
||||
.modern-map-card {
|
||||
background: #ffffff;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.12);
|
||||
padding: 16px;
|
||||
width: 190px; /* Lebar card */
|
||||
border: 1px solid rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
/* Bagian Header */
|
||||
.card-header-region {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.region-label {
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
color: #888;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.5px;
|
||||
display: block;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.region-name {
|
||||
font-weight: 700;
|
||||
font-size: 15px;
|
||||
margin: 0;
|
||||
color: #1e1e1e;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
/* Bagian Stats Row (Flexbox untuk menyusun ikon & teks) */
|
||||
.d-flex { display: flex; }
|
||||
.align-items-center { align-items: center; }
|
||||
.mb-2 { margin-bottom: 8px; }
|
||||
.me-2 { margin-right: 10px; }
|
||||
.fw-bold { font-weight: 700; }
|
||||
.small { font-size: 12px; }
|
||||
|
||||
/* Gaya Ikon Baris Statistik */
|
||||
.stat-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 8px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* Warna Latar Belakang Ringan untuk Ikon (Bootstrap style) */
|
||||
.bg-success-light { background-color: rgba(40, 167, 69, 0.1); }
|
||||
.bg-primary-light { background-color: rgba(0, 123, 255, 0.1); }
|
||||
.text-success { color: #28a745; }
|
||||
.text-primary { color: #007bff; }
|
||||
|
||||
.stat-info {
|
||||
flex: 1;
|
||||
}
|
||||
.stat-value {
|
||||
font-size: 14px;
|
||||
color: #222;
|
||||
line-height: 1;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.text-muted { color: #6c757d; }
|
||||
|
||||
/* Bagian Footer Action */
|
||||
.action-prompt {
|
||||
font-size: 12px;
|
||||
}
|
||||
/* Sedikit animasi pada chevron saat di-hover */
|
||||
.action-prompt i {
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
.leaflet-modern-tooltip:hover .action-prompt i {
|
||||
transform: translateX(3px);
|
||||
}
|
||||
|
||||
/* Gaya Bootstrap Helper Ringan (untuk jaga-jaga jika dashboard tidak memuatnya) */
|
||||
.border-top { border-top: 1px solid rgba(0,0,0,0.08) !important; }
|
||||
.border-bottom { border-bottom: 1px solid rgba(0,0,0,0.08) !important; }
|
||||
.py-2 { padding-top: 8px !important; padding-bottom: 8px !important; }
|
||||
.my-2 { margin-top: 8px !important; margin-bottom: 8px !important; }
|
||||
|
||||
.leaflet-popup-wrapper.leaflet-modern-popup-wrapper {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.leaflet-modern-popup-wrapper .leaflet-popup-content-wrapper {
|
||||
border-radius: 12px;
|
||||
padding: 0 !important; /* Hapus padding default Leaflet agar full width */
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
|
||||
border: 1px solid rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.leaflet-modern-popup-wrapper .leaflet-popup-content {
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
/* Penyesuaian panah kecil di bawah */
|
||||
.leaflet-modern-popup-wrapper .leaflet-popup-tip {
|
||||
background: #f8f9fa; /* Sesuaikan dengan warna body footer popup (bg-light) */
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
/* 2. Gaya untuk Modern Lahan Popup kita */
|
||||
.modern-lahan-popup {
|
||||
font-family: 'Public Sans', sans-serif;
|
||||
min-width: 270px; /* Lebar card */
|
||||
}
|
||||
|
||||
/* Typography Hierarki */
|
||||
.modern-lahan-popup .h5 { font-size: 16px; margin: 0; }
|
||||
.modern-lahan-popup .fs-5 { font-size: 1.25rem; }
|
||||
.modern-lahan-popup small { font-size: 11px; }
|
||||
|
||||
/* Header Farmer */
|
||||
.rounded-top-12 { border-radius: 12px 12px 0 0; }
|
||||
.header-farmer {
|
||||
border-bottom: 1px solid rgba(0,0,0,0.06);
|
||||
}
|
||||
.label-header {
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
.farmer-name {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
/* Body Details */
|
||||
.details-body {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
.rounded-bottom-12 { border-radius: 0 0 12px 12px; }
|
||||
|
||||
.label-detail {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.value-detail {
|
||||
font-size: 14px;
|
||||
margin-top: 1px;
|
||||
line-height: 1.1;
|
||||
}
|
||||
.value-commodity {
|
||||
font-size: 13px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
/* Ikon Container (derived from stats card style) */
|
||||
.icon-stat-container {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Helper Colors (for icons & backgrounds) */
|
||||
.text-danger-light { color: #dc3545 !important; }
|
||||
.text-danger { color: #dc3545 !important; }
|
||||
.text-success { color: #28a745 !important; }
|
||||
|
||||
/* Background Ringan (Bootstrap Style) */
|
||||
.text-success-light { background-color: rgba(40, 167, 69, 0.1) !important; }
|
||||
.text-danger-light { background-color: rgba(220, 53, 69, 0.1) !important; }
|
||||
.bg-primary-light { background-color: rgba(0, 123, 255, 0.1) !important; }
|
||||
|
||||
/* Bootstrap-like Utilities (untuk berjaga-jaga jika dash belum memuatnya) */
|
||||
.me-2 { margin-right: 10px !important; }
|
||||
.mb-3 { margin-bottom: 16px !important; }
|
||||
.ps-2 { padding-left: 12px !important; }
|
||||
.col-6 { width: 50%; }
|
||||
.col-12 { width: 100%; }
|
||||
.border { border: 1px solid rgba(0,0,0,0.08) !important; }
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<div class="card mb-3 stat-card-mini">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="avatar bg-label-success rounded p-2"><i class="ti tabler-mountain fs-3"></i></div>
|
||||
<!-- <span class="badge bg-label-success">+2.4%</span> -->
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<small class="text-muted text-uppercase">Total Land Area</small>
|
||||
<h4 class="mb-0 fw-bold">{{ number_format($luasTotal, 1) }} <small class="text-muted">ha</small></h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-3 stat-card-mini">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="avatar bg-label-success rounded p-2"><i class="ti tabler-map fs-3"></i></div>
|
||||
<!-- <span class="badge bg-label-success"></span> -->
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<small class="text-muted text-uppercase">Total Lahan</small>
|
||||
<h4 class="mb-0 fw-bold">{{ $totallahan }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-3 stat-card-mini">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="avatar bg-label-primary rounded p-2"><i class="ti tabler-users fs-3"></i></div>
|
||||
<span class="badge bg-success text-white text-center">Active</span>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<small class="text-muted text-uppercase">Registered Farmers</small>
|
||||
<h4 class="mb-0 fw-bold">{{ $totalpetani }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header"><h6 class="mb-0 fw-bold">Distribusi Komoditas</h6></div>
|
||||
<div class="card-body">
|
||||
@foreach(['Vanilla' => 45, 'Candlenut' => 30, 'Cocoa' => 15, 'Coffee' => 10] as $name => $val)
|
||||
<div class="mb-3">
|
||||
<div class="d-flex justify-content-between mb-1">
|
||||
<small class="fw-bold">{{ $name }}</small>
|
||||
<small class="text-muted">{{ $val }}%</small>
|
||||
</div>
|
||||
<div class="progress" style="height: 6px;">
|
||||
<div class="progress-bar bg-success" style="width: {{ $val }}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-9">
|
||||
<div class="card mb-4 overflow-hidden position-relative">
|
||||
<div class="card-header d-flex justify-content-between align-items-center bg-white py-3">
|
||||
<h6 class="mb-0 fw-bold"><i class="ti tabler-map-2 me-2"></i>Peta Sebaran Lahan</h6>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button class="btn btn-outline-secondary active" onclick="setMapLayer('satellite')">Satellite</button>
|
||||
<button class="btn btn-outline-secondary" onclick="setMapLayer('topo')">Topographic</button>
|
||||
<button class="btn btn-outline-secondary" onclick="setMapLayer('parcels')">Parcels</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="map">
|
||||
<button id="btnBackMap" class="btn btn-sm btn-dark shadow" style="display:none; position:absolute; top:20px; left:50px; z-index:1000;">
|
||||
<i class="ti tabler-arrow-left me-1"></i> Kembali ke Atas
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header border-bottom d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-0 fw-bold">Produktivitas Petani Regional</h6>
|
||||
<button class="btn btn-sm btn-success"><i class="ti tabler-plus me-1"></i> Bulk Action</button>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nama Petani</th>
|
||||
<th>ID Lahan</th>
|
||||
<th>Komoditas</th>
|
||||
<th>Luas (HA)</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($petaniList as $p)
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="avatar-label bg-label-secondary me-2">{{ substr($p->nama, 0, 1) }}</div>
|
||||
<span class="fw-bold">{{ $p->nama }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="text-muted small">TR-{{ $p->id }}</span></td>
|
||||
<td><span class="badge bg-label-info">Vanilla</span></td>
|
||||
<td class="fw-bold">{{ number_format($p->lahan->sum('luas_lahan'), 1) }}</td>
|
||||
<td><span class="badge bg-success">Verified</span></td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
<script>
|
||||
var satellite = L.tileLayer('https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}', { maxZoom: 22 });
|
||||
var topo = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png');
|
||||
var parcels = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png');
|
||||
|
||||
var map = L.map('map', { center: [-0.789, 113.921], zoom: 5, layers: [satellite], zoomControl: false });
|
||||
L.control.zoom({ position: 'topleft' }).addTo(map);
|
||||
|
||||
function setMapLayer(type) {
|
||||
map.removeLayer(satellite); map.removeLayer(topo); map.removeLayer(parcels);
|
||||
if(type === 'satellite') satellite.addTo(map);
|
||||
if(type === 'topo') topo.addTo(map);
|
||||
if(type === 'parcels') parcels.addTo(map);
|
||||
event.target.parentElement.querySelectorAll('.btn').forEach(b => b.classList.remove('active'));
|
||||
event.target.classList.add('active');
|
||||
}
|
||||
|
||||
// 2. Data dari Server
|
||||
var dataLevels = {
|
||||
'provinsi': @json($geoProvinsi),
|
||||
'kabupaten': @json($geoKabupaten),
|
||||
'kecamatan': @json($geoKecamatan),
|
||||
'desa': @json($geoDesa),
|
||||
'lahan': @json($geoLahan)
|
||||
};
|
||||
|
||||
var currentLayerGroup = L.featureGroup().addTo(map);
|
||||
var mapHistory = [];
|
||||
var btnBack = document.getElementById('btnBackMap');
|
||||
|
||||
function ensureLatLon(coords) {
|
||||
if (typeof coords[0] === 'number') {
|
||||
if (Math.abs(coords[0]) > 90) {
|
||||
return [coords[1], coords[0]];
|
||||
}
|
||||
return [coords[0], coords[1]];
|
||||
}
|
||||
return coords.map(ensureLatLon);
|
||||
}
|
||||
|
||||
function renderLevel(level, parentId = null, fallbackBounds = null) {
|
||||
var dataToRender = dataLevels[level];
|
||||
|
||||
if (parentId !== null) {
|
||||
dataToRender = dataToRender.filter(item => item.parent_id == parentId);
|
||||
}
|
||||
|
||||
if (dataToRender.length === 0) {
|
||||
alert(`Belum ada data pemetaan ${level} yang terdaftar di wilayah ini.`);
|
||||
if (mapHistory.length > 0) {
|
||||
mapHistory.pop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
currentLayerGroup.clearLayers();
|
||||
|
||||
if (level === 'lahan' && parentId !== null) {
|
||||
var parentDesa = dataLevels['desa'].find(d => d.id == parentId);
|
||||
|
||||
if (parentDesa && parentDesa.polygon) {
|
||||
try {
|
||||
var desaGeojson = typeof parentDesa.polygon === 'string' ? JSON.parse(parentDesa.polygon) : parentDesa.polygon;
|
||||
var desaLayer;
|
||||
|
||||
var desaStyle = {
|
||||
color: '#dc3545',
|
||||
weight: 2,
|
||||
dashArray: '5, 8',
|
||||
fillColor: 'none',
|
||||
interactive: false
|
||||
};
|
||||
|
||||
if (desaGeojson !== null && typeof desaGeojson === 'object' && desaGeojson.type) {
|
||||
desaLayer = L.geoJSON(desaGeojson, {
|
||||
style: desaStyle,
|
||||
coordsToLatLng: function (coords) {
|
||||
var a = coords[0], b = coords[1];
|
||||
if (Math.abs(a) > 90) return L.latLng(b, a);
|
||||
if (Math.abs(b) > 90) return L.latLng(a, b);
|
||||
return L.latLng(b, a);
|
||||
}
|
||||
});
|
||||
} else if (Array.isArray(desaGeojson)) {
|
||||
var safeCoordsDesa = ensureLatLon(desaGeojson);
|
||||
desaLayer = L.polygon(safeCoordsDesa, desaStyle);
|
||||
}
|
||||
|
||||
if (desaLayer) {
|
||||
currentLayerGroup.addLayer(desaLayer);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Gagal render batas desa:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dataToRender.forEach(function(item) {
|
||||
if (!item.polygon) return;
|
||||
try {
|
||||
var geojsonData = typeof item.polygon === 'string' ? JSON.parse(item.polygon) : item.polygon;
|
||||
var layer;
|
||||
|
||||
var styleOpts = level === 'lahan'
|
||||
? { color: '#28a745', weight: 2, fillColor: '#28a745', fillOpacity: 0.6 }
|
||||
: { color: '#f39c12', weight: 2, fillColor: '#f1c40f', fillOpacity: 0.3 };
|
||||
|
||||
if (geojsonData !== null && typeof geojsonData === 'object' && geojsonData.type) {
|
||||
layer = L.geoJSON(geojsonData, {
|
||||
style: styleOpts,
|
||||
coordsToLatLng: function (coords) {
|
||||
var a = coords[0], b = coords[1];
|
||||
if (Math.abs(a) > 90) return L.latLng(b, a);
|
||||
if (Math.abs(b) > 90) return L.latLng(a, b);
|
||||
return L.latLng(b, a);
|
||||
}
|
||||
});
|
||||
} else if (Array.isArray(geojsonData)) {
|
||||
var safeCoords = ensureLatLon(geojsonData);
|
||||
layer = L.polygon(safeCoords, styleOpts);
|
||||
}
|
||||
|
||||
if (layer) {
|
||||
if (level === 'lahan') {
|
||||
var listTanaman = item.tanaman && item.tanaman.length > 0 ? item.tanaman.join(', ') : null;
|
||||
|
||||
var komoditasText = listTanaman
|
||||
? listTanaman
|
||||
: '<span class="text-danger-light fw-medium small">Belum terdaftar</span>';
|
||||
|
||||
var cropIcon = listTanaman ? 'ti tabler-plant' : 'ti tabler-leaf-off';
|
||||
var cropIconColor = listTanaman ? 'text-success' : 'text-danger';
|
||||
|
||||
var popupContent = `
|
||||
<div class="modern-lahan-popup">
|
||||
<div class="p-3 bg-white rounded-top-12 header-farmer">
|
||||
<div class="d-flex align-items-center mb-1">
|
||||
<small class="label-header text-uppercase text-muted fw-semibold">Pemilik Lahan</small>
|
||||
</div>
|
||||
<h6 class="mb-0 fw-bold farmer-name h5">${item.nama_petani}</h6>
|
||||
</div>
|
||||
|
||||
<div class="p-3 bg-light rounded-bottom-12 details-body">
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-12 d-flex align-items-center">
|
||||
<div class="icon-stat-container rounded-circle bg-white text-muted border me-2">
|
||||
<i class="ti tabler-hash fs-5"></i>
|
||||
</div>
|
||||
<div>
|
||||
<small class="d-block text-muted text-uppercase fw-medium label-detail">ID Lahan</small>
|
||||
<span class="fw-bold text-dark value-detail">TR-${item.id}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-1">
|
||||
<div class="col-6 d-flex align-items-center">
|
||||
<div class="icon-stat-container rounded ${cropIconColor}-light me-2">
|
||||
<i class="${cropIcon} fs-5 ${cropIconColor}"></i>
|
||||
</div>
|
||||
<div class="flex-grow-1">
|
||||
<small class="d-block text-muted text-uppercase fw-medium label-detail">Komoditas</small>
|
||||
<span class="fw-semibold text-dark value-commodity">${komoditasText}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6 d-flex align-items-center border-start ps-2">
|
||||
<div class="icon-stat-container rounded bg-primary-light me-2">
|
||||
<i class="ti tabler-dimensions fs-5 text-primary"></i>
|
||||
</div>
|
||||
<div>
|
||||
<small class="d-block text-muted text-uppercase fw-medium label-detail">Luas Lahan</small>
|
||||
<span class="fw-bold text-dark value-detail">${parseFloat(item.luas).toFixed(1)} Ha</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
layer.bindPopup(popupContent, {
|
||||
maxWidth: 300,
|
||||
closeButton: true,
|
||||
offset: [0, 0],
|
||||
className: 'leaflet-modern-popup-wrapper'
|
||||
});
|
||||
} else {
|
||||
var tooltipContent = `
|
||||
<div class="modern-map-card">
|
||||
<div class="card-header-region">
|
||||
<span class="region-label">Wilayah</span>
|
||||
<h6 class="region-name">${item.nama}</h6>
|
||||
</div>
|
||||
|
||||
<div class="card-body-stats border-top border-bottom py-2 my-2">
|
||||
<div class="stat-row d-flex align-items-center mb-2">
|
||||
<div class="stat-icon bg-success-light text-success me-2 rounded-p-2">
|
||||
<i class="ti tabler-map"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<small class="text-muted text-uppercase fw-medium" style="font-size: 10px;">Jumlah Lahan</small>
|
||||
<div class="stat-value fw-bold">${parseInt(item.total_lahan)}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-row d-flex align-items-center">
|
||||
<div class="stat-icon bg-primary-light text-primary me-2 rounded-p-2">
|
||||
<i class="ti tabler-area"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<small class="text-muted text-uppercase fw-medium" style="font-size: 10px;">Total Luas</small>
|
||||
<div class="stat-value fw-bold">${parseFloat(item.total_luas).toFixed(2)} <small class="text-muted">Ha</small></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-footer-action text-center mt-2">
|
||||
<span class="action-prompt text-primary fw-medium small">
|
||||
Klik untuk detail <i class="ti tabler-chevron-right ms-1"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
layer.bindTooltip(tooltipContent, {
|
||||
sticky: true,
|
||||
direction: 'top',
|
||||
className: 'leaflet-modern-tooltip',
|
||||
offset: [0, -10]
|
||||
});
|
||||
|
||||
layer.on('click', function(e) {
|
||||
L.DomEvent.stopPropagation(e);
|
||||
var nextLevel = level === 'provinsi' ? 'kabupaten'
|
||||
: level === 'kabupaten' ? 'kecamatan'
|
||||
: level === 'kecamatan' ? 'desa' : 'lahan';
|
||||
|
||||
mapHistory.push({ level: level, parentId: parentId, bounds: currentLayerGroup.getBounds() });
|
||||
renderLevel(nextLevel, item.id, e.target.getBounds());
|
||||
});
|
||||
}
|
||||
currentLayerGroup.addLayer(layer);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Gagal memproses data level", level, "ID", item.id, e);
|
||||
}
|
||||
});
|
||||
|
||||
if (btnBack) btnBack.style.display = mapHistory.length > 0 ? 'block' : 'none';
|
||||
|
||||
if (currentLayerGroup.getLayers().length > 0) {
|
||||
var bounds = currentLayerGroup.getBounds();
|
||||
if (bounds.isValid()) {
|
||||
map.fitBounds(bounds, { padding: [30, 30], maxZoom: 18 });
|
||||
}
|
||||
} else if (fallbackBounds && fallbackBounds.isValid()) {
|
||||
map.fitBounds(fallbackBounds, { padding: [30, 30], maxZoom: 18 });
|
||||
}
|
||||
}
|
||||
|
||||
if (btnBack) {
|
||||
btnBack.addEventListener('click', function() {
|
||||
var prevState = mapHistory.pop();
|
||||
if (prevState) {
|
||||
renderLevel(prevState.level, prevState.parentId);
|
||||
if (prevState.bounds && prevState.bounds.isValid()) {
|
||||
map.fitBounds(prevState.bounds, { padding: [30, 30] });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
map.invalidateSize();
|
||||
// Render Awal: Provinsi
|
||||
renderLevel('provinsi', null);
|
||||
}, 300);
|
||||
|
||||
</script>
|
||||
@endpush
|
||||
@@ -33,14 +33,14 @@
|
||||
<!-- Header Section -->
|
||||
<div class="flex flex-col md:flex-row justify-between items-start md:items-center gap-4 mb-6">
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold teks-header-judul">
|
||||
Ringkasan M&E (Theory of Change)
|
||||
</h2>
|
||||
|
||||
<p class="text-sm mt-1 teks-header-sub">
|
||||
Capaian Utama Transformasi Bioekonomi Desa Ngada
|
||||
</p>
|
||||
</div>
|
||||
<h2 class="text-2xl font-bold teks-header-judul">
|
||||
Ringkasan M&E (Theory of Change)
|
||||
</h2>
|
||||
|
||||
<p class="text-sm mt-1 teks-header-sub">
|
||||
Capaian Utama Transformasi Bioekonomi Desa Ngada
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<button class="bg-white border border-gray-200 text-gray-600 px-4 py-2 rounded-lg text-sm font-medium hover:bg-gray-50 flex items-center gap-2">
|
||||
<i data-lucide="download" class="w-4 h-4"></i> Export PDF
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
<div
|
||||
class="offcanvas offcanvas-end"
|
||||
tabindex="-1"
|
||||
id="offcanvasAddColumn"
|
||||
aria-labelledby="offcanvasAddColumnLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasAddColumnLabel" class="offcanvas-title">Tambah Kolom</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close text-reset"
|
||||
data-bs-dismiss="offcanvas"
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="add-new-column pt-0" id="addColumnForm" action="{{ route('tabel.formulir.store', $tabel->id) }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" id="add-column-tipe" name="tipe" value="form-column" />
|
||||
<input type="hidden" id="add-column-parent" name="parent_id" value="" />
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-column-width">Lebar Kolom (1-12)</label>
|
||||
<input type="number" min="1" max="12" step="1" value="3"
|
||||
class="form-control" id="add-column-width" name="column_width" placeholder="Cth: 3" />
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success me-3 data-submit">Simpan</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Batal</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
const offcanvasAddColumn = new bootstrap.Offcanvas(document.getElementById('offcanvasAddColumn'));
|
||||
$('#addColumnForm').validate({
|
||||
rules: {
|
||||
column_width: { required: true, number: true },
|
||||
},
|
||||
messages: {
|
||||
column_width: { required: "Lebar kolom wajib diisi" },
|
||||
},
|
||||
submitHandler: function (form) {
|
||||
$.ajax({
|
||||
url: $(form).attr('action'),
|
||||
type: 'POST',
|
||||
data: $(form).serialize(),
|
||||
success: function () {
|
||||
offcanvasAddColumn.hide();
|
||||
form.reset();
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.mb-6, .form-control-validation').append(error);
|
||||
},
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
|
||||
$('.add-column').click(function(e) {
|
||||
e.preventDefault();
|
||||
$('#add-column-parent').val($(this).data('parent'));
|
||||
offcanvasAddColumn.show();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,27 @@
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
function addForm(tipe) {
|
||||
$.ajax({
|
||||
url: '{{ route('tabel.formulir.store', [$tabel->id]) }}',
|
||||
type: 'POST',
|
||||
data: {
|
||||
tipe: tipe,
|
||||
_token: '{{ csrf_token() }}',
|
||||
},
|
||||
success: function () {
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
}
|
||||
$(".add-hr-line").click(function (e) {
|
||||
e.preventDefault();
|
||||
addForm('form-hr-line');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,27 @@
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
function addForm(tipe) {
|
||||
$.ajax({
|
||||
url: '{{ route('tabel.formulir.store', [$tabel->id]) }}',
|
||||
type: 'POST',
|
||||
data: {
|
||||
tipe: tipe,
|
||||
_token: '{{ csrf_token() }}',
|
||||
},
|
||||
success: function () {
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
}
|
||||
$(".add-row").click(function (e) {
|
||||
e.preventDefault();
|
||||
addForm('form-row');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,77 @@
|
||||
<div
|
||||
class="offcanvas offcanvas-end"
|
||||
tabindex="-1"
|
||||
id="offcanvasAddSection"
|
||||
aria-labelledby="offcanvasAddSectionLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasAddSectionLabel" class="offcanvas-title">Tambah Section</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close text-reset"
|
||||
data-bs-dismiss="offcanvas"
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="add-new-section pt-0" id="addSectionForm" action="{{ route('tabel.formulir.store', $tabel->id) }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" id="add-section-tipe" name="tipe" value="form-section" />
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-section-label">Label Section</label>
|
||||
<input type="text" class="form-control" id="add-section-label" name="section_label" placeholder="Cth: Nama Petani" />
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success me-3 data-submit">Simpan</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Batal</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
const offcanvasAddSection = new bootstrap.Offcanvas(document.getElementById('offcanvasAddSection'));
|
||||
$('#addSectionForm').validate({
|
||||
rules: {
|
||||
section_label: { required: true }
|
||||
},
|
||||
messages: {
|
||||
section_label: { required: "Label wajib diisi" }
|
||||
},
|
||||
submitHandler: function (form) {
|
||||
$.ajax({
|
||||
url: $(form).attr('action'),
|
||||
type: 'POST',
|
||||
data: $(form).serialize(),
|
||||
success: function () {
|
||||
offcanvasAddSection.hide();
|
||||
form.reset();
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.mb-6, .form-control-validation').append(error);
|
||||
},
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
|
||||
$('.add-section').click(function(e) {
|
||||
e.preventDefault();
|
||||
offcanvasAddSection.show();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,85 @@
|
||||
<div
|
||||
class="offcanvas offcanvas-end"
|
||||
tabindex="-1"
|
||||
id="offcanvasAddValue"
|
||||
aria-labelledby="offcanvasAddValueLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasAddValueLabel" class="offcanvas-title">Tambah Formulir Nilai</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close text-reset"
|
||||
data-bs-dismiss="offcanvas"
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="add-new-value pt-0" id="addValueForm" action="{{ route('tabel.formulir.store', $tabel->id) }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" id="add-value-tipe" name="tipe" value="form-value" />
|
||||
<input type="hidden" id="add-value-parent" name="parent_id" value="" />
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-value-kolom">Kolom</label>
|
||||
<select class="form-select" id="add-value-kolom" name="kolom_id">
|
||||
<option value="">Pilih Kolom</option>
|
||||
@foreach ($tabel->kolom as $kolom)
|
||||
<option value="{{ $kolom->id }}">{{ $kolom->label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success me-3 data-submit">Simpan</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Batal</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
const offcanvasAddValue = new bootstrap.Offcanvas(document.getElementById('offcanvasAddValue'));
|
||||
$('#addValueForm').validate({
|
||||
rules: {
|
||||
kolom_id: { required: true },
|
||||
},
|
||||
messages: {
|
||||
kolom_id: { required: "Kolom wajib dipilih" },
|
||||
},
|
||||
submitHandler: function (form) {
|
||||
$.ajax({
|
||||
url: $(form).attr('action'),
|
||||
type: 'POST',
|
||||
data: $(form).serialize(),
|
||||
success: function () {
|
||||
offcanvasAddValue.hide();
|
||||
form.reset();
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.mb-6, .form-control-validation').append(error);
|
||||
},
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
|
||||
$('.add-value').click(function(e) {
|
||||
e.preventDefault();
|
||||
$('#add-value-parent').val($(this).data('parent'));
|
||||
offcanvasAddValue.show();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,94 @@
|
||||
<div
|
||||
class="offcanvas offcanvas-end"
|
||||
tabindex="-1"
|
||||
id="offcanvasEditColumn"
|
||||
aria-labelledby="offcanvasEditColumnLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasEditColumnLabel" class="offcanvas-title">Edit Kolom</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close text-reset"
|
||||
data-bs-dismiss="offcanvas"
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="pt-0" id="editColumnForm" action="{{ route('tabel.formulir.update', [$tabel->id, ':id']) }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<input type="hidden" id="edit-column-id" name="id" />
|
||||
<input type="hidden" id="edit-column-tipe" name="tipe" value="form-column" />
|
||||
<input type="hidden" id="edit-column-parent" name="parent_id" value="" />
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="edit-column-width">Lebar Kolom (1-12)</label>
|
||||
<input type="number" min="1" max="12" step="1" value="3"
|
||||
class="form-control" id="edit-column-width" name="column_width" placeholder="Cth: 3" />
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success me-3 data-submit">Simpan</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Batal</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
const offcanvasEditColumn = new bootstrap.Offcanvas(document.getElementById('offcanvasEditColumn'));
|
||||
$('.edit-column').click(function(e) {
|
||||
console.log('edit column');
|
||||
e.preventDefault();
|
||||
const id = $(this).data('id');
|
||||
$.get("{{ route('tabel.formulir.show', [$tabel->id, ':id']) }}".replace(':id', id), function (res) {
|
||||
if (res.status !== 'success') {
|
||||
return;
|
||||
}
|
||||
$('#edit-column-id').val(res.data.id);
|
||||
$('#edit-column-parent').val(res.data.parent_id);
|
||||
$('#edit-column-width').val(res.data.column_width);
|
||||
offcanvasEditColumn.show();
|
||||
}).fail(function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
});
|
||||
});
|
||||
$('#editColumnForm').validate({
|
||||
rules: {
|
||||
column_width: { required: true, number: true },
|
||||
},
|
||||
messages: {
|
||||
column_width: { required: "Lebar kolom wajib diisi" },
|
||||
},
|
||||
submitHandler: function (form) {
|
||||
console.log($('#edit-column-id').val());
|
||||
$.ajax({
|
||||
url: $(form).attr('action').replace(':id', $('#edit-column-id').val()),
|
||||
type: 'PUT',
|
||||
data: $(form).serialize(),
|
||||
success: function () {
|
||||
offcanvasEditColumn.hide();
|
||||
form.reset();
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.mb-6, .form-control-validation').append(error);
|
||||
},
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,89 @@
|
||||
<div
|
||||
class="offcanvas offcanvas-end"
|
||||
tabindex="-1"
|
||||
id="offcanvasEditSection"
|
||||
aria-labelledby="offcanvasEditSectionLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasEditSectionLabel" class="offcanvas-title">Edit Section</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close text-reset"
|
||||
data-bs-dismiss="offcanvas"
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="pt-0" id="editSectionForm" action="{{ route('tabel.formulir.update', [$tabel->id, ':id']) }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<input type="hidden" id="edit-section-id" name="id" />
|
||||
<input type="hidden" id="edit-section-tipe" name="tipe" value="form-section" />
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="edit-section-label">Label Section</label>
|
||||
<input type="text" class="form-control" id="edit-section-label" name="section_label" placeholder="Cth: Nama Petani" />
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success me-3 data-submit">Simpan</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Batal</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
const offcanvasEditSection = new bootstrap.Offcanvas(document.getElementById('offcanvasEditSection'));
|
||||
$('.edit-section').click(function(e) {
|
||||
console.log('edit section');
|
||||
e.preventDefault();
|
||||
const id = $(this).data('id');
|
||||
$.get("{{ route('tabel.formulir.show', [$tabel->id, ':id']) }}".replace(':id', id), function (res) {
|
||||
if (res.status !== 'success') {
|
||||
return;
|
||||
}
|
||||
$('#edit-section-id').val(res.data.id);
|
||||
$('#edit-section-label').val(res.data.section_label);
|
||||
offcanvasEditSection.show();
|
||||
}).fail(function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
});
|
||||
});
|
||||
$('#editSectionForm').validate({
|
||||
rules: {
|
||||
section_label: { required: true }
|
||||
},
|
||||
messages: {
|
||||
section_label: { required: "Label wajib diisi" }
|
||||
},
|
||||
submitHandler: function (form) {
|
||||
$.ajax({
|
||||
url: $(form).attr('action').replace(':id', $('#edit-section-id').val()),
|
||||
type: 'PUT',
|
||||
data: $(form).serialize(),
|
||||
success: function () {
|
||||
offcanvasEditSection.hide();
|
||||
form.reset();
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.mb-6, .form-control-validation').append(error);
|
||||
},
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,97 @@
|
||||
<div
|
||||
class="offcanvas offcanvas-end"
|
||||
tabindex="-1"
|
||||
id="offcanvasEditValue"
|
||||
aria-labelledby="offcanvasEditValueLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasEditValueLabel" class="offcanvas-title">Edit Formulir Nilai</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close text-reset"
|
||||
data-bs-dismiss="offcanvas"
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="pt-0" id="editValueForm" action="{{ route('tabel.formulir.update', [$tabel->id, ':id']) }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<input type="hidden" id="edit-value-id" name="id" />
|
||||
<input type="hidden" id="edit-value-tipe" name="tipe" value="form-value" />
|
||||
<input type="hidden" id="edit-value-parent" name="parent_id" value="" />
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="edit-value-kolom">Kolom</label>
|
||||
<select class="form-select" id="edit-value-kolom" name="kolom_id">
|
||||
<option value="">Pilih Kolom</option>
|
||||
@foreach ($tabel->kolom as $kolom)
|
||||
<option value="{{ $kolom->id }}">{{ $kolom->label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success me-3 data-submit">Simpan</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Batal</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
const offcanvasEditValue = new bootstrap.Offcanvas(document.getElementById('offcanvasEditValue'));
|
||||
$('.edit-value').click(function(e) {
|
||||
console.log('edit value');
|
||||
e.preventDefault();
|
||||
const id = $(this).data('id');
|
||||
$.get("{{ route('tabel.formulir.show', [$tabel->id, ':id']) }}".replace(':id', id), function (res) {
|
||||
if (res.status !== 'success') {
|
||||
return;
|
||||
}
|
||||
$('#edit-value-id').val(res.data.id);
|
||||
$('#edit-value-parent').val(res.data.parent_id);
|
||||
$('#edit-value-kolom').val(res.data.kolom_id);
|
||||
offcanvasEditValue.show();
|
||||
}).fail(function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
});
|
||||
});
|
||||
$('#editValueForm').validate({
|
||||
rules: {
|
||||
kolom_id: { required: true },
|
||||
},
|
||||
messages: {
|
||||
kolom_id: { required: "Kolom wajib dipilih" },
|
||||
},
|
||||
submitHandler: function (form) {
|
||||
$.ajax({
|
||||
url: $(form).attr('action').replace(':id', $('#edit-value-id').val()),
|
||||
type: 'PUT',
|
||||
data: $(form).serialize(),
|
||||
success: function () {
|
||||
offcanvasEditValue.hide();
|
||||
form.reset();
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.mb-6, .form-control-validation').append(error);
|
||||
},
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,283 @@
|
||||
@extends('layout.main')
|
||||
|
||||
@section('content')
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="card">
|
||||
<div class="card-header border-bottom d-flex justify-content-between align-items-center">
|
||||
<h5 class="card-title mb-0">Formulir untuk Tabel Basis Data Ekosistem: {{ $tabel->label }}</h5>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<form action="{{ route('tabel.formulir.generate', $tabel->id) }}" method="POST">
|
||||
@csrf
|
||||
<button class="btn btn-sm btn-label-primary" type="submit">
|
||||
<i class="ti tabler-automation me-1"></i> Generate Formulir
|
||||
</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="nav-align-top pt-4">
|
||||
<ul class="nav nav-pills" role="tablist">
|
||||
<li class="nav-item">
|
||||
<button
|
||||
type="button"
|
||||
class="nav-link active"
|
||||
role="tab"
|
||||
data-bs-toggle="tab"
|
||||
data-bs-target="#navs-pills-form"
|
||||
aria-controls="navs-pills-form"
|
||||
aria-selected="true">
|
||||
<i class="ti tabler-forms me-1"></i> Rancangan
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<button
|
||||
type="button"
|
||||
class="nav-link"
|
||||
role="tab"
|
||||
data-bs-toggle="tab"
|
||||
data-bs-target="#navs-pills-preview"
|
||||
aria-controls="navs-pills-preview"
|
||||
aria-selected="false">
|
||||
<i class="ti tabler-eye me-1"></i> Pratinjau
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="tab-content p-0">
|
||||
<div class="tab-pane fade show active" id="navs-pills-form" role="tabpanel">
|
||||
<div class="row pt-4">
|
||||
<div class="col-6 mb-4">
|
||||
<h6>Rancangan Form</h6>
|
||||
<ul class="list-group list-group-flush" id="list-form">
|
||||
<li class="list-group-item drag-item cursor-move ">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="lead"><strong>Formulir: {{ $tabel->label }}</strong></span>
|
||||
<div class="align-text-bottom">
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-primary rounded-pill add-row"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Tambah Baris">
|
||||
<i class="ti tabler-row-insert-bottom ti-md"></i></a>
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-primary rounded-pill add-section"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Tambah Section">
|
||||
<i class="ti tabler-new-section ti-md"></i></a>
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-primary rounded-pill add-hr-line"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Tambah Garis Pembatas">
|
||||
<i class="ti tabler-separator ti-md"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
@foreach($tabel->form as $form)
|
||||
<li class="list-group-item drag-item cursor-move pl-4">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span>{{ $form->tipe->label() }}
|
||||
@if($form->tipe->value == 'form-section')
|
||||
: {{ $form->section_label }}
|
||||
@endif
|
||||
</span>
|
||||
<div class="align-text-bottom">
|
||||
@if (!$loop->first)
|
||||
<button type="button"
|
||||
class="btn btn-icon btn-text-secondary move-up"
|
||||
data-id="{{ $form->id }}" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Pindah ke Urutan Sebelumnya">
|
||||
<i class="ti tabler-arrow-up"></i>
|
||||
</button>
|
||||
@endif
|
||||
@if (!$loop->last)
|
||||
<button type="button"
|
||||
class="btn btn-icon btn-text-secondary move-down"
|
||||
data-id="{{ $form->id }}" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Pindah ke Urutan Selanjutnya">
|
||||
<i class="ti tabler-arrow-down"></i>
|
||||
</button>
|
||||
@endif
|
||||
@if($form->tipe->value == 'form-row')
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-primary rounded-pill add-column"
|
||||
data-parent="{{ $form->id }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Tambah Kolom">
|
||||
<i class="ti tabler-column-insert-right ti-md"></i></a>
|
||||
@elseif($form->tipe->value == 'form-section')
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-primary rounded-pill edit-section" data-id="{{ $form->id }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Edit Section">
|
||||
<i class="ti tabler-section ti-md"></i></a>
|
||||
@endif
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-danger rounded-pill delete-record"
|
||||
data-id="{{ $form->id }}" data-nama="{{ $form->tipe->label() }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Hapus">
|
||||
<i class="ti tabler-trash ti-md"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
@if($form->tipe->value == 'form-row')
|
||||
<ul class="list-group list-group-flush nested-list">
|
||||
@foreach($form->form as $childForm)
|
||||
<li class="list-group-item drag-item cursor-move">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span>{{ $childForm->tipe->label() }}
|
||||
@if($childForm->tipe->value == 'form-column')
|
||||
: col-{{ $childForm->column_width }}
|
||||
@endif
|
||||
</span>
|
||||
<div class="align-text-bottom">
|
||||
@if (!$loop->first)
|
||||
<button type="button"
|
||||
class="btn btn-icon btn-text-secondary move-up"
|
||||
data-id="{{ $childForm->id }}" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Pindah ke Urutan Sebelumnya">
|
||||
<i class="ti tabler-arrow-up"></i>
|
||||
</button>
|
||||
@endif
|
||||
@if (!$loop->last)
|
||||
<button type="button"
|
||||
class="btn btn-icon btn-text-secondary move-down"
|
||||
data-id="{{ $childForm->id }}" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Pindah ke Urutan Selanjutnya">
|
||||
<i class="ti tabler-arrow-down"></i>
|
||||
</button>
|
||||
@endif
|
||||
@if($childForm->tipe->value == 'form-column')
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-primary rounded-pill edit-column"
|
||||
data-parent="{{ $form->id }}" data-id="{{ $childForm->id }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Edit Kolom">
|
||||
<i class="ti tabler-columns ti-md"></i></a>
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-primary rounded-pill move-column"
|
||||
data-parent="{{ $form->id }}" data-id="{{ $childForm->id }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Pindah Kolom ke Row Berbeda">
|
||||
<i class="ti tabler-transition-top ti-md"></i></a>
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-primary rounded-pill add-value"
|
||||
data-parent="{{ $childForm->id }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Tambah Form Nilai">
|
||||
<i class="ti tabler-file-plus ti-md"></i></a>
|
||||
@endif
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-danger rounded-pill delete-record"
|
||||
data-id="{{ $childForm->id }}" data-nama="{{ $childForm->tipe->label() }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Hapus">
|
||||
<i class="ti tabler-trash ti-md"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
@if($childForm->tipe->value == 'form-column')
|
||||
<ul class="list-group list-group-flush nested-list">
|
||||
@foreach($childForm->form as $grandchildForm)
|
||||
<li class="list-group-item drag-item cursor-move">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span>{{ $grandchildForm->tipe->label() }}
|
||||
@if($grandchildForm->tipe->value == 'form-value')
|
||||
: {{ $grandchildForm->kolom->label }}
|
||||
@endif
|
||||
</span>
|
||||
<div class="align-text-bottom">
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-primary rounded-pill edit-value"
|
||||
data-parent="{{ $childForm->id }}" data-id="{{ $grandchildForm->id }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Edit Form Nilai">
|
||||
<i class="ti tabler-file-text ti-md"></i></a>
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-danger rounded-pill delete-record"
|
||||
data-id="{{ $grandchildForm->id }}" data-nama="{{ $grandchildForm->tipe->label() }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Hapus">
|
||||
<i class="ti tabler-trash ti-md"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="navs-pills-preview" role="tabpanel">
|
||||
<div class="row pt-4">
|
||||
<div class="col-12 mb-4">
|
||||
<h6>Pratinjau Formulir</h6>
|
||||
{!! $tabel->renderHtml('preview') !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 text-end">
|
||||
<a href="{{ route('tabel.show', $tabel->id) }}" class="btn btn-label-secondary me-2">Kembali</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@include('ekosistem.form-basis-data.add-row')
|
||||
@include('ekosistem.form-basis-data.add-section')
|
||||
@include('ekosistem.form-basis-data.edit-section')
|
||||
@include('ekosistem.form-basis-data.add-hr-line')
|
||||
@include('ekosistem.form-basis-data.add-column')
|
||||
@include('ekosistem.form-basis-data.edit-column')
|
||||
@include('ekosistem.form-basis-data.move-column')
|
||||
@include('ekosistem.form-basis-data.add-value')
|
||||
@include('ekosistem.form-basis-data.edit-value')
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.7/Sortable.min.js"></script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".move-up").click(function (e) {
|
||||
e.preventDefault();
|
||||
let id = $(this).data('id');
|
||||
|
||||
$.post("{{ route('tabel.formulir.move-up', [$tabel->id, ':id']) }}".replace(':id', id), {
|
||||
_token: '{{ csrf_token() }}',
|
||||
_method: 'PUT'
|
||||
}, function (res) {
|
||||
if (res.status === 'success') {
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(".move-down").click(function (e) {
|
||||
e.preventDefault();
|
||||
let id = $(this).data('id');
|
||||
|
||||
$.post("{{ route('tabel.formulir.move-down', [$tabel->id, ':id']) }}".replace(':id', id), {
|
||||
_token: '{{ csrf_token() }}',
|
||||
_method: 'PUT'
|
||||
}, function (res) {
|
||||
if (res.status === 'success') {
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(".delete-record").click(function (e) {
|
||||
e.preventDefault();
|
||||
const id = $(this).data('id');
|
||||
const name = $(this).data('nama');
|
||||
|
||||
Swal.fire({
|
||||
title: 'Hapus?',
|
||||
text: `Form ${name} akan dihapus!`,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Ya, Hapus!',
|
||||
customClass: { confirmButton: 'btn btn-danger me-3', cancelButton: 'btn btn-label-secondary' },
|
||||
buttonsStyling: false
|
||||
}).then(function (result) {
|
||||
if (result.value) {
|
||||
$.ajax({
|
||||
url: "{{ route('tabel.formulir.destroy', [$tabel->id, ':id']) }}".replace(':id', id),
|
||||
type: 'POST',
|
||||
data: {
|
||||
_token: '{{ csrf_token() }}',
|
||||
_method: 'DELETE'
|
||||
},
|
||||
success: function () {
|
||||
Swal.fire({ icon: 'success', title: 'Terhapus!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => location.reload());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,98 @@
|
||||
<div
|
||||
class="offcanvas offcanvas-end"
|
||||
tabindex="-1"
|
||||
id="offcanvasMoveColumn"
|
||||
aria-labelledby="offcanvasMoveColumnLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasMoveColumnLabel" class="offcanvas-title">Edit Kolom</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close text-reset"
|
||||
data-bs-dismiss="offcanvas"
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="pt-0" id="moveColumnForm" action="{{ route('tabel.formulir.update', [$tabel->id, ':id']) }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<input type="hidden" id="move-column-id" name="id" />
|
||||
<input type="hidden" id="move-column-tipe" name="tipe" value="form-column" />
|
||||
<input type="hidden" id="move-column-width" name="column_width" value="" />
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="move-column-parent">Row Induk</label>
|
||||
<select class="form-select" id="move-column-parent" name="parent_id">
|
||||
<option value="">Pilih Row Induk</option>
|
||||
@foreach ($tabel->form->where('tipe', \App\Enums\LayoutForm::ROW) as $row)
|
||||
<option value="{{ $row->id }}">Row: {{ $row->urutan }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success me-3 data-submit">Simpan</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Batal</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
const offcanvasMoveColumn = new bootstrap.Offcanvas(document.getElementById('offcanvasMoveColumn'));
|
||||
$('.move-column').click(function(e) {
|
||||
console.log('move column');
|
||||
e.preventDefault();
|
||||
const id = $(this).data('id');
|
||||
$.get("{{ route('tabel.formulir.show', [$tabel->id, ':id']) }}".replace(':id', id), function (res) {
|
||||
if (res.status !== 'success') {
|
||||
return;
|
||||
}
|
||||
$('#move-column-id').val(res.data.id);
|
||||
$('#move-column-parent').val(res.data.parent_id);
|
||||
$('#move-column-width').val(res.data.column_width);
|
||||
offcanvasMoveColumn.show();
|
||||
}).fail(function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
});
|
||||
});
|
||||
$('#moveColumnForm').validate({
|
||||
rules: {
|
||||
parent_id: { required: true },
|
||||
},
|
||||
messages: {
|
||||
parent_id: { required: "Row induk wajib diisi" },
|
||||
},
|
||||
submitHandler: function (form) {
|
||||
console.log($('#move-column-id').val());
|
||||
$.ajax({
|
||||
url: $(form).attr('action').replace(':id', $('#move-column-id').val()),
|
||||
type: 'PUT',
|
||||
data: $(form).serialize(),
|
||||
success: function () {
|
||||
offcanvasMoveColumn.hide();
|
||||
form.reset();
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.mb-6, .form-control-validation').append(error);
|
||||
},
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -37,9 +37,15 @@
|
||||
<option value="date">Date</option>
|
||||
<option value="datetime">Datetime</option>
|
||||
<option value="text">Text</option>
|
||||
<option value="foreign_key">Relasi</option>
|
||||
<option value="enum">Enum</option> <option value="foreign_key">Relasi</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-6 form-control-validation" id="enum-form-opsi-update" style="display: none;">
|
||||
<label class="form-label" for="update-kolom-opsi-enum">Opsi Enum<span class="text-danger">*</span></label>
|
||||
<textarea class="form-control" id="update-kolom-opsi-enum" name="enum_opsi" placeholder='Cth: [{"label": "Ya", "value": "ya"}]'></textarea>
|
||||
</div>
|
||||
|
||||
<div class="mb-6 form-control-validation" id="relasi-form-tabel-update" style="display: none;">
|
||||
<label class="form-label" for="update-kolom-relasi-tabel">Tabel Relasi<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="update-kolom-relasi-tabel" name="relasi_tabel" placeholder="Cth: Nama Petani" />
|
||||
@@ -54,7 +60,7 @@
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="update-kolom-validasi">Validasi<span class="text-danger">*</span></label>
|
||||
<textarea class="form-control" id="update-kolom-validasi" name="validasi" value="1" placeholder="Cth: required"></textarea>
|
||||
<textarea class="form-control" id="update-kolom-validasi" name="validasi" placeholder="Cth: {"required": true}"></textarea>
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="switch">
|
||||
@@ -89,17 +95,39 @@
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
|
||||
$('#update-kolom-jenis_data').select2({
|
||||
dropdownParent: $('#offcanvasUpdateKolom'),
|
||||
width: '100%',
|
||||
});
|
||||
|
||||
$('#update-kolom-jenis_data').on('change', function() {
|
||||
var tipe = $(this).val();
|
||||
|
||||
|
||||
if (tipe === 'foreign_key') {
|
||||
$('#relasi-form-tabel-update').show();
|
||||
$('#relasi-form-kolom-update').show();
|
||||
$('#relasi-form-kolom-label-update').show();
|
||||
} else {
|
||||
$('#relasi-form-tabel-update').hide();
|
||||
$('#relasi-form-kolom-update').hide();
|
||||
$('#relasi-form-kolom-label-update').hide();
|
||||
}
|
||||
|
||||
|
||||
if (tipe === 'enum') {
|
||||
$('#enum-form-opsi-update').show();
|
||||
} else {
|
||||
$('#enum-form-opsi-update').hide();
|
||||
}
|
||||
});
|
||||
|
||||
$.validator.addMethod("snakecase", function(value, element) {
|
||||
return this.optional(element) || /^[a-z0-9]+(_[a-z0-9]+)*$/.test(value);
|
||||
}, "Gunakan format snake_case (huruf kecil dan underscore)");
|
||||
|
||||
const offcanvasUpdate = new bootstrap.Offcanvas(document.getElementById('offcanvasUpdateKolom'));
|
||||
|
||||
$(".edit-record").click(function () {
|
||||
const id = $(this).data('id');
|
||||
console.log("Edit record with ID:", id);
|
||||
@@ -114,21 +142,25 @@
|
||||
$('#update-kolom-id').val(res.data.id);
|
||||
$('#update-kolom-nama').val(res.data.kolom);
|
||||
$('#update-kolom-label').val(res.data.label);
|
||||
$('#update-kolom-jenis_data').val(res.data.tipe).trigger('change');
|
||||
$('#update-kolom-validasi').val(res.data.required ? 'required' : '');
|
||||
|
||||
let validasiVal = (typeof res.data.validasi === 'object' && res.data.validasi !== null)
|
||||
? JSON.stringify(res.data.validasi)
|
||||
: res.data.validasi;
|
||||
$('#update-kolom-validasi').val(validasiVal);
|
||||
|
||||
let opsiEnumVal = (typeof res.data.enum_opsi === 'object' && res.data.enum_opsi !== null)
|
||||
? JSON.stringify(res.data.enum_opsi)
|
||||
: res.data.enum_opsi;
|
||||
$('#update-kolom-opsi-enum').val(opsiEnumVal);
|
||||
|
||||
if (res.data.tipe === 'foreign_key') {
|
||||
console.log("Data relasi:", res.data);
|
||||
$('#update-kolom-relasi-tabel').val(res.data.relasi_tabel);
|
||||
$('#update-kolom-relasi-kolom-id').val(res.data.relasi_kolom_id);
|
||||
$('#update-kolom-relasi-kolom-label').val(res.data.relasi_kolom_label);
|
||||
$('#relasi-form-tabel-update').show();
|
||||
$('#relasi-form-kolom-update').show();
|
||||
$('#relasi-form-kolom-label-update').show();
|
||||
} else {
|
||||
$('#relasi-form-tabel-update').hide();
|
||||
$('#relasi-form-kolom-update').hide();
|
||||
$('#relasi-form-kolom-label-update').hide();
|
||||
}
|
||||
|
||||
$('#update-kolom-jenis_data').val(res.data.tipe).trigger('change');
|
||||
|
||||
$('#update-kolom-is_active').prop('checked', res.data.is_active === 1 || res.data.is_active === true);
|
||||
$('#update-kolom-is_browse').prop('checked', res.data.is_browse === 1 || res.data.is_browse === true);
|
||||
offcanvasUpdate.show();
|
||||
@@ -177,4 +209,4 @@
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@endpush
|
||||
@@ -86,13 +86,13 @@
|
||||
<div class="col-md-auto d-flex gap-2">
|
||||
@if (app()->has('SystemProgram'))
|
||||
@else
|
||||
<div class="col-md-auto">
|
||||
<div class="col-6">
|
||||
<div class="d-flex align-items-center">
|
||||
<label class="me-2 text-nowrap">Program</label>
|
||||
<select name="program_id" class="form-select form-select-sm w-auto" onchange="this.form.submit()" id="select-program">
|
||||
<option value="">Pilih Program</option>
|
||||
<option value="">--- Pilih Program ---</option>
|
||||
@foreach($programList as $prog)
|
||||
<option value="{{ $prog->id }}" {{ request('program_id') == $prog->id ? 'selected' : '' }}>{{ $prog->nama }}</option>
|
||||
<option value="{{ $prog->id }}" {{ request('program_id') == $prog->id ? 'selected' : '' }}>{{ $prog->nama_singkat }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
@@ -102,9 +102,8 @@
|
||||
<input type="text" name="search" class="form-control" placeholder="Cari Nama Petani..." value="{{ request('search') }}">
|
||||
<button type="submit" class="btn btn-outline-primary"><i class="ti tabler-search"></i></button>
|
||||
</div>
|
||||
<a href="{{ route('petani-cpm.create', ['program_id' => request('program_id')]) }}" class="btn btn-sm btn-primary"
|
||||
style="display: {{ request('program_id') ? 'flex' : 'none' }};">
|
||||
<i class="ti tabler-plus me-1"></i> Tambah
|
||||
<a href="{{ route('petani-cpm.create', ['program_id' => request('program_id')]) }}" class="btn btn-sm btn-primary flex-shrink-0">
|
||||
<i class="icon-base ti tabler-plus me-1"></i> Tambah
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
@@ -159,6 +158,7 @@
|
||||
'use strict';
|
||||
|
||||
$(document).ready(function () {
|
||||
$('#select-program').select2();
|
||||
|
||||
$(".delete-record").click(function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="card">
|
||||
<div class="card-header border-bottom mb-4">
|
||||
<h5 class="card-title mb-0">Edit Petani (CPM)</h5>
|
||||
<h5 class="card-title mb-0">Data Petani (CPM)</h5>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
@@ -159,6 +159,24 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h6 class="mb-3">Informasi Formulir Tabel</h6>
|
||||
|
||||
<hr class="my-4 mx-n4" />
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-auto d-flex gap-2">
|
||||
<a href="{{ route('tabel.formulir.index', ['tabel' => $tabel->id]) }}" class="btn btn-sm btn-primary" >
|
||||
<i class="ti tabler-edit me-1"></i> Edit
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<h6>Pratinjau Formulir</h6>
|
||||
{!! $tabel->renderHtml('preview') !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 text-end">
|
||||
<a href="{{ route('tabel.index') }}" class="btn btn-label-secondary me-2">Kembali</a>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
@extends('layout.main')
|
||||
|
||||
@section('content')
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="card">
|
||||
<div class="card-header border-bottom mb-4">
|
||||
<h5 class="card-title mb-0">Tambah Data {{ $tabel->label }}</h5>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form id="addNewDataForm" action="{{ route('tabel.data.store', [$tabel->id, 'program_id' => $program->id]) }}" method="POST" >
|
||||
@csrf
|
||||
|
||||
<h6 class="mb-3">Informasi {{ $tabel->label }}</h6>
|
||||
<div class="row">
|
||||
@foreach($kolom as $k)
|
||||
<div class="col-md-3 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-data-{{ $k->kolom }}">{{ $k->label }}<span class="text-danger">*</span></label>
|
||||
@if($k->tipe == 'varchar')
|
||||
<input type="text" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) }}" />
|
||||
@elseif($k->tipe == 'text')
|
||||
<textarea class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}">{{ old($k->kolom) }}</textarea>
|
||||
@elseif($k->tipe == 'integer')
|
||||
<input type="number" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) }}" step="1" />
|
||||
@elseif($k->tipe == 'float')
|
||||
<input type="number" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) }}" step="any" />
|
||||
@elseif($k->tipe == 'date')
|
||||
<input type="date" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) }}" />
|
||||
@elseif($k->tipe == 'datetime')
|
||||
<input type="datetime-local" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) }}" />
|
||||
@elseif($k->tipe == 'boolean')
|
||||
<select class="form-select tipe-boolean @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" name="{{ $k->kolom }}">
|
||||
<option value="1" {{ old($k->kolom) == 1 ? 'selected' : '' }}>Ya</option>
|
||||
<option value="0" {{ old($k->kolom) == 0 ? 'selected' : '' }}>Tidak</option>
|
||||
</select>
|
||||
@elseif($k->tipe == 'foreign_key')
|
||||
<select class="form-select tipe-fk @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" name="{{ $k->kolom }}">
|
||||
@if ($list_relasi->where('kolom_id', $k->id)->first() != null)
|
||||
@foreach($list_relasi->where('kolom_id', $k->id)->first()['options'] as $opsi_relasi)
|
||||
<option value="{{ $opsi_relasi->value }}" {{ old($k->kolom) == $opsi_relasi->value ? 'selected' : '' }}>{{ $opsi_relasi->label }}</option>
|
||||
@endforeach
|
||||
@endif
|
||||
</select>
|
||||
@elseif($k->tipe == 'enum')
|
||||
<select class="form-select tipe-fk @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" name="{{ $k->kolom }}">
|
||||
@foreach($k->enum_opsi as $opsi)
|
||||
<option value="{{ $opsi['value'] }}" {{ old($k->kolom) == $opsi['value'] ? 'selected' : '' }}>{{ $opsi['label'] }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@else
|
||||
<input type="text" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) }}" />
|
||||
@endif
|
||||
@error($k->kolom)<div class="error invalid-feedback">{{ $message }}</div>@enderror
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mt-4 text-end">
|
||||
<a href="{{ route('tabel.data.index', [$tabel->id, 'program_id' => $program->id]) }}" class="btn btn-label-secondary me-2">Kembali</a>
|
||||
<button type="submit" class="btn btn-success data-submit">Simpan Data</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
'use strict';
|
||||
$(document).ready(function () {
|
||||
$('#add-data-program,.tipe-boolean, .tipe-fk').select2();
|
||||
|
||||
$('#addNewDataForm').validate({
|
||||
rules: {
|
||||
tabel: { required: true, snakecase: true },
|
||||
label: { required: true },
|
||||
menu: { required: true }
|
||||
},
|
||||
messages: {
|
||||
tabel: { required: "Nama tabel wajib diisi", snakecase: "Gunakan format snake_case (huruf kecil dan underscore)" },
|
||||
label: { required: "Label wajib diisi" },
|
||||
menu: { required: "Judul menu wajib diisi" }
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.mb-6, .form-control-validation').append(error);
|
||||
},
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -10,58 +10,8 @@
|
||||
<div class="card-body">
|
||||
<form id="addNewDataForm" action="{{ route('tabel.data.store', [$tabel->id, 'program_id' => $program->id]) }}" method="POST" >
|
||||
@csrf
|
||||
|
||||
<h6 class="mb-3">Informasi {{ $tabel->label }}</h6>
|
||||
<div class="row">
|
||||
@foreach($kolom as $k)
|
||||
<div class="col-md-3 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-data-{{ $k->kolom }}">{{ $k->label }}<span class="text-danger">*</span></label>
|
||||
@if($k->tipe == 'varchar')
|
||||
<input type="text" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) }}" />
|
||||
@elseif($k->tipe == 'text')
|
||||
<textarea class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}">{{ old($k->kolom) }}</textarea>
|
||||
@elseif($k->tipe == 'integer')
|
||||
<input type="number" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) }}" step="1" />
|
||||
@elseif($k->tipe == 'float')
|
||||
<input type="number" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) }}" step="any" />
|
||||
@elseif($k->tipe == 'date')
|
||||
<input type="date" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) }}" />
|
||||
@elseif($k->tipe == 'datetime')
|
||||
<input type="datetime-local" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) }}" />
|
||||
@elseif($k->tipe == 'boolean')
|
||||
<select class="form-select tipe-boolean @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" name="{{ $k->kolom }}">
|
||||
<option value="1" {{ old($k->kolom) == 1 ? 'selected' : '' }}>Ya</option>
|
||||
<option value="0" {{ old($k->kolom) == 0 ? 'selected' : '' }}>Tidak</option>
|
||||
</select>
|
||||
@elseif($k->tipe == 'foreign_key')
|
||||
<select class="form-select tipe-fk @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" name="{{ $k->kolom }}">
|
||||
@if ($list_relasi->where('kolom_id', $k->id)->first() != null)
|
||||
@foreach($list_relasi->where('kolom_id', $k->id)->first()['options'] as $opsi_relasi)
|
||||
<option value="{{ $opsi_relasi->value }}" {{ old($k->kolom) == $opsi_relasi->value ? 'selected' : '' }}>{{ $opsi_relasi->label }}</option>
|
||||
@endforeach
|
||||
@endif
|
||||
</select>
|
||||
@elseif($k->tipe == 'enum')
|
||||
<select class="form-select tipe-fk @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" name="{{ $k->kolom }}">
|
||||
@foreach($k->enum_opsi as $opsi)
|
||||
<option value="{{ $opsi['value'] }}" {{ old($k->kolom) == $opsi['value'] ? 'selected' : '' }}>{{ $opsi['label'] }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@else
|
||||
<input type="text" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) }}" />
|
||||
@endif
|
||||
@error($k->kolom)<div class="error invalid-feedback">{{ $message }}</div>@enderror
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
|
||||
{!! $tabel->renderHtml('add', $errors, $list_relasi) !!}
|
||||
|
||||
<div class="mt-4 text-end">
|
||||
<a href="{{ route('tabel.data.index', [$tabel->id, 'program_id' => $program->id]) }}" class="btn btn-label-secondary me-2">Kembali</a>
|
||||
@@ -77,7 +27,7 @@
|
||||
<script>
|
||||
'use strict';
|
||||
$(document).ready(function () {
|
||||
$('#add-data-program,.tipe-boolean, .tipe-fk').select2();
|
||||
$('#add-data-program,.tipe-boolean, .tipe-foreign_key, .tipe-enum').select2();
|
||||
|
||||
$('#addNewDataForm').validate({
|
||||
rules: {
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
@extends('layout.main')
|
||||
|
||||
@section('content')
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="card">
|
||||
<div class="card-header border-bottom mb-4">
|
||||
<h5 class="card-title mb-0">Tambah Data {{ $tabel->label }}</h5>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form id="addUpdateDataForm" action="{{ route('tabel.data.update', [$tabel->id, $value_id, 'program_id' => $program->id]) }}" method="POST" >
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<h6 class="mb-3">Informasi {{ $tabel->label }}</h6>
|
||||
@if (!$program)
|
||||
<div class="row">
|
||||
<div class="col-md-3 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-data-program">Program<span class="text-danger">*</span></label>
|
||||
<select name="program_id" class="form-select form-select-sm w-auto" onchange="this.form.submit()">
|
||||
<option value="">Pilih Program</option>
|
||||
@foreach($programList as $prog)
|
||||
<option value="{{ $prog->id }}" {{ request('program_id') == $prog->id ? 'selected' : '' }}>{{ $prog->nama }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<div class="row">
|
||||
@foreach($kolom as $k)
|
||||
<?php
|
||||
$value = $values->where('kolom_id', $k->id)->first();
|
||||
?>
|
||||
<div class="col-md-3 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-data-{{ $k->kolom }}">{{ $k->label }}<span class="text-danger">*</span></label>
|
||||
@if($k->tipe == 'varchar')
|
||||
<input type="text" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" />
|
||||
@elseif($k->tipe == 'text')
|
||||
<textarea class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}">{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}</textarea>
|
||||
@elseif($k->tipe == 'integer')
|
||||
<input type="number" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" step="1" />
|
||||
@elseif($k->tipe == 'float')
|
||||
<input type="number" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" step="any" />
|
||||
@elseif($k->tipe == 'date')
|
||||
<input type="date" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" />
|
||||
@elseif($k->tipe == 'datetime')
|
||||
<input type="datetime-local" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" />
|
||||
@elseif($k->tipe == 'boolean')
|
||||
<select class="form-select tipe-boolean @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" name="{{ $k->kolom }}">
|
||||
<option value="1" {{ (old($k->kolom) ?? ($value['value_'.$k->tipe] ?? null)) == 1 ? 'selected' : '' }}>Ya</option>
|
||||
<option value="0" {{ (old($k->kolom) ?? ($value['value_'.$k->tipe] ?? null)) == 0 ? 'selected' : '' }}>Tidak</option>
|
||||
</select>
|
||||
@elseif($k->tipe == 'foreign_key')
|
||||
<select class="form-select tipe-fk @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" name="{{ $k->kolom }}">
|
||||
@if ($list_relasi->where('kolom_id', $k->id)->first() != null)
|
||||
@foreach($list_relasi->where('kolom_id', $k->id)->first()['options'] as $opsi_relasi)
|
||||
<option value="{{ $opsi_relasi->value }}" {{ old($k->kolom) ?? $value['value_'.$k->tipe] == $opsi_relasi->value ? 'selected' : '' }}>{{ $opsi_relasi->label }}</option>
|
||||
@endforeach
|
||||
@endif
|
||||
</select>
|
||||
@elseif($k->tipe == 'enum')
|
||||
<select class="form-select tipe-fk @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" name="{{ $k->kolom }}">
|
||||
@foreach($k->enum_opsi as $opsi)
|
||||
<option value="{{ $opsi['value'] }}" {{ old($k->kolom) ?? $value['value_'.$k->tipe] == $opsi['value'] ? 'selected' : '' }}>{{ $opsi['label'] }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@else
|
||||
<input type="text" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" />
|
||||
@endif
|
||||
@error($k->kolom)<div class="error invalid-feedback">{{ $message }}</div>@enderror
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mt-4 text-end">
|
||||
<a href="{{ route('tabel.data.index', [$tabel->id, 'program_id' => $program->id]) }}" class="btn btn-label-secondary me-2">Kembali</a>
|
||||
<button type="submit" class="btn btn-success data-submit">Simpan Data</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
'use strict';
|
||||
$(document).ready(function () {
|
||||
$('#add-data-program,.tipe-boolean, .tipe-fk').select2();
|
||||
|
||||
$('#addNewDataForm').validate({
|
||||
rules: {
|
||||
tabel: { required: true, snakecase: true },
|
||||
label: { required: true },
|
||||
menu: { required: true }
|
||||
},
|
||||
messages: {
|
||||
tabel: { required: "Nama tabel wajib diisi", snakecase: "Gunakan format snake_case (huruf kecil dan underscore)" },
|
||||
label: { required: "Label wajib diisi" },
|
||||
menu: { required: "Judul menu wajib diisi" }
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.mb-6, .form-control-validation').append(error);
|
||||
},
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -10,76 +10,10 @@
|
||||
<div class="card-body">
|
||||
<form id="addUpdateDataForm" action="{{ route('tabel.data.update', [$tabel->id, $value_id, 'program_id' => $program->id]) }}" method="POST" >
|
||||
@csrf
|
||||
@method('PUT')
|
||||
@method('PUT')
|
||||
|
||||
<h6 class="mb-3">Informasi {{ $tabel->label }}</h6>
|
||||
@if (!$program)
|
||||
<div class="row">
|
||||
<div class="col-md-3 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-data-program">Program<span class="text-danger">*</span></label>
|
||||
<select name="program_id" class="form-select form-select-sm w-auto" onchange="this.form.submit()">
|
||||
<option value="">Pilih Program</option>
|
||||
@foreach($programList as $prog)
|
||||
<option value="{{ $prog->id }}" {{ request('program_id') == $prog->id ? 'selected' : '' }}>{{ $prog->nama }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<div class="row">
|
||||
@foreach($kolom as $k)
|
||||
<?php
|
||||
$value = $values->where('kolom_id', $k->id)->first();
|
||||
?>
|
||||
<div class="col-md-3 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-data-{{ $k->kolom }}">{{ $k->label }}<span class="text-danger">*</span></label>
|
||||
@if($k->tipe == 'varchar')
|
||||
<input type="text" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" />
|
||||
@elseif($k->tipe == 'text')
|
||||
<textarea class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}">{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}</textarea>
|
||||
@elseif($k->tipe == 'integer')
|
||||
<input type="number" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" step="1" />
|
||||
@elseif($k->tipe == 'float')
|
||||
<input type="number" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" step="any" />
|
||||
@elseif($k->tipe == 'date')
|
||||
<input type="date" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" />
|
||||
@elseif($k->tipe == 'datetime')
|
||||
<input type="datetime-local" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" />
|
||||
@elseif($k->tipe == 'boolean')
|
||||
<select class="form-select tipe-boolean @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" name="{{ $k->kolom }}">
|
||||
<option value="1" {{ (old($k->kolom) ?? ($value['value_'.$k->tipe] ?? null)) == 1 ? 'selected' : '' }}>Ya</option>
|
||||
<option value="0" {{ (old($k->kolom) ?? ($value['value_'.$k->tipe] ?? null)) == 0 ? 'selected' : '' }}>Tidak</option>
|
||||
</select>
|
||||
@elseif($k->tipe == 'foreign_key')
|
||||
<select class="form-select tipe-fk @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" name="{{ $k->kolom }}">
|
||||
@if ($list_relasi->where('kolom_id', $k->id)->first() != null)
|
||||
@foreach($list_relasi->where('kolom_id', $k->id)->first()['options'] as $opsi_relasi)
|
||||
<option value="{{ $opsi_relasi->value }}" {{ old($k->kolom) ?? $value['value_'.$k->tipe] == $opsi_relasi->value ? 'selected' : '' }}>{{ $opsi_relasi->label }}</option>
|
||||
@endforeach
|
||||
@endif
|
||||
</select>
|
||||
@elseif($k->tipe == 'enum')
|
||||
<select class="form-select tipe-fk @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" name="{{ $k->kolom }}">
|
||||
@foreach($k->enum_opsi as $opsi)
|
||||
<option value="{{ $opsi['value'] }}" {{ old($k->kolom) ?? $value['value_'.$k->tipe] == $opsi['value'] ? 'selected' : '' }}>{{ $opsi['label'] }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@else
|
||||
<input type="text" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}"
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" />
|
||||
@endif
|
||||
@error($k->kolom)<div class="error invalid-feedback">{{ $message }}</div>@enderror
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
{!! $tabel->renderHtml('edit', $errors, $list_relasi, $values) !!}
|
||||
|
||||
|
||||
<div class="mt-4 text-end">
|
||||
<a href="{{ route('tabel.data.index', [$tabel->id, 'program_id' => $program->id]) }}" class="btn btn-label-secondary me-2">Kembali</a>
|
||||
<button type="submit" class="btn btn-success data-submit">Simpan Data</button>
|
||||
|
||||
@@ -49,16 +49,15 @@
|
||||
<div class="col-md-auto d-flex gap-2">
|
||||
@if (app()->has('SystemProgram'))
|
||||
@else
|
||||
<div class="col-md-auto">
|
||||
<div class="col-6">
|
||||
<div class="d-flex align-items-center">
|
||||
<label class="me-2 text-nowrap">Program</label>
|
||||
<select name="program_id" class="form-select form-select-sm w-auto" onchange="this.form.submit()">
|
||||
<option value="">Pilih Program</option>
|
||||
<select name="program_id" class="form-select form-select-sm w-auto" onchange="this.form.submit()" id="program_id">
|
||||
<option value="">--- Pilih Program ---</option>
|
||||
@foreach($programList as $prog)
|
||||
<option value="{{ $prog->id }}" {{ request('program_id') == $prog->id ? 'selected' : '' }}>{{ $prog->nama }}</option>
|
||||
<option value="{{ $prog->id }}" {{ request('program_id') == $prog->id ? 'selected' : '' }}>{{ $prog->nama_singkat }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<label class="ms-2 text-nowrap">entries</label>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@@ -66,9 +65,8 @@
|
||||
<input type="text" name="search" class="form-control" placeholder="Cari Nama Tabel..." value="{{ request('search') }}">
|
||||
<button type="submit" class="btn btn-outline-primary"><i class="ti tabler-search"></i></button>
|
||||
</div>
|
||||
<a href="{{ route('tabel.data.create', [$tabel->id, 'program_id' => request('program_id')]) }}" class="btn btn-sm btn-primary add-new"
|
||||
style="display: {{ request('program_id') ? 'flex' : 'none' }};">
|
||||
<i class="ti tabler-plus me-1"></i> Tambah
|
||||
<a href="{{ route('tabel.data.create', [$tabel->id, 'program_id' => request('program_id')]) }}" class="btn btn-sm btn-primary flex-shrink-0 add-new">
|
||||
<i class="icon-xs icon-base ti tabler-plus me-1"></i> Tambah
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
@@ -123,6 +121,8 @@
|
||||
'use strict';
|
||||
|
||||
$(document).ready(function () {
|
||||
$('#program_id').select2();
|
||||
|
||||
$(".delete-record").click(function (e) {
|
||||
e.preventDefault();
|
||||
const id = $(this).data('id');
|
||||
|
||||
@@ -12,63 +12,7 @@
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<h6 class="mb-3">Informasi {{ $tabel->label }}</h6>
|
||||
@if (!$program)
|
||||
<div class="row">
|
||||
<div class="col-md-3 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-data-program">Program<span class="text-danger">*</span></label>
|
||||
<select name="program_id" class="form-select form-select-sm w-auto" onchange="this.form.submit()">
|
||||
<option value="">Pilih Program</option>
|
||||
@foreach($programList as $prog)
|
||||
<option value="{{ $prog->id }}" {{ request('program_id') == $prog->id ? 'selected' : '' }}>{{ $prog->nama }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<div class="row">
|
||||
@foreach($kolom as $k)
|
||||
<?php
|
||||
$value = $values->where('kolom_id', $k->id)->first();
|
||||
?>
|
||||
<div class="col-md-3 mb-4 form-control-validation">
|
||||
<label class="form-label" for="add-data-{{ $k->kolom }}">{{ $k->label }}<span class="text-danger">*</span></label>
|
||||
@if($k->tipe == 'varchar')
|
||||
<input type="text" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" readonly
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" />
|
||||
@elseif($k->tipe == 'text')
|
||||
<textarea class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" readonly
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}">{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}</textarea>
|
||||
@elseif($k->tipe == 'integer')
|
||||
<input type="number" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" readonly
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" step="1" />
|
||||
@elseif($k->tipe == 'float')
|
||||
<input type="number" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" readonly
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" step="any" />
|
||||
@elseif($k->tipe == 'date')
|
||||
<input type="date" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" readonly
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" />
|
||||
@elseif($k->tipe == 'datetime')
|
||||
<input type="datetime-local" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" readonly
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" />
|
||||
@elseif($k->tipe == 'boolean')
|
||||
<input type="text" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" readonly
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ (old($k->kolom) ?? $value['value_'.$k->tipe]) == 1 ? 'Ya' : 'Tidak' }}" />
|
||||
@elseif($k->tipe == 'foreign_key')
|
||||
<input type="text" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" readonly
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ (old($k->kolom) ?? $value['value_relasi_label']) }}" />
|
||||
@elseif($k->tipe == 'enum')
|
||||
<input type="text" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" readonly
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ (old($k->kolom) ?? $value['value_enum_label']) }}" />
|
||||
@else
|
||||
<input type="text" class="form-control @error($k->kolom) is-invalid @enderror" id="add-data-{{ $k->kolom }}" readonly
|
||||
name="{{ $k->kolom }}" placeholder="Cth: {{ $k->label }}" value="{{ old($k->kolom) ?? $value['value_'.$k->tipe] }}" />
|
||||
@endif
|
||||
@error($k->kolom)<div class="error invalid-feedback">{{ $message }}</div>@enderror
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
{!! $tabel->renderHtml('view', $errors, null, $values) !!}
|
||||
|
||||
<div class="mt-4 text-end">
|
||||
<a href="{{ route('tabel.data.index', [$tabel->id, 'program_id' => $program->id]) }}" class="btn btn-label-secondary me-2">Kembali</a>
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
<!doctype html>
|
||||
|
||||
<html
|
||||
lang="en"
|
||||
class=" layout-wide customizer-hide"
|
||||
dir="ltr"
|
||||
data-skin="default"
|
||||
data-bs-theme="light"
|
||||
data-assets-path="../../assets/"
|
||||
data-template="vertical-menu-template">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
|
||||
<meta name="robots" content="noindex, nofollow" />
|
||||
<title>Agomonev | {{ $title ?? 'Auth' }} </title>
|
||||
|
||||
<meta name="description" content="" />
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/x-icon" href="../../assets/img/favicon/favicon.ico" />
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Public+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700&display=swap"
|
||||
rel="stylesheet" />
|
||||
|
||||
<link rel="stylesheet" href="{{ asset('assets/vendor/fonts/iconify-icons.css') }}" />
|
||||
|
||||
<script src="{{ asset('assets/vendor/libs/@algolia/autocomplete-js.js') }}"></script>
|
||||
|
||||
<!-- Core CSS -->
|
||||
<!-- build:css assets/vendor/css/theme.css -->
|
||||
|
||||
<link rel="stylesheet" href="{{ asset('assets/vendor/libs/node-waves/node-waves.css') }}" />
|
||||
|
||||
<link rel="stylesheet" href="{{ asset('assets/vendor/libs/pickr/pickr-themes.css') }}" />
|
||||
|
||||
<link rel="stylesheet" href="{{ asset('assets/vendor/css/core.css') }}" />
|
||||
<link rel="stylesheet" href="{{ asset('assets/css/demo.css') }}" />
|
||||
|
||||
<!-- Vendors CSS -->
|
||||
|
||||
<link rel="stylesheet" href="{{ asset('assets/vendor/libs/perfect-scrollbar/perfect-scrollbar.css') }}" />
|
||||
|
||||
<!-- endbuild -->
|
||||
|
||||
<!-- Vendor -->
|
||||
<link rel="stylesheet" href="{{ asset('assets/vendor/libs/@form-validation/form-validation.css') }}" />
|
||||
|
||||
<!-- Page CSS -->
|
||||
<!-- Page -->
|
||||
<link rel="stylesheet" href="{{ asset('assets/vendor/css/pages/page-auth.css') }}" />
|
||||
|
||||
<!-- Helpers -->
|
||||
<script src="{{ asset('assets/vendor/js/helpers.js') }}"></script>
|
||||
<!--! Template customizer & Theme config files MUST be included after core stylesheets and helpers.js in the <head> section -->
|
||||
|
||||
<!--? Template customizer: To hide customizer set displayCustomizer value false in config.js. -->
|
||||
<script src="{{ asset('assets/vendor/js/template-customizer.js') }}"></script>
|
||||
|
||||
<!--? Config: Mandatory theme config file contain global vars & default theme options, Set your preferred theme option in this file. -->
|
||||
|
||||
<script src="{{ asset('assets/js/config.js') }}"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Content -->
|
||||
|
||||
<div class="container-xxl">
|
||||
<div class="authentication-wrapper authentication-basic container-p-y">
|
||||
<div class="authentication-inner py-6">
|
||||
<!-- Register Card -->
|
||||
@yield('content')
|
||||
<!-- Register Card -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- / Content -->
|
||||
|
||||
<!-- Core JS -->
|
||||
<!-- build:js assets/vendor/js/theme.js -->
|
||||
|
||||
<script src="{{ asset('assets/vendor/libs/jquery/jquery.js') }}"></script>
|
||||
|
||||
<script src="{{ asset('assets/vendor/libs/popper/popper.js') }}"></script>
|
||||
<script src="{{ asset('assets/vendor/js/bootstrap.js') }}"></script>
|
||||
<script src="{{ asset('assets/vendor/libs/node-waves/node-waves.js') }}"></script>
|
||||
|
||||
<script src="{{ asset('assets/vendor/libs/pickr/pickr.js') }}"></script>
|
||||
|
||||
<script src="{{ asset('assets/vendor/libs/perfect-scrollbar/perfect-scrollbar.js') }}"></script>
|
||||
|
||||
<script src="{{ asset('assets/vendor/libs/hammer/hammer.js') }}"></script>
|
||||
|
||||
<script src="{{ asset('assets/vendor/libs/i18n/i18n.js') }}"></script>
|
||||
|
||||
<script src="{{ asset('assets/vendor/js/menu.js') }}"></script>
|
||||
|
||||
<!-- endbuild -->
|
||||
|
||||
<!-- Vendors JS -->
|
||||
<script src="{{ asset('assets/vendor/libs/@form-validation/popular.js') }}"></script>
|
||||
<script src="{{ asset('assets/vendor/libs/@form-validation/bootstrap5.js') }}"></script>
|
||||
<script src="{{ asset('assets/vendor/libs/@form-validation/auto-focus.js') }}"></script>
|
||||
|
||||
<!-- Main JS -->
|
||||
|
||||
<script src="{{ asset('assets/js/main.js') }}"></script>
|
||||
|
||||
<!-- Page JS -->
|
||||
<script src="{{ asset('assets/js/pages-auth.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,89 +0,0 @@
|
||||
@extends('auth.layout')
|
||||
@section('content')
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<!-- Logo -->
|
||||
<div class="app-brand justify-content-center mb-6">
|
||||
<a href="{{ route('dashboard.produktivitas') }}" class="app-brand-link">
|
||||
<span class="app-brand-logo demo">
|
||||
<span class="text-primary">
|
||||
<svg width="32" height="24" viewBox="0 0 32 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Daun Bagian Kiri -->
|
||||
<path opacity="0.3" d="M16 2.5C16 2.5 5 6.5 5 15.5C5 20.5 11 23.5 16 23.5V2.5Z" fill="currentColor" />
|
||||
<!-- Daun Bagian Kanan -->
|
||||
<path opacity="0.6" d="M16 2.5C16 2.5 27 6.5 27 15.5C27 20.5 21 23.5 16 23.5V2.5Z" fill="currentColor" />
|
||||
<!-- Grafik Pertumbuhan (Monev) -->
|
||||
<path d="M2 19L10 11L15 15L27 4" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" />
|
||||
<!-- Titik Target/Pencapaian -->
|
||||
<circle cx="27" cy="4" r="2.5" fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span class="app-brand-text demo menu-text fw-bold ms-3" style="text-transform: capitalize;">AgroMonev</span>
|
||||
</a>
|
||||
</div>
|
||||
<!-- /Logo -->
|
||||
<h4 class="mb-1">Selamat datang di AgroMonev!</h4>
|
||||
<p class="mb-6">Silakan masuk ke akun Anda</p>
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul class="mb-0">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
<form id="formAuthentication" class="mb-4" action="{{ route('auth.authenticate') }}" method="POST">
|
||||
@csrf
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label for="email" class="form-label">Email atau Username</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="email"
|
||||
name="email_username"
|
||||
placeholder="Masukkan email atau username Anda"
|
||||
autofocus />
|
||||
</div>
|
||||
<div class="mb-6 form-password-toggle form-control-validation">
|
||||
<label class="form-label" for="password">Password</label>
|
||||
<div class="input-group input-group-merge">
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
class="form-control"
|
||||
name="password"
|
||||
placeholder="············"
|
||||
aria-describedby="password" />
|
||||
<span class="input-group-text cursor-pointer"><i class="icon-base ti tabler-eye-off"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-8">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="form-check mb-0 ms-2">
|
||||
<input class="form-check-input" type="checkbox" id="remember-me" />
|
||||
<label class="form-check-label" for="remember-me"> Remember Me </label>
|
||||
</div>
|
||||
<a href="auth-forgot-password-basic.html">
|
||||
<p class="mb-0">Lupa Password?</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-6">
|
||||
<button class="btn btn-primary d-grid w-100" type="submit">Login</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p class="text-center">
|
||||
<span>Anda belum terdaftar?</span>
|
||||
<a href="{{ route('register') }}">
|
||||
<span>Buat akun baru</span>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@@ -10,6 +10,10 @@
|
||||
<label class="form-label" for="add-user-fullname">Nama Lengkap</label>
|
||||
<input type="text" class="form-control" id="add-user-fullname" placeholder="John Doe" name="name" required />
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="form-label" for="add-user-username">Nama akun</label>
|
||||
<input type="text" class="form-control" id="add-user-username" placeholder="john" name="username" required />
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="form-label" for="add-user-email">Email</label>
|
||||
<input type="email" id="add-user-email" class="form-control" placeholder="john.doe@example.com" name="email" required />
|
||||
|
||||
@@ -361,7 +361,7 @@
|
||||
<div class="dropdown-divider my-1 mx-n2"></div>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ route('userProfile.index') }}">
|
||||
<a class="dropdown-item" href="pages-profile-user.html">
|
||||
<i class="icon-base ti tabler-user me-3 icon-md"></i
|
||||
><span class="align-middle">Profil Saya</span>
|
||||
</a>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<aside id="layout-menu" class="layout-menu menu-vertical menu">
|
||||
<div class="app-brand demo ">
|
||||
<a href="{{ route('dashboard.produktivitas') }}" class="app-brand-link">
|
||||
<a href="{{ route('dashboard.summary') }}" class="app-brand-link">
|
||||
<span class="app-brand-logo demo">
|
||||
<span>
|
||||
<svg width="32" height="24" viewBox="0 0 32 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
@@ -58,8 +58,28 @@
|
||||
</a>
|
||||
<ul class="menu-sub">
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('dashboard.produktivitas') }}" class="menu-link">
|
||||
<div data-i18n="Produktivitas">Produktivitas</div>
|
||||
<a href="{{ route('dashboard.summary') }}" class="menu-link">
|
||||
<div data-i18n="Summary">Summary</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('dashboard.resiliensi') }}" class="menu-link">
|
||||
<div data-i18n="Reseliensi">Reseliensi</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('dashboard.hilirisasi') }}" class="menu-link">
|
||||
<div data-i18n="Hilirisasi">Hilirisasi</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('dashboard.konektivitas') }}" class="menu-link">
|
||||
<div data-i18n="Konektivitas">Konektivitas</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('dashboard.akselerasi') }}" class="menu-link">
|
||||
<div data-i18n="Akselerasi">Akselerasi</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -109,7 +129,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="menu-item {{ request()->routeIs(['petani-cpm.*','tabel.data.*']) ? 'active open' : '' }}">
|
||||
<li class="menu-item {{ request()->routeIs(['petani-cpm.*', 'lahan-cpcl.*', 'tabel.data.*']) ? 'active open' : '' }}">
|
||||
<a href="javascript:void(0);" class="menu-link menu-toggle">
|
||||
<i class="menu-icon icon-base ti tabler-folder-root"></i>
|
||||
<div data-i18n="Basis Data Ekosistem">Basis Data Ekosistem</div>
|
||||
@@ -117,7 +137,14 @@
|
||||
<ul class="menu-sub">
|
||||
<li class="menu-item {{ request()->routeIs('petani-cpm.*') ? 'active' : '' }}">
|
||||
<a href="{{ route('petani-cpm.index') }}" class="menu-link">
|
||||
<div data-i18n="Petani">Petani</div>
|
||||
<div data-i18n="Petani CPM">Petani CPM</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="menu-sub">
|
||||
<li class="menu-item {{ request()->routeIs('lahan-cpcl.*') ? 'active' : '' }}">
|
||||
<a href="{{ route('lahan-cpcl.index') }}" class="menu-link">
|
||||
<div data-i18n="Lahan CPCL">Lahan CPCL</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -151,11 +178,18 @@
|
||||
</li>
|
||||
</ul>
|
||||
</li> -->
|
||||
<li class="menu-item">
|
||||
<li class="menu-item {{ request()->routeIs(['realisasi.*', 'kelompok-belajar-tani.*', 'workshop.*']) ? 'active open' : '' }}">
|
||||
<a href="javascript:void(0);" class="menu-link menu-toggle">
|
||||
<i class="menu-icon icon-base ti tabler-webhook"></i>
|
||||
<div data-i18n="Program & Komunitas">Program & Komunitas</div>
|
||||
</a>
|
||||
<ul class="menu-sub">
|
||||
<li class="menu-item {{ request()->routeIs('realisasi.*') ? 'active' : '' }}">
|
||||
<a href="{{ route('realisasi.index') }}" class="menu-link">
|
||||
<div data-i18n="Capaian Program">Capaian Program</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="menu-sub">
|
||||
<li class="menu-item {{ request()->routeIs('kelompok-belajar-tani.*') ? 'active' : '' }}">
|
||||
<a href="{{ route('kelompok-belajar-tani.index') }}" class="menu-link">
|
||||
@@ -164,19 +198,19 @@
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="menu-sub">
|
||||
<li class="menu-item">
|
||||
<li class="menu-item {{ request()->routeIs('workshop.*') ? 'active' : '' }}">
|
||||
<a href="{{ route('workshop.index') }}" class="menu-link">
|
||||
<div data-i18n="Workshop & Lokakarya">Workshop & Lokakarya</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="menu-sub">
|
||||
<!-- <ul class="menu-sub">
|
||||
<li class="menu-item">
|
||||
<a href="#" class="menu-link">
|
||||
<div data-i18n="Desiminasi & Replikasi">Desiminasi & Replikasi</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</ul> -->
|
||||
</li>
|
||||
<!-- Master Data -->
|
||||
<li class="menu-header small">
|
||||
@@ -189,26 +223,26 @@
|
||||
<div data-i18n="Wilayah">Wilayah</div>
|
||||
</a>
|
||||
<ul class="menu-sub">
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('provinsi.index') }}" class="menu-link">
|
||||
<div data-i18n="Provinsi">provinsi</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('kabupatenkota.index') }}" class="menu-link">
|
||||
<div data-i18n="Kabupaten Kota">Kabupaten Kota</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('kecamatan.index') }}" class="menu-link">
|
||||
<div data-i18n="Kecamatan">Kecamatan</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('desakelurahan.index') }}" class="menu-link">
|
||||
<div data-i18n="Desa Kelurahan">Desa Kelurahan</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('provinsi.index') }}" class="menu-link">
|
||||
<div data-i18n="Provinsi">provinsi</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('kabupatenkota.index') }}" class="menu-link">
|
||||
<div data-i18n="Kabupaten Kota">Kabupaten Kota</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('kecamatan.index') }}" class="menu-link">
|
||||
<div data-i18n="Kecamatan">Kecamatan</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('desakelurahan.index') }}" class="menu-link">
|
||||
<div data-i18n="Desa Kelurahan">Desa Kelurahan</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
@@ -224,10 +258,27 @@
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('komoditas.index') }}" class="menu-link">
|
||||
<a href="javascript:void(0);" class="menu-link menu-toggle">
|
||||
<i class="menu-icon icon-base ti tabler-plant"></i>
|
||||
<div data-i18n="Komoditas">Komoditas</div>
|
||||
<div data-i18n="Tanaman">Tanaman</div>
|
||||
</a>
|
||||
<ul class="menu-sub">
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('komoditas.index') }}" class="menu-link">
|
||||
<div data-i18n="Komoditas">Komoditas</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('jenis-komoditas.index') }}" class="menu-link">
|
||||
<div data-i18n="Jenis Komoditas">Jenis Komoditas</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ route('varietas.index') }}" class="menu-link">
|
||||
<div data-i18n="Varietas">Varietas</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<!-- Konfigurasi -->
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
@section('content')
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="mb-6">
|
||||
<x-wilayah-dashboard />
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-header border-bottom">
|
||||
<h5 class="card-title mb-0">Data Desa/Kelurahan</h5>
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasAddJenisKomoditas" aria-labelledby="offcanvasAddJenisKomoditasLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasAddJenisKomoditasLabel" class="offcanvas-title">Tambah Jenis Komoditas</h5>
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="add-new-jeniskomoditas pt-0" id="addNewJenisKomoditasForm" action="{{ route('jenis-komoditas.store') }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-jenis-komoditas-komoditas">
|
||||
Komoditas <span class="text-danger">*</span>
|
||||
</label>
|
||||
<select id="add-jenis-komoditas-komoditas" name="komoditas_id" class="select2 form-select" data-placeholder="Pilih Komoditas">
|
||||
<option value=""></option>
|
||||
@foreach($komoditas as $item)
|
||||
<option value="{{ $item->id }}">{{ $item->nama }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-jenis-komoditas-name">
|
||||
Nama Jenis Komoditas <span class="text-danger">*</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="add-jenis-komoditas-name"
|
||||
placeholder="Contoh: Kopi Arabika"
|
||||
name="nama"
|
||||
autocomplete="off" />
|
||||
</div>
|
||||
|
||||
<div class="mt-8">
|
||||
<button type="submit" class="btn btn-primary me-3 data-submit">Submit</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,45 @@
|
||||
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasEditJenisKomoditas" aria-labelledby="offcanvasEditJenisKomoditasLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasEditJenisKomoditasLabel" class="offcanvas-title">Edit Jenis Komoditas</h5>
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="edit-jeniskomoditas pt-0" id="editJenisKomoditasForm" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<input type="hidden" id="edit-jenis-komoditas-id" name="id">
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="edit-jenis-komoditas-komoditas">
|
||||
Komoditas <span class="text-danger">*</span>
|
||||
</label>
|
||||
<select id="edit-jenis-komoditas-komoditas" name="komoditas_id" class="select2 form-select" data-placeholder="Pilih Komoditas">
|
||||
<option value=""></option>
|
||||
@foreach($komoditas as $item)
|
||||
<option value="{{ $item->id }}">{{ $item->nama }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="edit-jenis-komoditas-name">
|
||||
Nama Jenis Komoditas <span class="text-danger">*</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="edit-jenis-komoditas-name"
|
||||
placeholder="Contoh: Kopi Arabika"
|
||||
name="nama"
|
||||
autocomplete="off" />
|
||||
</div>
|
||||
|
||||
<div class="mt-8">
|
||||
<button type="submit" class="btn btn-primary me-3 data-submit">Update</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,485 @@
|
||||
@extends('layout.main')
|
||||
|
||||
@section('content')
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header border-bottom">
|
||||
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center gap-3">
|
||||
<div>
|
||||
<h5 class="card-title mb-0">Jenis Komoditas</h5>
|
||||
<small class="text-muted">Kelola data jenis komoditas</small>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
data-bs-toggle="offcanvas"
|
||||
data-bs-target="#offcanvasAddJenisKomoditas">
|
||||
<i class="ti tabler-plus me-1"></i>
|
||||
Tambah Jenis Komoditas
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body border-bottom">
|
||||
<form
|
||||
method="GET"
|
||||
action="{{ route('jenis-komoditas.index') }}"
|
||||
class="row g-3 align-items-center justify-content-between">
|
||||
|
||||
<div class="col-md-auto">
|
||||
<div class="d-flex align-items-center">
|
||||
<label class="me-2 text-nowrap">Show</label>
|
||||
<select name="per_page" class="form-select form-select-sm w-auto" onchange="this.form.submit()">
|
||||
@foreach([10, 25, 50, 100] as $limit)
|
||||
<option value="{{ $limit }}" {{ (int) request('per_page', 10) === $limit ? 'selected' : '' }}>
|
||||
{{ $limit }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<label class="ms-2 text-nowrap">entries</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-auto">
|
||||
<div class="input-group input-group-sm">
|
||||
<input
|
||||
type="text"
|
||||
name="search"
|
||||
class="form-control"
|
||||
placeholder="Cari jenis komoditas..."
|
||||
value="{{ request('search') }}">
|
||||
|
||||
@if(request('search'))
|
||||
<a href="{{ route('jenis-komoditas.index', ['per_page' => request('per_page', 10)]) }}"
|
||||
class="btn btn-outline-secondary">
|
||||
<i class="ti tabler-x"></i>
|
||||
</a>
|
||||
@endif
|
||||
|
||||
<button type="submit" class="btn btn-outline-primary">
|
||||
<i class="ti tabler-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive text-nowrap">
|
||||
<table class="table table-hover">
|
||||
<thead class="border-top">
|
||||
<tr>
|
||||
<th style="width: 70px;">No</th>
|
||||
<th>Nama Jenis Komoditas</th>
|
||||
<th>Komoditas</th>
|
||||
<th class="text-center" style="width: 160px;">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@forelse($jenisKomoditas as $index => $jenis)
|
||||
@php
|
||||
$komoditasNama = $jenis->komoditas->nama ?? '-';
|
||||
$words = preg_split('/\s+/', trim($komoditasNama));
|
||||
$initials = collect($words)
|
||||
->filter()
|
||||
->map(fn($word) => strtoupper(substr($word, 0, 1)))
|
||||
->take(2)
|
||||
->implode('');
|
||||
|
||||
$states = ['success', 'danger', 'warning', 'info', 'primary', 'secondary'];
|
||||
$state = $states[$jenis->id % count($states)];
|
||||
@endphp
|
||||
|
||||
<tr>
|
||||
<td>{{ $jenisKomoditas->firstItem() + $index }}</td>
|
||||
|
||||
<td>
|
||||
<div class="d-flex justify-content-start align-items-center">
|
||||
<div class="avatar-wrapper me-3">
|
||||
<div class="avatar avatar-sm">
|
||||
<span class="avatar-initial rounded-circle bg-label-{{ $state }}">
|
||||
{{ $initials ?: 'JK' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column">
|
||||
<span class="fw-medium text-heading">{{ $jenis->nama }}</span>
|
||||
<small class="text-muted">ID: {{ $jenis->id }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="badge bg-label-secondary">
|
||||
{{ $komoditasNama }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<div class="d-flex justify-content-center align-items-center">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-icon btn-text-secondary rounded-pill view-record"
|
||||
data-id="{{ $jenis->id }}"
|
||||
title="Lihat">
|
||||
<i class="ti tabler-eye ti-md"></i>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-icon btn-text-secondary rounded-pill edit-record"
|
||||
data-id="{{ $jenis->id }}"
|
||||
title="Edit">
|
||||
<i class="ti tabler-edit ti-md"></i>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-icon btn-text-secondary rounded-pill delete-record"
|
||||
data-id="{{ $jenis->id }}"
|
||||
data-nama="{{ $jenis->nama }}"
|
||||
title="Hapus">
|
||||
<i class="ti tabler-trash ti-md"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="5" class="text-center py-5">
|
||||
<div class="d-flex flex-column align-items-center">
|
||||
<i class="ti tabler-database-off ti-lg mb-2 text-muted"></i>
|
||||
<span class="text-muted">Tidak ada data ditemukan.</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@if($jenisKomoditas->hasPages())
|
||||
<div class="card-footer d-flex justify-content-center justify-content-md-end border-top">
|
||||
{{ $jenisKomoditas->appends(request()->query())->links('pagination::bootstrap-5') }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@include('master.jeniskomoditas.add')
|
||||
@include('master.jeniskomoditas.edit')
|
||||
@include('master.jeniskomoditas.view')
|
||||
@endsection
|
||||
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
$(function () {
|
||||
const csrfToken = "{{ csrf_token() }}";
|
||||
const baseUrl = "{{ url('jenis-komoditas') }}";
|
||||
|
||||
const offcanvasAdd = new bootstrap.Offcanvas(document.getElementById('offcanvasAddJenisKomoditas'));
|
||||
const offcanvasEdit = new bootstrap.Offcanvas(document.getElementById('offcanvasEditJenisKomoditas'));
|
||||
const offcanvasView = new bootstrap.Offcanvas(document.getElementById('offcanvasViewJenisKomoditas'));
|
||||
|
||||
$.ajaxSetup({
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': csrfToken
|
||||
}
|
||||
});
|
||||
|
||||
$('.select2').each(function () {
|
||||
const $this = $(this);
|
||||
|
||||
$this.wrap('<div class="position-relative"></div>').select2({
|
||||
dropdownParent: $this.parent(),
|
||||
placeholder: $this.data('placeholder') || 'Pilih data',
|
||||
allowClear: true,
|
||||
width: '100%'
|
||||
});
|
||||
});
|
||||
|
||||
$.validator.setDefaults({
|
||||
errorElement: 'div',
|
||||
errorClass: 'invalid-feedback',
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
},
|
||||
errorPlacement: function (error, element) {
|
||||
if (element.hasClass('select2-hidden-accessible')) {
|
||||
error.insertAfter(element.next('.select2-container'));
|
||||
} else {
|
||||
error.appendTo(element.closest('.form-control-validation'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('.select2').on('change', function () {
|
||||
const $form = $(this).closest('form');
|
||||
|
||||
if ($form.data('validator')) {
|
||||
$(this).valid();
|
||||
}
|
||||
});
|
||||
|
||||
function showSuccess(title = 'Berhasil!', text = 'Data berhasil diproses') {
|
||||
return Swal.fire({
|
||||
icon: 'success',
|
||||
title,
|
||||
text,
|
||||
showConfirmButton: false,
|
||||
timer: 1500,
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-primary'
|
||||
},
|
||||
buttonsStyling: false
|
||||
});
|
||||
}
|
||||
|
||||
function showError(xhr, fallback = 'Terjadi kesalahan sistem.') {
|
||||
let message = fallback;
|
||||
|
||||
if (xhr.responseJSON?.message) {
|
||||
message = xhr.responseJSON.message;
|
||||
}
|
||||
|
||||
if (xhr.responseJSON?.errors) {
|
||||
message = Object.values(xhr.responseJSON.errors).flat().join('<br>');
|
||||
}
|
||||
|
||||
return Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Gagal!',
|
||||
html: message,
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-primary'
|
||||
},
|
||||
buttonsStyling: false
|
||||
});
|
||||
}
|
||||
|
||||
function resetForm($form) {
|
||||
if (!$form.length) return;
|
||||
|
||||
$form[0].reset();
|
||||
|
||||
if ($form.data('validator')) {
|
||||
$form.validate().resetForm();
|
||||
}
|
||||
|
||||
$form.find('.is-invalid').removeClass('is-invalid');
|
||||
|
||||
$form.find('.select2').each(function () {
|
||||
$(this).val('').trigger('change.select2');
|
||||
});
|
||||
}
|
||||
|
||||
function setButtonLoading($button, isLoading, text = 'Menyimpan...') {
|
||||
if (isLoading) {
|
||||
$button
|
||||
.data('original-text', $button.html())
|
||||
.prop('disabled', true)
|
||||
.html(`<span class="spinner-border spinner-border-sm me-1"></span>${text}`);
|
||||
} else {
|
||||
$button
|
||||
.prop('disabled', false)
|
||||
.html($button.data('original-text'));
|
||||
}
|
||||
}
|
||||
|
||||
$('#addNewJenisKomoditasForm').validate({
|
||||
rules: {
|
||||
komoditas_id: {
|
||||
required: true
|
||||
},
|
||||
nama: {
|
||||
required: true,
|
||||
maxlength: 255
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
komoditas_id: {
|
||||
required: 'Komoditas wajib dipilih'
|
||||
},
|
||||
nama: {
|
||||
required: 'Nama jenis komoditas wajib diisi',
|
||||
maxlength: 'Nama maksimal 255 karakter'
|
||||
}
|
||||
},
|
||||
submitHandler: function (form, event) {
|
||||
event.preventDefault();
|
||||
|
||||
const $form = $(form);
|
||||
const $button = $form.find('button[type="submit"]');
|
||||
|
||||
setButtonLoading($button, true);
|
||||
|
||||
$.ajax({
|
||||
url: $form.attr('action'),
|
||||
type: 'POST',
|
||||
data: $form.serialize(),
|
||||
success: function (res) {
|
||||
offcanvasAdd.hide();
|
||||
|
||||
showSuccess(
|
||||
'Berhasil!',
|
||||
res.message || 'Data jenis komoditas berhasil disimpan'
|
||||
).then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
showError(xhr, 'Gagal menyimpan data jenis komoditas');
|
||||
},
|
||||
complete: function () {
|
||||
setButtonLoading($button, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('#offcanvasAddJenisKomoditas').on('hidden.bs.offcanvas', function () {
|
||||
resetForm($('#addNewJenisKomoditasForm'));
|
||||
});
|
||||
|
||||
$(document).on('click', '.edit-record', function () {
|
||||
const id = $(this).data('id');
|
||||
const $form = $('#editJenisKomoditasForm');
|
||||
|
||||
resetForm($form);
|
||||
|
||||
$.ajax({
|
||||
url: `${baseUrl}/${id}`,
|
||||
type: 'GET',
|
||||
success: function (res) {
|
||||
const data = res.data || res;
|
||||
|
||||
$('#edit-jenis-komoditas-id').val(data.id);
|
||||
$('#edit-jenis-komoditas-komoditas').val(data.komoditas_id).trigger('change');
|
||||
$('#edit-jenis-komoditas-name').val(data.nama);
|
||||
|
||||
offcanvasEdit.show();
|
||||
},
|
||||
error: function (xhr) {
|
||||
showError(xhr, 'Terjadi kesalahan saat mengambil data edit');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#editJenisKomoditasForm').validate({
|
||||
rules: {
|
||||
komoditas_id: {
|
||||
required: true
|
||||
},
|
||||
nama: {
|
||||
required: true,
|
||||
maxlength: 255
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
komoditas_id: {
|
||||
required: 'Komoditas wajib dipilih'
|
||||
},
|
||||
nama: {
|
||||
required: 'Nama jenis komoditas wajib diisi',
|
||||
maxlength: 'Nama maksimal 255 karakter'
|
||||
}
|
||||
},
|
||||
submitHandler: function (form, event) {
|
||||
event.preventDefault();
|
||||
|
||||
const $form = $(form);
|
||||
const id = $('#edit-jenis-komoditas-id').val();
|
||||
const $button = $form.find('button[type="submit"]');
|
||||
|
||||
setButtonLoading($button, true, 'Mengupdate...');
|
||||
|
||||
$.ajax({
|
||||
url: `${baseUrl}/${id}`,
|
||||
type: 'POST',
|
||||
data: $form.serialize(),
|
||||
success: function (res) {
|
||||
offcanvasEdit.hide();
|
||||
|
||||
showSuccess(
|
||||
'Updated!',
|
||||
res.message || 'Data jenis komoditas berhasil diperbarui'
|
||||
).then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
showError(xhr, 'Gagal mengupdate data jenis komoditas');
|
||||
},
|
||||
complete: function () {
|
||||
setButtonLoading($button, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('#offcanvasEditJenisKomoditas').on('hidden.bs.offcanvas', function () {
|
||||
resetForm($('#editJenisKomoditasForm'));
|
||||
});
|
||||
|
||||
$(document).on('click', '.view-record', function () {
|
||||
const id = $(this).data('id');
|
||||
|
||||
$.ajax({
|
||||
url: `${baseUrl}/${id}`,
|
||||
type: 'GET',
|
||||
success: function (res) {
|
||||
const data = res.data || res;
|
||||
|
||||
$('#view-jenis-komoditas-komoditas').val(data.komoditas?.nama || data.nama_komoditas || '-');
|
||||
$('#view-jenis-komoditas-name').val(data.nama || '-');
|
||||
|
||||
offcanvasView.show();
|
||||
},
|
||||
error: function (xhr) {
|
||||
showError(xhr, 'Terjadi kesalahan saat mengambil detail data');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '.delete-record', function () {
|
||||
const id = $(this).data('id');
|
||||
const nama = $(this).data('nama') || 'data ini';
|
||||
|
||||
Swal.fire({
|
||||
title: 'Apakah Anda yakin?',
|
||||
text: `Jenis Komoditas "${nama}" akan dihapus secara permanen.`,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Ya, Hapus!',
|
||||
cancelButtonText: 'Batal',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-primary me-3',
|
||||
cancelButton: 'btn btn-label-secondary'
|
||||
},
|
||||
buttonsStyling: false
|
||||
}).then(function (result) {
|
||||
if (!result.isConfirmed) return;
|
||||
|
||||
$.ajax({
|
||||
url: `${baseUrl}/${id}`,
|
||||
type: 'DELETE',
|
||||
success: function (res) {
|
||||
showSuccess(
|
||||
'Terhapus!',
|
||||
res.message || 'Data jenis komoditas berhasil dihapus'
|
||||
).then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
showError(xhr, 'Gagal menghapus data jenis komoditas');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,24 @@
|
||||
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasViewJenisKomoditas" aria-labelledby="offcanvasViewJenisKomoditasLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasViewJenisKomoditasLabel" class="offcanvas-title">Detail Jenis Komoditas</h5>
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<div class="mb-6">
|
||||
<label class="form-label">Komoditas</label>
|
||||
<input type="text" class="form-control" id="view-jenis-komoditas-komoditas" readonly>
|
||||
</div>
|
||||
|
||||
<div class="mb-6">
|
||||
<label class="form-label">Nama Jenis Komoditas</label>
|
||||
<input type="text" class="form-control" id="view-jenis-komoditas-name" readonly>
|
||||
</div>
|
||||
|
||||
<div class="mt-8">
|
||||
<button type="button" class="btn btn-label-secondary" data-bs-dismiss="offcanvas">
|
||||
Tutup
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
@section('content')
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="mb-6">
|
||||
<x-wilayah-dashboard />
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-body border-bottom">
|
||||
<form method="GET" action="{{ route('kabupatenkota.index') }}" class="d-flex justify-content-between align-items-center row gap-3 gap-md-0">
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
@section('content')
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="mb-6">
|
||||
<x-wilayah-dashboard />
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-header border-bottom">
|
||||
<h5 class="card-title mb-0">Data Kecamatan</h5>
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
@section('content')
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="mb-6">
|
||||
<x-wilayah-dashboard />
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-body border-bottom">
|
||||
<form method="GET" action="{{ route('provinsi.index') }}" class="d-flex justify-content-between align-items-center row gap-3 gap-md-0">
|
||||
@@ -35,6 +38,7 @@
|
||||
<th>No</th>
|
||||
<th>Kode Provinsi</th>
|
||||
<th>Nama Provinsi</th>
|
||||
<th class="text-center">Status Kelengkapan</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -62,6 +66,19 @@
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="text-center">
|
||||
@if($prov->kabupaten_kota_count > 0)
|
||||
<span class="badge bg-label-success d-inline-flex align-items-center" style="border-radius: 20px; padding: 6px 10px;">
|
||||
<i class="ti tabler-check me-1" style="font-size: 16px;"></i> Aktif (Ada Kabupaten)
|
||||
</span>
|
||||
@else
|
||||
<span class="badge bg-label-warning d-inline-flex align-items-center" style="border-radius: 20px; padding: 6px 10px;">
|
||||
<i class="ti tabler-alert-circle me-1" style="font-size: 16px;"></i> Belum Ada Wilayah
|
||||
</span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-secondary rounded-pill edit-record" data-id="{{ $prov->id }}"><i class="ti tabler-edit ti-md"></i></a>
|
||||
@@ -72,7 +89,7 @@
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="4" class="text-center py-4">Tidak ada data ditemukan.</td>
|
||||
<td colspan="5" class="text-center py-4">Tidak ada data ditemukan.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasAddVarietas" aria-labelledby="offcanvasAddVarietasLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasAddVarietasLabel" class="offcanvas-title">Tambah Varietas</h5>
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="add-new-varietas pt-0" id="addNewVarietasForm" action="{{ route('varietas.store') }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-varietas-komoditas">
|
||||
Komoditas <span class="text-danger">*</span>
|
||||
</label>
|
||||
<select id="add-varietas-komoditas" name="komoditas_id" class="select2 form-select" data-placeholder="Pilih Komoditas">
|
||||
<option value=""></option>
|
||||
@foreach($komoditas as $item)
|
||||
<option value="{{ $item->id }}">{{ $item->nama }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-varietas-jenis-komoditas">
|
||||
Jenis Komoditas <span class="text-danger">*</span>
|
||||
</label>
|
||||
<select id="add-varietas-jenis-komoditas" name="jenis_komoditas_id" class="select2 form-select" data-placeholder="Pilih Jenis Komoditas">
|
||||
<option value=""></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-varietas-name">
|
||||
Nama Varietas <span class="text-danger">*</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="add-varietas-name"
|
||||
placeholder="Contoh: Ciherang"
|
||||
name="nama"
|
||||
autocomplete="off">
|
||||
</div>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-varietas-description">Deskripsi</label>
|
||||
<textarea
|
||||
class="form-control"
|
||||
id="add-varietas-description"
|
||||
placeholder="Opsional"
|
||||
name="deskripsi"
|
||||
rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="mt-8">
|
||||
<button type="submit" class="btn btn-primary me-3 data-submit">Submit</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,64 @@
|
||||
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasEditVarietas" aria-labelledby="offcanvasEditVarietasLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasEditVarietasLabel" class="offcanvas-title">Edit Varietas</h5>
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="edit-varietas pt-0" id="editVarietasForm" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<input type="hidden" id="edit-varietas-id" name="id">
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="edit-varietas-komoditas">
|
||||
Komoditas <span class="text-danger">*</span>
|
||||
</label>
|
||||
<select id="edit-varietas-komoditas" name="komoditas_id" class="select2 form-select" data-placeholder="Pilih Komoditas">
|
||||
<option value=""></option>
|
||||
@foreach($komoditas as $item)
|
||||
<option value="{{ $item->id }}">{{ $item->nama }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="edit-varietas-jenis-komoditas">
|
||||
Jenis Komoditas <span class="text-danger">*</span>
|
||||
</label>
|
||||
<select id="edit-varietas-jenis-komoditas" name="jenis_komoditas_id" class="select2 form-select" data-placeholder="Pilih Jenis Komoditas">
|
||||
<option value=""></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="edit-varietas-name">
|
||||
Nama Varietas <span class="text-danger">*</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="edit-varietas-name"
|
||||
placeholder="Contoh: Ciherang"
|
||||
name="nama"
|
||||
autocomplete="off">
|
||||
</div>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="edit-varietas-description">Deskripsi</label>
|
||||
<textarea
|
||||
class="form-control"
|
||||
id="edit-varietas-description"
|
||||
placeholder="Opsional"
|
||||
name="deskripsi"
|
||||
rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="mt-8">
|
||||
<button type="submit" class="btn btn-primary me-3 data-submit">Update</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,547 @@
|
||||
@extends('layout.main')
|
||||
|
||||
@section('content')
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="card">
|
||||
<div class="card-body border-bottom">
|
||||
<form method="GET" action="{{ route('varietas.index') }}" class="d-flex justify-content-between align-items-center row gap-3 gap-md-0">
|
||||
<div class="col-md-auto">
|
||||
<div class="d-flex align-items-center">
|
||||
<label class="me-2 text-nowrap">Show</label>
|
||||
<select name="per_page" class="form-select form-select-sm w-auto" onchange="this.form.submit()">
|
||||
<option value="10" {{ request('per_page') == 10 ? 'selected' : '' }}>10</option>
|
||||
<option value="25" {{ request('per_page') == 25 ? 'selected' : '' }}>25</option>
|
||||
<option value="50" {{ request('per_page') == 50 ? 'selected' : '' }}>50</option>
|
||||
<option value="100" {{ request('per_page') == 100 ? 'selected' : '' }}>100</option>
|
||||
</select>
|
||||
<label class="ms-2 text-nowrap">entries</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-auto d-flex gap-2">
|
||||
<div class="input-group input-group-sm w-auto">
|
||||
<input
|
||||
type="text"
|
||||
name="search"
|
||||
class="form-control"
|
||||
placeholder="Cari Varietas..."
|
||||
value="{{ request('search') }}">
|
||||
|
||||
@if(request('search'))
|
||||
<a href="{{ route('varietas.index', ['per_page' => request('per_page', 10)]) }}" class="btn btn-outline-secondary">
|
||||
<i class="ti tabler-x"></i>
|
||||
</a>
|
||||
@endif
|
||||
|
||||
<button type="submit" class="btn btn-outline-primary">
|
||||
<i class="ti tabler-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-primary add-new"
|
||||
data-bs-toggle="offcanvas"
|
||||
data-bs-target="#offcanvasAddVarietas">
|
||||
<i class="ti tabler-plus me-1"></i> Tambah
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive text-nowrap">
|
||||
<table class="table table-hover">
|
||||
<thead class="border-top">
|
||||
<tr>
|
||||
<th>No</th>
|
||||
<th>Nama Varietas</th>
|
||||
<th>Komoditas</th>
|
||||
<th>Jenis Komoditas</th>
|
||||
<th class="text-center">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@forelse($varietas as $index => $item)
|
||||
@php
|
||||
$namaVarietas = $item->nama ?? '-';
|
||||
$words = preg_split('/\s+/', trim($namaVarietas));
|
||||
$initials = collect($words)
|
||||
->filter()
|
||||
->map(fn($word) => strtoupper(substr($word, 0, 1)))
|
||||
->take(2)
|
||||
->implode('');
|
||||
|
||||
$states = ['success', 'danger', 'warning', 'info', 'primary', 'secondary'];
|
||||
$state = $states[$item->id % count($states)];
|
||||
@endphp
|
||||
|
||||
<tr>
|
||||
<td>{{ $varietas->firstItem() + $index }}</td>
|
||||
|
||||
<td>
|
||||
<div class="d-flex justify-content-start align-items-center">
|
||||
<div class="avatar-wrapper me-3">
|
||||
<div class="avatar avatar-sm">
|
||||
<span class="avatar-initial rounded-circle bg-label-{{ $state }}">
|
||||
{{ $initials ?: 'VR' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column">
|
||||
<span class="fw-medium text-heading">{{ $item->nama }}</span>
|
||||
<small class="text-muted">{{ $item->deskripsi }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="badge bg-label-secondary">
|
||||
{{ $item->komoditas->nama ?? '-' }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="badge bg-label-info">
|
||||
{{ $item->jenisKomoditas->nama ?? '-' }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<div class="d-flex justify-content-center align-items-center">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-icon btn-text-secondary rounded-pill view-record"
|
||||
data-id="{{ $item->id }}"
|
||||
title="Lihat">
|
||||
<i class="ti tabler-eye ti-md"></i>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-icon btn-text-secondary rounded-pill edit-record"
|
||||
data-id="{{ $item->id }}"
|
||||
title="Edit">
|
||||
<i class="ti tabler-edit ti-md"></i>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-icon btn-text-secondary rounded-pill delete-record"
|
||||
data-id="{{ $item->id }}"
|
||||
data-nama="{{ $item->nama }}"
|
||||
title="Hapus">
|
||||
<i class="ti tabler-trash ti-md"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="6" class="text-center py-4">
|
||||
Tidak ada data ditemukan.
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@if($varietas->hasPages())
|
||||
<div class="card-footer d-flex justify-content-center justify-content-md-end border-top">
|
||||
{{ $varietas->appends(request()->query())->links('pagination::bootstrap-5') }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@include('master.varietas.add')
|
||||
@include('master.varietas.edit')
|
||||
@include('master.varietas.view')
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
$(function () {
|
||||
const csrfToken = "{{ csrf_token() }}";
|
||||
const baseUrl = "{{ url('varietas') }}";
|
||||
|
||||
const offcanvasAdd = new bootstrap.Offcanvas(document.getElementById('offcanvasAddVarietas'));
|
||||
const offcanvasEdit = new bootstrap.Offcanvas(document.getElementById('offcanvasEditVarietas'));
|
||||
const offcanvasView = new bootstrap.Offcanvas(document.getElementById('offcanvasViewVarietas'));
|
||||
|
||||
$.ajaxSetup({
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': csrfToken
|
||||
}
|
||||
});
|
||||
|
||||
$('.select2').each(function () {
|
||||
const $this = $(this);
|
||||
|
||||
$this.wrap('<div class="position-relative"></div>').select2({
|
||||
dropdownParent: $this.parent(),
|
||||
placeholder: $this.data('placeholder') || 'Pilih data',
|
||||
allowClear: true,
|
||||
width: '100%'
|
||||
});
|
||||
});
|
||||
|
||||
$.validator.setDefaults({
|
||||
errorElement: 'div',
|
||||
errorClass: 'invalid-feedback',
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
},
|
||||
errorPlacement: function (error, element) {
|
||||
if (element.hasClass('select2-hidden-accessible')) {
|
||||
error.insertAfter(element.next('.select2-container'));
|
||||
} else {
|
||||
error.appendTo(element.closest('.form-control-validation'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('.select2').on('change', function () {
|
||||
const $form = $(this).closest('form');
|
||||
|
||||
if (!$form.length) return;
|
||||
if (!$form.data('validator')) return;
|
||||
|
||||
$(this).valid();
|
||||
});
|
||||
|
||||
function showSuccess(title = 'Berhasil!', text = 'Data berhasil diproses') {
|
||||
return Swal.fire({
|
||||
icon: 'success',
|
||||
title,
|
||||
text,
|
||||
showConfirmButton: false,
|
||||
timer: 1500,
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-primary'
|
||||
},
|
||||
buttonsStyling: false
|
||||
});
|
||||
}
|
||||
|
||||
function showError(xhr, fallback = 'Terjadi kesalahan sistem.') {
|
||||
let message = fallback;
|
||||
|
||||
if (xhr.responseJSON?.message) {
|
||||
message = xhr.responseJSON.message;
|
||||
}
|
||||
|
||||
if (xhr.responseJSON?.errors) {
|
||||
message = Object.values(xhr.responseJSON.errors).flat().join('<br>');
|
||||
}
|
||||
|
||||
return Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Gagal!',
|
||||
html: message,
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-primary'
|
||||
},
|
||||
buttonsStyling: false
|
||||
});
|
||||
}
|
||||
|
||||
function setButtonLoading($button, isLoading, text = 'Menyimpan...') {
|
||||
if (isLoading) {
|
||||
$button
|
||||
.data('original-text', $button.html())
|
||||
.prop('disabled', true)
|
||||
.html(`<span class="spinner-border spinner-border-sm me-1"></span>${text}`);
|
||||
} else {
|
||||
$button
|
||||
.prop('disabled', false)
|
||||
.html($button.data('original-text'));
|
||||
}
|
||||
}
|
||||
|
||||
function resetForm($form) {
|
||||
if (!$form.length) return;
|
||||
|
||||
$form[0].reset();
|
||||
|
||||
if ($form.data('validator')) {
|
||||
$form.validate().resetForm();
|
||||
}
|
||||
|
||||
$form.find('.is-invalid').removeClass('is-invalid');
|
||||
|
||||
$form.find('.select2').each(function () {
|
||||
$(this).val('').trigger('change.select2');
|
||||
});
|
||||
}
|
||||
|
||||
function loadJenisKomoditas(komoditasId, targetSelector, selectedId = null) {
|
||||
const $target = $(targetSelector);
|
||||
|
||||
$target.empty().append('<option value=""></option>').trigger('change.select2');
|
||||
|
||||
if (!komoditasId) return;
|
||||
|
||||
$.ajax({
|
||||
url: `/jenis-komoditas-by-komoditas/${komoditasId}`,
|
||||
type: 'GET',
|
||||
success: function (res) {
|
||||
const data = res.data || [];
|
||||
|
||||
data.forEach(function (item) {
|
||||
const option = new Option(item.nama, item.id, false, false);
|
||||
$target.append(option);
|
||||
});
|
||||
|
||||
if (selectedId) {
|
||||
$target.val(selectedId);
|
||||
}
|
||||
|
||||
$target.trigger('change.select2');
|
||||
},
|
||||
error: function (xhr) {
|
||||
showError(xhr, 'Gagal mengambil data jenis komoditas.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$('#add-varietas-komoditas').on('change', function () {
|
||||
const komoditasId = $(this).val();
|
||||
loadJenisKomoditas(komoditasId, '#add-varietas-jenis-komoditas');
|
||||
});
|
||||
|
||||
$('#edit-varietas-komoditas').on('change', function () {
|
||||
const komoditasId = $(this).val();
|
||||
loadJenisKomoditas(komoditasId, '#edit-varietas-jenis-komoditas');
|
||||
});
|
||||
|
||||
$('#addNewVarietasForm').validate({
|
||||
rules: {
|
||||
komoditas_id: {
|
||||
required: true
|
||||
},
|
||||
jenis_komoditas_id: {
|
||||
required: true
|
||||
},
|
||||
nama: {
|
||||
required: true,
|
||||
maxlength: 255
|
||||
},
|
||||
deskripsi: {
|
||||
maxlength: 10000
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
komoditas_id: {
|
||||
required: 'Komoditas wajib dipilih'
|
||||
},
|
||||
jenis_komoditas_id: {
|
||||
required: 'Jenis komoditas wajib dipilih'
|
||||
},
|
||||
nama: {
|
||||
required: 'Nama varietas wajib diisi',
|
||||
maxlength: 'Nama maksimal 255 karakter'
|
||||
},
|
||||
deskripsi: {
|
||||
maxlength: 'Deskripsi terlalu panjang'
|
||||
}
|
||||
},
|
||||
submitHandler: function (form, event) {
|
||||
event.preventDefault();
|
||||
|
||||
const $form = $(form);
|
||||
const $button = $form.find('button[type="submit"]');
|
||||
|
||||
setButtonLoading($button, true);
|
||||
|
||||
$.ajax({
|
||||
url: $form.attr('action'),
|
||||
type: 'POST',
|
||||
data: $form.serialize(),
|
||||
success: function (res) {
|
||||
offcanvasAdd.hide();
|
||||
|
||||
showSuccess(
|
||||
'Berhasil!',
|
||||
res.message || 'Data varietas berhasil disimpan'
|
||||
).then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
showError(xhr, 'Gagal menyimpan data varietas');
|
||||
},
|
||||
complete: function () {
|
||||
setButtonLoading($button, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('#offcanvasAddVarietas').on('hidden.bs.offcanvas', function () {
|
||||
resetForm($('#addNewVarietasForm'));
|
||||
$('#add-varietas-jenis-komoditas').empty().append('<option value=""></option>').trigger('change.select2');
|
||||
});
|
||||
|
||||
$(document).on('click', '.view-record', function () {
|
||||
const id = $(this).data('id');
|
||||
|
||||
$.ajax({
|
||||
url: `${baseUrl}/${id}`,
|
||||
type: 'GET',
|
||||
success: function (res) {
|
||||
const data = res.data || res;
|
||||
|
||||
$('#view-varietas-komoditas').val(data.komoditas?.nama || '-');
|
||||
$('#view-varietas-jenis-komoditas').val(data.jenis_komoditas?.nama || data.jenis_komoditas?.nama || data.jenisKomoditas?.nama || '-');
|
||||
$('#view-varietas-name').val(data.nama || '-');
|
||||
$('#view-varietas-description').val(data.deskripsi || '-');
|
||||
|
||||
offcanvasView.show();
|
||||
},
|
||||
error: function (xhr) {
|
||||
showError(xhr, 'Terjadi kesalahan saat mengambil detail data.');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '.edit-record', function () {
|
||||
const id = $(this).data('id');
|
||||
const $form = $('#editVarietasForm');
|
||||
|
||||
resetForm($form);
|
||||
|
||||
$.ajax({
|
||||
url: `${baseUrl}/${id}`,
|
||||
type: 'GET',
|
||||
success: function (res) {
|
||||
const data = res.data || res;
|
||||
|
||||
$('#edit-varietas-id').val(data.id);
|
||||
$('#edit-varietas-komoditas').val(data.komoditas_id).trigger('change.select2');
|
||||
$('#edit-varietas-name').val(data.nama || '');
|
||||
$('#edit-varietas-description').val(data.deskripsi || '');
|
||||
|
||||
loadJenisKomoditas(
|
||||
data.komoditas_id,
|
||||
'#edit-varietas-jenis-komoditas',
|
||||
data.jenis_komoditas_id
|
||||
);
|
||||
|
||||
offcanvasEdit.show();
|
||||
},
|
||||
error: function (xhr) {
|
||||
showError(xhr, 'Terjadi kesalahan saat mengambil data edit.');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#editVarietasForm').validate({
|
||||
rules: {
|
||||
komoditas_id: {
|
||||
required: true
|
||||
},
|
||||
jenis_komoditas_id: {
|
||||
required: true
|
||||
},
|
||||
nama: {
|
||||
required: true,
|
||||
maxlength: 255
|
||||
},
|
||||
deskripsi: {
|
||||
maxlength: 10000
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
komoditas_id: {
|
||||
required: 'Komoditas wajib dipilih'
|
||||
},
|
||||
jenis_komoditas_id: {
|
||||
required: 'Jenis komoditas wajib dipilih'
|
||||
},
|
||||
nama: {
|
||||
required: 'Nama varietas wajib diisi',
|
||||
maxlength: 'Nama maksimal 255 karakter'
|
||||
},
|
||||
deskripsi: {
|
||||
maxlength: 'Deskripsi terlalu panjang'
|
||||
}
|
||||
},
|
||||
submitHandler: function (form, event) {
|
||||
event.preventDefault();
|
||||
|
||||
const $form = $(form);
|
||||
const id = $('#edit-varietas-id').val();
|
||||
const $button = $form.find('button[type="submit"]');
|
||||
|
||||
setButtonLoading($button, true, 'Mengupdate...');
|
||||
|
||||
$.ajax({
|
||||
url: `${baseUrl}/${id}`,
|
||||
type: 'POST',
|
||||
data: $form.serialize(),
|
||||
success: function (res) {
|
||||
offcanvasEdit.hide();
|
||||
|
||||
showSuccess(
|
||||
'Updated!',
|
||||
res.message || 'Data varietas berhasil diperbarui'
|
||||
).then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
showError(xhr, 'Gagal mengupdate data varietas');
|
||||
},
|
||||
complete: function () {
|
||||
setButtonLoading($button, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('#offcanvasEditVarietas').on('hidden.bs.offcanvas', function () {
|
||||
resetForm($('#editVarietasForm'));
|
||||
$('#edit-varietas-jenis-komoditas').empty().append('<option value=""></option>').trigger('change.select2');
|
||||
});
|
||||
|
||||
$(document).on('click', '.delete-record', function () {
|
||||
const id = $(this).data('id');
|
||||
const nama = $(this).data('nama') || 'data ini';
|
||||
|
||||
Swal.fire({
|
||||
title: 'Apakah Anda yakin?',
|
||||
text: `Varietas "${nama}" akan dihapus secara permanen.`,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Ya, Hapus!',
|
||||
cancelButtonText: 'Batal',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-primary me-3',
|
||||
cancelButton: 'btn btn-label-secondary'
|
||||
},
|
||||
buttonsStyling: false
|
||||
}).then(function (result) {
|
||||
if (!result.isConfirmed) return;
|
||||
|
||||
$.ajax({
|
||||
url: `${baseUrl}/${id}`,
|
||||
type: 'DELETE',
|
||||
success: function (res) {
|
||||
showSuccess(
|
||||
'Terhapus!',
|
||||
res.message || 'Data varietas berhasil dihapus'
|
||||
).then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
showError(xhr, 'Gagal menghapus data varietas');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,34 @@
|
||||
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasViewVarietas" aria-labelledby="offcanvasViewVarietasLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasViewVarietasLabel" class="offcanvas-title">Detail Varietas</h5>
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<div class="mb-6">
|
||||
<label class="form-label">Komoditas</label>
|
||||
<input type="text" class="form-control" id="view-varietas-komoditas" readonly>
|
||||
</div>
|
||||
|
||||
<div class="mb-6">
|
||||
<label class="form-label">Jenis Komoditas</label>
|
||||
<input type="text" class="form-control" id="view-varietas-jenis-komoditas" readonly>
|
||||
</div>
|
||||
|
||||
<div class="mb-6">
|
||||
<label class="form-label">Nama Varietas</label>
|
||||
<input type="text" class="form-control" id="view-varietas-name" readonly>
|
||||
</div>
|
||||
|
||||
<div class="mb-6">
|
||||
<label class="form-label">Deskripsi</label>
|
||||
<textarea class="form-control" id="view-varietas-description" rows="3" readonly></textarea>
|
||||
</div>
|
||||
|
||||
<div class="mt-8">
|
||||
<button type="button" class="btn btn-label-secondary" data-bs-dismiss="offcanvas">
|
||||
Tutup
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -140,11 +140,12 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
|
||||
@@ -159,7 +160,7 @@
|
||||
let regionBoundaryLayer = L.featureGroup().addTo(map);
|
||||
|
||||
function focusToRegionBoundary(selectElement) {
|
||||
regionBoundaryLayer.clearLayers();
|
||||
regionBoundaryLayer.clearLayers(); // Bersihkan garis wilayah sebelumnya
|
||||
|
||||
let selectedOption = selectElement.options[selectElement.selectedIndex];
|
||||
if (!selectedOption || !selectedOption.hasAttribute('data-path')) return;
|
||||
@@ -174,7 +175,7 @@
|
||||
|
||||
function formatCoordinates(coords) {
|
||||
if (coords.length === 2 && typeof coords[0] === 'number') {
|
||||
return [coords[0], coords[1]]; // JANGAN DIBALIK (Leaflet Draw butuh format asli)
|
||||
return [coords[0], coords[1]]; // JANGAN DIBALIK
|
||||
}
|
||||
return coords.map(formatCoordinates);
|
||||
}
|
||||
@@ -182,11 +183,11 @@
|
||||
let latLngs = formatCoordinates(rawData);
|
||||
|
||||
let polygon = L.polygon(latLngs, {
|
||||
color: '#ffc107',
|
||||
fillColor: '#ffc107',
|
||||
fillOpacity: 0.15,
|
||||
weight: 3,
|
||||
dashArray: '8, 6',
|
||||
color: '#3b5998',
|
||||
fillColor: '#3b5998',
|
||||
fillOpacity: 0.1,
|
||||
weight: 2,
|
||||
dashArray: '5, 5',
|
||||
interactive: false
|
||||
});
|
||||
|
||||
@@ -228,8 +229,10 @@
|
||||
|
||||
map.on(L.Draw.Event.CREATED, function (e) {
|
||||
let layer = e.layer;
|
||||
|
||||
drawnItems.clearLayers();
|
||||
drawnItems.addLayer(layer);
|
||||
|
||||
updatePathTextarea(layer);
|
||||
});
|
||||
|
||||
@@ -241,32 +244,14 @@
|
||||
|
||||
map.on(L.Draw.Event.DELETED, function () {
|
||||
document.getElementById('path').value = '';
|
||||
|
||||
let luasInput = document.querySelector('input[name="luas_lahan"]');
|
||||
if (luasInput) luasInput.value = '';
|
||||
});
|
||||
|
||||
function updatePathTextarea(layer) {
|
||||
let latlngs = layer.getLatLngs()[0];
|
||||
|
||||
let pathData = latlngs.map(function(latlng) {
|
||||
return [latlng.lng, latlng.lat];
|
||||
});
|
||||
document.getElementById('path').value = JSON.stringify(pathData);
|
||||
|
||||
let areaSquareMeters = L.GeometryUtil.geodesicArea(latlngs);
|
||||
let areaHectares = areaSquareMeters / 10000;
|
||||
|
||||
let luasInput = document.querySelector('input[name="luas_lahan"]');
|
||||
if (luasInput) {
|
||||
luasInput.value = areaHectares.toFixed(2);
|
||||
luasInput.style.transition = "background-color 0.5s ease";
|
||||
luasInput.style.backgroundColor = "#e8fdf0";
|
||||
|
||||
setTimeout(() => {
|
||||
luasInput.style.backgroundColor = "";
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
|
||||
let statusSelect = document.getElementById('status_kepemilikan');
|
||||
|
||||
@@ -162,11 +162,12 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
|
||||
@@ -203,11 +204,11 @@
|
||||
let latLngs = formatCoordinates(rawData);
|
||||
|
||||
let polygon = L.polygon(latLngs, {
|
||||
color: '#ffc107',
|
||||
fillColor: '#ffc107',
|
||||
fillOpacity: 0.15,
|
||||
weight: 3,
|
||||
dashArray: '8, 6',
|
||||
color: '#3b5998',
|
||||
fillColor: '#3b5998',
|
||||
fillOpacity: 0.1,
|
||||
weight: 2,
|
||||
dashArray: '5, 5',
|
||||
interactive: false
|
||||
});
|
||||
|
||||
@@ -275,32 +276,14 @@
|
||||
|
||||
map.on(L.Draw.Event.DELETED, function () {
|
||||
document.getElementById('path').value = '';
|
||||
|
||||
let luasInput = document.querySelector('input[name="luas_lahan"]');
|
||||
if (luasInput) luasInput.value = '';
|
||||
});
|
||||
|
||||
function updatePathTextarea(layer) {
|
||||
let latlngs = layer.getLatLngs()[0];
|
||||
|
||||
let pathData = latlngs.map(function(latlng) {
|
||||
return [latlng.lng, latlng.lat];
|
||||
});
|
||||
document.getElementById('path').value = JSON.stringify(pathData);
|
||||
|
||||
let areaSquareMeters = L.GeometryUtil.geodesicArea(latlngs);
|
||||
let areaHectares = areaSquareMeters / 10000;
|
||||
|
||||
let luasInput = document.querySelector('input[name="luas_lahan"]');
|
||||
if (luasInput) {
|
||||
luasInput.value = areaHectares.toFixed(2);
|
||||
luasInput.style.transition = "background-color 0.5s ease";
|
||||
luasInput.style.backgroundColor = "#e8fdf0";
|
||||
|
||||
setTimeout(() => {
|
||||
luasInput.style.backgroundColor = "";
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
|
||||
let statusSelect = document.getElementById('status_kepemilikan');
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,832 @@
|
||||
@extends('layout.main')
|
||||
|
||||
@push('style')
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
||||
|
||||
<style>
|
||||
#map {
|
||||
height: 100%;
|
||||
min-height: 620px;
|
||||
width: 100%;
|
||||
background-color: var(--bs-body-bg);
|
||||
z-index: 1;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.map-wrapper {
|
||||
min-height: 620px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.points-table-wrapper {
|
||||
max-height: 320px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.leaflet-popup-content {
|
||||
color: #2f2b3d;
|
||||
}
|
||||
|
||||
.plant-marker-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
background: rgba(var(--bs-success-rgb), 0.95);
|
||||
border: 2px solid #fff;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.plant-marker-icon.sakit {
|
||||
background: rgba(var(--bs-danger-rgb), 0.95);
|
||||
}
|
||||
|
||||
.plant-marker-icon.mati {
|
||||
background: rgba(var(--bs-dark-rgb), 0.95);
|
||||
}
|
||||
|
||||
.plant-dot-marker {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
border-radius: 50%;
|
||||
background: rgba(var(--bs-success-rgb), 0.95);
|
||||
border: 2px solid #fff;
|
||||
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
.plant-dot-marker.sakit {
|
||||
background: rgba(var(--bs-danger-rgb), 0.95);
|
||||
}
|
||||
|
||||
.plant-dot-marker.mati {
|
||||
background: rgba(var(--bs-dark-rgb), 0.95);
|
||||
}
|
||||
|
||||
.detail-box {
|
||||
padding: .75rem;
|
||||
border: 1px solid var(--bs-border-color);
|
||||
border-radius: .375rem;
|
||||
background-color: rgba(var(--bs-primary-rgb), .04);
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
font-size: .75rem;
|
||||
color: var(--bs-secondary-color);
|
||||
margin-bottom: .25rem;
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
font-weight: 500;
|
||||
color: var(--bs-heading-color);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.custom-plant-popup .leaflet-popup-content-wrapper {
|
||||
border-radius: 14px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background: var(--bs-card-bg);
|
||||
color: var(--bs-body-color);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28);
|
||||
}
|
||||
|
||||
.custom-plant-popup .leaflet-popup-content {
|
||||
margin: 0;
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
.custom-plant-popup .leaflet-popup-tip {
|
||||
background: var(--bs-card-bg);
|
||||
}
|
||||
|
||||
.plant-popup-card {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.plant-popup-header {
|
||||
padding: 10px 12px;
|
||||
background: rgba(var(--bs-primary-rgb), 0.14);
|
||||
border-bottom: 1px solid var(--bs-border-color);
|
||||
}
|
||||
|
||||
.plant-popup-title {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
color: var(--bs-heading-color);
|
||||
margin: 0;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.plant-popup-subtitle {
|
||||
font-size: 0.75rem;
|
||||
color: var(--bs-secondary-color);
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.plant-popup-body {
|
||||
padding: 10px 12px 12px;
|
||||
}
|
||||
|
||||
.plant-popup-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
font-size: 0.75rem;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.plant-popup-label {
|
||||
color: var(--bs-secondary-color);
|
||||
}
|
||||
|
||||
.plant-popup-value {
|
||||
color: var(--bs-heading-color);
|
||||
font-weight: 500;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.plant-popup-actions {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.plant-popup-actions .btn {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.plant-popup-help {
|
||||
font-size: 0.7rem;
|
||||
color: var(--bs-secondary-color);
|
||||
margin-top: 8px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
@php
|
||||
$groupName = ($tanaman->komoditas->nama ?? 'Tanaman') . ' - ' . ($tanaman->profile->nama ?? 'Pemilik');
|
||||
@endphp
|
||||
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="card">
|
||||
<div class="card-header border-bottom mb-4 d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h5 class="card-title mb-0">Edit Kelompok Tanaman</h5>
|
||||
<small class="text-muted">{{ $groupName }}</small>
|
||||
</div>
|
||||
|
||||
<a href="{{ route('map-tanaman.index') }}" class="btn btn-sm btn-label-secondary">
|
||||
<i class="ti tabler-arrow-left me-1"></i> Kembali
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form id="editTanamanForm" action="{{ route('map-tanaman.update', $tanaman->id) }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-5 mb-4">
|
||||
|
||||
<h6 class="mb-3 text-primary">
|
||||
<i class="ti tabler-seeding me-1"></i> Informasi Kelompok
|
||||
</h6>
|
||||
|
||||
<div class="alert alert-info mb-3">
|
||||
<i class="ti tabler-info-circle me-1"></i>
|
||||
Data lahan, pemilik, komoditas, jenis, dan varietas tidak diubah dari halaman ini. Perubahan hanya untuk titik tanaman.
|
||||
</div>
|
||||
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-md-6">
|
||||
<div class="detail-box">
|
||||
<div class="detail-label">Pemilik/Pengelola</div>
|
||||
<div class="detail-value">{{ $tanaman->profile->nama ?? '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="detail-box">
|
||||
<div class="detail-label">Lahan</div>
|
||||
<div class="detail-value">{{ $tanaman->lahan->nama ?? '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="detail-box">
|
||||
<div class="detail-label">Komoditas</div>
|
||||
<div class="detail-value">{{ $tanaman->komoditas->nama ?? '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="detail-box">
|
||||
<div class="detail-label">Jenis Komoditas</div>
|
||||
<div class="detail-value">{{ $tanaman->jenisKomoditas->nama ?? '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<div class="detail-box">
|
||||
<div class="detail-label">Varietas</div>
|
||||
<div class="detail-value">{{ $tanaman->varietas->nama ?? '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3 form-control-validation">
|
||||
<label class="form-label">Deskripsi</label>
|
||||
<textarea
|
||||
name="deskripsi"
|
||||
class="form-control"
|
||||
rows="3"
|
||||
placeholder="Catatan tambahan">{{ old('deskripsi', $tanaman->deskripsi ?? '') }}</textarea>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<h6 class="mb-3 text-primary">
|
||||
<i class="ti tabler-current-location me-1"></i> Titik Koordinat Tanaman
|
||||
</h6>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<div>
|
||||
<label class="form-label text-success fw-bold mb-0">
|
||||
Klik map untuk menambahkan titik baru
|
||||
</label>
|
||||
<small class="text-muted d-block">
|
||||
Kondisi dan hapus titik bisa dilakukan dari tabel atau popup map.
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="btn-group" role="group" aria-label="Marker Mode">
|
||||
<input type="radio" class="btn-check" name="marker_mode" id="marker-mode-plant" value="plant" checked>
|
||||
<label class="btn btn-sm btn-outline-primary" for="marker-mode-plant">
|
||||
<i class="ti tabler-plant-2 me-1"></i> Ikon
|
||||
</label>
|
||||
|
||||
<input type="radio" class="btn-check" name="marker_mode" id="marker-mode-dot" value="dot">
|
||||
<label class="btn btn-sm btn-outline-primary" for="marker-mode-dot">
|
||||
<i class="ti tabler-point me-1"></i> Titik
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3 form-control-validation">
|
||||
<input type="hidden" id="points_validation" name="points_validation">
|
||||
</div>
|
||||
|
||||
<div class="points-table-wrapper border rounded">
|
||||
<table class="table table-sm table-hover mb-0" id="points-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50px;">No</th>
|
||||
<th>Latitude</th>
|
||||
<th>Longitude</th>
|
||||
<th style="width: 150px;">Kondisi</th>
|
||||
<th style="width: 60px;" class="text-center">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr id="empty-points-row">
|
||||
<td colspan="5" class="text-center text-muted py-4">
|
||||
Belum ada titik tanaman. Klik area pada peta.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="points-hidden-wrapper"></div>
|
||||
|
||||
<div class="mt-4 text-end">
|
||||
<a href="{{ route('map-tanaman.index') }}" class="btn btn-label-secondary me-2">
|
||||
Batal
|
||||
</a>
|
||||
<button type="submit" class="btn btn-primary data-submit">
|
||||
Simpan Perubahan
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-7">
|
||||
<div class="border rounded h-100 map-wrapper">
|
||||
<div id="map"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
$(document).ready(function () {
|
||||
$.ajaxSetup({
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': "{{ csrf_token() }}"
|
||||
}
|
||||
});
|
||||
|
||||
const editForm = document.getElementById('editTanamanForm');
|
||||
|
||||
const lahanPath = {{ Illuminate\Support\Js::from($tanaman->lahan->path ?? null) }};
|
||||
|
||||
let plantPoints = {{ Illuminate\Support\Js::from(
|
||||
$points->map(function ($point) {
|
||||
$kondisi = $point->kondisi_tanaman;
|
||||
$kondisiValue = is_object($kondisi) && property_exists($kondisi, 'value')
|
||||
? $kondisi->value
|
||||
: $kondisi;
|
||||
|
||||
return [
|
||||
'id' => $point->id,
|
||||
'nama' => $point->nama,
|
||||
'latitude' => $point->latitude,
|
||||
'longitude' => $point->longitude,
|
||||
'kondisi_tanaman' => $kondisiValue,
|
||||
'_delete' => false,
|
||||
'_new' => false,
|
||||
];
|
||||
})->values()
|
||||
) }};
|
||||
|
||||
const map = L.map('map').setView([-2.5489, 118.0149], 5);
|
||||
|
||||
L.tileLayer('https://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', {
|
||||
maxZoom: 22,
|
||||
subdomains: ['mt0', 'mt1', 'mt2', 'mt3'],
|
||||
attribution: '© Google Maps Satellite'
|
||||
}).addTo(map);
|
||||
|
||||
let currentPolygon = null;
|
||||
let plantMarkers = [];
|
||||
|
||||
function showError(xhr, fallback = 'Terjadi kesalahan sistem.') {
|
||||
let message = fallback;
|
||||
|
||||
if (xhr.responseJSON?.message) {
|
||||
message = xhr.responseJSON.message;
|
||||
}
|
||||
|
||||
if (xhr.responseJSON?.errors) {
|
||||
message = Object.values(xhr.responseJSON.errors).flat().join('<br>');
|
||||
}
|
||||
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Gagal!',
|
||||
html: message,
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-primary'
|
||||
},
|
||||
buttonsStyling: false
|
||||
});
|
||||
}
|
||||
|
||||
function escapeHtml(value) {
|
||||
return String(value ?? '')
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
function parsePath(path) {
|
||||
if (!path) return null;
|
||||
|
||||
let parsed = path;
|
||||
|
||||
if (typeof path === 'string') {
|
||||
try {
|
||||
parsed = JSON.parse(path);
|
||||
} catch (error) {
|
||||
console.error('Path bukan JSON valid:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (parsed.type && parsed.coordinates) {
|
||||
return {
|
||||
type: 'geojson',
|
||||
data: parsed
|
||||
};
|
||||
}
|
||||
|
||||
if (Array.isArray(parsed)) {
|
||||
return {
|
||||
type: 'array',
|
||||
data: parsed
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function renderLahanPolygon(path) {
|
||||
const parsed = parsePath(path);
|
||||
|
||||
if (!parsed) return null;
|
||||
|
||||
let layer = null;
|
||||
|
||||
if (parsed.type === 'geojson') {
|
||||
layer = L.geoJSON(parsed.data, {
|
||||
style: {
|
||||
color: '#28c76f',
|
||||
fillColor: '#28c76f',
|
||||
fillOpacity: 0.35,
|
||||
weight: 2
|
||||
}
|
||||
}).addTo(map);
|
||||
|
||||
map.fitBounds(layer.getBounds(), { padding: [30, 30] });
|
||||
}
|
||||
|
||||
if (parsed.type === 'array') {
|
||||
const latLngs = parsed.data.map(coord => [coord[1], coord[0]]);
|
||||
|
||||
layer = L.polygon(latLngs, {
|
||||
color: '#28c76f',
|
||||
fillColor: '#28c76f',
|
||||
fillOpacity: 0.35,
|
||||
weight: 2
|
||||
}).addTo(map);
|
||||
|
||||
map.fitBounds(layer.getBounds(), { padding: [30, 30] });
|
||||
}
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
function getMarkerMode() {
|
||||
return $('input[name="marker_mode"]:checked').val() || 'plant';
|
||||
}
|
||||
|
||||
function getPlantIcon(point) {
|
||||
const kondisi = point.kondisi_tanaman || 'sehat';
|
||||
|
||||
return L.divIcon({
|
||||
className: '',
|
||||
html: `
|
||||
<div class="plant-marker-icon ${kondisi}">
|
||||
<i class="ti tabler-plant-2"></i>
|
||||
</div>
|
||||
`,
|
||||
iconSize: [32, 32],
|
||||
iconAnchor: [16, 16],
|
||||
popupAnchor: [0, -16]
|
||||
});
|
||||
}
|
||||
|
||||
function getDotIcon(point) {
|
||||
const kondisi = point.kondisi_tanaman || 'sehat';
|
||||
|
||||
return L.divIcon({
|
||||
className: '',
|
||||
html: `<div class="plant-dot-marker ${kondisi}"></div>`,
|
||||
iconSize: [11, 11],
|
||||
iconAnchor: [5.5, 5.5],
|
||||
popupAnchor: [0, -8]
|
||||
});
|
||||
}
|
||||
|
||||
function formatKondisiLabel(kondisi) {
|
||||
const labels = {
|
||||
sehat: 'Sehat',
|
||||
sakit: 'Sakit',
|
||||
mati: 'Mati'
|
||||
};
|
||||
|
||||
return labels[kondisi] || '-';
|
||||
}
|
||||
|
||||
function getActivePoints() {
|
||||
return plantPoints.filter(point => !point._delete);
|
||||
}
|
||||
|
||||
function buildPlantPopup(point, index, visibleIndex) {
|
||||
const title = point.nama && point.nama !== 'null'
|
||||
? point.nama
|
||||
: `Titik Tanaman ${visibleIndex + 1}`;
|
||||
|
||||
return `
|
||||
<div class="plant-popup-card">
|
||||
<div class="plant-popup-header">
|
||||
<p class="plant-popup-title">${escapeHtml(title)}</p>
|
||||
<div class="plant-popup-subtitle">Titik Tanaman ${visibleIndex + 1}</div>
|
||||
</div>
|
||||
|
||||
<div class="plant-popup-body">
|
||||
<div class="plant-popup-row">
|
||||
<span class="plant-popup-label">Latitude</span>
|
||||
<span class="plant-popup-value">${point.latitude}</span>
|
||||
</div>
|
||||
|
||||
<div class="plant-popup-row">
|
||||
<span class="plant-popup-label">Longitude</span>
|
||||
<span class="plant-popup-value">${point.longitude}</span>
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
<label class="form-label mb-1" style="font-size: .75rem;">Kondisi Tanaman</label>
|
||||
<select class="form-select form-select-sm popup-point-condition" data-index="${index}">
|
||||
<option value="sehat" ${point.kondisi_tanaman === 'sehat' ? 'selected' : ''}>Sehat</option>
|
||||
<option value="sakit" ${point.kondisi_tanaman === 'sakit' ? 'selected' : ''}>Sakit</option>
|
||||
<option value="mati" ${point.kondisi_tanaman === 'mati' ? 'selected' : ''}>Mati</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="plant-popup-actions">
|
||||
<button type="button" class="btn btn-sm btn-label-danger popup-remove-point" data-index="${index}">
|
||||
<i class="ti tabler-trash me-1"></i> Hapus Titik
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="plant-popup-help">
|
||||
Perubahan akan tersimpan setelah klik <strong>Simpan Perubahan</strong>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function renderPointsTable() {
|
||||
const $tbody = $('#points-table tbody');
|
||||
const $hiddenWrapper = $('#points-hidden-wrapper');
|
||||
|
||||
$tbody.empty();
|
||||
$hiddenWrapper.empty();
|
||||
|
||||
const activePoints = getActivePoints();
|
||||
|
||||
if (!activePoints.length) {
|
||||
$tbody.append(`
|
||||
<tr id="empty-points-row">
|
||||
<td colspan="5" class="text-center text-muted py-4">
|
||||
Belum ada titik tanaman. Klik area pada peta.
|
||||
</td>
|
||||
</tr>
|
||||
`);
|
||||
|
||||
$('#points_validation').val('');
|
||||
} else {
|
||||
$('#points_validation').val('filled');
|
||||
}
|
||||
|
||||
let visibleNumber = 1;
|
||||
|
||||
plantPoints.forEach((point, index) => {
|
||||
const prefix = `points[${index}]`;
|
||||
|
||||
$hiddenWrapper.append(`
|
||||
<input type="hidden" name="${prefix}[id]" value="${point.id || ''}">
|
||||
<input type="hidden" name="${prefix}[latitude]" value="${point.latitude}">
|
||||
<input type="hidden" name="${prefix}[longitude]" value="${point.longitude}">
|
||||
<input type="hidden" name="${prefix}[kondisi_tanaman]" value="${point.kondisi_tanaman}">
|
||||
<input type="hidden" name="${prefix}[_delete]" value="${point._delete ? 1 : 0}">
|
||||
`);
|
||||
|
||||
if (point._delete) return;
|
||||
|
||||
$tbody.append(`
|
||||
<tr>
|
||||
<td>${visibleNumber}</td>
|
||||
<td>${point.latitude}</td>
|
||||
<td>${point.longitude}</td>
|
||||
<td>
|
||||
<select class="form-select form-select-sm point-condition" data-index="${index}">
|
||||
<option value="sehat" ${point.kondisi_tanaman === 'sehat' ? 'selected' : ''}>Sehat</option>
|
||||
<option value="sakit" ${point.kondisi_tanaman === 'sakit' ? 'selected' : ''}>Sakit</option>
|
||||
<option value="mati" ${point.kondisi_tanaman === 'mati' ? 'selected' : ''}>Mati</option>
|
||||
</select>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<button type="button" class="btn btn-sm btn-icon btn-label-danger remove-point" data-index="${index}">
|
||||
<i class="ti tabler-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
`);
|
||||
|
||||
visibleNumber++;
|
||||
});
|
||||
}
|
||||
|
||||
function refreshPlantMarkers() {
|
||||
plantMarkers.forEach(marker => map.removeLayer(marker));
|
||||
plantMarkers = [];
|
||||
|
||||
const mode = getMarkerMode();
|
||||
let visibleIndex = 0;
|
||||
|
||||
plantPoints.forEach((point, index) => {
|
||||
if (point._delete) return;
|
||||
|
||||
const icon = mode === 'dot'
|
||||
? getDotIcon(point)
|
||||
: getPlantIcon(point);
|
||||
|
||||
const marker = L.marker([point.latitude, point.longitude], {
|
||||
icon: icon
|
||||
}).addTo(map)
|
||||
.bindPopup(buildPlantPopup(point, index, visibleIndex), {
|
||||
className: 'custom-plant-popup',
|
||||
closeButton: true,
|
||||
maxWidth: 280
|
||||
});
|
||||
|
||||
plantMarkers.push(marker);
|
||||
visibleIndex++;
|
||||
});
|
||||
}
|
||||
|
||||
function refreshField(name) {
|
||||
if (typeof fvEdit !== 'undefined' && name) {
|
||||
fvEdit.revalidateField(name);
|
||||
}
|
||||
}
|
||||
|
||||
function refreshAll() {
|
||||
renderPointsTable();
|
||||
refreshPlantMarkers();
|
||||
refreshField('points_validation');
|
||||
}
|
||||
|
||||
currentPolygon = renderLahanPolygon(lahanPath);
|
||||
|
||||
renderPointsTable();
|
||||
refreshPlantMarkers();
|
||||
|
||||
const activePoints = getActivePoints();
|
||||
|
||||
if (activePoints.length > 0) {
|
||||
const bounds = L.latLngBounds(
|
||||
activePoints
|
||||
.filter(point => point.latitude && point.longitude)
|
||||
.map(point => [point.latitude, point.longitude])
|
||||
);
|
||||
|
||||
if (bounds.isValid()) {
|
||||
map.fitBounds(bounds, { padding: [40, 40] });
|
||||
}
|
||||
}
|
||||
|
||||
map.on('click', function (e) {
|
||||
const lat = e.latlng.lat.toFixed(8);
|
||||
const lng = e.latlng.lng.toFixed(8);
|
||||
|
||||
plantPoints.push({
|
||||
id: '',
|
||||
nama: 'Titik Baru',
|
||||
latitude: lat,
|
||||
longitude: lng,
|
||||
kondisi_tanaman: 'sehat',
|
||||
_delete: false,
|
||||
_new: true,
|
||||
});
|
||||
|
||||
refreshAll();
|
||||
});
|
||||
|
||||
$(document).on('change', '.point-condition', function () {
|
||||
const index = $(this).data('index');
|
||||
const value = $(this).val();
|
||||
|
||||
if (plantPoints[index]) {
|
||||
plantPoints[index].kondisi_tanaman = value;
|
||||
}
|
||||
|
||||
refreshAll();
|
||||
});
|
||||
|
||||
$(document).on('change', '.popup-point-condition', function () {
|
||||
const index = $(this).data('index');
|
||||
const value = $(this).val();
|
||||
|
||||
if (plantPoints[index]) {
|
||||
plantPoints[index].kondisi_tanaman = value;
|
||||
}
|
||||
|
||||
map.closePopup();
|
||||
refreshAll();
|
||||
});
|
||||
|
||||
$(document).on('click', '.remove-point', function () {
|
||||
const index = $(this).data('index');
|
||||
|
||||
if (!plantPoints[index]) return;
|
||||
|
||||
if (plantPoints[index].id) {
|
||||
plantPoints[index]._delete = true;
|
||||
} else {
|
||||
plantPoints.splice(index, 1);
|
||||
}
|
||||
|
||||
refreshAll();
|
||||
});
|
||||
|
||||
$(document).on('click', '.popup-remove-point', function () {
|
||||
const index = $(this).data('index');
|
||||
|
||||
if (!plantPoints[index]) return;
|
||||
|
||||
Swal.fire({
|
||||
title: 'Hapus titik ini?',
|
||||
text: 'Titik tanaman akan dihapus setelah kamu klik Simpan Perubahan.',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Ya, hapus',
|
||||
cancelButtonText: 'Batal',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-primary me-3',
|
||||
cancelButton: 'btn btn-label-secondary'
|
||||
},
|
||||
buttonsStyling: false
|
||||
}).then(function (result) {
|
||||
if (!result.isConfirmed) return;
|
||||
|
||||
if (plantPoints[index].id) {
|
||||
plantPoints[index]._delete = true;
|
||||
} else {
|
||||
plantPoints.splice(index, 1);
|
||||
}
|
||||
|
||||
map.closePopup();
|
||||
refreshAll();
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('change', 'input[name="marker_mode"]', function () {
|
||||
refreshPlantMarkers();
|
||||
});
|
||||
|
||||
let fvEdit = FormValidation.formValidation(editForm, {
|
||||
fields: {
|
||||
points_validation: {
|
||||
validators: {
|
||||
callback: {
|
||||
message: 'Minimal harus ada satu titik tanaman aktif.',
|
||||
callback: function () {
|
||||
return getActivePoints().length > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
eleValidClass: '',
|
||||
rowSelector: '.form-control-validation'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
}
|
||||
}).on('core.form.valid', function () {
|
||||
const formData = $(editForm).serialize();
|
||||
const $button = $(editForm).find('button[type="submit"]');
|
||||
|
||||
$button.prop('disabled', true)
|
||||
.html('<span class="spinner-border spinner-border-sm me-1"></span>Menyimpan...');
|
||||
|
||||
$.ajax({
|
||||
url: editForm.action,
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
success: function (res) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Berhasil!',
|
||||
text: res.message || 'Data titik tanaman berhasil diperbarui.',
|
||||
timer: 1500,
|
||||
showConfirmButton: false
|
||||
}).then(() => {
|
||||
window.location.href = res.redirect || "{{ route('map-tanaman.index') }}";
|
||||
});
|
||||
},
|
||||
error: function (xhr) {
|
||||
showError(xhr, 'Gagal memperbarui data tanaman.');
|
||||
},
|
||||
complete: function () {
|
||||
$button.prop('disabled', false).html('Simpan Perubahan');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
setTimeout(() => map.invalidateSize(), 300);
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,230 @@
|
||||
@extends('layout.main')
|
||||
|
||||
@section('content')
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="card">
|
||||
<div class="card-body border-bottom">
|
||||
<form method="GET" action="{{ route('tanaman.index') }}" class="d-flex justify-content-between align-items-center row gap-3 gap-md-0">
|
||||
<div class="col-md-auto">
|
||||
<div class="d-flex align-items-center">
|
||||
<label class="me-2 text-nowrap">Show</label>
|
||||
<select name="per_page" class="form-select form-select-sm w-auto" onchange="this.form.submit()">
|
||||
@foreach([10, 25, 50, 100] as $limit)
|
||||
<option value="{{ $limit }}" {{ request('per_page', 10) == $limit ? 'selected' : '' }}>
|
||||
{{ $limit }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<label class="ms-2 text-nowrap">entries</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-auto d-flex gap-2">
|
||||
<div class="input-group input-group-sm w-auto">
|
||||
<input type="text" name="search" class="form-control" placeholder="Cari tanaman..." value="{{ request('search') }}">
|
||||
|
||||
@if(request('search'))
|
||||
<a href="{{ route('tanaman.index', ['per_page' => request('per_page', 10)]) }}" class="btn btn-outline-secondary">
|
||||
<i class="ti tabler-x"></i>
|
||||
</a>
|
||||
@endif
|
||||
|
||||
<button type="submit" class="btn btn-outline-primary">
|
||||
<i class="ti tabler-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<a href="{{ route('map-tanaman.create') }}" class="btn btn-sm btn-primary">
|
||||
<i class="ti tabler-plus me-1"></i> Tambah
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive text-nowrap">
|
||||
<table class="table table-hover">
|
||||
<thead class="border-top">
|
||||
<tr>
|
||||
<th>No</th>
|
||||
<th>Kelompok Tanaman</th>
|
||||
<th>Pemilik</th>
|
||||
<th>Lahan</th>
|
||||
<th>Wilayah</th>
|
||||
<th>Varietas</th>
|
||||
<th>Jumlah Titik</th>
|
||||
<th>Kondisi</th>
|
||||
<th class="text-center">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@forelse($tanaman as $index => $item)
|
||||
@php
|
||||
$states = ['success', 'danger', 'warning', 'info', 'primary', 'secondary'];
|
||||
$state = $states[$item->id % count($states)];
|
||||
|
||||
$groupName = ($item->komoditas->nama ?? 'Tanaman') . ' - ' . ($item->profile->nama ?? 'Pemilik');
|
||||
@endphp
|
||||
|
||||
<tr>
|
||||
<td>{{ $tanaman->firstItem() + $index }}</td>
|
||||
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="avatar-wrapper me-3">
|
||||
<div class="avatar avatar-sm">
|
||||
<span class="avatar-initial rounded-circle bg-label-{{ $state }}">
|
||||
{{ strtoupper(substr($item->komoditas->nama ?? 'TN', 0, 2)) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column">
|
||||
<span class="fw-medium text-heading">{{ $groupName }}</span>
|
||||
<small class="text-muted">
|
||||
{{ $item->jenisKomoditas->nama ?? '-' }}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>{{ $item->profile->nama ?? '-' }}</td>
|
||||
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<span>{{ $item->lahan->nama ?? '-' }}</span>
|
||||
<small class="text-muted">{{ $item->lahan->uid ?? '-' }}</small>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<small>
|
||||
{{ $item->lahan->desaKelurahan->nama ?? '-' }}<br>
|
||||
<span class="text-muted">
|
||||
{{ $item->lahan->desaKelurahan->kecamatan->nama ?? '-' }}
|
||||
</span>
|
||||
</small>
|
||||
</td>
|
||||
|
||||
<td>{{ $item->varietas->nama ?? '-' }}</td>
|
||||
|
||||
<td>
|
||||
<span class="badge bg-label-primary">
|
||||
{{ $item->total_tanaman }} titik
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<div class="d-flex flex-column gap-1">
|
||||
<span class="badge bg-label-success">
|
||||
Sehat: {{ $item->total_sehat ?? 0 }}
|
||||
</span>
|
||||
<span class="badge bg-label-danger">
|
||||
Sakit: {{ $item->total_sakit ?? 0 }}
|
||||
</span>
|
||||
<span class="badge bg-label-dark">
|
||||
Mati: {{ $item->total_mati ?? 0 }}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<div class="d-flex justify-content-center align-items-center">
|
||||
<a href="{{ route('map-tanaman.show', $item->id) }}"
|
||||
class="btn btn-icon btn-text-secondary rounded-pill"
|
||||
title="Lihat">
|
||||
<i class="ti tabler-eye ti-md"></i>
|
||||
</a>
|
||||
|
||||
<a href="{{ route('map-tanaman.edit', $item->id) }}"
|
||||
class="btn btn-icon btn-text-secondary rounded-pill"
|
||||
title="Edit">
|
||||
<i class="ti tabler-edit ti-md"></i>
|
||||
</a>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-icon btn-text-secondary rounded-pill delete-group"
|
||||
data-id="{{ $item->id }}"
|
||||
data-nama="{{ $groupName }}"
|
||||
title="Hapus">
|
||||
<i class="ti tabler-trash ti-md"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="9" class="text-center py-4">
|
||||
Tidak ada data ditemukan.
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@if($tanaman->hasPages())
|
||||
<div class="card-footer d-flex justify-content-center justify-content-md-end border-top">
|
||||
{{ $tanaman->appends(request()->query())->links('pagination::bootstrap-5') }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
$(function () {
|
||||
$.ajaxSetup({
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': "{{ csrf_token() }}"
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click', '.delete-group', function () {
|
||||
const id = $(this).data('id');
|
||||
const nama = $(this).data('nama');
|
||||
|
||||
Swal.fire({
|
||||
title: 'Apakah Anda yakin?',
|
||||
text: `Semua titik tanaman pada kelompok "${nama}" akan dihapus.`,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Ya, Hapus!',
|
||||
cancelButtonText: 'Batal',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-primary me-3',
|
||||
cancelButton: 'btn btn-label-secondary'
|
||||
},
|
||||
buttonsStyling: false
|
||||
}).then(function (result) {
|
||||
if (!result.isConfirmed) return;
|
||||
|
||||
$.ajax({
|
||||
url: `/map-tanaman/${id}`,
|
||||
type: 'DELETE',
|
||||
success: function (res) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Terhapus!',
|
||||
text: res.message || 'Data berhasil dihapus.',
|
||||
showConfirmButton: false,
|
||||
timer: 1500
|
||||
}).then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Gagal!',
|
||||
text: xhr.responseJSON?.message || 'Gagal menghapus data.'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,698 @@
|
||||
@extends('layout.main')
|
||||
|
||||
@push('style')
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
||||
|
||||
<style>
|
||||
#map {
|
||||
height: 560px;
|
||||
width: 100%;
|
||||
background-color: var(--bs-body-bg);
|
||||
z-index: 1;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
font-size: 0.8125rem;
|
||||
color: var(--bs-secondary-color);
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
font-weight: 500;
|
||||
color: var(--bs-heading-color);
|
||||
margin-bottom: 1rem;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.detail-section {
|
||||
padding-bottom: .75rem;
|
||||
margin-bottom: .75rem;
|
||||
border-bottom: 1px solid var(--bs-border-color);
|
||||
}
|
||||
|
||||
.detail-section:last-child {
|
||||
border-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.map-note {
|
||||
background-color: rgba(var(--bs-info-rgb), 0.16);
|
||||
color: var(--bs-info);
|
||||
border: 1px solid rgba(var(--bs-info-rgb), 0.25);
|
||||
}
|
||||
|
||||
.points-table-wrapper {
|
||||
max-height: 280px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.leaflet-popup-content {
|
||||
color: #2f2b3d;
|
||||
}
|
||||
|
||||
.plant-marker-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
background: rgba(var(--bs-success-rgb), 0.95);
|
||||
border: 2px solid #fff;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.plant-marker-icon.sakit {
|
||||
background: rgba(var(--bs-danger-rgb), 0.95);
|
||||
}
|
||||
|
||||
.plant-marker-icon.mati {
|
||||
background: rgba(var(--bs-dark-rgb), 0.95);
|
||||
}
|
||||
|
||||
.plant-dot-marker {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
border-radius: 50%;
|
||||
background: rgba(var(--bs-success-rgb), 0.95);
|
||||
border: 2px solid #fff;
|
||||
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
.plant-dot-marker.sakit {
|
||||
background: rgba(var(--bs-danger-rgb), 0.95);
|
||||
}
|
||||
|
||||
.plant-dot-marker.mati {
|
||||
background: rgba(var(--bs-dark-rgb), 0.95);
|
||||
}
|
||||
|
||||
.custom-plant-popup .leaflet-popup-content-wrapper {
|
||||
border-radius: 14px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background: var(--bs-card-bg);
|
||||
color: var(--bs-body-color);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28);
|
||||
}
|
||||
|
||||
.custom-plant-popup .leaflet-popup-content {
|
||||
margin: 0;
|
||||
min-width: 220px;
|
||||
}
|
||||
|
||||
.custom-plant-popup .leaflet-popup-tip {
|
||||
background: var(--bs-card-bg);
|
||||
}
|
||||
|
||||
.plant-popup-card {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.plant-popup-header {
|
||||
padding: 10px 12px;
|
||||
background: rgba(var(--bs-primary-rgb), 0.14);
|
||||
border-bottom: 1px solid var(--bs-border-color);
|
||||
}
|
||||
|
||||
.plant-popup-title {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
color: var(--bs-heading-color);
|
||||
margin: 0;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.plant-popup-subtitle {
|
||||
font-size: 0.75rem;
|
||||
color: var(--bs-secondary-color);
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.plant-popup-body {
|
||||
padding: 10px 12px 12px;
|
||||
}
|
||||
|
||||
.plant-popup-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
font-size: 0.75rem;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.plant-popup-row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.plant-popup-label {
|
||||
color: var(--bs-secondary-color);
|
||||
}
|
||||
|
||||
.plant-popup-value {
|
||||
color: var(--bs-heading-color);
|
||||
font-weight: 500;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.plant-popup-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 3px 8px;
|
||||
border-radius: 999px;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.plant-popup-badge.sehat {
|
||||
background: rgba(var(--bs-success-rgb), 0.16);
|
||||
color: var(--bs-success);
|
||||
}
|
||||
|
||||
.plant-popup-badge.sakit {
|
||||
background: rgba(var(--bs-danger-rgb), 0.16);
|
||||
color: var(--bs-danger);
|
||||
}
|
||||
|
||||
.plant-popup-badge.mati {
|
||||
background: rgba(var(--bs-dark-rgb), 0.16);
|
||||
color: var(--bs-dark);
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
@php
|
||||
$totalTanaman = $points->count();
|
||||
|
||||
$totalSehat = $points->filter(function ($point) {
|
||||
$kondisi = $point->kondisi_tanaman;
|
||||
$value = is_object($kondisi) && property_exists($kondisi, 'value') ? $kondisi->value : $kondisi;
|
||||
return $value === 'sehat';
|
||||
})->count();
|
||||
|
||||
$totalSakit = $points->filter(function ($point) {
|
||||
$kondisi = $point->kondisi_tanaman;
|
||||
$value = is_object($kondisi) && property_exists($kondisi, 'value') ? $kondisi->value : $kondisi;
|
||||
return $value === 'sakit';
|
||||
})->count();
|
||||
|
||||
$totalMati = $points->filter(function ($point) {
|
||||
$kondisi = $point->kondisi_tanaman;
|
||||
$value = is_object($kondisi) && property_exists($kondisi, 'value') ? $kondisi->value : $kondisi;
|
||||
return $value === 'mati';
|
||||
})->count();
|
||||
|
||||
$groupName = ($tanaman->komoditas->nama ?? 'Tanaman') . ' - ' . ($tanaman->profile->nama ?? 'Pemilik');
|
||||
@endphp
|
||||
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<div>
|
||||
<h4 class="mb-1">Detail Kelompok Tanaman</h4>
|
||||
<small class="text-muted">{{ $groupName }}</small>
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<a href="{{ route('map-tanaman.index') }}" class="btn btn-label-secondary">
|
||||
<i class="ti tabler-arrow-left me-1"></i> Kembali
|
||||
</a>
|
||||
|
||||
<a href="{{ route('map-tanaman.edit', $tanaman->id) }}" class="btn btn-primary">
|
||||
<i class="ti tabler-edit me-1"></i> Edit
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
{{-- DETAIL DATA --}}
|
||||
<div class="col-lg-5 mb-4">
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header border-bottom">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="ti tabler-seeding me-1"></i> Ringkasan Kelompok
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-4">
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">Kelompok Tanaman</div>
|
||||
<div class="detail-value">{{ $groupName }}</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">Jumlah Titik Tanaman</div>
|
||||
<div class="detail-value">
|
||||
<span class="badge bg-label-primary">{{ $totalTanaman }} titik</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">Ringkasan Kondisi</div>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<span class="badge bg-label-success">Sehat: {{ $totalSehat }}</span>
|
||||
<span class="badge bg-label-danger">Sakit: {{ $totalSakit }}</span>
|
||||
<span class="badge bg-label-dark">Mati: {{ $totalMati }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">Deskripsi</div>
|
||||
<div class="detail-value">{{ $tanaman->deskripsi ?? '-' }}</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">Metode Pengumpulan</div>
|
||||
<div class="detail-value">{{ $tanaman->metode_pengumpulan ?? '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header border-bottom">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="ti tabler-user-pin me-1"></i> Pemilik & Lahan
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-4">
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">Pemilik/Pengelola</div>
|
||||
<div class="detail-value">{{ $tanaman->profile->nama ?? '-' }}</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">Lahan</div>
|
||||
<div class="detail-value">{{ $tanaman->lahan->nama ?? '-' }}</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">UID Lahan</div>
|
||||
<div class="detail-value">{{ $tanaman->lahan->uid ?? '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header border-bottom">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="ti tabler-map-pin me-1"></i> Wilayah
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-4">
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">Provinsi</div>
|
||||
<div class="detail-value">
|
||||
{{ $tanaman->lahan->desaKelurahan->kecamatan->kabupatenkota->provinsi->nama ?? '-' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">Kabupaten/Kota</div>
|
||||
<div class="detail-value">
|
||||
{{ $tanaman->lahan->desaKelurahan->kecamatan->kabupatenkota->nama ?? '-' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">Kecamatan</div>
|
||||
<div class="detail-value">
|
||||
{{ $tanaman->lahan->desaKelurahan->kecamatan->nama ?? '-' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">Desa/Kelurahan</div>
|
||||
<div class="detail-value">
|
||||
{{ $tanaman->lahan->desaKelurahan->nama ?? '-' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header border-bottom">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="ti tabler-leaf me-1"></i> Komoditas
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-4">
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">Komoditas</div>
|
||||
<div class="detail-value">{{ $tanaman->komoditas->nama ?? '-' }}</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">Jenis Komoditas</div>
|
||||
<div class="detail-value">{{ $tanaman->jenisKomoditas->nama ?? '-' }}</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-label">Varietas</div>
|
||||
<div class="detail-value">{{ $tanaman->varietas->nama ?? '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- MAP --}}
|
||||
<div class="col-lg-7 mb-4">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header border-bottom d-flex justify-content-between align-items-center">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="ti tabler-map-pin me-1"></i> Lokasi Semua Titik Tanaman
|
||||
</h5>
|
||||
|
||||
<div class="btn-group" role="group" aria-label="Marker Mode">
|
||||
<input type="radio" class="btn-check" name="marker_mode" id="marker-mode-plant" value="plant" checked>
|
||||
<label class="btn btn-sm btn-outline-primary" for="marker-mode-plant">
|
||||
<i class="ti tabler-plant-2 me-1"></i> Ikon
|
||||
</label>
|
||||
|
||||
<input type="radio" class="btn-check" name="marker_mode" id="marker-mode-dot" value="dot">
|
||||
<label class="btn btn-sm btn-outline-primary" for="marker-mode-dot">
|
||||
<i class="ti tabler-point me-1"></i> Titik
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-4">
|
||||
<div id="map"></div>
|
||||
|
||||
<div class="alert map-note mt-3 mb-0">
|
||||
<i class="ti tabler-info-circle me-1"></i>
|
||||
Area hijau menunjukkan polygon lahan. Marker menunjukkan seluruh titik tanaman dalam kelompok ini.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header border-bottom">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="ti tabler-list-details me-1"></i> Daftar Titik Tanaman
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-4">
|
||||
<div class="points-table-wrapper border rounded">
|
||||
<table class="table table-sm table-hover mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50px;">No</th>
|
||||
<th>Nama</th>
|
||||
<th>Latitude</th>
|
||||
<th>Longitude</th>
|
||||
<th>Kondisi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($points as $index => $point)
|
||||
@php
|
||||
$kondisi = $point->kondisi_tanaman;
|
||||
$kondisiValue = is_object($kondisi) && property_exists($kondisi, 'value')
|
||||
? $kondisi->value
|
||||
: $kondisi;
|
||||
|
||||
$conditionClass = match($kondisiValue) {
|
||||
'sehat' => 'success',
|
||||
'sakit' => 'danger',
|
||||
'mati' => 'dark',
|
||||
default => 'secondary',
|
||||
};
|
||||
@endphp
|
||||
<tr>
|
||||
<td>{{ $index + 1 }}</td>
|
||||
<td>
|
||||
<div class="fw-medium">{{ $point->nama ?? '-' }}</div>
|
||||
<small class="text-muted">{{ $point->uid ?? '-' }}</small>
|
||||
</td>
|
||||
<td>{{ $point->latitude ?? '-' }}</td>
|
||||
<td>{{ $point->longitude ?? '-' }}</td>
|
||||
<td>
|
||||
<span class="badge bg-label-{{ $conditionClass }}">
|
||||
{{ $kondisiValue ? ucfirst(str_replace('_', ' ', $kondisiValue)) : '-' }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="5" class="text-center text-muted py-4">
|
||||
Belum ada titik tanaman.
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
$(document).ready(function () {
|
||||
const lahanPath = {{ Illuminate\Support\Js::from($tanaman->lahan->path ?? null) }};
|
||||
|
||||
const points = {{ Illuminate\Support\Js::from(
|
||||
$points->map(function ($point) {
|
||||
$kondisi = $point->kondisi_tanaman;
|
||||
$kondisiValue = is_object($kondisi) && property_exists($kondisi, 'value')
|
||||
? $kondisi->value
|
||||
: $kondisi;
|
||||
|
||||
return [
|
||||
'id' => $point->id,
|
||||
'uid' => $point->uid,
|
||||
'nama' => $point->nama,
|
||||
'latitude' => $point->latitude,
|
||||
'longitude' => $point->longitude,
|
||||
'kondisi_tanaman' => $kondisiValue,
|
||||
];
|
||||
})->values()
|
||||
) }};
|
||||
|
||||
const map = L.map('map').setView([-2.5489, 118.0149], 5);
|
||||
|
||||
L.tileLayer('https://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', {
|
||||
maxZoom: 22,
|
||||
subdomains: ['mt0', 'mt1', 'mt2', 'mt3'],
|
||||
attribution: '© Google Maps Satellite'
|
||||
}).addTo(map);
|
||||
|
||||
let pointMarkers = [];
|
||||
|
||||
function parsePath(path) {
|
||||
if (!path) return null;
|
||||
|
||||
let parsed = path;
|
||||
|
||||
if (typeof path === 'string') {
|
||||
try {
|
||||
parsed = JSON.parse(path);
|
||||
} catch (error) {
|
||||
console.error('Path bukan JSON valid:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (parsed.type && parsed.coordinates) {
|
||||
return {
|
||||
type: 'geojson',
|
||||
data: parsed
|
||||
};
|
||||
}
|
||||
|
||||
if (Array.isArray(parsed)) {
|
||||
return {
|
||||
type: 'array',
|
||||
data: parsed
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function renderLahanPolygon(path) {
|
||||
const parsed = parsePath(path);
|
||||
|
||||
if (!parsed) {
|
||||
console.warn('Format koordinat lahan tidak valid atau kosong.');
|
||||
return null;
|
||||
}
|
||||
|
||||
let layer = null;
|
||||
|
||||
if (parsed.type === 'geojson') {
|
||||
layer = L.geoJSON(parsed.data, {
|
||||
style: {
|
||||
color: '#28c76f',
|
||||
fillColor: '#28c76f',
|
||||
fillOpacity: 0.35,
|
||||
weight: 2
|
||||
}
|
||||
}).addTo(map);
|
||||
|
||||
map.fitBounds(layer.getBounds(), { padding: [30, 30] });
|
||||
}
|
||||
|
||||
if (parsed.type === 'array') {
|
||||
const latLngs = parsed.data.map(coord => [coord[1], coord[0]]);
|
||||
|
||||
layer = L.polygon(latLngs, {
|
||||
color: '#28c76f',
|
||||
fillColor: '#28c76f',
|
||||
fillOpacity: 0.35,
|
||||
weight: 2
|
||||
}).addTo(map);
|
||||
|
||||
map.fitBounds(layer.getBounds(), { padding: [30, 30] });
|
||||
}
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
function getMarkerMode() {
|
||||
return $('input[name="marker_mode"]:checked').val() || 'plant';
|
||||
}
|
||||
|
||||
function getPlantIcon(point) {
|
||||
const kondisi = point.kondisi_tanaman || 'sehat';
|
||||
|
||||
return L.divIcon({
|
||||
className: '',
|
||||
html: `
|
||||
<div class="plant-marker-icon ${kondisi}">
|
||||
<i class="ti tabler-plant-2"></i>
|
||||
</div>
|
||||
`,
|
||||
iconSize: [32, 32],
|
||||
iconAnchor: [16, 16],
|
||||
popupAnchor: [0, -16]
|
||||
});
|
||||
}
|
||||
|
||||
function getDotIcon(point) {
|
||||
const kondisi = point.kondisi_tanaman || 'sehat';
|
||||
|
||||
return L.divIcon({
|
||||
className: '',
|
||||
html: `<div class="plant-dot-marker ${kondisi}"></div>`,
|
||||
iconSize: [11, 11],
|
||||
iconAnchor: [5.5, 5.5],
|
||||
popupAnchor: [0, -8]
|
||||
});
|
||||
}
|
||||
|
||||
function formatKondisiLabel(kondisi) {
|
||||
const labels = {
|
||||
sehat: 'Sehat',
|
||||
sakit: 'Sakit',
|
||||
mati: 'Mati'
|
||||
};
|
||||
|
||||
return labels[kondisi] || '-';
|
||||
}
|
||||
|
||||
function renderPointMarkers() {
|
||||
pointMarkers.forEach(marker => map.removeLayer(marker));
|
||||
pointMarkers = [];
|
||||
|
||||
const mode = getMarkerMode();
|
||||
|
||||
points.forEach((point, index) => {
|
||||
if (!point.latitude || !point.longitude) return;
|
||||
|
||||
const icon = mode === 'dot'
|
||||
? getDotIcon(point)
|
||||
: getPlantIcon(point);
|
||||
|
||||
const popupContent = `
|
||||
<div class="plant-popup-card">
|
||||
<div class="plant-popup-header">
|
||||
<p class="plant-popup-title">
|
||||
${point.nama || 'Titik Tanaman ' + (index + 1)}
|
||||
</p>
|
||||
<div class="plant-popup-subtitle">
|
||||
Titik Tanaman ${index + 1}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="plant-popup-body">
|
||||
<div class="plant-popup-row">
|
||||
<span class="plant-popup-label">Latitude</span>
|
||||
<span class="plant-popup-value">${point.latitude}</span>
|
||||
</div>
|
||||
|
||||
<div class="plant-popup-row">
|
||||
<span class="plant-popup-label">Longitude</span>
|
||||
<span class="plant-popup-value">${point.longitude}</span>
|
||||
</div>
|
||||
|
||||
<div class="plant-popup-row">
|
||||
<span class="plant-popup-label">Kondisi</span>
|
||||
<span class="plant-popup-value">
|
||||
<span class="plant-popup-badge ${point.kondisi_tanaman || 'sehat'}">
|
||||
${formatKondisiLabel(point.kondisi_tanaman)}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const marker = L.marker([point.latitude, point.longitude], {
|
||||
icon: icon
|
||||
}).addTo(map)
|
||||
.bindPopup(popupContent, {
|
||||
className: 'custom-plant-popup',
|
||||
closeButton: true,
|
||||
maxWidth: 260
|
||||
});
|
||||
|
||||
pointMarkers.push(marker);
|
||||
});
|
||||
}
|
||||
|
||||
const lahanLayer = renderLahanPolygon(lahanPath);
|
||||
|
||||
renderPointMarkers();
|
||||
|
||||
if (points.length > 0) {
|
||||
const bounds = L.latLngBounds(
|
||||
points
|
||||
.filter(point => point.latitude && point.longitude)
|
||||
.map(point => [point.latitude, point.longitude])
|
||||
);
|
||||
|
||||
if (bounds.isValid()) {
|
||||
map.fitBounds(bounds, { padding: [40, 40] });
|
||||
}
|
||||
} else if (lahanLayer) {
|
||||
map.fitBounds(lahanLayer.getBounds(), { padding: [30, 30] });
|
||||
}
|
||||
|
||||
$(document).on('change', 'input[name="marker_mode"]', function () {
|
||||
renderPointMarkers();
|
||||
});
|
||||
|
||||
setTimeout(function () {
|
||||
map.invalidateSize();
|
||||
}, 300);
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
+11
-8
@@ -12,10 +12,12 @@
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="add-new-aktivitas pt-0" id="addNewAktivitasForm" action="{{ route('framework.transformasi.aktivitas.store', [$framework->id, ':transformasiId']) }}" method="POST">
|
||||
<form class="pt-0" id="addNewAktivitasForm" action="{{ route('framework.transformasi.aktivitas.store', [$framework->id, ':transformasiId']) }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" id="add-aktivitas-transformasi-id" name="transformasi_id"/>
|
||||
<input type="hidden" id="add-aktivitas-jenis" name="jenis_aktivitas" value="aktivitas"/>
|
||||
<input type="hidden" id="add-aktivitas-parent_id" name="parent_id"/>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-aktivitas-kode">Kode<span class="text-danger">*</span></label>
|
||||
@@ -25,13 +27,6 @@
|
||||
<label class="form-label" for="add-aktivitas-nama">Aktivitas<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="add-aktivitas-nama" name="nama" placeholder="Cth: Aktivitas" />
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-aktivitas-jenis">Jenis Aktivitas<span class="text-danger">*</span></label>
|
||||
<select class="form-select" id="add-aktivitas-jenis" name="jenis_aktivitas">
|
||||
<option value="tujuan">Tujuan Jangka Pendek</option>
|
||||
<option value="aktivitas">Aktivitas</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-aktivitas-indikator">Indikator<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="add-aktivitas-indikator" name="indikator" placeholder="Cth: Indikator" />
|
||||
@@ -54,7 +49,15 @@
|
||||
$(".add-aktivitas").click(function () {
|
||||
const id = $(this).data('id');
|
||||
console.log('Add aktivitas, transformasi id: ' + id);
|
||||
const parentId = $(this).data('parent-id');
|
||||
$('#add-aktivitas-transformasi-id').val(id);
|
||||
console.log('Add aktivitas, parent id: ' + parentId);
|
||||
$('#add-aktivitas-parent_id').val(parentId);
|
||||
|
||||
const addForm = $('#addNewAktivitasForm');
|
||||
addForm.validate().resetForm();
|
||||
addForm.find('.is-invalid').removeClass('is-invalid');
|
||||
|
||||
offcanvasAddAktivitas.show();
|
||||
});
|
||||
$('#addNewAktivitasForm').validate({
|
||||
@@ -0,0 +1,106 @@
|
||||
<div
|
||||
class="offcanvas offcanvas-end"
|
||||
tabindex="-1"
|
||||
id="offcanvasAddTujuan"
|
||||
aria-labelledby="offcanvasAddTujuanLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasAddTujuanLabel" class="offcanvas-title">Tambah Tujuan</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close text-reset"
|
||||
data-bs-dismiss="offcanvas"
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="pt-0" id="addNewTujuanForm" action="{{ route('framework.transformasi.aktivitas.store', [$framework->id, ':transformasiId']) }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" id="add-tujuan-transformasi-id" name="transformasi_id"/>
|
||||
<input type="hidden" id="add-tujuan-jenis" name="jenis_aktivitas" value="tujuan"/>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-tujuan-kode">Kode<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="add-tujuan-kode" name="kode" placeholder="Cth: AK1" />
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-tujuan-nama">Tujuan Jangka Pendek<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="add-tujuan-nama" name="nama" placeholder="Cth: Tujuan Jangka Pendek" />
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-tujuan-indikator">Indikator<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="add-tujuan-indikator" name="indikator" placeholder="Cth: Indikator" />
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-tujuan-deskripsi">Deskripsi<span class="text-danger">*</span></label>
|
||||
<textarea class="form-control" id="add-tujuan-deskripsi" name="deskripsi" placeholder="Cth: Deskripsi"></textarea>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success me-3 data-submit">Simpan</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Batal</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
const offcanvasAddTujuan = new bootstrap.Offcanvas(document.getElementById('offcanvasAddTujuan'));
|
||||
$(".add-tujuan").click(function () {
|
||||
const id = $(this).data('id');
|
||||
console.log('Add tujuan, transformasi id: ' + id);
|
||||
$('#add-aktivitas-transformasi-id').val(id);
|
||||
|
||||
const addForm = $('#addNewTujuanForm');
|
||||
addForm.validate().resetForm();
|
||||
addForm.find('.is-invalid').removeClass('is-invalid');
|
||||
|
||||
// $.get("{{ route('framework.transformasi.show', [$framework->id, ':id']) }}".replace(':id', id), function (res) {
|
||||
// if (res.status === 'success') {
|
||||
// for(let i = 0; i < res.data.aktivitas.length; i++) {
|
||||
// $('#add-aktivitas-parent_id').append(`<option value="${res.data.aktivitas[i].id}">${res.data.aktivitas[i].nama}</option>`);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
offcanvasAddTujuan.show();
|
||||
});
|
||||
$('#addNewTujuanForm').validate({
|
||||
rules: {
|
||||
kode: { required: true },
|
||||
nama: { required: true }
|
||||
},
|
||||
messages: {
|
||||
kode: { required: "Kode tujuan wajib diisi" },
|
||||
nama: { required: "Tujuan wajib diisi" }
|
||||
},
|
||||
submitHandler: function (form) {
|
||||
$.ajax({
|
||||
url: $(form).attr('action').replace(':transformasiId', $('#add-aktivitas-transformasi-id').val()),
|
||||
type: 'POST',
|
||||
data: $(form).serialize(),
|
||||
success: function () {
|
||||
offcanvasAddTujuan.hide();
|
||||
form.reset();
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.mb-6, .form-control-validation').append(error);
|
||||
},
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
+3
-7
@@ -18,6 +18,8 @@
|
||||
|
||||
<input type="hidden" id="update-aktivitas-transformasi-id" name="transformasi_id"/>
|
||||
<input type="hidden" id="update-aktivitas-id" name="id"/>
|
||||
<input type="hidden" id="update-aktivitas-jenis" name="jenis_aktivitas" value="aktivitas"/>
|
||||
<input type="hidden" id="update-aktivitas-parent_id" name="parent_id"/>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="update-aktivitas-kode">Kode<span class="text-danger">*</span></label>
|
||||
@@ -27,13 +29,6 @@
|
||||
<label class="form-label" for="update-aktivitas-nama">Aktivitas<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="update-aktivitas-nama" name="nama" placeholder="Cth: Aktivitas" />
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="update-aktivitas-jenis">Jenis Aktivitas<span class="text-danger">*</span></label>
|
||||
<select class="form-select" id="update-aktivitas-jenis" name="jenis_aktivitas">
|
||||
<option value="tujuan">Tujuan Jangka Pendek</option>
|
||||
<option value="aktivitas">Aktivitas</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="update-aktivitas-indikator">Indikator<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="update-aktivitas-indikator" name="indikator" placeholder="Cth: Indikator" />
|
||||
@@ -72,6 +67,7 @@
|
||||
$('#update-aktivitas-jenis').val(res.data.jenis_aktivitas);
|
||||
$('#update-aktivitas-indikator').val(res.data.indikator);
|
||||
$('#update-aktivitas-deskripsi').val(res.data.deskripsi);
|
||||
$('#update-aktivitas-parent_id').val(res.data.parent_id);
|
||||
offcanvasUpdateAktivitas.show();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,112 @@
|
||||
<div
|
||||
class="offcanvas offcanvas-end"
|
||||
tabindex="-1"
|
||||
id="offcanvasUpdateTujuan"
|
||||
aria-labelledby="offcanvasUpdateTujuanLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasUpdateTujuanLabel" class="offcanvas-title">Update Tujuan</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close text-reset"
|
||||
data-bs-dismiss="offcanvas"
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="pt-0" id="updateTujuanForm" action="{{ route('framework.transformasi.aktivitas.update', [$framework->id, ':transformasiId', ':id']) }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<input type="hidden" id="update-tujuan-transformasi-id" name="transformasi_id"/>
|
||||
<input type="hidden" id="update-tujuan-id" name="id"/>
|
||||
<input type="hidden" id="update-tujuan-jenis" name="jenis_aktivitas" value="tujuan"/>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="update-tujuan-kode">Kode<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="update-tujuan-kode" name="kode" placeholder="Cth: AK1" />
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="update-tujuan-nama">Aktivitas<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="update-tujuan-nama" name="nama" placeholder="Cth: Aktivitas" />
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="update-tujuan-indikator">Indikator<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="update-tujuan-indikator" name="indikator" placeholder="Cth: Indikator" />
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="update-tujuan-deskripsi">Deskripsi<span class="text-danger">*</span></label>
|
||||
<textarea class="form-control" id="update-tujuan-deskripsi" name="deskripsi" placeholder="Cth: Deskripsi"></textarea>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success me-3 data-submit">Simpan</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Batal</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
const offcanvasUpdateTujuan = new bootstrap.Offcanvas(document.getElementById('offcanvasUpdateTujuan'));
|
||||
$(".edit-tujuan").click(function () {
|
||||
const id = $(this).data('id');
|
||||
const transformasiId = $(this).data('transformasi-id');
|
||||
console.log('Update aktivitas, aktivitas id: ' + id + ', transformasi id: ' + transformasiId);
|
||||
$('#update-tujuan-id').val(id);
|
||||
$('#update-tujuan-transformasi-id').val(transformasiId);
|
||||
|
||||
const editForm = $('#updateTujuanForm');
|
||||
editForm.validate().resetForm();
|
||||
editForm.find('.is-invalid').removeClass('is-invalid');
|
||||
|
||||
$.get("{{ route('framework.transformasi.aktivitas.show', [$framework->id, ':transformasiId', ':id']) }}"
|
||||
.replace(':transformasiId', transformasiId).replace(':id', id), function (res) {
|
||||
if (res.status === 'success') {
|
||||
$('#update-tujuan-kode').val(res.data.kode);
|
||||
$('#update-tujuan-nama').val(res.data.nama);
|
||||
$('#update-tujuan-jenis').val(res.data.jenis_aktivitas);
|
||||
$('#update-tujuan-indikator').val(res.data.indikator);
|
||||
$('#update-tujuan-deskripsi').val(res.data.deskripsi);
|
||||
offcanvasUpdateTujuan.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
$('#updateTujuanForm').validate({
|
||||
rules: {
|
||||
kode: { required: true },
|
||||
nama: { required: true }
|
||||
},
|
||||
messages: {
|
||||
kode: { required: "Kode tujuan wajib diisi" },
|
||||
nama: { required: "Tujuan wajib diisi" }
|
||||
},
|
||||
submitHandler: function (form) {
|
||||
$.ajax({
|
||||
url: $(form).attr('action').replace(':transformasiId', $('#update-tujuan-transformasi-id').val()).replace(':id', $('#update-tujuan-id').val()),
|
||||
type: 'POST',
|
||||
data: $(form).serialize(),
|
||||
success: function () {
|
||||
offcanvasUpdateTujuan.hide();
|
||||
form.reset();
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.mb-6, .form-control-validation').append(error);
|
||||
},
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,74 @@
|
||||
@forelse($tujuan->aktivitas as $aktivitas)
|
||||
@forelse($aktivitas->target as $targetAktivitas)
|
||||
<tr>
|
||||
<td><span class="text-heading">{{ $transformasi->kode }} {{ $transformasi->nama }} (ID: {{ $transformasi->id }})</span></td>
|
||||
<td><span class="{{ $aktivitas->jenis_aktivitas == 'tujuan' ? 'text-heading' : 'text-muted' }}">{{ $aktivitas->kode }} {{ $aktivitas->nama }} (ID: {{ $aktivitas->id }})</span></td>
|
||||
<td><span class="text-muted">{{ $aktivitas->deskripsi }}</span></td>
|
||||
<td><span class="text-muted">{{ $aktivitas->indikator }}</span></td>
|
||||
<td><span class="text-muted">{{ $targetAktivitas->variabel }} (ID: {{ $targetAktivitas->id }}, Tipe: {{ $targetAktivitas->tipe }}, Realiasasi: {{ $targetAktivitas->tipe_realisasi }})</span></td>
|
||||
<td>
|
||||
@if($targetAktivitas->tipe === 'integer')
|
||||
<span class="text-muted">{{ $targetAktivitas->target_integer }}</span>
|
||||
@elseif($targetAktivitas->tipe === 'float')
|
||||
<span class="text-muted">{{ $targetAktivitas->target_float }}</span>
|
||||
@elseif($targetAktivitas->tipe === 'boolean')
|
||||
<span class="text-muted">{{ $targetAktivitas->target_boolean ? 'Ya' : 'Tidak' }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if($targetAktivitas->tipe === 'integer')
|
||||
<span class="text-muted">{{ $targetAktivitas->baseline_integer }}</span>
|
||||
@elseif($targetAktivitas->tipe === 'float')
|
||||
<span class="text-muted">{{ $targetAktivitas->baseline_float }}</span>
|
||||
@elseif($targetAktivitas->tipe === 'boolean')
|
||||
<span class="text-muted">{{ $targetAktivitas->baseline_boolean ? 'Ya' : 'Tidak' }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<div class="dropdown">
|
||||
<button type="button" class="btn p-0 dropdown-toggle hide-arrow" data-bs-toggle="dropdown">
|
||||
<i class="icon-base ti tabler-dots-vertical"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<!-- aktivitas -->
|
||||
<a class="dropdown-item add-aktivitas" href="javascript:void(0);" data-id="{{ $transformasi->id }}" data-parent-id="{{ $tujuan->id }}"><i class="icon-base ti tabler-plus me-1"></i> Tambah Aktivitas</a>
|
||||
<a class="dropdown-item edit-aktivitas" href="javascript:void(0);" data-id="{{ $aktivitas->id }}" data-tujuan-id="{{ $tujuan->id }}" data-transformasi-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-edit me-1"></i> Edit Aktivitas</a>
|
||||
<a class="dropdown-item delete-aktivitas" href="javascript:void(0);" data-id="{{ $aktivitas->id }}" data-transformasi-id="{{ $transformasi->id }}" data-nama="{{ $aktivitas->nama }}"><i class="icon-base ti tabler-trash me-1"></i> Hapus Aktivitas</a>
|
||||
<hr/>
|
||||
<a class="dropdown-item add-target" href="javascript:void(0);" data-id="{{ $aktivitas->id }}" data-transformasi-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-plus me-1"></i> Tambah Target</a>
|
||||
<a class="dropdown-item edit-target" href="javascript:void(0);" data-id="{{ $targetAktivitas->id }}" data-aktivitas-id="{{ $targetAktivitas->id }}" data-transformasi-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-edit me-1"></i> Edit Target</a>
|
||||
<a class="dropdown-item delete-target" href="javascript:void(0);" data-id="{{ $targetAktivitas->id }}" data-aktivitas-id="{{ $targetAktivitas->id }}" data-transformasi-id="{{ $transformasi->id }}" data-nama="{{ $targetAktivitas->variabel }}"><i class="icon-base ti tabler-trash me-1"></i> Hapus Target</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td><span class="text-heading">{{ $transformasi->kode }} {{ $transformasi->nama }} (ID: {{ $transformasi->id }})</span></td>
|
||||
<td><span class="{{ $aktivitas->jenis_aktivitas == 'tujuan' ? 'text-heading' : 'text-muted' }}">{{ $aktivitas->kode }} {{ $aktivitas->nama }} (ID: {{ $aktivitas->id }})</span></td>
|
||||
<td><span class="text-muted">{{ $aktivitas->deskripsi }}</span></td>
|
||||
<td><span class="text-muted">{{ $aktivitas->indikator }}</span></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="dropdown">
|
||||
<button type="button" class="btn p-0 dropdown-toggle hide-arrow" data-bs-toggle="dropdown">
|
||||
<i class="icon-base ti tabler-dots-vertical"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<!-- aktivitas -->
|
||||
<a class="dropdown-item add-aktivitas" href="javascript:void(0);" data-id="{{ $transformasi->id }}" data-parent-id="{{ $tujuan->id }}"><i class="icon-base ti tabler-plus me-1"></i> Tambah Aktivitas</a>
|
||||
<a class="dropdown-item edit-aktivitas" href="javascript:void(0);" data-id="{{ $aktivitas->id }}" data-tujuan-id="{{ $tujuan->id }}" data-transformasi-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-edit me-1"></i> Edit Aktivitas</a>
|
||||
<a class="dropdown-item delete-aktivitas" href="javascript:void(0);" data-id="{{ $aktivitas->id }}" data-transformasi-id="{{ $transformasi->id }}" data-nama="{{ $aktivitas->nama }}"><i class="icon-base ti tabler-trash me-1"></i> Hapus Aktivitas</a>
|
||||
<hr/>
|
||||
<a class="dropdown-item add-target" href="javascript:void(0);" data-id="{{ $aktivitas->id }}" data-transformasi-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-plus me-1"></i> Tambah Target</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
<!-- endforelse target -->
|
||||
@empty
|
||||
@endforelse
|
||||
<!-- endforelse tujuan -->
|
||||
@@ -0,0 +1,109 @@
|
||||
@forelse($transformasi->tujuan as $tujuan)
|
||||
@forelse($tujuan->target as $target)
|
||||
<tr>
|
||||
<td><span class="text-heading">{{ $transformasi->kode }} {{ $transformasi->nama }} (ID: {{ $transformasi->id }})</span></td>
|
||||
<td><span class="{{ $tujuan->jenis_aktivitas == 'tujuan' ? 'text-heading' : 'text-muted' }}">{{ $tujuan->kode }} {{ $tujuan->nama }} (ID: {{ $tujuan->id }})</span></td>
|
||||
<td><span class="text-muted">{{ $tujuan->deskripsi }}</span></td>
|
||||
<td><span class="text-muted">{{ $tujuan->indikator }}</span></td>
|
||||
<td><span class="text-muted">{{ $target->variabel }} (ID: {{ $target->id }}, Tipe: {{ $target->tipe }}, Realiasasi: {{ $target->tipe_realisasi }})</span></td>
|
||||
<td>
|
||||
@if($target->tipe === 'integer')
|
||||
<span class="text-muted">{{ $target->target_integer }}</span>
|
||||
@elseif($target->tipe === 'float')
|
||||
<span class="text-muted">{{ $target->target_float }}</span>
|
||||
@elseif($target->tipe === 'boolean')
|
||||
<span class="text-muted">{{ $target->target_boolean ? 'Ya' : 'Tidak' }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if($target->tipe === 'integer')
|
||||
<span class="text-muted">{{ $target->baseline_integer }}</span>
|
||||
@elseif($target->tipe === 'float')
|
||||
<span class="text-muted">{{ $target->baseline_float }}</span>
|
||||
@elseif($target->tipe === 'boolean')
|
||||
<span class="text-muted">{{ $target->baseline_boolean ? 'Ya' : 'Tidak' }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<div class="dropdown">
|
||||
<button type="button" class="btn p-0 dropdown-toggle hide-arrow" data-bs-toggle="dropdown">
|
||||
<i class="icon-base ti tabler-dots-vertical"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item edit-transformasi" href="javascript:void(0);" data-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-edit me-1"></i> Edit Transformasi</a>
|
||||
<a class="dropdown-item delete-transformasi" href="javascript:void(0);" data-id="{{ $transformasi->id }}" data-nama="{{ $transformasi->nama }}"><i class="icon-base ti tabler-trash me-1"></i> Hapus Transformasi</a>
|
||||
<hr/>
|
||||
<!-- tujuan -->
|
||||
<a class="dropdown-item add-tujuan" href="javascript:void(0);" data-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-plus me-1"></i> Tambah Tujuan</a>
|
||||
<a class="dropdown-item edit-tujuan" href="javascript:void(0);" data-id="{{ $tujuan->id }}" data-transformasi-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-edit me-1"></i> Edit Tujuan</a>
|
||||
<a class="dropdown-item delete-tujuan" href="javascript:void(0);" data-id="{{ $tujuan->id }}" data-transformasi-id="{{ $transformasi->id }}" data-nama="{{ $tujuan->nama }}"><i class="icon-base ti tabler-trash me-1"></i> Hapus Tujuan</a>
|
||||
<hr/>
|
||||
<!-- aktivitas -->
|
||||
<a class="dropdown-item add-aktivitas" href="javascript:void(0);" data-id="{{ $transformasi->id }}" data-parent-id="{{ $tujuan->id }}"><i class="icon-base ti tabler-plus me-1"></i> Tambah Aktivitas</a>
|
||||
<hr/>
|
||||
<a class="dropdown-item add-target" href="javascript:void(0);" data-id="{{ $tujuan->id }}" data-transformasi-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-plus me-1"></i> Tambah Target</a>
|
||||
<a class="dropdown-item edit-target" href="javascript:void(0);" data-id="{{ $target->id }}" data-aktivitas-id="{{ $tujuan->id }}" data-transformasi-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-edit me-1"></i> Edit Target</a>
|
||||
<a class="dropdown-item delete-target" href="javascript:void(0);" data-id="{{ $target->id }}" data-aktivitas-id="{{ $tujuan->id }}" data-transformasi-id="{{ $transformasi->id }}" data-nama="{{ $target->variabel }}"><i class="icon-base ti tabler-trash me-1"></i> Hapus Target</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td><span class="text-heading">{{ $transformasi->kode }} {{ $transformasi->nama }} (ID: {{ $transformasi->id }})</span></td>
|
||||
<td><span class="{{ $tujuan->jenis_aktivitas == 'tujuan' ? 'text-heading' : 'text-muted' }}">{{ $tujuan->kode }} {{ $tujuan->nama }} (ID: {{ $tujuan->id }})</span></td>
|
||||
<td><span class="text-muted">{{ $tujuan->deskripsi }}</span></td>
|
||||
<td><span class="text-muted">{{ $tujuan->indikator }}</span></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="dropdown">
|
||||
<button type="button" class="btn p-0 dropdown-toggle hide-arrow" data-bs-toggle="dropdown">
|
||||
<i class="icon-base ti tabler-dots-vertical"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item edit-transformasi" href="javascript:void(0);" data-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-edit me-1"></i> Edit Transformasi</a>
|
||||
<a class="dropdown-item delete-transformasi" href="javascript:void(0);" data-id="{{ $transformasi->id }}" data-nama="{{ $transformasi->nama }}"><i class="icon-base ti tabler-trash me-1"></i> Hapus Transformasi</a>
|
||||
<hr/>
|
||||
<!-- tujuan -->
|
||||
<a class="dropdown-item add-tujuan" href="javascript:void(0);" data-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-plus me-1"></i> Tambah Tujuan</a>
|
||||
<a class="dropdown-item edit-tujuan" href="javascript:void(0);" data-id="{{ $tujuan->id }}" data-transformasi-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-edit me-1"></i> Edit Tujuan</a>
|
||||
<a class="dropdown-item delete-tujuan" href="javascript:void(0);" data-id="{{ $tujuan->id }}" data-transformasi-id="{{ $transformasi->id }}" data-nama="{{ $tujuan->nama }}"><i class="icon-base ti tabler-trash me-1"></i> Hapus Tujuan</a>
|
||||
<hr/>
|
||||
<!-- aktivitas -->
|
||||
<a class="dropdown-item add-aktivitas" href="javascript:void(0);" data-id="{{ $transformasi->id }}" data-parent-id="{{ $tujuan->id }}"><i class="icon-base ti tabler-plus me-1"></i> Tambah Aktivitas</a>
|
||||
<hr/>
|
||||
<a class="dropdown-item add-target" href="javascript:void(0);" data-id="{{ $tujuan->id }}" data-transformasi-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-plus me-1"></i> Tambah Target</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
<!-- endforelse target -->
|
||||
@include('program.framework.view-aktivitas')
|
||||
@empty
|
||||
<tr>
|
||||
<td><span class="text-heading">{{ $transformasi->kode }} {{ $transformasi->nama }}</span></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="dropdown">
|
||||
<button type="button" class="btn p-0 dropdown-toggle hide-arrow" data-bs-toggle="dropdown">
|
||||
<i class="icon-base ti tabler-dots-vertical"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item edit-transformasi" href="javascript:void(0);" data-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-edit me-1"></i> Edit Transformasi</a>
|
||||
<a class="dropdown-item delete-transformasi" href="javascript:void(0);" data-id="{{ $transformasi->id }}" data-nama="{{ $transformasi->nama }}"><i class="icon-base ti tabler-trash me-1"></i> Hapus Transformasi</a>
|
||||
<hr/>
|
||||
<a class="dropdown-item add-tujuan" href="javascript:void(0);" data-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-plus me-1"></i> Tambah Tujuan</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
<!-- endforelse tujuan -->
|
||||
@@ -57,106 +57,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($framework->transformasi as $transformasi)
|
||||
@forelse($transformasi->aktivitas as $aktivitas)
|
||||
@forelse($aktivitas->target as $target)
|
||||
<tr>
|
||||
<td><span class="text-heading">{{ $transformasi->kode }} {{ $transformasi->nama }}</span></td>
|
||||
<td><span class="{{ $aktivitas->jenis_aktivitas == 'tujuan' ? 'text-heading' : 'text-muted' }}">{{ $aktivitas->nama }}</span></td>
|
||||
<td><span class="text-muted">{{ $aktivitas->deskripsi }}</span></td>
|
||||
<td><span class="text-muted">{{ $aktivitas->indikator }}</span></td>
|
||||
<td><span class="text-muted">{{ $target->variabel }}</span></td>
|
||||
<td>
|
||||
@if($target->tipe === 'integer')
|
||||
<span class="text-muted">{{ $target->target_integer }}</span>
|
||||
@elseif($target->tipe === 'float')
|
||||
<span class="text-muted">{{ $target->target_float }}</span>
|
||||
@elseif($target->tipe === 'boolean')
|
||||
<span class="text-muted">{{ $target->target_boolean ? 'Ya' : 'Tidak' }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if($target->tipe === 'integer')
|
||||
<span class="text-muted">{{ $target->baseline_integer }}</span>
|
||||
@elseif($target->tipe === 'float')
|
||||
<span class="text-muted">{{ $target->baseline_float }}</span>
|
||||
@elseif($target->tipe === 'boolean')
|
||||
<span class="text-muted">{{ $target->baseline_boolean ? 'Ya' : 'Tidak' }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<div class="dropdown">
|
||||
<button type="button" class="btn p-0 dropdown-toggle hide-arrow" data-bs-toggle="dropdown">
|
||||
<i class="icon-base ti tabler-dots-vertical"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item edit-transformasi" href="javascript:void(0);" data-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-edit me-1"></i> Edit Transformasi</a>
|
||||
<a class="dropdown-item delete-transformasi" href="javascript:void(0);" data-id="{{ $transformasi->id }}" data-nama="{{ $transformasi->nama }}"><i class="icon-base ti tabler-trash me-1"></i> Hapus Transformasi</a>
|
||||
<hr/>
|
||||
<a class="dropdown-item add-aktivitas" href="javascript:void(0);" data-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-plus me-1"></i> Tambah Tujuan/Aktivitas</a>
|
||||
<a class="dropdown-item edit-aktivitas" href="javascript:void(0);" data-id="{{ $aktivitas->id }}" data-transformasi-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-edit me-1"></i> Edit Tujuan/Aktivitas</a>
|
||||
<a class="dropdown-item delete-aktivitas" href="javascript:void(0);" data-id="{{ $aktivitas->id }}" data-transformasi-id="{{ $transformasi->id }}" data-nama="{{ $aktivitas->nama }}"><i class="icon-base ti tabler-trash me-1"></i> Hapus Tujuan/Aktivitas</a>
|
||||
<hr/>
|
||||
<a class="dropdown-item add-target" href="javascript:void(0);" data-id="{{ $aktivitas->id }}" data-transformasi-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-plus me-1"></i> Tambah Target</a>
|
||||
<a class="dropdown-item edit-target" href="javascript:void(0);" data-id="{{ $target->id }}" data-aktivitas-id="{{ $aktivitas->id }}" data-transformasi-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-edit me-1"></i> Edit Target</a>
|
||||
<a class="dropdown-item delete-target" href="javascript:void(0);" data-id="{{ $target->id }}" data-aktivitas-id="{{ $aktivitas->id }}" data-transformasi-id="{{ $transformasi->id }}" data-nama="{{ $target->variabel }}"><i class="icon-base ti tabler-trash me-1"></i> Hapus Target</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td><span class="text-heading">{{ $transformasi->kode }} {{ $transformasi->nama }}</span></td>
|
||||
<td><span class="{{ $aktivitas->jenis_aktivitas == 'tujuan' ? 'text-heading' : 'text-muted' }}">{{ $aktivitas->nama }}</span></td>
|
||||
<td><span class="text-muted">{{ $aktivitas->deskripsi }}</span></td>
|
||||
<td><span class="text-muted">{{ $aktivitas->indikator }}</span></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="dropdown">
|
||||
<button type="button" class="btn p-0 dropdown-toggle hide-arrow" data-bs-toggle="dropdown">
|
||||
<i class="icon-base ti tabler-dots-vertical"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item edit-transformasi" href="javascript:void(0);" data-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-edit me-1"></i> Edit Transformasi</a>
|
||||
<a class="dropdown-item delete-transformasi" href="javascript:void(0);" data-id="{{ $transformasi->id }}" data-nama="{{ $transformasi->nama }}"><i class="icon-base ti tabler-trash me-1"></i> Hapus Transformasi</a>
|
||||
<hr/>
|
||||
<a class="dropdown-item add-aktivitas" href="javascript:void(0);" data-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-plus me-1"></i> Tambah Tujuan/Aktivitas</a>
|
||||
<a class="dropdown-item edit-aktivitas" href="javascript:void(0);" data-id="{{ $aktivitas->id }}" data-transformasi-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-edit me-1"></i> Edit Tujuan/Aktivitas</a>
|
||||
<a class="dropdown-item delete-aktivitas" href="javascript:void(0);" data-id="{{ $aktivitas->id }}" data-transformasi-id="{{ $transformasi->id }}" data-nama="{{ $aktivitas->nama }}"><i class="icon-base ti tabler-trash me-1"></i> Hapus Tujuan/Aktivitas</a>
|
||||
<hr/>
|
||||
<a class="dropdown-item add-target" href="javascript:void(0);" data-id="{{ $aktivitas->id }}" data-transformasi-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-plus me-1"></i> Tambah Target</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
<!-- endforelse target -->
|
||||
@empty
|
||||
<tr>
|
||||
<td><span class="text-heading">{{ $transformasi->kode }} {{ $transformasi->nama }}</span></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="dropdown">
|
||||
<button type="button" class="btn p-0 dropdown-toggle hide-arrow" data-bs-toggle="dropdown">
|
||||
<i class="icon-base ti tabler-dots-vertical"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item edit-transformasi" href="javascript:void(0);" data-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-edit me-1"></i> Edit Transformasi</a>
|
||||
<a class="dropdown-item delete-transformasi" href="javascript:void(0);" data-id="{{ $transformasi->id }}" data-nama="{{ $transformasi->nama }}"><i class="icon-base ti tabler-trash me-1"></i> Hapus Transformasi</a>
|
||||
<hr/>
|
||||
<a class="dropdown-item add-aktivitas" href="javascript:void(0);" data-id="{{ $transformasi->id }}"><i class="icon-base ti tabler-plus me-1"></i> Tambah Tujuan/Aktivitas</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
<!-- endforelse aktivitas -->
|
||||
@include('program.framework.view-tujuan')
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="4" class="text-center py-4">Tidak ada data ditemukan.</td>
|
||||
@@ -178,9 +79,12 @@
|
||||
</div>
|
||||
@include('program.transformasi.add')
|
||||
@include('program.transformasi.edit')
|
||||
@include('program.aktivitas.add')
|
||||
@include('program.aktivitas.edit')
|
||||
@include('program.aktivitas.add-tujuan')
|
||||
@include('program.aktivitas.add-aktivitas')
|
||||
@include('program.aktivitas.edit-tujuan')
|
||||
@include('program.aktivitas.edit-aktivitas')
|
||||
@include('program.target.add')
|
||||
@include('program.target.edit')
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
<div
|
||||
class="offcanvas offcanvas-end"
|
||||
tabindex="-1"
|
||||
id="offcanvasAddRealisasi"
|
||||
aria-labelledby="offcanvasAddRealisasiLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasAddRealisasiLabel" class="offcanvas-title">Perbarui Capaian Realisasi</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close text-reset"
|
||||
data-bs-dismiss="offcanvas"
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="t-0" id="addNewRealisasiForm" action="{{ route('realisasi.store') }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" id="add-target-transformasi-id" name="transformasi_id"/>
|
||||
<input type="hidden" id="add-target-aktivitas-id" name="aktivitas_id"/>
|
||||
<input type="hidden" id="add-target-id" name="target_id"/>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-target-variabel">Variabel Target<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="add-target-variabel" name="variabel" placeholder="Cth: AK1" readonly />
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label form-check-label" for="add-target-target">Target<span class="text-danger">*</span></label>
|
||||
<input type="number" step="1" min="0" class="form-control" style="display: none;" id="add-target-target-integer" name="target_integer" placeholder="Cth: 100" readonly />
|
||||
<input type="number" step="any" min="0" class="form-control" style="display: none;" id="add-target-target-float" name="target_float" placeholder="Cth: 100.23" readonly />
|
||||
<input type="text" class="form-control" style="display: none;" id="add-target-target-boolean" name="target_text" placeholder="Cth: 100.23" readonly />
|
||||
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label form-check-label" for="add-target-baseline">Baseline<span class="text-danger">*</span></label>
|
||||
<input type="number" step="1" min="0" class="form-control" style="display: none;" id="add-target-baseline-integer" name="baseline_integer" placeholder="Cth: 100" readonly />
|
||||
<input type="number" step="any" min="0" class="form-control" style="display: none;" id="add-target-baseline-float" name="baseline_float" placeholder="Cth: 100.23" readonly />
|
||||
<input type="text" class="form-control" style="display: none;" id="add-target-baseline-boolean" name="baseline_text" placeholder="Cth: 100.23" readonly />
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label form-check-label" for="add-target-realisasi">Capaian Realisasi<span class="text-danger">*</span></label>
|
||||
<input type="number" step="1" min="0" class="form-control" style="display: none;" id="add-target-realisasi-integer" name="realisasi_integer" placeholder="Cth: 100" />
|
||||
<input type="number" step="any" min="0" class="form-control" style="display: none;" id="add-target-realisasi-float" name="realisasi_float" placeholder="Cth: 100.23" />
|
||||
<div class="form-check form-check-inline" id="add-target-realisasi-boolean-true" style="display: none;">
|
||||
<input type="radio" name="realisasi_boolean" value="1" />
|
||||
<label class="form-check-label" for="add-target-realisasi-boolean-true">Ya</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline" id="add-target-realisasi-boolean-false" style="display: none;">
|
||||
<input type="radio" name="realisasi_boolean" value="0" />
|
||||
<label class="form-check-label" for="add-target-realisasi-boolean-false">Tidak</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success me-3 data-submit">Simpan</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Batal</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
const offcanvasAddRealisasi = new bootstrap.Offcanvas(document.getElementById('offcanvasAddRealisasi'));
|
||||
|
||||
$(".add-realisasi").click(function () {
|
||||
const targetId = $(this).data('target-id');
|
||||
const aktivitasId = $(this).data('aktivitas-id');
|
||||
const transformasiId = $(this).data('transformasi-id');
|
||||
console.log('Add target, target id: ' + targetId);
|
||||
$('#add-target-aktivitas-id').val(aktivitasId);
|
||||
$('#add-target-transformasi-id').val(transformasiId);
|
||||
$('#add-target-id').val(targetId);
|
||||
|
||||
$.get("{{ route('framework.transformasi.aktivitas.target.show', [$framework->id, ':transformasiId', ':aktivitasId', ':id']) }}"
|
||||
.replace(':aktivitasId', aktivitasId)
|
||||
.replace(':transformasiId', transformasiId)
|
||||
.replace(':id', targetId), function (res) {
|
||||
if (res.status === 'success') {
|
||||
$('#add-target-variabel').val(res.data.variabel);
|
||||
|
||||
$('#add-target-target-integer').val(res.data.target_integer);
|
||||
$('#add-target-target-float').val(res.data.target_float);
|
||||
$('#add-target-target-boolean').val(res.data.target_boolean ? 'Ya' : 'Tidak');
|
||||
$('#add-target-baseline-integer').val(res.data.baseline_integer);
|
||||
$('#add-target-baseline-float').val(res.data.baseline_float);
|
||||
$('#add-target-baseline-boolean').val(res.data.baseline_boolean ? 'Ya' : 'Tidak');
|
||||
|
||||
if (res.data.latest_realisasi != null) {
|
||||
$('#add-target-realisasi-integer').val(res.data.latest_realisasi.realisasi_integer);
|
||||
$('#add-target-realisasi-float').val(res.data.latest_realisasi.realisasi_float);
|
||||
$('#add-target-realisasi-boolean-true').prop('checked', res.data.latest_realisasi.realisasi_boolean);
|
||||
$('#add-target-realisasi-boolean-false').prop('checked', !res.data.latest_realisasi.realisasi_boolean);
|
||||
} else {
|
||||
$('#add-target-realisasi-integer').val(res.data.baseline_integer);
|
||||
$('#add-target-realisasi-float').val(res.data.baseline_float);
|
||||
$('#add-target-realisasi-boolean-true').prop('checked', res.data.baseline_boolean);
|
||||
$('#add-target-realisasi-boolean-false').prop('checked', !res.data.baseline_boolean);
|
||||
}
|
||||
|
||||
$('#add-target-target-integer, #add-target-target-float, #add-target-target-boolean')
|
||||
.hide().prop('disabled', true);
|
||||
$('#add-target-baseline-integer, #add-target-baseline-float, #add-target-baseline-boolean')
|
||||
.hide().prop('disabled', true);
|
||||
$('#add-target-realisasi-integer, #add-target-realisasi-float, #add-target-realisasi-boolean-true, #add-target-realisasi-boolean-false')
|
||||
.hide().prop('disabled', true);
|
||||
|
||||
if (res.data.tipe === 'integer') {
|
||||
$('#add-target-target-integer').show().prop('disabled', false);
|
||||
$('#add-target-baseline-integer').show().prop('disabled', false);
|
||||
$('#add-target-realisasi-integer').show().prop('disabled', false);
|
||||
} else if (res.data.tipe === 'float') {
|
||||
$('#add-target-target-float').show().prop('disabled', false);
|
||||
$('#add-target-baseline-float').show().prop('disabled', false);
|
||||
$('#add-target-realisasi-float').show().prop('disabled', false);
|
||||
} else if (res.data.tipe === 'boolean') {
|
||||
$('#add-target-target-boolean').show().prop('disabled', false);
|
||||
$('#add-target-baseline-boolean').show().prop('disabled', false);
|
||||
$('#add-target-realisasi-boolean-true, #add-target-realisasi-boolean-false').show().prop('disabled', false);
|
||||
}
|
||||
|
||||
|
||||
offcanvasAddRealisasi.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
$('#addNewRealisasiForm').validate({
|
||||
rules: {
|
||||
realisasi_integer: { required: true, number: true, min: 0 },
|
||||
realisasi_float: { required: true, number: true, min: 0 },
|
||||
realisasi_boolean: { required: true }
|
||||
},
|
||||
messages: {
|
||||
realisasi_integer: { required: "Realisasi integer wajib diisi", number: "Harus berupa angka", min: "Harus berupa angka positif" },
|
||||
realisasi_float: { required: "Realisasi float wajib diisi", number: "Harus berupa angka", min: "Harus berupa angka positif" },
|
||||
realisasi_boolean: { required: "Realisasi boolean wajib diisi" }
|
||||
},
|
||||
submitHandler: function (form) {
|
||||
$.ajax({
|
||||
url: $(form).attr('action'),
|
||||
type: 'POST',
|
||||
data: $(form).serialize(),
|
||||
success: function () {
|
||||
offcanvasAddRealisasi.hide();
|
||||
form.reset();
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.mb-6, .form-control-validation').append(error);
|
||||
},
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,168 @@
|
||||
<div
|
||||
class="offcanvas offcanvas-end"
|
||||
tabindex="-1"
|
||||
id="offcanvasEditRealisasi"
|
||||
aria-labelledby="offcanvasEditRealisasiLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasEditRealisasiLabel" class="offcanvas-title">Ubah Capaian Realisasi</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close text-reset"
|
||||
data-bs-dismiss="offcanvas"
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="t-0" id="editRealisasiForm" action="{{ route('realisasi.update', ':id') }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<input type="hidden" id="edit-target-transformasi-id" name="transformasi_id"/>
|
||||
<input type="hidden" id="edit-target-aktivitas-id" name="aktivitas_id"/>
|
||||
<input type="hidden" id="edit-target-id" name="target_id"/>
|
||||
<input type="hidden" id="edit-target-realisasi-id" name="id"/>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="edit-target-variabel">Variabel Target<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="edit-target-variabel" name="variabel" placeholder="Cth: AK1" readonly />
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label form-check-label" for="edit-target-target">Target<span class="text-danger">*</span></label>
|
||||
<input type="number" step="1" min="0" class="form-control" id="edit-target-target-integer" name="target_integer" placeholder="Cth: 100" readonly />
|
||||
<input type="number" step="any" min="0" class="form-control" style="display: none;" id="edit-target-target-float" name="target_float" placeholder="Cth: 100.23" readonly />
|
||||
<div class="form-check form-check-inline" id="edit-target-target-boolean-true" style="display: none;">
|
||||
<input type="radio" name="target_boolean" value="1" readonly />
|
||||
<label class="form-check-label" for="edit-target-target-boolean-true">Ya</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline" id="edit-target-target-boolean-false" style="display: none;">
|
||||
<input type="radio" name="target_boolean" value="0" readonly />
|
||||
<label class="form-check-label" for="edit-target-target-boolean-false">Tidak</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label form-check-label" for="edit-target-baseline">Baseline<span class="text-danger">*</span></label>
|
||||
<input type="number" step="1" min="0" class="form-control" id="edit-target-baseline-integer" name="baseline_integer" placeholder="Cth: 100" readonly />
|
||||
<input type="number" step="any" min="0" class="form-control" style="display: none;" id="edit-target-baseline-float" name="baseline_float" placeholder="Cth: 100.23" readonly />
|
||||
<div class="form-check form-check-inline" id="edit-target-baseline-boolean-true" style="display: none;">
|
||||
<input type="radio" name="baseline_boolean" value="1" readonly />
|
||||
<label class="form-check-label" for="edit-target-baseline-boolean-true">Ya</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline" id="edit-target-baseline-boolean-false" style="display: none;">
|
||||
<input type="radio" name="baseline_boolean" value="0" readonly />
|
||||
<label class="form-check-label" for="edit-target-baseline-boolean-false">Tidak</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label form-check-label" for="edit-target-realisasi">Capaian Realisasi<span class="text-danger">*</span></label>
|
||||
<input type="number" step="1" min="0" class="form-control" id="edit-target-realisasi-integer" name="realisasi_integer" placeholder="Cth: 100" />
|
||||
<input type="number" step="any" min="0" class="form-control" style="display: none;" id="edit-target-realisasi-float" name="realisasi_float" placeholder="Cth: 100.23" />
|
||||
<div class="form-check form-check-inline" id="edit-target-realisasi-boolean-true" style="display: none;">
|
||||
<input type="radio" name="realisasi_boolean" value="1" />
|
||||
<label class="form-check-label" for="edit-target-realisasi-boolean-true">Ya</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline" id="edit-target-realisasi-boolean-false" style="display: none;">
|
||||
<input type="radio" name="realisasi_boolean" value="0" />
|
||||
<label class="form-check-label" for="edit-target-realisasi-boolean-false">Tidak</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success me-3 data-submit">Simpan</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Batal</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
const offcanvasEditRealisasi = new bootstrap.Offcanvas(document.getElementById('offcanvasEditRealisasi'));
|
||||
|
||||
$(".edit-realisasi").click(function () {
|
||||
const targetId = $(this).data('target-id');
|
||||
const aktivitasId = $(this).data('aktivitas-id');
|
||||
const transformasiId = $(this).data('transformasi-id');
|
||||
const id = $(this).data('id');
|
||||
console.log('Edit target, target id: ' + targetId);
|
||||
$('#edit-target-aktivitas-id').val(aktivitasId);
|
||||
$('#edit-target-transformasi-id').val(transformasiId);
|
||||
$('#edit-target-id').val(targetId);
|
||||
$('#edit-target-realisasi-id').val(id);
|
||||
|
||||
$.get("{{ route('realisasi.show', ':id') }}"
|
||||
.replace(':id', id), function (res) {
|
||||
if (res.status === 'success') {
|
||||
$('#edit-target-variabel').val(res.data.target.variabel);
|
||||
|
||||
$('#edit-target-target-integer').val(res.data.target.target_integer);
|
||||
$('#edit-target-target-float').val(res.data.target.target_float);
|
||||
$('#edit-target-target-boolean-true').prop('checked', res.data.target.target_boolean);
|
||||
$('#edit-target-target-boolean-false').prop('checked', !res.data.target.target_boolean);
|
||||
$('#edit-target-baseline-integer').val(res.data.target.baseline_integer);
|
||||
$('#edit-target-baseline-float').val(res.data.target.baseline_float);
|
||||
$('#edit-target-baseline-boolean-true').prop('checked', res.data.target.baseline_boolean);
|
||||
$('#edit-target-baseline-boolean-false').prop('checked', !res.data.target.baseline_boolean);
|
||||
|
||||
$('#edit-target-realisasi-integer').val(res.data.realisasi_integer);
|
||||
$('#edit-target-realisasi-float').val(res.data.realisasi_float);
|
||||
$('#edit-target-realisasi-boolean-true').prop('checked', res.data.realisasi_boolean);
|
||||
$('#edit-target-realisasi-boolean-false').prop('checked', !res.data.realisasi_boolean);
|
||||
|
||||
if (res.data.target.tipe === 'integer') {
|
||||
$('#edit-target-target-integer').show().prop('disabled', false);
|
||||
$('#edit-target-baseline-integer').show().prop('disabled', false);
|
||||
$('#edit-target-realisasi-integer').show().prop('disabled', false);
|
||||
} else if (res.data.target.tipe === 'float') {
|
||||
$('#edit-target-target-float').show().prop('disabled', false);
|
||||
$('#edit-target-baseline-float').show().prop('disabled', false);
|
||||
$('#edit-target-realisasi-float').show().prop('disabled', false);
|
||||
} else if (res.data.target.tipe === 'boolean') {
|
||||
$('#edit-target-target-boolean-true, #edit-target-target-boolean-false').show().prop('disabled', false);
|
||||
$('#edit-target-baseline-boolean-true, #edit-target-baseline-boolean-false').show().prop('disabled', false);
|
||||
$('#edit-target-realisasi-boolean-true, #edit-target-realisasi-boolean-false').show().prop('disabled', false);
|
||||
}
|
||||
|
||||
offcanvasEditRealisasi.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
$('#editRealisasiForm').validate({
|
||||
rules: {
|
||||
realisasi_integer: { required: true, number: true, min: 0 },
|
||||
realisasi_float: { required: true, number: true, min: 0 },
|
||||
realisasi_boolean: { required: true }
|
||||
},
|
||||
messages: {
|
||||
realisasi_integer: { required: "Realisasi integer wajib diisi", number: "Harus berupa angka", min: "Harus berupa angka positif" },
|
||||
realisasi_float: { required: "Realisasi float wajib diisi", number: "Harus berupa angka", min: "Harus berupa angka positif" },
|
||||
realisasi_boolean: { required: "Realisasi boolean wajib diisi" }
|
||||
},
|
||||
submitHandler: function (form) {
|
||||
$.ajax({
|
||||
url: $(form).attr('action').replace(':id', $('#edit-target-realisasi-id').val()),
|
||||
type: 'PUT',
|
||||
data: $(form).serialize(),
|
||||
success: function () {
|
||||
offcanvasEditRealisasi.hide();
|
||||
form.reset();
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.mb-6, .form-control-validation').append(error);
|
||||
},
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,126 @@
|
||||
@forelse($tujuan->aktivitas as $aktivitas)
|
||||
@forelse($aktivitas->target as $targetAktivitas)
|
||||
<tr>
|
||||
<td><span class="text-heading">{{ $transformasi->kode }} {{ $transformasi->nama }} (ID: {{ $transformasi->id }})</span></td>
|
||||
<td><span class="{{ $aktivitas->jenis_aktivitas == 'tujuan' ? 'text-heading' : 'text-muted' }}">{{ $aktivitas->kode }} {{ $aktivitas->nama }} (ID: {{ $aktivitas->id }})</span></td>
|
||||
<td><span class="text-muted">{{ $aktivitas->deskripsi }}</span></td>
|
||||
<td><span class="text-muted">{{ $aktivitas->indikator }}</span></td>
|
||||
<td><span class="text-muted">{{ $targetAktivitas->variabel }} (ID: {{ $targetAktivitas->id }}, Tipe: {{ $targetAktivitas->tipe }}, Realiasasi: {{ $targetAktivitas->tipe_realisasi }})</span></td>
|
||||
<td>
|
||||
@if($targetAktivitas->tipe === 'integer')
|
||||
<span class="text-muted">{{ $targetAktivitas->target_integer }}</span>
|
||||
@elseif($targetAktivitas->tipe === 'float')
|
||||
<span class="text-muted">{{ $targetAktivitas->target_float }}</span>
|
||||
@elseif($targetAktivitas->tipe === 'boolean')
|
||||
<span class="text-muted">{{ $targetAktivitas->target_boolean ? 'Ya' : 'Tidak' }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if($targetAktivitas->tipe === 'integer')
|
||||
<span class="text-muted">{{ $targetAktivitas->baseline_integer }}</span>
|
||||
@elseif($targetAktivitas->tipe === 'float')
|
||||
<span class="text-muted">{{ $targetAktivitas->baseline_float }}</span>
|
||||
@elseif($targetAktivitas->tipe === 'boolean')
|
||||
<span class="text-muted">{{ $targetAktivitas->baseline_boolean ? 'Ya' : 'Tidak' }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if($targetAktivitas->latestRealisasi)
|
||||
@if($targetAktivitas->tipe === 'integer')
|
||||
<span class="text-muted">{{ $targetAktivitas->latestRealisasi->realisasi_integer }}</span>
|
||||
<span class="text-muted {{ $targetAktivitas->latestRealisasi->realisasi_integer / $targetAktivitas->target_integer <= 0.5 ? 'text-danger' : 'text-success' }}">
|
||||
({{ number_format(($targetAktivitas->latestRealisasi->realisasi_integer / $targetAktivitas->target_integer) * 100, 2) }}%)
|
||||
</span>
|
||||
@elseif($targetAktivitas->tipe === 'float')
|
||||
<span class="text-muted">{{ $targetAktivitas->latestRealisasi->realisasi_float }}</span>
|
||||
<span class="text-muted {{ $targetAktivitas->latestRealisasi->realisasi_float / $targetAktivitas->target_float <= 0.5 ? 'text-danger' : 'text-success' }}">
|
||||
({{ number_format(($targetAktivitas->latestRealisasi->realisasi_float / $targetAktivitas->target_float) * 100, 2) }}%)
|
||||
</span>
|
||||
@elseif($targetAktivitas->tipe === 'boolean')
|
||||
<span class="text-muted">{{ $targetAktivitas->latestRealisasi->realisasi_boolean ? 'Ya' : 'Tidak' }}</span>
|
||||
@endif
|
||||
@if($targetAktivitas->latestRealisasi && $targetAktivitas->latestRealisasi->verifikasi->count() > 0)
|
||||
<span class="badge badge-center rounded-pill bg-label-success ms-2"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Terverifikasi">
|
||||
<i class="ti tabler-check ti-md"></i>
|
||||
</span>
|
||||
@else
|
||||
<span class="badge badge-center rounded-pill bg-label-danger ms-2"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Belum Terverifikasi">
|
||||
<i class="ti tabler-exclamation-mark ti-md"></i>
|
||||
</span>
|
||||
@endif
|
||||
@else
|
||||
-
|
||||
@endif
|
||||
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-success rounded-pill add-realisasi"
|
||||
data-framework-id="{{ $framework->id }}"
|
||||
data-transformasi-id="{{ $transformasi->id }}"
|
||||
data-aktivitas-id="{{ $aktivitas->id }}"
|
||||
data-target-id="{{ $targetAktivitas->id }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Perbarui Realisasi">
|
||||
<i class="ti tabler-chart-dots ti-md"></i>
|
||||
</a>
|
||||
@if($targetAktivitas->latestRealisasi)
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-success rounded-pill edit-realisasi"
|
||||
data-framework-id="{{ $framework->id }}"
|
||||
data-transformasi-id="{{ $transformasi->id }}"
|
||||
data-aktivitas-id="{{ $aktivitas->id }}"
|
||||
data-target-id="{{ $targetAktivitas->id }}"
|
||||
data-id="{{ $targetAktivitas->latestRealisasi->id }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Edit Realisasi">
|
||||
<i class="ti tabler-edit-circle ti-md"></i>
|
||||
</a>
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-secondary rounded-pill history-realisasi"
|
||||
data-framework-id="{{ $framework->id }}"
|
||||
data-transformasi-id="{{ $transformasi->id }}"
|
||||
data-aktivitas-id="{{ $aktivitas->id }}"
|
||||
data-target-id="{{ $targetAktivitas->id }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Riwayat Realisasi">
|
||||
<i class="ti tabler-logs ti-md"></i>
|
||||
</a>
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-secondary rounded-pill add-verifikasi"
|
||||
data-framework-id="{{ $framework->id }}"
|
||||
data-transformasi-id="{{ $transformasi->id }}"
|
||||
data-aktivitas-id="{{ $aktivitas->id }}"
|
||||
data-target-id="{{ $targetAktivitas->id }}"
|
||||
data-realisasi-id="{{ $targetAktivitas->latestRealisasi->id }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Tambah Dokumen Verifikasi">
|
||||
<i class="ti tabler-file-plus ti-md"></i>
|
||||
</a>
|
||||
@if($targetAktivitas->latestRealisasi && $targetAktivitas->latestRealisasi->verifikasi->count() > 0)
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-secondary rounded-pill list-verifikasi"
|
||||
data-framework-id="{{ $framework->id }}"
|
||||
data-transformasi-id="{{ $transformasi->id }}"
|
||||
data-aktivitas-id="{{ $aktivitas->id }}"
|
||||
data-target-id="{{ $targetAktivitas->id }}"
|
||||
data-realisasi-id="{{ $targetAktivitas->latestRealisasi->id }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Daftar Dokumen Verifikasi">
|
||||
<i class="ti tabler-files ti-md"></i>
|
||||
</a>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td><span class="text-heading">{{ $transformasi->kode }} {{ $transformasi->nama }} (ID: {{ $transformasi->id }})</span></td>
|
||||
<td><span class="{{ $aktivitas->jenis_aktivitas == 'tujuan' ? 'text-heading' : 'text-muted' }}">{{ $aktivitas->kode }} {{ $aktivitas->nama }} (ID: {{ $aktivitas->id }})</span></td>
|
||||
<td><span class="text-muted">{{ $aktivitas->deskripsi }}</span></td>
|
||||
<td><span class="text-muted">{{ $aktivitas->indikator }}</span></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
@endforelse
|
||||
<!-- endforelse target -->
|
||||
@empty
|
||||
@endforelse
|
||||
<!-- endforelse tujuan -->
|
||||
@@ -0,0 +1,137 @@
|
||||
@forelse($transformasi->tujuan as $tujuan)
|
||||
@forelse($tujuan->target as $target)
|
||||
<tr>
|
||||
<td><span class="text-heading">{{ $transformasi->kode }} {{ $transformasi->nama }} (ID: {{ $transformasi->id }})</span></td>
|
||||
<td><span class="{{ $tujuan->jenis_aktivitas == 'tujuan' ? 'text-heading' : 'text-muted' }}">{{ $tujuan->kode }} {{ $tujuan->nama }} (ID: {{ $tujuan->id }})</span></td>
|
||||
<td><span class="text-muted">{{ $tujuan->deskripsi }}</span></td>
|
||||
<td><span class="text-muted">{{ $tujuan->indikator }}</span></td>
|
||||
<td><span class="text-muted">{{ $target->variabel }} (ID: {{ $target->id }}, Tipe: {{ $target->tipe }}, Realiasasi: {{ $target->tipe_realisasi }})</span></td>
|
||||
<td>
|
||||
@if($target->tipe === 'integer')
|
||||
<span class="text-muted">{{ $target->target_integer }}</span>
|
||||
@elseif($target->tipe === 'float')
|
||||
<span class="text-muted">{{ $target->target_float }}</span>
|
||||
@elseif($target->tipe === 'boolean')
|
||||
<span class="text-muted">{{ $target->target_boolean ? 'Ya' : 'Tidak' }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if($target->tipe === 'integer')
|
||||
<span class="text-muted">{{ $target->baseline_integer }}</span>
|
||||
@elseif($target->tipe === 'float')
|
||||
<span class="text-muted">{{ $target->baseline_float }}</span>
|
||||
@elseif($target->tipe === 'boolean')
|
||||
<span class="text-muted">{{ $target->baseline_boolean ? 'Ya' : 'Tidak' }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if($target->latestRealisasi)
|
||||
@if($target->tipe === 'integer')
|
||||
<span class="text-muted">{{ $target->latestRealisasi->realisasi_integer }}</span>
|
||||
<span class="text-muted {{ $target->latestRealisasi->realisasi_integer / $target->target_integer <= 0.5 ? 'text-danger' : 'text-success' }}">
|
||||
({{ number_format(($target->latestRealisasi->realisasi_integer / $target->target_integer) * 100, 2) }}%)
|
||||
</span>
|
||||
@elseif($target->tipe === 'float')
|
||||
<span class="text-muted">{{ $target->latestRealisasi->realisasi_float }}</span>
|
||||
<span class="text-muted {{ $target->latestRealisasi->realisasi_float / $target->target_float <= 0.5 ? 'text-danger' : 'text-success' }}">
|
||||
({{ number_format(($target->latestRealisasi->realisasi_float / $target->target_float) * 100, 2) }}%)
|
||||
</span>
|
||||
@elseif($target->tipe === 'boolean')
|
||||
<span class="text-muted">{{ $target->latestRealisasi->realisasi_boolean ? 'Ya' : 'Tidak' }}</span>
|
||||
@endif
|
||||
@if($target->latestRealisasi && $target->latestRealisasi->verifikasi->count() > 0)
|
||||
<span class="badge badge-center rounded-pill bg-label-success ms-2"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Terverifikasi">
|
||||
<i class="ti tabler-check ti-md"></i>
|
||||
</span>
|
||||
@else
|
||||
<span class="badge badge-center rounded-pill bg-label-danger ms-2"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Belum Terverifikasi">
|
||||
<i class="ti tabler-exclamation-mark ti-md"></i>
|
||||
</span>
|
||||
@endif
|
||||
@else
|
||||
-
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-success rounded-pill add-realisasi"
|
||||
data-framework-id="{{ $framework->id }}"
|
||||
data-transformasi-id="{{ $transformasi->id }}"
|
||||
data-aktivitas-id="{{ $tujuan->id }}"
|
||||
data-target-id="{{ $target->id }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Perbarui Realisasi">
|
||||
<i class="ti tabler-chart-dots ti-md"></i>
|
||||
</a>
|
||||
@if($target->latestRealisasi)
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-success rounded-pill edit-realisasi"
|
||||
data-framework-id="{{ $framework->id }}"
|
||||
data-transformasi-id="{{ $transformasi->id }}"
|
||||
data-aktivitas-id="{{ $tujuan->id }}"
|
||||
data-target-id="{{ $target->id }}"
|
||||
data-id="{{ $target->latestRealisasi->id }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Edit Realisasi">
|
||||
<i class="ti tabler-edit-circle ti-md"></i>
|
||||
</a>
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-secondary rounded-pill history-realisasi"
|
||||
data-framework-id="{{ $framework->id }}"
|
||||
data-transformasi-id="{{ $transformasi->id }}"
|
||||
data-aktivitas-id="{{ $tujuan->id }}"
|
||||
data-target-id="{{ $target->id }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Riwayat Realisasi">
|
||||
<i class="ti tabler-logs ti-md"></i>
|
||||
</a>
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-secondary rounded-pill add-verifikasi"
|
||||
data-framework-id="{{ $framework->id }}"
|
||||
data-transformasi-id="{{ $transformasi->id }}"
|
||||
data-aktivitas-id="{{ $tujuan->id }}"
|
||||
data-target-id="{{ $target->id }}"
|
||||
data-realisasi-id="{{ $target->latestRealisasi->id }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Tambah Dokumen Verifikasi">
|
||||
<i class="ti tabler-file-plus ti-md"></i>
|
||||
</a>
|
||||
@if($target->latestRealisasi && $target->latestRealisasi->verifikasi->count() > 0)
|
||||
<a href="javascript:;" class="btn btn-icon btn-text-secondary rounded-pill list-verifikasi"
|
||||
data-framework-id="{{ $framework->id }}"
|
||||
data-transformasi-id="{{ $transformasi->id }}"
|
||||
data-aktivitas-id="{{ $tujuan->id }}"
|
||||
data-target-id="{{ $target->id }}"
|
||||
data-realisasi-id="{{ $target->latestRealisasi->id }}"
|
||||
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Daftar Dokumen Verifikasi">
|
||||
<i class="ti tabler-files ti-md"></i>
|
||||
</a>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td><span class="text-heading">{{ $transformasi->kode }} {{ $transformasi->nama }} (ID: {{ $transformasi->id }})</span></td>
|
||||
<td><span class="{{ $tujuan->jenis_aktivitas == 'tujuan' ? 'text-heading' : 'text-muted' }}">{{ $tujuan->kode }} {{ $tujuan->nama }} (ID: {{ $tujuan->id }})</span></td>
|
||||
<td><span class="text-muted">{{ $tujuan->deskripsi }}</span></td>
|
||||
<td><span class="text-muted">{{ $tujuan->indikator }}</span></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
@endforelse
|
||||
<!-- endforelse target -->
|
||||
@include('program.realisasi.index-aktivitas')
|
||||
@empty
|
||||
<tr>
|
||||
<td><span class="text-heading">{{ $transformasi->kode }} {{ $transformasi->nama }}</span></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
@endforelse
|
||||
<!-- endforelse tujuan -->
|
||||
@@ -0,0 +1,178 @@
|
||||
@extends('layout.main')
|
||||
|
||||
@push('styles')
|
||||
<link rel="stylesheet"
|
||||
href="https://cdn.datatables.net/rowgroup/1.4.1/css/rowGroup.dataTables.min.css">
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="row g-6 mb-6">
|
||||
|
||||
<div class="col-sm-6 col-xl-4">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start justify-content-between">
|
||||
<div class="content-left">
|
||||
<span class="text-heading">Capaian Realisasi</span>
|
||||
<div class="d-flex align-items-center my-1">
|
||||
<h4 class="mb-0 me-2 {{ $ringkasanCapaianRealisasi->persentase >= 80 ? 'text-success' : ($ringkasanIsiRealisasi->persentase >= 50 ? 'text-warning' : 'text-danger') }}">
|
||||
{{ $ringkasanCapaianRealisasi->persentase ?? 0 }}%
|
||||
</h4>
|
||||
</div>
|
||||
<small class="mb-0">
|
||||
{{ $ringkasanCapaianRealisasi->capaian_80 ?? 0 }} Capaian ≥ 80%,
|
||||
{{ $ringkasanCapaianRealisasi->capaian_50_80 ?? 0 }} Capaian 50% - 80%,
|
||||
{{ $ringkasanCapaianRealisasi->capaian_50 ?? 0 }} Capaian < 50%</small>
|
||||
</div>
|
||||
|
||||
<div class="avatar">
|
||||
<span class="avatar-initial rounded bg-label-success">
|
||||
<i class="icon-base ti tabler-gauge icon-26px"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-xl-4">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start justify-content-between">
|
||||
<div class="content-left">
|
||||
<span class="text-heading">Keterisian Data Capaian Realisasi</span>
|
||||
<div class="d-flex align-items-center my-1">
|
||||
<h4 class="mb-0 me-2 {{ $ringkasanIsiRealisasi->persentase >= 80 ? 'text-success' : ($ringkasanIsiRealisasi->persentase >= 50 ? 'text-warning' : 'text-danger') }}">
|
||||
{{ $ringkasanIsiRealisasi->persentase ?? 0 }}%
|
||||
</h4>
|
||||
</div>
|
||||
<small class="mb-0">{{ $ringkasanIsiRealisasi->count_realisasi ?? 0 }} Data Terisi / {{ $ringkasanIsiRealisasi->count_target ?? 0 }} Data Target</small>
|
||||
</div>
|
||||
|
||||
<div class="avatar">
|
||||
<span class="avatar-initial rounded bg-label-primary">
|
||||
<i class="icon-base ti tabler-chart-dots icon-26px"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-xl-4">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start justify-content-between">
|
||||
<div class="content-left">
|
||||
<span class="text-heading">Kelengkapan Dokumen Verifikasi</span>
|
||||
<div class="d-flex align-items-center my-1">
|
||||
<h4 class="mb-0 me-2 {{ $ringkasanVerifikasi->persentase >= 80 ? 'text-success' : ($ringkasanVerifikasi->persentase >= 50 ? 'text-warning' : 'text-danger') }}">
|
||||
{{ $ringkasanVerifikasi->persentase ?? 0 }}%
|
||||
</h4>
|
||||
</div>
|
||||
<small class="mb-0">{{ $ringkasanVerifikasi->count_unverifikasi ?? 0 }} Realisasi Belum Dilengkapi Dokumen</small>
|
||||
</div>
|
||||
|
||||
<div class="avatar">
|
||||
<span class="avatar-initial rounded bg-label-secondary">
|
||||
<i class="icon-base ti tabler-files icon-26px"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header border-bottom mb-4">
|
||||
<h5 class="card-title mb-0">Realiasi Capaian</h5>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form id="viewFrameworkForm">
|
||||
@csrf
|
||||
|
||||
<h6 class="mb-3">Informasi Kerangka Kerja</h6>
|
||||
<div class="row">
|
||||
<div class="col-md-3 mb-4 form-control-validation">
|
||||
<label class="form-label" for="update-framework-nama">Nama Kerangka Kerja<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="update" name="nama" placeholder="Cth: Tabel Pertanian" value="{{ old('nama', $framework->nama) }}" readonly/>
|
||||
</div>
|
||||
<div class="col-md-3 mb-4 form-control-validation">
|
||||
<label class="form-label" for="update-framework-tahun">Tahun Implementasi<span class="text-danger">*</span></label>
|
||||
<input type="number" step="1" min="2026" class="form-control" id="update-framework-tahun" name="tahun" placeholder="Cth: 2023" value="{{ old('tahun', $framework->tahun) ?? now()->year }}" readonly/>
|
||||
</div>
|
||||
<div class="col-md-6 mb-4 form-control-validation">
|
||||
<label class="form-label" for="update-framework-program">Untuk Program<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="update-framework-tahun" name="tahun" placeholder="Cth: 2023" value="{{ old('program_id', $framework->program->nama) }}" readonly/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h6 class="mb-3">Informasi Rencana Kerja dan Realisasi</h6>
|
||||
|
||||
<hr class="my-4 mx-n4" />
|
||||
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-12 mb-4 form-control-validation">
|
||||
|
||||
<div class="table-responsive text-nowrap mb-4">
|
||||
<table class="table table-hover" id="realisasiTable">
|
||||
<thead class="border-top">
|
||||
<tr>
|
||||
<th>Transformasi</th>
|
||||
<th>Tujuan Jangka Pendek/Aktivitas</th>
|
||||
<th>Deskripsi</th>
|
||||
<th>Indikator</th>
|
||||
<th>Variabel</th>
|
||||
<th>Target</th>
|
||||
<th>Baseline</th>
|
||||
<th>Capaian Realisasi</th>
|
||||
<th>Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($framework->transformasi as $transformasi)
|
||||
@include('program.realisasi.index-tujuan')
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="4" class="text-center py-4">Tidak ada data ditemukan.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
<!-- endforelse tranformasi -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@include('program.realisasi.add')
|
||||
@include('program.realisasi.list')
|
||||
@include('program.realisasi.edit')
|
||||
@include('program.verifikasi.add')
|
||||
@include('program.verifikasi.list')
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script src="https://cdn.datatables.net/rowgroup/1.4.1/js/dataTables.rowGroup.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/datatables-rowsgroup@2.0.0/dataTables.rowsGroup.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
$(document).ready(function () {
|
||||
$('#realisasiTable').DataTable({
|
||||
"paging": true,
|
||||
"lengthChange": false,
|
||||
"searching": true,
|
||||
"ordering": false,
|
||||
"info": true,
|
||||
"autoWidth": true,
|
||||
"scrollX": true,
|
||||
"rowsGroup": [0]
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,83 @@
|
||||
<div
|
||||
class="offcanvas offcanvas-end"
|
||||
tabindex="-1"
|
||||
id="offcanvasListRealisasi"
|
||||
aria-labelledby="offcanvasListRealisasiLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasListRealisasiLabel" class="offcanvas-title">Riwayat Capaian Realisasi</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close text-reset"
|
||||
data-bs-dismiss="offcanvas"
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="t-0" id="historyRealisasiForm">
|
||||
|
||||
<input type="hidden" id="list-target-transformasi-id" name="transformasi_id"/>
|
||||
<input type="hidden" id="list-target-aktivitas-id" name="aktivitas_id"/>
|
||||
<input type="hidden" id="list-target-id" name="target_id"/>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="list-target-variabel">Variabel Target<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="list-target-variabel" name="variabel" placeholder="Cth: AK1" readonly />
|
||||
</div>
|
||||
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nilai Realisasi</th>
|
||||
<th>Update</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="historyRealisasiTableBody">
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Tutup</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
const offcanvasListRealisasi = new bootstrap.Offcanvas(document.getElementById('offcanvasListRealisasi'));
|
||||
|
||||
$(".history-realisasi").click(function () {
|
||||
const targetId = $(this).data('target-id');
|
||||
const aktivitasId = $(this).data('aktivitas-id');
|
||||
const transformasiId = $(this).data('transformasi-id');
|
||||
console.log('Add target, target id: ' + targetId);
|
||||
$('#list-target-aktivitas-id').val(aktivitasId);
|
||||
$('#list-target-transformasi-id').val(transformasiId);
|
||||
$('#list-target-id').val(targetId);
|
||||
|
||||
$.get("{{ route('framework.transformasi.aktivitas.target.show', [$framework->id, ':transformasiId', ':aktivitasId', ':id']) }}"
|
||||
.replace(':aktivitasId', aktivitasId)
|
||||
.replace(':transformasiId', transformasiId)
|
||||
.replace(':id', targetId), function (res) {
|
||||
if (res.status === 'success') {
|
||||
$('#list-target-variabel').val(res.data.variabel);
|
||||
|
||||
let rows = '';
|
||||
res.data.realisasi.forEach(function (realisasi) {
|
||||
let realisasiValue = '';
|
||||
if (res.data.tipe === 'integer') {
|
||||
realisasiValue = realisasi.realisasi_integer;
|
||||
} else if (res.data.tipe === 'float') {
|
||||
realisasiValue = realisasi.realisasi_float;
|
||||
} else if (res.data.tipe === 'boolean') {
|
||||
realisasiValue = realisasi.realisasi_boolean ? 'Ya' : 'Tidak';
|
||||
}
|
||||
rows += '<tr><td>' + realisasiValue + '</td><td>' + new Date(realisasi.updated_at).toLocaleString() + '</td></tr>';
|
||||
});
|
||||
$('#historyRealisasiTableBody').html(rows);
|
||||
|
||||
offcanvasListRealisasi.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -56,6 +56,17 @@
|
||||
<label class="form-check-label" for="add-target-baseline-boolean-false">Tidak</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-target-tipe-realisasi">Tipe Perhitungan Nilai Realisasi<span class="text-danger">*</span></label>
|
||||
<select class="form-select" id="add-target-tipe-realisasi" name="tipe_realisasi">
|
||||
<option value="manual">Input Manual</option>
|
||||
<option value="referensi">Dihitung Otomatis</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation" id="add-target-value-query-container" style="display: none;">
|
||||
<label class="form-label" for="add-target-value-query">Query Perhitungan Nilai Realisasi</label>
|
||||
<textarea class="form-control" id="add-target-value-query" name="value_query" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success me-3 data-submit">Simpan</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Batal</button>
|
||||
@@ -68,7 +79,7 @@
|
||||
$(document).ready(function() {
|
||||
const offcanvasAddTarget = new bootstrap.Offcanvas(document.getElementById('offcanvasAddTarget'));
|
||||
|
||||
$('#add-target-tipe').select2({
|
||||
$('#add-target-tipe, #add-target-tipe-realisasi').select2({
|
||||
dropdownParent: $('#offcanvasAddTarget'),
|
||||
width: '100%',
|
||||
});
|
||||
@@ -91,6 +102,13 @@
|
||||
$('#add-target-baseline-boolean-true, #add-target-baseline-boolean-false').show().prop('disabled', false);
|
||||
}
|
||||
});
|
||||
$('#add-target-tipe-realisasi').change(function() {
|
||||
const tipe = $(this).val();
|
||||
$('#add-target-value-query-container').hide().prop('disabled', true);
|
||||
if (tipe === 'referensi') {
|
||||
$('#add-target-value-query-container').show().prop('disabled', false);
|
||||
}
|
||||
});
|
||||
|
||||
$(".add-target").click(function () {
|
||||
const id = $(this).data('id');
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
<div
|
||||
class="offcanvas offcanvas-end"
|
||||
tabindex="-1"
|
||||
id="offcanvasUpdateTarget"
|
||||
aria-labelledby="offcanvasUpdateTargetLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasUpdateTargetLabel" class="offcanvas-title">Edit Target</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close text-reset"
|
||||
data-bs-dismiss="offcanvas"
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="pt-0" id="updateTargetForm" action="{{ route('framework.transformasi.aktivitas.target.update', [$framework->id, ':transformasiId', ':aktivitasId', ':id']) }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<input type="hidden" id="update-target-transformasi-id" name="transformasi_id"/>
|
||||
<input type="hidden" id="update-target-aktivitas-id" name="aktivitas_id"/>
|
||||
<input type="hidden" id="update-target-id" name="id"/>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="update-target-variabel">Variabel Target<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="update-target-variabel" name="variabel" placeholder="Cth: AK1" />
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="update-target-tipe">Tipe Data Target<span class="text-danger">*</span></label>
|
||||
<select class="form-select" id="update-target-tipe" name="tipe">
|
||||
<option value="integer">Integer</option>
|
||||
<option value="float">Float</option>
|
||||
<option value="boolean">Boolean</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label form-check-label" for="update-target-target">Target<span class="text-danger">*</span></label>
|
||||
<input type="number" step="1" min="0" class="form-control" id="update-target-target-integer" name="target_integer" placeholder="Cth: 100" />
|
||||
<input type="number" step="any" min="0" class="form-control" style="display: none;" id="update-target-target-float" name="target_float" placeholder="Cth: 100.23" />
|
||||
<div class="form-check form-check-inline" id="update-target-target-boolean-true" style="display: none;">
|
||||
<input type="radio" name="target_boolean" value="1" />
|
||||
<label class="form-check-label" for="update-target-target-boolean-true">Ya</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline" id="update-target-target-boolean-false" style="display: none;">
|
||||
<input type="radio" name="target_boolean" value="0" />
|
||||
<label class="form-check-label" for="update-target-target-boolean-false">Tidak</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label form-check-label" for="update-target-baseline">Baseline<span class="text-danger">*</span></label>
|
||||
<input type="number" step="1" min="0" class="form-control" id="update-target-baseline-integer" name="baseline_integer" placeholder="Cth: 100" />
|
||||
<input type="number" step="any" min="0" class="form-control" style="display: none;" id="update-target-baseline-float" name="baseline_float" placeholder="Cth: 100.23" />
|
||||
<div class="form-check form-check-inline" id="update-target-baseline-boolean-true" style="display: none;">
|
||||
<input type="radio" name="baseline_boolean" value="1" />
|
||||
<label class="form-check-label" for="update-target-baseline-boolean-true">Ya</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline" id="update-target-baseline-boolean-false" style="display: none;">
|
||||
<input type="radio" name="baseline_boolean" value="0" />
|
||||
<label class="form-check-label" for="update-target-baseline-boolean-false">Tidak</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="update-target-tipe-realisasi">Tipe Perhitungan Nilai Realisasi<span class="text-danger">*</span></label>
|
||||
<select class="form-select" id="update-target-tipe-realisasi" name="tipe_realisasi">
|
||||
<option value="manual">Input Manual</option>
|
||||
<option value="referensi">Dihitung Otomatis</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation" id="update-target-value-query-container" style="display: none;">
|
||||
<label class="form-label" for="update-target-value-query">Query Perhitungan Nilai Realisasi</label>
|
||||
<textarea class="form-control" id="update-target-value-query" name="value_query" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success me-3 data-submit">Simpan</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Batal</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
const offcanvasUpdateTarget = new bootstrap.Offcanvas(document.getElementById('offcanvasUpdateTarget'));
|
||||
|
||||
$('#update-target-tipe, #update-target-tipe-realisasi').select2({
|
||||
dropdownParent: $('#offcanvasUpdateTarget'),
|
||||
width: '100%',
|
||||
});
|
||||
$(".edit-target").click(function () {
|
||||
const id = $(this).data('id');
|
||||
const transformasiId = $(this).data('transformasi-id');
|
||||
const aktivitasId = $(this).data('aktivitas-id');
|
||||
console.log('Add target, aktivitas id: ' + id);
|
||||
$('#update-target-aktivitas-id').val(aktivitasId);
|
||||
$('#update-target-transformasi-id').val(transformasiId);
|
||||
$('#update-target-id').val(id);
|
||||
|
||||
$.get("{{ route('framework.transformasi.aktivitas.target.show', [$framework->id, ':transformasiId', ':aktivitasId', ':id']) }}"
|
||||
.replace(':aktivitasId', aktivitasId)
|
||||
.replace(':transformasiId', transformasiId)
|
||||
.replace(':id', id), function (res) {
|
||||
if (res.status === 'success') {
|
||||
$('#update-target-variabel').val(res.data.variabel);
|
||||
$('#update-target-tipe').val(res.data.tipe).trigger('change');
|
||||
$('#update-target-target-integer').val(res.data.target_integer);
|
||||
$('#update-target-target-float').val(res.data.target_float);
|
||||
$('#update-target-target-boolean-true').prop('checked', res.data.target_boolean);
|
||||
$('#update-target-target-boolean-false').prop('checked', !res.data.target_boolean);
|
||||
$('#update-target-baseline-integer').val(res.data.baseline_integer);
|
||||
$('#update-target-baseline-float').val(res.data.baseline_float);
|
||||
$('#update-target-baseline-boolean-true').prop('checked', res.data.baseline_boolean);
|
||||
$('#update-target-baseline-boolean-false').prop('checked', !res.data.baseline_boolean);
|
||||
$('#update-target-tipe-realisasi').val(res.data.tipe_realisasi).trigger('change');
|
||||
$('#update-target-value-query').val(res.data.value_query);
|
||||
offcanvasUpdateTarget.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$('#update-target-tipe').change(function() {
|
||||
const tipe = $(this).val();
|
||||
$('#update-target-target-integer, #update-target-target-float, #update-target-target-boolean-true, #update-target-target-boolean-false').hide().prop('disabled', true);
|
||||
if (tipe === 'integer') {
|
||||
$('#update-target-target-integer').show().prop('disabled', false);
|
||||
} else if (tipe === 'float') {
|
||||
$('#update-target-target-float').show().prop('disabled', false);
|
||||
} else if (tipe === 'boolean') {
|
||||
$('#update-target-target-boolean-true, #update-target-target-boolean-false').show().prop('disabled', false);
|
||||
}
|
||||
$('#update-target-baseline-integer, #update-target-baseline-float, #update-target-baseline-boolean-true, #update-target-baseline-boolean-false').hide().prop('disabled', true);
|
||||
if (tipe === 'integer') {
|
||||
$('#update-target-baseline-integer').show().prop('disabled', false);
|
||||
} else if (tipe === 'float') {
|
||||
$('#update-target-baseline-float').show().prop('disabled', false);
|
||||
} else if (tipe === 'boolean') {
|
||||
$('#update-target-baseline-boolean-true, #update-target-baseline-boolean-false').show().prop('disabled', false);
|
||||
}
|
||||
});
|
||||
$('#update-target-tipe-realisasi').change(function() {
|
||||
const tipe = $(this).val();
|
||||
$('#update-target-value-query-container').hide().prop('disabled', true);
|
||||
if (tipe === 'referensi') {
|
||||
$('#update-target-value-query-container').show().prop('disabled', false);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$('#updateTargetForm').validate({
|
||||
rules: {
|
||||
variabel: { required: true },
|
||||
tipe: { required: true },
|
||||
target_integer: { required: true, number: true, min: 0 },
|
||||
target_float: { required: true, number: true, min: 0 },
|
||||
target_boolean: { required: true }
|
||||
},
|
||||
messages: {
|
||||
variabel: { required: "Variabel target wajib diisi" },
|
||||
tipe: { required: "Tipe data target wajib diisi" },
|
||||
target_integer: { required: "Target integer wajib diisi", number: "Harus berupa angka", min: "Harus berupa angka positif" },
|
||||
target_float: { required: "Target float wajib diisi", number: "Harus berupa angka", min: "Harus berupa angka positif" },
|
||||
target_boolean: { required: "Target boolean wajib diisi" }
|
||||
},
|
||||
submitHandler: function (form) {
|
||||
$.ajax({
|
||||
url: $(form).attr('action')
|
||||
.replace(':aktivitasId', $('#update-target-aktivitas-id').val())
|
||||
.replace(':transformasiId', $('#update-target-transformasi-id').val())
|
||||
.replace(':id', $('#update-target-id').val()),
|
||||
type: 'PUT',
|
||||
data: $(form).serialize(),
|
||||
success: function () {
|
||||
offcanvasUpdateTarget.hide();
|
||||
form.reset();
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.mb-6, .form-control-validation').append(error);
|
||||
},
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,176 @@
|
||||
<div
|
||||
class="offcanvas offcanvas-end"
|
||||
tabindex="-1"
|
||||
id="offcanvasAddVerifikasi"
|
||||
aria-labelledby="offcanvasAddVerifikasiLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasAddVerifikasiLabel" class="offcanvas-title">Tambah Verifikasi</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close text-reset"
|
||||
data-bs-dismiss="offcanvas"
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="t-0" id="addNewVerifikasiForm" action="{{ route('verifikasi.store') }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" id="add-verifikasi-transformasi-id" name="transformasi_id"/>
|
||||
<input type="hidden" id="add-verifikasi-aktivitas-id" name="aktivitas_id"/>
|
||||
<input type="hidden" id="add-verifikasi-target-id" name="target_id"/>
|
||||
<input type="hidden" id="add-verifikasi-realisasi-id" name="realisasi_id"/>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-verifikasi-variabel">Variabel Target<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="add-verifikasi-variabel" name="variabel" placeholder="Cth: AK1" readonly />
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label form-check-label" for="add-verifikasi-target">Target<span class="text-danger">*</span></label>
|
||||
<input type="number" step="1" min="0" class="form-control" id="add-verifikasi-target-integer" name="target_integer" placeholder="Cth: 100" readonly />
|
||||
<input type="number" step="any" min="0" class="form-control" style="display: none;" id="add-verifikasi-target-float" name="target_float" placeholder="Cth: 100.23" readonly />
|
||||
<div class="form-check form-check-inline" id="add-verifikasi-target-boolean-true" style="display: none;">
|
||||
<input type="radio" name="target_boolean" value="1" readonly />
|
||||
<label class="form-check-label" for="add-verifikasi-target-boolean-true">Ya</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline" id="add-verifikasi-target-boolean-false" style="display: none;">
|
||||
<input type="radio" name="target_boolean" value="0" readonly />
|
||||
<label class="form-check-label" for="add-verifikasi-target-boolean-false">Tidak</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label form-check-label" for="add-verifikasi-baseline">Baseline<span class="text-danger">*</span></label>
|
||||
<input type="number" step="1" min="0" class="form-control" id="add-verifikasi-baseline-integer" name="baseline_integer" placeholder="Cth: 100" readonly />
|
||||
<input type="number" step="any" min="0" class="form-control" style="display: none;" id="add-verifikasi-baseline-float" name="baseline_float" placeholder="Cth: 100.23" readonly />
|
||||
<div class="form-check form-check-inline" id="add-verifikasi-baseline-boolean-true" style="display: none;">
|
||||
<input type="radio" name="baseline_boolean" value="1" readonly />
|
||||
<label class="form-check-label" for="add-verifikasi-baseline-boolean-true">Ya</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline" id="add-verifikasi-baseline-boolean-false" style="display: none;">
|
||||
<input type="radio" name="baseline_boolean" value="0" readonly />
|
||||
<label class="form-check-label" for="add-verifikasi-baseline-boolean-false">Tidak</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label form-check-label" for="add-verifikasi-realisasi">Capaian Realisasi<span class="text-danger">*</span></label>
|
||||
<input type="number" step="1" min="0" class="form-control" id="add-verifikasi-realisasi-integer" name="realisasi_integer" placeholder="Cth: 100" readonly />
|
||||
<input type="number" step="any" min="0" class="form-control" style="display: none;" id="add-verifikasi-realisasi-float" name="realisasi_float" placeholder="Cth: 100.23" readonly />
|
||||
<div class="form-check form-check-inline" id="add-verifikasi-realisasi-boolean-true" style="display: none;">
|
||||
<input type="radio" name="realisasi_boolean" value="1" readonly />
|
||||
<label class="form-check-label" for="add-verifikasi-realisasi-boolean-true">Ya</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline" id="add-verifikasi-realisasi-boolean-false" style="display: none;">
|
||||
<input type="radio" name="realisasi_boolean" value="0" readonly />
|
||||
<label class="form-check-label" for="add-verifikasi-realisasi-boolean-false">Tidak</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-verifikasi-dokumen">Dokumen Verifikasi<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="add-verifikasi-dokumen" name="dokumen" placeholder="Cth: AK1" />
|
||||
</div>
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="add-verifikasi-link-dokumen">Link Dokumen<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="add-verifikasi-link-dokumen" name="link_dokumen" placeholder="Cth: https://example.com/dokumen" />
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success me-3 data-submit">Simpan</button>
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Batal</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
const offcanvasAddVerifikasi = new bootstrap.Offcanvas(document.getElementById('offcanvasAddVerifikasi'));
|
||||
|
||||
$(".add-verifikasi").click(function () {
|
||||
const targetId = $(this).data('target-id');
|
||||
const aktivitasId = $(this).data('aktivitas-id');
|
||||
const transformasiId = $(this).data('transformasi-id');
|
||||
const realisasiId = $(this).data('realisasi-id');
|
||||
console.log('Add target, target id: ' + targetId);
|
||||
$('#add-verifikasi-aktivitas-id').val(aktivitasId);
|
||||
$('#add-verifikasi-transformasi-id').val(transformasiId);
|
||||
$('#add-verifikasi-target-id').val(targetId);
|
||||
$('#add-verifikasi-realisasi-id').val(realisasiId);
|
||||
|
||||
$.get("{{ route('realisasi.show', ':id') }}"
|
||||
.replace(':id', realisasiId), function (res) {
|
||||
if (res.status === 'success') {
|
||||
$('#add-verifikasi-variabel').val(res.data.target.variabel);
|
||||
|
||||
$('#add-verifikasi-target-integer').val(res.data.target.target_integer);
|
||||
$('#add-verifikasi-target-float').val(res.data.target.target_float);
|
||||
$('#add-verifikasi-target-boolean-true').prop('checked', res.data.target.target_boolean);
|
||||
$('#add-verifikasi-target-boolean-false').prop('checked', !res.data.target.target_boolean);
|
||||
$('#add-verifikasi-baseline-integer').val(res.data.target.baseline_integer);
|
||||
$('#add-verifikasi-baseline-float').val(res.data.target.baseline_float);
|
||||
$('#add-verifikasi-baseline-boolean-true').prop('checked', res.data.target.baseline_boolean);
|
||||
$('#add-verifikasi-baseline-boolean-false').prop('checked', !res.data.target.baseline_boolean);
|
||||
|
||||
$('#add-verifikasi-realisasi-integer').val(res.data.realisasi_integer);
|
||||
$('#add-verifikasi-realisasi-float').val(res.data.realisasi_float);
|
||||
$('#add-verifikasi-realisasi-boolean-true').prop('checked', res.data.realisasi_boolean);
|
||||
$('#add-verifikasi-realisasi-boolean-false').prop('checked', !res.data.realisasi_boolean);
|
||||
|
||||
if (res.data.target.tipe === 'integer') {
|
||||
$('#add-verifikasi-target-integer').show().prop('disabled', false);
|
||||
$('#add-verifikasi-baseline-integer').show().prop('disabled', false);
|
||||
$('#add-verifikasi-realisasi-integer').show().prop('disabled', false);
|
||||
} else if (res.data.target.tipe === 'float') {
|
||||
$('#add-verifikasi-target-float').show().prop('disabled', false);
|
||||
$('#add-verifikasi-baseline-float').show().prop('disabled', false);
|
||||
$('#add-verifikasi-realisasi-float').show().prop('disabled', false);
|
||||
} else if (res.data.target.tipe === 'boolean') {
|
||||
$('#add-verifikasi-target-boolean-true, #add-verifikasi-target-boolean-false').show().prop('disabled', false);
|
||||
$('#add-verifikasi-baseline-boolean-true, #add-verifikasi-baseline-boolean-false').show().prop('disabled', false);
|
||||
$('#add-verifikasi-realisasi-boolean-true, #add-verifikasi-realisasi-boolean-false').show().prop('disabled', false);
|
||||
}
|
||||
|
||||
offcanvasAddVerifikasi.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
$('#addNewVerifikasiForm').validate({
|
||||
rules: {
|
||||
realisasi_integer: { required: true, number: true, min: 0 },
|
||||
realisasi_float: { required: true, number: true, min: 0 },
|
||||
realisasi_boolean: { required: true }
|
||||
},
|
||||
messages: {
|
||||
realisasi_integer: { required: "Realisasi integer wajib diisi", number: "Harus berupa angka", min: "Harus berupa angka positif" },
|
||||
realisasi_float: { required: "Realisasi float wajib diisi", number: "Harus berupa angka", min: "Harus berupa angka positif" },
|
||||
realisasi_boolean: { required: "Realisasi boolean wajib diisi" }
|
||||
},
|
||||
submitHandler: function (form) {
|
||||
$.ajax({
|
||||
url: $(form).attr('action'),
|
||||
type: 'POST',
|
||||
data: $(form).serialize(),
|
||||
success: function () {
|
||||
offcanvasAddVerifikasi.hide();
|
||||
form.reset();
|
||||
Swal.fire({ icon: 'success', title: 'Berhasil!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => window.location.reload());
|
||||
},
|
||||
error: function (xhr) {
|
||||
console.error(xhr);
|
||||
Swal.fire({ icon: 'error', title: 'Gagal!', text: xhr.responseJSON?.message || 'Error' });
|
||||
}
|
||||
});
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function (error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.mb-6, .form-control-validation').append(error);
|
||||
},
|
||||
highlight: function (element) {
|
||||
$(element).addClass('is-invalid');
|
||||
},
|
||||
unhighlight: function (element) {
|
||||
$(element).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,117 @@
|
||||
<div
|
||||
class="offcanvas offcanvas-end"
|
||||
tabindex="-1"
|
||||
id="offcanvasListVerifikasi"
|
||||
aria-labelledby="offcanvasListVerifikasiLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 id="offcanvasListVerifikasiLabel" class="offcanvas-title">Daftar Dokumen Verifikasi</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close text-reset"
|
||||
data-bs-dismiss="offcanvas"
|
||||
aria-label="Tutup"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
|
||||
<form class="t-0" id="historyVerifikasiForm">
|
||||
|
||||
<input type="hidden" id="list-verifikasi-transformasi-id" name="transformasi_id"/>
|
||||
<input type="hidden" id="list-verifikasi-aktivitas-id" name="aktivitas_id"/>
|
||||
<input type="hidden" id="list-verifikasi-target-id" name="target_id"/>
|
||||
<input type="hidden" id="list-verifikasi-realisasi-id" name="realisasi_id"/>
|
||||
|
||||
<div class="mb-6 form-control-validation">
|
||||
<label class="form-label" for="list-verifikasi-variabel">Variabel Target<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="list-verifikasi-variabel" name="variabel" placeholder="Cth: AK1" readonly />
|
||||
</div>
|
||||
|
||||
<table class="table table-hover" id="historyVerifikasiTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Dokumen</th>
|
||||
<th>Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="historyVerifikasiTableBody">
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<button type="reset" class="btn btn-label-danger" data-bs-dismiss="offcanvas">Tutup</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
const offcanvasListVerifikasi = new bootstrap.Offcanvas(document.getElementById('offcanvasListVerifikasi'));
|
||||
|
||||
$(".list-verifikasi").click(function () {
|
||||
const targetId = $(this).data('target-id');
|
||||
const aktivitasId = $(this).data('aktivitas-id');
|
||||
const transformasiId = $(this).data('transformasi-id');
|
||||
const realisasiId = $(this).data('realisasi-id');
|
||||
$('#list-verifikasi-aktivitas-id').val(aktivitasId);
|
||||
$('#list-verifikasi-transformasi-id').val(transformasiId);
|
||||
$('#list-verifikasi-target-id').val(targetId);
|
||||
$('#list-verifikasi-realisasi-id').val(realisasiId);
|
||||
|
||||
$.get("{{ route('realisasi.show', ':id') }}"
|
||||
.replace(':id', realisasiId), function (res) {
|
||||
if (res.status === 'success') {
|
||||
$('#list-verifikasi-variabel').val(res.data.target.variabel);
|
||||
|
||||
let rows = '';
|
||||
if (res.data.tipe === 'integer') {
|
||||
realisasiValue = res.data.realisasi_integer;
|
||||
} else if (res.data.tipe === 'float') {
|
||||
realisasiValue = res.data.realisasi_float;
|
||||
} else if (res.data.tipe === 'boolean') {
|
||||
realisasiValue = res.data.realisasi_boolean ? 'Ya' : 'Tidak';
|
||||
}
|
||||
|
||||
res.data.verifikasi.forEach(function (verifikasi) {
|
||||
rows += '<tr><td>' + verifikasi.dokumen + '</td><td>'
|
||||
+ '<a href="' + verifikasi.link_dokumen + '" target="_blank" class="btn btn-icon btn-text-secondary rounded-pill">'
|
||||
+ '<i class="ti tabler-file ti-md"></i></a>'
|
||||
+ '<a href="javascript:;" class="btn btn-icon btn-text-danger rounded-pill delete-verifikasi" data-id="' + verifikasi.id + '" data-nama="' + verifikasi.dokumen + '">'
|
||||
+ '<i class="ti tabler-trash ti-md"></i></a>'
|
||||
+ '</td></tr>';
|
||||
});
|
||||
$('#historyVerifikasiTableBody').html(rows);
|
||||
|
||||
offcanvasListVerifikasi.show();
|
||||
}
|
||||
});
|
||||
|
||||
$('#historyVerifikasiTable').on('click', '.delete-verifikasi', function () {
|
||||
const id = $(this).data('id');
|
||||
const nama = $(this).data('nama');
|
||||
Swal.fire({
|
||||
title: 'Hapus?',
|
||||
text: `Dokumen Verifikasi: ${nama} akan dihapus!`,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Ya, Hapus!',
|
||||
customClass: { confirmButton: 'btn btn-danger me-3', cancelButton: 'btn btn-label-secondary' },
|
||||
buttonsStyling: false
|
||||
}).then(function (result) {
|
||||
if (result.value) {
|
||||
$.ajax({
|
||||
url: "{{ route('verifikasi.destroy', ':id') }}".replace(':id', id),
|
||||
type: 'POST',
|
||||
data: {
|
||||
_token: '{{ csrf_token() }}',
|
||||
_method: 'DELETE'
|
||||
},
|
||||
success: function () {
|
||||
Swal.fire({ icon: 'success', title: 'Terhapus!', showConfirmButton: false, timer: 1500 })
|
||||
.then(() => location.reload());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
Reference in New Issue
Block a user