diff --git a/accounts.md b/accounts.md index 8eabd59..8641611 100644 --- a/accounts.md +++ b/accounts.md @@ -1,2 +1,14 @@ ## Details -- kwesi@click-mobile.com/frantic@300 \ No newline at end of file +- kwesi@click-mobile.com/frantic@300 + + + +MAIL_DRIVER=smtp +MAIL_HOST=smtp.office365.com +MAIL_PORT=587 +MAIL_USERNAME=alerts@click-mobile.com +MAIL_PASSWORD=K$286565586884an +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=null +MAIL_FROM_NAME="${APP_NAME}" +MAIL_FROM_ADDRESS="no-reply@click-mobile.com" diff --git a/app/Http/Controllers/ClientsController.php b/app/Http/Controllers/ClientsController.php index 8668532..012deac 100644 --- a/app/Http/Controllers/ClientsController.php +++ b/app/Http/Controllers/ClientsController.php @@ -830,6 +830,64 @@ class ClientsController extends Controller return response()->json(['message' => 'Note added successfully!']); } + public function update_notes(Request $request, $id) + { + $note = ClientNote::findOrFail($id); + + // Optional: Double-check the 2-day rule on the backend for security + if ($note->created_at->diffInDays(now()) > 2) { + return response()->json(['errors' => ['Cannot edit notes older than 2 days.']], 403); + } + + $note->update([ + 'notes_body' => $request->notes_body, + ]); + + return response()->json(['success' => true, 'message' => 'Note updated successfully!']); + } + + public function update_short_code(Request $request, $id) + { + // Validate the inputs based on the fields in your edit modal + $validated = $request->validate([ + 'code_type' => 'required|string', + 'shortcode' => 'required|string', + 'network' => 'required|string', + 'status' => 'required|string', + 'expiry_date' => 'nullable|date', + 'remarks' => 'nullable|string', + ]); + + // Find the record and update it + $shortcode = ShortCode::findOrFail($id); // Adjust 'ShortCode' to your actual model name + $shortcode->update($validated); + + // Return the JSON response for SweetAlert + return response()->json([ + 'success' => true, + 'message' => 'Short code updated successfully!' + ]); + } + public function update_payment(Request $request, $id) + { + // Validate the inputs based on the fields in your edit modal + $validated = $request->validate([ + 'invoice_number' => 'required|string', + 'invoice_amount' => 'required|numeric', + 'invoice_date' => 'required|date', + 'invoice_status' => 'required|string', + ]); + + // Find the record and update it + $payment = ClientPayment::findOrFail($id); // Adjust 'ClientPayment' to your actual model name + $payment->update($validated); + + // Return the JSON response for SweetAlert + return response()->json([ + 'success' => true, + 'message' => 'Payment record updated successfully!' + ]); + } diff --git a/app/Http/Controllers/OtpController.php b/app/Http/Controllers/OtpController.php index 4bc1589..99b6f3d 100644 --- a/app/Http/Controllers/OtpController.php +++ b/app/Http/Controllers/OtpController.php @@ -4,7 +4,11 @@ namespace App\Http\Controllers; use App\Models\StaffMember; use Illuminate\Http\Request; +use App\Mail\LoginOtpMail; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Hash; +use Illuminate\Support\Facades\Mail; +use Illuminate\Support\Facades\Log; class OtpController extends Controller { diff --git a/public/assets/js/client-show-modal.js b/public/assets/js/client-show-modal.js index 861a1a7..8a3d4d9 100644 --- a/public/assets/js/client-show-modal.js +++ b/public/assets/js/client-show-modal.js @@ -8,7 +8,8 @@ document.addEventListener("DOMContentLoaded", function() { // Generic AJAX handler for standard forms (Shortcodes & Payments) - $(document).on('submit', '#shortcodeForm, #paymentForm, #noteForm', function(e) { + // $(document).on('submit', '#shortcodeForm, #paymentForm, #noteForm', function(e) { + $(document).on('submit', '#shortcodeForm, #paymentForm, #noteForm, #editNoteForm, #editShortcodeForm, #editPaymentForm', function(e) { e.preventDefault(); let $form = $(this); @@ -378,5 +379,100 @@ document.addEventListener("DOMContentLoaded", function() { } }); }); - }); + + + + // Confirm and Delete Note + $(document).on('click', '.delete-note-btn', function() { + let id = $(this).data('id'); + if(confirm("Are you sure you want to delete this note? This action cannot be undone.")) { + // Send AJAX DELETE request using the meta tag for CSRF + $.ajax({ + url: `/notes/${id}`, + type: 'DELETE', + headers: { + 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') + }, + success: function(res) { + location.reload(); + } + }); + } + }); + + // Confirm and Delete Short Code + $(document).on('click', '.delete-shortcode-btn', function() { + let id = $(this).data('id'); + if(confirm("Are you sure you want to delete this short code?")) { + $.ajax({ + url: `/shortcodes/${id}`, + type: 'DELETE', + headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }, + success: function(res) { location.reload(); } + }); + } + }); + + // Confirm and Delete Payment + $(document).on('click', '.delete-payment-btn', function() { + let id = $(this).data('id'); + if(confirm("Are you sure you want to delete this payment record?")) { + $.ajax({ + url: `/payments/${id}`, + type: 'DELETE', + headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }, + success: function(res) { location.reload(); } + }); + } + }); + + // --- POPULATE NOTE EDIT MODAL --- + $(document).on('click', '.edit-note-btn', function() { + let id = $(this).data('id'); + let body = $(this).closest('.list-group-item').find('p').text(); + + $('#edit_note_id').val(id); + $('#edit_note_body').val(body); + + $('#editNoteForm').attr('action', `/notes/${id}`); + + // Replaced vanilla JS with jQuery modal show + $('#editNoteModal').modal('show'); + }); + + // --- POPULATE SHORT CODE EDIT MODAL --- + $(document).on('click', '.edit-shortcode-btn', function() { + let id = $(this).data('id'); + + $('#edit_shortcode_id').val(id); + $('#edit_sc_type').val($(this).data('type')); + $('#edit_sc_code').val($(this).data('code')); + $('#edit_sc_network').val($(this).data('network')); + $('#edit_sc_status').val($(this).data('status')); + $('#edit_sc_expiry').val($(this).data('expiry')); + $('#edit_sc_remarks').val($(this).data('remarks')); + + $('#editShortcodeForm').attr('action', `/shortcodes/${id}`); + + // Replaced vanilla JS with jQuery modal show + $('#editShortcodeModal').modal('show'); + }); + + // --- POPULATE PAYMENT EDIT MODAL --- + $(document).on('click', '.edit-payment-btn', function() { + let id = $(this).data('id'); + + $('#edit_payment_id').val(id); + $('#edit_pay_invoice').val($(this).data('invoice')); + $('#edit_pay_amount').val($(this).data('amount')); + $('#edit_pay_date').val($(this).data('date')); + $('#edit_pay_status').val($(this).data('status')); + + $('#editPaymentForm').attr('action', `/payments/${id}`); + + // Replaced vanilla JS with jQuery modal show + $('#editPaymentModal').modal('show'); + }); + + }); // <-- End of the main $(document).ready }); \ No newline at end of file diff --git a/resources/views/clients/partials/short-notes-payments-edit.blade.php b/resources/views/clients/partials/short-notes-payments-edit.blade.php new file mode 100644 index 0000000..98ae0db --- /dev/null +++ b/resources/views/clients/partials/short-notes-payments-edit.blade.php @@ -0,0 +1,129 @@ + + + + + + + + \ No newline at end of file diff --git a/resources/views/clients/show.blade.php b/resources/views/clients/show.blade.php index 6190cb1..623b74c 100644 --- a/resources/views/clients/show.blade.php +++ b/resources/views/clients/show.blade.php @@ -370,15 +370,29 @@ @endif

{{ $note->notes_body }}

-
- - - {{ $note->created_by_info->name ?? 'System User' }} - - - - {{ $note->created_at->format('d M Y, h:i A') }} - +
+
+ + + {{ $note->created_by_info->name ?? 'System User' }} + + + + {{ $note->created_at->format('d M Y, h:i A') }} + +
+ + + @if($note->created_at->diffInDays(now()) <= 2) +
+ + +
+ @endif
@empty @@ -389,7 +403,7 @@ - +
@php $allCodes = collect($voice_codes)->concat($sms_codes)->concat($ussd_codes); @@ -402,10 +416,11 @@ Type Shortcode - Network + Network Status - Remarks + Remarks Expiry Date + Actions @@ -417,13 +432,29 @@ {{ $code->status ?? 'Active' }} -
{{ $code->remarks ?? '-' }}
{{ $code->expiry_date ? \Carbon\Carbon::parse($code->expiry_date)->format('d M Y') : 'N/A' }} + + + + + @endforeach @@ -448,35 +479,47 @@ Amount Date Status + Actions @foreach($recent_payments as $payment) - {{ $payment->invoice_number ?? 'N/A' }} - @php - $serviceNames = $payment->service_names; - @endphp - @if($serviceNames->count() > 0) -
- @foreach($serviceNames as $serviceName) - - {{ $serviceName }} - - @endforeach -
- @else + @php $serviceNames = $payment->service_names; @endphp + @if($serviceNames->count() > 0) +
+ @foreach($serviceNames as $serviceName) + + {{ $serviceName }} + + @endforeach +
+ @else - @endif - {{ $payment->invoice_amount }} + {{ $payment->invoice_amount }} {{ $payment->invoice_date ? \Carbon\Carbon::parse($payment->invoice_date)->format('d M Y') : 'N/A' }} {{ $payment->invoice_status ?? 'Pending' }} + + + + @endforeach @@ -486,96 +529,47 @@
No payment records found.
- @endif -
- - -
- @if(isset($showdocuments) && count($showdocuments) > 0) -
- @foreach($showdocuments as $file) -
-
-
- -
-
{{ $file->name }}
- {{ $file->file_extension ?? 'file' }} -
-
- @if(!empty($file->file_path)) - - - - - @endif -
-
- @endforeach -
- @else -
- No documents uploaded for this client. -
- @endif -
- - - - -
-
-
- Client Notes & Activity Logs -
- {{ count($show_notes) }} Entries -
- - -
- @if(isset($show_notes) && count($show_notes) > 0) -
- @foreach($show_notes as $note) -
-
-
-
- -
- - {{ $note->created_by_info->name ?? 'System User' }} -
- @if(isset($note->highlight) && $note->highlight == 'YES') - Highlighted - @endif -
- - {{ \Carbon\Carbon::parse($note->created_at)->format('d M Y, h:i A') }} - -
- - -

- {{ $note->notes_body ?? $note->note ?? $note->content ?? 'No content found' }} -

-
+ @endif
- @endforeach -
- @else -
- No notes recorded for this client yet. -
- @endif -
-
- + +
+ @if(isset($showdocuments) && count($showdocuments) > 0) +
+ @foreach($showdocuments as $file) +
+
+
+ +
+
{{ $file->name }}
+ {{ $file->file_extension ?? 'file' }} +
+
+ @if(!empty($file->file_path)) + + + + + @endif +
+
+ @endforeach +
+ @else +
+ No documents uploaded for this client. +
+ @endif +
+ + + + @include('clients.partials.shortcode-payment-docs-modal') @include('clients.partials.edit-modal') +@include('clients.partials.short-notes-payments-edit') @endsection @push('scripts') - @endpush \ No newline at end of file diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 882852a..4c7c7f6 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -29,37 +29,12 @@ diff --git a/routes/web.php b/routes/web.php index 7ec6349..7e8a127 100644 --- a/routes/web.php +++ b/routes/web.php @@ -24,6 +24,11 @@ Route::middleware(['auth'])->group(function () { Route::get('/', [App\Http\Controllers\DashboardController::class, 'index'])->name('dashboard'); Route::get('home', [App\Http\Controllers\DashboardController::class, 'index'])->name('home'); #Clients + + Route::put('/notes/{id}', [App\Http\Controllers\ClientsController::class, 'update_notes']); + Route::put('/shortcodes/{id}', [App\Http\Controllers\ClientsController::class, 'update_short_code']); + Route::put('/payments/{id}', [App\Http\Controllers\ClientsController::class, 'update_payment']); + Route::get('/clients/data', [App\Http\Controllers\ClientsController::class, 'fetchData'])->name('clients.data'); Route::get('/clients/export', [App\Http\Controllers\ClientsController::class, 'export'])->name('clients.export'); Route::get('/clients/{id}/json', [App\Http\Controllers\ClientsController::class, 'getClientJson']); @@ -53,10 +58,8 @@ Route::middleware(['auth'])->group(function () { // Route::get('/senderids', [App\Http\Controllers\SenderidsController::class, 'index']); Route::resource('senderids', App\Http\Controllers\SenderidsController::class)->except(['create', 'show', 'edit']); - // Route::get('/shortcodes', [App\Http\Controllers\ShortCodesController::class, 'index']); - // use App\Http\Controllers\ShortCodesController; Route::resource('shortcodes', App\Http\Controllers\ShortCodesController::class)->except(['create', 'show', 'edit']);