nhance/app/Views/add_image_list.php

584 lines
27 KiB
PHP
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
helper('datatable_view');
$aim_header_labels = [
'Advertisement Image Name', 'Client Name', 'Client Short Name', 'Status', 'Action',
];
$aim_col_count = count($aim_header_labels);
$aim_col_max_len = array_fill(0, $aim_col_count, 0);
for ($i = 0; $i < $aim_col_count; $i++) {
$aim_col_max_len[$i] = mb_strlen($aim_header_labels[$i]);
}
$addImageList = $addImageList ?? [];
foreach ($addImageList as $row) {
$aim_col_max_len[0] = max($aim_col_max_len[0], mb_strlen((string) ($row['name'] ?? '')));
$c1 = ($row['client_id'] ?? 0) != 0 ? (string) ($row['client_name'] ?? '') : '-';
$aim_col_max_len[1] = max($aim_col_max_len[1], mb_strlen($c1));
$c2 = ($row['client_id'] ?? 0) != 0 ? (string) ($row['short_name'] ?? '') : '-';
$aim_col_max_len[2] = max($aim_col_max_len[2], mb_strlen($c2));
$aim_col_max_len[3] = max($aim_col_max_len[3], mb_strlen((string) ($row['status'] ?? '')));
$aim_col_max_len[4] = max($aim_col_max_len[4], 4);
}
$aim_col_min_px = [120, 140, 120, 88, 72];
$aim_col_max_px = [400, 400, 240, 140, 88];
$aim_col_width_px = nhance_dt_column_widths_px($aim_header_labels, $aim_col_max_len, $aim_col_min_px, $aim_col_max_px);
?>
<style>
.col-12{
max-width: 98% !important;
}
.dataTables_length label {height: 21px !important;}
<?php for ($i = 0; $i < $aim_col_count; $i++) : ?>
#add-image-list-table_wrapper .dataTables_scrollHead table thead th:nth-child(<?= $i + 1 ?>),
#add-image-list-table thead th:nth-child(<?= $i + 1 ?>) {
min-width: <?= (int) $aim_col_width_px[$i] ?>px;
width: <?= (int) $aim_col_width_px[$i] ?>px;
box-sizing: border-box;
vertical-align: middle;
overflow: visible !important;
}
#add-image-list-table tbody td:nth-child(<?= $i + 1 ?>) {
width: <?= (int) $aim_col_width_px[$i] ?>px;
max-width: <?= (int) $aim_col_width_px[$i] ?>px;
min-width: <?= (int) $aim_col_width_px[$i] ?>px;
box-sizing: border-box;
vertical-align: middle;
}
<?php endfor; ?>
#add-image-list-table tbody td:nth-child(1),
#add-image-list-table tbody td:nth-child(2),
#add-image-list-table tbody td:nth-child(3),
#add-image-list-table tbody td:nth-child(4) {
overflow: hidden;
text-overflow: ellipsis;
}
#add-image-list-table tbody td:nth-child(5) {
overflow: visible;
text-overflow: clip;
}
#add-image-list-table tbody td {
padding: 5px 11px !important;
font-size: 13px;
line-height: 1.25;
}
#add-image-list-table thead th {
padding: 5px 2.35rem 5px 11px !important;
font-size: 13px;
line-height: 1.25;
}
</style>
<div class="row" id="client_list">
<div class="col-12">
<div class="card">
<div class="card-body">
<!-- <div class="row" style="margin-bottom:1rem;">
<div class="col-6" style="align-self: center;">
<h4 style="position: relative;">Advertisement Images</h4>
</div>
<div class="col-6" style="text-align: right; position: relative;top: 5px;">
<a data-toggle="modal" data-target="#bike_make_login-modal" href="#" type="button" id="btnAdd" class="btn btn-primary waves-effect waves-light" data-toggle="" data-placement="top" title="Add" data-trigger="hover">ADD</a>
</div>
</div> -->
<!-- <table data-custom-table-css="table" class="table table-sm table-hover m-0 table-centered dt-responsive nowrap w-100" cellspacing="0"
id="tickets-table"> -->
<table data-custom-table-css="table" class="table mb-0 nowrap" cellspacing="0" id="add-image-list-table">
<thead class="bg-light">
<tr>
<th class="font-weight-medium">Advertisement Image Name&nbsp;</th>
<th class="font-weight-medium">Client Name&nbsp;</th>
<th class="font-weight-medium">Client Short Name&nbsp;</th>
<th class="font-weight-medium">Status&nbsp;</th>
<th class="font-weight-medium text-center">Action&nbsp;</th>
</tr>
</thead>
<tbody>
<?php foreach($addImageList as $row){ ?>
<tr >
<td class="client_info" data-id="<?php echo $row['id']; ?>"><?php echo $row['name']; ?></td>
<td class="client_info" ><?php echo $row['client_id'] != 0 ? $row['client_name'] : '-' ; ?></td>
<td class="client_info" ><?php echo $row['client_id'] != 0 ? $row['short_name'] : '-'; ?></td>
<td class="client_info" ><?php echo $row['status']; ?></td>
<td class="text-center table-action-cell">
<div class="btn-group dropdown">
<a href="javascript: void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown" aria-expanded="false"><i class="mdi mdi-dots-horizontal"></i></a>
<div class="dropdown-menu dropdown-menu-right">
<a class="dropdown-item advertise_image_edit" href="#" data-toggle="modal" data-wholearray='<?php echo json_encode($row, JSON_HEX_APOS); ?>' data-target="#bike_make_login-modal"><i class="mdi mdi-pencil mr-2 text-muted font-18 vertical-middle"></i>Edit</a>
<?php if($row['client_id'] != 0) { ?> <a class="dropdown-item" onclick="remove_advertise_image('<?= $row['id'];?>')"><i class="mdi mdi-delete mr-2 text-muted font-18 vertical-middle"></i>Delete</a> <?php } ?>
</div>
</div>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
</div><!-- end col -->
</div>
<!-- end row -->
<div id="append_client_info"></div>
<div id="bike_make_login-modal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<div class="mt-2 mb-4">
<h4 id="advertise_add_edit">Add Advertise Image </h4>
</div>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<form id="model_form_data" class="px-4" enctype="multipart/form-data" data-parsley-validate data-parsley-excluded="[disabled]">
<input type="hidden" name="add_image_id" id="add_image_id" value="0">
<!-- old
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label for="branchname">Upload Image</label>
<div class="input-icon">
<input type="file" class="form-control" name="advertise_image" id="advertise_image" accept="image/*" onchange="PreviewImage();" required>
<i class="mdi mdi-upload additional-icon"></i>
</div>
</div>
<div class="form-group col-md-6 float-left" style="position: relative;top: 0px;">
<img src=" " width="100" height="100" id="uploadPreview" class="avatar img-circle img-thumbnail" alt="avatar"/>
</div>
<div class="form-group col-md-3">
<label for="client_branch">Client<span class="text-danger">*</span></label>
<select class="form-control" id="client_id" name="client_id" required>
<option value="">Select Client</option>
<?php
if (isset($client) && count($client)) {
foreach ($client as $key => $value) {
echo "<option value='" . $value['id'] . "'>" . $value['client_name'] . "</option>";
}
}
?>
</select>
</div>
</div>
</div>
-->
<div class="row mb-2 align-items-stretch">
<!-- Left column: col-8 -->
<div class="col-md-8 d-flex flex-column justify-content-between">
<!-- Top section -->
<div class="form-group">
<label for="branchname">Upload Image</label>
<div class="input-icon">
<input type="file" class="form-control" name="advertise_image" id="advertise_image" accept=".jpg,.jpeg,.png" onchange="PreviewImage();" required
data-parsley-required-message="Image is required"
data-parsley-allowed-ext="true"
data-parsley-max-file-size="true"
data-parsley-exact-dimensions="true"
data-parsley-errors-container="#advertise_image_error">
<i class="mdi mdi-upload additional-icon"></i>
</div>
<div id="advertise_image_error"></div>
</div>
<!-- Bottom section -->
<div class="form-group">
<label for="client_branch">Client <span class="text-danger">*</span></label>
<select class="form-control" id="client_id" name="client_id" required
data-parsley-required-message="Client is required"
data-parsley-type="integer"
data-parsley-min="0"
data-parsley-min-message="Invalid client selected"
data-parsley-type-message="Invalid client selected"
data-parsley-errors-container="#client_id_error">
<option value="">Select Client</option>
<option value="0">Default Image</option>
<?php
if (isset($client) && count($client)) {
foreach ($client as $value) {
echo "<option value='" . $value['id'] . "'>" . $value['client_name'] . "</option>";
}
}
?>
</select>
<div id="client_id_error"></div>
</div>
</div>
<!-- Right column: col-4, preview image -->
<div class="col-md-4 d-flex flex-column align-items-center justify-content-center">
<img src="" class="avatar img-circle img-thumbnail" id="uploadPreview" alt="Preview" style="max-width: 100%; height: auto;">
<small style="font-size: x-small; margin-top: 5px; text-align: center;">
dimensions - 1640x664 pixels <br> size - 200kb
</small>
</div>
</div>
<div class="form-group text-center">
<button type="button" class="btn btn-primary" onclick="submitBranch()">Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
<script>
function submitBranch() {
var form = $('#model_form_data');
form.parsley().validate();
if (!form.parsley().isValid()) {
return;
}
const fileInput = $('#advertise_image')[0].files[0]; // get actual file object
const imageId = $('#add_image_id').val();
const clientId = $('#client_id').val();
var url = '<?= base_url("add_advertise_image") ?>';
var formData = new FormData();
formData.append('advertise_image', fileInput);
formData.append('add_image_id', imageId);
formData.append('client_id', clientId);
$.ajax({
type: 'POST',
url: url,
data: formData,
processData: false,
contentType: false,
dataType: 'json',
success: function(response) {
console.log(response);
if (response.status) {
$('#bike_make_login-modal').modal('hide');
$('#advertise_image').val('');
$('#client_id').val(null).trigger('change');
$('#uploadPreview').attr('src', '<?= base_url('public/assets/images/avatar_2x.png') ?>');
toastr.success('Image uploaded successfully!');
window.location.reload();
} else {
toastr.error(response.message || 'Something went wrong.');
}
},
error: function(xhr, status, error) {
// Get the current domain
const hostname = window.location.hostname;
if (hostname === 'localhost' || hostname === '127.0.0.1') {
// DEVELOPER MODE: Show everything in a nice group
console.group("%c Debug: Server Error ", "background: #222; color: #bada55; padding: 2px;");
console.error("Status:", xhr.status);
console.error("Type:", error);
console.error("Full Response:", xhr.responseText);
console.groupEnd();
} else {
// LIVE MODE: Only log a simple, non-revealing error
console.error("Server Error: Action could not be completed. Reference Code: " + xhr.responseText);
}
if (xhr.status === 400) {
let response = JSON.parse(xhr.responseText);
let errorMessages = "";
let seenMessages = []; // Array to store unique messages
if (response.errors) {
$.each(response.errors, function (field, message) {
if (!seenMessages.includes(message)) {
errorMessages += `• ${message}<br>`;
seenMessages.push(message); // Mark this message as "seen"
}
});
toastr.error(errorMessages, 'Validation Error', { "allowHtml": true });
} else {
toastr.warning(response.message || 'Validation failed', 'Warning');
}
} else if (xhr.status === 403) {
let response = JSON.parse(xhr.responseText);
toastr.error(response.message, 'Security Policy');
} else if (xhr.status === 500) {
toastr.error('Something went wrong . Please try again later.', 'Server Error');
} else {
toastr.error('An unexpected error occurred. Please try again later.', 'Error');
}
}
});
}
function PreviewImage() {
console.log('function called');
var fileInput = document.getElementById("advertise_image");
var file = fileInput.files[0];
var $fileInput = $(fileInput);
$fileInput.removeAttr('data-dimension-valid');
$fileInput.removeAttr('data-size-valid');
$fileInput.removeAttr('data-ext-valid');
if (file) {
var allowedExtensions = ["jpg", "jpeg", "png"];
var fileExtension = file.name.split('.').pop().toLowerCase();
if (!allowedExtensions.includes(fileExtension)) {
$fileInput.attr('data-ext-valid', 'false');
} else {
$fileInput.attr('data-ext-valid', 'true');
}
if (file.size > 200 * 1024) {
$fileInput.attr('data-size-valid', 'false');
} else {
$fileInput.attr('data-size-valid', 'true');
}
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function (event) {
var img = new Image();
img.src = event.target.result;
img.onload = function () {
if (img.width !== 1640 || img.height !== 664) {
$fileInput.attr('data-dimension-valid', 'false');
document.getElementById("uploadPreview").src = "<?= base_url()."public/assets/images/avatar_2x.png" ?>"; // Remove the preview image
} else {
$fileInput.attr('data-dimension-valid', 'true');
document.getElementById("uploadPreview").src = img.src;
}
$fileInput.parsley().validate();
};
};
} else {
document.getElementById("uploadPreview").src = "<?= base_url()."public/assets/images/avatar_2x.png" ?>";
$fileInput.parsley().validate();
}
}
var table;
$(document).ready(function() {
window.Parsley.addValidator('allowedExt', {
validateString: function(value, requirement, parsleyInstance) {
return parsleyInstance.$element.attr('data-ext-valid') !== 'false';
},
messages: { en: 'Only JPG, JPEG, PNG allowed' }
});
window.Parsley.addValidator('maxFileSize', {
validateString: function(value, requirement, parsleyInstance) {
return parsleyInstance.$element.attr('data-size-valid') !== 'false';
},
messages: { en: 'Image size must not exceed 200 KB' }
});
window.Parsley.addValidator('exactDimensions', {
validateString: function(value, requirement, parsleyInstance) {
return parsleyInstance.$element.attr('data-dimension-valid') !== 'false';
},
messages: { en: 'Image dimensions must be exactly 1640x664 pixels' }
});
$('#client_id').select2();
$('#client_id').on('select2:select select2:clear', function () {
$(this).parsley().validate();
});
$('#add_image_id').val('');
$('#client_id').val(null).trigger('change');
$('#advertise_image').val('');
nhanceListDataTableBeforeInit();
table = $('#add-image-list-table').DataTable(nhanceMergeListDataTableOptions({
// dom: "<'row'<'col-sm-1'f><'col-sm-11 text-right'B>>" + // Filter left, button right
// "<'row'<'col-sm-12'tr>>" +
// "<'row'<'col-sm-5'i><'col-sm-7'p>>",
dom: "<'row'<'col-12 d-flex justify-content-between align-items-center'<'datatable-search dataTables_filter'f><'datatable-buttons dt-buttons'B>>>" +
"<'row'<'col-sm-12'tr>>" +
"<'row align-items-center'<'col-5 text-start'i><'col-7 d-flex justify-content-end align-items-center'<'me-2'l>p>>",
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
buttons: [
{
text: '<i class="mdi mdi-plus"></i> <span class="btn-custom">Add</span>',
className: 'btn app-btn-primary',
action: function (e, dt, node, config) {
// ✅ Call your modal logic
callmodal();
}
}
],
language: {
search: `
<div class="datatable-search-wrapper" style="position:relative; display:inline-block;">
_INPUT_
<i class="mdi mdi-magnify datatable-search-icon"
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666;"></i>
<i class="mdi mdi-close-circle datatable-clear-icon"
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
</div>`,
searchPlaceholder: "Search",
emptyTable: '<div class="text-center text-muted">No Data found</div>',
paginate: {
previous: '◄',
next: '►'
}
},
paging: true,
columnDefs: [
<?php for ($i = 0; $i < $aim_col_count; $i++) : ?>
{ targets: <?= $i ?>, width: '<?= (int) $aim_col_width_px[$i] ?>px' },
<?php endfor; ?>
],
}));
nhanceListDataTableAfterInit();
nhanceListDataTableBindAdjust(table);
function applyBottomRowDropup() {
if (!table) return;
const currentRows = table.rows({ page: 'current' }).nodes().toArray();
$('#add-image-list-table tbody tr').removeClass('nh-force-dropup');
$('#add-image-list-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup');
const targetCount = Math.min(2, currentRows.length);
for (let i = 0; i < targetCount; i++) {
const row = currentRows[currentRows.length - 1 - i];
if (!row) continue;
$(row).addClass('nh-force-dropup');
$(row).find('td.table-action-cell .btn-group.dropdown').addClass('dropup');
}
}
applyBottomRowDropup();
$('#add-image-list-table').on('draw.dt', applyBottomRowDropup);
});
// ✅ Define your modal function separately
function callmodal() {
$('#add_image_id').val(0);
$('#client_id').val(null).trigger('change');
$('#advertise_add_edit').html('Add Advertise Image');
$('#uploadPreview').attr('src', '<?= base_url()."public/assets/images/avatar_2x.png" ?>');
$('#advertise_image').prop('required', true);
if ($('#model_form_data').length) {
$('#model_form_data').parsley().reset();
}
$('#bike_model_login-modal').modal('show'); // ✅ this shows the modal
var myModal = new bootstrap.Modal(document.getElementById('bike_make_login-modal'));
myModal.show();
}
function remove_advertise_image(id) {
if (!confirm("Are you sure you want to delete this image?")) return;
$.ajax({
type: 'POST',
url: '<?= base_url("remove_advertise_image"); ?>',
data: { add_image_id: id },
success: function (response) {
toastr.success('Deleted successfully');
location.reload(); // refresh page
},
error: function (xhr) {
console.error(xhr.responseText);
}
});
}
// $('#btnAdd').click(function () {
// $('#add_image_id').val(0);
// $('#advertise_add_edit').html('Add Advertise Image');
// $('#uploadPreview').attr('src', '<?= base_url()."public/assets/images/avatar_2x.png" ?>');
// })
// $('.advertise_image_edit').click(function (params) {
// // console.log($(this).data('id'));
// $('#add_image_id').val($(this).data('id'));
// var url = '<?= base_url("getAdvertiseImage/"); ?>'+$(this).data('id') ;
// $.ajax({
// type: 'GET',
// url: url,
// success: function (response) {
// console.log(response);
// $('#advertise_add_edit').html('Edit Advertise Image');
// $('#uploadPreview').attr('src', '<?= base_url() . "public/uploads/advertiseImage/"?>' + response)
// .on('error', function() {
// $(this).attr('src', '<?= base_url()."public/assets/images/avatar_2x.png" ?>');
// });
// },
// error: function (xhr, status, error) {
// console.error(xhr.responseText);
// }
// })
// })
$(document).on('click', '.advertise_image_edit', function (e) {
e.preventDefault();
// 1. Clear fields first for a clean state (Good practice)
$('#add_image_id').val('');
$('#client_id').val(null).trigger('change');
$('#advertise_image').val('');
// Reset preview to default before processing to avoid flicker/old image
$('#uploadPreview').attr('src', '<?= base_url("public/assets/images/avatar_2x.png") ?>');
let wholearray = JSON.parse($(this).attr('data-wholearray'));
let ad_name = wholearray.name;
let ad_id = wholearray.id;
let c_id = wholearray.client_id; // This holds the Client ID for the dropdown
// console.log('Whole array:', wholearray);
// console.log('Clicked ID:', ad_id);
// 2. Set the data fields and title
$('#add_image_id').val(ad_id);
$('#advertise_add_edit').html('Edit Advertise Image');
// 🎯 CRITICAL FIX: Set the value of the Client SELECT dropdown
// This pre-selects the client associated with the image.
$('#client_id').val(c_id).trigger('change');
// 3. Construct the image URL
// NOTE: If this path fails (404/403), revert to the previous controller path:
const imgUrl = '<?= base_url("showAdvertiseImage/"); ?>' + ad_name;
// const imgUrl = '<?= base_url('public/uploads/add_image_upload/'); ?>' + ad_name;
// 4. Set the image source AND add robust error handling for default image
$('#uploadPreview').attr('src', imgUrl).on('error', function() {
// Fallback: If the image fails to load, set the source to the default image.
$(this).attr('src', '<?= base_url("public/assets/images/avatar_2x.png") ?>');
});
// 5. Clear the file input
$('#advertise_image').val('');
$('#advertise_image').prop('required', false);
if ($('#model_form_data').length) {
$('#model_form_data').parsley().reset();
}
// 6. Show the modal
var myModal = new bootstrap.Modal(document.getElementById('bike_make_login-modal'));
myModal.show();
});
</script>