diff --git a/app/Controllers/LeadsController.php b/app/Controllers/LeadsController.php index a712688f..2c506aed 100644 --- a/app/Controllers/LeadsController.php +++ b/app/Controllers/LeadsController.php @@ -302,8 +302,8 @@ class LeadsController extends BaseController public function viewLeadsList() { - $data['tab_name'] = 'Leads'; - $data['page_name'] = 'Leads'; + $data['tab_name'] = 'Opportunities'; + $data['page_name'] = 'Opportunities'; // Set basic data $data['issuer'] = $this->issuer; @@ -372,7 +372,7 @@ class LeadsController extends BaseController 'lead_type' => [ 'rules' => 'integer', - 'errors' => ['required' => 'Lead Type is required'] + 'errors' => ['required' => 'Opportunity Type is required'] ], 'issuer' => [ 'rules' => 'required', @@ -934,10 +934,10 @@ class LeadsController extends BaseController } 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) @@ -946,9 +946,9 @@ class LeadsController extends BaseController $this->insertMultiFilesData($data[0]['multi_file_data'], $id, $data[0]['lead_form_type']); $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) @@ -1305,7 +1305,7 @@ class LeadsController extends BaseController if (!$lead_data) { // 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 @@ -1494,7 +1494,7 @@ class LeadsController extends BaseController $lead_id = $data['lead_id'] ?? null; 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(); @@ -2796,7 +2796,7 @@ class LeadsController extends BaseController $file_name_with_path = WRITEPATH . "/uploads/lead_files/" . $lead_data['file_name']; if (!$lead_data) { - return ['status' => 'failed', 'message' => 'Lead data not found']; + return ['status' => 'failed', 'message' => 'Opportunity data not found']; } try{ @@ -5583,7 +5583,7 @@ class LeadsController extends BaseController // dd($file_name_with_path); if (!$lead_data) { - return ['status' => 'failed', 'message' => 'Lead data not found']; + return ['status' => 'failed', 'message' => 'Opportunity data not found']; } if ($lead_data['file_name']) { @@ -6579,7 +6579,7 @@ class LeadsController extends BaseController return $this->respond([ 'status' => false, 'code' => 400, - 'message' => 'Lead ID is required' + 'message' => 'Opportunity ID is required' ], 400); } diff --git a/app/Controllers/RestAuthenticationController.php b/app/Controllers/RestAuthenticationController.php index e4c474a1..ab536240 100755 --- a/app/Controllers/RestAuthenticationController.php +++ b/app/Controllers/RestAuthenticationController.php @@ -648,7 +648,8 @@ class RestAuthenticationController extends AdminController 'function' => $th->getTrace()[0]['function'] ?? null, 'class' => $th->getTrace()[0]['class'] ?? null, ]; - return $this->respond(['status' => 'failed','code' => 500,'data' => $th, 'error_data' => $errorData],500); + log_message('error', 'Error Data: ' . json_encode($errorData)); + return $this->respond(['status' => 'failed','code' => 500,'data' => $th],500); } } @@ -2345,7 +2346,7 @@ class RestAuthenticationController extends AdminController } $decoded = $result['decoded']; - $userId = $decoded['id'] ?? null; + $userId = $decoded['post_hr_id'] ?? null; if (!$userId) { return $this->respond([ diff --git a/app/Controllers/SalesController.php b/app/Controllers/SalesController.php index 3de595f8..a830542e 100644 --- a/app/Controllers/SalesController.php +++ b/app/Controllers/SalesController.php @@ -88,7 +88,7 @@ class SalesController extends BaseController } // 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') ->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 ); - if (in_array($role,[5])) { + if (in_array($role,[1,5])) { $sales_manager_ids = array_column( $db->table('user_profiles up') @@ -822,36 +822,46 @@ class SalesController extends BaseController public function branchLevelDashboard($branchId,$sales_manager_ids) { - $data['tab_name'] = 'Dashboard'; - $data['page_name'] = 'Dashboard'; // Hardcoded branch ID as requested // $branchId = 1; try { - // 1. Lead Statistics - $stats = $this->leadModel->getLeadStats(); // Using existing model method - - // 2. Activity Statistics - $activityStats = [ - '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)) { + $sales_manager_ids = array_values(array_map('intval', $sales_manager_ids)); + + // Final safe check + if (empty($sales_manager_ids)) { // No valid IDs — skip queries or return empty - $teamPerformance = []; - $recentActivities = []; - $leadsOverview = []; - } else { + $total_leads = 0; + $total_activity = 0; + $total_completed_activity = 0; + $total_pending_activity = 0; + $pending_activities = []; + $recent_activities = []; + $teamPerformance = []; + + $leadsOverview = []; + } else { - if (empty($sales_manager_ids) || !is_array($sales_manager_ids)) { - $sales_manager_ids = array_filter((array) $sales_manager_ids); // removes null, "", 0 - } + 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') ->select('u.first_name, u.last_name, u.profile as role, (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) ->get()->getResultArray(); - // 4. Recent Activities (Joining for Lead Names) - $recentActivities = $this->activityModel->select('sales_activities.*, sales_actual_leads.company_name') + // 6. Recent Activities (Joining for Lead Names) + $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') ->orderBy('sales_activities.scheduled_date', 'DESC') ->limit(6) ->findAll(); - $sales_manager_ids = array_values(array_map('intval', $sales_manager_ids)); - $recentActivities = $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') - ->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') + // 7. Pending Activities (List) + $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,sa.notes') ->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') - ->limit(6) ->whereIn('sa.assigned_to', $sales_manager_ids) + ->where('sa.status', 'pending') ->get()->getResultArray(); - // 5. All Leads Overview - $leadsOverview = $db->table('sales_actual_leads sal') + // 8. All Leads Overview + $leadsOverview = $db->table('sales_actual_leads sal') ->select('sal.lead_id,sal.company_name,sal.status,up.first_name AS assigned_to, COUNT(DISTINCT sa.activity_id) AS activities, 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('leads l', 'l.actual_lead_id = sal.lead_id', 'left') ->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') ->whereIn('sal.assigned_to', $sales_manager_ids) ->get() ->getResultArray(); - } - // 6. activityBreakdown - $total = $db->table('sales_activities')->countAll(); - + // 9. Activity BrakDown $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') ->orderBy('total', 'DESC') ->get() ->getResultArray(); - - $teamPerformance = array_filter($teamPerformance, function($row) { - return ($row['total_acts'] + $row['done_acts']) > 0; - }); - - + } $data = [ - 'total_leads' => $stats['total'], - 'total_activities' => $activityStats['total'], - 'completed_acts' => $activityStats['completed'], - 'pipeline_value' => '15.0L', // Hardcoded placeholder from PDF [cite: 14] - 'team' => $teamPerformance, - 'recent_acts' => $recentActivities, - 'leads_overview' => $leadsOverview, + 'total_leads' => $total_leads, + 'total_acts' => $total_activity, + 'total_completed_acts' => $total_completed_activity, + 'total_pending_acts'=> $total_pending_activity, + 'pipeline_value' => '15.0L', // Hardcoded placeholder from PDF [cite: 14] + 'team' => $teamPerformance, + 'recent_acts' => $recent_activities, + 'pending_acts' => $pending_activities, + 'leads_overview' => $leadsOverview, 'activity_breakdown'=> $activityBreakdown, - 'tab_name' => "Sales Dashboard", - 'page_name' => "Sales Dashboard" + 'tab_name' => "Sales Dashboard", + 'page_name' => "Sales Dashboard" ]; // dd($data); diff --git a/app/Filters/AuthJWT.php b/app/Filters/AuthJWT.php index ec34d902..45f4517a 100755 --- a/app/Filters/AuthJWT.php +++ b/app/Filters/AuthJWT.php @@ -115,9 +115,19 @@ class AuthJWT implements FilterInterface } // Refresh sliding expiration - $model->update($id, [ - 'token_time_out' => time() + getenv('TOKENTIMEOUT') - ]); + $newExpiry = time() + getenv('TOKENTIMEOUT'); + + if (!isset($decoded['emp_code'])) { + // HR user: refresh token_time_out across all branches (same mobile/email) + // so switching branches doesn't cause an unexpected expiry + $field = !empty($user['mobile']) ? 'mobile' : 'email'; + $model->where($field, $user[$field]) + ->where('contact_type', 'client') + ->where('is_active', 1) + ->update(null, ['token_time_out' => $newExpiry]); + } else { + $model->update($id, ['token_time_out' => $newExpiry]); + } return true; } diff --git a/app/Helpers/JWTToken.php b/app/Helpers/JWTToken.php index c964bac7..f671197a 100755 --- a/app/Helpers/JWTToken.php +++ b/app/Helpers/JWTToken.php @@ -136,7 +136,7 @@ class JWTToken $token = $jwtParts[0]; try { - $decoded = JWT::decode($token, new Key("secret", 'HS512')); + $decoded = JWT::decode($token, new Key(env('JWT_SECRET'), 'HS512')); return json_encode(['status' => true, 'message' => 'Token is valid', 'data' =>$decoded->data->id ]); } catch (ExpiredException $e) { return json_encode(['status' => false, 'message' => 'Token has expired']); @@ -158,7 +158,7 @@ class JWTToken $jwtParts = explode(' ', $jwt); $token = $jwtParts[1]; - $decoded = JWT::decode($token, new Key("secret", 'HS512')); + $decoded = JWT::decode($token, new Key(env('JWT_SECRET'), 'HS512')); return $decoded->id; } @@ -169,7 +169,7 @@ class JWTToken $jwtParts = explode(' ', $jwt); $token = $jwtParts[1]; - $decoded = JWT::decode($token, new Key("secret", 'HS512')); + $decoded = JWT::decode($token, new Key(env('JWT_SECRET'), 'HS512')); return $decoded->role; } @@ -181,7 +181,7 @@ class JWTToken $jwtParts = explode(' ', $jwt); $token = $jwtParts[1]; - $decoded = JWT::decode($token, new Key("secret", 'HS512')); + $decoded = JWT::decode($token, new Key(env('JWT_SECRET'), 'HS512')); return $decoded; } diff --git a/app/Views/cd_master_add_modal.php b/app/Views/cd_master_add_modal.php index 2d9c0143..9ff01a91 100644 --- a/app/Views/cd_master_add_modal.php +++ b/app/Views/cd_master_add_modal.php @@ -68,6 +68,7 @@
+
@@ -126,12 +127,15 @@ console.log(res) if(res.status == true){ - toastr.warning(res.message, 'warning'); + + $('#cd_ac_no_for_cd_master_errorr').text(res.message); + // toastr.warning(res.message, 'warning'); // $('#cd_ac_no').val(''); $('#cd_master_btn_Submit').prop('disabled',true); return; } $('#cd_master_btn_Submit').prop('disabled',false); + $('#cd_ac_no_for_cd_master_errorr').text(''); }, error: function (xhr, status, error) { console.error(xhr.responseText); diff --git a/app/Views/client_onboarding.php b/app/Views/client_onboarding.php index c63e00a6..928836a0 100755 --- a/app/Views/client_onboarding.php +++ b/app/Views/client_onboarding.php @@ -273,9 +273,7 @@
-

Client Onboarding

+

Client Onboarding

"> diff --git a/app/Views/layout/header.php b/app/Views/layout/header.php index 67198829..f5109843 100755 --- a/app/Views/layout/header.php +++ b/app/Views/layout/header.php @@ -2073,7 +2073,7 @@ /assets/images/leads_sb.png" alt="Logo" height="20"> - Leads + Opportunities diff --git a/app/Views/lead_filter.php b/app/Views/lead_filter.php index 07cf83bb..620d4a08 100644 --- a/app/Views/lead_filter.php +++ b/app/Views/lead_filter.php @@ -39,7 +39,7 @@
- + - + $value) { @@ -739,7 +739,7 @@ hide_list_show_add(); - var page_title = 'Edit Lead'; + var page_title = 'Edit Opportunity'; $('#page_title').text(page_title); $('#leads_primarykey').val(res.data.id); diff --git a/app/Views/leads_form_handler.php b/app/Views/leads_form_handler.php index 01960410..c9efd20a 100644 --- a/app/Views/leads_form_handler.php +++ b/app/Views/leads_form_handler.php @@ -604,7 +604,8 @@ if (isset($selected_lead_type)) { let isFirstField = container.childElementCount === 0; // Check if it's the first field let placeholder = isFirstField ? 'First file must be Demography.' : ''; - let accept = isFirstField ? '.xls,.xlsx' : ''; + let accept = isFirstField ? '.xls,.xlsx' : '.xls,.xlsx,.pdf,.jpg,.jpeg,.png'; + let accept_text = isFirstField ? 'First file: Excel only (.xls, .xlsx)' : 'Files: PDF, Excel (.xlsx, .xls), Images (.png, .jpg, .jpeg)'; if(selected_lead_form_type != 1){ @@ -640,12 +641,12 @@ if (isset($selected_lead_type)) {

- PDF | Excel (XLSX, XLS) | Images (PNG, JPG)
+ ${accept_text}
@@ -954,7 +955,7 @@ if (isset($selected_lead_type)) { hide_list_show_add(); - $('#page_title').text('Edit Lead'); + $('#page_title').text('Edit Opportunity'); $('#leads_primarykey').val(data.id || ''); $('#actual_lead_id').val(data.actual_lead_id || 0); $('#policy_start_date').val(data.policy_end_date || ''); @@ -1129,7 +1130,7 @@ if (isset($selected_lead_type)) { } } - $('#page_title').text('Edit Lead'); + $('#page_title').text('Edit Opportunity'); $('#leads_primarykey').val(data.id || ''); $('#actual_lead_id').val(data.actual_lead_id || 0); $('#policy_start_date').val(data.policy_end_date || ''); diff --git a/app/Views/leads_list.php b/app/Views/leads_list.php index 98b9f232..7ad9f74a 100644 --- a/app/Views/leads_list.php +++ b/app/Views/leads_list.php @@ -151,7 +151,7 @@ table.dataTable tbody td {
-

Leads List

+

Opportunities List

@@ -165,7 +165,7 @@ table.dataTable tbody td {
S.No  
-
Lead Type  
+
Opportunity Type  
Issuer  
Client Type  
Client / Branch  
@@ -257,7 +257,7 @@ table.dataTable tbody td { @@ -67,6 +70,7 @@ $increment = 1; + First file: Excel only (.xls, .xlsx)
diff --git a/app/Views/sales/activity_view.php b/app/Views/sales/activity_view.php index 46833e9f..58d81c9f 100644 --- a/app/Views/sales/activity_view.php +++ b/app/Views/sales/activity_view.php @@ -255,7 +255,7 @@ - +
@@ -274,8 +274,8 @@
- - @@ -325,7 +325,7 @@ - + @@ -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 = ; const API = ''; @@ -480,6 +480,10 @@ function closeModal(id) { } 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 openModal('activityModal'); } @@ -786,7 +790,8 @@ function openActivityModal() { document.getElementById('act_owner').dispatchEvent(new Event('change')); document.getElementById('act_lead_id').value = lead_id; 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) { @@ -1123,150 +1128,7 @@ document.getElementById('do_follow').addEventListener('change', function () { 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 = ` -
-
-
${result.data.name}
-
${result.data.mobile}
-
-
- -
-
- `; - - // - // 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}
`; - 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) { if (!input) return null; diff --git a/app/Views/sales/branch_level_dashboard_view.php b/app/Views/sales/branch_level_dashboard_view.php index 66d98d13..7f3789f4 100644 --- a/app/Views/sales/branch_level_dashboard_view.php +++ b/app/Views/sales/branch_level_dashboard_view.php @@ -89,17 +89,17 @@
-
+
Total Activities
-
+
Pending Activities
-
+
Completed Activities
@@ -113,8 +113,8 @@
-

Recent Activities - All Team

- 6 activities +

Pending Activities - All Team

+
@@ -126,21 +126,21 @@ - - + + '📞', 'Email' => '✉️', 'Meeting' => '📅', 'Visit' => '🚗', - 'Demo' => '🎬', + 'Demo' => '🖥️', 'Share' => '📄', 'Todo' => '✓' ]; $icon = $activityIcons[$a['activity_type']] ?? '📌'; $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'])); ?> @@ -151,8 +151,11 @@
+ - + @@ -213,7 +216,7 @@ 'Email' => ['color' => '#48bb78', 'icon' => '✉️'], 'Meeting' => ['color' => '#4299e1', 'icon' => '📅'], 'Visit' => ['color' => '#ecc94b', 'icon' => '🚗'], - 'Demo' => ['color' => '#9f7aea', 'icon' => '🎬'], + 'Demo' => ['color' => '#9f7aea', 'icon' => '🖥️'], 'Share' => ['color' => '#ed8936', 'icon' => '📄'], 'Todo' => ['color' => '#718096', 'icon' => '✓'], ]; @@ -228,7 +231,7 @@ ?>
- + % @@ -244,7 +247,13 @@

All Leads Overview

- Click a lead to see details + + + Click a lead to see details +
diff --git a/app/Views/sales/sales_manager_level_dashboard.php b/app/Views/sales/sales_manager_level_dashboard.php index 5fc0483e..b9cbbf41 100644 --- a/app/Views/sales/sales_manager_level_dashboard.php +++ b/app/Views/sales/sales_manager_level_dashboard.php @@ -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: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; +} + + +
@@ -99,13 +116,15 @@
+ +

My Upcoming Activities

pending
- + + '📞', 'Email' => '✉️', 'Meeting' => '📅', 'Visit' => '🚗', 'Demo' => '🖥️', 'Share' => '📄', 'Todo' => '✓' ]; + $icon = $activityIcons[$u['activity_type']] ?? '📌'; + $formattedscheduledDate = date('M d, Y, h:i A', strtotime($u['scheduled_date'])); + ?> +
+
+ +
+ +
+
+ +
+
+ + - +
+
+ +
+ +
+
+

My Recent Leads

-
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ + + +
+
diff --git a/app/Views/sales/tracker_view.php b/app/Views/sales/tracker_view.php index 3ceb43a6..392b307b 100644 --- a/app/Views/sales/tracker_view.php +++ b/app/Views/sales/tracker_view.php @@ -185,7 +185,8 @@
- + +
@@ -283,7 +284,7 @@ - + @@ -352,7 +353,7 @@ - + @@ -502,7 +503,8 @@
- + +
@@ -934,7 +936,7 @@ function renderCard(opps) { } function renderTimeline(acts) { 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) { cont.classList.add('no-line'); @@ -1044,7 +1046,8 @@ document.getElementById('addLeadForm').onsubmit = async (e) => { let companyRegex = /^[A-Za-z\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 function showError(message, fieldName) { @@ -1081,7 +1084,8 @@ document.getElementById('addLeadForm').onsubmit = async (e) => { } if (phone && !phoneRegex.test(phone)) { - return showError("Phone number can contain only +, numbers and spaces (10–20 digits).", 'phone'); + // return showError("Phone number can contain only +, numbers and spaces (10–20 digits).", 'phone'); + return showError("Phone number can contain only numbers (10 digits)", 'phone'); } if (!data.status) { @@ -1170,7 +1174,8 @@ document.getElementById('editLeadForm').onsubmit = async (e) => { let companyRegex = /^[A-Za-z\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]$/; // 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)) { - return showError("Phone number can contain only +, numbers and spaces (10–20 digits).", 'phone'); + // return showError("Phone number can contain only +, numbers and spaces (10–20 digits).", 'phone'); + return showError("Phone number can contain only numbers (10 digits)", 'phone'); } if (gst && !gstRegex.test(gst)) {