feat(builder): implementasi native drag and drop homepage layout builder yang 100% aman

This commit is contained in:
Mas Budi Kusuma
2026-09-16 08:11:03 +07:00
parent e6e39f4fa9
commit 1cee7ecf5c
2 changed files with 459 additions and 288 deletions
+114
View File
@@ -908,3 +908,117 @@ function edukarsa_about_page_html() {
<?php
}
// =========================================================================
// FITUR BUILDER TATA LETAK BERANDA (DRAG & DROP NATIVE)
// =========================================================================
add_action('admin_menu', function() {
add_submenu_page(
'edukarsa_settings',
edukarsa_t( 'Tata Letak Beranda', 'Homepage Layout' ),
edukarsa_t( '🏗️ Tata Letak', '🏗️ Layout' ),
'manage_options',
'edukarsa_layout',
'edukarsa_layout_page_html'
);
});
add_action('admin_init', function() {
register_setting('edukarsa_layout_group', 'edukarsa_homepage_layout', 'sanitize_text_field');
});
function edukarsa_layout_page_html() {
if ( ! current_user_can( 'manage_options' ) ) return;
// Muat jQuery UI Sortable (Bawaan Inti WordPress)
wp_enqueue_script('jquery-ui-sortable');
$default_layout = array('stats','about','milestone','program','video','keunggulan','cta','news','faq');
$saved_layout = get_option('edukarsa_homepage_layout', implode(',', $default_layout));
$current_layout = explode(',', $saved_layout);
// Pastikan seksi baru tidak hilang jika pernah disimpan di format lama
foreach($default_layout as $sec) {
if(!in_array($sec, $current_layout)) $current_layout[] = $sec;
}
$section_names = array(
'stats' => edukarsa_t('📊 Statistik (3 Kotak Capaian)', '📊 Statistics Cards'),
'about' => edukarsa_t('👤 Sambutan & Profil Pimpinan', '👤 Welcome & Leader Profile'),
'milestone' => edukarsa_t('🏆 Rekam Jejak (Milestones)', '🏆 Milestones History'),
'program' => edukarsa_t('📚 Program Unggulan / Kurikulum', '📚 Featured Programs'),
'video' => edukarsa_t('🎬 Video Profil Parallax', '🎬 Parallax Videos'),
'keunggulan' => edukarsa_t('⭐ Poin Keunggulan (Grid Berurut)', '⭐ Advantages Grid'),
'cta' => edukarsa_t('📢 Banner Ajakan (CTA) Pendaftaran', '📢 Admission CTA Banner'),
'news' => edukarsa_t('📰 Berita & Warta Terkini', '📰 Latest News & Updates'),
'faq' => edukarsa_t('❓ Seksi Tanya Jawab (FAQ)', '❓ Frequently Asked Questions')
);
?>
<div class="wrap edukarsa-admin-wrap" style="max-width: 800px; margin-top: 25px;">
<div style="background: #ffffff; border: 1px solid #e2e8f0; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 15px rgba(0,0,0,0.03);">
<div style="padding: 25px 30px; background: #fafafa; border-bottom: 1px solid #f1f5f9;">
<h1 style="font-weight: 800; font-size: 22px; color: #0f172a; margin: 0 0 8px; line-height: 1.2;">
<?php echo esc_html(edukarsa_t('🏗️ Builder Tata Letak Beranda', '🏗️ Homepage Layout Builder')); ?>
</h1>
<p style="color: #64748b; font-size: 14px; margin: 0;">
<?php echo esc_html(edukarsa_t('Tahan dan geser (drag & drop) blok di bawah ini untuk mengatur urutan seksi di halaman beranda. Modul yang dimatikan di Pengaturan Utama akan otomatis dilewati.', 'Drag and drop the blocks below to rearrange the homepage sections. Modules disabled in Main Settings will be skipped automatically.')); ?>
</p>
</div>
<form action="options.php" method="post" style="padding: 30px;">
<?php settings_fields('edukarsa_layout_group'); ?>
<div style="background: #eef2ff; border: 1px solid #c7d2fe; padding: 16px 20px; border-radius: 8px; margin-bottom: 15px; font-weight: 700; color: #3730a3; display: flex; align-items: center; gap: 12px;">
<span style="font-size: 22px;">🔒</span>
<?php echo esc_html(edukarsa_t('🌟 Slider Banner (Terkunci di Posisi Teratas)', '🌟 Slider Banner (Locked at Very Top)')); ?>
</div>
<input type="hidden" name="edukarsa_homepage_layout" id="layout_order" value="<?php echo esc_attr(implode(',', $current_layout)); ?>">
<ul id="sortable-layout" style="margin: 0; padding: 0; list-style: none;">
<?php foreach($current_layout as $sec): if(isset($section_names[$sec])): ?>
<li data-id="<?php echo esc_attr($sec); ?>" style="background: #ffffff; border: 1px solid #cbd5e1; border-radius: 8px; padding: 16px 20px; margin-bottom: 12px; cursor: grab; display: flex; align-items: center; gap: 15px; transition: all 0.2s; position: relative;">
<span class="dashicons dashicons-menu-alt2" style="color: #94a3b8; font-size: 24px; display: flex; align-items: center; justify-content: center; width: 24px; height: 24px;"></span>
<span style="font-size: 15px; font-weight: 700; color: #1e293b; flex-grow: 1;"><?php echo esc_html($section_names[$sec]); ?></span>
<span style="font-size: 11px; font-weight: 800; color: #94a3b8; text-transform: uppercase; background: #f1f5f9; padding: 4px 10px; border-radius: 12px;">Draggable</span>
</li>
<?php endif; endforeach; ?>
</ul>
<div style="margin-top: 30px; text-align: right; border-top: 1px solid #f1f5f9; padding-top: 25px;">
<?php submit_button(edukarsa_t('Simpan Tata Letak', 'Save Layout Order'), 'primary large', 'submit', false, array('style'=>'border-radius:8px; font-weight:700; padding:8px 30px; font-size: 15px;')); ?>
</div>
</form>
</div>
</div>
<style>
#sortable-layout li:hover { box-shadow: 0 4px 12px rgba(11,74,142,0.08) !important; border-color: #0b4a8e !important; }
#sortable-layout li:hover .dashicons { color: #0b4a8e; }
.ui-sortable-helper { box-shadow: 0 15px 35px rgba(0,0,0,0.15) !important; transform: scale(1.02); z-index: 9999; border-color: #0b4a8e !important; }
.ui-sortable-placeholder { background: #f8fafc; border: 2px dashed #cbd5e1; border-radius: 8px; visibility: visible !important; height: 60px; margin-bottom: 12px; }
</style>
<script>
jQuery(document).ready(function($) {
$("#sortable-layout").sortable({
placeholder: "ui-sortable-placeholder",
cursor: "grabbing",
axis: "y",
containment: "parent",
tolerance: "pointer",
update: function(event, ui) {
var newOrder = [];
$("#sortable-layout li").each(function() {
newOrder.push($(this).data('id'));
});
$("#layout_order").val(newOrder.join(','));
}
});
$("#sortable-layout").disableSelection();
});
</script>
<?php
}