You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1256 lines
54 KiB
1256 lines
54 KiB
<!DOCTYPE html>
|
|
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
|
|
|
<head th:replace="~{fragments/modules/base/head :: head}"></head>
|
|
<style>
|
|
|
|
/* .modal-body {
|
|
max-height: 70vh;
|
|
overflow-y: auto;
|
|
overflow-x: hidden;
|
|
padding-right: 15px;
|
|
} */
|
|
.edit-campaign{
|
|
|
|
max-height: 70vh;
|
|
overflow-y: auto; /* Enables vertical scrolling */
|
|
overflow-x: hidden; /* Hides horizontal scrolling */
|
|
padding-right: 15px; /* Prevents content cutoff */
|
|
}
|
|
|
|
</style>
|
|
<body>
|
|
|
|
<!--[if lt IE 8]>
|
|
<p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
|
|
<![endif]-->
|
|
|
|
<div class="wrapper">
|
|
<!-- header top menu Start -->
|
|
<header th:replace="~{fragments/modules/base/header :: header}"></header>
|
|
<!-- header top menu end -->
|
|
|
|
<div class="page-wrap">
|
|
<!--=============== Left Menu side Start ================-->
|
|
<div th:replace="~{fragments/modules/base/menu :: menu}"></div>
|
|
<!--=============== Left side End ================-->
|
|
<div class="main-content">
|
|
<div class="container-fluid">
|
|
<div class="page-header mb-2">
|
|
<div class="row align-items-end">
|
|
<div class="col-lg-8">
|
|
<div class="page-header-title">
|
|
<i class="fa fa-list-alt bg-blue"></i>
|
|
<div class="d-inline">
|
|
<h5>Campaign List</h5>
|
|
<span>1913 Campaign List</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-4">
|
|
<nav class="breadcrumb-container" aria-label="breadcrumb">
|
|
<ol class="breadcrumb">
|
|
<li class="breadcrumb-item"><a href="/gcc/index"><i
|
|
class="ik ik-home"></i></a></li>
|
|
<li class="breadcrumb-item" aria-current="page">1913 Campaign</li>
|
|
<li class="breadcrumb-item active" aria-current="page">Campaign List</li>
|
|
</ol>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<h4 class="h4 text-right text-mute" style="font-size: 12px;">
|
|
Auot refresh in <font id="refresh-countdown">00</font> seconds
|
|
</h4>
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-md-12">
|
|
<div class="card">
|
|
|
|
<div class="card-body">
|
|
<div class="page-header-title" >
|
|
<h5 style="margin: 0;font-weight: bold;">Campaigns List</h5><hr>
|
|
</div>
|
|
|
|
<table id="StartCampaigntable" class="table table-striped table-bordered table-hover dataTable" role="grid">
|
|
<thead class="thead-dark">
|
|
<tr role="row">
|
|
<th>S.No</th>
|
|
<th class="text-center">Campaign</th>
|
|
<th class="text-center">Category</th>
|
|
<th class="text-center">Date</th>
|
|
<th class="text-center">Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr th:each="campaign, iterStat : ${campaigns}">
|
|
<td th:text="${iterStat.index + 1}" class="text-center"></td> <!-- Serial number -->
|
|
<td th:text="${campaign['campaign_name']}" class="text-center"></td> <!-- Campaign name -->
|
|
<td th:text="${campaign['category_name']}" class="text-center"></td> <!-- Category name -->
|
|
<td th:text="${campaign['start_date']}" class="text-center"></td> <!-- Total calls -->
|
|
<td class="text-center">
|
|
<button type="button" class="btn btn-success"
|
|
th:onclick="return callCampEdit([[${campaign.campaign_id}]], [[${campaign.category_id}]])"
|
|
data-animation="true"
|
|
data-toggle="tooltip"
|
|
data-placement="top"
|
|
title="Edit">
|
|
View
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
|
|
</tbody>
|
|
<tfoot class="thead-dark">
|
|
<tr role="row">
|
|
<th>S.No</th>
|
|
<th class="text-center">Campaign</th>
|
|
<th class="text-center">Category</th>
|
|
<th class="text-center">Date</th>
|
|
<th class="text-center">Action</th>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-12">
|
|
<div class="card">
|
|
|
|
<div class="card-block">
|
|
<div class="page-header-title" >
|
|
<h5 style="margin: 0;font-weight: bold;">Campaign Status List</h5><hr>
|
|
</div>
|
|
<div>
|
|
<table id="CampaignDatatable" class="table table-striped table-bordered table-hover dataTable" role="grid">
|
|
<thead class="thead-dark">
|
|
<tr role="row">
|
|
<th>S.No</th>
|
|
<th class="text-center">Name</th>
|
|
<th class="text-center">Category</th>
|
|
<th class="text-center">Event Date</th>
|
|
<th class="text-center">Description</th>
|
|
<th class="text-center">Status</th>
|
|
<th class="text-center">Action</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
<tbody>
|
|
<tr th:each="activeCampaign, iterStat : ${activeCampaigns}">
|
|
<td th:text="${iterStat.index + 1}" class="text-center"></td> <!-- Serial number -->
|
|
<td th:text="${activeCampaign['campaign_name']}" class="text-center"></td>
|
|
<td th:text="${activeCampaign['category_name']}" class="text-center"></td>
|
|
<td th:text="${activeCampaign['start_date']} + ' - ' + ${activeCampaign['end_date']}" class="text-center"></td>
|
|
<td th:text="${activeCampaign['description']}" class="text-center"></td> <!-- Calls per agent -->
|
|
<td class="text-center">
|
|
<th:block th:switch="${activeCampaign['campaign_status']}">
|
|
<th:block th:case="'ONGOING'">
|
|
<button type="button" class="status-button btn btn-danger"
|
|
th:data-id="${activeCampaign['campaign_id']}">Ongoing</button>
|
|
</th:block>
|
|
<th:block th:case="'CLOSED'">
|
|
<span class="text-success">Closed</span>
|
|
</th:block>
|
|
</th:block>
|
|
</td>
|
|
|
|
<td class="text-center">
|
|
<th:block th:switch="${activeCampaign['campaign_status']}">
|
|
<th:block th:case="'ONGOING'">
|
|
<a href="#" th:onclick="return callEdit([[${activeCampaign.campaign_id}]])" data-animation="true" data-toggle="tooltip" data-placement="top" title="Edit" data-original-title="Edit">
|
|
<i class="ik ik-edit f-16 mr-15 text-green"></i>
|
|
</a>
|
|
</th:block>
|
|
<th:block th:case="'CLOSED'">
|
|
<button type="button" class="btn btn-primary" th:onclick="return callEdit([[${activeCampaign.campaign_id}]])">View</button>
|
|
</th:block>
|
|
</th:block>
|
|
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div id="pageLoader" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;">
|
|
<div style="position: relative; top: 50%; transform: translateY(-50%);">
|
|
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;">
|
|
<span class="sr-only">Loading...</span>
|
|
</div>
|
|
<!-- Add the 'Please wait' text below the spinner -->
|
|
<p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p>
|
|
</div>
|
|
</div>
|
|
|
|
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<!-- Edit campaign Category List Modal -->
|
|
<div class="modal fade" id="editcampaignModal" tabindex="-1" role="dialog" aria-labelledby="editcampaignModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
|
|
<div class="modal-dialog modal-lg" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="editModalLabel">Details of Campaign</h5>
|
|
<button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
|
|
<input type="hidden" name="modal_campaign_id" id="modal_campaign_id" />
|
|
|
|
<!-- Row 1: Total Count, Completed, Pending -->
|
|
<div class="form-group row">
|
|
<div class="col-md-3">
|
|
<label for="totalCount">Overall Data</label>
|
|
<input type="text" class="form-control" id="totalCount" readonly>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label for="overallpendingCount">Overall Pending</label>
|
|
<input type="text" class="form-control" id="overallpendingCount" readonly>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label for="completedCount">Assigned Completed</label>
|
|
<input type="text" class="form-control" id="completedCount" readonly>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label for="pendingCount">Assigned Pending</label>
|
|
<input type="text" class="form-control" id="pendingCount" readonly>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Row 2: Call Per Agent, Select Agents, Count -->
|
|
<div class="form-group">
|
|
<label><b><u>Today Assign:</u></b></label>
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<label for="call_per_agent">Call Per Agent<span class="text-danger">*</span></label>
|
|
<input type="text" class="form-control" id="call_per_agent" required>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<label for="agentDropdown" class="form-label fw-bold">Agent Selection <span class="text-danger">*</span></label>
|
|
<div class="dropdown">
|
|
<button class="btn btn-light border rounded w-100 text-start"
|
|
type="button"
|
|
id="agentDropdownBtn"
|
|
data-bs-toggle="dropdown"
|
|
aria-expanded="false">
|
|
Select Agent(s)
|
|
</button>
|
|
<ul class="dropdown-menu p-3"
|
|
aria-labelledby="agentDropdownBtn"
|
|
style="max-height: 250px; overflow-y: auto; width: 100%;">
|
|
<div id="agentCheckboxContainer">
|
|
<!-- Checkboxes will be loaded here -->
|
|
</div>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<label for="call_count">Today calls Count</label>
|
|
<input type="text" class="form-control" id="call_count" readonly>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<input type="hidden" name="modal_category_id" class="form-control" id="modal_category_id" readonly>
|
|
</div>
|
|
|
|
<div class="form-group text-center">
|
|
<button type="button" class="btn btn-primary" id="furtherAssign">Click to Assign</button>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- Edit campaign Modal -->
|
|
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="editModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
|
|
<div class="modal-dialog modal-lg" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="editModalLabel">Edit Campaign</h5>
|
|
<button type="button" class="close" data-bs-dismiss="modal" aria-label="Close" onclick="location.reload();">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="edit-campaign">
|
|
<form id="editForm" onsubmit="submitForm(event)">
|
|
<input type="hidden" name="campaign_id" id="campaign_id" />
|
|
|
|
<div class="form-group">
|
|
<label for="campaign_name">Name<span class="text-danger">*</span></label>
|
|
<input type="text" class="form-control" id="campaign_name" readonly>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<input type="hidden" name ="category_id" class="form-control" id="category_id" readonly>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label><b><u>Event Date:</u></b></label>
|
|
<div class="row">
|
|
<div class="col">
|
|
<label for="start_date">From Date<span class="text-danger">*</span></label>
|
|
<input type="date" class="form-control" id="start_date" readonly>
|
|
</div>
|
|
<div class="col">
|
|
<label for="end_date">To Date<span class="text-danger">*</span></label>
|
|
<input type="date" class="form-control" id="end_date" required>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div class="form-group">
|
|
<label for="description_modal">Description<span class="text-danger">*</span></label>
|
|
<textarea class="form-control" id="description_modal" rows="2" readonly></textarea>
|
|
</div>
|
|
|
|
<!-- Questions & Answers Section -->
|
|
<h5><b>Questions & Answers</b></h5>
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered" id="questionTable">
|
|
<thead>
|
|
<tr>
|
|
<th>Question</th>
|
|
<th>Answers</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<!-- Dynamic content will be inserted here -->
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="card" id="campaignaddquestion">
|
|
<div class="card-header justify-content-between align-items-center">
|
|
<h3><b>Add Questions</b></h3>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="questionsContainer">
|
|
<!-- Dynamic questions will be added here -->
|
|
</div>
|
|
<button type="button" class="btn btn-success mt-3" id="addQuestionBtn">+ Add Question</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group text-center" id="savebuttonhide">
|
|
<button type="submit" class="btn btn-primary" id="editsubmit">Save changes</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div>
|
|
|
|
<script th:replace="~{fragments/modules/base/script :: script}"></script>
|
|
<script src="node_modules/tempusdominus-bootstrap-4/build/js/tempusdominus-bootstrap-4.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
|
|
|
|
<script type="text/javascript">
|
|
|
|
|
|
$(document).ready(function () {
|
|
|
|
|
|
|
|
// Define buttons for DataTables
|
|
var buttons = [
|
|
{
|
|
extend: 'pageLength',
|
|
className: 'btn btn-warning'
|
|
},
|
|
{
|
|
title: 'Data export',
|
|
extend: 'copyHtml5',
|
|
text: 'Copy',
|
|
className: 'btn btn-secondary'
|
|
},
|
|
{
|
|
extend: 'excelHtml5',
|
|
text: 'Excel',
|
|
className: 'btn btn-secondary'
|
|
},
|
|
{
|
|
extend: 'csvHtml5',
|
|
text: 'CSV',
|
|
className: 'btn btn-secondary'
|
|
},
|
|
{
|
|
extend: 'pdfHtml5',
|
|
text: 'PDF',
|
|
className: 'btn btn-secondary'
|
|
}
|
|
];
|
|
|
|
// DataTables initialization for #StartCampaigntable
|
|
$('#StartCampaigntable').DataTable({
|
|
dom: 'Bftip',
|
|
columnDefs: [
|
|
{targets: 'no-sort', orderable: false}
|
|
],
|
|
lengthMenu: [
|
|
[50, 100, 200, 500, -1],
|
|
['50 rows', '100 rows', '200 rows', '500 rows', 'Show all']
|
|
],
|
|
scrollY: '30vh',
|
|
fixedColumns: {
|
|
left: 1,
|
|
right: 1
|
|
},
|
|
buttons: buttons,
|
|
fixedHeader: true,
|
|
autoWidth: true,
|
|
responsive: true,
|
|
searching: true,
|
|
select: false,
|
|
processing: false,
|
|
});
|
|
|
|
// DataTables initialization for #CampaignDatatable
|
|
$('#CampaignDatatable').DataTable({
|
|
dom: 'Bftip',
|
|
columnDefs: [
|
|
{targets: 'no-sort', orderable: false}
|
|
],
|
|
lengthMenu: [
|
|
[50, 100, 200, 500, -1],
|
|
['50 rows', '100 rows', '200 rows', '500 rows', 'Show all']
|
|
],
|
|
scrollY: '50vh',
|
|
fixedColumns: {
|
|
left: 1,
|
|
right: 1
|
|
},
|
|
buttons: buttons,
|
|
fixedHeader: true,
|
|
autoWidth: true,
|
|
responsive: true,
|
|
searching: true,
|
|
select: false,
|
|
processing: false,
|
|
});
|
|
|
|
|
|
/* const rows = document.querySelectorAll("#CampaignDatatable tbody tr");
|
|
rows.forEach(row => {
|
|
const eventDateText = row.querySelector('td:nth-child(4)').innerText; // Get the event date text
|
|
const statusButton = row.querySelector('.status-button'); // Select the status button
|
|
// Parse start and end dates
|
|
const dates = eventDateText.split(' - ');
|
|
const endDate = new Date(dates[1].trim()); // Extract the end date
|
|
// Get the current date
|
|
const currentDate = new Date();
|
|
currentDate.setHours(0, 0, 0, 0); // Reset time to compare dates only
|
|
// Compare dates and update button text and class
|
|
if (endDate >= currentDate) {
|
|
|
|
statusButton.classList.remove('btn-success');
|
|
|
|
statusButton.classList.add('btn-danger');
|
|
|
|
statusButton.innerText = 'Ongoing';
|
|
|
|
} else {
|
|
|
|
statusButton.classList.remove('btn-danger');
|
|
|
|
statusButton.classList.add('btn-success');
|
|
|
|
statusButton.innerText = 'Completed';
|
|
|
|
}
|
|
|
|
}); */
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Start campaign function
|
|
function startCampaign(callsPerAgent, campaignId) {
|
|
$.ajax({
|
|
url: '/gcc/api/campaign/startcampaign?campaign_id=' + campaignId + '&calls_per_agent=' + callsPerAgent, // URL to your Spring Boot controller
|
|
type: 'GET', // GET request
|
|
contentType: 'application/json',
|
|
success: function (response) {
|
|
if (response && response.length > 0 && response != 0) {
|
|
// If the response contains values
|
|
console.log('Campaign started successfully:', response);
|
|
|
|
|
|
Swal.fire({
|
|
allowOutsideClick: false,
|
|
allowEscapeKey: false,
|
|
allowEnterKey: false,
|
|
title: 'Success!',
|
|
text: 'Data transferred successfully!',
|
|
icon: 'success',
|
|
timer: 2000,
|
|
showConfirmButton: false
|
|
}).then(() => {
|
|
location.reload(); // Reload after success
|
|
});
|
|
|
|
} else {
|
|
// If the response is empty, null, or 0
|
|
Swal.fire({
|
|
title: 'Error!',
|
|
text: 'No data was transferred ,Please check Agents are assigned!.',
|
|
icon: 'error',
|
|
timer: 3000,
|
|
showConfirmButton: true
|
|
});
|
|
}
|
|
},
|
|
error: function (xhr, status, error) {
|
|
// Handle error scenario here
|
|
console.error('Error starting campaign:', error);
|
|
// You can show an error message to the user
|
|
Swal.fire({
|
|
title: 'Error!',
|
|
text: 'An error occurred while transferring data.',
|
|
icon: 'error',
|
|
timer: 3000,
|
|
showConfirmButton: true
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
$(document).ready(function () {
|
|
window.callCampEdit = function (campaignId,categoryId) {
|
|
fetchCampaignStatistics(campaignId,categoryId);
|
|
return false; // Prevent default anchor click behavior
|
|
};
|
|
|
|
function fetchCampaignStatistics(campaignId,categoryId) {
|
|
$.ajax({
|
|
url: `/gcc/api/campaign/statistics?campaignId=${campaignId}`,
|
|
type: 'GET',
|
|
dataType: 'json',
|
|
success: function (response) {
|
|
if (response) {
|
|
$('#totalCount').val(response.totalCount || 0);
|
|
$('#completedCount').val(response.completedCount || 0);
|
|
$('#pendingCount').val(response.pendingCount || 0);
|
|
|
|
// Set values in the modal
|
|
$('#modal_campaign_id').val(campaignId);
|
|
$('#modal_category_id').val(categoryId);
|
|
|
|
// Correctly calculate and display Overall Pending Count
|
|
let overallPendingCount = (response.totalCount || 0) - (response.completedCount || 0);
|
|
$('#overallpendingCount').val(overallPendingCount);
|
|
|
|
// Show the modal after populating the fields
|
|
$('#editcampaignModal').modal('show');
|
|
} else {
|
|
console.error('No data returned');
|
|
}
|
|
},
|
|
error: function (xhr, status, error) {
|
|
console.error('Error fetching campaign statistics:', error);
|
|
}
|
|
});
|
|
}
|
|
|
|
$(document).ready(function () {
|
|
function loadAgents() {
|
|
$.ajax({
|
|
url: "/gcc/api/campaign/assignagentid",
|
|
type: "GET",
|
|
dataType: "json",
|
|
success: function (response) {
|
|
console.log("Agents:", response);
|
|
$("#agentCheckboxContainer").empty(); // Clear previous checkboxes
|
|
|
|
// Append "Select All" checkbox
|
|
$("#agentCheckboxContainer").append(`
|
|
<li>
|
|
<label class="dropdown-item">
|
|
<input type="checkbox" id="selectAllAgents"> Select All
|
|
</label>
|
|
</li>
|
|
`);
|
|
|
|
// Append individual agent checkboxes
|
|
response.forEach(agent => {
|
|
$("#agentCheckboxContainer").append(`
|
|
<li>
|
|
<label class="dropdown-item">
|
|
<input type="checkbox" class="agentCheckbox" value="${agent.agent_id}" data-name="${agent.agent_name}">
|
|
${agent.agent_name}
|
|
</label>
|
|
</li>
|
|
`);
|
|
});
|
|
|
|
// "Select All" checkbox logic
|
|
$("#selectAllAgents").change(function () {
|
|
$(".agentCheckbox").prop("checked", this.checked);
|
|
calculateCallCount(); // Recalculate count when selecting all
|
|
});
|
|
|
|
// If any individual checkbox is unchecked, uncheck "Select All"
|
|
$(document).on("change", ".agentCheckbox", function () {
|
|
let allChecked = $(".agentCheckbox").length === $(".agentCheckbox:checked").length;
|
|
$("#selectAllAgents").prop("checked", allChecked);
|
|
calculateCallCount(); // Recalculate count on checkbox change
|
|
});
|
|
|
|
console.log("Agents Loaded...");
|
|
},
|
|
error: function (xhr) {
|
|
console.error("AJAX Error:", xhr.status, xhr.responseText);
|
|
Swal.fire({
|
|
icon: "error",
|
|
title: "Error Fetching Data",
|
|
text: "Failed to load agents. Please try again.",
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// Function to calculate Count = Call Per Agent * Selected Agents
|
|
function calculateCallCount() {
|
|
let callPerAgent = parseInt($("#call_per_agent").val()) || 0;
|
|
let selectedAgentsCount = $(".agentCheckbox:checked").length;
|
|
let totalCount = callPerAgent * selectedAgentsCount;
|
|
|
|
let totalCountValue = parseInt($("#totalCount").val()) || 0;
|
|
let completedCountValue = parseInt($("#completedCount").val()) || 0;
|
|
let pendingCount = totalCountValue - completedCountValue; // Pending count calculation
|
|
|
|
if (totalCount > pendingCount) {
|
|
Swal.fire({
|
|
icon: "warning",
|
|
title: "Warning",
|
|
text: "you can't assign more than overall pending count, now you can assign.",
|
|
|
|
//text: `Assigned Pending count (${totalCount}) cannot exceed the today calls count (${pendingCount}).`,
|
|
});
|
|
totalCount = pendingCount; // Restrict value to pending count
|
|
}
|
|
|
|
$("#call_count").val(totalCount); // Update the Count field
|
|
}
|
|
|
|
// Load agents when the page loads
|
|
loadAgents();
|
|
|
|
// Update count when Call Per Agent changes
|
|
$("#call_per_agent").on("input", function () {
|
|
calculateCallCount();
|
|
});
|
|
|
|
// Update count when agents are selected/deselected
|
|
$(document).on("change", ".agentCheckbox", function () {
|
|
calculateCallCount();
|
|
});
|
|
});
|
|
|
|
|
|
// On 'Save Changes' button click
|
|
$('#furtherAssign').click(function () {
|
|
let campaign_id = $('#modal_campaign_id').val();
|
|
let category_id = $('#modal_category_id').val();
|
|
let call_per_agent = $('#call_per_agent').val();
|
|
|
|
// Get selected agent IDs
|
|
let fselectedAgents = [];
|
|
$(".agentCheckbox:checked").each(function () {
|
|
fselectedAgents.push($(this).val());
|
|
});
|
|
|
|
// Validation check
|
|
if (!call_per_agent) {
|
|
Swal.fire({
|
|
icon: "info",
|
|
title: "Missing Information",
|
|
text: "Please fill in 'Call Per Agent'.",
|
|
});
|
|
return; // Stop further execution
|
|
}
|
|
|
|
if (fselectedAgents.length === 0) {
|
|
Swal.fire({
|
|
icon: "info",
|
|
title: "Missing Information",
|
|
text: "Select at least one agent.",
|
|
});
|
|
return; // Stop further execution
|
|
}
|
|
|
|
console.log("campaign_id=",campaign_id);
|
|
console.log("category_id=",category_id);
|
|
console.log("call_per_agent=",call_per_agent);
|
|
console.log("fselectedAgents=",fselectedAgents);
|
|
|
|
$('#furtherAssign').prop('disabled', true).text('Processing');//Click to Assign
|
|
$('#pageLoader').show();
|
|
// AJAX POST request to submit data
|
|
$.ajax({
|
|
url: "/gcc/api/agents/furtherAssignedAgents",
|
|
type: "POST",
|
|
contentType: "application/json",
|
|
data: JSON.stringify({
|
|
campaign_id: campaign_id,
|
|
category_id: category_id,
|
|
call_per_agent: call_per_agent,
|
|
selected_agents: fselectedAgents // Ensure key matches your controller parameter
|
|
}),
|
|
success: function (response) {
|
|
$('#pageLoader').hide();
|
|
$('#furtherAssign').prop('disabled', false).text('Click to Assign');
|
|
if(response.status ==='success'){
|
|
Swal.fire({
|
|
allowOutsideClick: false,
|
|
allowEscapeKey: false,
|
|
allowEnterKey: false,
|
|
icon: "success",
|
|
title: "Success",
|
|
text: "Agents successfully assigned to the campaign.",
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
$('#furtherAssign').prop('disabled', false).text('Click to Assign');
|
|
$('#editcampaignModal').modal('hide'); // Close modal on success
|
|
location.reload();
|
|
}
|
|
});
|
|
|
|
}
|
|
if(response.status ==='error'){
|
|
|
|
$('#furtherAssign').prop('disabled', false).text('Click to Assign');
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Error',
|
|
text: response.message
|
|
});
|
|
}
|
|
},
|
|
error: function (xhr) {
|
|
$('#pageLoader').hide();
|
|
console.error("AJAX Error:", xhr.status, xhr.responseText);
|
|
$('#furtherAssign').prop('disabled', false).text('Click to Assign');
|
|
Swal.fire({
|
|
icon: "error",
|
|
title: "Error",
|
|
text: "Failed to assign agents. Please try again.",
|
|
});
|
|
}
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
//Update request form details
|
|
$(document).ready(function () {
|
|
// Function to open the edit modal and populate data
|
|
window.callEdit = function (campaignId) {
|
|
fetchCampaignDetails(campaignId);
|
|
|
|
return false; // Prevent default anchor click behavior
|
|
};
|
|
|
|
|
|
|
|
function setEndDateMin() {
|
|
|
|
var fromDate = document.getElementById('start_date').value;
|
|
|
|
document.getElementById('end_date').min = fromDate;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function to load answer types dynamically
|
|
function loadAnswerTypes(callback) {
|
|
$.ajax({
|
|
url: "/gcc/api/getAnswerTypes",
|
|
type: "GET",
|
|
success: function(data) {
|
|
callback(data);
|
|
},
|
|
error: function() {
|
|
console.log("Error loading answer types.");
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
|
|
|
|
function fetchCampaignDetails(campaignId) {
|
|
$.ajax({
|
|
url: `/gcc/api/campaign/getCampaignDetailsById?campaign_id=${campaignId}`,
|
|
type: 'GET',
|
|
success: function (response) {
|
|
console.log("API Response:", response); // Debugging output
|
|
|
|
if (!response) {
|
|
console.log("Response is null or undefined");
|
|
alert("API returned an empty response.");
|
|
return;
|
|
}
|
|
|
|
if (Array.isArray(response)) {
|
|
console.log("Response is an array with length:", response.length);
|
|
} else {
|
|
console.log("Response is not an array, type:", typeof response);
|
|
}
|
|
|
|
if (Array.isArray(response) && response.length > 0) {
|
|
let campaign = response[0]; // Extract first object for campaign details
|
|
|
|
// Ensure category_id is set
|
|
if (campaign.category_id) {
|
|
$('#category_id').val(campaign.category_id);
|
|
console.log("Category ID set:", campaign.category_id);
|
|
} else {
|
|
console.warn("Category ID is missing in API response");
|
|
}
|
|
|
|
|
|
|
|
// Campaign status check
|
|
if (campaign.campaign_status === "CLOSED") {
|
|
$('#campaignaddquestion, #savebuttonhide').hide();
|
|
$('#end_date').prop('readonly', true);
|
|
} else {
|
|
$('#campaignaddquestion, #savebuttonhide').show();
|
|
}
|
|
|
|
|
|
let campaignid = campaign.campaign_id;
|
|
console.log("campaignid ",campaignid);
|
|
// Populate campaign details in the modal
|
|
$('#campaign_id').val(campaign.campaign_id);
|
|
|
|
$('#campaign_name').val(campaign.campaign_name);
|
|
$('#start_date').val(campaign.start_date);
|
|
$('#end_date').val(campaign.end_date);
|
|
$('#no_of_agents').val(campaign.no_of_agents);
|
|
$('#calls_per_agent').val(campaign.calls_per_agent);
|
|
$('#description_modal').val(campaign.description);
|
|
|
|
// Handle questions and answers dynamically
|
|
let questionHtml = "";
|
|
response.forEach(q => {
|
|
let answers = Array.isArray(q.campaign_answer) ? q.campaign_answer.join(", ") : "No Answers";
|
|
questionHtml += `<tr>
|
|
<td>${q.questions}</td>
|
|
<td>${answers}</td>
|
|
</tr>`;
|
|
});
|
|
|
|
// Populate table inside the modal
|
|
$('#questionTable tbody').html(questionHtml);
|
|
|
|
|
|
/////////////this is for adding questions and answers dynamically //////////////
|
|
let questionCount = 0;
|
|
|
|
|
|
let validAnswerTypeIds = [];
|
|
// Function to generate answer type dropdown dynamically
|
|
function generateAnswerTypeDropdown(questionId, answerTypes) {
|
|
let dropdownHtml = `<label for="answerType${questionId}">Select Answer Type<span class="text-danger">*</span></label>
|
|
<select class="form-control answer-type" data-question-id="${questionId}">
|
|
<option value="">--Select--</option>`;
|
|
|
|
$.each(answerTypes, function(index, entry) {
|
|
dropdownHtml += `<option value="${entry.answer_type_id}">${entry.type_name}</option>`;
|
|
if (!validAnswerTypeIds.includes(entry.answer_type_id.toString())) {
|
|
validAnswerTypeIds.push(entry.answer_type_id.toString()); // Store as string
|
|
}
|
|
});
|
|
|
|
dropdownHtml += `</select>`;
|
|
return dropdownHtml;
|
|
}
|
|
|
|
// Add question button
|
|
$('#addQuestionBtn').click(function() {
|
|
|
|
if ($('#questionsContainer').is(':hidden')) {
|
|
$('#questionsContainer').show(); // Show container on first click
|
|
}
|
|
|
|
questionCount++;
|
|
loadAnswerTypes(function(answerTypes) {
|
|
let questionHtml = `
|
|
<div class="question-block border p-3 mb-3" data-question-id="${questionCount}">
|
|
<label for="question${questionCount}">Enter Question <span class="text-danger">*</span></label>
|
|
<input type="text" class="form-control mb-2 question-input" name="question[]" placeholder="Type your question" required>
|
|
${generateAnswerTypeDropdown(questionCount, answerTypes)}
|
|
<div class="answers-container mt-3" id="answersContainer${questionCount}"></div>
|
|
<button type="button" class="btn btn-danger btn-sm mt-2 remove-question">Remove Question</button>
|
|
</div>`;
|
|
$('#questionsContainer').append(questionHtml);
|
|
});
|
|
});
|
|
|
|
// Handle answer type selection
|
|
$(document).on('change', '.answer-type', function() {
|
|
let questionId = $(this).data('question-id');
|
|
let selectedType = $(this).val(); // Keep as string
|
|
let answersContainer = $(`#answersContainer${questionId}`);
|
|
answersContainer.html('');
|
|
|
|
|
|
// Check if selected type is valid
|
|
if (validAnswerTypeIds.includes(selectedType)) {
|
|
let answerBlock = `
|
|
<div class="answer-block">
|
|
<label>Answers:</label>
|
|
<div class="answer-list"></div>
|
|
${selectedType === "1" ? "" : `<button type="button" class="btn btn-info btn-sm add-answer mt-2" data-question-id="${questionId}">+ Add Answer</button>`}
|
|
</div>`;
|
|
answersContainer.append(answerBlock);
|
|
}
|
|
});
|
|
|
|
// Add answer dynamically
|
|
$(document).on('click', '.add-answer', function() {
|
|
let questionId = $(this).data('question-id');
|
|
let answerList = $(`#answersContainer${questionId} .answer-list`);
|
|
let answerInput = `
|
|
<div class="answer-input d-flex align-items-center mb-2">
|
|
<input type="text" class="form-control answer-text" placeholder="Enter answer" required>
|
|
<button type="button" class="btn btn-danger btn-sm remove-answer ms-2">X</button>
|
|
</div>`;
|
|
answerList.append(answerInput);
|
|
});
|
|
|
|
|
|
// Load answer types on page load for the first question
|
|
loadAnswerTypes(function(answerTypes) {
|
|
let initialDropdown = generateAnswerTypeDropdown(0, answerTypes);
|
|
$('#questionsContainer').append(`
|
|
<div class="question-block border p-3 mb-3" data-question-id="0">
|
|
<label for="question0">Enter Question <span class="text-danger">*</span></label>
|
|
<input type="text" class="form-control mb-2 question-input" name="question[]" placeholder="Type your question" required>
|
|
${initialDropdown}
|
|
<div class="answers-container mt-3" id="answersContainer0"></div>
|
|
<button type="button" class="btn btn-danger btn-sm mt-2 remove-question">Remove Question</button>
|
|
</div>`);
|
|
});
|
|
|
|
// Remove question
|
|
$(document).on('click', '.remove-question', function() {
|
|
$(this).closest('.question-block').remove();
|
|
});
|
|
|
|
// Remove answer
|
|
$(document).on('click', '.remove-answer', function() {
|
|
$(this).closest('.answer-input').remove();
|
|
});
|
|
|
|
|
|
// Ensure modal is displayed
|
|
setEndDateMin();
|
|
$('#editModal').modal('show');
|
|
} else {
|
|
alert('Campaign details not found.');
|
|
}
|
|
},
|
|
error: function (xhr, status, error) {
|
|
console.error('Error fetching campaign details:', error);
|
|
alert('An error occurred while fetching campaign details.');
|
|
}
|
|
});
|
|
|
|
|
|
|
|
$('#editsubmit').click(function (event) {
|
|
event.preventDefault(); // Prevent default form submission
|
|
|
|
let campaignId = $('#campaign_id').val();
|
|
if (!campaignId) {
|
|
Swal.fire({
|
|
icon: 'warning',
|
|
title: 'Validation Error',
|
|
text: 'Campaign ID is required.'
|
|
});
|
|
return;
|
|
}
|
|
|
|
var campaignData = {
|
|
campaign_id: parseInt(campaignId), // Ensure it's converted to a number
|
|
|
|
end_date: $('#end_date').val().trim(),
|
|
questionsData: []
|
|
};
|
|
console.log("campaignData ",campaignData);
|
|
let isValid = true; // Validation flag
|
|
|
|
// Validate campaign details
|
|
if ( !campaignData.end_date) {
|
|
Swal.fire({
|
|
icon: 'warning',
|
|
title: 'Validation Error',
|
|
text: 'Please select enddate.'
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Validate questions and answers
|
|
$('.question-block').each(function () {
|
|
|
|
let category = $('#category_id').val()?.trim();
|
|
if (!category) {
|
|
console.warn("Category ID is empty or undefined!");
|
|
} else {
|
|
console.log("Captured Category ID:", category);
|
|
}
|
|
|
|
// Keep as string for comparison
|
|
let questionText = $(this).find('.question-input').val().trim();
|
|
let answerType = $(this).find('.answer-type').val();
|
|
let selectedType = answerType.toString();
|
|
let answers = [];
|
|
|
|
|
|
// Validate question text
|
|
if (!questionText) {
|
|
Swal.fire({
|
|
icon: 'info',
|
|
title: 'Info',
|
|
text: 'Please enter a question before submitting.'
|
|
});
|
|
isValid = false;
|
|
return false; // Exit loop
|
|
}
|
|
|
|
// Validate answer type selection
|
|
if (!answerType) {
|
|
Swal.fire({
|
|
icon: 'info',
|
|
title: 'Info',
|
|
text: 'Please select an answer type for each question.'
|
|
});
|
|
isValid = false;
|
|
return false; // Exit loop
|
|
}
|
|
|
|
|
|
// Skip answer validation for "Text" answer type (ID = 1)
|
|
let answersContainer = $(this).find('.answer-list');
|
|
if (answerType !== "1" && answersContainer.children().length === 1) {
|
|
Swal.fire({
|
|
icon: 'info',
|
|
title: 'Info',
|
|
text: 'Each question must have at least two answer (except for Text type).'
|
|
});
|
|
isValid = false;
|
|
return false; // Exit loop
|
|
}
|
|
|
|
// Validate answers (only if not Text type)
|
|
if (selectedType !== "1") {
|
|
let hasEmptyAnswer = false;
|
|
|
|
$(this).find('.answer-text').each(function () {
|
|
let answer = $(this).val().trim();
|
|
if (answer) {
|
|
answers.push(answer);
|
|
} else {
|
|
hasEmptyAnswer = true;
|
|
}
|
|
});
|
|
|
|
if (hasEmptyAnswer || answers.length === 0) {
|
|
Swal.fire({
|
|
icon: 'info',
|
|
title: 'Info',
|
|
text: 'Please fill in all answer fields before submitting.',
|
|
});
|
|
isValid = false;
|
|
return false; // Stop processing further
|
|
}
|
|
}
|
|
|
|
campaignData.questionsData.push({ category: category, question: questionText, answerType: answerType, answers: answers });
|
|
});
|
|
|
|
if (!isValid) return;
|
|
|
|
// Disable submit button to prevent duplicate submissions
|
|
$('#editsubmit').prop('disabled', true).text('Saving...');
|
|
|
|
// Send data via AJAX
|
|
$.ajax({
|
|
url: '/gcc/api/campaign/updateCampaign',
|
|
type: 'POST',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify(campaignData),
|
|
success: function (response) {
|
|
$('#editsubmit').prop('disabled', false).text('Save changes');
|
|
Swal.fire({
|
|
allowOutsideClick: false,
|
|
allowEscapeKey: false,
|
|
allowEnterKey: false,
|
|
title: 'Success!',
|
|
text: response,
|
|
icon: 'success',
|
|
confirmButtonText: 'OK'
|
|
}).then(() => {
|
|
$('#editsubmit').prop('disabled', false).text('Save changes');
|
|
$('#editModal').modal('hide');
|
|
location.reload();
|
|
});
|
|
},
|
|
error: function (xhr) {
|
|
Swal.fire({ title: 'Error!', text: xhr.responseText, icon: 'error' });
|
|
$('#editsubmit').prop('disabled', false).text('Save Changes');
|
|
}
|
|
});
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/////////////dizo///////////////
|
|
|
|
$(document).ready(function () {
|
|
|
|
/* function checkExpiredCampaigns() {
|
|
$(".status-button").each(function () {
|
|
let button = $(this);
|
|
let campaignId = button.data("id");
|
|
let endDate = button.closest("tr").find("td:nth-child(4)").text().split(" - ")[1].trim(); // Extracting end_date
|
|
|
|
let today = new Date().toISOString().split("T")[0]; // Get current date in YYYY-MM-DD format
|
|
|
|
if (endDate < today) {
|
|
$.ajax({
|
|
url: "/gcc/api/campaign/auto-close",
|
|
type: "POST",
|
|
data: { campaignId: campaignId },
|
|
success: function (response) {
|
|
console.log("Campaign ID " + campaignId + " auto-closed.");
|
|
button.replaceWith('<span class="text-success">Closed</span>'); // Update UI
|
|
},
|
|
error: function (xhr) {
|
|
console.error("Error closing campaign:", xhr.responseText);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
checkExpiredCampaigns(); // Run on page load */
|
|
|
|
$(document).on("click", ".status-button", function () {
|
|
let button = $(this);
|
|
let campaignId = button.data("id"); // Get campaign ID from data attribute
|
|
|
|
if (!campaignId) {
|
|
Swal.fire("Error!", "Campaign ID is missing.", "error");
|
|
return;
|
|
}
|
|
|
|
if (button.text().trim() === "Close") {
|
|
return;
|
|
}
|
|
|
|
Swal.fire({
|
|
title: "Are you sure?",
|
|
text: "Do you want to close the Campaign?",
|
|
icon: "warning",
|
|
showCancelButton: true,
|
|
confirmButtonText: "Yes",
|
|
cancelButtonText: "No",
|
|
confirmButtonColor: "#007bff",
|
|
cancelButtonColor: "#dc3545",
|
|
allowOutsideClick: false,
|
|
allowEscapeKey: false,
|
|
allowEnterKey: false
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
console.log("Closing campaign with ID:", campaignId); // Debugging log
|
|
|
|
$.ajax({
|
|
url: "/gcc/api/campaign/close?campaignId=" + campaignId, // ✅ Ensure query parameter
|
|
type: "POST",
|
|
success: function (response) {
|
|
console.log("Success Response:", response);
|
|
Swal.fire({
|
|
allowOutsideClick: false,
|
|
allowEscapeKey: false,
|
|
allowEnterKey: false,
|
|
title: "Success!",
|
|
text: "Campaign has been closed.",
|
|
icon: "success",
|
|
allowOutsideClick: false,
|
|
allowEscapeKey: false
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
location.reload();
|
|
}
|
|
});
|
|
|
|
},
|
|
error: function (xhr, status, error) {
|
|
console.error("Error Details:", xhr.responseText);
|
|
Swal.fire("Error!", "Failed to close campaign.", "error");
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
});
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|