Merge branch 'dev' of bitbucket.org:jubilian/nhance into dev

This commit is contained in:
VENKATESHWARAN 2026-02-26 15:20:31 +05:30
commit 1cf83a69cd
13 changed files with 219 additions and 261 deletions

View File

@ -302,8 +302,8 @@ class LeadsController extends BaseController
public function viewLeadsList() public function viewLeadsList()
{ {
$data['tab_name'] = 'Leads'; $data['tab_name'] = 'Opportunities';
$data['page_name'] = 'Leads'; $data['page_name'] = 'Opportunities';
// Set basic data // Set basic data
$data['issuer'] = $this->issuer; $data['issuer'] = $this->issuer;
@ -372,7 +372,7 @@ class LeadsController extends BaseController
'lead_type' => [ 'lead_type' => [
'rules' => 'integer', 'rules' => 'integer',
'errors' => ['required' => 'Lead Type is required'] 'errors' => ['required' => 'Opportunity Type is required']
], ],
'issuer' => [ 'issuer' => [
'rules' => 'required', 'rules' => 'required',
@ -934,10 +934,10 @@ class LeadsController extends BaseController
} }
if (count($insertCount) > 0) { if (count($insertCount) > 0) {
return $this->respond(['status' => true, 'lead_id' => $insert, 'message' => 'New Lead created successfully', 'data' => $data], 200); return $this->respond(['status' => true, 'lead_id' => $insert, 'message' => 'New Opportunity created successfully', 'data' => $data], 200);
} }
return $this->respond(['status' => false, 'lead_id' => $insert, 'message' => "Failed to create Lead", 'data' => $data], 200); return $this->respond(['status' => false, 'lead_id' => $insert, 'message' => "Failed to create Opportunity", 'data' => $data], 200);
} }
private function updateOldLead($id, $data) private function updateOldLead($id, $data)
@ -946,9 +946,9 @@ class LeadsController extends BaseController
$this->insertMultiFilesData($data[0]['multi_file_data'], $id, $data[0]['lead_form_type']); $this->insertMultiFilesData($data[0]['multi_file_data'], $id, $data[0]['lead_form_type']);
$this->insertLeadStatus($id, $data[0]['status'], 3); $this->insertLeadStatus($id, $data[0]['status'], 3);
return $this->respond(['status' => true, 'lead_id' => $id, 'message' => "Lead updated successfully", 'data' => $data], 200); return $this->respond(['status' => true, 'lead_id' => $id, 'message' => "Opportunity updated successfully", 'data' => $data], 200);
} }
return $this->respond(['status' => false, 'lead_id' => $id, 'message' => "Failed to update Lead", 'data' => $data], 200); return $this->respond(['status' => false, 'lead_id' => $id, 'message' => "Failed to update Opportunity", 'data' => $data], 200);
} }
// Get the Single Lead data for edit uisng ajax (do not delete) // Get the Single Lead data for edit uisng ajax (do not delete)
@ -1305,7 +1305,7 @@ class LeadsController extends BaseController
if (!$lead_data) { if (!$lead_data) {
// Handle case where lead doesn't exist // Handle case where lead doesn't exist
throw new \Exception('Lead not found'); throw new \Exception('Opportunity not found');
} }
// 4. Conditional query - only fetch if needed // 4. Conditional query - only fetch if needed
@ -1494,7 +1494,7 @@ class LeadsController extends BaseController
$lead_id = $data['lead_id'] ?? null; $lead_id = $data['lead_id'] ?? null;
if (!$lead_id) { if (!$lead_id) {
return $this->respond(['status' => false, 'message' => 'Lead ID is required'], 400); return $this->respond(['status' => false, 'message' => 'Opportunity ID is required'], 400);
} }
$rfq_created = $this->RFQModel->where('lead_id', $lead_id)->where('is_active', 1)->countAllResults(); $rfq_created = $this->RFQModel->where('lead_id', $lead_id)->where('is_active', 1)->countAllResults();
@ -2796,7 +2796,7 @@ class LeadsController extends BaseController
$file_name_with_path = WRITEPATH . "/uploads/lead_files/" . $lead_data['file_name']; $file_name_with_path = WRITEPATH . "/uploads/lead_files/" . $lead_data['file_name'];
if (!$lead_data) { if (!$lead_data) {
return ['status' => 'failed', 'message' => 'Lead data not found']; return ['status' => 'failed', 'message' => 'Opportunity data not found'];
} }
try{ try{
@ -5583,7 +5583,7 @@ class LeadsController extends BaseController
// dd($file_name_with_path); // dd($file_name_with_path);
if (!$lead_data) { if (!$lead_data) {
return ['status' => 'failed', 'message' => 'Lead data not found']; return ['status' => 'failed', 'message' => 'Opportunity data not found'];
} }
if ($lead_data['file_name']) { if ($lead_data['file_name']) {
@ -6579,7 +6579,7 @@ class LeadsController extends BaseController
return $this->respond([ return $this->respond([
'status' => false, 'status' => false,
'code' => 400, 'code' => 400,
'message' => 'Lead ID is required' 'message' => 'Opportunity ID is required'
], 400); ], 400);
} }

View File

@ -88,7 +88,7 @@ class SalesController extends BaseController
} }
// Otherwise fetch ALL sales managers in this branch // Otherwise fetch ALL sales managers in this branch
elseif (in_array($role,[1,2,3,4,5])) { elseif (in_array($role,[1,5])) {
$data['users'] = $db->table('user_profiles up') $data['users'] = $db->table('user_profiles up')
->select('up.id, up.first_name, up.last_name, up.nhance_branch_id') ->select('up.id, up.first_name, up.last_name, up.nhance_branch_id')
@ -793,7 +793,7 @@ class SalesController extends BaseController
// dd($logged_user_id, $nhance_branch_id, $role, $team_id ); // dd($logged_user_id, $nhance_branch_id, $role, $team_id );
if (in_array($role,[5])) { if (in_array($role,[1,5])) {
$sales_manager_ids = array_column( $sales_manager_ids = array_column(
$db->table('user_profiles up') $db->table('user_profiles up')
@ -822,36 +822,46 @@ class SalesController extends BaseController
public function branchLevelDashboard($branchId,$sales_manager_ids) public function branchLevelDashboard($branchId,$sales_manager_ids)
{ {
$data['tab_name'] = 'Dashboard';
$data['page_name'] = 'Dashboard';
// Hardcoded branch ID as requested // Hardcoded branch ID as requested
// $branchId = 1; // $branchId = 1;
try { try {
// 1. Lead Statistics $sales_manager_ids = array_values(array_map('intval', $sales_manager_ids));
$stats = $this->leadModel->getLeadStats(); // Using existing model method
// 2. Activity Statistics // Final safe check
$activityStats = [ if (empty($sales_manager_ids)) {
'total' => $this->activityModel->countAllResults(),
'completed' => $this->activityModel->where('status', 'completed')->countAllResults(),
'pending' => $this->activityModel->where('status', 'pending')->countAllResults(),
];
// 3. Team Performance (Aggregating activity counts per user)
$db = \Config\Database::connect();
// Final safe check
if (empty($sales_manager_ids)) {
// No valid IDs — skip queries or return empty // No valid IDs — skip queries or return empty
$teamPerformance = []; $total_leads = 0;
$recentActivities = []; $total_activity = 0;
$leadsOverview = []; $total_completed_activity = 0;
} else { $total_pending_activity = 0;
$pending_activities = [];
$recent_activities = [];
$teamPerformance = [];
if (empty($sales_manager_ids) || !is_array($sales_manager_ids)) { $leadsOverview = [];
$sales_manager_ids = array_filter((array) $sales_manager_ids); // removes null, "", 0 } else {
}
if (empty($sales_manager_ids) || !is_array($sales_manager_ids)) {
$sales_manager_ids = array_filter((array) $sales_manager_ids); // removes null, "", 0
}
// 1. Lead Statistics
$total_leads = $this->leadModel->whereIn('assigned_to', $sales_manager_ids)->countAllResults(); // Use countAllResults, NOT countAll
// echo $this->leadModel->getLastQuery();die();
// 2. Total activity
$total_activity = $this->activityModel->whereIn('assigned_to', $sales_manager_ids)->countAllResults();
// 3. Completed activity
$total_completed_activity = $this->activityModel->whereIn('assigned_to', $sales_manager_ids)->where('status', 'completed')->countAllResults();
// 4. Pending activity
$total_pending_activity = $this->activityModel->whereIn('assigned_to', $sales_manager_ids)->where('status', 'pending')->countAllResults();
$db = \Config\Database::connect();
// 5. Team Performance
$teamPerformance = $db->table('user_profiles as u') $teamPerformance = $db->table('user_profiles as u')
->select('u.first_name, u.last_name, u.profile as role, ->select('u.first_name, u.last_name, u.profile as role,
(SELECT COUNT(*) FROM sales_activities WHERE assigned_to = u.id) as total_acts, (SELECT COUNT(*) FROM sales_activities WHERE assigned_to = u.id) as total_acts,
@ -861,25 +871,25 @@ class SalesController extends BaseController
->where('u.is_active', 1) ->where('u.is_active', 1)
->get()->getResultArray(); ->get()->getResultArray();
// 4. Recent Activities (Joining for Lead Names) // 6. Recent Activities (Joining for Lead Names)
$recentActivities = $this->activityModel->select('sales_activities.*, sales_actual_leads.company_name') $recent_activities = $this->activityModel->select('sales_activities.*, sales_actual_leads.company_name')
->join('sales_actual_leads', 'sales_actual_leads.lead_id = sales_activities.lead_id') ->join('sales_actual_leads', 'sales_actual_leads.lead_id = sales_activities.lead_id')
->orderBy('sales_activities.scheduled_date', 'DESC') ->orderBy('sales_activities.scheduled_date', 'DESC')
->limit(6) ->limit(6)
->findAll(); ->findAll();
$sales_manager_ids = array_values(array_map('intval', $sales_manager_ids)); // 7. Pending Activities (List)
$recentActivities = $db->table('sales_activities sa') $pending_activities = $db->table('sales_activities sa')
->select('sa.activity_id,sa.lead_id,sa.activity_type,sa.scheduled_date,sa.status,sa.assigned_to,sal.company_name,up.first_name AS assigned_to_name') ->select('sa.activity_id,sa.lead_id,sa.activity_type,sa.scheduled_date,sa.status,sa.assigned_to,sal.company_name,up.first_name AS assigned_to_name,sa.notes')
->join('(SELECT lead_id, MAX(company_name) AS company_name FROM sales_actual_leads GROUP BY lead_id) sal','sal.lead_id = sa.lead_id','left')
->join('user_profiles up', 'up.id = sa.assigned_to', 'left') ->join('user_profiles up', 'up.id = sa.assigned_to', 'left')
->join('sales_actual_leads sal', 'sal.lead_id = sa.lead_id', 'left') // ✅ ADD THIS
->orderBy('sa.scheduled_date', 'DESC') ->orderBy('sa.scheduled_date', 'DESC')
->limit(6)
->whereIn('sa.assigned_to', $sales_manager_ids) ->whereIn('sa.assigned_to', $sales_manager_ids)
->where('sa.status', 'pending')
->get()->getResultArray(); ->get()->getResultArray();
// 5. All Leads Overview // 8. All Leads Overview
$leadsOverview = $db->table('sales_actual_leads sal') $leadsOverview = $db->table('sales_actual_leads sal')
->select('sal.lead_id,sal.company_name,sal.status,up.first_name AS assigned_to, ->select('sal.lead_id,sal.company_name,sal.status,up.first_name AS assigned_to,
COUNT(DISTINCT sa.activity_id) AS activities, COUNT(DISTINCT sa.activity_id) AS activities,
COUNT(DISTINCT l.id) AS opportunities COUNT(DISTINCT l.id) AS opportunities
@ -888,39 +898,34 @@ class SalesController extends BaseController
->join('sales_activities sa', 'sa.lead_id = sal.lead_id', 'left') ->join('sales_activities sa', 'sa.lead_id = sal.lead_id', 'left')
->join('leads l', 'l.actual_lead_id = sal.lead_id', 'left') ->join('leads l', 'l.actual_lead_id = sal.lead_id', 'left')
->groupBy('sal.lead_id, sal.company_name, sal.status, up.first_name') ->groupBy('sal.lead_id, sal.company_name, sal.status, up.first_name')
->having('COUNT(DISTINCT sa.activity_id) + COUNT(DISTINCT l.id) >', 0) // ← this line // ->having('COUNT(DISTINCT sa.activity_id) + COUNT(DISTINCT l.id) >', 0) // ← this line
->orderBy('sal.created_at', 'DESC') ->orderBy('sal.created_at', 'DESC')
->whereIn('sal.assigned_to', $sales_manager_ids) ->whereIn('sal.assigned_to', $sales_manager_ids)
->get() ->get()
->getResultArray(); ->getResultArray();
}
// 6. activityBreakdown
$total = $db->table('sales_activities')->countAll();
// 9. Activity BrakDown
$activityBreakdown = $db->table('sales_activities') $activityBreakdown = $db->table('sales_activities')
->select("activity_type, COUNT(*) AS total, ROUND(COUNT(*) * 100.0 / {$total}, 0) AS percentage", false) ->select("activity_type, COUNT(*) AS total, ROUND(COUNT(*) * 100.0 / {$total_activity}, 0) AS percentage", false)
->whereIn('assigned_to', $sales_manager_ids)
->groupBy('activity_type') ->groupBy('activity_type')
->orderBy('total', 'DESC') ->orderBy('total', 'DESC')
->get() ->get()
->getResultArray(); ->getResultArray();
}
$teamPerformance = array_filter($teamPerformance, function($row) {
return ($row['total_acts'] + $row['done_acts']) > 0;
});
$data = [ $data = [
'total_leads' => $stats['total'], 'total_leads' => $total_leads,
'total_activities' => $activityStats['total'], 'total_acts' => $total_activity,
'completed_acts' => $activityStats['completed'], 'total_completed_acts' => $total_completed_activity,
'pipeline_value' => '15.0L', // Hardcoded placeholder from PDF [cite: 14] 'total_pending_acts'=> $total_pending_activity,
'team' => $teamPerformance, 'pipeline_value' => '15.0L', // Hardcoded placeholder from PDF [cite: 14]
'recent_acts' => $recentActivities, 'team' => $teamPerformance,
'leads_overview' => $leadsOverview, 'recent_acts' => $recent_activities,
'pending_acts' => $pending_activities,
'leads_overview' => $leadsOverview,
'activity_breakdown'=> $activityBreakdown, 'activity_breakdown'=> $activityBreakdown,
'tab_name' => "Sales Dashboard", 'tab_name' => "Sales Dashboard",
'page_name' => "Sales Dashboard" 'page_name' => "Sales Dashboard"
]; ];
// dd($data); // dd($data);

View File

@ -2073,7 +2073,7 @@
<a href="<?= base_url('/leads/list') ?>" class="img-inactive"> <a href="<?= base_url('/leads/list') ?>" class="img-inactive">
<img <img
src="<?= base_url() . "public"; ?>/assets/images/leads_sb.png" alt="Logo" height="20"> src="<?= base_url() . "public"; ?>/assets/images/leads_sb.png" alt="Logo" height="20">
<span> Leads </span> <span> Opportunities </span>
</a> </a>
</li> </li>
<?php } ?> <?php } ?>

View File

@ -39,7 +39,7 @@
</div> </div>
<div class="form-group col-md-3"> <div class="form-group col-md-3">
<label for="filter_lead_type"> Lead Type <span class="text-danger"></span></label> <label for="filter_lead_type"> Opportunity Type <span class="text-danger"></span></label>
<select class="form-control" id="filter_lead_type" name="filter_lead_type"> <select class="form-control" id="filter_lead_type" name="filter_lead_type">
<option value="0">Select</option> <option value="0">Select</option>
<?php <?php

View File

@ -165,10 +165,10 @@ $isActive = get_role_id() == STAFF_ROLE_ID && in_array(ENROLLMENT_TEAM_ID, user_
<div class="leadTypeTile"> <div class="leadTypeTile">
<div class="card dash-card" onclick="hide_and_show_tile(1,1)"> <div class="card dash-card" onclick="hide_and_show_tile(1,1)">
<div class="card-block"> <div class="card-block">
<h4 class="mb-3">Leads</h4> <h4 class="mb-3">opportunities</h4>
<h2 ><span class="span-color"><?= isset($lead_data) ? $lead_data['total'] : 0 ?></span> <h2 ><span class="span-color"><?= isset($lead_data) ? $lead_data['total'] : 0 ?></span>
</h2> </h2>
<h6><span class="text-danger">Lead Tracker</span></h6> <h6><span class="text-danger">Opportunity Tracker</span></h6>
</div> </div>
</div> </div>
</div> </div>

View File

@ -124,7 +124,7 @@
<a href="<?= base_url('leads/list') ?>" style="cursor: pointer;"> <a href="<?= base_url('leads/list') ?>" style="cursor: pointer;">
<i class="mdi mdi-chevron-left" style="font-size: 43px;"></i> <i class="mdi mdi-chevron-left" style="font-size: 43px;"></i>
</a> </a>
<span class="title-text" id="page_title" style="position: relative;">Add Lead</span> <span class="title-text" id="page_title" style="position: relative;">Add Opportunity</span>
</h4> </h4>
</div> </div>
<form role="form" class="parsley-examples" method="post" id="leads_form_id" <form role="form" class="parsley-examples" method="post" id="leads_form_id"
@ -139,9 +139,9 @@
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="lead_type">Lead Type<span class="text-danger">*</span></label> <label for="lead_type">Opportunity Type<span class="text-danger">*</span></label>
<select class="form-control" id="lead_type" name="lead_type" required> <select class="form-control" id="lead_type" name="lead_type" required>
<option value="">Select Lead Type</option> <option value="">Select Opportunity Type</option>
<?php <?php
if (isset($lead_type) && count($lead_type)) { if (isset($lead_type) && count($lead_type)) {
foreach ($lead_type as $key => $value) { foreach ($lead_type as $key => $value) {
@ -739,7 +739,7 @@
hide_list_show_add(); hide_list_show_add();
var page_title = 'Edit Lead'; var page_title = 'Edit Opportunity';
$('#page_title').text(page_title); $('#page_title').text(page_title);
$('#leads_primarykey').val(res.data.id); $('#leads_primarykey').val(res.data.id);

View File

@ -955,7 +955,7 @@ if (isset($selected_lead_type)) {
hide_list_show_add(); hide_list_show_add();
$('#page_title').text('Edit Lead'); $('#page_title').text('Edit Opportunity');
$('#leads_primarykey').val(data.id || ''); $('#leads_primarykey').val(data.id || '');
$('#actual_lead_id').val(data.actual_lead_id || 0); $('#actual_lead_id').val(data.actual_lead_id || 0);
$('#policy_start_date').val(data.policy_end_date || ''); $('#policy_start_date').val(data.policy_end_date || '');
@ -1130,7 +1130,7 @@ if (isset($selected_lead_type)) {
} }
} }
$('#page_title').text('Edit Lead'); $('#page_title').text('Edit Opportunity');
$('#leads_primarykey').val(data.id || ''); $('#leads_primarykey').val(data.id || '');
$('#actual_lead_id').val(data.actual_lead_id || 0); $('#actual_lead_id').val(data.actual_lead_id || 0);
$('#policy_start_date').val(data.policy_end_date || ''); $('#policy_start_date').val(data.policy_end_date || '');

View File

@ -151,7 +151,7 @@ table.dataTable tbody td {
<div class="card-body"> <div class="card-body">
<div class="row" style="margin-bottom:1rem;"> <div class="row" style="margin-bottom:1rem;">
<div class="col-6" style="align-self: center;"> <div class="col-6" style="align-self: center;">
<h4 style="position: relative;">Leads List</h4> <h4 style="position: relative;">Opportunities List</h4>
</div> </div>
<div class="col-3" id="status_change" style="text-align: right; position: relative;top: 56px; left: 291px;"> <div class="col-3" id="status_change" style="text-align: right; position: relative;top: 56px; left: 291px;">
@ -165,7 +165,7 @@ table.dataTable tbody td {
<thead class="bg-light"> <thead class="bg-light">
<tr> <tr>
<th><div class="column-header">S.No &nbsp;</div></th> <th><div class="column-header">S.No &nbsp;</div></th>
<th><div class="column-header">Lead Type &nbsp;</div></th> <th><div class="column-header">Opportunity Type &nbsp;</div></th>
<th><div class="column-header">Issuer &nbsp;</div></th> <th><div class="column-header">Issuer &nbsp;</div></th>
<th><div class="column-header">Client Type &nbsp;</div></th> <th><div class="column-header">Client Type &nbsp;</div></th>
<th><div class="column-header">Client / Branch &nbsp;</div></th> <th><div class="column-header">Client / Branch &nbsp;</div></th>
@ -257,7 +257,7 @@ table.dataTable tbody td {
<div class="modal-dialog modal-dialog-centered"> <div class="modal-dialog modal-dialog-centered">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h4 class="modal-title" id="myCenterModalLabel">Select Lead Type</h4> <h4 class="modal-title" id="myCenterModalLabel">Select Opportunity Type</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
@ -265,14 +265,14 @@ table.dataTable tbody td {
<div class="radio-option selected" onclick="selectOption(this, 'lead_eb')"> <div class="radio-option selected" onclick="selectOption(this, 'lead_eb')">
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="radio" name="lead_form_type" id="lead_eb" value="1" checked> <input class="form-check-input" type="radio" name="lead_form_type" id="lead_eb" value="1" checked>
<label class="form-check-label" for="lead_eb">Lead EB</label> <label class="form-check-label" for="lead_eb">EB</label>
</div> </div>
</div> </div>
<div class="radio-option" onclick="selectOption(this, 'lead_non_eb')"> <div class="radio-option" onclick="selectOption(this, 'lead_non_eb')">
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="radio" name="lead_form_type" id="lead_non_eb" value="2"> <input class="form-check-input" type="radio" name="lead_form_type" id="lead_non_eb" value="2">
<label class="form-check-label" for="lead_non_eb">Lead Non-EB</label> <label class="form-check-label" for="lead_non_eb">Non-EB</label>
</div> </div>
</div> </div>
</div> </div>
@ -467,7 +467,7 @@ table.dataTable tbody td {
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]], lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
buttons: [ buttons: [
{ {
text: 'Add', text: '<i class="mdi mdi-plus" ></i><span class=" btn-custom"> Add </span>',
className: 'btn app-btn-primary mr-2', className: 'btn app-btn-primary mr-2',
action: function(e, dt, node, config) { action: function(e, dt, node, config) {
openLeadTypeAskModal(); openLeadTypeAskModal();
@ -481,7 +481,7 @@ table.dataTable tbody td {
{ {
extend: 'csv', extend: 'csv',
text: '<i class="mdi mdi-file-delimited " ></i><span class=" btn-custom"> CSV </span>', text: '<i class="mdi mdi-file-delimited " ></i><span class=" btn-custom"> CSV </span>',
title: 'Policy-Tranction-Inception-List', title: 'Opportunity-List',
className: 'app-btn-primary ', className: 'app-btn-primary ',
exportOptions: { exportOptions: {
columns: ':not(:last-child)' columns: ':not(:last-child)'
@ -523,7 +523,7 @@ table.dataTable tbody td {
// let Lead_type = $('#openLeadTypeAskModal').val() // let Lead_type = $('#openLeadTypeAskModal').val()
let Lead_type = $('input[name="lead_form_type"]:checked').val(); let Lead_type = $('input[name="lead_form_type"]:checked').val();
console.log('Lead_type ', Lead_type) console.log('Lead_type ', Lead_type)
let url = '<?=base_url('/util/getLeadNonEB/')?>' + Lead_type let url = '<?=base_url('/util/getLeadNonEB/')?>' + Lead_type + '/0';
console.log('url ', url) console.log('url ', url)
window.location.href = url; window.location.href = url;

View File

@ -66,7 +66,7 @@
<a href="<?= base_url('leads/list') ?>" style="cursor: pointer;" type="button" id="btnAdd"> <a href="<?= base_url('leads/list') ?>" style="cursor: pointer;" type="button" id="btnAdd">
<i class="mdi mdi-chevron-left" style="font-size: 43px;"></i> <i class="mdi mdi-chevron-left" style="font-size: 43px;"></i>
</a> </a>
<span class="title-text" id="page_title" style="position: relative;">Add Lead</span> <span class="title-text" id="page_title" style="position: relative;">Add Opportunity</span>
</h4> </h4>
</div> </div>
<form role="form" class="parsley-examples" method="post" id="leads_non_eb_form_id" <form role="form" class="parsley-examples" method="post" id="leads_non_eb_form_id"
@ -81,9 +81,9 @@
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="lead_type">Lead Type<span class="text-danger">*</span></label> <label for="lead_type">Opportunity Type<span class="text-danger">*</span></label>
<select class="form-control" id="lead_type" name="lead_type" required> <select class="form-control" id="lead_type" name="lead_type" required>
<option value="">Select Lead Type</option> <option value="">Select Opportunity Type</option>
<?php <?php
if (isset($lead_type) && count($lead_type)) { if (isset($lead_type) && count($lead_type)) {
foreach ($lead_type as $key => $value) { foreach ($lead_type as $key => $value) {

View File

@ -255,7 +255,7 @@
<button type="button" class="activity-type-btn d_activity_type" data-type="Email" onclick="selectType('Email', this)">✉️ Email</button> <button type="button" class="activity-type-btn d_activity_type" data-type="Email" onclick="selectType('Email', this)">✉️ Email</button>
<button type="button" class="activity-type-btn d_activity_type" data-type="Meeting" onclick="selectType('Meeting', this)">📅 Meeting</button> <button type="button" class="activity-type-btn d_activity_type" data-type="Meeting" onclick="selectType('Meeting', this)">📅 Meeting</button>
<button type="button" class="activity-type-btn d_activity_type" data-type="Visit" onclick="selectType('Visit', this)">🚗 Visit</button> <button type="button" class="activity-type-btn d_activity_type" data-type="Visit" onclick="selectType('Visit', this)">🚗 Visit</button>
<button type="button" class="activity-type-btn d_activity_type" data-type="Demo" onclick="selectType('Demo', this)">🎬 Demo</button> <button type="button" class="activity-type-btn d_activity_type" data-type="Demo" onclick="selectType('Demo', this)">🖥️ Demo</button>
<button type="button" class="activity-type-btn d_activity_type" data-type="Share" onclick="selectType('Share', this)">📄 Share Docs</button> <button type="button" class="activity-type-btn d_activity_type" data-type="Share" onclick="selectType('Share', this)">📄 Share Docs</button>
<button type="button" class="activity-type-btn d_activity_type" data-type="Todo" onclick="selectType('Todo', this)"> To Do</button> <button type="button" class="activity-type-btn d_activity_type" data-type="Todo" onclick="selectType('Todo', this)"> To Do</button>
</div> </div>
@ -274,8 +274,8 @@
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="form-label">Assigned To</label> <label class="form-label">Assigned To <span class="text-danger">*</span></label>
<select id="act_owner" class="search-input searchable" style="width:100%"> <select id="act_owner" class="search-input searchable" style="width:100%" required>
<?php foreach($users as $user): ?> <?php foreach($users as $user): ?>
<option value="<?= $user['id'] ?>"><?= $user['first_name'] ?></option> <option value="<?= $user['id'] ?>"><?= $user['first_name'] ?></option>
<?php endforeach; ?> <?php endforeach; ?>
@ -325,7 +325,7 @@
<button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Email', this)">✉️ Email</button> <button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Email', this)">✉️ Email</button>
<button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Meeting', this)">📅 Meeting</button> <button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Meeting', this)">📅 Meeting</button>
<button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Visit', this)">🚗 Visit</button> <button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Visit', this)">🚗 Visit</button>
<button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Demo', this)">🎬 Demo</button> <button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Demo', this)">🖥️ Demo</button>
<button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Share', this)">📄 Share Docs</button> <button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Share', this)">📄 Share Docs</button>
<button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Todo', this)"> To Do</button> <button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Todo', this)"> To Do</button>
@ -429,7 +429,7 @@ function resetFlatpicker(){
}); });
} }
const activityIcons = { Call: "📞", Email: "✉️", Meeting: "📅", Visit: "🚗",Demo: "🎬", Share: "📄", Todo: "" }; const activityIcons = { Call: "📞", Email: "✉️", Meeting: "📅", Visit: "🚗",Demo: "🖥️", Share: "📄", Todo: "" };
const salesManagerIds = <?= json_encode($sales_manager_ids ?? []) ?>; const salesManagerIds = <?= json_encode($sales_manager_ids ?? []) ?>;
const API = '<?= base_url('sales') ?>'; const API = '<?= base_url('sales') ?>';
@ -480,6 +480,10 @@ function closeModal(id) {
} }
function openMainActivityModal() { function openMainActivityModal() {
document.getElementById('act_owner').value = "";
document.getElementById('act_owner').dispatchEvent(new Event('change'));
document.getElementById('act_lead_id').value = "";
document.getElementById('act_lead_id').dispatchEvent(new Event('change'));
document.getElementById('act_string_flag').value = "frommain"; // ✅ flag for main document.getElementById('act_string_flag').value = "frommain"; // ✅ flag for main
openModal('activityModal'); openModal('activityModal');
} }
@ -787,6 +791,7 @@ function openActivityModal() {
document.getElementById('act_lead_id').value = lead_id; document.getElementById('act_lead_id').value = lead_id;
document.getElementById('act_lead_id').dispatchEvent(new Event('change')); document.getElementById('act_lead_id').dispatchEvent(new Event('change'));
document.getElementById('act_string_flag').value = "frompopup"; document.getElementById('act_string_flag').value = "frompopup";
openModal('activityModal');
} }
function openComp(id, assigned_to, lead_id, string_flag) { function openComp(id, assigned_to, lead_id, string_flag) {
@ -1123,149 +1128,6 @@ document.getElementById('do_follow').addEventListener('change', function () {
selectedFollowUpActivityType = ''; // Reset global variable selectedFollowUpActivityType = ''; // Reset global variable
} }
}); });
const btnSaveContact = document.getElementById('btnSaveContact');
if (btnSaveContact) {
btnSaveContact.onclick = async (e) => {
e.preventDefault(); // Prevent accidental form submission
// 1. Get and Trim Values
const nameInput = document.getElementById('contact_name');
const mobileInput = document.getElementById('contact_mobile');
const leadIdInput = document.getElementById('lead_id');
const name = nameInput.value.trim();
const mobile = mobileInput.value.trim();
const lead_id = leadIdInput.value.trim();
// 2. Simple Client-Side Validation
if (!name || !mobile) {
return toastr.warning('Please enter both contact person name and mobile number.');
}
let payload = { lead_id: lead_id, name: name, mobile: mobile };
// Reset previous error states
document.querySelectorAll('.is-invalid').forEach(el => el.classList.remove('is-invalid'));
try {
const res = await fetch(`${API}/contacts`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
const result = await res.json();
if (res.ok) {
// Success: Clear inputs
nameInput.value = '';
mobileInput.value = '';
// Hide "No Data" message if it exists
const noData = document.getElementById('NoData');
if(noData) noData.style.display = 'none';
// Generate HTML for the new contact
const contactHtml = `
<div class="contact-card d-flex justify-content-between align-items-center mb-2 p-2"
style="background: #f8f8f8; border-radius: 8px;"
data-id="${result.data.contact_id}">
<div>
<div class="fw-bold">${result.data.name}</div>
<div class="text-muted">${result.data.mobile}</div>
</div>
<div>
<button type="button"
class="btn btn-danger btn-sm btnRemoveContact"
data-id="${result.data.contact_id}">
Remove
</button>
</div>
</div>
`;
// <button type="button"
// class="btn btn-secondary btn-sm btnEditContact"
// data-id="${result.data.contact_id}">
// Update
// </button>
// Append to container
document.getElementById('savedContactsContainer').insertAdjacentHTML('beforeend', contactHtml);
toastr.success('Contact saved successfully');
} else {
// Handle Errors using the 'result' we already parsed
if (res.status === 400) {
let errorMessages = "";
let seenMessages = [];
let isFirstError = true; // Fixed: Variable initialization
if (result.messages) {
Object.entries(result.messages).forEach(([field, message]) => {
// Find element by name attribute (Vanilla JS)
let inputElement = document.querySelector(`[name="${field}"]`);
if (inputElement) {
inputElement.classList.add('is-invalid');
if (isFirstError) {
setTimeout(() => inputElement.focus(), 100);
isFirstError = false;
}
}
if (!seenMessages.includes(message)) {
errorMessages += `• ${message}<br>`;
seenMessages.push(message);
}
});
toastr.error(errorMessages, 'Validation Error', { allowHtml: true });
} else {
toastr.warning(result.message || 'Validation failed');
}
} else {
toastr.error(result.message || 'An error occurred while saving.');
}
}
} catch (error) {
console.error("Fetch Error:", error);
toastr.error('Network error or server is unreachable.');
}
};
}
const savedContactsContainer = document.getElementById('savedContactsContainer');
if (savedContactsContainer) {
savedContactsContainer.onclick = async (e) => {
// Check if the clicked element is a Remove button
if (e.target.classList.contains('btnRemoveContact')) {
const btn = e.target;
const contactId = btn.dataset.id; // Get data-id
const card = btn.closest('.contact-card'); // Find the parent card
try {
const res = await fetch(`${API}/contacts/${contactId}`, {
method: 'DELETE',
});
if (res.ok) {
card.remove(); // Remove from DOM
toastr.success('Contact removed successfully');
// Check if container is empty to show "No Data"
const container = document.getElementById('savedContactsContainer');
if (container.querySelectorAll('.contact-card').length === 0) {
const noData = document.getElementById('NoData');
if(noData) noData.style.display = 'block';
}
} else {
toastr.error('Failed to remove contact');
}
} catch (error) {
console.error(error);
toastr.error('An error occurred');
}
}
};
}
function convertDBFormatted(input) { function convertDBFormatted(input) {

View File

@ -89,17 +89,17 @@
<!-- <div class="stat-change text-success"> 12% this month</div> --> <!-- <div class="stat-change text-success"> 12% this month</div> -->
</div> </div>
<div class="card-hero"> <div class="card-hero">
<div class="stat-val"><?php echo $total_activities ?></div> <div class="stat-val"><?php echo $total_acts ?></div>
<div class="stat-label">Total Activities</div> <div class="stat-label">Total Activities</div>
<!-- <div class="stat-change text-success"> 5% this month</div> --> <!-- <div class="stat-change text-success"> 5% this month</div> -->
</div> </div>
<div class="card-hero"> <div class="card-hero">
<div class="stat-val"><?php echo ($total_activities - $completed_acts) ?></div> <div class="stat-val"><?php echo $total_pending_acts ?></div>
<div class="stat-label">Pending Activities</div> <div class="stat-label">Pending Activities</div>
<!-- <div class="stat-change text-success"> 15% this month</div> --> <!-- <div class="stat-change text-success"> 15% this month</div> -->
</div> </div>
<div class="card-hero"> <div class="card-hero">
<div class="stat-val"><?php echo $completed_acts ?></div> <div class="stat-val"><?php echo $total_completed_acts ?></div>
<div class="stat-label">Completed Activities</div> <div class="stat-label">Completed Activities</div>
<!-- <div class="stat-change text-success"> 15% this month</div> --> <!-- <div class="stat-change text-success"> 15% this month</div> -->
</div> </div>
@ -113,8 +113,8 @@
<div class="main-grid"> <div class="main-grid">
<div class="card"> <div class="card">
<div class="table-header"> <div class="table-header">
<h3 style="font-size: 16px; font-weight: 700;">Recent Activities - All Team</h3> <h3 style="font-size: 16px; font-weight: 700;">Pending Activities - All Team</h3>
<span style="color: #718096; font-size: 12px; font-weight: 600;">6 activities</span> <span style="color: #718096; font-size: 12px; font-weight: 600;"><?= count($pending_acts) . ' ' . (count($pending_acts) == 1 ? 'activity' : 'activities') ?></span>
</div> </div>
<table> <table>
<thead> <thead>
@ -126,21 +126,21 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<?php if (!empty($recent_acts)): ?> <?php if (!empty($pending_acts)): ?>
<?php foreach ($recent_acts as $a): ?> <?php foreach ($pending_acts as $a): ?>
<?php <?php
$activityIcons = [ $activityIcons = [
'Call' => '📞', 'Call' => '📞',
'Email' => '✉️', 'Email' => '✉️',
'Meeting' => '📅', 'Meeting' => '📅',
'Visit' => '🚗', 'Visit' => '🚗',
'Demo' => '🎬', 'Demo' => '🖥️',
'Share' => '📄', 'Share' => '📄',
'Todo' => '✓' 'Todo' => '✓'
]; ];
$icon = $activityIcons[$a['activity_type']] ?? '📌'; $icon = $activityIcons[$a['activity_type']] ?? '📌';
$statusClass = strtolower(str_replace(' ', '-', $a['status'])); $statusClass = strtolower(str_replace(' ', '-', $a['status']));
$formattedDate = date('d M Y', strtotime($a['scheduled_date'])); $formattedscheduledDate = date('M d, Y, h:i A', strtotime($a['scheduled_date']));
?> ?>
<tr> <tr>
<td><strong><?= esc($a['company_name']) ?></strong></td> <td><strong><?= esc($a['company_name']) ?></strong></td>
@ -151,8 +151,11 @@
<div style="font-size: 12px; color: #718096;"> <div style="font-size: 12px; color: #718096;">
<?= esc($a['assigned_to_name'] ?? 'ID: ' . $a['assigned_to']) ?> <?= esc($a['assigned_to_name'] ?? 'ID: ' . $a['assigned_to']) ?>
</div> </div>
<!-- <div style="font-size: 12px; color: #718096;">
<?= esc($a['notes'] ?? 'ID: ' . $a['assigned_to']) ?>
</div> -->
</td> </td>
<td style="color: #4a5568; font-weight: 500;"><?= $formattedDate ?></td> <td style="color: #4a5568; font-weight: 500;"><?= $formattedscheduledDate ?></td>
<td><span class="status-pill status-<?= $statusClass ?>"><?= ucfirst(esc($a['status'])) ?></span></td> <td><span class="status-pill status-<?= $statusClass ?>"><?= ucfirst(esc($a['status'])) ?></span></td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
@ -213,7 +216,7 @@
'Email' => ['color' => '#48bb78', 'icon' => '✉️'], 'Email' => ['color' => '#48bb78', 'icon' => '✉️'],
'Meeting' => ['color' => '#4299e1', 'icon' => '📅'], 'Meeting' => ['color' => '#4299e1', 'icon' => '📅'],
'Visit' => ['color' => '#ecc94b', 'icon' => '🚗'], 'Visit' => ['color' => '#ecc94b', 'icon' => '🚗'],
'Demo' => ['color' => '#9f7aea', 'icon' => '🎬'], 'Demo' => ['color' => '#9f7aea', 'icon' => '🖥️'],
'Share' => ['color' => '#ed8936', 'icon' => '📄'], 'Share' => ['color' => '#ed8936', 'icon' => '📄'],
'Todo' => ['color' => '#718096', 'icon' => '✓'], 'Todo' => ['color' => '#718096', 'icon' => '✓'],
]; ];
@ -228,7 +231,7 @@
?> ?>
<div class="breakdown-item"> <div class="breakdown-item">
<span> <span>
<span class="dot" style="background: <?= $color ?>;"></span> <span style="background: <?= $color ?>;"></span>
<?= $icon ?> <?= esc($type) ?> <?= $icon ?> <?= esc($type) ?>
</span> </span>
<strong><?= $item['percentage'] ?>%</strong> <strong><?= $item['percentage'] ?>%</strong>
@ -244,7 +247,13 @@
<div class="card"> <div class="card">
<div class="table-header"> <div class="table-header">
<h3 style="font-size: 16px; font-weight: 700;">All Leads Overview</h3> <h3 style="font-size: 16px; font-weight: 700;">All Leads Overview</h3>
<span style="color: #718096; font-size: 12px; font-weight: 600;">Click a lead to see details</span> <!-- <span style="color: #718096; font-size: 12px; font-weight: 600;">Click a lead to see details</span> -->
<a href="<?= base_url('sales') ?>"
style="color: #718096; font-size: 12px; font-weight: 600; text-decoration: none; padding: 4px 8px; transition: color 0.2s ease; display: inline-block; cursor: pointer;"
onmouseover="this.style.color='#ff6b35';"
onmouseout="this.style.color='#718096';">
Click a lead to see details
</a>
</div> </div>
<table> <table>
<thead> <thead>

View File

@ -48,6 +48,23 @@
.btn-view { background: #f0f0f0; color: #666; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 13px; transition: all 0.2s;} .btn-view { background: #f0f0f0; color: #666; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 13px; transition: all 0.2s;}
.btn-view:hover { background: #f0f0f0; transform: translateY(-1px); } .btn-view:hover { background: #f0f0f0; transform: translateY(-1px); }
/* Fix for the grid layout on smaller screens */
@media (max-width: 992px) {
.dashboard-grid { grid-template-columns: 1fr; }
}
/* Fix for inputs inside modal rows */
input, select, textarea {
width: 100%; /* Change from 400px to 100% */
box-sizing: border-box; /* Ensures padding doesn't add to width */
padding: 10px 15px;
border: 1px solid #e0e0e0;
border-radius: 8px;
font-size: 14px;
}
</style> </style>
<div class="my-dash"> <div class="my-dash">
@ -99,13 +116,15 @@
</div> </div>
</div> </div>
<div class="dashboard-grid"> <div class="dashboard-grid">
<div class="list-card"> <div class="list-card">
<div style="display:flex; justify-content:space-between; margin-bottom:15px; align-items: center;"> <div style="display:flex; justify-content:space-between; margin-bottom:15px; align-items: center;">
<h3 style="font-size:16px; font-weight: 700; margin: 0;">My Upcoming Activities</h3> <h3 style="font-size:16px; font-weight: 700; margin: 0;">My Upcoming Activities</h3>
<span style="color:#ff6b35; font-size:12px; font-weight: 600;"><?= $acts['pending'] ?> pending</span> <span style="color:#ff6b35; font-size:12px; font-weight: 600;"><?= $acts['pending'] ?> pending</span>
</div> </div>
<?php foreach($upcoming as $u): ?> <!-- <?php foreach($upcoming as $u): ?>
<div class="list-item"> <div class="list-item">
<div> <div>
<div style="font-weight:600; font-size:14px; color: #333;"><?= $u['company_name'] ?></div> <div style="font-weight:600; font-size:14px; color: #333;"><?= $u['company_name'] ?></div>
@ -113,13 +132,41 @@
</div> </div>
<button class="badge-done" onclick="openComp(<?= $u['activity_id'] ?>,<?= $u['lead_id'] ?>)"> Mark as completed</button> <button class="badge-done" onclick="openComp(<?= $u['activity_id'] ?>,<?= $u['lead_id'] ?>)"> Mark as completed</button>
</div> </div>
<?php endforeach; ?> -->
<?php foreach($upcoming as $u):
$activityIcons = [ 'Call' => '📞', 'Email' => '✉️', 'Meeting' => '📅', 'Visit' => '🚗', 'Demo' => '🖥️', 'Share' => '📄', 'Todo' => '✓' ];
$icon = $activityIcons[$u['activity_type']] ?? '📌';
$formattedscheduledDate = date('M d, Y, h:i A', strtotime($u['scheduled_date']));
?>
<div class="list-item" style="display: flex; align-items: center; gap: 15px;">
<div class="lead-initial" style="flex-shrink: 0;">
<?= $icon ?>
</div>
<div style="flex-grow: 1; display: flex; flex-direction: column; min-width: 0;">
<div style="font-weight: 700; font-size: 14px; color: #333; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
<?= esc($u['company_name']) ?>
</div>
<div style="font-size: 11px; color: #999; margin-top: 2px; white-space: nowrap;">
<span style="color: #ff6b35; font-weight: 600;"><?= strtoupper($u['activity_type'] ?? 'EMAIL') ?></span>
- <?= $formattedscheduledDate ?>
</div>
</div>
<div style="flex-shrink: 0;">
<button class="badge-done" onclick="openComp(<?= $u['activity_id'] ?>, <?= $u['lead_id'] ?>)">
Mark as completed
</button>
</div>
</div>
<?php endforeach; ?> <?php endforeach; ?>
</div> </div>
<div class="list-card"> <div class="list-card">
<h3 style="font-size:16px; font-weight: 700; margin-bottom:20px;">My Recent Leads</h3> <h3 style="font-size:16px; font-weight: 700; margin-bottom:20px;">My Recent Leads</h3>
<?php foreach($recent_leads as $rl): ?> <?php foreach($recent_leads as $rl): ?>
<div class="list-item"> <!-- <div class="list-item">
<div style="display:flex; gap:12px; align-items:center;"> <div style="display:flex; gap:12px; align-items:center;">
<div class="lead-initial"><?= substr($rl['company_name'], 0, 1) ?></div> <div class="lead-initial"><?= substr($rl['company_name'], 0, 1) ?></div>
<div> <div>
@ -128,6 +175,35 @@
</div> </div>
</div> </div>
<span class="status-pill" style="background: #e3f2fd; color: #1976d2;"><?= $rl['status'] ?></span> <span class="status-pill" style="background: #e3f2fd; color: #1976d2;"><?= $rl['status'] ?></span>
</div> -->
<div class="list-item" style="display: flex; align-items: center; gap: 15px; padding: 12px 0; border-bottom: 1px solid #f9f9f9;">
<div style="flex-shrink: 0;">
<div class="avatar-title"
style="background-color: #f1f3fa; width: 42px; height: 42px; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #1976d2; font-weight: 700; font-size: 16px;">
<?php
$firstLetter = !empty($rl['company_name']) ? substr($rl['company_name'], 0, 1) : '?';
echo strtoupper(esc($firstLetter));
?>
</div>
</div>
<div style="flex-grow: 1; min-width: 0;">
<div style="font-weight: 600; font-size: 14px; color: #333; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
<?= esc($rl['company_name']) ?>
</div>
<div style="font-size: 11px; color: #999; margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
<?= esc($rl['email']) ?>
</div>
</div>
<div style="flex-shrink: 0;">
<span class="status-pill"
style="background: #e3f2fd; color: #1976d2; padding: 4px 10px; border-radius: 12px; font-size: 10px; font-weight: 600; white-space: nowrap;">
<?= esc($rl['status']) ?>
</span>
</div>
</div> </div>
<?php endforeach; ?> <?php endforeach; ?>
</div> </div>

View File

@ -185,7 +185,8 @@
</div> </div>
<div class="col-md-12" style="width: 94%;"> <div class="col-md-12" style="width: 94%;">
<label class="form-label">Phone</label> <label class="form-label">Phone</label>
<input type="text" class="form-control" name="phone" style="width: 100%;" placeholder="Enter the Phone Number" oninput="this.value = this.value.replace(/[^\d\s+]/g, '')"> <!-- <input type="text" class="form-control" name="phone" style="width: 100%;" placeholder="Enter the Phone Number" oninput="this.value = this.value.replace(/[^\d\s+]/g, '')"> -->
<input type="text" class="form-control" name="phone" style="width: 100%;" placeholder="Enter the Phone Number" maxlength="10" oninput="this.value = this.value.replace(/[^0-9]/g, '').substring(0, 10);">
</div> </div>
</div> </div>
<div class="form-row mb-1"> <div class="form-row mb-1">
@ -283,7 +284,7 @@
<button type="button" class="activity-type-btn d_activity_type" data-type="Email" onclick="selectType('Email', this)">✉️ Email</button> <button type="button" class="activity-type-btn d_activity_type" data-type="Email" onclick="selectType('Email', this)">✉️ Email</button>
<button type="button" class="activity-type-btn d_activity_type" data-type="Meeting" onclick="selectType('Meeting', this)">📅 Meeting</button> <button type="button" class="activity-type-btn d_activity_type" data-type="Meeting" onclick="selectType('Meeting', this)">📅 Meeting</button>
<button type="button" class="activity-type-btn d_activity_type" data-type="Visit" onclick="selectType('Visit', this)">🚗 Visit</button> <button type="button" class="activity-type-btn d_activity_type" data-type="Visit" onclick="selectType('Visit', this)">🚗 Visit</button>
<button type="button" class="activity-type-btn d_activity_type" data-type="Demo" onclick="selectType('Demo', this)">🎬 Demo</button> <button type="button" class="activity-type-btn d_activity_type" data-type="Demo" onclick="selectType('Demo', this)">🖥️ Demo</button>
<button type="button" class="activity-type-btn d_activity_type" data-type="Share" onclick="selectType('Share', this)">📄 Share Docs</button> <button type="button" class="activity-type-btn d_activity_type" data-type="Share" onclick="selectType('Share', this)">📄 Share Docs</button>
<button type="button" class="activity-type-btn d_activity_type" data-type="Todo" onclick="selectType('Todo', this)"> To Do</button> <button type="button" class="activity-type-btn d_activity_type" data-type="Todo" onclick="selectType('Todo', this)"> To Do</button>
@ -352,7 +353,7 @@
<button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Email', this)">✉️ Email</button> <button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Email', this)">✉️ Email</button>
<button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Meeting', this)">📅 Meeting</button> <button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Meeting', this)">📅 Meeting</button>
<button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Visit', this)">🚗 Visit</button> <button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Visit', this)">🚗 Visit</button>
<button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Demo', this)">🎬 Demo</button> <button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Demo', this)">🖥️ Demo</button>
<button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Share', this)">📄 Share Docs</button> <button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Share', this)">📄 Share Docs</button>
<button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Todo', this)"> To Do</button> <button type="button" class="activity-type-btn f_activity_type" onclick="selectFollowUpActivityType('Todo', this)"> To Do</button>
@ -502,7 +503,8 @@
</div> </div>
<div class="col-md-12" style="width: 94%;"> <div class="col-md-12" style="width: 94%;">
<label class="form-label">Phone</label> <label class="form-label">Phone</label>
<input type="text" class="form-control" name="phone" style="width: 100%;" placeholder="Enter the Phone Number" oninput="this.value = this.value.replace(/[^\d\s+]/g, '')"> <!-- <input type="text" class="form-control" name="phone" style="width: 100%;" placeholder="Enter the Phone Number" oninput="this.value = this.value.replace(/[^\d\s+]/g, '')"> -->
<input type="text" class="form-control" name="phone" style="width: 100%;" placeholder="Enter the Phone Number" maxlength="10" oninput="this.value = this.value.replace(/[^0-9]/g, '').substring(0, 10);">
</div> </div>
</div> </div>
<div class="col-12 mb-1"> <div class="col-12 mb-1">
@ -934,7 +936,7 @@ function renderCard(opps) {
} }
function renderTimeline(acts) { function renderTimeline(acts) {
const cont = document.getElementById('timelineContainer'); const cont = document.getElementById('timelineContainer');
const activityIcons = { Call: "📞", Email: "✉️", Meeting: "📅", Visit: "🚗",Demo: "🎬", Share: "📄", Todo: "" }; const activityIcons = { Call: "📞", Email: "✉️", Meeting: "📅", Visit: "🚗",Demo: "🖥️", Share: "📄", Todo: "" };
if (acts.length === 0) { if (acts.length === 0) {
cont.classList.add('no-line'); cont.classList.add('no-line');
@ -1044,7 +1046,8 @@ document.getElementById('addLeadForm').onsubmit = async (e) => {
let companyRegex = /^[A-Za-z\s]+$/; let companyRegex = /^[A-Za-z\s]+$/;
let emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; let emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
let phoneRegex = /^\+?[0-9\s]{10,20}$/; // Phone regex (+, numbers, spaces allowed, 10-20 length) // let phoneRegex = /^\+?[0-9\s]{0,10}$/; // Phone regex (+, numbers, spaces allowed, 10-20 length)
let phoneRegex = /^\d{10}$/;
// 1. HELPER FUNCTION: Shows Toastr and focuses the specific field // 1. HELPER FUNCTION: Shows Toastr and focuses the specific field
function showError(message, fieldName) { function showError(message, fieldName) {
@ -1081,7 +1084,8 @@ document.getElementById('addLeadForm').onsubmit = async (e) => {
} }
if (phone && !phoneRegex.test(phone)) { if (phone && !phoneRegex.test(phone)) {
return showError("Phone number can contain only +, numbers and spaces (1020 digits).", 'phone'); // return showError("Phone number can contain only +, numbers and spaces (1020 digits).", 'phone');
return showError("Phone number can contain only numbers (10 digits)", 'phone');
} }
if (!data.status) { if (!data.status) {
@ -1170,7 +1174,8 @@ document.getElementById('editLeadForm').onsubmit = async (e) => {
let companyRegex = /^[A-Za-z\s]+$/; let companyRegex = /^[A-Za-z\s]+$/;
let emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; let emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
let phoneRegex = /^\+?[0-9\s]{10,20}$/; // let phoneRegex = /^\+?[0-9\s]{10,20}$/;
let phoneRegex = /^\d{10}$/;
let gstRegex = /^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z][0-9A-Z]Z[0-9A-Z]$/; let gstRegex = /^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z][0-9A-Z]Z[0-9A-Z]$/;
// 1. HELPER FUNCTION: Shows Toastr and focuses the specific field // 1. HELPER FUNCTION: Shows Toastr and focuses the specific field
@ -1208,7 +1213,8 @@ document.getElementById('editLeadForm').onsubmit = async (e) => {
} }
if (phone && !phoneRegex.test(phone)) { if (phone && !phoneRegex.test(phone)) {
return showError("Phone number can contain only +, numbers and spaces (1020 digits).", 'phone'); // return showError("Phone number can contain only +, numbers and spaces (1020 digits).", 'phone');
return showError("Phone number can contain only numbers (10 digits)", 'phone');
} }
if (gst && !gstRegex.test(gst)) { if (gst && !gstRegex.test(gst)) {