File: /mnt/data/dreamstour-wp/wp-content/page-template-add-tour11.php
<?php
/**
* Template Name: Dreams Template Add Tour
*/
// Check if user is logged in and has proper permissions
if (!is_user_logged_in()) {
wp_redirect(home_url());
exit;
}
// Check if user has proper role (administrator or subscriber)
$current_user = wp_get_current_user();
if (!in_array('administrator', $current_user->roles) && !in_array('agent', $current_user->roles)) {
wp_redirect(home_url());
exit;
}
// Check if editing existing tour
$edit_mode = false;
$tour_data = array();
$tour_id = 0;
if (isset($_GET['post_id']) && !empty($_GET['post_id'])) {
$tour_id = intval($_GET['post_id']);
$tour_post = get_post($tour_id);
if ($tour_post && $tour_post->post_type === 'tour') {
// Only the post author can edit
if ((int) $tour_post->post_author !== (int) $current_user->ID) {
wp_redirect(home_url());
exit;
}
$edit_mode = true;
// Migrate existing base64 images to attachment IDs if needed
migrate_itenary_images_to_attachments($tour_id);
// Get tour meta data
$tour_data = array(
'post_title' => $tour_post->post_title,
'post_content' => $tour_post->post_content,
'tour_start_date' => get_post_meta($tour_id, 'tour_start_date', true),
'tour_end_date' => get_post_meta($tour_id, 'tour_end_date', true),
'tour_destination' => get_post_meta($tour_id, 'tour_destination', true),
'tour_people_limit' => get_post_meta($tour_id, 'tour_people_limit', true),
'tour_price' => get_post_meta($tour_id, 'tour_price', true),
'tour_offer_price' => get_post_meta($tour_id, 'tour_offer_price', true),
'tour_min_age' => get_post_meta($tour_id, 'tour_min_age', true),
'tour_city' => get_post_meta($tour_id, 'tour_city', true),
'tour_state' => get_post_meta($tour_id, 'tour_state', true),
'tour_zip' => get_post_meta($tour_id, 'tour_zip', true),
'tour_address' => get_post_meta($tour_id, 'tour_address', true),
'tour_address_1' => get_post_meta($tour_id, 'tour_address_1', true),
'tour_highlights' => get_post_meta($tour_id, 'tour_highlights', true),
'tour_itenary' => get_post_meta($tour_id, 'tour_itenary', true),
'tour_faq' => get_post_meta($tour_id, 'tour_faq', true),
'tour_gallery' => get_post_meta($tour_id, 'tour_gallery', true),
);
// Get taxonomy terms
$tour_data['tour_category'] = wp_get_post_terms($tour_id, 'tour_category', array('fields' => 'ids'));
$tour_data['tour_activities'] = wp_get_post_terms($tour_id, 'tour_activities', array('fields' => 'ids'));
$tour_data['tour_includes'] = wp_get_post_terms($tour_id, 'tour_includes', array('fields' => 'ids'));
$tour_data['tour_excludes'] = wp_get_post_terms($tour_id, 'tour_excludes', array('fields' => 'ids'));
$tour_data['tour_country'] = wp_get_post_terms($tour_id, 'tour_country', array('fields' => 'ids'));
$tour_data['tour_duration_days'] = wp_get_post_terms($tour_id, 'tour_duration_days', array('fields' => 'ids'));
$tour_data['tour_duration_nights'] = wp_get_post_terms($tour_id, 'tour_duration_nights', array('fields' => 'ids'));
$tour_data['tour_why_book'] = wp_get_post_terms($tour_id, 'tour_why_book', array('fields' => 'ids'));
} else {
wp_redirect(home_url());
exit;
}
}
// Function to get itinerary image URL from attachment ID or base64 data
function get_itenary_image_url($image_data) {
if (empty($image_data)) {
return '';
}
// Check if it's an attachment ID (numeric)
if (is_numeric($image_data)) {
$attachment_id = intval($image_data);
$image_url = wp_get_attachment_image_url($attachment_id, 'medium');
return $image_url ? $image_url : '';
}
// Check if it's base64 data (for backward compatibility)
if (strpos($image_data, 'data:image/') === 0) {
return $image_data;
}
return '';
}
// Function to handle base64 image conversion to WordPress attachment
function handle_base64_image($base64_data, $post_id, $filename_prefix = 'image') {
// Include WordPress file handling functions
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/media.php');
require_once(ABSPATH . 'wp-admin/includes/image.php');
error_log("handle_base64_image called with prefix: $filename_prefix, post_id: $post_id");
// Parse the base64 data
if (preg_match('/^data:image\/(\w+);base64,/', $base64_data, $type)) {
$base64_data = substr($base64_data, strpos($base64_data, ',') + 1);
$type = strtolower($type[1]);
error_log("Detected image type: $type");
if (!in_array($type, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) {
error_log("Unsupported image type: $type");
return false;
}
$base64_data = str_replace(' ', '+', $base64_data);
$image_data = base64_decode($base64_data);
if ($image_data === false) {
error_log("Failed to decode base64 data");
return false;
}
error_log("Decoded image data size: " . strlen($image_data) . " bytes");
// Create a temporary file
$upload_dir = wp_upload_dir();
$filename = $filename_prefix . '_' . time() . '.' . $type;
$file_path = $upload_dir['path'] . '/' . $filename;
error_log("Saving file to: $file_path");
if (file_put_contents($file_path, $image_data)) {
error_log("File saved successfully");
// Create attachment
$attachment = array(
'post_mime_type' => 'image/' . $type,
'post_title' => sanitize_file_name($filename),
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment($attachment, $file_path, $post_id);
if (!is_wp_error($attach_id)) {
$attach_data = wp_generate_attachment_metadata($attach_id, $file_path);
wp_update_attachment_metadata($attach_id, $attach_data);
error_log("Created attachment with ID: $attach_id");
return $attach_id;
} else {
error_log("Failed to create attachment: " . $attach_id->get_error_message());
}
} else {
error_log("Failed to save file to: $file_path");
}
} else {
error_log("Invalid base64 data format");
}
return false;
}
// Function to migrate existing base64 images to attachment IDs
function migrate_itenary_images_to_attachments($tour_id) {
$itenary = get_post_meta($tour_id, 'tour_itenary', true);
if (empty($itenary) || !is_array($itenary)) {
return false;
}
$updated = false;
foreach ($itenary as $key => $item) {
if (!empty($item['image']) && strpos($item['image'], 'data:image/') === 0) {
$attachment_id = handle_base64_image($item['image'], $tour_id, 'itenary_migrated_' . $key);
if ($attachment_id) {
$itenary[$key]['image'] = $attachment_id;
$updated = true;
}
}
}
if ($updated) {
update_post_meta($tour_id, 'tour_itenary', $itenary);
return true;
}
return false;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['tour_nonce']) && wp_verify_nonce($_POST['tour_nonce'], 'save_tour')) {
// Include WordPress file handling functions
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/media.php');
require_once(ABSPATH . 'wp-admin/includes/image.php');
$user_id = get_current_user_id();
$is_edit = isset($_POST['edit_tour_id']) && !empty($_POST['edit_tour_id']);
if ($is_edit) {
// Update existing tour
$tour_id = intval($_POST['edit_tour_id']);
$tour_id = wp_update_post(array(
'ID' => $tour_id,
'post_title' => sanitize_text_field($_POST['tour_name']),
'post_content' => wp_kses_post($_POST['tour_description']),
'post_excerpt' => isset($_POST['tour_description']) ? wp_trim_words(wp_kses_post($_POST['tour_description']), 40, '') : '',
'post_name' => isset($_POST['tour_name']) ? sanitize_title(wp_unslash($_POST['tour_name'])) : '',
));
} else {
// Insert new tour post
$tour_id = wp_insert_post(array(
'post_type' => 'tour',
'post_status' => 'publish',
'post_title' => sanitize_text_field($_POST['tour_name']),
'post_content' => wp_kses_post($_POST['tour_description']),
'post_excerpt' => isset($_POST['tour_description']) ? wp_trim_words(wp_kses_post($_POST['tour_description']), 40, '') : '',
'post_author' => $user_id,
'post_name' => isset($_POST['tour_name']) ? sanitize_title(wp_unslash($_POST['tour_name'])) : '',
'comment_status' => 'closed',
'ping_status' => 'closed',
));
}
if ($tour_id && !is_wp_error($tour_id)) {
// Save Meta
$fields = [
'start_date' => 'tour_start_date',
'end_date' => 'tour_end_date',
'destination' => 'tour_destination',
'people_limit' => 'tour_people_limit',
'price' => 'tour_price',
'offer_price' => 'tour_offer_price',
'min_age' => 'tour_min_age',
'city' => 'tour_city',
'state' => 'tour_state',
'zip' => 'tour_zip',
'address' => 'tour_address',
'address1' => 'tour_address_1',
];
foreach ($fields as $field => $meta_key) {
if (!empty($_POST[$field])) {
update_post_meta($tour_id, $meta_key, sanitize_text_field($_POST[$field]));
}
}
// Highlights (array)
if (!empty($_POST['highlights'])) {
update_post_meta($tour_id, 'tour_highlights', array_map('sanitize_text_field', $_POST['highlights']));
}
// Itinerary
if (!empty($_POST['itenary_title'])) {
$itenary = [];
foreach ($_POST['itenary_title'] as $i => $title) {
if (!empty($title)) {
$image_id = '';
// Debug: Log what we're processing
error_log("Processing itinerary item $i: " . $title);
// First, check for uploaded file for this itinerary item
if (!empty($_FILES['itenary_images']['name'][$i])) {
error_log("Found uploaded file for itinerary $i: " . $_FILES['itenary_images']['name'][$i]);
$file = array(
'name' => $_FILES['itenary_images']['name'][$i],
'type' => $_FILES['itenary_images']['type'][$i],
'tmp_name' => $_FILES['itenary_images']['tmp_name'][$i],
'error' => $_FILES['itenary_images']['error'][$i],
'size' => $_FILES['itenary_images']['size'][$i]
);
$upload = wp_handle_upload($file, array('test_form' => false));
if (!isset($upload['error'])) {
$attachment = array(
'post_mime_type' => $upload['type'],
'post_title' => sanitize_file_name($file['name']),
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment($attachment, $upload['file'], $tour_id);
$attach_data = wp_generate_attachment_metadata($attach_id, $upload['file']);
wp_update_attachment_metadata($attach_id, $attach_data);
$image_id = $attach_id;
error_log("Created attachment ID: $attach_id for itinerary $i");
} else {
error_log("Upload error for itinerary $i: " . $upload['error']);
}
}
// If no uploaded file, check for base64, URL, or existing attachment ID
elseif (!empty($_POST['itenary_image'][$i])) {
$image_data = $_POST['itenary_image'][$i];
error_log("Found image data for itinerary $i: " . substr($image_data, 0, 50) . "...");
// Check if it's base64 data
if (strpos($image_data, 'data:image/') === 0) {
$image_id = handle_base64_image($image_data, $tour_id, 'itenary_' . $i);
error_log("Converted base64 to attachment ID: $image_id for itinerary $i");
}
// Check if it's a WordPress attachment URL
elseif (strpos($image_data, wp_upload_dir()['baseurl']) === 0) {
// Extract attachment ID from URL
$attachment_id = attachment_url_to_postid($image_data);
if ($attachment_id) {
$image_id = $attachment_id;
error_log("Found attachment ID from URL: $image_id for itinerary $i");
} else {
error_log("Could not find attachment ID for URL: $image_data");
}
} else {
// It's already an attachment ID
$image_id = intval($image_data);
error_log("Using existing attachment ID: $image_id for itinerary $i");
}
} else {
error_log("No image data found for itinerary $i");
}
$itenary[] = [
'title' => sanitize_text_field($title),
'date' => sanitize_text_field($_POST['itenary_date'][$i] ?? ''),
'time' => sanitize_text_field($_POST['itenary_time'][$i] ?? ''),
'description' => sanitize_textarea_field($_POST['itenary_description'][$i] ?? ''),
'image' => $image_id,
];
}
}
if (!empty($itenary)) {
update_post_meta($tour_id, 'tour_itenary', $itenary);
error_log("Saved itinerary data: " . print_r($itenary, true));
}
} else {
error_log("No itinerary titles found in POST data");
}
// FAQ
if (!empty($_POST['faq_question'])) {
$faq = [];
foreach ($_POST['faq_question'] as $i => $q) {
if (!empty($q)) {
$faq[] = [
'question' => sanitize_text_field($q),
'answer' => sanitize_textarea_field($_POST['faq_answer'][$i] ?? ''),
];
}
}
if (!empty($faq)) {
update_post_meta($tour_id, 'tour_faq', $faq);
}
}
// Taxonomies
$taxonomy_map = [
'category' => 'tour_category',
'activities' => 'tour_activities',
'includes' => 'tour_includes',
'excludes' => 'tour_excludes',
'country' => 'tour_country',
'duration_days' => 'tour_duration_days',
'duration_nights' => 'tour_duration_nights',
'why_book' => 'tour_why_book',
];
foreach ($taxonomy_map as $field => $taxonomy) {
if (!empty($_POST[$field])) {
$terms = is_array($_POST[$field]) ? array_map('intval', $_POST[$field]) : intval($_POST[$field]);
wp_set_object_terms($tour_id, $terms, $taxonomy);
}
}
// Handle gallery deletions first
if (!empty($_POST['delete_gallery_images'])) {
$existing_gallery = get_post_meta($tour_id, 'tour_gallery', true);
if (is_array($existing_gallery)) {
$delete_ids = array_map('intval', $_POST['delete_gallery_images']);
$updated_gallery = array_diff($existing_gallery, $delete_ids);
update_post_meta($tour_id, 'tour_gallery', array_values($updated_gallery));
// Delete the actual attachment files
foreach ($delete_ids as $delete_id) {
wp_delete_attachment($delete_id, true);
}
}
}
// Handle gallery uploads
if (!empty($_FILES['gallery_images']['name'][0])) {
$existing_gallery = get_post_meta($tour_id, 'tour_gallery', true);
$gallery_ids = is_array($existing_gallery) ? $existing_gallery : [];
$upload_dir = wp_upload_dir();
foreach ($_FILES['gallery_images']['name'] as $key => $filename) {
if (!empty($filename)) {
$file = array(
'name' => $_FILES['gallery_images']['name'][$key],
'type' => $_FILES['gallery_images']['type'][$key],
'tmp_name' => $_FILES['gallery_images']['tmp_name'][$key],
'error' => $_FILES['gallery_images']['error'][$key],
'size' => $_FILES['gallery_images']['size'][$key]
);
$upload = wp_handle_upload($file, array('test_form' => false));
if (!isset($upload['error'])) {
$attachment = array(
'post_mime_type' => $upload['type'],
'post_title' => sanitize_file_name($filename),
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment($attachment, $upload['file'], $tour_id);
$attach_data = wp_generate_attachment_metadata($attach_id, $upload['file']);
wp_update_attachment_metadata($attach_id, $attach_data);
$gallery_ids[] = $attach_id;
}
}
}
if (!empty($gallery_ids)) {
update_post_meta($tour_id, 'tour_gallery', array_unique($gallery_ids));
}
}
// Redirect to tour page
wp_redirect(get_permalink($tour_id));
exit;
}
}
get_header();
?>
<!-- Page Wrapper -->
<div class="content">
<div class="container">
<div class="row">
<!-- Sidebar -->
<div class="col-lg-3 theiaStickySidebar">
<div class="card border-0 mb-4 mb-lg-0">
<div class="card-body">
<div>
<h5 class="mb-3"><?php echo $edit_mode ? esc_html__('Edit Tour', 'dreams-tour') : esc_html__('Add Tour', 'dreams-tour'); ?></h5>
<ul class="add-tab-list">
<li><a href="#basic_info" class="active"><?php esc_html_e('Tour Details', 'dreams-tour'); ?></a></li>
<li><a href="#location"><?php esc_html_e('Locations', 'dreams-tour'); ?></a></li>
<li><a href="#highlights"><?php esc_html_e('Highlights', 'dreams-tour'); ?></a></li>
<li><a href="#room_types"><?php esc_html_e('Activities', 'dreams-tour'); ?></a></li>
<li><a href="#popular_amenities"><?php esc_html_e('Includes', 'dreams-tour'); ?></a></li>
<li><a href="#excludes"><?php esc_html_e('Excludes', 'dreams-tour'); ?></a></li>
<li><a href="#itenary"><?php esc_html_e('Itenary', 'dreams-tour'); ?></a></li>
<li><a href="#faq"><?php esc_html_e('FAQ', 'dreams-tour'); ?></a></li>
<li><a href="#gallery"><?php esc_html_e('Gallery', 'dreams-tour'); ?></a></li>
<li><a href="#description"><?php esc_html_e('Description', 'dreams-tour'); ?></a></li>
</ul>
</div>
</div>
</div>
</div>
<!-- /Sidebar -->
<!-- Add Tour -->
<div class="col-lg-9">
<form action="" method="post" enctype="multipart/form-data">
<?php wp_nonce_field('save_tour', 'tour_nonce'); ?>
<?php if ($edit_mode): ?>
<input type="hidden" name="edit_tour_id" value="<?php echo esc_attr($tour_id); ?>" />
<?php endif; ?>
<div class="card shadow-none" id="basic_info">
<div class="card-header">
<div class="d-flex align-items-center justify-content-between">
<h5 class="fs-18"><?php esc_html_e('Tour Details', 'dreams-tour'); ?></h5>
</div>
</div>
<div class="card-body pb-1">
<div class="row">
<div class="col-md-12">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Tour Name', 'dreams-tour'); ?></label>
<input type="text" class="form-control" name="tour_name" value="<?php echo $edit_mode ? esc_attr($tour_data['post_title']) : ''; ?>" />
</div>
</div>
<div class="col-lg-4 col-md-6">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Category', 'dreams-tour'); ?></label>
<select class="select" name="category">
<option value=""><?php esc_html_e('Select', 'dreams-tour'); ?></option>
<?php
$dt_categories = get_terms(array('taxonomy' => 'tour_category', 'hide_empty' => false));
$selected_category = $edit_mode && !empty($tour_data['tour_category']) ? $tour_data['tour_category'][0] : '';
if (!is_wp_error($dt_categories)) {
foreach ($dt_categories as $dt_cat) {
$selected = ($selected_category == $dt_cat->term_id) ? 'selected' : '';
echo '<option value="' . esc_attr($dt_cat->term_id) . '" ' . $selected . '>' . esc_html($dt_cat->name) . '</option>';
}
}
?>
</select>
</div>
</div>
<div class="col-lg-4 col-md-6">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Start Date', 'dreams-tour'); ?></label>
<div class="input-icon-end position-relative">
<input type="text" class="form-control datetimepicker" placeholder="<?php esc_attr_e('dd/mm/yyyy', 'dreams-tour'); ?>" name="start_date" value="<?php echo $edit_mode ? esc_attr($tour_data['tour_start_date']) : ''; ?>">
<span class="input-icon-addon">
<i class="isax isax-calendar"></i>
</span>
</div>
</div>
</div>
<div class="col-lg-4 col-md-6">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('End Date', 'dreams-tour'); ?></label>
<div class="input-icon-end position-relative">
<input type="text" class="form-control datetimepicker" placeholder="<?php esc_attr_e('dd/mm/yyyy', 'dreams-tour'); ?>" name="end_date" value="<?php echo $edit_mode ? esc_attr($tour_data['tour_end_date']) : ''; ?>">
<span class="input-icon-addon">
<i class="isax isax-calendar"></i>
</span>
</div>
</div>
</div>
<div class="col-lg-4 col-md-6">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Destination', 'dreams-tour'); ?></label>
<input type="text" class="form-control" name="destination" value="<?php echo $edit_mode ? esc_attr($tour_data['tour_destination']) : ''; ?>" />
</div>
</div>
<div class="col-lg-4 col-md-6">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Duration (Days)', 'dreams-tour'); ?></label>
<select class="select" name="duration_days">
<option value=""><?php esc_html_e('Select', 'dreams-tour'); ?></option>
<?php
$dt_days_selected = $edit_mode && !empty($tour_data['tour_duration_days']) ? $tour_data['tour_duration_days'][0] : 0;
$dt_days_terms = get_terms(array('taxonomy' => 'tour_duration_days', 'hide_empty' => false));
if (!is_wp_error($dt_days_terms)) {
foreach ($dt_days_terms as $term) {
echo '<option value="' . esc_attr($term->term_id) . '"' . selected($dt_days_selected, $term->term_id, false) . '>' . esc_html($term->name) . '</option>';
}
}
?>
</select>
</div>
</div>
<div class="col-lg-4 col-md-6">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Duration (Nights)', 'dreams-tour'); ?></label>
<select class="select" name="duration_nights">
<option value=""><?php esc_html_e('Select', 'dreams-tour'); ?></option>
<?php
$dt_nights_selected = $edit_mode && !empty($tour_data['tour_duration_nights']) ? $tour_data['tour_duration_nights'][0] : 0;
$dt_nights_terms = get_terms(array('taxonomy' => 'tour_duration_nights', 'hide_empty' => false));
if (!is_wp_error($dt_nights_terms)) {
foreach ($dt_nights_terms as $term) {
echo '<option value="' . esc_attr($term->term_id) . '"' . selected($dt_nights_selected, $term->term_id, false) . '>' . esc_html($term->name) . '</option>';
}
}
?>
</select>
</div>
</div>
<div class="col-lg-4 col-md-6">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Total Number Of Peoples Alloted', 'dreams-tour'); ?></label>
<input type="text" class="form-control" name="people_limit" value="<?php echo $edit_mode ? esc_attr($tour_data['tour_people_limit']) : ''; ?>" />
</div>
</div>
<div class="col-lg-4 col-md-6">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Pricing (USD)', 'dreams-tour'); ?></label>
<input type="text" class="form-control" name="price" value="<?php echo $edit_mode ? esc_attr($tour_data['tour_price']) : ''; ?>" />
</div>
</div>
<div class="col-lg-4 col-md-6">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Offer Price (USD)', 'dreams-tour'); ?></label>
<input type="text" class="form-control" name="offer_price" value="<?php echo $edit_mode ? esc_attr($tour_data['tour_offer_price']) : ''; ?>" />
</div>
</div>
<div class="col-lg-4 col-md-6">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Min Age', 'dreams-tour'); ?></label>
<input type="text" class="form-control" name="min_age" value="<?php echo $edit_mode ? esc_attr($tour_data['tour_min_age']) : ''; ?>" />
</div>
</div>
</div>
</div>
</div>
<div class="card shadow-none" id="location">
<div class="card-header">
<div class="d-flex align-items-center justify-content-between">
<h5 class="fs-18"><?php esc_html_e('Location', 'dreams-tour'); ?></h5>
</div>
</div>
<div class="card-body pb-1">
<div class="row">
<div class="col-xl-3 col-md-6">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Country', 'dreams-tour'); ?></label>
<select class="select" name="country">
<option value=""><?php esc_html_e('Select', 'dreams-tour'); ?></option>
<?php
$dt_countries = get_terms(array('taxonomy' => 'tour_country', 'hide_empty' => false));
$selected_country = $edit_mode && !empty($tour_data['tour_country']) ? $tour_data['tour_country'][0] : '';
if (!is_wp_error($dt_countries)) {
foreach ($dt_countries as $dt_country) {
$selected = ($selected_country == $dt_country->term_id) ? 'selected' : '';
echo '<option value="' . esc_attr($dt_country->term_id) . '" ' . $selected . '>' . esc_html($dt_country->name) . '</option>';
}
}
?>
</select>
</div>
</div>
<div class="col-xl-3 col-md-6">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('City', 'dreams-tour'); ?></label>
<input type="text" class="form-control" name="city" value="<?php echo $edit_mode ? esc_attr($tour_data['tour_city']) : ''; ?>" />
</div>
</div>
<div class="col-xl-3 col-md-6">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('State', 'dreams-tour'); ?></label>
<input type="text" class="form-control" name="state" value="<?php echo $edit_mode ? esc_attr($tour_data['tour_state']) : ''; ?>" />
</div>
</div>
<div class="col-xl-3 col-md-6">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Zip Code', 'dreams-tour'); ?></label>
<input type="text" class="form-control" name="zip" value="<?php echo $edit_mode ? esc_attr($tour_data['tour_zip']) : ''; ?>" />
</div>
</div>
<div class="col-md-12">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Address', 'dreams-tour'); ?></label>
<input type="text" class="form-control" name="address" value="<?php echo $edit_mode ? esc_attr($tour_data['tour_address']) : ''; ?>" />
</div>
</div>
<div class="col-md-12">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Address 1', 'dreams-tour'); ?></label>
<input type="text" class="form-control" name="address1" value="<?php echo $edit_mode ? esc_attr($tour_data['tour_address_1']) : ''; ?>" />
</div>
</div>
</div>
</div>
</div>
<div class="card shadow-none" id="highlights">
<div class="card-header">
<div class="d-flex align-items-center justify-content-between">
<h5 class="fs-18"><?php esc_html_e('Highlights', 'dreams-tour'); ?></h5>
</div>
</div>
<div class="card-body">
<div class="row add-highlight-info">
<?php if ($edit_mode && !empty($tour_data['tour_highlights'])): ?>
<?php foreach ($tour_data['tour_highlights'] as $highlight): ?>
<div class="col-md-12 highlight-info">
<div class="mb-3">
<div class="d-flex align-items-center">
<input type="text" class="form-control me-2" name="highlights[]" value="<?php echo esc_attr($highlight); ?>" placeholder="<?php esc_attr_e('Enter highlight', 'dreams-tour'); ?>">
<a href="javascript:void(0);" class="text-danger trash-icon d-flex align-items-center justify-content-center ms-3 remove-highlight"><i class="isax isax-trash"></i></a>
</div>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<div class="col-md-12">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Highlights', 'dreams-tour'); ?></label>
<input type="text" class="form-control" name="highlights[]" />
</div>
</div>
<?php endif; ?>
</div>
<div>
<a href="javascript:void(0);" class="btn btn-primary btn-sm add-highlight"><i class="isax isax-add-circle me-1"></i><?php esc_html_e('Add New', 'dreams-tour'); ?></a>
</div>
</div>
</div>
<div class="card shadow-none" id="room_types">
<div class="card-header">
<div class="d-flex align-items-center justify-content-between">
<h5 class="fs-18"><?php esc_html_e('Activities', 'dreams-tour'); ?></h5>
</div>
</div>
<div class="card-body pb-1">
<div class="row">
<?php
$dt_activities = get_terms(array('taxonomy' => 'tour_activities', 'hide_empty' => false));
$selected_activities = $edit_mode && !empty($tour_data['tour_activities']) ? $tour_data['tour_activities'] : array();
if (!is_wp_error($dt_activities) && !empty($dt_activities)) {
$chunks = array_chunk($dt_activities, ceil(count($dt_activities) / 3));
foreach ($chunks as $chunk) {
echo '<div class="col-lg-4 col-md-6"><div class="mb-3">';
foreach ($chunk as $term) {
$id = 'activity-' . esc_attr($term->term_id);
$checked = in_array($term->term_id, $selected_activities) ? 'checked' : '';
echo '<div class="form-check d-flex align-items-center ps-0 mb-2">';
echo '<input class="form-check-input ms-0 mt-0" type="checkbox" id="' . $id . '" name="activities[]" value="' . esc_attr($term->term_id) . '" ' . $checked . '>';
echo '<label class="form-check-label ms-2" for="' . $id . '">';
echo esc_html($term->name);
echo '</label></div>';
}
echo '</div></div>';
}
}
?>
</div>
</div>
</div>
<!-- Why Book With Us -->
<div class="card shadow-none" id="why_book_with_us">
<div class="card-header">
<div class="d-flex align-items-center justify-content-between">
<h5 class="fs-18"><?php esc_html_e('Why Book With Us', 'dreams-tour'); ?></h5>
</div>
</div>
<div class="card-body pb-1">
<div class="row">
<?php
$dt_why = get_terms(array('taxonomy' => 'tour_why_book', 'hide_empty' => false));
$selected_why = $edit_mode && !empty($tour_data['tour_why_book']) ? $tour_data['tour_why_book'] : array();
if (!is_wp_error($dt_why) && !empty($dt_why)) {
$chunks = array_chunk($dt_why, ceil(count($dt_why) / 3));
foreach ($chunks as $chunk) {
echo '<div class="col-lg-4 col-md-6"><div class="mb-3">';
foreach ($chunk as $term) {
$id = 'why-' . esc_attr($term->term_id);
$checked = in_array($term->term_id, $selected_why) ? 'checked' : '';
echo '<div class="form-check d-flex align-items-center ps-0 mb-2">';
echo '<input class="form-check-input ms-0 mt-0" type="checkbox" id="' . $id . '" name="why_book[]" value="' . esc_attr($term->term_id) . '" ' . $checked . '>';
echo '<label class="form-check-label ms-2" for="' . $id . '">';
echo esc_html($term->name);
echo '</label></div>';
}
echo '</div></div>';
}
}
?>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6">
<div class="card shadow-none" id="popular_amenities">
<div class="card-header">
<div class="d-flex align-items-center justify-content-between">
<h5 class="fs-18"><?php esc_html_e('Includes', 'dreams-tour'); ?></h5>
</div>
</div>
<div class="card-body pb-1">
<div>
<div class="mb-3">
<?php
$dt_includes = get_terms(array('taxonomy' => 'tour_includes', 'hide_empty' => false));
$selected_includes = $edit_mode && !empty($tour_data['tour_includes']) ? $tour_data['tour_includes'] : array();
if (!is_wp_error($dt_includes)) {
foreach ($dt_includes as $term) {
$id = 'include-' . esc_attr($term->term_id);
$checked = in_array($term->term_id, $selected_includes) ? 'checked' : '';
echo '<div class="form-check d-flex align-items-center ps-0 mb-2">';
echo '<input class="form-check-input ms-0 mt-0" type="checkbox" id="' . $id . '" name="includes[]" value="' . esc_attr($term->term_id) . '" ' . $checked . '>';
echo '<label class="form-check-label ms-2" for="' . $id . '">';
echo esc_html($term->name);
echo '</label></div>';
}
}
?>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="card shadow-none" id="excludes">
<div class="card-header">
<div class="d-flex align-items-center justify-content-between">
<h5 class="fs-18"><?php esc_html_e('Excludes', 'dreams-tour'); ?></h5>
</div>
</div>
<div class="card-body pb-1">
<div>
<div class="mb-3">
<?php
$dt_excludes = get_terms(array('taxonomy' => 'tour_excludes', 'hide_empty' => false));
$selected_excludes = $edit_mode && !empty($tour_data['tour_excludes']) ? $tour_data['tour_excludes'] : array();
if (!is_wp_error($dt_excludes)) {
foreach ($dt_excludes as $term) {
$id = 'exclude-' . esc_attr($term->term_id);
$checked = in_array($term->term_id, $selected_excludes) ? 'checked' : '';
echo '<div class="form-check d-flex align-items-center ps-0 mb-2">';
echo '<input class="form-check-input ms-0 mt-0" type="checkbox" id="' . $id . '" name="excludes[]" value="' . esc_attr($term->term_id) . '" ' . $checked . '>';
echo '<label class="form-check-label ms-2" for="' . $id . '">';
echo esc_html($term->name);
echo '</label></div>';
}
}
?>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card shadow-none" id="itenary">
<div class="card-header">
<h5 class="fs-18"><?php esc_html_e('Itenary', 'dreams-tour'); ?></h5>
</div>
<div class="card-body ">
<div>
<a href="javascript:void(0);" class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#add_itenary">
<i class="isax isax-add-circle me-1"></i><?php esc_html_e('Add New', 'dreams-tour'); ?>
</a>
</div>
<?php
// Check if we have existing itinerary data from edit mode
if ($edit_mode && !empty($tour_data['tour_itenary'])) {
foreach ($tour_data['tour_itenary'] as $idx => $itenary_item) {
$title = isset($itenary_item['title']) ? $itenary_item['title'] : '';
$date = isset($itenary_item['date']) ? $itenary_item['date'] : '';
$description = isset($itenary_item['description']) ? $itenary_item['description'] : '';
$image = isset($itenary_item['image']) ? $itenary_item['image'] : '';
echo '<div class="card shadow-none mb-0 mt-3 itenary-item" data-index="' . $idx . '">';
echo '<div class="card-body px-3 py-2">';
echo '<div class="d-flex align-items-start justify-content-between flex-wrap row-gap-3">';
echo '<div class="flex-grow-1">';
echo '<h6><a href="javascript:void(0);">' . esc_html($title) . '</a></h6>';
if ($date) {
$display_dt = $date;
$display_tm = isset($itenary_item['time']) ? trim($itenary_item['time']) : '';
if ($display_tm !== '') { $display_dt .= ' ' . $display_tm; }
echo '<p class="text-muted mb-1"><i class="isax isax-calendar me-1"></i>' . esc_html($display_dt) . '</p>';
}
if ($description) {
echo '<p class="mb-2">' . esc_html(wp_trim_words($description, 20, '...')) . '</p>';
}
if ($image) {
$image_url = get_itenary_image_url($image);
if ($image_url) {
echo '<div class="itenary-image-preview mb-2">';
echo '<img src="' . esc_url($image_url) . '" alt="Itinerary Image" style="max-width: 100px; height: auto; border-radius: 4px;">';
echo '</div>';
}
}
echo '</div>';
echo '<div class="d-flex align-items-center">';
echo '<a href="javascript:void(0);" data-bs-toggle="modal" data-bs-target="#edit_itenary" class="rounded-edit d-flex align-items-center justify-content-center me-2 edit-itenary-btn" data-index="' . $idx . '"><i class="isax isax-edit-2"></i></a>';
echo '<a href="javascript:void(0);" class="trash-icon d-flex align-items-center justify-content-center remove-itenary"><i class="isax isax-trash text-danger"></i></a>';
echo '</div></div></div></div>';
echo '<input type="hidden" name="itenary_title[]" value="' . esc_attr($title) . '" />';
echo '<input type="hidden" name="itenary_date[]" value="' . esc_attr($date) . '" />';
$time = isset($itenary_item['time']) ? $itenary_item['time'] : '';
echo '<input type="hidden" name="itenary_time[]" value="' . esc_attr($time) . '" />';
echo '<textarea name="itenary_description[]" style="display:none;">' . esc_textarea($description) . '</textarea>';
$image_url = get_itenary_image_url($image);
echo '<input type="hidden" name="itenary_image[]" value="' . esc_attr($image_url) . '" />';
}
} else {
// Handle POST data for new additions
$dt_itenary_titles = isset($_POST['itenary_title']) && is_array($_POST['itenary_title']) ? array_map('sanitize_text_field', $_POST['itenary_title']) : array();
$dt_itenary_dates = isset($_POST['itenary_date']) && is_array($_POST['itenary_date']) ? array_map('sanitize_text_field', $_POST['itenary_date']) : array();
$dt_itenary_times = isset($_POST['itenary_time']) && is_array($_POST['itenary_time']) ? array_map('sanitize_text_field', $_POST['itenary_time']) : array();
$dt_itenary_descriptions = isset($_POST['itenary_description']) && is_array($_POST['itenary_description']) ? array_map('sanitize_textarea_field', $_POST['itenary_description']) : array();
$dt_itenary_images = isset($_POST['itenary_image']) && is_array($_POST['itenary_image']) ? array_map('sanitize_text_field', $_POST['itenary_image']) : array();
if (!empty($dt_itenary_titles)) {
foreach ($dt_itenary_titles as $idx => $title) {
$date = isset($dt_itenary_dates[$idx]) ? $dt_itenary_dates[$idx] : '';
$description = isset($dt_itenary_descriptions[$idx]) ? $dt_itenary_descriptions[$idx] : '';
$image = isset($dt_itenary_images[$idx]) ? $dt_itenary_images[$idx] : '';
echo '<div class="card shadow-none mb-0 mt-3 itenary-item" data-index="' . $idx . '">';
echo '<div class="card-body px-3 py-2">';
echo '<div class="d-flex align-items-start justify-content-between flex-wrap row-gap-3">';
echo '<div class="flex-grow-1">';
echo '<h6><a href="javascript:void(0);">' . esc_html($title) . '</a></h6>';
if ($date) {
$display_dt = $date;
$display_tm = isset($dt_itenary_times[$idx]) ? trim($dt_itenary_times[$idx]) : '';
if ($display_tm !== '') { $display_dt .= ' ' . $display_tm; }
echo '<p class="text-muted mb-1"><i class="isax isax-calendar me-1"></i>' . esc_html($display_dt) . '</p>';
}
if ($description) {
echo '<p class="mb-2">' . esc_html(wp_trim_words($description, 20, '...')) . '</p>';
}
if ($image) {
$image_url = get_itenary_image_url($image);
if ($image_url) {
echo '<div class="itenary-image-preview mb-2">';
echo '<img src="' . esc_url($image_url) . '" alt="Itinerary Image" style="max-width: 100px; height: auto; border-radius: 4px;">';
echo '</div>';
}
}
echo '</div>';
echo '<div class="d-flex align-items-center">';
echo '<a href="javascript:void(0);" data-bs-toggle="modal" data-bs-target="#edit_itenary" class="rounded-edit d-flex align-items-center justify-content-center me-2 edit-itenary-btn" data-index="' . $idx . '"><i class="isax isax-edit-2"></i></a>';
echo '<a href="javascript:void(0);" class="trash-icon d-flex align-items-center justify-content-center remove-itenary"><i class="isax isax-trash text-danger"></i></a>';
echo '</div></div></div></div>';
echo '<input type="hidden" name="itenary_title[]" value="' . esc_attr($title) . '" />';
echo '<input type="hidden" name="itenary_date[]" value="' . esc_attr($date) . '" />';
$time = isset($dt_itenary_times[$idx]) ? $dt_itenary_times[$idx] : '';
echo '<input type="hidden" name="itenary_time[]" value="' . esc_attr($time) . '" />';
echo '<textarea name="itenary_description[]" style="display:none;">' . esc_textarea($description) . '</textarea>';
$image_url = get_itenary_image_url($image);
echo '<input type="hidden" name="itenary_image[]" value="' . esc_attr($image_url) . '" />';
}
}
}
?>
<div class="itenary_append"></div>
</div>
</div>
<div class="card shadow-none" id="faq">
<div class="card-header">
<h5 class="fs-18"><?php esc_html_e('FAQ', 'dreams-tour'); ?></h5>
</div>
<div class="card-body ">
<div>
<a href="javascript:void(0);" class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#add_faq">
<i class="isax isax-add-circle me-1"></i><?php esc_html_e('Add New', 'dreams-tour'); ?>
</a>
</div>
<?php
// Check if we have existing FAQ data from edit mode
if ($edit_mode && !empty($tour_data['tour_faq'])) {
foreach ($tour_data['tour_faq'] as $i => $faq_item) {
$q = isset($faq_item['question']) ? $faq_item['question'] : '';
$a = isset($faq_item['answer']) ? $faq_item['answer'] : '';
if ($q) { ?>
<div class="card shadow-none mb-0 mt-3 faq-item">
<div class="card-body px-3 py-2">
<div class="d-flex align-items-center justify-content-between flex-wrap row-gap-3">
<h6><a href="javascript:void(0);"> <?php echo esc_html($q); ?></a></h6>
<div class="d-flex align-items-center">
<a href="javascript:void(0);" data-bs-toggle="modal" data-bs-target="#edit_faq" class="rounded-edit d-flex align-items-center justify-content-center me-2 edit-faq-btn"><i class="isax isax-edit-2"></i></a>
<a href="javascript:void(0);" class="trash-icon d-flex align-items-center justify-content-center remove-faq"><i class="isax isax-trash text-danger"></i></a>
</div></div></div></div>
<input type="hidden" name="faq_question[]" value="<?php echo esc_attr($q); ?>" />
<textarea name="faq_answer[]" style="display:none;"><?php echo esc_textarea($a); ?></textarea>
<?php }
}
} else {
// Handle POST data for new additions
$dt_faq_q = isset($_POST['faq_question']) && is_array($_POST['faq_question']) ? array_map('sanitize_text_field', $_POST['faq_question']) : array();
$dt_faq_a = isset($_POST['faq_answer']) && is_array($_POST['faq_answer']) ? array_map('sanitize_textarea_field', $_POST['faq_answer']) : array();
if (!empty($dt_faq_q)) {
foreach ($dt_faq_q as $i => $q) {
$a = isset($dt_faq_a[$i]) ? $dt_faq_a[$i] : ''; ?>
<div class="card shadow-none mb-0 mt-3 faq-item">
<div class="card-body px-3 py-2">
<div class="d-flex align-items-center justify-content-between flex-wrap row-gap-3">
<h6><a href="javascript:void(0);"> <?php echo esc_html($q); ?></a></h6>
<div class="d-flex align-items-center">
<a href="javascript:void(0);" data-bs-toggle="modal" data-bs-target="#edit_faq" class="rounded-edit d-flex align-items-center justify-content-center me-2 edit-faq-btn"><i class="isax isax-edit-2"></i></a>
<a href="javascript:void(0);" class="trash-icon d-flex align-items-center justify-content-center remove-faq"><i class="isax isax-trash text-danger"></i></a>
</div></div></div></div>
<input type="hidden" name="faq_question[]" value="<?php echo esc_attr($q); ?>" />
<textarea name="faq_answer[]" style="display:none;"><?php echo esc_textarea($a); ?></textarea>
<?php }
}
}
?>
<div class="faq_append">
</div>
</div>
</div>
<div class="card shadow-none" id="gallery">
<div class="card-header">
<h5 class="fs-18"><?php esc_html_e('Gallery', 'dreams-tour'); ?></h5>
</div>
<div class="card-body">
<div class="file-upload drag-file w-100 d-flex align-items-center justify-content-center flex-column mb-2">
<span class="upload-img d-block mb-2"><i class="isax isax-document-upload fs-24"></i></span>
<h6 class="mb-1"><?php esc_html_e('Upload Gallery Images', 'dreams-tour'); ?></h6>
<p class="mb-0"><?php esc_html_e('Upload Feature Image First, Image size should below 5MB', 'dreams-tour'); ?></p>
<input type="file" name="gallery_images[]" accept="image/*" multiple>
</div>
<div class="gallery-preview d-flex align-items-center flex-wrap">
<?php if ($edit_mode && !empty($tour_data['tour_gallery'])): ?>
<?php foreach ($tour_data['tour_gallery'] as $image_id): ?>
<?php $image_url = wp_get_attachment_url($image_id); ?>
<?php if ($image_url): ?>
<div class="gallery-upload-img me-2 mb-2">
<img src="<?php echo esc_url($image_url); ?>" alt="Gallery Image" style="width: 100px; height: 100px; object-fit: cover; border-radius: 4px;">
<span class="trash-icon d-flex align-items-center justify-content-center text-danger gallery-trash" data-image-id="<?php echo esc_attr($image_id); ?>"><i class="isax isax-trash"></i></span>
</div>
<?php endif; ?>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
</div>
<div class="card shadow-none" id="description">
<div class="card-header">
<h5 class="fs-18"><?php esc_html_e('Description', 'dreams-tour'); ?></h5>
</div>
<!-- <div class="card-body text-editor">
<div class="snow-editor"></div>
<textarea name="tour_description" style="display:none;"><?php echo $edit_mode ? esc_textarea($tour_data['post_content']) : ''; ?></textarea>
</div> -->
<div class="card-body text-editor">
<?php
$content = $edit_mode ? $tour_data['post_content'] : '';
$editor_id = 'tour_description'; // same name/id for textarea
wp_editor(
$content,
$editor_id,
array(
'textarea_name' => 'tour_description', // important for $_POST
'media_buttons' => true, // set true if you want media uploader
'teeny' => true, // simple editor
'quicktags' => true, // enable/disable text (HTML) tab
'textarea_rows' => 8,
)
);
?>
</div>
</div>
<div class="d-flex align-items-center justify-content-center">
<button type="button" class="btn btn-light me-2"><?php esc_html_e('Reset', 'dreams-tour'); ?></button>
<button type="submit" class="btn btn-primary"><?php echo $edit_mode ? esc_html__('Update Tour', 'dreams-tour') : esc_html__('Add New Tour', 'dreams-tour'); ?></button>
</div>
</form>
</div>
<!-- /Add Tour -->
</div>
</div>
</div>
<!-- /Page Wrapper -->
<!-- Add Faq Modal -->
<div class="modal fade" id="add_faq">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5>Add New FAQ</h5>
<button data-bs-dismiss="modal" aria-label="close" class="btn-close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Question', 'dreams-tour'); ?> <span class="text-danger"> *</span></label>
<input type="text" class="form-control" id="faq_question_input">
</div>
<div>
<label class="form-label"><?php esc_html_e('Answer', 'dreams-tour'); ?> <span class="text-danger"> *</span></label>
<textarea class="form-control" id="faq_answer_input" rows="3"></textarea>
</div>
</div>
<div class="modal-footer">
<div class="d-flex align-items-center justify-content-end m-0">
<button type="button" data-bs-dismiss="modal" class="btn btn-sm btn-light me-2"><?php esc_html_e('Cancel', 'dreams-tour'); ?></button>
<button type="button" id="add_faq_btn" class="btn btn-sm btn-primary"><?php esc_html_e('Add FAQ', 'dreams-tour'); ?></button>
</div>
</div>
</div>
</div>
</div>
<!-- /Add Faq Modal -->
<!-- Faq Modal -->
<div class="modal fade" id="edit_faq">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5>Edit FAQ</h5>
<button data-bs-dismiss="modal" aria-label="close" class="btn-close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Question', 'dreams-tour'); ?> <span class="text-danger"> *</span></label>
<input type="text" class="form-control" id="edit_faq_question_input" placeholder="<?php esc_attr_e('Enter question', 'dreams-tour'); ?>">
</div>
<div>
<label class="form-label"><?php esc_html_e('Answer', 'dreams-tour'); ?> <span class="text-danger"> *</span></label>
<textarea class="form-control" id="edit_faq_answer_input" rows="3" placeholder="<?php esc_attr_e('Enter answer', 'dreams-tour'); ?>"></textarea>
</div>
</div>
<div class="modal-footer">
<div class="d-flex align-items-center justify-content-end m-0">
<button type="button" data-bs-dismiss="modal" class="btn btn-sm btn-light me-2"><?php esc_html_e('Cancel', 'dreams-tour'); ?></button>
<button type="button" id="save_faq_btn" class="btn btn-sm btn-primary"><?php esc_html_e('Save FAQ', 'dreams-tour'); ?></button>
</div>
</div>
</div>
</div>
</div>
<!-- /Faq Modal -->
<!-- Add Itenary -->
<div class="modal fade" id="add_itenary">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5><?php esc_html_e('Add New Itenary', 'dreams-tour'); ?></h5>
<button data-bs-dismiss="modal" aria-label="close" class="btn-close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Title', 'dreams-tour'); ?> <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="itenary_title_input" placeholder="<?php esc_attr_e('Enter itinerary title', 'dreams-tour'); ?>">
</div>
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Date & Time', 'dreams-tour'); ?></label>
<div class="input-group gap-3">
<div class="input-icon-end position-relative flex-fill">
<input type="text" class="form-control datetimepicker" id="itenary_date_input" placeholder="<?php esc_attr_e('dd/mm/yyyy', 'dreams-tour'); ?>">
<span class="input-icon-addon">
<i class="isax isax-calendar"></i>
</span>
</div>
<div class="input-icon-end position-relative flex-fill">
<input type="text" class="form-control timepicker" id="itenary_time_input" placeholder="<?php esc_attr_e('hh:mm', 'dreams-tour'); ?>">
<span class="input-icon-addon">
<i class="isax isax-calendar"></i>
</span>
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Description', 'dreams-tour'); ?></label>
<textarea class="form-control" id="itenary_description_input" rows="4" placeholder="<?php esc_attr_e('Enter detailed description', 'dreams-tour'); ?>"></textarea>
</div>
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Image', 'dreams-tour'); ?></label>
<div class="file-upload drag-file w-100 d-flex align-items-center justify-content-center flex-column">
<span class="upload-img d-block mb-2"><i class="isax isax-document-upload fs-24"></i></span>
<h6 class="mb-1"><?php esc_html_e('Upload Itinerary Image', 'dreams-tour'); ?></h6>
<p class="mb-0"><?php esc_html_e('Image size should below 5MB', 'dreams-tour'); ?></p>
<input type="file" id="itenary_image_input" accept="image/*">
</div>
<div id="itenary_image_preview" class="mt-2" style="display: none;">
<img id="itenary_preview_img" src="" alt="Preview" style="max-width: 200px; height: auto; border-radius: 4px;">
</div>
</div>
</div>
<div class="modal-footer">
<div class="d-flex align-items-center justify-content-end m-0">
<button type="button" data-bs-dismiss="modal" class="btn btn-sm btn-light me-2"><?php esc_html_e('Cancel', 'dreams-tour'); ?></button>
<button type="button" id="add_itenary_btn" class="btn btn-sm btn-primary"><?php esc_html_e('Add Itenary', 'dreams-tour'); ?></button>
</div>
</div>
</div>
</div>
</div>
<!-- Add Itenary -->
<!-- Edit Itenary -->
<div class="modal fade" id="edit_itenary">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5><?php esc_html_e('Edit Itenary', 'dreams-tour'); ?></h5>
<button data-bs-dismiss="modal" aria-label="close" class="btn-close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Title', 'dreams-tour'); ?> <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="edit_itenary_title_input" placeholder="<?php esc_attr_e('Enter itinerary title', 'dreams-tour'); ?>">
</div>
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Date & Time', 'dreams-tour'); ?></label>
<div class="input-group gap-3">
<div class="input-icon-end position-relative flex-fill">
<input type="text" class="form-control datetimepicker" id="edit_itenary_date_input" placeholder="<?php esc_attr_e('dd/mm/yyyy', 'dreams-tour'); ?>">
<span class="input-icon-addon">
<i class="isax isax-calendar"></i>
</span>
</div>
<div class="input-icon-end position-relative flex-fill">
<input type="text" class="form-control timepicker" id="itenary_time_input" placeholder="<?php esc_attr_e('hh:mm', 'dreams-tour'); ?>">
<span class="input-icon-addon">
<i class="isax isax-calendar"></i>
</span>
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Description', 'dreams-tour'); ?></label>
<textarea class="form-control" id="edit_itenary_description_input" rows="4" placeholder="<?php esc_attr_e('Enter detailed description', 'dreams-tour'); ?>"></textarea>
</div>
<div class="mb-3">
<label class="form-label"><?php esc_html_e('Image', 'dreams-tour'); ?></label>
<div class="file-upload drag-file w-100 d-flex align-items-center justify-content-center flex-column">
<span class="upload-img d-block mb-2"><i class="isax isax-document-upload fs-24"></i></span>
<h6 class="mb-1"><?php esc_html_e('Upload Itinerary Image', 'dreams-tour'); ?></h6>
<p class="mb-0"><?php esc_html_e('Image size should below 5MB', 'dreams-tour'); ?></p>
<input type="file" id="edit_itenary_image_input" accept="image/*">
</div>
<div id="edit_itenary_image_preview" class="mt-2">
<img id="edit_itenary_preview_img" src="" alt="Preview" style="max-width: 200px; height: auto; border-radius: 4px;">
</div>
</div>
</div>
<div class="modal-footer">
<div class="d-flex align-items-center justify-content-end m-0">
<button type="button" data-bs-dismiss="modal" class="btn btn-sm btn-light me-2"><?php esc_html_e('Cancel', 'dreams-tour'); ?></button>
<button type="button" id="save_itenary_btn" class="btn btn-sm btn-primary"><?php esc_html_e('Save Itenary', 'dreams-tour'); ?></button>
</div>
</div>
</div>
</div>
</div>
<!-- /Edit Itenary -->
<!-- Delete Modal -->
<div class="modal fade" id="delete_modal">
<div class="modal-dialog modal-dialog-centered modal-sm">
<div class="modal-content">
<div class="modal-body">
<form action="">
<div class="text-center">
<h5 class="mb-3">Confirm Delete</h5>
<p class="mb-3">Are you sure you want to delete this item?</p>
<div class="d-flex align-items-center justify-content-center">
<a href="#" class="btn btn-light me-2" data-bs-dismiss="modal">No</a>
<button type="submit" class="btn btn-primary">Yes</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- /Delete Modal -->
<script>
jQuery(document).ready(function($) {
// ==================== REMOVAL FUNCTIONS - FIXED VERSION ====================
// Remove FAQ item - PROPERLY REMOVES HIDDEN INPUTS TOO
$(document).on('click', '.remove-faq', function(e) {
e.preventDefault();
var item = $(this).closest('.faq-item');
console.log('Removing FAQ item:', item);
// Remove all associated hidden inputs (they are siblings after the item)
var questionInput = item.nextAll('input[name="faq_question[]"]').first();
var answerInput = item.nextAll('textarea[name="faq_answer[]"]').first();
console.log('Found associated inputs to remove:', {
question: questionInput.length,
answer: answerInput.length
});
// Remove the item and all its associated inputs
item.remove();
questionInput.remove();
answerInput.remove();
console.log('FAQ item and associated inputs removed');
});
// Remove Itinerary item - PROPERLY REMOVES HIDDEN INPUTS TOO
$(document).on('click', '.remove-itenary', function(e) {
e.preventDefault();
var item = $(this).closest('.itenary-item');
console.log('Removing itinerary item:', item);
// Remove all associated hidden inputs (they are siblings after the item)
var titleInput = item.nextAll('input[name="itenary_title[]"]').first();
var dateInput = item.nextAll('input[name="itenary_date[]"]').first();
var descInput = item.nextAll('textarea[name="itenary_description[]"]').first();
var imageInput = item.nextAll('input[name="itenary_image[]"]').first();
console.log('Found associated inputs to remove:', {
title: titleInput.length,
date: dateInput.length,
description: descInput.length,
image: imageInput.length
});
// Remove the item and all its associated inputs
item.remove();
titleInput.remove();
dateInput.remove();
descInput.remove();
imageInput.remove();
console.log('Itinerary item and associated inputs removed');
});
// Remove Highlight functionality
$(document).on('click', '.remove-highlight', function(e) {
e.preventDefault();
$(this).closest('.highlight-info').remove();
});
// ==================== ADDITION FUNCTIONS ====================
// Add FAQ functionality
$('#add_faq_btn').on('click', function() {
var question = $('#faq_question_input').val().trim();
var answer = $('#faq_answer_input').val().trim();
if (question && answer) {
var faqHtml = '<div class="card shadow-none mb-0 mt-3 faq-item">' +
'<div class="card-body px-3 py-2">' +
'<div class="d-flex align-items-center justify-content-between flex-wrap row-gap-3">' +
'<h6><a href="javascript:void(0);">' + question + '</a></h6>' +
'<div class="d-flex align-items-center">' +
'<a href="javascript:void(0);" data-bs-toggle="modal" data-bs-target="#edit_faq" class="rounded-edit d-flex align-items-center justify-content-center me-2 edit-faq-btn"><i class="isax isax-edit-2"></i></a>' +
'<a href="javascript:void(0);" class="trash-icon d-flex align-items-center justify-content-center remove-faq"><i class="isax isax-trash text-danger"></i></a>' +
'</div></div></div></div>' +
'<input type="hidden" name="faq_question[]" value="' + question + '" />' +
'<textarea name="faq_answer[]" style="display:none;">' + answer + '</textarea>';
$('#faq .faq_append').append(faqHtml);
$('#faq_question_input').val('');
$('#faq_answer_input').val('');
$('#add_faq').modal('hide');
}
});
// Add Itinerary functionality
$('#add_itenary_btn').on('click', function() {
var title = $('#itenary_title_input').val().trim();
var date = $('#itenary_date_input').val().trim();
var description = $('#itenary_description_input').val().trim();
var imageFile = $('#itenary_image_input')[0].files[0];
var imageUrl = '';
console.log('Add clicked - Title:', title, 'Date:', date, 'Description:', description, 'ImageFile:', imageFile);
if (title) {
// Handle image preview
if (imageFile) {
console.log('Processing image file:', imageFile.name, imageFile.size);
var reader = new FileReader();
reader.onload = function(e) {
imageUrl = e.target.result;
console.log('Image processed, calling addItineraryItem with imageUrl:', imageUrl);
addItineraryItem(title, date, description, imageUrl);
};
reader.readAsDataURL(imageFile);
} else {
console.log('No image file, calling addItineraryItem without image');
addItineraryItem(title, date, description, imageUrl);
}
}
});
// Function to add itinerary item
function addItineraryItem(title, date, description, imageUrl) {
var itenaryHtml = '<div class="card shadow-none mb-0 mt-3 itenary-item">' +
'<div class="card-body px-3 py-2">' +
'<div class="d-flex align-items-start justify-content-between flex-wrap row-gap-3">' +
'<div class="flex-grow-1">' +
'<h6><a href="javascript:void(0);">' + title + '</a></h6>';
if (date) {
itenaryHtml += '<p class="text-muted mb-1"><i class="isax isax-calendar me-1"></i>' + date + '</p>';
}
if (description) {
itenaryHtml += '<p class="mb-2">' + (description.length > 100 ? description.substring(0, 100) + '...' : description) + '</p>';
}
if (imageUrl) {
itenaryHtml += '<div class="itenary-image-preview mb-2">' +
'<img src="' + imageUrl + '" alt="Itinerary Image" style="max-width: 100px; height: auto; border-radius: 4px;">' +
'</div>';
}
itenaryHtml += '</div>' +
'<div class="d-flex align-items-center">' +
'<a href="javascript:void(0);" data-bs-toggle="modal" data-bs-target="#edit_itenary" class="rounded-edit d-flex align-items-center justify-content-center me-2 edit-itenary-btn"><i class="isax isax-edit-2"></i></a>' +
'<a href="javascript:void(0);" class="trash-icon d-flex align-items-center justify-content-center remove-itenary"><i class="isax isax-trash text-danger"></i></a>' +
'</div></div></div></div>' +
'<input type="hidden" name="itenary_title[]" value="' + title + '" />' +
'<input type="hidden" name="itenary_date[]" value="' + date + '" />' +
'<input type="hidden" name="itenary_time[]" value="' + date + '" />' +
'<textarea name="itenary_description[]" style="display:none;">' + description + '</textarea>' +
'<input type="hidden" name="itenary_image[]" value="' + imageUrl + '" />';
$('#itenary .itenary_append').append(itenaryHtml);
// Clear form
$('#itenary_title_input').val('');
$('#itenary_date_input').val('');
$('#itenary_description_input').val('');
$('#itenary_image_input').val('');
$('#itenary_image_preview').hide();
$('#add_itenary').modal('hide');
}
// ==================== EDIT FUNCTIONS ====================
// Edit FAQ functionality
$(document).on('click', '.edit-faq-btn', function(e) {
e.preventDefault();
var item = $(this).closest('.faq-item');
// FAQ hidden inputs are also siblings, not children
var question = item.nextAll('input[name="faq_question[]"]').first().val();
var answer = item.nextAll('textarea[name="faq_answer[]"]').first().val();
console.log('Edit FAQ clicked - Question:', question, 'Answer:', answer);
console.log('FAQ inputs found:', {
questionInput: item.nextAll('input[name="faq_question[]"]').length,
answerInput: item.nextAll('textarea[name="faq_answer[]"]').length
});
// Clear and populate edit modal
$('#edit_faq_question_input').val(question || '');
$('#edit_faq_answer_input').val(answer || '');
// Store the actual DOM element instead of index
$('#edit_faq').data('edit-item', item);
console.log('FAQ modal populated - Question:', $('#edit_faq_question_input').val(), 'Answer:', $('#edit_faq_answer_input').val());
});
// Save edited FAQ
$('#save_faq_btn').on('click', function() {
var editItem = $('#edit_faq').data('edit-item');
var question = $('#edit_faq_question_input').val().trim();
var answer = $('#edit_faq_answer_input').val().trim();
if (question && editItem) {
updateFAQItem(editItem, question, answer);
}
});
// Function to update FAQ item
function updateFAQItem(item, question, answer) {
console.log('Updating FAQ item:', item, 'Question:', question, 'Answer:', answer);
// Update display
item.find('h6 a').text(question);
// Update hidden inputs (they are siblings, not children)
var questionInput = item.nextAll('input[name="faq_question[]"]').first();
var answerInput = item.nextAll('textarea[name="faq_answer[]"]').first();
questionInput.val(question);
answerInput.val(answer);
// Verify the update
console.log('FAQ hidden inputs updated:');
console.log('Question input value:', questionInput.val());
console.log('Answer input value:', answerInput.val());
console.log('FAQ item updated successfully');
$('#edit_faq').modal('hide');
}
// Edit Itinerary functionality
$(document).on('click', '.edit-itenary-btn', function(e) {
e.preventDefault();
var item = $(this).closest('.itenary-item');
console.log('Edit clicked - Item element:', item);
console.log('Hidden inputs found (siblings):', item.nextAll('input[name="itenary_title[]"]').length);
// Store the actual DOM element for later reference
$('#edit_itenary').data('edit-item', item);
// Use the manual populate function
populateEditModal(item);
});
// Save edited Itinerary
$('#save_itenary_btn').on('click', function() {
var editItem = $('#edit_itenary').data('edit-item');
var title = $('#edit_itenary_title_input').val().trim();
var date = $('#edit_itenary_date_input').val().trim();
var description = $('#edit_itenary_description_input').val().trim();
var imageFile = $('#edit_itenary_image_input')[0].files[0];
var imageUrl = $('#edit_itenary_preview_img').attr('src') || '';
if (title && editItem) {
// Handle new image upload
if (imageFile) {
var reader = new FileReader();
reader.onload = function(e) {
imageUrl = e.target.result;
updateItineraryItem(editItem, title, date, description, imageUrl);
};
reader.readAsDataURL(imageFile);
} else {
updateItineraryItem(editItem, title, date, description, imageUrl);
}
}
});
// Function to update itinerary item
function updateItineraryItem(item, title, date, description, imageUrl) {
console.log('Updating item:', item, 'Title:', title, 'Date:', date, 'Description:', description, 'ImageUrl:', imageUrl);
// Update display
item.find('h6 a').text(title);
// Handle date display
var dateElement = item.find('p.text-muted');
if (date && date.trim() !== '') {
if (dateElement.length) {
dateElement.html('<i class="isax isax-calendar me-1"></i>' + date);
} else {
item.find('h6').after('<p class="text-muted mb-1"><i class="isax isax-calendar me-1"></i>' + date + '</p>');
}
} else {
dateElement.remove();
}
// Handle description display
var descElement = item.find('p:not(.text-muted):not(.mb-1)');
if (description && description.trim() !== '') {
var shortDesc = description.length > 100 ? description.substring(0, 100) + '...' : description;
if (descElement.length) {
descElement.text(shortDesc);
} else {
item.find('.flex-grow-1').append('<p class="mb-2">' + shortDesc + '</p>');
}
} else {
descElement.remove();
}
// Handle image display
var imagePreview = item.find('.itenary-image-preview');
if (imageUrl && imageUrl.trim() !== '' && imageUrl !== 'undefined') {
if (imagePreview.length) {
imagePreview.find('img').attr('src', imageUrl);
imagePreview.show();
} else {
item.find('.flex-grow-1').append('<div class="itenary-image-preview mb-2"><img src="' + imageUrl + '" alt="Itinerary Image" style="max-width: 100px; height: auto; border-radius: 4px;"></div>');
}
} else {
imagePreview.remove();
}
// Update hidden inputs (they are siblings, not children)
var titleInput = item.nextAll('input[name="itenary_title[]"]').first();
var dateInput = item.nextAll('input[name="itenary_date[]"]').first();
var descInput = item.nextAll('textarea[name="itenary_description[]"]').first();
var imageInput = item.nextAll('input[name="itenary_image[]"]').first();
titleInput.val(title);
dateInput.val(date);
descInput.val(description);
imageInput.val(imageUrl || '');
// Verify the update
console.log('Itinerary hidden inputs updated:');
console.log('Title input value:', titleInput.val());
console.log('Date input value:', dateInput.val());
console.log('Description input value:', descInput.val());
console.log('Image input value:', imageInput.val());
console.log('Item updated successfully');
$('#edit_itenary').modal('hide');
}
// ==================== UTILITY FUNCTIONS ====================
// Manual function to populate edit modal
function populateEditModal(item) {
console.log('populateEditModal called with item:', item);
if (!item || !item.length) {
console.log('No item provided or item is empty');
return;
}
// The hidden inputs are siblings of the .itenary-item, not children
var title = item.nextAll('input[name="itenary_title[]"]').first().val();
var date = item.nextAll('input[name="itenary_date[]"]').first().val();
var description = item.nextAll('textarea[name="itenary_description[]"]').first().val();
var image = item.nextAll('input[name="itenary_image[]"]').first().val();
console.log('Extracted data:', {title, date, description, image});
// Clear and populate fields
$('#edit_itenary_title_input').val(title || '');
$('#edit_itenary_date_input').val(date || '');
$('#edit_itenary_description_input').val(description || '');
$('#edit_itenary_image_input').val('');
// Handle image
if (image && image !== '' && image !== 'undefined') {
$('#edit_itenary_preview_img').attr('src', image);
$('#edit_itenary_image_preview').show();
} else {
$('#edit_itenary_preview_img').attr('src', '');
$('#edit_itenary_image_preview').hide();
}
console.log('Modal populated successfully');
}
// Image preview for add modal
$('#itenary_image_input').on('change', function() {
var file = this.files[0];
console.log('Add itinerary image selected:', file);
if (file) {
var reader = new FileReader();
reader.onload = function(e) {
console.log('Add itinerary image loaded:', e.target.result);
$('#itenary_preview_img').attr('src', e.target.result);
$('#itenary_image_preview').show();
};
reader.readAsDataURL(file);
}
});
// Image preview for edit modal
$('#edit_itenary_image_input').on('change', function() {
var file = this.files[0];
console.log('Edit itinerary image selected:', file);
if (file) {
var reader = new FileReader();
reader.onload = function(e) {
console.log('Edit itinerary image loaded:', e.target.result);
$('#edit_itenary_preview_img').attr('src', e.target.result);
$('#edit_itenary_image_preview').show();
};
reader.readAsDataURL(file);
}
});
// Gallery image preview
$('input[name="gallery_images[]"]').on('change', function() {
var files = this.files;
var galleryContainer = $('.gallery-preview');
// Add new previews (don't clear existing ones)
for (var i = 0; i < files.length; i++) {
var file = files[i];
if (file.type.startsWith('image/')) {
var reader = new FileReader();
reader.onload = function(e) {
var previewHtml = '<div class="gallery-upload-img me-2 mb-2">' +
'<img src="' + e.target.result + '" alt="Gallery Image" style="width: 100px; height: 100px; object-fit: cover; border-radius: 4px;">' +
'<span class="trash-icon d-flex align-items-center justify-content-center text-danger gallery-trash"><i class="isax isax-trash"></i></span>' +
'</div>';
galleryContainer.append(previewHtml);
};
reader.readAsDataURL(file);
}
}
});
// Remove Gallery Image functionality
$(document).on('click', '.gallery-trash', function() {
var imageId = $(this).data('image-id');
var imageElement = $(this).parent();
// If it's an existing image (has image-id), we need to handle it differently
if (imageId) {
// Add a hidden input to mark this image for deletion
var deleteInput = '<input type="hidden" name="delete_gallery_images[]" value="' + imageId + '">';
imageElement.after(deleteInput);
}
// Hide the image element
imageElement.hide();
});
// Initialize Quill editor for description
var quillEditor = null;
if (typeof Quill !== 'undefined') {
var snowEditor = document.querySelector('.snow-editor');
if (snowEditor) {
quillEditor = new Quill(snowEditor, {
theme: 'snow',
modules: {
toolbar: [
['bold', 'italic', 'underline'],
[{ 'header': [null, 1, 2, 3, 4, 5, 6] }],
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
['link', 'image', 'video'],
['blockquote', 'code-block'],
[{ 'color': [] }, { 'background': [] }],
[{ 'align': [] }]
]
}
});
// Load existing content in edit mode
<?php if ($edit_mode && !empty($tour_data['post_content'])): ?>
var existingContent = <?php echo json_encode($tour_data['post_content']); ?>;
if (existingContent) {
quillEditor.root.innerHTML = existingContent;
}
<?php endif; ?>
// Sync content to hidden textarea on form submit
$('form').on('submit', function() {
var content = quillEditor.root.innerHTML;
$('textarea[name="tour_description"]').val(content);
});
}
}
});
</script>
<?php get_footer(); ?>