فهرست منبع

loading uscite

FabioFratini 7 ماه پیش
والد
کامیت
bd3b7c9d07
2فایلهای تغییر یافته به همراه333 افزوده شده و 58 حذف شده
  1. 99 58
      app/Http/Livewire/RecordOUT.php
  2. 234 0
      resources/views/livewire/records_out.blade.php

+ 99 - 58
app/Http/Livewire/RecordOUT.php

@@ -372,8 +372,12 @@ class RecordOUT extends Component
     }
 
 
+
     public function store()
     {
+        // Start loading state
+        $this->emit('start-loading', 'Salvataggio in corso...');
+
         $this->emit('refresh');
 
         if ($this->numero_fattura == null || $this->numero_fattura == '') {
@@ -382,30 +386,27 @@ class RecordOUT extends Component
 
         if (empty($this->data_pagamento) || $this->data_pagamento == '1970-01-01') {
             $this->data_pagamento = null;
-            Log::info("Setting data_pagamento to NULL in store");
             $is_paid = false;
         } else {
-            Log::info("Using data_pagamento: " . $this->data_pagamento);
             $is_paid = true;
         }
 
         $this->validate();
 
         try {
+            // Optimize: Use DB transaction for better performance
+            \DB::beginTransaction();
 
-            if ($this->attachment) {
-                Log::info("STORE DEBUG - Attachment original name: " . $this->attachment->getClientOriginalName());
-            }
-
+            // Create record first
             $record = \App\Models\Record::create([
                 'member_id' => $this->member_id,
                 'supplier_id' => $this->supplier_id,
                 'payment_method_id' => $this->payment_method_id,
                 'date' => $this->date,
                 'data_pagamento' => $this->data_pagamento,
-                'attachment' => '',
+                'attachment' => '', // Will be updated later if needed
                 'type' => $this->type,
-                'amount' => $this->currencyToDouble($this->amount),
+                'amount' => 0, // Will be calculated after rows
                 'commercial' => $this->commercial,
                 'numero_fattura' => $this->numero_fattura,
                 'is_paid' => $is_paid,
@@ -413,63 +414,83 @@ class RecordOUT extends Component
 
             $this->dataId = $record->id;
 
-            $this->recordFileService->createRecordFolders($record->id, 'OUT');
-
-            if ($this->attachment) {
-                try {
-                    $attachmentPath = $this->recordFileService->uploadAttachment($this->attachment, $record->id, 'OUT');
-
-                    $updateResult = \DB::table('records')
-                        ->where('id', $record->id)
-                        ->update(['attachment' => $attachmentPath]);
-
-
-                    $updatedRecord = \App\Models\Record::where('id', $record->id)->first();
+            // Update loading message
+            $this->emit('update-loading', 'Creazione cartelle...');
 
-                    $record->refresh();
-
-                } catch (\Exception $ex) {
-                    session()->flash('warning', 'Record created but attachment upload failed: ' . $ex->getMessage());
-                }
-            } else {
-                Log::info("STORE DEBUG - No attachment to upload");
-            }
+            // Create folders (this is usually fast)
+            $this->recordFileService->createRecordFolders($record->id, 'OUT');
 
+            // Create record rows first (faster than file operations)
+            $this->emit('update-loading', 'Salvataggio dati...');
             $tot = 0;
+            $rowsData = [];
+
             foreach ($this->rows as $row) {
                 foreach ($row["when"] as $x => $y) {
                     $row["when"][$x]['period'] = $row["when"][$x]['month'] . "-" . $row["when"][$x]['year'];
                 }
+
                 $imponibile = isset($row["imponibile"]) ? $this->currencyToDouble($row["imponibile"]) : null;
                 $aliquota_iva = isset($row["aliquota_iva"]) ? floatval(str_replace('%', '', $row["aliquota_iva"])) : null;
+                $amount = $this->currencyToDouble($row["amount"]);
 
-                \App\Models\RecordRow::create([
+                $rowsData[] = [
                     'record_id' => $this->dataId,
                     'causal_id' => $row["causal_id"],
                     'note' => $row["note"],
-                    'amount' => $this->currencyToDouble($row["amount"]),
+                    'amount' => $amount,
                     'imponibile' => $imponibile,
                     'aliquota_iva' => $aliquota_iva,
                     'commercial' => $row["commercial"],
-                    'when' => json_encode($row["when"])
-                ]);
-                $tot += $this->currencyToDouble($row["amount"]);
+                    'when' => json_encode($row["when"]),
+                    'created_at' => now(),
+                    'updated_at' => now()
+                ];
+                $tot += $amount;
             }
 
+            // Bulk insert for better performance
+            \App\Models\RecordRow::insert($rowsData);
+
+            // Update total amount
             $record->amount = $tot;
             $record->save();
 
-            session()->flash('success', 'Movimento creato');
+            // Handle attachment upload last (slowest operation)
+            if ($this->attachment) {
+                $this->emit('update-loading', 'Caricamento allegato...');
+
+                try {
+                    // Use a more optimized approach for file upload
+                    $attachmentPath = $this->recordFileService->uploadAttachment($this->attachment, $record->id, 'OUT');
+
+                    // Update only the attachment field to avoid unnecessary queries
+                    \DB::table('records')
+                        ->where('id', $record->id)
+                        ->update(['attachment' => $attachmentPath]);
+                } catch (\Exception $ex) {
+                    // Don't fail the entire operation for attachment issues
+                    Log::error("Attachment upload failed for record {$record->id}: " . $ex->getMessage());
+                    session()->flash('warning', 'Record creato ma caricamento allegato fallito: ' . $ex->getMessage());
+                }
+            }
+
+            \DB::commit();
+
+            $this->emit('stop-loading');
+            session()->flash('success', 'Movimento creato con successo');
+
             $this->resetFields();
             $this->add = false;
             $this->emit('setEdit', false);
         } catch (\Exception $ex) {
-            Log::error("STORE ERROR - General error: " . $ex->getMessage());
-            Log::error("STORE ERROR - Exception trace: " . $ex->getTraceAsString());
-            $this->emit('flash-error', 'Errore (' . $ex->getMessage() . ')');
+            \DB::rollback();
+            $this->emit('stop-loading');
+
+            Log::error("Store error: " . $ex->getMessage());
+            $this->emit('flash-error', 'Errore durante il salvataggio: ' . $ex->getMessage());
         }
     }
-
     public function setDataPagamentoAttribute($value)
     {
         if (empty($value) || $value == '1970-01-01' || $value == '0000-00-00') {
@@ -584,33 +605,45 @@ class RecordOUT extends Component
 
     public function update()
     {
+        // Start loading state
+        $this->emit('start-loading', 'Aggiornamento in corso...');
+
         $this->emit('refresh');
         $this->validate();
+
         if (empty($this->data_pagamento) || $this->data_pagamento == '') {
             $this->data_pagamento = null;
-            Log::info("Data pagamento vuota, imposto a NULL in update");
             $is_paid = false;
         } else {
-            Log::info("Data pagamento in update: " . $this->data_pagamento);
             $is_paid = true;
         }
 
         try {
+            \DB::beginTransaction();
 
             $attachmentPath = $this->attachment_old;
 
+            // Handle attachment first if needed
             if ($this->attachment) {
+                $this->emit('update-loading', 'Aggiornamento allegato...');
+
                 try {
+                    // Delete old attachment if exists
                     if ($this->attachment_old) {
                         $this->recordFileService->deleteAttachment($this->attachment_old);
                     }
 
                     $attachmentPath = $this->recordFileService->uploadAttachment($this->attachment, $this->dataId, 'OUT');
                 } catch (\Exception $ex) {
+                    $this->emit('stop-loading');
                     session()->flash('error', 'Errore caricamento allegato: ' . $ex->getMessage());
                     return;
                 }
             }
+
+            $this->emit('update-loading', 'Aggiornamento record...');
+
+            // Update main record
             \App\Models\Record::whereId($this->dataId)->update([
                 'member_id' => $this->member_id,
                 'supplier_id' => $this->supplier_id,
@@ -624,7 +657,7 @@ class RecordOUT extends Component
                 'attachment' => $attachmentPath,
             ]);
 
-            $tot = 0;
+            $this->emit('update-loading', 'Aggiornamento righe...');
 
             $existingRows = \App\Models\RecordRow::where('record_id', $this->dataId)
                 ->select('id', 'quantita', 'numero_linea')
@@ -634,6 +667,9 @@ class RecordOUT extends Component
 
             \App\Models\RecordRow::where('record_id', $this->dataId)->delete();
 
+            $tot = 0;
+            $newRowsData = [];
+
             foreach ($this->rows as $row) {
                 foreach ($row["when"] as $x => $y) {
                     $row["when"][$x]['period'] = $row["when"][$x]['month'] . "-" . $row["when"][$x]['year'];
@@ -642,57 +678,62 @@ class RecordOUT extends Component
                 $imponibile = null;
                 if (isset($row["imponibile"]) && $row["imponibile"] !== null && $row["imponibile"] !== '') {
                     $imponibile = $this->currencyToDouble($row["imponibile"]);
-                    Log::info("Imponibile: " . $imponibile);
                 }
 
                 $aliquota_iva = null;
                 if (isset($row["aliquota_iva"]) && $row["aliquota_iva"] !== null && $row["aliquota_iva"] !== '') {
                     $aliquota_iva = floatval(str_replace('%', '', $row["aliquota_iva"]));
-                    Log::info("Aliquota IVA: " . $aliquota_iva);
                 }
 
                 $amount = $this->currencyToDouble($row["amount"]);
-
-                $imposta = null;
-                if ($imponibile !== null) {
-                    $imposta = $amount - $imponibile;
-                    Log::info("Imposta calculated: " . $imposta);
-                }
+                $imposta = $imponibile !== null ? $amount - $imponibile : null;
 
                 $recordRowData = [
                     'record_id' => $this->dataId,
                     'causal_id' => $row["causal_id"],
                     'note' => $row["note"],
-                    'amount' => $this->currencyToDouble($row["amount"]),
+                    'amount' => $amount,
                     'commercial' => $row["commercial"],
                     'when' => json_encode($row["when"]),
                     'imponibile' => $imponibile,
                     'aliquota_iva' => $aliquota_iva,
                     'imposta' => $imposta,
                     'divisa' => 'EUR',
+                    'created_at' => now(),
+                    'updated_at' => now()
                 ];
 
+                // Preserve existing metadata if available
                 if (isset($row["id"]) && isset($existingRows[$row["id"]])) {
                     $existingRow = $existingRows[$row["id"]];
                     $recordRowData['quantita'] = $existingRow['quantita'];
                     $recordRowData['numero_linea'] = $existingRow['numero_linea'];
                 }
 
-                Log::info("RecordRowData: " . json_encode($recordRowData));
-                \App\Models\RecordRow::create($recordRowData);
-                $tot += $this->currencyToDouble($row["amount"]);
+                $newRowsData[] = $recordRowData;
+                $tot += $amount;
             }
 
-            $rec = \App\Models\Record::findOrFail($this->dataId);
-            $rec->amount = $tot;
-            $rec->save();
+            \App\Models\RecordRow::insert($newRowsData);
+
+            \DB::table('records')
+                ->where('id', $this->dataId)
+                ->update(['amount' => $tot]);
+
+            \DB::commit();
+
+            $this->emit('stop-loading');
+            session()->flash('success', 'Movimento aggiornato con successo');
 
-            session()->flash('success', 'Movimento aggiornato');
             $this->resetFields();
             $this->update = false;
             $this->emit('setEdit', false);
         } catch (\Exception $ex) {
-            $this->emit('flash-error', 'Errore (' . $ex->getMessage() . ')');
+            \DB::rollback();
+            $this->emit('stop-loading');
+
+            Log::error("Update error: " . $ex->getMessage());
+            $this->emit('flash-error', 'Errore durante l\'aggiornamento: ' . $ex->getMessage());
         }
     }
 

+ 234 - 0
resources/views/livewire/records_out.blade.php

@@ -694,6 +694,17 @@
             </div>
         </div>
     </div>
+    <div id="loadingOverlay" class="loading-overlay" style="display: none;">
+    <div class="loading-content">
+        <div class="loading-spinner"></div>
+        <div class="loading-text">Caricamento...</div>
+        <div class="loading-progress">
+            <div class="progress-bar-custom">
+                <div class="progress-fill"></div>
+            </div>
+        </div>
+    </div>
+</div>
 </div>
 @push('scripts')
     <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
@@ -746,6 +757,77 @@
             text-overflow: ellipsis;
             white-space: nowrap;
         }
+        .loading-overlay {
+            position: fixed;
+            top: 0;
+            left: 0;
+            width: 100%;
+            height: 100%;
+            background: rgba(0, 0, 0, 0.7);
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            z-index: 9999;
+            backdrop-filter: blur(2px);
+        }
+
+        .loading-content {
+            background: white;
+            padding: 30px;
+            border-radius: 10px;
+            text-align: center;
+            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
+            min-width: 300px;
+        }
+
+        .loading-spinner {
+            width: 40px;
+            height: 40px;
+            border: 4px solid #f3f3f3;
+            border-top: 4px solid #0C6197;
+            border-radius: 50%;
+            animation: spin 1s linear infinite;
+            margin: 0 auto 20px;
+        }
+
+        @keyframes spin {
+            0% { transform: rotate(0deg); }
+            100% { transform: rotate(360deg); }
+        }
+
+        .loading-text {
+            font-size: 16px;
+            font-weight: 600;
+            color: #333;
+            margin-bottom: 15px;
+        }
+
+        .progress-bar-custom {
+            width: 100%;
+            height: 4px;
+            background: #f0f0f0;
+            border-radius: 2px;
+            overflow: hidden;
+        }
+
+        .progress-fill {
+            height: 100%;
+            background: linear-gradient(90deg, #0C6197, #1e7bb8);
+            width: 0%;
+            transition: width 0.3s ease;
+            animation: progressPulse 2s ease-in-out infinite;
+        }
+
+        @keyframes progressPulse {
+            0%, 100% { opacity: 1; }
+            50% { opacity: 0.7; }
+        }
+
+        /* Disable form during loading */
+        .loading-active {
+            pointer-events: none;
+            opacity: 0.7;
+        }
     </style>
     <script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
     <script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
@@ -1605,6 +1687,158 @@
             }
         }, 300);
     }
+    let loadingOverlay = null;
+    let progressInterval = null;
+
+    function showLoading(message = 'Caricamento...') {
+        loadingOverlay = document.getElementById('loadingOverlay');
+        const loadingText = loadingOverlay.querySelector('.loading-text');
+        const progressFill = loadingOverlay.querySelector('.progress-fill');
+        const form = document.getElementById('accountingExit');
+
+        if (loadingText) {
+            loadingText.textContent = message;
+        }
+
+        // Reset progress
+        if (progressFill) {
+            progressFill.style.width = '0%';
+        }
+
+        // Disable form interactions
+        if (form) {
+            form.classList.add('loading-active');
+        }
+
+        loadingOverlay.style.display = 'flex';
+
+        // Start progress animation
+        startProgressAnimation();
+    }
+
+    function updateLoading(message) {
+        if (loadingOverlay) {
+            const loadingText = loadingOverlay.querySelector('.loading-text');
+            if (loadingText) {
+                loadingText.textContent = message;
+            }
+
+            // Increase progress
+            const progressFill = loadingOverlay.querySelector('.progress-fill');
+            if (progressFill) {
+                const currentWidth = parseInt(progressFill.style.width) || 0;
+                const newWidth = Math.min(currentWidth + 25, 90); // Don't go to 100% until complete
+                progressFill.style.width = newWidth + '%';
+            }
+        }
+    }
+
+    function hideLoading() {
+        if (loadingOverlay) {
+            const progressFill = loadingOverlay.querySelector('.progress-fill');
+            const form = document.getElementById('accountingExit');
+
+            // Complete progress
+            if (progressFill) {
+                progressFill.style.width = '100%';
+            }
+
+            // Hide after a short delay to show completion
+            setTimeout(() => {
+                loadingOverlay.style.display = 'none';
+
+                // Re-enable form interactions
+                if (form) {
+                    form.classList.remove('loading-active');
+                }
+
+                // Clear progress interval
+                if (progressInterval) {
+                    clearInterval(progressInterval);
+                    progressInterval = null;
+                }
+            }, 500);
+        }
+    }
+
+    function startProgressAnimation() {
+        const progressFill = loadingOverlay?.querySelector('.progress-fill');
+        if (!progressFill) return;
+
+        let progress = 0;
+        progressInterval = setInterval(() => {
+            if (progress < 20) { // Slow initial progress
+                progress += 1;
+                progressFill.style.width = progress + '%';
+            }
+        }, 100);
+    }
+
+    // Livewire event listeners
+    document.addEventListener('DOMContentLoaded', function() {
+        // Listen for loading events from Livewire
+        Livewire.on('start-loading', message => {
+            showLoading(message);
+        });
+
+        Livewire.on('update-loading', message => {
+            updateLoading(message);
+        });
+
+        Livewire.on('stop-loading', () => {
+            hideLoading();
+        });
+
+        // Show loading on form submissions
+        document.addEventListener('click', function(e) {
+            const target = e.target;
+
+            // Check if clicked element is a submit button
+            if ((target.textContent.includes('inserisci') || target.textContent.includes('salva')) &&
+                target.classList.contains('btn--ui')) {
+
+                // Small delay to let Livewire start
+                setTimeout(() => {
+                    if (!loadingOverlay || loadingOverlay.style.display === 'none') {
+                        const action = target.textContent.includes('inserisci') ? 'Salvataggio' : 'Aggiornamento';
+                        showLoading(action + ' in corso...');
+                    }
+                }, 100);
+            }
+        });
+
+        // Auto-hide loading on page errors
+        Livewire.on('flash-error', () => {
+            hideLoading();
+        });
+
+        // Also hide on success messages
+        window.addEventListener('beforeunload', function() {
+            hideLoading();
+        });
+    });
+
+    // Show loading during file uploads
+    document.addEventListener('change', function(e) {
+        if (e.target && e.target.type === 'file' && e.target.files.length > 0) {
+            const file = e.target.files[0];
+            const maxSize = 10 * 1024 * 1024; // 10MB
+
+            if (file.size > maxSize) {
+                alert('Il file è troppo grande. Dimensione massima: 10MB');
+                e.target.value = '';
+                return;
+            }
+
+            // Show brief loading for file processing
+            if (file.size > 1024 * 1024) { // Files larger than 1MB
+                showLoading('Elaborazione file...');
+                setTimeout(() => {
+                    hideLoading();
+                }, 1000);
+            }
+        }
+    });
     </script>
 
 @endpush