added cpanel api

This commit is contained in:
abdul-wahab12345 2024-06-28 06:58:04 +00:00
parent 804e880331
commit 1760c7e0aa
16 changed files with 383 additions and 56 deletions

View File

@ -6,6 +6,50 @@
use App\Models\Response; use App\Models\Response;
use App\Models\TicketNote; use App\Models\TicketNote;
use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Session;
use Mailgun\Mailgun;
use App\Models\Company;
function get_company($key,$value){
return Company::where($key,$value)->first();
}
function get_current_company_tickets($args = []){
$companyId = getSelectedCompany();
if(!$companyId){
return false;
}
$company = get_company('id',$companyId);
if(!$company){
return false;
}
$tickets = Ticket::where('to_email', $company->email);
if(isset($args['type'])){
$tickets->where('type',$args['type']);
}
if(isset($args['status'])){
$tickets->where('status',$args['status']);
}
if(isset($args['orderby'])){
$tickets->orderBy($args['orderby'],$args['order']??'asc');
}
if(isset($args['with'])){
$tickets->with($args['with']);
}
$tickets = $tickets->get();
return $tickets;
}
function getResponse($company_id, $key, $type) { function getResponse($company_id, $key, $type) {
$meta = CompanyMeta::where('company_id', $company_id)->where('key', $key)->where('type', $type)->first(); $meta = CompanyMeta::where('company_id', $company_id)->where('key', $key)->where('type', $type)->first();
@ -70,7 +114,7 @@ function insertTicket($from_email, $to_email, $subject, $content, $type, $sender
function getSelectedCompany() { function getSelectedCompany() {
$company = Session::get('selected_company'); $company = Session::get('selected_company');
if (!$company) { if (!$company) {
return response()->json(['message' => 'Company not found'], 404); return false;
} }
return $company; return $company;
} }
@ -110,3 +154,44 @@ function containsHtml($string) {
return $string != strip_tags($string); return $string != strip_tags($string);
} }
} }
if (!function_exists('sendEmailViaMailgun')) {
function sendEmailViaMailgun( $domain, $from, $to, $subject, $html) {
$apiKey = env('MAILGUN_SECRET');
// Create a new Mailgun instance with API credentials
$mg = Mailgun::create($apiKey);
// Prepare the message parameters
$params = [
'from' => $from,
'to' => $to,
'subject' => $subject,
'html' => $html
];
// Send the email
$response = $mg->messages()->send($domain, $params);
// Return the response from Mailgun
return $response;
}
function createResponse($ticket_id, $message, $user_id = 0)
{
// Create a new Response instance
$response = new Response;
// Set the properties of the Response
$response->message = $message;
$response->ticket_id = $ticket_id;
$response->user_id = $user_id; // You may want to dynamically set the user_id based on the authenticated user
// Save the response to the database
$response->save();
// Return the created response
return $response;
}
}

View File

@ -13,19 +13,15 @@ class DashboardController extends Controller
{ {
public function dashboard() public function dashboard()
{ {
$companyId = Session::get('selected_company');
$company = Company::find($companyId); $tickets = get_current_company_tickets(['type' => 'inbox']);
$tickets = Ticket::where('type', 'inbox')
->where('to_email', 'LIKE', '%' . $company->domain)
->get();
return view('index', ['tickets' => $tickets]); return view('index', ['tickets' => $tickets]);
} }
public function waiting() public function waiting()
{ {
$companyId = Session::get('selected_company');
$company = Company::find($companyId); $tickets = get_current_company_tickets(['status' => 'waiting']);
$tickets = Ticket::where('status', 'waiting')->where('type', 'chat')->where('to_email', 'LIKE', '%' . $company->domain)->get();
return view('waiting', ['tickets' => $tickets]); return view('waiting', ['tickets' => $tickets]);
} }

View File

@ -309,8 +309,18 @@ public function deleteSpamHandling($index)
public function inbox() public function inbox()
{ {
$tickets = Ticket::orderBy('id', 'desc')->with('lastResponse')->get(); $tickets = get_current_company_tickets([
'type' => 'inbox',
'orderby' => 'id',
'order' => 'desc',
'with' => 'lastResponse'
]);
$messages = []; $messages = [];
return view('inbox', ['tickets' => $tickets, 'messages' => $messages]); return view('inbox', ['tickets' => $tickets, 'messages' => $messages]);
} }

View File

@ -4,31 +4,55 @@
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class EmailController extends Controller class EmailController extends Controller
{ {
public function saveEmail(Request $request){ public function saveEmail(Request $request){
DB::beginTransaction();
try {
$token = $request->input('token'); $token = $request->input('token');
$timestamp = $request->input('timestamp'); $timestamp = $request->input('timestamp');
$signature = $request->input('signature'); $signature = $request->input('signature');
// if (!verifyMailgunSignature($token, $timestamp, $signature)) { if (!verifyMailgunSignature($token, $timestamp, $signature)) {
// abort(403, 'Invalid signature.'); update_setting('aw_test','Invalid signature.');
// } abort(403, 'Invalid signature.');
}
$data = $this->extractMailgunData($request->all()); $data = $this->extractMailgunData($request->all());
insertTicket($data['from_email'], $data['to_email'], $data['subject'], $data['message'] );
update_setting('aw_test',json_encode($request->all()));
$to_email = $data['to_email'];
$message = $data['message'];
update_setting('aw_test',$to_email);
$company = get_company('email',$to_email);
if($company){
$ticket = insertTicket($data['from_email'], $data['to_email'], $data['subject'], $message,'inbox',$data['from_name'] );
if($ticket)
$response = createResponse($ticket->id,$message);
}else{}
// update_setting('aw_test',json_encode($request->all()));
DB::commit();
} catch (\Exception $e) {
update_setting('aw_test',$e->getMessage());
DB::rollBack();
// Handle the exception
}
} }
public function extractMailgunData($data) { public function extractMailgunData($data) {
// Decode the JSON payload into an associative array
// $data = json_decode($jsonPayload, true);
// Prepare an array to hold the extracted data // Prepare an array to hold the extracted data
$extractedData = [ $extractedData = [

View File

@ -5,6 +5,8 @@
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Services\MailgunService; use App\Services\MailgunService;
use Illuminate\Support\Str;
use App\Services\CPanelApiService;
class MailgunController extends Controller class MailgunController extends Controller
{ {
@ -69,6 +71,18 @@ public function verifyDomain(Request $request)
}elseif($state == 'active'){ }elseif($state == 'active'){
$this->createRoute($request); $this->createRoute($request);
$email = "kundesone.$domain@kundesone.no";
$this->createEmail($domain,$email);
$company = get_company('domain',$domain);
if($company){
$company->internal_email = $email;
$company->save();
}
return $email;
return redirect('/dashboard'); return redirect('/dashboard');
} }
@ -81,6 +95,23 @@ public function createRoute(Request $request)
$response = $this->mailgunService->createRoute($domain, $forwardUrl); $response = $this->mailgunService->createRoute($domain, $forwardUrl);
return $response; return $response;
} }
public function createEmail($domain,$email){
$password = Str::random(12);
$quota = 0;
$response = $this->cpanelApiService->createEmailAccount($domain, $email, $password, $quota);
if (isset($response['error'])) {
return false;
}
return $email;
}
} }

View File

@ -6,22 +6,27 @@
use App\Models\Ticket; use App\Models\Ticket;
use App\Models\Comment; use App\Models\Comment;
use App\Models\Response; use App\Models\Response;
use App\Models\Company;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Support\Facades\Session;
class TicketController extends Controller class TicketController extends Controller
{ {
public function allTickets() public function allTickets()
{ {
$tickets = Ticket::all(); $tickets = get_current_company_tickets();
return view('all-tickets', ['tickets' => $tickets]); return view('all-tickets', ['tickets' => $tickets]);
} }
public function storeResponse(Request $request) public function storeResponse(Request $request)
{ {
$this->validate($request, [ $this->validate($request, [
'message' => 'required' 'message' => 'required' ,
'ticket_id' => 'required' ,
]); ]);
$ticket_id = $request->ticket_id;
// Load the HTML content into DOMDocument // Load the HTML content into DOMDocument
$dom = new \DOMDocument(); $dom = new \DOMDocument();
libxml_use_internal_errors(true); // Prevents HTML errors from being thrown as exceptions libxml_use_internal_errors(true); // Prevents HTML errors from being thrown as exceptions
@ -40,11 +45,21 @@ public function storeResponse(Request $request)
// Save the modified HTML // Save the modified HTML
$messageWithClasses = $dom->saveHTML($dom->documentElement); $messageWithClasses = $dom->saveHTML($dom->documentElement);
$response = new Response; // create response
$response->message = $messageWithClasses; $response = createResponse($ticket_id,$messageWithClasses,1);
$response->ticket_id = $request->ticket_id;
$response->user_id = 1; $ticket = Ticket::find($ticket_id);
$response->save(); $companyId = Session::get('selected_company');
$company = get_company('id',$companyId);
//Send mail to mailgun
$domain = $company->domain;
$from = $company->email;
$to = $ticket->from_email;
$subject = $ticket->subject;
$html = $request->message;
sendEmailViaMailgun($domain, $from, $to, $subject, $html);
// Return the updated response and time // Return the updated response and time
return response()->json([ return response()->json([
@ -85,4 +100,12 @@ public function storeComment(Request $request)
return $comment; return $comment;
} }
public function deleteComment($commentId)
{
$comment = Comment::findOrFail($commentId);
$comment->delete();
return response()->json(['message' => 'Comment Deleted Successfully']);
}
} }

View File

@ -0,0 +1,50 @@
<?php
// app/Services/CPanelApiService.php
namespace App\Services;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
class CPanelApiService
{
protected $client;
protected $cpanelUrl;
protected $cpanelUsername;
protected $cpanelToken;
public function __construct()
{
$this->cpanelUrl = env('CPANEL_URL');
$this->cpanelUsername = env('CPANEL_USERNAME');
$this->cpanelToken = env('CPANEL_TOKEN');
$this->client = new Client([
'base_uri' => $this->cpanelUrl,
'headers' => [
'Authorization' => 'cpanel ' . $this->cpanelUsername . ':' . $this->cpanelToken
]
]);
}
public function createEmailAccount($domain, $email, $password, $quota)
{
$query = [
'cpanel_jsonapi_user' => $this->cpanelUsername,
'cpanel_jsonapi_apiversion' => '2',
'cpanel_jsonapi_module' => 'Email',
'cpanel_jsonapi_func' => 'addpop',
'domain' => $domain,
'email' => $email,
'password' => $password,
'quota' => $quota
];
try {
$response = $this->client->request('GET', '/json-api/cpanel', ['query' => $query]);
return json_decode($response->getBody(), true);
} catch (GuzzleException $e) {
return ['error' => $e->getMessage()];
}
}
}

View File

@ -6,7 +6,7 @@
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": "^8.1", "php": "^8.1",
"guzzlehttp/guzzle": "^7.2", "guzzlehttp/guzzle": "^7.8",
"laravel/framework": "^10.10", "laravel/framework": "^10.10",
"laravel/sanctum": "^3.3", "laravel/sanctum": "^3.3",
"laravel/tinker": "^2.8", "laravel/tinker": "^2.8",

2
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "e3f9f69a248021a08a4b420d64573db7", "content-hash": "3427d1f055fffcf2c0867d5d8137c3f3",
"packages": [ "packages": [
{ {
"name": "brick/math", "name": "brick/math",

View File

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('companies', function (Blueprint $table) {
$table->string('internal_email')->default('');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('companies', function (Blueprint $table) {
//
});
}
};

View File

@ -30,3 +30,8 @@
[26-Jun-2024 04:05:49 UTC] PHP Warning: Module "fileinfo" is already loaded in Unknown on line 0 [26-Jun-2024 04:05:49 UTC] PHP Warning: Module "fileinfo" is already loaded in Unknown on line 0
[26-Jun-2024 11:15:17 UTC] PHP Warning: Module "fileinfo" is already loaded in Unknown on line 0 [26-Jun-2024 11:15:17 UTC] PHP Warning: Module "fileinfo" is already loaded in Unknown on line 0
[26-Jun-2024 11:31:01 UTC] PHP Warning: Module "fileinfo" is already loaded in Unknown on line 0 [26-Jun-2024 11:31:01 UTC] PHP Warning: Module "fileinfo" is already loaded in Unknown on line 0
[28-Jun-2024 06:04:29 UTC] PHP Warning: Module "fileinfo" is already loaded in Unknown on line 0
[28-Jun-2024 06:04:33 UTC] PHP Warning: Module "fileinfo" is already loaded in Unknown on line 0
[28-Jun-2024 06:04:34 UTC] PHP Warning: Module "fileinfo" is already loaded in Unknown on line 0
[28-Jun-2024 06:18:54 UTC] PHP Warning: Module "fileinfo" is already loaded in Unknown on line 0
[28-Jun-2024 06:20:52 UTC] PHP Warning: Module "fileinfo" is already loaded in Unknown on line 0

View File

@ -4,7 +4,7 @@
<div class="dev-toggle-sidebar"> <div class="dev-toggle-sidebar">
<img src="{{ asset('images/icons/blocks-icon.svg') }}"> <img src="{{ asset('images/icons/blocks-icon.svg') }}">
</div> </div>
<h2 class="d-flex align-items-center">Hello Maxwell <span>👋🏼</span>,</h2> <h2 class="d-flex align-items-center">Hello {{auth()->user()->name}} <span>👋🏼</span>,</h2>
</div> </div>
<div class="col-sm-8 d-flex justify-content-end align-items-center"> <div class="col-sm-8 d-flex justify-content-end align-items-center">
<div class="search-box d-flex align-items-center"> <div class="search-box d-flex align-items-center">

View File

@ -186,9 +186,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
title.</span> title.</span>
</div> </div>
</div> </div>
@if(Auth::user()->role_id == 2)
<button type="submit" class="dev-form-submit-btn">Save</button> <button type="submit" class="dev-form-submit-btn">Save</button>
@endif
</form> </form>
</div> </div>
</div> </div>
@ -420,9 +418,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
</div> </div>
</div> </div>
</form> </form>
@if(Auth::user()->role_id == 2)
<button type="submit" class="dev-form-submit-btn">Save</button> <button type="submit" class="dev-form-submit-btn">Save</button>
@endif
</div> </div>
</form> </form>
</div> </div>
@ -471,15 +467,13 @@ function toggleClosed(day) {
@csrf @csrf
<div class="dev-input-group dev-input-group-input-info"> <div class="dev-input-group dev-input-group-input-info">
<label>Name</label> <label>Name</label>
<input name="name" type="text" placeholder="Type here" value="{{ $canned_response[0]['value'] ?? '' }}" required> <input name="name" type="text" placeholder="Type here" required>
</div> </div>
<div class="dev-input-group dev-input-group-input-info"> <div class="dev-input-group dev-input-group-input-info">
<label>Text</label> <label>Text</label>
<textarea name="text" required rows="6">{{ $canned_response[1]['value'] ?? '' }}</textarea> <textarea name="text" required rows="6"></textarea>
</div> </div>
@if(Auth::user()->role_id == 2)
<button type="submit" class="dev-form-submit-btn">Save</button> <button type="submit" class="dev-form-submit-btn">Save</button>
@endif
</form> </form>
</div> </div>
</div> </div>
@ -487,6 +481,7 @@ function toggleClosed(day) {
<div class="dev-title-row"> <div class="dev-title-row">
<h2>Canned responses</h2> <h2>Canned responses</h2>
<div class="dev-users-boxs"> <div class="dev-users-boxs">
@if(!is_null($canned_response))
@foreach(json_decode($canned_response->value) as $index => $values) @foreach(json_decode($canned_response->value) as $index => $values)
<div class="dev-users-box"> <div class="dev-users-box">
<div class="dev-box"> <div class="dev-box">
@ -497,10 +492,11 @@ function toggleClosed(day) {
<img src="{{ asset('images/settingss.svg') }}" alt=""> <img src="{{ asset('images/settingss.svg') }}" alt="">
</div> </div>
<div class="dev-icon"> <div class="dev-icon">
<a href="{{ route('delete.canned.response', $index) }}" class="delete-user"><img src="{{ asset('images/binn.svg') }}" alt=""></a> <a style="cursor:pointer;" href="{{ route('delete.canned.response', $index) }}" class="delete-user"><img src="{{ asset('images/binn.svg') }}" alt=""></a>
</div> </div>
</div> </div>
@endforeach @endforeach
@endif
</div> </div>
</div> </div>
</div> </div>
@ -865,6 +861,7 @@ class="form-control input-reply-textarea">{!! $automatic_reply_text->value ?? ''
<h2>Email addresses that never should be marked as spam<br> <h2>Email addresses that never should be marked as spam<br>
Blocked email addresses</h2> Blocked email addresses</h2>
<div class="dev-users-boxs"> <div class="dev-users-boxs">
@if(!is_null($spam_handling))
@foreach(json_decode($spam_handling->value) as $index => $values) @foreach(json_decode($spam_handling->value) as $index => $values)
<div class="dev-users-box"> <div class="dev-users-box">
<div class="dev-box"> <div class="dev-box">
@ -875,14 +872,46 @@ class="form-control input-reply-textarea">{!! $automatic_reply_text->value ?? ''
<img src="{{ asset('images/settingss.svg') }}" alt=""> <img src="{{ asset('images/settingss.svg') }}" alt="">
</div> </div>
<div class="dev-icon"> <div class="dev-icon">
<a href="{{ route('delete.spam.handling', $index) }}" class="delete-user"><img src="{{ asset('images/binn.svg') }}" alt=""></a> <a href="{{ route('delete.spam.handling', $index) }}" style="cursor:pointer;" class="delete-user"><img src="{{ asset('images/binn.svg') }}" alt=""></a>
</div> </div>
</div> </div>
@endforeach @endforeach
@endif
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@10"></script>
<script defer>
document.addEventListener('DOMContentLoaded', function () {
const deleteLinks = document.querySelectorAll('.delete-user');
deleteLinks.forEach(function (link) {
link.addEventListener('click', function (event) {
event.preventDefault(); // Prevent the default link click behavior
const url = this.href;
Swal.fire({
title: 'Are you sure?',
text: "You won't be able to revert this!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
}).then((result) => {
if (result.isConfirmed) {
// If the user confirms, redirect to the delete URL
window.location.href = url;
}
});
});
});
});
</script>
<!-- --> <!-- -->
<div class="dev-tabcontent dev-tabcontent-tags"> <div class="dev-tabcontent dev-tabcontent-tags">
<div class="dev-tabcontent-outers"> <div class="dev-tabcontent-outers">

View File

@ -103,7 +103,7 @@ class="side-bar-link bg-light-color d-flex align-items-center justify-content-be
<div class="dev-toggle-sidebar"> <div class="dev-toggle-sidebar">
<img src="{{ asset('images/icons/blocks-icon.svg') }}"> <img src="{{ asset('images/icons/blocks-icon.svg') }}">
</div> </div>
<h2 class="d-flex align-items-center">Hello Maxwell <span>👋🏼</span>,</h2> <h2 class="d-flex align-items-center">Hello {{auth()->user()->name}} <span>👋🏼</span>,</h2>
</div> </div>
<div class="col-sm-8 d-flex justify-content-end align-items-center"> <div class="col-sm-8 d-flex justify-content-end align-items-center">
<div class="search-box d-flex align-items-center"> <div class="search-box d-flex align-items-center">

View File

@ -61,7 +61,7 @@ class="ui button comment--btn bg-dark-green-color color-light comment-edit-btn "
<i class="edit outline icon"></i> <i class="edit outline icon"></i>
</button> </button>
<button <button
class="ui button comment--btn bg-light-green-color color-light comment-delete-btn"> class="ui button comment--btn bg-light-green-color color-light comment-delete-btn" data-comment-id="{{ $comment->id }}">
<i class="trash alternate outline icon"></i> <i class="trash alternate outline icon"></i>
</button> </button>
</div> </div>
@ -80,6 +80,50 @@ class="ui button comment--btn bg-light-green-color color-light comment-delete-bt
</ul> </ul>
</div> </div>
<!--delete Comment-->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
$(document).ready(function() {
$('.comment-delete-btn').on('click', function() {
var commentId = $(this).data('comment-id');
var commentElement = $(this).closest('.response-comment');
// SweetAlert confirmation dialog
Swal.fire({
title: 'Are you sure?',
text: "You won't be able to revert this!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
}).then((result) => {
if (result.isConfirmed) {
$.ajax({
url: '/delete-comment/' + commentId,
method: 'GET',
data: {
_token: '{{ csrf_token() }}'
},
success: function(response) {
toastr.success("Comment Deleted Successfully");
commentElement.remove();
},
error: function(error) {
console.error('Error deleting comment:', error);
Swal.fire(
'Error!',
'An error occurred while deleting the comment.',
'error'
);
}
});
}
});
});
});
</script>
<!--store comment--> <!--store comment-->
<script> <script>
$(document).ready(function() { $(document).ready(function() {
@ -101,9 +145,18 @@ class="ui button comment--btn bg-light-green-color color-light comment-delete-bt
_token: '{{ csrf_token() }}' _token: '{{ csrf_token() }}'
}, },
success: function(response) { success: function(response) {
$('.accordion-body--custom').prepend(response);
toastr.success("Comment Added Successfully"); toastr.success("Comment Added Successfully");
$('.input-comment-textarea').val(''); $('.input-comment-textarea').val('');
$.ajax({
url: '/fetch-action-box/' + ticketId,
method: 'GET',
success: function(response) {
$('.action-box').html(response);
},
error: function(error) {
console.log('Error fetching action box content:', error);
}
});
}, },
error: function(error) { error: function(error) {
console.error('Error adding comment:', error); console.error('Error adding comment:', error);
@ -116,35 +169,27 @@ class="ui button comment--btn bg-light-green-color color-light comment-delete-bt
<!--change ticket status--> <!--change ticket status-->
<script> <script>
$(document).ready(function() { $(document).ready(function() {
// Click event for status buttons
$('.status-btn').on('click', function() { $('.status-btn').on('click', function() {
var newStatus = $(this).data('status'); var newStatus = $(this).data('status');
// Update UI immediately
$('.status-btn').removeClass('active'); $('.status-btn').removeClass('active');
$(this).addClass('active'); $(this).addClass('active');
// Optionally, update backend via AJAX
updateTicketStatus(newStatus); updateTicketStatus(newStatus);
}); });
// Function to update ticket status via AJAX
function updateTicketStatus(newStatus) { function updateTicketStatus(newStatus) {
// Example AJAX request
$.ajax({ $.ajax({
url: 'update-ticket-status/{{ $ticket->id }}', // Replace with your route url: 'update-ticket-status/{{ $ticket->id }}',
method: 'POST', method: 'POST',
data: { data: {
status: newStatus, status: newStatus,
_token: '{{ csrf_token() }}' _token: '{{ csrf_token() }}'
}, },
success: function(response) { success: function(response) {
// Handle success response if needed
toastr.success(response.message); toastr.success(response.message);
}, },
error: function(error) { error: function(error) {
console.error('Error updating ticket status:', error); console.error('Error updating ticket status:', error);
// Optionally handle error response
} }
}); });
} }

View File

@ -48,6 +48,7 @@
Route::get('/inbox-setting', [InboxController::class, 'inboxSetting'])->name('inbox.setting'); Route::get('/inbox-setting', [InboxController::class, 'inboxSetting'])->name('inbox.setting');
Route::post('update-ticket-status/{ticketId}', [TicketController::class, 'updateStatus']); Route::post('update-ticket-status/{ticketId}', [TicketController::class, 'updateStatus']);
Route::post('store-comment', [TicketController::class, 'storeComment']); Route::post('store-comment', [TicketController::class, 'storeComment']);
Route::get('delete-comment/{commentId}', [TicketController::class, 'deleteComment']);
Route::post('store/response', [TicketController::class, 'storeResponse'])->name('store.response'); Route::post('store/response', [TicketController::class, 'storeResponse'])->name('store.response');
//Basic Setting Route //Basic Setting Route
Route::post('inbox/basic-setting', [InboxController::class, 'basicSetting'])->name('inbox.basic.setting'); Route::post('inbox/basic-setting', [InboxController::class, 'basicSetting'])->name('inbox.basic.setting');