bank-sampah/Views/ReduksiSampah/Komposting/Index.cshtml

439 lines
17 KiB
Plaintext

@{
var jenis = "Komposting";
var tableUrl = Url.Content("~/ReduksiSampah/Komposting/Table");
ViewData["Title"] = $"Reduksi Sampah - {jenis}";
}
<div class="flex flex-col gap-2 md:flex-row md:justify-between md:gap-0 items-center">
<div class="prose md:w-1/2 w-full">
<span class="text-xl font-semibold text-black">
Reduksi Sampah - @jenis
</span>
</div>
<div class="flex flex-wrap items-center gap-2 md:w-1/2 w-full justify-end">
<select id="filter_tahun" class="select md:w-44 w-full rounded-full select-sm">
<option value="">Semua Tahun</option>
<option value="2025">2025</option>
<option value="2024">2024</option>
<option value="2023">2023</option>
</select>
<button class="btn btn-sm rounded-full bg-bank-sampah-primary-500 text-white hover:bg-bank-sampah-primary-600"
onclick="modal_tambah.showModal()">
<i class="ph ph-plus"></i>
Tambah Lokasi
</button>
<button class="btn btn-sm rounded-full btn-neutral" onclick="modal_validasi.showModal()">
<i class="ph ph-check-circle"></i>
Validasi Data
</button>
<button class="btn btn-sm rounded-full btn-info" onclick="modal_history.showModal()">
<i class="ph ph-clock-counter-clockwise"></i>
History
</button>
</div>
</div>
<div class="h-6"></div>
<!-- Modal Tambah -->
<dialog id="modal_tambah" class="modal modal-bottom sm:modal-middle">
<div class="modal-box w-full max-w-3xl p-6 bg-white rounded-2xl">
<div class="flex items-center justify-between mb-6">
<h3 class="text-lg font-semibold text-gray-900">Tambah Lokasi Komposting</h3>
<form method="dialog">
<button class="btn btn-sm btn-circle btn-ghost">✕</button>
</form>
</div>
<form class="space-y-4">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<fieldset class="fieldset">
<legend class="fieldset-legend">Nama Lokasi</legend>
<input type="text" class="input w-full" placeholder="Nama Lokasi" />
</fieldset>
<fieldset class="fieldset">
<legend class="fieldset-legend">Periode</legend>
<input type="month" class="input w-full" />
</fieldset>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<fieldset class="fieldset">
<legend class="fieldset-legend">Kecamatan</legend>
<input type="text" class="input w-full" placeholder="Kecamatan" />
</fieldset>
<fieldset class="fieldset">
<legend class="fieldset-legend">Kelurahan</legend>
<input type="text" class="input w-full" placeholder="Kelurahan" />
</fieldset>
</div>
<div class="grid grid-cols-2 md:grid-cols-3 gap-4">
<fieldset class="fieldset">
<legend class="fieldset-legend">RT</legend>
<input type="text" class="input w-full" placeholder="RT" />
</fieldset>
<fieldset class="fieldset">
<legend class="fieldset-legend">RW</legend>
<input type="text" class="input w-full" placeholder="RW" />
</fieldset>
<fieldset class="fieldset">
<legend class="fieldset-legend">Status</legend>
<select class="select w-full">
<option>Aktif</option>
<option>Tidak Aktif</option>
</select>
</fieldset>
</div>
<fieldset class="fieldset">
<legend class="fieldset-legend">Bukti</legend>
<input type="file" class="file-input w-full" />
</fieldset>
<fieldset class="fieldset">
<legend class="fieldset-legend">Detail Alamat</legend>
<textarea class="textarea w-full" rows="3"></textarea>
</fieldset>
<div class="flex justify-end gap-2 pt-4">
<button type="button" class="btn btn-ghost rounded-full" onclick="modal_tambah.close()">Batal</button>
<button type="submit" class="btn bg-bank-sampah-primary-500 text-white rounded-full">Simpan</button>
</div>
</form>
</div>
</dialog>
<!-- Modal Validasi -->
<dialog id="modal_validasi" class="modal modal-bottom sm:modal-middle">
<div class="modal-box w-full max-w-xl p-6 bg-white rounded-2xl">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold text-gray-900">Validasi Data Komposting</h3>
<form method="dialog">
<button class="btn btn-sm btn-circle btn-ghost">✕</button>
</form>
</div>
<div class="space-y-4">
<div class="bg-gray-50 rounded-xl p-4">
<div class="text-sm text-gray-500">Periode</div>
<div class="text-base font-semibold text-gray-900">Jan 2025</div>
<div class="mt-2 text-sm text-gray-500">Nama Lokasi</div>
<div class="text-base font-semibold text-gray-900">Jakarta Pusat</div>
</div>
<div class="flex flex-col sm:flex-row gap-3">
<button class="btn btn-outline btn-error rounded-full w-full sm:w-1/2" type="button">
Tolak
</button>
<button class="btn btn-success text-white rounded-full w-full sm:w-1/2" type="button">
Setujui
</button>
</div>
</div>
</div>
</dialog>
<!-- Modal History -->
<dialog id="modal_history" class="modal modal-bottom sm:modal-middle">
<div class="modal-box w-full max-w-xl p-6 bg-white rounded-2xl">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold text-gray-900">History Perubahan Data</h3>
<form method="dialog">
<button class="btn btn-sm btn-circle btn-ghost">✕</button>
</form>
</div>
<div class="max-h-80 overflow-y-auto">
<ul class="timeline timeline-vertical">
<li>
<div class="timeline-start">Hari ini</div>
<div class="timeline-middle">
<i class="ph ph-check-circle text-green-600"></i>
</div>
<div class="timeline-end timeline-box">
Validasi data oleh Admin Subandri
</div>
</li>
<li>
<div class="timeline-start">3 hari lalu</div>
<div class="timeline-middle">
<i class="ph ph-pen text-amber-500"></i>
</div>
<div class="timeline-end timeline-box">
Pembaruan data B3 dan B4
</div>
</li>
<li>
<div class="timeline-start">1 minggu lalu</div>
<div class="timeline-middle">
<i class="ph ph-plus-circle text-blue-500"></i>
</div>
<div class="timeline-end timeline-box">
Penambahan lokasi baru Jakarta Utara
</div>
</li>
</ul>
</div>
</div>
</dialog>
<div class="card bg-white shadow-sm">
<div class="card-body p-2">
<div class="w-full overflow-x-auto">
<table class="table w-full text-center" id="example">
<thead>
<tr>
<th rowspan="2">No</th>
<th colspan="5">Lokasi Rumah Komposting</th>
<th rowspan="2">Status</th>
<th colspan="12">Jumlah Sampah yang di Reduksi (Kg/Bulan)</th>
<th rowspan="2">Aksi</th>
</tr>
<tr>
<th>Kecamatan</th>
<th>Kelurahan</th>
<th>RT</th>
<th>RW</th>
<th>Detail Alamat</th>
<th>B1</th>
<th>B2</th>
<th>B3</th>
<th>B4</th>
<th>B5</th>
<th>B6</th>
<th>B7</th>
<th>B8</th>
<th>B9</th>
<th>B10</th>
<th>B11</th>
<th>B12</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
@section Scripts {
<script type="text/javascript">
const tableAjaxUrl = '@tableUrl';
const updateUrl = '@Url.Content("~/ReduksiSampah/Komposting/Update")';
const decimalFields = ['b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'b10', 'b11', 'b12'];
let table;
$(document).ready(function () {
const columns = [
{ data: null, render: function (data, type, row, meta) { return meta.row + 1; }, orderable: false, searchable: false },
{ data: 'kecamatan', defaultContent: '-' },
{ data: 'kelurahan', defaultContent: '-' },
{ data: 'rt', defaultContent: '-' },
{ data: 'rw', defaultContent: '-' },
{ data: 'detail_alamat', defaultContent: '-' },
{
data: 'status',
render: function (data, type, row) {
return buildStatusSelect(row.id, data);
},
orderable: false,
searchable: false
}
];
decimalFields.forEach(function (field) {
columns.push({
data: field,
defaultContent: null,
render: function (data, type, row) {
return buildDecimalInput(row.id, field, data);
},
orderable: false,
searchable: false
});
});
columns.push({
data: null,
orderable: false,
searchable: false,
render: function (data, type, row) {
return `<div class="flex items-center justify-center gap-2">
<button type="button"
class="btn btn-square btn-sm btn-warning text-white btn-edit-row tooltip tooltip-left tooltip-warning"
data-tip="Edit"
data-id="${row.id}">
<i class="ph ph-note-pencil"></i>
</button>
<button type="button"
class="btn btn-square btn-sm btn-success text-white btn-save-row tooltip tooltip-left tooltip-success"
data-id="${row.id}"
data-tip="Simpan"
disabled>
<i class="ph ph-floppy-disk"></i>
</button>
</div>`;
}
});
table = new DataTable('#example', {
ajax: {
url: tableAjaxUrl,
data: function (d) {
d.tahun = $('#filter_tahun').val();
},
dataSrc: 'data',
error: function (xhr, status, err) {
console.error('Gagal memuat data komposting:', err);
}
},
scrollX: true,
scrollCollapse: true,
autoWidth: false,
searching: false,
ordering: false,
paging: false,
info: false,
columns: columns,
fixedColumns: {
left: 6
},
createdRow: function (row, data) {
$(row).attr('data-row-id', data.id);
},
initComplete: function () {
$('div.dt-scroll-body thead').css('visibility', 'collapse');
}
});
$('#example').on('click', '.btn-edit-row', function () {
const rowId = $(this).data('id');
setRowEditingState(rowId, true);
});
$('#example').on('click', '.btn-save-row', function () {
const rowId = $(this).data('id');
saveRowChanges(rowId);
});
$('#filter_tahun').on('change', function () {
table.ajax.reload();
});
});
function buildStatusSelect(rowId, currentValue) {
const options = ['Aktif', 'Tidak Aktif']
.map(function (option) {
const selected = option === currentValue ? 'selected' : '';
return `<option value="${option}" ${selected}>${option}</option>`;
})
.join('');
return `<div class="flex justify-center">
<select class="select select-warning select-sm w-32 text-black"
data-field="status"
data-id="${rowId}"
name="status-${rowId}"
disabled>
${options}
</select>
</div>`;
}
function buildDecimalInput(rowId, fieldName, value) {
const displayValue = (typeof value === 'number' || typeof value === 'string') ? value : '';
return `<div class="flex justify-center">
<input type="number"
step="0.01"
min="0"
data-id="${rowId}"
data-field="${fieldName}"
name="${fieldName}-${rowId}"
value="${displayValue}"
class="input input-warning input-sm w-24 text-right text-black"
disabled />
</div>`;
}
function getRowById(rowId) {
return $(`#example tbody tr[data-row-id="${rowId}"]`);
}
function setRowEditingState(rowId, enableEditing) {
const $row = getRowById(rowId);
if ($row.length === 0) {
return;
}
$row.toggleClass('editing', enableEditing);
$row.find('select[data-field], input[data-field]').prop('disabled', !enableEditing);
$row.find('.btn-edit-row').prop('disabled', enableEditing);
$row.find('.btn-save-row').prop('disabled', !enableEditing);
if (enableEditing) {
const $firstInput = $row.find('input[data-field]').first();
if ($firstInput.length) {
$firstInput.trigger('focus');
}
}
}
function collectRowPayload(rowId) {
const id = parseInt(rowId, 10);
if (Number.isNaN(id)) {
return null;
}
const $row = getRowById(rowId);
if ($row.length === 0) {
return null;
}
const payload = {
Id: id,
Status: $row.find('select[data-field="status"]').val()
};
decimalFields.forEach(function (field) {
const $input = $row.find(`input[data-field="${field}"]`);
const rawValue = ($input.val() || '').trim();
payload[field.toUpperCase()] = rawValue === '' ? null : parseFloat(rawValue);
});
return payload;
}
function saveRowChanges(rowId) {
const payload = collectRowPayload(rowId);
if (!payload) {
Swal.fire({
icon: 'error',
title: 'Gagal',
text: 'Data tidak valid untuk disimpan.'
});
return;
}
$.ajax({
url: updateUrl,
method: 'POST',
contentType: 'application/json',
data: JSON.stringify(payload),
success: function (response) {
const successMessage = (response && response.message) ? response.message : 'Data berhasil disimpan.';
Swal.fire({
icon: 'success',
title: 'Berhasil',
text: successMessage
}).then(function () {
setRowEditingState(rowId, false);
table.ajax.reload(null, false);
});
},
error: function (xhr) {
const message = (xhr && xhr.responseJSON && xhr.responseJSON.message)
? xhr.responseJSON.message
: 'Terjadi kesalahan saat menyimpan data.';
Swal.fire({
icon: 'error',
title: 'Gagal',
text: message
});
}
});
}
</script>
}