completed clients and MNO module
This commit is contained in:
@@ -134,6 +134,8 @@ class ClientsController extends Controller
|
||||
// dump($change_account_mgr_permission);
|
||||
$change_account_mgr_permission = $this->hasAnyAccess([$change_account_mgr_permission]) ? 'YES' : 'NO';
|
||||
// dd($change_account_mgr_permission);
|
||||
|
||||
// dd($showclient);
|
||||
return view('clients.show', [
|
||||
'page_title' => 'Client Profile',
|
||||
'showclient' => $showclient,
|
||||
@@ -390,7 +392,39 @@ class ClientsController extends Controller
|
||||
return redirect('clients');
|
||||
}
|
||||
|
||||
public function getClientJson($id)
|
||||
{
|
||||
$client = \App\Models\Client::findOrFail($id);
|
||||
return response()->json($client);
|
||||
}
|
||||
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$client = \App\Models\Client::findOrFail($id);
|
||||
|
||||
$client->update([
|
||||
'name' => $request->name,
|
||||
'email' => $request->email,
|
||||
'phone' => $request->phone,
|
||||
'contact_person' => $request->contact_person,
|
||||
'company_type' => $request->company_type,
|
||||
'contract_type' => $request->contract_type,
|
||||
'industry' => $request->industry,
|
||||
'status' => $request->status,
|
||||
'currency' => $request->currency,
|
||||
'country' => $request->country,
|
||||
// Arrays handled by model casts
|
||||
'services' => $request->services,
|
||||
'message_types' => $request->message_types,
|
||||
'connections' => $request->connections,
|
||||
'support_phones' => $request->support_phones,
|
||||
'support_emails' => $request->support_emails,
|
||||
'rate_emails' => $request->rate_emails,
|
||||
'support_skype' => $request->support_skype,
|
||||
]);
|
||||
|
||||
return response()->json(['message' => 'Client updated successfully!']);
|
||||
}
|
||||
|
||||
|
||||
public function storeFiles(AddFilesRequest $request){
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class NetworkOperatorsControlle extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$data = [
|
||||
'page_title' => 'Dashboard'
|
||||
];
|
||||
return view('network_operators.index', $data);
|
||||
}
|
||||
}
|
||||
115
app/Http/Controllers/NetworkOperatorsController.php
Normal file
115
app/Http/Controllers/NetworkOperatorsController.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\NetworkOperator;
|
||||
|
||||
class NetworkOperatorsController extends Controller
|
||||
{
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = NetworkOperator::query();
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->input('search');
|
||||
$query->where('name', 'like', "%{$search}%")
|
||||
->orWhere('contact_person_email', 'like', "%{$search}%")
|
||||
->orWhere('support_phones', 'like', "%{$search}%");
|
||||
}
|
||||
|
||||
if ($request->filled('country')) {
|
||||
$query->where('country', $request->input('country'));
|
||||
}
|
||||
|
||||
if ($request->filled('connection_status')) {
|
||||
$query->where('connection_status', 'like', "%{$request->input('connection_status')}%");
|
||||
}
|
||||
|
||||
// Paginate instead of getting all records at once (e.g., 10 per page)
|
||||
$operators = $query->latest('id')->paginate(10)->withQueryString();
|
||||
|
||||
// dd($operators);
|
||||
|
||||
$totalActive = NetworkOperator::where('connection_status', 'Active')->count();
|
||||
$totalSipLinks = NetworkOperator::where('connection_type', 'like', '%VPN%')->count();
|
||||
$totalOperators = NetworkOperator::count();
|
||||
|
||||
return view('network_operators.index', compact('operators', 'totalActive', 'totalSipLinks', 'totalOperators'));
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'name' => 'required|string|max:200',
|
||||
'country' => 'required|string',
|
||||
]);
|
||||
|
||||
NetworkOperator::create([
|
||||
'name' => $request->name,
|
||||
'country' => $request->country,
|
||||
'connection_status' => $request->connection_status ?? 'Online',
|
||||
'contact_person' => $request->contact_person,
|
||||
'contact_person_phone' => $request->contact_person_phone,
|
||||
'contact_person_email' => $request->contact_person_email,
|
||||
'technical_support_person' => $request->technical_support_person,
|
||||
'support_skype' => $request->support_skype,
|
||||
'mno_account_manager' => $request->mno_account_manager,
|
||||
'services' => $request->services,
|
||||
'support_emails' => $request->support_emails,
|
||||
'finance_emails' => $request->finance_emails,
|
||||
'buying_rate' => $request->buying_rate ?? 0,
|
||||
'rate_type' => $request->rate_type,
|
||||
'payment_terms' => $request->payment_terms,
|
||||
'connection_type' => $request->connection_type,
|
||||
]);
|
||||
|
||||
return response()->json(['message' => 'MNO Partner created successfully!']);
|
||||
}
|
||||
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$operator = NetworkOperator::findOrFail($id);
|
||||
|
||||
$request->validate([
|
||||
'name' => 'required|string|max:200',
|
||||
'country' => 'required|string',
|
||||
]);
|
||||
|
||||
$operator->update([
|
||||
'name' => $request->name,
|
||||
'country' => $request->country,
|
||||
'connection_status' => $request->connection_status,
|
||||
'contact_person' => $request->contact_person,
|
||||
'contact_person_phone' => $request->contact_person_phone,
|
||||
'contact_person_email' => $request->contact_person_email,
|
||||
'technical_support_person' => $request->technical_support_person,
|
||||
'support_skype' => $request->support_skype,
|
||||
'mno_account_manager' => $request->mno_account_manager,
|
||||
'services' => $request->services,
|
||||
'support_emails' => $request->support_emails,
|
||||
'finance_emails' => $request->finance_emails,
|
||||
'buying_rate' => $request->buying_rate,
|
||||
'rate_type' => $request->rate_type,
|
||||
'payment_terms' => $request->payment_terms,
|
||||
'connection_type' => $request->connection_type,
|
||||
]);
|
||||
|
||||
return response()->json(['message' => 'MNO Partner updated successfully!']);
|
||||
}
|
||||
|
||||
// Fetch single record JSON for editing modal
|
||||
public function getJson($id)
|
||||
{
|
||||
$operator = NetworkOperator::findOrFail($id);
|
||||
return response()->json($operator);
|
||||
}
|
||||
public function show($id)
|
||||
{
|
||||
$operator = NetworkOperator::findOrFail($id);
|
||||
return view('network_operators.show', compact('operator'));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
use Session;
|
||||
use App\Models;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ProjectStatusesController extends Controller
|
||||
{
|
||||
//load up project status
|
||||
public function index(){
|
||||
$user_id = \Auth::user()->id;
|
||||
// dd($user_id);
|
||||
$result = Models\ProjectStatus::with('project')
|
||||
->where('assignee_id', $user_id)
|
||||
->orderBy('project_id', 'DESC')
|
||||
->get();
|
||||
$data = [
|
||||
'page_title' => 'Projects Status List',
|
||||
'project_statuses' => $result
|
||||
];
|
||||
return view('project_status.index', $data);
|
||||
}
|
||||
public function add_status($id){
|
||||
$result = Models\Project::with('statusInfo')->where('id', $id)->firstOrFail();
|
||||
$data = [
|
||||
'page_title' => 'Projects Status Update',
|
||||
'project' => $result
|
||||
];
|
||||
// dd($data);
|
||||
return view('project_status.add_status', $data);
|
||||
}
|
||||
public function create() {
|
||||
|
||||
return view('project_status.create');
|
||||
}
|
||||
|
||||
public function store(Request $request) {
|
||||
// Save a new post
|
||||
$this->validate($request, [
|
||||
'description' => 'required',
|
||||
'status' => 'required',
|
||||
'project_id' => 'required',
|
||||
'assignee_id' => 'required'
|
||||
]);
|
||||
$project_status_arr = $request->except('_token');
|
||||
$result = Models\ProjectStatus::create($project_status_arr);
|
||||
Session::flash('success_message', 'Project status added successfully!');
|
||||
|
||||
return redirect(url('projects'));
|
||||
}
|
||||
|
||||
public function show($id) {
|
||||
// Show a specific post
|
||||
}
|
||||
|
||||
public function edit($id) {
|
||||
// Show form to edit a post
|
||||
}
|
||||
|
||||
public function update(Request $request, $id) {
|
||||
// Update a specific post
|
||||
return redirect(url('project-status'));
|
||||
}
|
||||
|
||||
public function destroy($id) {
|
||||
// Delete a specific post
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
use Session;
|
||||
use App\Models;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ProjectsController extends Controller
|
||||
{
|
||||
|
||||
public function index(){
|
||||
$user_id = \Auth::user()->id;
|
||||
// dd($user_id);
|
||||
$result = Models\Project::where('user_id', $user_id)->get();
|
||||
$data = [
|
||||
'page_title' => 'Projects List',
|
||||
'projects' => $result
|
||||
];
|
||||
return view('projects.index', $data);
|
||||
}
|
||||
public function create() {
|
||||
// Show form to create a new post
|
||||
return view('projects.create');
|
||||
}
|
||||
|
||||
public function store(Request $request) {
|
||||
// Save a new post
|
||||
$this->validate($request, [
|
||||
'name' => 'required',
|
||||
'description'=> 'required',
|
||||
'dependancy' => 'sometimes',
|
||||
'status' => 'required',
|
||||
]);
|
||||
$project_arr = $request->except('_token');
|
||||
$result = Models\Project::create($project_arr);
|
||||
Session::flash('success_message', 'Project created successfully!');
|
||||
return redirect(url('projects'));
|
||||
}
|
||||
|
||||
public function show($id) {
|
||||
// Show a specific post
|
||||
$user_id = \Auth::user()->id;
|
||||
$result = Models\Project::with('statusInfo')->where('id', $id)->firstOrFail();
|
||||
$data = [
|
||||
'page_title' => 'Projects Details',
|
||||
'project' => $result
|
||||
];
|
||||
// dump($data);
|
||||
return view('projects.show', $data);
|
||||
}
|
||||
|
||||
public function edit($id) {
|
||||
// Show form to edit a post
|
||||
$user_id = \Auth::user()->id;
|
||||
$result = Models\Project::with('statusInfo')->where('id', $id)->firstOrFail();
|
||||
$data = [
|
||||
'page_title' => 'Projects Update',
|
||||
'project' => $result
|
||||
];
|
||||
return view('projects.edit', $data);
|
||||
}
|
||||
|
||||
public function update(Request $request, $id) {
|
||||
// Update a specific post
|
||||
$this->validate($request, [
|
||||
'name' => 'required',
|
||||
'description'=> 'required',
|
||||
'dependancy' => 'sometimes',
|
||||
'status' => 'required',
|
||||
]);
|
||||
|
||||
$project = Models\Project::findOrFail($id);
|
||||
|
||||
$project->name = $request->name;
|
||||
$project->description = $request->description;
|
||||
$project->dependancy = $request->dependancy;
|
||||
$project->status = $request->status;
|
||||
$result = $project->save();
|
||||
Session::flash('success_message', 'Project details updated successfully!');
|
||||
return redirect(url('projects'));
|
||||
}
|
||||
|
||||
public function destroy($id) {
|
||||
// Delete a specific post
|
||||
}
|
||||
}
|
||||
@@ -51,4 +51,14 @@ class Client extends Model
|
||||
}
|
||||
return $service_name_arr;
|
||||
}
|
||||
|
||||
protected $casts = [
|
||||
'connections' => 'array',
|
||||
'message_types' => 'array',
|
||||
'services' => 'array',
|
||||
'support_emails' => 'array',
|
||||
'rate_emails' => 'array',
|
||||
'support_skype' => 'array',
|
||||
'support_phones' => 'array',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -5,11 +5,17 @@ namespace App\Models;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
|
||||
class NetworkOps extends Model
|
||||
class NetworkOperator extends Model
|
||||
{
|
||||
protected $guarded = array('id');
|
||||
public $table = "network_operators";
|
||||
|
||||
|
||||
protected $casts = [
|
||||
'services' => 'array',
|
||||
'support_emails' => 'array',
|
||||
'finance_emails' => 'array',
|
||||
'bind_specifics' => 'array',
|
||||
];
|
||||
public function account_manager_info(){
|
||||
return $this->hasOne('App\Models\StaffMember', 'id', 'account_manager_id');
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
@@ -23,5 +24,6 @@ class AppServiceProvider extends ServiceProvider
|
||||
if (config('app.env') === 'production') {
|
||||
URL::forceScheme('https');
|
||||
}
|
||||
Paginator::useBootstrapFive();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,5 +249,134 @@ document.addEventListener("DOMContentLoaded", function() {
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
|
||||
// 1. Populate Edit Client Modal when opened
|
||||
$(document).on('click', '[data-bs-target="#editClientModal"]', function() {
|
||||
let clientId = $(this).data('client-id');
|
||||
let $form = $('#editClientForm');
|
||||
|
||||
$form.attr('action', base_url + '/clients/' + clientId);
|
||||
|
||||
// Fetch Services first, then Client data
|
||||
$.ajax({
|
||||
url: base_url + '/api/services',
|
||||
type: 'GET',
|
||||
success: function(services) {
|
||||
let $servicesSelect = $('#edit_services');
|
||||
$servicesSelect.empty();
|
||||
services.forEach(function(s) {
|
||||
$servicesSelect.append(new Option(s.name, s.id));
|
||||
});
|
||||
|
||||
// Now fetch client details
|
||||
$.ajax({
|
||||
url: base_url + '/clients/' + clientId + '/json',
|
||||
type: 'GET',
|
||||
success: function(client) {
|
||||
$('#edit_name').val(client.name);
|
||||
$('#edit_email').val(client.email);
|
||||
$('#edit_phone').val(client.phone);
|
||||
$('#edit_contact_person').val(client.contact_person);
|
||||
$('#edit_company_type').val(client.company_type);
|
||||
$('#edit_contract_type').val(client.contract_type);
|
||||
$('#edit_industry').val(client.industry);
|
||||
$('#edit_status').val(client.status);
|
||||
$('#edit_currency').val(client.currency);
|
||||
$('#edit_country').val(client.country);
|
||||
|
||||
// Helper function to set values for Select2 multi-select tags fields
|
||||
function setSelect2Values(selector, values) {
|
||||
let $el = $(selector);
|
||||
$el.val(null).trigger('change');
|
||||
if (values && Array.isArray(values)) {
|
||||
values.forEach(function(val) {
|
||||
if ($el.find("option[value='" + val + "']").length === 0) {
|
||||
$el.append(new Option(val, val, true, true));
|
||||
}
|
||||
});
|
||||
$el.val(values).trigger('change');
|
||||
}
|
||||
}
|
||||
|
||||
setSelect2Values('#edit_services', client.services);
|
||||
setSelect2Values('#edit_message_types', client.message_types);
|
||||
setSelect2Values('#edit_connections', client.connections);
|
||||
setSelect2Values('#edit_support_phones', client.support_phones);
|
||||
setSelect2Values('#edit_support_emails', client.support_emails);
|
||||
setSelect2Values('#edit_rate_emails', client.rate_emails);
|
||||
setSelect2Values('#edit_support_skype', client.support_skype);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize Select2 with tags option enabled for all multi-select fields inside edit modal
|
||||
$('#editClientModal').on('shown.bs.modal', function () {
|
||||
$('#editClientModal .select2-tags').each(function() {
|
||||
if (!$(this).hasClass("select2-hidden-accessible")) {
|
||||
$(this).select2({
|
||||
theme: 'bootstrap-5',
|
||||
dropdownParent: $('#editClientModal'),
|
||||
tags: true, // Allows typing custom entries for emails, phones, etc.
|
||||
tokenSeparators: [',', ' '],
|
||||
placeholder: 'Select or type and hit enter...'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Clean up Select2 when modal closes
|
||||
$('#editClientModal').on('hidden.bs.modal', function () {
|
||||
$('#editClientModal .select2-tags').val(null).trigger('change');
|
||||
});
|
||||
|
||||
// Submit Edit Client Form via AJAX
|
||||
$(document).on('submit', '#editClientForm', function(e) {
|
||||
e.preventDefault(); // Hard stop on native form post
|
||||
|
||||
let $form = $(this);
|
||||
let $submitBtn = $form.find('button[type="submit"]');
|
||||
let originalBtnText = $submitBtn.text();
|
||||
|
||||
$submitBtn.prop('disabled', true).text('Updating...');
|
||||
|
||||
$.ajax({
|
||||
url: $form.attr('action'),
|
||||
type: 'POST', // Spoofed as PUT via hidden input
|
||||
data: $form.serialize(),
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
|
||||
},
|
||||
success: function(response) {
|
||||
$('#editClientModal').modal('hide');
|
||||
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Updated!',
|
||||
text: response.message || 'Client updated successfully.',
|
||||
confirmButtonColor: '#0d6efd'
|
||||
}).then(() => {
|
||||
location.reload();
|
||||
});
|
||||
},
|
||||
error: function(xhr) {
|
||||
let errors = xhr.responseJSON?.errors;
|
||||
let errorMsg = 'Something went wrong. Please check your inputs.';
|
||||
if (errors) {
|
||||
errorMsg = Object.values(errors).flat().join('\n');
|
||||
}
|
||||
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Validation Error',
|
||||
text: errorMsg,
|
||||
confirmButtonColor: '#dc3545'
|
||||
});
|
||||
|
||||
$submitBtn.prop('disabled', false).text(originalBtnText);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
183
public/assets/js/mno_index.js
Normal file
183
public/assets/js/mno_index.js
Normal file
@@ -0,0 +1,183 @@
|
||||
$(document).ready(function() {
|
||||
const mnoModal = new bootstrap.Modal(document.getElementById('mnoModal'));
|
||||
const $form = $('#mnoForm');
|
||||
|
||||
|
||||
function loadServicesAndOpen(callback) {
|
||||
$.ajax({
|
||||
url: base_url + '/api/services',
|
||||
type: 'GET',
|
||||
success: function(services) {
|
||||
let $servicesSelect = $('#mnoServices');
|
||||
$servicesSelect.empty();
|
||||
services.forEach(function(s) {
|
||||
$servicesSelect.append(new Option(s.name, s.id));
|
||||
});
|
||||
if (typeof callback === 'function') callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setSelect2Values(selector, values) {
|
||||
let $el = $(selector);
|
||||
$el.val(null).trigger('change');
|
||||
if (values && Array.isArray(values)) {
|
||||
values.forEach(function(val) {
|
||||
if ($el.find("option[value='" + val + "']").length === 0) {
|
||||
// If it's a free-form tag not in the base options, append it
|
||||
$el.append(new Option(val, val, true, true));
|
||||
}
|
||||
});
|
||||
$el.val(values).trigger('change');
|
||||
}
|
||||
}
|
||||
|
||||
// --- OPEN MODAL FOR CREATE ---
|
||||
$('#btnOpenMnoModal').on('click', function(e) {
|
||||
e.preventDefault(); // Prevent any default anchor/button jump
|
||||
|
||||
$form[0].reset();
|
||||
$('#mnoId').val('');
|
||||
$('#methodField').html('');
|
||||
$form.attr('action', "{{ route('mnos.store') }}");
|
||||
$('#mnoModalTitle').text('Add New MNO');
|
||||
$('#btnSubmitMno').html('<i class="bi bi-save me-2"></i>Save Gateway Profile');
|
||||
|
||||
// Clear all multi-selects first
|
||||
$('#mnoServices, #mnoSupportEmails, #mnoFinanceEmails').val(null).trigger('change');
|
||||
|
||||
// Fetch services and then open the modal directly
|
||||
$.ajax({
|
||||
url: base_url + '/api/services',
|
||||
type: 'GET',
|
||||
success: function(services) {
|
||||
let $servicesSelect = $('#mnoServices');
|
||||
$servicesSelect.empty();
|
||||
services.forEach(function(s) {
|
||||
$servicesSelect.append(new Option(s.name, s.id));
|
||||
});
|
||||
$servicesSelect.trigger('change');
|
||||
|
||||
// Open modal safely once data is ready
|
||||
mnoModal.show();
|
||||
},
|
||||
error: function() {
|
||||
// Fallback: open modal even if service fetch fails
|
||||
mnoModal.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// --- OPEN MODAL FOR EDIT ---
|
||||
$(document).on('click', '.btn-edit-mno', function() {
|
||||
const mnoId = $(this).data('id');
|
||||
|
||||
$form[0].reset();
|
||||
$('#methodField').html('<input type="hidden" name="_method" value="PUT">');
|
||||
$form.attr('action', base_url + '/mnos/' + mnoId);
|
||||
$('#mnoModalTitle').text('Modify MNO Profile');
|
||||
$('#btnSubmitMno').html('<i class="bi bi-check-circle me-2"></i>Apply Changes');
|
||||
|
||||
loadServicesAndOpen(function() {
|
||||
$.ajax({
|
||||
url: base_url + '/mnos/' + mnoId + '/json',
|
||||
type: 'GET',
|
||||
success: function(mno) {
|
||||
$('#mnoId').val(mno.id);
|
||||
$('#mnoName').val(mno.name);
|
||||
$('#mnoCountry').val(mno.country);
|
||||
$('#mnoConnectionStatus').val(mno.connection_status);
|
||||
$('#mnoContactPerson').val(mno.contact_person);
|
||||
$('#mnoContactPhone').val(mno.contact_person_phone);
|
||||
$('#mnoContactEmail').val(mno.contact_person_email);
|
||||
$('#mnoTechSupport').val(mno.technical_support_person);
|
||||
$('#mnoSupportSkype').val(mno.support_skype);
|
||||
$('#mnoAccountManager').val(mno.mno_account_manager);
|
||||
$('#mnoBuyingRate').val(mno.buying_rate);
|
||||
$('#mnoRateType').val(mno.rate_type);
|
||||
$('#mnoPaymentTerms').val(mno.payment_terms);
|
||||
$('#mnoConnectionType').val(mno.connection_type);
|
||||
|
||||
// Populate Select2 fields with existing records
|
||||
setSelect2Values('#mnoServices', mno.services);
|
||||
setSelect2Values('#mnoSupportEmails', mno.support_emails);
|
||||
setSelect2Values('#mnoFinanceEmails', mno.finance_emails);
|
||||
|
||||
mnoModal.show();
|
||||
},
|
||||
error: function() {
|
||||
Swal.fire('Error', 'Could not fetch MNO details.', 'error');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// --- INITIALIZE SELECT2 TAGS ON MODAL SHOWN ---
|
||||
$('#mnoModal').on('shown.bs.modal', function () {
|
||||
// Initialize Database-driven services multi-select (no custom tags allowed)
|
||||
if (!$('#mnoServices').hasClass("select2-hidden-accessible")) {
|
||||
$('#mnoServices').select2({
|
||||
theme: 'bootstrap-5',
|
||||
dropdownParent: $('#mnoModal'),
|
||||
placeholder: 'Select services...'
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize Email fields with custom tagging enabled (allows typing custom emails)
|
||||
$('#mnoModal .select2-tags').each(function() {
|
||||
if (!$(this).hasClass("select2-hidden-accessible")) {
|
||||
$(this).select2({
|
||||
theme: 'bootstrap-5',
|
||||
dropdownParent: $('#mnoModal'),
|
||||
tags: true,
|
||||
tokenSeparators: [',', ' '],
|
||||
placeholder: 'Type email and press enter...'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// --- AJAX FORM SUBMISSION ---
|
||||
$form.on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const $btn = $('#btnSubmitMno');
|
||||
const originalText = $btn.html();
|
||||
|
||||
$btn.html('<span class="spinner-border spinner-border-sm me-2"></span> Saving...');
|
||||
$btn.prop('disabled', true);
|
||||
|
||||
$.ajax({
|
||||
url: $form.attr('action'),
|
||||
type: 'POST',
|
||||
data: $form.serialize(),
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
|
||||
},
|
||||
success: function(response) {
|
||||
mnoModal.hide();
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Success!',
|
||||
text: response.message || 'Saved successfully.',
|
||||
confirmButtonColor: '#5c4df0'
|
||||
}).then(() => {
|
||||
location.reload();
|
||||
});
|
||||
},
|
||||
error: function(xhr) {
|
||||
let errors = xhr.responseJSON?.errors;
|
||||
let errorMsg = 'Validation failed. Please check inputs.';
|
||||
if (errors) {
|
||||
errorMsg = Object.values(errors).flat().join('\n');
|
||||
}
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Error',
|
||||
text: errorMsg,
|
||||
confirmButtonColor: '#dc3545'
|
||||
});
|
||||
$btn.html(originalText).prop('disabled', false);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
103
resources/views/clients/partials/edit-modal.blade.php
Normal file
103
resources/views/clients/partials/edit-modal.blade.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<div class="modal fade" id="editClientModal" tabindex="-1" aria-labelledby="editClientModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<form id="editClientForm" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title fw-bold" id="editClientModalLabel"><i class="bi bi-pencil-square text-primary me-2"></i>Edit Client Details</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row g-3">
|
||||
<!-- Basic Info -->
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-muted small fw-bold">Client Name</label>
|
||||
<input type="text" name="name" id="edit_name" class="form-control" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-muted small fw-bold">Primary Email</label>
|
||||
<input type="email" name="email" id="edit_email" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-muted small fw-bold">Phone</label>
|
||||
<input type="text" name="phone" id="edit_phone" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-muted small fw-bold">Contact Person</label>
|
||||
<input type="text" name="contact_person" id="edit_contact_person" class="form-control">
|
||||
</div>
|
||||
|
||||
<!-- Categorization / Types -->
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-muted small fw-bold">Company Type</label>
|
||||
<input type="text" name="company_type" id="edit_company_type" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-muted small fw-bold">Contract Type</label>
|
||||
<input type="text" name="contract_type" id="edit_contract_type" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-muted small fw-bold">Industry</label>
|
||||
<input type="text" name="industry" id="edit_industry" class="form-control">
|
||||
</div>
|
||||
|
||||
<!-- Multi-select / Select2 Fields -->
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-muted small fw-bold">Services</label>
|
||||
<select name="services[]" id="edit_services" class="form-select select2-tags" multiple="multiple"></select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-muted small fw-bold">Message Types</label>
|
||||
<select name="message_types[]" id="edit_message_types" class="form-select select2-tags" multiple="multiple">
|
||||
<option value="SMS">SMS</option>
|
||||
<option value="USSD">USSD</option>
|
||||
<option value="Voice">Voice</option>
|
||||
<option value="Email">Email</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-muted small fw-bold">Connections</label>
|
||||
<select name="connections[]" id="edit_connections" class="form-select select2-tags" multiple="multiple"></select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-muted small fw-bold">Support Phones</label>
|
||||
<select name="support_phones[]" id="edit_support_phones" class="form-select select2-tags" multiple="multiple"></select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-muted small fw-bold">Support Emails</label>
|
||||
<select name="support_emails[]" id="edit_support_emails" class="form-select select2-tags" multiple="multiple"></select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-muted small fw-bold">Rate Emails</label>
|
||||
<select name="rate_emails[]" id="edit_rate_emails" class="form-select select2-tags" multiple="multiple"></select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-muted small fw-bold">Support MS Teams</label>
|
||||
<select name="support_skype[]" id="edit_support_skype" class="form-select select2-tags" multiple="multiple"></select>
|
||||
</div>
|
||||
|
||||
<!-- Status & Meta -->
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-muted small fw-bold">Status</label>
|
||||
<input type="text" name="status" id="edit_status" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-muted small fw-bold">Currency</label>
|
||||
<input type="text" name="currency" id="edit_currency" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-muted small fw-bold">Country</label>
|
||||
<input type="text" name="country" id="edit_country" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary btn-sm px-4">Update Client</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -38,9 +38,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<!-- Button to trigger the Edit modal or go to edit page -->
|
||||
<button class="btn btn-primary fw-bold shadow-sm px-4" data-bs-toggle="modal" data-bs-target="#editClientModal">
|
||||
<i class="bi bi-pencil-square me-2"></i> Edit Client
|
||||
<button type="button" class="btn btn-sm btn-outline-primary edit-client-btn" data-client-id="{{ $showclient->id }}" data-bs-toggle="modal" data-bs-target="#editClientModal">
|
||||
<i class="bi bi-pencil me-1"></i> Edit Client
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -129,11 +128,9 @@
|
||||
<div class="mb-3">
|
||||
<div class="text-muted small mb-2">Subscribed Services</div>
|
||||
<div>
|
||||
@php
|
||||
$services = json_decode($showclient->services, true) ?? [];
|
||||
@endphp
|
||||
@if(count($services) > 0)
|
||||
@foreach($services as $service)
|
||||
|
||||
@if(count($showclient->services) > 0)
|
||||
@foreach($showclient->services as $service)
|
||||
<span class="badge bg-secondary bg-opacity-10 text-secondary border me-1">{{ $service }}</span>
|
||||
@endforeach
|
||||
@else
|
||||
@@ -156,16 +153,15 @@
|
||||
<div class="mb-2">
|
||||
<div class="text-muted small mb-1">Message Types</div>
|
||||
<div>
|
||||
@php
|
||||
$msgTypes = json_decode($showclient->message_types, true) ?? [];
|
||||
@endphp
|
||||
@if(count($msgTypes) > 0)
|
||||
@foreach($msgTypes as $type)
|
||||
@if($showclient->message_types !== null)
|
||||
@if(count($showclient->message_types) > 0)
|
||||
@foreach($showclient->message_types as $type)
|
||||
<span class="badge bg-info bg-opacity-10 text-info border border-info me-1">{{ $type }}</span>
|
||||
@endforeach
|
||||
@else
|
||||
<span class="text-muted small">N/A</span>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -250,11 +246,11 @@
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<!-- Helper Macro for JSON Emails/Phones -->
|
||||
<!-- JSON Emails/Phones -->
|
||||
@php
|
||||
function renderBadges($jsonString, $type = 'email') {
|
||||
$items = json_decode($jsonString, true) ?? [];
|
||||
if(count($items) === 0) return '<span class="text-muted small">N/A</span>';
|
||||
function renderBadges($items, $type = 'email') {
|
||||
if(gettype($items) == 'string') return '<span class="text-muted small">'.$items.'</span>';
|
||||
elseif(count($items) === 0) return '<span class="text-muted small">N/A</span>';
|
||||
$html = '';
|
||||
foreach($items as $item) {
|
||||
$icon = $type == 'email' ? 'bi-envelope' : 'bi-telephone';
|
||||
@@ -263,27 +259,43 @@
|
||||
return $html;
|
||||
}
|
||||
@endphp
|
||||
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="text-muted small mb-1">Finance Emails</div>
|
||||
<div>{!! renderBadges($showclient->finance_email, 'email') !!}</div>
|
||||
@if($showclient->finance_email == null)
|
||||
<span class="text-muted small">N/A</span>
|
||||
@else
|
||||
<div>{!! renderBadges($showclient->finance_email, 'email') !!}</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="text-muted small mb-1">Support Emails</div>
|
||||
<div>{!! renderBadges($showclient->support_emails, 'email') !!}</div>
|
||||
@if($showclient->support_emails == null)
|
||||
<span class="text-muted small">N/A</span>
|
||||
@else
|
||||
<div>{!! renderBadges($showclient->support_emails, 'email') !!}</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="text-muted small mb-1">Rate Emails</div>
|
||||
<div>{!! renderBadges($showclient->rate_emails, 'email') !!}</div>
|
||||
@if($showclient->rate_emails == null)
|
||||
<span class="text-muted small">N/A</span>
|
||||
@else
|
||||
<div>{!! renderBadges($showclient->rate_emails, 'email') !!}</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mb-0">
|
||||
<div class="text-muted small mb-1">Support Phones</div>
|
||||
<div>{!! renderBadges($showclient->support_phones, 'phone') !!}</div>
|
||||
@if($showclient->support_phones == null)
|
||||
<span class="text-muted small">N/A</span>
|
||||
@else
|
||||
<div>{!! renderBadges($showclient->support_phones, 'phone') !!}</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -440,6 +452,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($recent_payments as $payment)
|
||||
<?php //dump($payment); ?>
|
||||
<tr>
|
||||
<td class="fw-bold text-dark">{{ $payment->invoice_number ?? 'N/A' }}</td>
|
||||
|
||||
@@ -459,6 +472,7 @@
|
||||
<span class="text-muted small">-</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ $payment->invoice_amount }} </td>
|
||||
<td class="text-muted small">{{ $payment->invoice_date ? \Carbon\Carbon::parse($payment->invoice_date)->format('d M Y') : 'N/A' }}</td>
|
||||
<td>
|
||||
<span class="badge bg-info bg-opacity-10 text-info text-uppercase">{{ $payment->invoice_status ?? 'Pending' }}</span>
|
||||
@@ -558,9 +572,12 @@
|
||||
|
||||
</div>
|
||||
@include('clients.partials.shortcode-payment-docs-modal')
|
||||
@include('clients.partials.edit-modal')
|
||||
@endsection
|
||||
@push('scripts')
|
||||
<script src="{{ asset('public/assets/js/client-show-modal.js') }}"></script>
|
||||
<script>
|
||||
</script>
|
||||
@endpush
|
||||
@endpush
|
||||
|
||||
0546907824
|
||||
@@ -22,65 +22,56 @@
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<div>
|
||||
<h4 class="fw-bold mb-1">Mobile Network Operators (MNO)</h4>
|
||||
<p class="text-secondary mb-0" style="font-size: 0.9rem;">Manage telecommunications carrier connections, signaling links, and gateways.</p>
|
||||
<p class="text-secondary mb-0" style="font-size: 0.9rem;">Manage MNO details, connections and others</p>
|
||||
</div>
|
||||
<button class="btn text-white fw-bold d-flex align-items-center" style="background-color: #5c4df0; border-radius: 8px;" id="btnOpenMnoModal">
|
||||
<i class="bi bi-broadcast-pin me-2"></i> Add MNO Partner
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Dynamic Metrics Cards -->
|
||||
<div class="row g-4 mb-4">
|
||||
<div class="col-xl-3 col-md-6">
|
||||
<div class="col-xl-4 col-md-6">
|
||||
<div class="content-card p-3 h-100 border-start border-4 border-0" style="border-left-color: #5c4df0 !important;">
|
||||
<div class="text-secondary fw-bold mb-1" style="font-size: 0.75rem; letter-spacing: 0.5px;">ACTIVE CONNECTIONS</div>
|
||||
<h3 class="fw-bold mb-0">4 <span class="fs-6 fw-normal text-success"><i class="bi bi-arrow-up"></i> 100% Up</span></h3>
|
||||
<h3 class="fw-bold mb-0">{{ $totalActive }} <span class="fs-6 fw-normal text-success"><i class="bi bi-arrow-up"></i> Online</span></h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-md-6">
|
||||
<div class="col-xl-4 col-md-6">
|
||||
<div class="content-card p-3 h-100 border-start border-4 border-0" style="border-left-color: #10b981 !important;">
|
||||
<div class="text-secondary fw-bold mb-1" style="font-size: 0.75rem; letter-spacing: 0.5px;">PROVISIONED SHORTCODES</div>
|
||||
<h3 class="fw-bold mb-0">12</h3>
|
||||
<div class="text-secondary fw-bold mb-1" style="font-size: 0.75rem; letter-spacing: 0.5px;">VPN LINKS </div>
|
||||
<h3 class="fw-bold mb-0">{{ $totalSipLinks }} Links</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-md-6">
|
||||
<div class="col-xl-4 col-md-6">
|
||||
<div class="content-card p-3 h-100 border-start border-4 border-0" style="border-left-color: #f59e0b !important;">
|
||||
<div class="text-secondary fw-bold mb-1" style="font-size: 0.75rem; letter-spacing: 0.5px;">TOTAL SIP TRUNKS</div>
|
||||
<h3 class="fw-bold mb-0">6 Links</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-md-6">
|
||||
<div class="content-card p-3 h-100 border-start border-4 border-0" style="border-left-color: #ef4444 !important;">
|
||||
<div class="text-secondary fw-bold mb-1" style="font-size: 0.75rem; letter-spacing: 0.5px;">AGGREGATED DAILY VOL</div>
|
||||
<h3 class="fw-bold mb-0">142.8k <span class="fs-6 fw-normal text-secondary" style="font-size:0.75rem !important;">hits</span></h3>
|
||||
<div class="text-secondary fw-bold mb-1" style="font-size: 0.75rem; letter-spacing: 0.5px;">REGISTERED MNO PARTNERS</div>
|
||||
<h3 class="fw-bold mb-0">{{ $totalOperators }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-card">
|
||||
<div class="p-3 border-bottom bg-light bg-opacity-50">
|
||||
<div class="row g-3">
|
||||
<form method="GET" action="{{ route('mnos.index') }}" class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-white border-end-0 text-secondary"><i class="bi bi-search"></i></span>
|
||||
<input type="text" class="form-control bg-white border-start-0 ps-0" placeholder="Search gateways, IPs, or partner networks...">
|
||||
<input type="text" name="search" value="{{ request('search') }}" class="form-control bg-white border-start-0 ps-0" placeholder="Search here...">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-select bg-white">
|
||||
<option value="">All Regions</option>
|
||||
<option value="GH">Ghana (GH)</option>
|
||||
<option value="ZM">Zambia (ZM)</option>
|
||||
</select>
|
||||
@include('network_operators.partials.countries')
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-select bg-white">
|
||||
<option value="">All Link Types</option>
|
||||
<option value="vpn">IPsec VPN</option>
|
||||
<option value="tailscale">IPSec VPN Tunnel</option>
|
||||
<option value="public">Whitelisted Public IP</option>
|
||||
<select name="connection_status" class="form-select bg-white" onchange="this.form.submit()">
|
||||
<option value="">Any Status</option>
|
||||
<option value="Active" {{ request('link_type') == 'vpn' ? 'selected' : '' }}>Active</option>
|
||||
<option value="Inactive" {{ request('link_type') == 'direct' ? 'selected' : '' }}>Inactive</option>
|
||||
<option value="Pending" {{ request('link_type') == 'direct' ? 'selected' : '' }}>Pending</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
@@ -89,251 +80,87 @@
|
||||
<tr>
|
||||
<th>Operator</th>
|
||||
<th>Country</th>
|
||||
<th>Network Codes</th>
|
||||
<th>Infrastructure Links</th>
|
||||
<th>Capabilities</th>
|
||||
<th>Link Status</th>
|
||||
<th>Connection Type</th>
|
||||
<th>Services</th>
|
||||
<th>Status</th>
|
||||
<th class="text-end">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="avatar-circle bg-warning bg-opacity-10 text-warning me-3">MTN</div>
|
||||
<div>
|
||||
<div class="fw-bold text-dark">MTN Ghana</div>
|
||||
<div class="text-secondary" style="font-size: 0.8rem;">Scancom PLC</div>
|
||||
@forelse($operators as $operator)
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="avatar-circle bg-primary bg-opacity-10 text-primary me-3">
|
||||
{{ strtoupper(substr($operator->name, 0, 2)) }}
|
||||
</div>
|
||||
<div>
|
||||
<div class="fw-bold text-dark">{{ $operator->name }}</div>
|
||||
<div class="text-secondary" style="font-size: 0.8rem;">{{ $operator->contact_person ?? 'N/A' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="fw-semibold">Ghana (GH)</span></td>
|
||||
<td>
|
||||
<span class="tech-badge">MCC: 620</span>
|
||||
<span class="tech-badge">MNC: 01</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="text-dark fw-semibold" style="font-size: 0.85rem;"><i class="bi bi-shield-lock me-1 text-primary"></i> IPsec VPN Tunnel</div>
|
||||
<div class="text-secondary style" style="font-size: 0.75rem;">Gateway: 172.16.42.1</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex gap-1 flex-wrap">
|
||||
<span class="badge bg-secondary text-dark border bg-light" style="font-size: 0.65rem;">USSD</span>
|
||||
<span class="badge bg-secondary text-dark border bg-light" style="font-size: 0.65rem;">SMS Gateway</span>
|
||||
<span class="badge bg-secondary text-dark border bg-light" style="font-size: 0.65rem;">SIP Trunk</span>
|
||||
<span class="badge bg-secondary text-dark border bg-light" style="font-size: 0.65rem;">MoMo API</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span class="d-flex align-items-center gap-2">
|
||||
<span class="status-indicator bg-success"></span>
|
||||
<span class="fw-semibold text-success" style="font-size: 0.85rem;">Online</span>
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<button class="btn btn-sm btn-light text-secondary me-1"><i class="bi bi-terminal"></i></button>
|
||||
<button class="btn btn-sm btn-light text-primary btn-edit-mno"
|
||||
data-id="1" data-name="MTN Ghana" data-company="Scancom PLC" data-country="GH" data-mcc="620" data-mnc="01" data-link="vpn" data-gateway="172.16.42.1" data-capabilities='["ussd","sms","voice","momo"]' data-status="online">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="avatar-circle bg-danger bg-opacity-10 text-danger me-3">TL</div>
|
||||
<div>
|
||||
<div class="fw-bold text-dark">Telecel Ghana</div>
|
||||
<div class="text-secondary" style="font-size: 0.8rem;">Telecel Group</div>
|
||||
</td>
|
||||
<td><span class="fw-semibold">{{ $operator->country }}</span></td>
|
||||
<td>
|
||||
<div class="text-dark fw-semibold" style="font-size: 0.85rem;"><i class="bi bi-shield-lock me-1 text-primary"></i> {{ $operator->connection_type ?? 'N/A' }}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex gap-1 flex-wrap">
|
||||
@if(is_array($operator->services))
|
||||
@foreach($operator->services as $service)
|
||||
<span class="badge bg-secondary text-dark border bg-light" style="font-size: 0.65rem;">{{ strtoupper($service) }}</span>
|
||||
@endforeach
|
||||
@else
|
||||
<span class="text-muted small">None</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="fw-semibold">Ghana (GH)</span></td>
|
||||
<td>
|
||||
<span class="tech-badge">MCC: 620</span>
|
||||
<span class="tech-badge">MNC: 02</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="text-dark fw-semibold" style="font-size: 0.85rem;"><i class="bi bi-shuffle me-1 text-info"></i> VPN Tunnel</div>
|
||||
<div class="text-secondary" style="font-size: 0.75rem;">Peer IP: 100.115.2.4</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex gap-1 flex-wrap">
|
||||
<span class="badge bg-secondary text-dark border bg-light" style="font-size: 0.65rem;">USSD</span>
|
||||
<span class="badge bg-secondary text-dark border bg-light" style="font-size: 0.65rem;">SMS Gateway</span>
|
||||
<span class="badge bg-secondary text-dark border bg-light" style="font-size: 0.65rem;">Payment API</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span class="d-flex align-items-center gap-2">
|
||||
<span class="status-indicator bg-success"></span>
|
||||
<span class="fw-semibold text-success" style="font-size: 0.85rem;">Online</span>
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<button class="btn btn-sm btn-light text-secondary me-1"><i class="bi bi-terminal"></i></button>
|
||||
<button class="btn btn-sm btn-light text-primary btn-edit-mno"
|
||||
data-id="2" data-name="Telecel Ghana" data-company="Telecel Group" data-country="GH" data-mcc="620" data-mnc="02" data-link="tailscale" data-gateway="100.115.2.4" data-capabilities='["ussd","sms","momo"]' data-status="online">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</td>
|
||||
<td>
|
||||
<span class="d-flex align-items-center gap-2">
|
||||
<span class="status-indicator {{ ($operator->connection_status == 'Active') ? 'bg-success' : 'bg-danger' }}"></span>
|
||||
<span class="fw-semibold {{ ($operator->connection_status == 'Active') ? 'text-success' : 'text-danger' }}" style="font-size: 0.85rem;">
|
||||
{{ $operator->connection_status ?? 'N/A' }}
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<div class="d-flex gap-1 justify-content-end align-items-center">
|
||||
<a href="{{ route('mnos.show', $operator->id) }}" class="btn btn-sm btn-light text-secondary me-1" title="View Details">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
<button class="btn btn-sm btn-light text-primary btn-edit-mno" data-id="{{ $operator->id }}" title="Edit MNO">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="6" class="text-center py-4 text-muted">No MNO partners found.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- Pagination Links Footer -->
|
||||
@if($operators->hasPages())
|
||||
<div class="p-3 border-top bg-light bg-opacity-50 d-flex justify-content-between align-items-center">
|
||||
<div class="text-secondary small">
|
||||
Showing {{ $operators->firstItem() }} to {{ $operators->lastItem() }} of {{ $operators->total() }} MNO partners
|
||||
</div>
|
||||
<div>
|
||||
{{ $operators->links() }}
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('modals')
|
||||
<div class="modal fade" id="mnoModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-light">
|
||||
<h5 class="modal-title fw-bold" id="mnoModalTitle">Configure MNO Link</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<form id="mnoForm">
|
||||
<div class="modal-body p-4">
|
||||
<input type="hidden" id="mnoId" name="id">
|
||||
|
||||
<h6 class="fw-bold mb-3 text-secondary text-uppercase" style="font-size: 0.75rem;">Carrier Identity</h6>
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Brand Name *</label>
|
||||
<input type="text" class="form-control" id="mnoName" name="name" required placeholder="e.g. MTN Ghana">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Registered Corporate Title</label>
|
||||
<input type="text" class="form-control" id="mnoCompany" name="corporate_name" placeholder="e.g. Scancom PLC">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Operating Country *</label>
|
||||
<select class="form-select" id="mnoCountry" name="country_code" required>
|
||||
<option value="GH">Ghana (GH)</option>
|
||||
<option value="ZM">Zambia (ZM)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Mobile Country Code (MCC) *</label>
|
||||
<input type="text" class="form-control" id="mnoMcc" name="mcc" required placeholder="e.g. 620">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Mobile Network Code (MNC) *</label>
|
||||
<input type="text" class="form-control" id="mnoMnc" name="mnc" required placeholder="e.g. 01">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h6 class="fw-bold mb-3 text-secondary text-uppercase" style="font-size: 0.75rem;">Network & Transport Configuration</h6>
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Interconnect Type</label>
|
||||
<select class="form-select" id="mnoLinkType" name="link_type">
|
||||
<option value="vpn">IPsec VPN Tunnel</option>
|
||||
<option value="tailscale">Tailscale Overlaid Mesh</option>
|
||||
<option value="public">Whitelisted Public Endpoint</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Remote Gateway IP / Endpoint Address</label>
|
||||
<input type="text" class="form-control" id="mnoGateway" name="remote_gateway" placeholder="e.g. 172.16.42.1">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h6 class="fw-bold mb-3 text-secondary text-uppercase" style="font-size: 0.75rem;">Provisioned Interface Frameworks</h6>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-12">
|
||||
<label class="form-label text-secondary fw-semibold d-block style" style="font-size: 0.85rem; margin-bottom: 0.5rem;">Enable Capabilities</label>
|
||||
<div class="form-check form-check-inline me-4">
|
||||
<input class="form-check-input" type="checkbox" id="capUssd" name="capabilities[]" value="ussd">
|
||||
<label class="form-check-label text-dark" for="capUssd">USSD Gateway (SIGTRAN/M3UA)</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline me-4">
|
||||
<input class="form-check-input" type="checkbox" id="capSms" name="capabilities[]" value="sms">
|
||||
<label class="form-check-label text-dark" for="capSms">SMS SMPP Bindings</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline me-4">
|
||||
<input class="form-check-input" type="checkbox" id="capVoice" name="capabilities[]" value="voice">
|
||||
<label class="form-check-label text-dark" for="capVoice">SIP Voice Trunking</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="checkbox" id="capMomo" name="capabilities[]" value="momo">
|
||||
<label class="form-check-label text-dark" for="capMomo">Mobile Money Node</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn text-white fw-bold px-4" style="background-color: #5c4df0;" id="btnSubmitMno">
|
||||
Save Gateway Profile
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@include('network_operators.partials.mno_modals')
|
||||
@endpush
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
const mnoModal = new bootstrap.Modal(document.getElementById('mnoModal'));
|
||||
const $form = $('#mnoForm');
|
||||
|
||||
// --- OPEN MODAL FOR CREATE ---
|
||||
$('#btnOpenMnoModal').on('click', function() {
|
||||
$form[0].reset();
|
||||
$('#mnoId').val('');
|
||||
$('#mnoModalTitle').text('Configure New MNO Interconnect');
|
||||
$('#btnSubmitMno').html('<i class="bi bi-save me-2"></i>Save Gateway Profile');
|
||||
mnoModal.show();
|
||||
});
|
||||
|
||||
// --- OPEN MODAL FOR EDIT ---
|
||||
$('.btn-edit-mno').on('click', function() {
|
||||
const data = $(this).data();
|
||||
|
||||
$form[0].reset();
|
||||
$('#mnoId').val(data.id);
|
||||
$('#mnoName').val(data.name);
|
||||
$('#mnoCompany').val(data.company);
|
||||
$('#mnoCountry').val(data.country);
|
||||
$('#mnoMcc').val(data.mcc);
|
||||
$('#mnoMnc').val(data.mnc);
|
||||
$('#mnoLinkType').val(data.link);
|
||||
$('#mnoGateway').val(data.gateway);
|
||||
|
||||
// Clear and map checkmarks safely
|
||||
$('input[name="capabilities[]"]').prop('checked', false);
|
||||
if (data.capabilities && Array.isArray(data.capabilities)) {
|
||||
data.capabilities.forEach(function(cap) {
|
||||
$('input[value="' + cap + '"]').prop('checked', true);
|
||||
});
|
||||
}
|
||||
|
||||
$('#mnoModalTitle').text('Modify Link Profiles: ' + data.name);
|
||||
$('#btnSubmitMno').html('<i class="bi bi-check-circle me-2"></i>Apply Changes');
|
||||
|
||||
mnoModal.show();
|
||||
});
|
||||
|
||||
// --- AJAX FORM SUBMISSION SIMULATION ---
|
||||
$form.on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const $btn = $('#btnSubmitMno');
|
||||
const originalText = $btn.html();
|
||||
|
||||
$btn.html('<span class="spinner-border spinner-border-sm me-2"></span> Updating Trunk Contexts...');
|
||||
$btn.prop('disabled', true);
|
||||
|
||||
setTimeout(() => {
|
||||
console.log('MNO Payload Synchronized:', $form.serializeArray());
|
||||
$btn.html(originalText).prop('disabled', false);
|
||||
mnoModal.hide();
|
||||
alert('Gateway routing map refreshed successfully.');
|
||||
}, 900);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script src="{{ asset('public/assets/js/mno_index.js') }} "></script>
|
||||
@endpush
|
||||
@@ -0,0 +1,58 @@
|
||||
|
||||
<select name="country" class="form-select bg-white" onchange="this.form.submit()">
|
||||
<option value="">All Regions (Africa)</option>
|
||||
<option value="Algeria" {{ request('country') == 'Algeria' ? 'selected' : '' }}>Algeria</option>
|
||||
<option value="Angola" {{ request('country') == 'Angola' ? 'selected' : '' }}>Angola</option>
|
||||
<option value="Benin" {{ request('country') == 'Benin' ? 'selected' : '' }}>Benin</option>
|
||||
<option value="Botswana" {{ request('country') == 'Botswana' ? 'selected' : '' }}>Botswana</option>
|
||||
<option value="Burkina Faso" {{ request('country') == 'Burkina Faso' ? 'selected' : '' }}>Burkina Faso</option>
|
||||
<option value="Burundi" {{ request('country') == 'Burundi' ? 'selected' : '' }}>Burundi</option>
|
||||
<option value="Cabo Verde" {{ request('country') == 'Cabo Verde' ? 'selected' : '' }}>Cabo Verde</option>
|
||||
<option value="Cameroon" {{ request('country') == 'Cameroon' ? 'selected' : '' }}>Cameroon</option>
|
||||
<option value="Central African Republic" {{ request('country') == 'Central African Republic' ? 'selected' : '' }}>Central African Republic</option>
|
||||
<option value="Chad" {{ request('country') == 'Chad' ? 'selected' : '' }}>Chad</option>
|
||||
<option value="Comoros" {{ request('country') == 'Comoros' ? 'selected' : '' }}>Comoros</option>
|
||||
<option value="Congo" {{ request('country') == 'Congo' ? 'selected' : '' }}>Congo</option>
|
||||
<option value="Democratic Republic of the Congo" {{ request('country') == 'Democratic Republic of the Congo' ? 'selected' : '' }}>Democratic Republic of the Congo</option>
|
||||
<option value="Cote d'Ivoire" {{ request('country') == "Cote d'Ivoire" ? 'selected' : '' }}>Cote d'Ivoire</option>
|
||||
<option value="Djibouti" {{ request('country') == 'Djibouti' ? 'selected' : '' }}>Djibouti</option>
|
||||
<option value="Egypt" {{ request('country') == 'Egypt' ? 'selected' : '' }}>Egypt</option>
|
||||
<option value="Equatorial Guinea" {{ request('country') == 'Equatorial Guinea' ? 'selected' : '' }}>Equatorial Guinea</option>
|
||||
<option value="Eritrea" {{ request('country') == 'Eritrea' ? 'selected' : '' }}>Eritrea</option>
|
||||
<option value="Eswatini" {{ request('country') == 'Eswatini' ? 'selected' : '' }}>Eswatini</option>
|
||||
<option value="Ethiopia" {{ request('country') == 'Ethiopia' ? 'selected' : '' }}>Ethiopia</option>
|
||||
<option value="Gabon" {{ request('country') == 'Gabon' ? 'selected' : '' }}>Gabon</option>
|
||||
<option value="Gambia" {{ request('country') == 'Gambia' ? 'selected' : '' }}>Gambia</option>
|
||||
<option value="Ghana" {{ request('country') == 'Ghana' ? 'selected' : '' }}>Ghana</option>
|
||||
<option value="Guinea" {{ request('country') == 'Guinea' ? 'selected' : '' }}>Guinea</option>
|
||||
<option value="Guinea-Bissau" {{ request('country') == 'Guinea-Bissau' ? 'selected' : '' }}>Guinea-Bissau</option>
|
||||
<option value="Kenya" {{ request('country') == 'Kenya' ? 'selected' : '' }}>Kenya</option>
|
||||
<option value="Lesotho" {{ request('country') == 'Lesotho' ? 'selected' : '' }}>Lesotho</option>
|
||||
<option value="Liberia" {{ request('country') == 'Liberia' ? 'selected' : '' }}>Liberia</option>
|
||||
<option value="Libya" {{ request('country') == 'Libya' ? 'selected' : '' }}>Libya</option>
|
||||
<option value="Madagascar" {{ request('country') == 'Madagascar' ? 'selected' : '' }}>Madagascar</option>
|
||||
<option value="Malawi" {{ request('country') == 'Malawi' ? 'selected' : '' }}>Malawi</option>
|
||||
<option value="Mali" {{ request('country') == 'Mali' ? 'selected' : '' }}>Mali</option>
|
||||
<option value="Mauritania" {{ request('country') == 'Mauritania' ? 'selected' : '' }}>Mauritania</option>
|
||||
<option value="Mauritius" {{ request('country') == 'Mauritius' ? 'selected' : '' }}>Mauritius</option>
|
||||
<option value="Morocco" {{ request('country') == 'Morocco' ? 'selected' : '' }}>Morocco</option>
|
||||
<option value="Mozambique" {{ request('country') == 'Mozambique' ? 'selected' : '' }}>Mozambique</option>
|
||||
<option value="Namibia" {{ request('country') == 'Namibia' ? 'selected' : '' }}>Namibia</option>
|
||||
<option value="Niger" {{ request('country') == 'Niger' ? 'selected' : '' }}>Niger</option>
|
||||
<option value="Nigeria" {{ request('country') == 'Nigeria' ? 'selected' : '' }}>Nigeria</option>
|
||||
<option value="Rwanda" {{ request('country') == 'Rwanda' ? 'selected' : '' }}>Rwanda</option>
|
||||
<option value="Sao Tome and Principe" {{ request('country') == 'Sao Tome and Principe' ? 'selected' : '' }}>Sao Tome and Principe</option>
|
||||
<option value="Senegal" {{ request('country') == 'Senegal' ? 'selected' : '' }}>Senegal</option>
|
||||
<option value="Seychelles" {{ request('country') == 'Seychelles' ? 'selected' : '' }}>Seychelles</option>
|
||||
<option value="Sierra Leone" {{ request('country') == 'Sierra Leone' ? 'selected' : '' }}>Sierra Leone</option>
|
||||
<option value="Somalia" {{ request('country') == 'Somalia' ? 'selected' : '' }}>Somalia</option>
|
||||
<option value="South Africa" {{ request('country') == 'South Africa' ? 'selected' : '' }}>South Africa</option>
|
||||
<option value="South Sudan" {{ request('country') == 'South Sudan' ? 'selected' : '' }}>South Sudan</option>
|
||||
<option value="Sudan" {{ request('country') == 'Sudan' ? 'selected' : '' }}>Sudan</option>
|
||||
<option value="Tanzania" {{ request('country') == 'Tanzania' ? 'selected' : '' }}>Tanzania</option>
|
||||
<option value="Togo" {{ request('country') == 'Togo' ? 'selected' : '' }}>Togo</option>
|
||||
<option value="Tunisia" {{ request('country') == 'Tunisia' ? 'selected' : '' }}>Tunisia</option>
|
||||
<option value="Uganda" {{ request('country') == 'Uganda' ? 'selected' : '' }}>Uganda</option>
|
||||
<option value="Zambia" {{ request('country') == 'Zambia' ? 'selected' : '' }}>Zambia</option>
|
||||
<option value="Zimbabwe" {{ request('country') == 'Zimbabwe' ? 'selected' : '' }}>Zimbabwe</option>
|
||||
</select>
|
||||
165
resources/views/network_operators/partials/mno_modals.blade.php
Normal file
165
resources/views/network_operators/partials/mno_modals.blade.php
Normal file
@@ -0,0 +1,165 @@
|
||||
<div class="modal fade" id="mnoModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-light">
|
||||
<h5 class="modal-title fw-bold" id="mnoModalTitle"></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<form id="mnoForm" method="POST" action="{{ url('mnos') }}">
|
||||
@csrf
|
||||
<div id="methodField"></div>
|
||||
|
||||
<div class="modal-body p-4">
|
||||
<input type="hidden" id="mnoId" name="id">
|
||||
|
||||
<h6 class="fw-bold mb-3 text-secondary text-uppercase" style="font-size: 0.75rem;">Carrier Identity</h6>
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Brand Name *</label>
|
||||
<input type="text" class="form-control" id="mnoName" name="name" required placeholder="e.g. MTN Ghana">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem; width: 100%;">Operating Country *</label>
|
||||
<select class="form-select w-100" id="mnoCountry" name="country" required>
|
||||
<option value="">Select Country</option>
|
||||
<option value="Algeria">Algeria</option>
|
||||
<option value="Angola">Angola</option>
|
||||
<option value="Benin">Benin</option>
|
||||
<option value="Botswana">Botswana</option>
|
||||
<option value="Burkina Faso">Burkina Faso</option>
|
||||
<option value="Burundi">Burundi</option>
|
||||
<option value="Cabo Verde">Cabo Verde</option>
|
||||
<option value="Cameroon">Cameroon</option>
|
||||
<option value="Central African Republic">Central African Republic</option>
|
||||
<option value="Chad">Chad</option>
|
||||
<option value="Comoros">Comoros</option>
|
||||
<option value="Congo">Congo</option>
|
||||
<option value="Democratic Republic of the Congo">Democratic Republic of the Congo</option>
|
||||
<option value="Cote d'Ivoire">Cote d'Ivoire</option>
|
||||
<option value="Djibouti">Djibouti</option>
|
||||
<option value="Egypt">Egypt</option>
|
||||
<option value="Equatorial Guinea">Equatorial Guinea</option>
|
||||
<option value="Eritrea">Eritrea</option>
|
||||
<option value="Eswatini">Eswatini</option>
|
||||
<option value="Ethiopia">Ethiopia</option>
|
||||
<option value="Gabon">Gabon</option>
|
||||
<option value="Gambia">Gambia</option>
|
||||
<option value="Ghana">Ghana</option>
|
||||
<option value="Guinea">Guinea</option>
|
||||
<option value="Guinea-Bissau">Guinea-Bissau</option>
|
||||
<option value="Kenya">Kenya</option>
|
||||
<option value="Lesotho">Lesotho</option>
|
||||
<option value="Liberia">Liberia</option>
|
||||
<option value="Libya">Libya</option>
|
||||
<option value="Madagascar">Madagascar</option>
|
||||
<option value="Malawi">Malawi</option>
|
||||
<option value="Mali">Mali</option>
|
||||
<option value="Mauritania">Mauritania</option>
|
||||
<option value="Mauritius">Mauritius</option>
|
||||
<option value="Morocco">Morocco</option>
|
||||
<option value="Mozambique">Mozambique</option>
|
||||
<option value="Namibia">Namibia</option>
|
||||
<option value="Niger">Niger</option>
|
||||
<option value="Nigeria">Nigeria</option>
|
||||
<option value="Rwanda">Rwanda</option>
|
||||
<option value="Sao Tome and Principe">Sao Tome and Principe</option>
|
||||
<option value="Senegal">Senegal</option>
|
||||
<option value="Seychelles">Seychelles</option>
|
||||
<option value="Sierra Leone">Sierra Leone</option>
|
||||
<option value="Somalia">Somalia</option>
|
||||
<option value="South Africa">South Africa</option>
|
||||
<option value="South Sudan">South Sudan</option>
|
||||
<option value="Sudan">Sudan</option>
|
||||
<option value="Tanzania">Tanzania</option>
|
||||
<option value="Togo">Togo</option>
|
||||
<option value="Tunisia">Tunisia</option>
|
||||
<option value="Uganda">Uganda</option>
|
||||
<option value="Zambia">Zambia</option>
|
||||
<option value="Zimbabwe">Zimbabwe</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Connection Status</label>
|
||||
<select class="form-select" id="mnoConnectionStatus" name="connection_status">
|
||||
<option value="Active">Active</option>
|
||||
<option value="Inactive">Inactive</option>
|
||||
<option value="Pending">Pending</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h6 class="fw-bold mb-3 text-secondary text-uppercase" style="font-size: 0.75rem;">Contact & Support Personnel</h6>
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Contact Person</label>
|
||||
<input type="text" class="form-control" id="mnoContactPerson" name="contact_person" placeholder="Full name">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Contact Phone</label>
|
||||
<input type="text" class="form-control" id="mnoContactPhone" name="contact_person_phone" placeholder="Phone number">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Contact Email</label>
|
||||
<input type="email" class="form-control" id="mnoContactEmail" name="contact_person_email" placeholder="Email address">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Technical Support Person</label>
|
||||
<input type="text" class="form-control" id="mnoTechSupport" name="technical_support_person" placeholder="Tech contact">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Support Skype</label>
|
||||
<input type="text" class="form-control" id="mnoSupportSkype" name="support_skype" placeholder="Skype ID">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Account Manager</label>
|
||||
<input type="text" class="form-control" id="mnoAccountManager" name="mno_account_manager" placeholder="Manager name">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h6 class="fw-bold mb-3 text-secondary text-uppercase" style="font-size: 0.75rem;">Multi-Entry & Services Configuration</h6>
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Services</label>
|
||||
<select name="services[]" id="mnoServices" class="form-select select2-db" multiple="multiple"></select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Support Emails</label>
|
||||
<select name="support_emails[]" id="mnoSupportEmails" class="form-select select2-tags" multiple="multiple"></select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Finance Emails</label>
|
||||
<select name="finance_emails[]" id="mnoFinanceEmails" class="form-select select2-tags" multiple="multiple"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h6 class="fw-bold mb-3 text-secondary text-uppercase" style="font-size: 0.75rem;">Commercial & Technical Configurations</h6>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-3">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Buying Rate</label>
|
||||
<input type="number" step="0.0001" class="form-control" id="mnoBuyingRate" name="buying_rate" value="0.0000">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Rate Type</label>
|
||||
<input type="text" class="form-control" id="mnoRateType" name="rate_type" placeholder="e.g. Fixed / Tiered">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Payment Terms</label>
|
||||
<input type="text" class="form-control" id="mnoPaymentTerms" name="payment_terms" placeholder="e.g. Net 30">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label text-secondary fw-semibold" style="font-size: 0.85rem;">Connection Type</label>
|
||||
<input type="text" class="form-control" id="mnoConnectionType" name="connection_type" placeholder="e.g. SMPP / API">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn text-white fw-bold px-4" style="background-color: #5c4df0;" id="btnSubmitMno">
|
||||
Save Gateway Profile
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
161
resources/views/network_operators/show.blade.php
Normal file
161
resources/views/network_operators/show.blade.php
Normal file
@@ -0,0 +1,161 @@
|
||||
@extends('layouts.masterbeta')
|
||||
|
||||
@section('title', 'Cick ERP - ' . $operator->name)
|
||||
|
||||
@section('breadcrumbs')
|
||||
<a href="{{ url('/') }}" class="text-secondary text-decoration-none"><i class="bi bi-house me-2"></i></a>
|
||||
<i class="bi bi-chevron-right text-secondary me-2" style="font-size: 0.8rem;"></i>
|
||||
<a href="{{ route('mnos.index') }}" class="text-secondary text-decoration-none me-2" style="font-size: 0.95rem;">MNO Partners</a>
|
||||
<i class="bi bi-chevron-right text-secondary me-2" style="font-size: 0.8rem;"></i>
|
||||
<span class="fw-bold" style="font-size: 0.95rem;">{{ $operator->name }}</span>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<!-- Header Section -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="avatar-circle bg-primary bg-opacity-10 text-primary fw-bold me-3 fs-4" style="width: 55px; height: 55px; border-radius: 50%; display: flex; align-items: center; justify-content: center;">
|
||||
{{ strtoupper(substr($operator->name, 0, 2)) }}
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="fw-bold mb-1">{{ $operator->name }}</h3>
|
||||
<p class="text-secondary mb-0" style="font-size: 0.9rem;">
|
||||
<i class="bi bi-geo-alt me-1"></i> {{ $operator->country }} •
|
||||
<span class="badge {{ $operator->connection_status == 'Online' ? 'bg-success' : 'bg-danger' }} ms-1">
|
||||
{{ $operator->connection_status ?? 'Offline' }}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a href="{{ route('mnos.index') }}" class="btn btn-outline-secondary btn-sm fw-bold">
|
||||
<i class="bi bi-arrow-left me-1"></i> Back to List
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Overview Metrics Row -->
|
||||
<div class="row g-4 mb-4">
|
||||
<div class="col-xl-4 col-md-6">
|
||||
<div class="content-card p-3 h-100 border-start border-4 border-primary">
|
||||
<div class="text-secondary fw-bold mb-1" style="font-size: 0.75rem; letter-spacing: 0.5px;">CONNECTION TYPE</div>
|
||||
<h5 class="fw-bold mb-0 text-dark">{{ $operator->connection_type ?? 'Standard Link' }}</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-md-6">
|
||||
<div class="content-card p-3 h-100 border-start border-4 border-success">
|
||||
<div class="text-secondary fw-bold mb-1" style="font-size: 0.75rem; letter-spacing: 0.5px;">BUYING RATE</div>
|
||||
<h5 class="fw-bold mb-0 text-dark">{{ $operator->buying_rate ? number_format($operator->buying_rate, 4) : '0.0000' }}</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-md-6">
|
||||
<div class="content-card p-3 h-100 border-start border-4 border-warning">
|
||||
<div class="text-secondary fw-bold mb-1" style="font-size: 0.75rem; letter-spacing: 0.5px;">PAYMENT TERMS</div>
|
||||
<h5 class="fw-bold mb-0 text-dark">{{ $operator->payment_terms ?? 'N/A' }}</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Detailed Attributes Grid -->
|
||||
<div class="row g-4">
|
||||
<!-- Left Column: Carrier & Technical Meta -->
|
||||
<div class="col-lg-8">
|
||||
<div class="content-card p-4 mb-4">
|
||||
<h5 class="fw-bold mb-3 text-secondary" style="font-size: 0.9rem; text-transform: uppercase; letter-spacing: 0.5px;">
|
||||
<i class="bi bi-info-circle me-2 text-primary"></i> Carrier & Technical Configuration
|
||||
</h5>
|
||||
<hr class="text-muted opacity-25">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<span class="text-muted small d-block">Operating Country</span>
|
||||
<strong class="text-dark">{{ $operator->country }}</strong>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<span class="text-muted small d-block">Rate Type</span>
|
||||
<strong class="text-dark">{{ $operator->rate_type ?? 'N/A' }}</strong>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<span class="text-muted small d-block">Account Manager</span>
|
||||
<strong class="text-dark">{{ $operator->mno_account_manager ?? 'N/A' }}</strong>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<span class="text-muted small d-block">Direct Business</span>
|
||||
<strong class="text-dark">{{ $operator->direct_business ?? 'YES' }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Provisioned Services Badges -->
|
||||
<div class="content-card p-4">
|
||||
<h5 class="fw-bold mb-3 text-secondary" style="font-size: 0.9rem; text-transform: uppercase; letter-spacing: 0.5px;">
|
||||
<i class="bi bi-layers me-2 text-primary"></i> Provisioned Services
|
||||
</h5>
|
||||
<hr class="text-muted opacity-25">
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
@if(is_array($operator->services) && count($operator->services) > 0)
|
||||
@foreach($operator->services as $service)
|
||||
<span class="badge bg-light text-primary border px-3 py-2" style="font-size: 0.85rem;">
|
||||
<i class="bi bi-check-circle-fill me-1 text-success"></i> {{ is_numeric($service) ? App\Models\Service::find($service)->name ?? 'Service #'.$service : $service }}
|
||||
</span>
|
||||
@endforeach
|
||||
@else
|
||||
<span class="text-muted small">No specific services provisioned.</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Column: Contacts & Support Channels -->
|
||||
<div class="col-lg-4">
|
||||
<div class="content-card p-4 mb-4">
|
||||
<h5 class="fw-bold mb-3 text-secondary" style="font-size: 0.9rem; text-transform: uppercase; letter-spacing: 0.5px;">
|
||||
<i class="bi bi-headset me-2 text-primary"></i> Support Contacts
|
||||
</h5>
|
||||
<hr class="text-muted opacity-25">
|
||||
|
||||
<div class="mb-3">
|
||||
<span class="text-muted small d-block">Contact Person</span>
|
||||
<strong class="text-dark">{{ $operator->contact_person ?? 'N/A' }}</strong>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<span class="text-muted small d-block">Direct Phone</span>
|
||||
<strong class="text-dark">{{ $operator->contact_person_phone ?? 'N/A' }}</strong>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<span class="text-muted small d-block">Technical Support Lead</span>
|
||||
<strong class="text-dark">{{ $operator->technical_support_person ?? 'N/A' }}</strong>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<span class="text-muted small d-block">Support MS Team</span>
|
||||
<strong class="text-dark">{{ $operator->support_skype ?? 'N/A' }}</strong>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<span class="text-muted small d-block mb-1">Support Emails</span>
|
||||
<div class="d-flex flex-wrap gap-1">
|
||||
@if(is_array($operator->support_emails) && count($operator->support_emails) > 0)
|
||||
@foreach($operator->support_emails as $email)
|
||||
<span class="badge bg-secondary bg-opacity-10 text-dark border" style="font-size: 0.75rem;">{{ $email }}</span>
|
||||
@endforeach
|
||||
@else
|
||||
<span class="text-muted small">None listed</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span class="text-muted small d-block mb-1">Finance Emails</span>
|
||||
<div class="d-flex flex-wrap gap-1">
|
||||
@if(is_array($operator->finance_emails) && count($operator->finance_emails) > 0)
|
||||
@foreach($operator->finance_emails as $email)
|
||||
<span class="badge bg-secondary bg-opacity-10 text-dark border" style="font-size: 0.75rem;">{{ $email }}</span>
|
||||
@endforeach
|
||||
@else
|
||||
<span class="text-muted small">None listed</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
46
resources/views/vendor/pagination/bootstrap-4.blade.php
vendored
Normal file
46
resources/views/vendor/pagination/bootstrap-4.blade.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
|
||||
<span class="page-link" aria-hidden="true">‹</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev" aria-label="@lang('pagination.previous')">‹</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach ($elements as $element)
|
||||
{{-- "Three Dots" Separator --}}
|
||||
@if (is_string($element))
|
||||
<li class="page-item disabled" aria-disabled="true"><span class="page-link">{{ $element }}</span></li>
|
||||
@endif
|
||||
|
||||
{{-- Array Of Links --}}
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<li class="page-item active" aria-current="page"><span class="page-link">{{ $page }}</span></li>
|
||||
@else
|
||||
<li class="page-item"><a class="page-link" href="{{ $url }}">{{ $page }}</a></li>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next" aria-label="@lang('pagination.next')">›</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
|
||||
<span class="page-link" aria-hidden="true">›</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
80
resources/views/vendor/pagination/bootstrap-5.blade.php
vendored
Normal file
80
resources/views/vendor/pagination/bootstrap-5.blade.php
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav class="d-flex justify-items-center justify-content-between">
|
||||
<div class="d-flex justify-content-between flex-fill d-sm-none">
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">@lang('pagination.previous')</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev">@lang('pagination.previous')</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next">@lang('pagination.next')</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">@lang('pagination.next')</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="d-none flex-sm-fill d-sm-flex align-items-sm-center justify-content-sm-between">
|
||||
<div>
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
|
||||
<span class="page-link" aria-hidden="true">‹</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev" aria-label="@lang('pagination.previous')">‹</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach ($elements as $element)
|
||||
{{-- "Three Dots" Separator --}}
|
||||
@if (is_string($element))
|
||||
<li class="page-item disabled" aria-disabled="true"><span class="page-link">{{ $element }}</span></li>
|
||||
@endif
|
||||
|
||||
{{-- Array Of Links --}}
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<li class="page-item active" aria-current="page"><span class="page-link">{{ $page }}</span></li>
|
||||
@else
|
||||
<li class="page-item"><a class="page-link" href="{{ $url }}">{{ $page }}</a></li>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next" aria-label="@lang('pagination.next')">›</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
|
||||
<span class="page-link" aria-hidden="true">›</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@endif
|
||||
46
resources/views/vendor/pagination/default.blade.php
vendored
Normal file
46
resources/views/vendor/pagination/default.blade.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
|
||||
<span aria-hidden="true">‹</span>
|
||||
</li>
|
||||
@else
|
||||
<li>
|
||||
<a href="{{ $paginator->previousPageUrl() }}" rel="prev" aria-label="@lang('pagination.previous')">‹</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach ($elements as $element)
|
||||
{{-- "Three Dots" Separator --}}
|
||||
@if (is_string($element))
|
||||
<li class="disabled" aria-disabled="true"><span>{{ $element }}</span></li>
|
||||
@endif
|
||||
|
||||
{{-- Array Of Links --}}
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<li class="active" aria-current="page"><span>{{ $page }}</span></li>
|
||||
@else
|
||||
<li><a href="{{ $url }}">{{ $page }}</a></li>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li>
|
||||
<a href="{{ $paginator->nextPageUrl() }}" rel="next" aria-label="@lang('pagination.next')">›</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
|
||||
<span aria-hidden="true">›</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
36
resources/views/vendor/pagination/semantic-ui.blade.php
vendored
Normal file
36
resources/views/vendor/pagination/semantic-ui.blade.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
@if ($paginator->hasPages())
|
||||
<div class="ui pagination menu" role="navigation">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<a class="icon item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')"> <i class="left chevron icon"></i> </a>
|
||||
@else
|
||||
<a class="icon item" href="{{ $paginator->previousPageUrl() }}" rel="prev" aria-label="@lang('pagination.previous')"> <i class="left chevron icon"></i> </a>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach ($elements as $element)
|
||||
{{-- "Three Dots" Separator --}}
|
||||
@if (is_string($element))
|
||||
<a class="icon item disabled" aria-disabled="true">{{ $element }}</a>
|
||||
@endif
|
||||
|
||||
{{-- Array Of Links --}}
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<a class="item active" href="{{ $url }}" aria-current="page">{{ $page }}</a>
|
||||
@else
|
||||
<a class="item" href="{{ $url }}">{{ $page }}</a>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<a class="icon item" href="{{ $paginator->nextPageUrl() }}" rel="next" aria-label="@lang('pagination.next')"> <i class="right chevron icon"></i> </a>
|
||||
@else
|
||||
<a class="icon item disabled" aria-disabled="true" aria-label="@lang('pagination.next')"> <i class="right chevron icon"></i> </a>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
27
resources/views/vendor/pagination/simple-bootstrap-4.blade.php
vendored
Normal file
27
resources/views/vendor/pagination/simple-bootstrap-4.blade.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">@lang('pagination.previous')</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev">@lang('pagination.previous')</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next">@lang('pagination.next')</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">@lang('pagination.next')</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
29
resources/views/vendor/pagination/simple-bootstrap-5.blade.php
vendored
Normal file
29
resources/views/vendor/pagination/simple-bootstrap-5.blade.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav role="navigation" aria-label="Pagination Navigation">
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">{!! __('pagination.previous') !!}</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev">
|
||||
{!! __('pagination.previous') !!}
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next">{!! __('pagination.next') !!}</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">{!! __('pagination.next') !!}</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
19
resources/views/vendor/pagination/simple-default.blade.php
vendored
Normal file
19
resources/views/vendor/pagination/simple-default.blade.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="disabled" aria-disabled="true"><span>@lang('pagination.previous')</span></li>
|
||||
@else
|
||||
<li><a href="{{ $paginator->previousPageUrl() }}" rel="prev">@lang('pagination.previous')</a></li>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li><a href="{{ $paginator->nextPageUrl() }}" rel="next">@lang('pagination.next')</a></li>
|
||||
@else
|
||||
<li class="disabled" aria-disabled="true"><span>@lang('pagination.next')</span></li>
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
25
resources/views/vendor/pagination/simple-tailwind.blade.php
vendored
Normal file
25
resources/views/vendor/pagination/simple-tailwind.blade.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav role="navigation" aria-label="Pagination Navigation" class="flex justify-between">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<span class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md dark:text-gray-600 dark:bg-gray-800 dark:border-gray-600">
|
||||
{!! __('pagination.previous') !!}
|
||||
</span>
|
||||
@else
|
||||
<a href="{{ $paginator->previousPageUrl() }}" rel="prev" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300">
|
||||
{!! __('pagination.previous') !!}
|
||||
</a>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<a href="{{ $paginator->nextPageUrl() }}" rel="next" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300">
|
||||
{!! __('pagination.next') !!}
|
||||
</a>
|
||||
@else
|
||||
<span class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md dark:text-gray-600 dark:bg-gray-800 dark:border-gray-600">
|
||||
{!! __('pagination.next') !!}
|
||||
</span>
|
||||
@endif
|
||||
</nav>
|
||||
@endif
|
||||
106
resources/views/vendor/pagination/tailwind.blade.php
vendored
Normal file
106
resources/views/vendor/pagination/tailwind.blade.php
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav role="navigation" aria-label="{{ __('Pagination Navigation') }}" class="flex items-center justify-between">
|
||||
<div class="flex justify-between flex-1 sm:hidden">
|
||||
@if ($paginator->onFirstPage())
|
||||
<span class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md dark:text-gray-600 dark:bg-gray-800 dark:border-gray-600">
|
||||
{!! __('pagination.previous') !!}
|
||||
</span>
|
||||
@else
|
||||
<a href="{{ $paginator->previousPageUrl() }}" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300">
|
||||
{!! __('pagination.previous') !!}
|
||||
</a>
|
||||
@endif
|
||||
|
||||
@if ($paginator->hasMorePages())
|
||||
<a href="{{ $paginator->nextPageUrl() }}" class="relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300">
|
||||
{!! __('pagination.next') !!}
|
||||
</a>
|
||||
@else
|
||||
<span class="relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md dark:text-gray-600 dark:bg-gray-800 dark:border-gray-600">
|
||||
{!! __('pagination.next') !!}
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
|
||||
<div>
|
||||
<p class="text-sm text-gray-700 leading-5 dark:text-gray-400">
|
||||
{!! __('Showing') !!}
|
||||
@if ($paginator->firstItem())
|
||||
<span class="font-medium">{{ $paginator->firstItem() }}</span>
|
||||
{!! __('to') !!}
|
||||
<span class="font-medium">{{ $paginator->lastItem() }}</span>
|
||||
@else
|
||||
{{ $paginator->count() }}
|
||||
@endif
|
||||
{!! __('of') !!}
|
||||
<span class="font-medium">{{ $paginator->total() }}</span>
|
||||
{!! __('results') !!}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span class="relative z-0 inline-flex rtl:flex-row-reverse shadow-sm rounded-md">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<span aria-disabled="true" aria-label="{{ __('pagination.previous') }}">
|
||||
<span class="relative inline-flex items-center px-2 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default rounded-l-md leading-5 dark:bg-gray-800 dark:border-gray-600" aria-hidden="true">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
@else
|
||||
<a href="{{ $paginator->previousPageUrl() }}" rel="prev" class="relative inline-flex items-center px-2 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-l-md leading-5 hover:text-gray-400 focus:z-10 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:active:bg-gray-700 dark:focus:border-blue-800" aria-label="{{ __('pagination.previous') }}">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</a>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach ($elements as $element)
|
||||
{{-- "Three Dots" Separator --}}
|
||||
@if (is_string($element))
|
||||
<span aria-disabled="true">
|
||||
<span class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 cursor-default leading-5 dark:bg-gray-800 dark:border-gray-600">{{ $element }}</span>
|
||||
</span>
|
||||
@endif
|
||||
|
||||
{{-- Array Of Links --}}
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<span aria-current="page">
|
||||
<span class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 dark:bg-gray-800 dark:border-gray-600">{{ $page }}</span>
|
||||
</span>
|
||||
@else
|
||||
<a href="{{ $url }}" class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 hover:text-gray-500 focus:z-10 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-400 dark:hover:text-gray-300 dark:active:bg-gray-700 dark:focus:border-blue-800" aria-label="{{ __('Go to page :page', ['page' => $page]) }}">
|
||||
{{ $page }}
|
||||
</a>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<a href="{{ $paginator->nextPageUrl() }}" rel="next" class="relative inline-flex items-center px-2 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-r-md leading-5 hover:text-gray-400 focus:z-10 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:active:bg-gray-700 dark:focus:border-blue-800" aria-label="{{ __('pagination.next') }}">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</a>
|
||||
@else
|
||||
<span aria-disabled="true" aria-label="{{ __('pagination.next') }}">
|
||||
<span class="relative inline-flex items-center px-2 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default rounded-r-md leading-5 dark:bg-gray-800 dark:border-gray-600" aria-hidden="true">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@endif
|
||||
@@ -14,32 +14,28 @@ Route::middleware(['auth'])->group(function () {
|
||||
|
||||
Route::get('/', [App\Http\Controllers\DashboardController::class, 'index'])->name('home');
|
||||
Route::get('home', [App\Http\Controllers\DashboardController::class, 'index'])->name('home');
|
||||
|
||||
// Route::get('/clients', [App\Http\Controllers\ClientsController::class, 'index'])->name('clients.index');
|
||||
#Clients
|
||||
Route::get('/clients/data', [App\Http\Controllers\ClientsController::class, 'fetchData'])->name('clients.data');
|
||||
Route::get('/clients/export', [App\Http\Controllers\ClientController::class, 'export'])->name('clients.export');
|
||||
|
||||
// {{ route('shortcodes.store') }}
|
||||
// {{ route('client-payments.store') }}
|
||||
// {{ route('client-files.store') }}
|
||||
// Route::post('/shortcodes', [App\Http\Controllers\ShortCodesController::class, 'store'])->name('shortcodes.store');
|
||||
Route::get('/clients/{id}/json', [App\Http\Controllers\ClientsController::class, 'getClientJson']);
|
||||
Route::put('/clients/{id}', [App\Http\Controllers\ClientsController::class, 'update'])->name('clients.update');
|
||||
Route::post('/clients/shortcodes-store', [App\Http\Controllers\ClientsController::class, 'shortcodeStore'])->name('shortcodes.store');
|
||||
Route::post('/clients/payments-store', [App\Http\Controllers\ClientsController::class, 'paymentsStore'])->name('client-payments.store');
|
||||
Route::post('/clients/files-store', [App\Http\Controllers\ClientsController::class, 'storeDocument'])->name('client-files.store');
|
||||
|
||||
Route::post('/clients/notes-store', [App\Http\Controllers\ClientsController::class, 'storeNote'])->name('client-notes.store');
|
||||
|
||||
|
||||
|
||||
Route::get('/client-files/download/{id}', [App\Http\Controllers\ClientsController::class, 'clientFiledownload'])->name('client-files.download');
|
||||
Route::resource('clients', App\Http\Controllers\ClientsController::class);
|
||||
|
||||
|
||||
#MNOs mnos.store
|
||||
Route::get('/mnos/{id}', [App\Http\Controllers\NetworkOperatorsController::class, 'show'])->name('mnos.show');
|
||||
Route::get('/mnos', [App\Http\Controllers\NetworkOperatorsController::class, 'index'])->name('mnos.index');
|
||||
Route::post('/mnos', [App\Http\Controllers\NetworkOperatorsController::class, 'store'])->name('mnos.store');
|
||||
Route::get('/mnos/{id}/json', [App\Http\Controllers\NetworkOperatorsController::class, 'getJson']);
|
||||
Route::put('/mnos/{id}', [App\Http\Controllers\NetworkOperatorsController::class, 'update'])->name('mnos.update');
|
||||
|
||||
Route::get('/staff', [App\Http\Controllers\StaffController::class, 'index'])->name('home');
|
||||
|
||||
|
||||
Route::get('/mnos', [App\Http\Controllers\NetworkOperatorsControlle::class, 'index'])->name('mnos.index');
|
||||
Route::get('/documents', [App\Http\Controllers\DocumentsVaultController::class, 'index'])->name('documents.index');
|
||||
|
||||
Route::get('/senderids', [App\Http\Controllers\SenderidsController::class, 'index']);
|
||||
|
||||
87
scratch.md
Normal file
87
scratch.md
Normal file
@@ -0,0 +1,87 @@
|
||||
`name` varchar(200) NOT NULL DEFAULT '',
|
||||
`country` varchar(200) NOT NULL DEFAULT '',
|
||||
`contact_person` varchar(191) DEFAULT NULL,
|
||||
`contact_person_phone` varchar(25) DEFAULT NULL,
|
||||
`contact_person_email` varchar(191) DEFAULT NULL,
|
||||
|
||||
`support_emails` text DEFAULT NULL,
|
||||
`finance_emails` text DEFAULT NULL,
|
||||
`support_skype` text DEFAULT NULL,
|
||||
|
||||
`technical_support_person` varchar(191) DEFAULT NULL,
|
||||
`services` text DEFAULT NULL,
|
||||
`buying_rate` decimal(10,4) DEFAULT 0.0000,
|
||||
`rate_type` varchar(20) DEFAULT NULL,
|
||||
`payment_terms` varchar(20) DEFAULT NULL,
|
||||
`sliding_rate_file` text DEFAULT NULL,
|
||||
`connection_status` varchar(70) DEFAULT NULL,
|
||||
`connection_type` text DEFAULT NULL,
|
||||
`integration_type` text DEFAULT NULL,
|
||||
`bind_specifics` text DEFAULT NULL,
|
||||
`account_manager_id` int(11) DEFAULT NULL,
|
||||
`mno_account_manager` varchar(191) DEFAULT NULL,
|
||||
`contract_auto_renew` varchar(15) DEFAULT NULL,
|
||||
`contract_validity` varchar(191) DEFAULT NULL,
|
||||
`direct_business` varchar(10) DEFAULT 'YES',
|
||||
|
||||
@php
|
||||
function renderBadges($jsonString, $type = 'email') {
|
||||
$items = json_decode($jsonString, true) ?? [];
|
||||
if(count($items) === 0) return '<span class="text-muted small">N/A</span>';
|
||||
$html = '';
|
||||
foreach($items as $item) {
|
||||
$icon = $type == 'email' ? 'bi-envelope' : 'bi-telephone';
|
||||
$html .= '<span class="badge bg-light text-dark border me-1 mb-1"><i class="bi '.$icon.' text-secondary me-1"></i>'.$item.'</span>';
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
@endphp
|
||||
|
||||
@php
|
||||
$services = json_decode($showclient->services, true) ?? [];
|
||||
@endphp
|
||||
|
||||
@php
|
||||
$msgTypes = json_decode($showclient->message_types, true) ?? [];
|
||||
@endphp
|
||||
|
||||
{!! renderBadges($showclient->finance_email, 'email') !!}
|
||||
<div>{!! renderBadges($showclient->finance_email, 'email') !!}</div>
|
||||
{!! renderBadges($showclient->support_emails, 'email') !!}</div>
|
||||
<div>{!! renderBadges($showclient->rate_emails, 'email') !!}</div>
|
||||
<div>{!! renderBadges($showclient->support_phones, 'phone') !!}</div>
|
||||
|
||||
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="text-muted small mb-1">Finance Emails</div>
|
||||
@if($showclient->finance_email !== null || $showclient->finance_email !== "")
|
||||
<div><?php dump($showclient->finance_email) ?></div>
|
||||
<div>{!! renderBadges($showclient->finance_email, 'email') !!}</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="text-muted small mb-1">Support Emails</div>
|
||||
@if($showclient->support_emails !== null)
|
||||
<div>{!! renderBadges($showclient->support_emails, 'email') !!}</div>
|
||||
<div><?php dump($showclient->support_emails) ?></div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="text-muted small mb-1">Rate Emails</div>
|
||||
@if($showclient->rate_emails !== null)
|
||||
<div><?php dump($showclient->rate_emails) ?></div>
|
||||
<div>{!! renderBadges($showclient->rate_emails, 'email') !!}</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mb-0">
|
||||
<div class="text-muted small mb-1">Support Phones</div>
|
||||
@if($showclient->support_phones !== null)
|
||||
<div><?php dump($showclient->support_phones) ?></div>
|
||||
<div>{!! renderBadges($showclient->support_phones, 'phone') !!}</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user