first commit
This commit is contained in:
132
resources/views/admin/articoli/create.blade.php
Normal file
132
resources/views/admin/articoli/create.blade.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<div class="flex justify-between items-center">
|
||||
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
|
||||
{{ __('Nuovo Articolo') }}
|
||||
</h2>
|
||||
<a href="{{ route('admin.articoli.index') }}" class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded">
|
||||
← Torna alla lista
|
||||
</a>
|
||||
</div>
|
||||
</x-slot>
|
||||
|
||||
<div class="py-12">
|
||||
<div class="max-w-4xl mx-auto sm:px-6 lg:px-8">
|
||||
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
|
||||
<div class="p-6">
|
||||
<form method="POST" action="{{ route('admin.articoli.store') }}">
|
||||
@csrf
|
||||
|
||||
<!-- Sezione Ubicazione -->
|
||||
<div class="mb-8">
|
||||
<h3 class="text-lg font-medium text-gray-900 mb-4 pb-2 border-b">Ubicazione</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label for="codice_articolo" class="block text-sm font-medium text-gray-700">Codice Articolo *</label>
|
||||
<input type="text" name="codice_articolo" id="codice_articolo" value="{{ old('codice_articolo') }}" required
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
@error('codice_articolo')
|
||||
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="ciclo" class="block text-sm font-medium text-gray-700">Ciclo</label>
|
||||
<input type="text" name="ciclo" id="ciclo" value="{{ old('ciclo') }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="diametro" class="block text-sm font-medium text-gray-700">Diametro</label>
|
||||
<input type="text" name="diametro" id="diametro" value="{{ old('diametro') }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="posizione" class="block text-sm font-medium text-gray-700">Posizione</label>
|
||||
<input type="text" name="posizione" id="posizione" value="{{ old('posizione') }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="quantita" class="block text-sm font-medium text-gray-700">Quantita</label>
|
||||
<input type="number" name="quantita" id="quantita" value="{{ old('quantita', 0) }}" min="0"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div class="md:col-span-2">
|
||||
<label for="descrizione" class="block text-sm font-medium text-gray-700">Descrizione</label>
|
||||
<textarea name="descrizione" id="descrizione" rows="3"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">{{ old('descrizione') }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sezione Parametri Tecnologici -->
|
||||
<div class="mb-8">
|
||||
<h3 class="text-lg font-medium text-gray-900 mb-4 pb-2 border-b">Parametri Tecnologici</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label for="tipo_lavorazione" class="block text-sm font-medium text-gray-700">Tipo di Lavorazione</label>
|
||||
<input type="text" name="tipo_lavorazione" id="tipo_lavorazione" value="{{ old('tipo_lavorazione') }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="materiale_lavorare" class="block text-sm font-medium text-gray-700">Materiale da Lavorare</label>
|
||||
<input type="text" name="materiale_lavorare" id="materiale_lavorare" value="{{ old('materiale_lavorare') }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="maximum_thickness" class="block text-sm font-medium text-gray-700">Maximum Thickness</label>
|
||||
<input type="text" name="maximum_thickness" id="maximum_thickness" value="{{ old('maximum_thickness') }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="speed_rpm" class="block text-sm font-medium text-gray-700">Speed (RPM)</label>
|
||||
<input type="number" name="speed_rpm" id="speed_rpm" value="{{ old('speed_rpm') }}" min="0"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="feed" class="block text-sm font-medium text-gray-700">Feed</label>
|
||||
<input type="number" name="feed" id="feed" value="{{ old('feed') }}" min="0" step="0.01"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="max_thrust_a" class="block text-sm font-medium text-gray-700">Max Thrust (A)</label>
|
||||
<input type="text" name="max_thrust_a" id="max_thrust_a" value="{{ old('max_thrust_a') }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="min_torque_a" class="block text-sm font-medium text-gray-700">Min Torque (A)</label>
|
||||
<input type="text" name="min_torque_a" id="min_torque_a" value="{{ old('min_torque_a') }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="quantita_fori" class="block text-sm font-medium text-gray-700">Quantita Fori</label>
|
||||
<input type="number" name="quantita_fori" id="quantita_fori" value="{{ old('quantita_fori') }}" min="0"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<a href="{{ route('admin.articoli.index') }}" class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded">
|
||||
← Torna alla lista
|
||||
</a>
|
||||
<button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
|
||||
Salva Articolo
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
138
resources/views/admin/articoli/edit.blade.php
Normal file
138
resources/views/admin/articoli/edit.blade.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<div class="flex justify-between items-center">
|
||||
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
|
||||
{{ __('Modifica Articolo') }}: {{ $articolo->codice_articolo }}
|
||||
</h2>
|
||||
<div class="flex items-center space-x-4">
|
||||
<a href="{{ route('admin.articoli.create') }}" class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">
|
||||
+ Nuovo Articolo
|
||||
</a>
|
||||
<a href="{{ route('admin.articoli.index') }}" class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded">
|
||||
← Torna alla lista
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</x-slot>
|
||||
|
||||
<div class="py-12">
|
||||
<div class="max-w-4xl mx-auto sm:px-6 lg:px-8">
|
||||
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
|
||||
<div class="p-6">
|
||||
<form method="POST" action="{{ route('admin.articoli.update', $articolo) }}">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<!-- Sezione Ubicazione -->
|
||||
<div class="mb-8">
|
||||
<h3 class="text-lg font-medium text-gray-900 mb-4 pb-2 border-b">Ubicazione</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label for="codice_articolo" class="block text-sm font-medium text-gray-700">Codice Articolo *</label>
|
||||
<input type="text" name="codice_articolo" id="codice_articolo" value="{{ old('codice_articolo', $articolo->codice_articolo) }}" required
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
@error('codice_articolo')
|
||||
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="ciclo" class="block text-sm font-medium text-gray-700">Ciclo</label>
|
||||
<input type="text" name="ciclo" id="ciclo" value="{{ old('ciclo', $articolo->ciclo) }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="diametro" class="block text-sm font-medium text-gray-700">Diametro</label>
|
||||
<input type="text" name="diametro" id="diametro" value="{{ old('diametro', $articolo->diametro) }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="posizione" class="block text-sm font-medium text-gray-700">Posizione</label>
|
||||
<input type="text" name="posizione" id="posizione" value="{{ old('posizione', $articolo->posizione) }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="quantita" class="block text-sm font-medium text-gray-700">Quantita</label>
|
||||
<input type="number" name="quantita" id="quantita" value="{{ old('quantita', $articolo->quantita) }}" min="0"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div class="md:col-span-2">
|
||||
<label for="descrizione" class="block text-sm font-medium text-gray-700">Descrizione</label>
|
||||
<textarea name="descrizione" id="descrizione" rows="3"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">{{ old('descrizione', $articolo->descrizione) }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sezione Parametri Tecnologici -->
|
||||
<div class="mb-8">
|
||||
<h3 class="text-lg font-medium text-gray-900 mb-4 pb-2 border-b">Parametri Tecnologici</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label for="tipo_lavorazione" class="block text-sm font-medium text-gray-700">Tipo di Lavorazione</label>
|
||||
<input type="text" name="tipo_lavorazione" id="tipo_lavorazione" value="{{ old('tipo_lavorazione', $articolo->tipo_lavorazione) }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="materiale_lavorare" class="block text-sm font-medium text-gray-700">Materiale da Lavorare</label>
|
||||
<input type="text" name="materiale_lavorare" id="materiale_lavorare" value="{{ old('materiale_lavorare', $articolo->materiale_lavorare) }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="maximum_thickness" class="block text-sm font-medium text-gray-700">Maximum Thickness</label>
|
||||
<input type="text" name="maximum_thickness" id="maximum_thickness" value="{{ old('maximum_thickness', $articolo->maximum_thickness) }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="speed_rpm" class="block text-sm font-medium text-gray-700">Speed (RPM)</label>
|
||||
<input type="number" name="speed_rpm" id="speed_rpm" value="{{ old('speed_rpm', $articolo->speed_rpm) }}" min="0"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="feed" class="block text-sm font-medium text-gray-700">Feed</label>
|
||||
<input type="number" name="feed" id="feed" value="{{ old('feed', $articolo->feed) }}" min="0" step="0.01"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="max_thrust_a" class="block text-sm font-medium text-gray-700">Max Thrust (A)</label>
|
||||
<input type="text" name="max_thrust_a" id="max_thrust_a" value="{{ old('max_thrust_a', $articolo->max_thrust_a) }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="min_torque_a" class="block text-sm font-medium text-gray-700">Min Torque (A)</label>
|
||||
<input type="text" name="min_torque_a" id="min_torque_a" value="{{ old('min_torque_a', $articolo->min_torque_a) }}"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="quantita_fori" class="block text-sm font-medium text-gray-700">Quantita Fori</label>
|
||||
<input type="number" name="quantita_fori" id="quantita_fori" value="{{ old('quantita_fori', $articolo->quantita_fori) }}" min="0"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<a href="{{ route('admin.articoli.index') }}" class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded">
|
||||
← Torna alla lista
|
||||
</a>
|
||||
<button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
|
||||
Salva Articolo
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
407
resources/views/admin/articoli/index.blade.php
Normal file
407
resources/views/admin/articoli/index.blade.php
Normal file
@@ -0,0 +1,407 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<div class="flex justify-between items-center">
|
||||
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
|
||||
{{ __('Gestione Articoli') }}
|
||||
</h2>
|
||||
<div class="flex items-center space-x-4">
|
||||
<button type="button" id="btn-stampa-qr" onclick="stampaQrSelezionati()"
|
||||
class="bg-purple-500 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded hidden">
|
||||
Stampa QR CODE (<span id="count-selezionati">0</span>)
|
||||
</button>
|
||||
<button type="button" onclick="openImportModal()"
|
||||
class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">
|
||||
Importa Excel
|
||||
</button>
|
||||
<a href="{{ route('admin.articoli.create') }}" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
|
||||
+ Nuovo Articolo
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</x-slot>
|
||||
|
||||
<div class="py-12">
|
||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||
@if (session('success'))
|
||||
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-4">
|
||||
{{ session('success') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
|
||||
<div class="p-6">
|
||||
<!-- Search Form -->
|
||||
<form method="GET" action="{{ route('admin.articoli.index') }}" class="mb-6">
|
||||
<div class="flex gap-4">
|
||||
<input type="text" name="search" value="{{ request('search') }}"
|
||||
placeholder="Cerca per codice, descrizione o ciclo..."
|
||||
class="flex-1 rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||||
<button type="submit" class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded">
|
||||
Cerca
|
||||
</button>
|
||||
@if(request('search'))
|
||||
<a href="{{ route('admin.articoli.index') }}" class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded">
|
||||
Reset
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Table -->
|
||||
<table class="w-full divide-y divide-gray-200">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider w-10">
|
||||
<input type="checkbox" id="select-all" onclick="toggleSelectAll()"
|
||||
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
||||
</th>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Codice</th>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Ciclo</th>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Descrizione</th>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Posizione</th>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Quantita</th>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200">
|
||||
@forelse ($articoli as $articolo)
|
||||
<tr class="{{ $loop->even ? 'bg-gray-100' : 'bg-white' }} hover:bg-blue-50 cursor-pointer" onclick="goToDetail(event, '{{ route('admin.articoli.show', $articolo) }}')">
|
||||
<td class="px-3 py-2 whitespace-nowrap" onclick="event.stopPropagation()">
|
||||
<input type="checkbox" class="articolo-checkbox rounded border-gray-300 text-blue-600 focus:ring-blue-500"
|
||||
value="{{ $articolo->id }}" onchange="updateSelection()">
|
||||
</td>
|
||||
<td class="px-3 py-2 whitespace-nowrap text-sm font-medium text-gray-900">
|
||||
{{ $articolo->codice_articolo }}
|
||||
</td>
|
||||
<td class="px-3 py-2 whitespace-nowrap text-sm text-gray-500">
|
||||
{{ $articolo->ciclo }}
|
||||
</td>
|
||||
<td class="px-3 py-2 text-sm text-gray-500 truncate max-w-xs">
|
||||
{{ $articolo->descrizione }}
|
||||
</td>
|
||||
<td class="px-3 py-2 whitespace-nowrap text-sm text-gray-500">
|
||||
{{ $articolo->posizione }}
|
||||
</td>
|
||||
<td class="px-3 py-2 whitespace-nowrap text-sm text-gray-500">
|
||||
{{ $articolo->quantita }}
|
||||
</td>
|
||||
<td class="px-3 py-2 whitespace-nowrap text-sm font-medium space-x-2" onclick="event.stopPropagation()">
|
||||
<a href="{{ route('admin.articoli.show', $articolo) }}" class="text-blue-600 hover:text-blue-900">Dettagli</a>
|
||||
<a href="{{ route('admin.articoli.edit', $articolo) }}" class="text-indigo-600 hover:text-indigo-900">Modifica</a>
|
||||
<form action="{{ route('admin.articoli.destroy', $articolo) }}" method="POST" class="inline" onsubmit="return confirm('Sei sicuro di voler eliminare questo articolo?');">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit" class="text-red-600 hover:text-red-900">Elimina</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="7" class="px-3 py-4 text-center text-gray-500">
|
||||
Nessun articolo trovato.
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Pagination -->
|
||||
<div class="mt-4">
|
||||
{{ $articoli->withQueryString()->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Import Modal Overlay -->
|
||||
<div id="import-modal" class="fixed inset-0 z-50" style="display: none;">
|
||||
<!-- Backdrop -->
|
||||
<div class="fixed inset-0" style="background-color: rgba(0, 0, 0, 0.5);" onclick="closeImportModal()"></div>
|
||||
<!-- Modal Content -->
|
||||
<div class="fixed inset-0 flex items-center justify-center p-4">
|
||||
<div class="relative bg-white rounded-lg shadow-xl w-half max-w-md p-6">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h3 class="text-lg font-medium text-gray-900">Importa Articoli da Excel</h3>
|
||||
<button onclick="closeImportModal()" class="text-gray-400 hover:text-gray-600">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<form id="import-form" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<!-- Drop Zone -->
|
||||
<div id="drop-zone" class="border-2 border-dashed border-gray-300 rounded-lg p-6 text-center cursor-pointer hover:border-blue-500 transition-colors">
|
||||
<svg style="width: 48px; height: 48px;" class="mx-auto text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"></path>
|
||||
</svg>
|
||||
<p class="mt-2 text-sm text-gray-600">
|
||||
<span class="font-semibold text-blue-600">Clicca per selezionare</span> o trascina un file Excel
|
||||
</p>
|
||||
<p class="mt-1 text-xs text-gray-500">Solo file .xlsx o .xls</p>
|
||||
<input type="file" id="file-input" name="file" accept=".xlsx,.xls" class="hidden">
|
||||
</div>
|
||||
|
||||
<!-- Selected File -->
|
||||
<div id="selected-file" class="hidden mt-4 p-3 bg-gray-50 rounded-lg flex items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
<svg class="w-8 h-8 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
|
||||
</svg>
|
||||
<span id="file-name" class="ml-2 text-sm text-gray-700"></span>
|
||||
</div>
|
||||
<button type="button" onclick="clearFile()" class="text-red-500 hover:text-red-700">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Clean Import Checkbox -->
|
||||
<div class="mt-4">
|
||||
<label class="flex items-center">
|
||||
<input type="checkbox" id="clean-import" name="clean_import" value="1"
|
||||
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
||||
<span class="ml-2 text-sm text-gray-700">Importazione pulita</span>
|
||||
</label>
|
||||
<p class="mt-1 ml-6 text-xs text-gray-500">
|
||||
Cancella tutti gli articoli esistenti prima dell'importazione
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Progress Bar -->
|
||||
<div id="progress-container" class="hidden mt-4">
|
||||
<div class="w-full bg-gray-200 rounded-full h-2.5">
|
||||
<div id="progress-bar" class="bg-blue-600 h-2.5 rounded-full transition-all duration-300" style="width: 0%"></div>
|
||||
</div>
|
||||
<p id="progress-text" class="text-sm text-gray-600 mt-2 text-center">Caricamento in corso...</p>
|
||||
</div>
|
||||
|
||||
<!-- Result Message -->
|
||||
<div id="result-message" class="hidden mt-4 p-3 rounded-lg"></div>
|
||||
|
||||
<!-- Buttons -->
|
||||
<div class="mt-6 flex justify-end space-x-4">
|
||||
<button type="button" onclick="closeImportModal()"
|
||||
style="padding: 8px 16px; background-color: #d1d5db; color: #374151; border-radius: 6px; border: none; cursor: pointer;">
|
||||
Annulla
|
||||
</button>
|
||||
<button type="submit" id="import-btn"
|
||||
style="padding: 8px 16px; background-color: #9ca3af; color: white; border-radius: 6px; border: none; cursor: not-allowed;">
|
||||
Importa
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function goToDetail(event, url) {
|
||||
window.location.href = url;
|
||||
}
|
||||
|
||||
function toggleSelectAll() {
|
||||
const selectAll = document.getElementById('select-all');
|
||||
const checkboxes = document.querySelectorAll('.articolo-checkbox');
|
||||
checkboxes.forEach(cb => cb.checked = selectAll.checked);
|
||||
updateSelection();
|
||||
}
|
||||
|
||||
function updateSelection() {
|
||||
const checkboxes = document.querySelectorAll('.articolo-checkbox:checked');
|
||||
const count = checkboxes.length;
|
||||
const btn = document.getElementById('btn-stampa-qr');
|
||||
const countSpan = document.getElementById('count-selezionati');
|
||||
|
||||
countSpan.textContent = count;
|
||||
|
||||
if (count > 0) {
|
||||
btn.classList.remove('hidden');
|
||||
} else {
|
||||
btn.classList.add('hidden');
|
||||
}
|
||||
|
||||
// Update select-all checkbox state
|
||||
const allCheckboxes = document.querySelectorAll('.articolo-checkbox');
|
||||
const selectAll = document.getElementById('select-all');
|
||||
selectAll.checked = allCheckboxes.length > 0 && count === allCheckboxes.length;
|
||||
selectAll.indeterminate = count > 0 && count < allCheckboxes.length;
|
||||
}
|
||||
|
||||
function stampaQrSelezionati() {
|
||||
const checkboxes = document.querySelectorAll('.articolo-checkbox:checked');
|
||||
const ids = Array.from(checkboxes).map(cb => cb.value);
|
||||
|
||||
if (ids.length === 0) {
|
||||
alert('Seleziona almeno un articolo');
|
||||
return;
|
||||
}
|
||||
|
||||
// Open PDF in new window
|
||||
const url = '{{ route('admin.articoli.print-qrcodes') }}?ids=' + ids.join(',');
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
|
||||
// Import Modal Functions
|
||||
const dropZone = document.getElementById('drop-zone');
|
||||
const fileInput = document.getElementById('file-input');
|
||||
const importForm = document.getElementById('import-form');
|
||||
const importBtn = document.getElementById('import-btn');
|
||||
const selectedFile = document.getElementById('selected-file');
|
||||
const fileName = document.getElementById('file-name');
|
||||
const progressContainer = document.getElementById('progress-container');
|
||||
const progressBar = document.getElementById('progress-bar');
|
||||
const progressText = document.getElementById('progress-text');
|
||||
const resultMessage = document.getElementById('result-message');
|
||||
|
||||
function openImportModal() {
|
||||
document.getElementById('import-modal').style.display = 'flex';
|
||||
resetImportForm();
|
||||
}
|
||||
|
||||
function closeImportModal() {
|
||||
document.getElementById('import-modal').style.display = 'none';
|
||||
resetImportForm();
|
||||
}
|
||||
|
||||
function resetImportForm() {
|
||||
importForm.reset();
|
||||
fileInput.value = '';
|
||||
selectedFile.classList.add('hidden');
|
||||
dropZone.classList.remove('hidden');
|
||||
progressContainer.classList.add('hidden');
|
||||
resultMessage.classList.add('hidden');
|
||||
importBtn.disabled = true;
|
||||
progressBar.style.width = '0%';
|
||||
}
|
||||
|
||||
function clearFile() {
|
||||
fileInput.value = '';
|
||||
selectedFile.classList.add('hidden');
|
||||
dropZone.classList.remove('hidden');
|
||||
importBtn.disabled = true;
|
||||
importBtn.style.backgroundColor = '#9ca3af';
|
||||
importBtn.style.cursor = 'not-allowed';
|
||||
}
|
||||
|
||||
function handleFileSelect(file) {
|
||||
if (file && (file.name.endsWith('.xlsx') || file.name.endsWith('.xls'))) {
|
||||
const dataTransfer = new DataTransfer();
|
||||
dataTransfer.items.add(file);
|
||||
fileInput.files = dataTransfer.files;
|
||||
|
||||
fileName.textContent = file.name;
|
||||
selectedFile.classList.remove('hidden');
|
||||
dropZone.classList.add('hidden');
|
||||
importBtn.disabled = false;
|
||||
importBtn.style.backgroundColor = '#2563eb';
|
||||
importBtn.style.cursor = 'pointer';
|
||||
resultMessage.classList.add('hidden');
|
||||
} else {
|
||||
alert('Per favore seleziona un file Excel (.xlsx o .xls)');
|
||||
}
|
||||
}
|
||||
|
||||
// Click to upload
|
||||
dropZone.addEventListener('click', () => fileInput.click());
|
||||
|
||||
// File input change
|
||||
fileInput.addEventListener('change', (e) => {
|
||||
if (e.target.files.length > 0) {
|
||||
handleFileSelect(e.target.files[0]);
|
||||
}
|
||||
});
|
||||
|
||||
// Drag and drop
|
||||
dropZone.addEventListener('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
dropZone.classList.add('border-blue-500', 'bg-blue-50');
|
||||
});
|
||||
|
||||
dropZone.addEventListener('dragleave', (e) => {
|
||||
e.preventDefault();
|
||||
dropZone.classList.remove('border-blue-500', 'bg-blue-50');
|
||||
});
|
||||
|
||||
dropZone.addEventListener('drop', (e) => {
|
||||
e.preventDefault();
|
||||
dropZone.classList.remove('border-blue-500', 'bg-blue-50');
|
||||
|
||||
if (e.dataTransfer.files.length > 0) {
|
||||
handleFileSelect(e.dataTransfer.files[0]);
|
||||
}
|
||||
});
|
||||
|
||||
// Form submit
|
||||
importForm.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const formData = new FormData(importForm);
|
||||
formData.append('clean_import', document.getElementById('clean-import').checked ? '1' : '0');
|
||||
|
||||
// Show progress
|
||||
progressContainer.classList.remove('hidden');
|
||||
importBtn.disabled = true;
|
||||
progressBar.style.width = '30%';
|
||||
progressText.textContent = 'Caricamento file...';
|
||||
|
||||
try {
|
||||
const response = await fetch('{{ route('admin.articoli.import') }}', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||
}
|
||||
});
|
||||
|
||||
progressBar.style.width = '70%';
|
||||
progressText.textContent = 'Elaborazione in corso...';
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
progressBar.style.width = '100%';
|
||||
|
||||
if (data.success) {
|
||||
resultMessage.className = 'mt-4 p-3 rounded-lg bg-green-100 text-green-700';
|
||||
resultMessage.textContent = data.message;
|
||||
progressText.textContent = 'Completato!';
|
||||
|
||||
// Reload page after 2 seconds
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 2000);
|
||||
} else {
|
||||
resultMessage.className = 'mt-4 p-3 rounded-lg bg-red-100 text-red-700';
|
||||
resultMessage.textContent = data.message;
|
||||
progressContainer.classList.add('hidden');
|
||||
importBtn.disabled = false;
|
||||
}
|
||||
|
||||
resultMessage.classList.remove('hidden');
|
||||
} catch (error) {
|
||||
progressContainer.classList.add('hidden');
|
||||
resultMessage.className = 'mt-4 p-3 rounded-lg bg-red-100 text-red-700';
|
||||
resultMessage.textContent = 'Errore durante l\'importazione: ' + error.message;
|
||||
resultMessage.classList.remove('hidden');
|
||||
importBtn.disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Close modal on escape key
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
closeImportModal();
|
||||
}
|
||||
});
|
||||
|
||||
// Close modal on outside click
|
||||
document.getElementById('import-modal').addEventListener('click', (e) => {
|
||||
if (e.target === document.getElementById('import-modal')) {
|
||||
closeImportModal();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</x-app-layout>
|
||||
50
resources/views/admin/articoli/pdf-qrcodes.blade.php
Normal file
50
resources/views/admin/articoli/pdf-qrcodes.blade.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>QR Codes Articoli</title>
|
||||
<style>
|
||||
@page {
|
||||
margin: 10mm;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 6pt;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.qr-container {
|
||||
display: inline-block;
|
||||
width: 15mm;
|
||||
text-align: center;
|
||||
margin: 2mm;
|
||||
vertical-align: top;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
.qr-code {
|
||||
width: 10mm;
|
||||
height: 10mm;
|
||||
}
|
||||
|
||||
.qr-label {
|
||||
font-size: 5pt;
|
||||
margin-top: 1mm;
|
||||
word-break: break-all;
|
||||
line-height: 1.2;
|
||||
max-width: 15mm;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@foreach($articoliWithQr as $item)
|
||||
<div class="qr-container">
|
||||
<img src="data:image/png;base64,{{ $item['qr_base64'] }}" class="qr-code" alt="QR Code">
|
||||
<div class="qr-label">{{ $item['articolo']->codice_articolo }}</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</body>
|
||||
</html>
|
||||
150
resources/views/admin/articoli/show.blade.php
Normal file
150
resources/views/admin/articoli/show.blade.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<div class="flex justify-between items-center">
|
||||
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
|
||||
{{ __('Dettaglio Articolo') }}: {{ $articolo->codice_articolo }}
|
||||
</h2>
|
||||
<div class="space-x-2">
|
||||
<a href="{{ route('admin.articoli.edit', $articolo) }}" class="bg-indigo-500 hover:bg-indigo-700 text-white font-bold py-2 px-4 rounded">
|
||||
Modifica
|
||||
</a>
|
||||
<a href="{{ route('admin.articoli.index') }}" class="text-gray-600 hover:text-gray-900">
|
||||
← Torna alla lista
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</x-slot>
|
||||
|
||||
<div class="py-12">
|
||||
<div class="max-w-6xl mx-auto sm:px-6 lg:px-8">
|
||||
@if (session('success'))
|
||||
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-4">
|
||||
{{ session('success') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
<!-- Dettagli Articolo -->
|
||||
<div class="lg:col-span-2 space-y-6">
|
||||
<!-- Sezione Ubicazione -->
|
||||
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
|
||||
<div class="p-6">
|
||||
<h3 class="text-lg font-medium text-gray-900 mb-4 pb-2 border-b">Ubicazione</h3>
|
||||
<dl class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500">Codice Articolo</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 font-semibold">{{ $articolo->codice_articolo }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500">Ciclo</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->ciclo ?? '-' }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500">Diametro</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->diametro ?? '-' }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500">Posizione</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->posizione ?? '-' }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500">Quantita</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->quantita }}</dd>
|
||||
</div>
|
||||
<div class="md:col-span-2">
|
||||
<dt class="text-sm font-medium text-gray-500">Descrizione</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->descrizione ?? '-' }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sezione Parametri Tecnologici -->
|
||||
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
|
||||
<div class="p-6">
|
||||
<h3 class="text-lg font-medium text-gray-900 mb-4 pb-2 border-b">Parametri Tecnologici</h3>
|
||||
<dl class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500">Tipo di Lavorazione</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->tipo_lavorazione ?? '-' }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500">Materiale da Lavorare</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->materiale_lavorare ?? '-' }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500">Maximum Thickness</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->maximum_thickness ?? '-' }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500">Speed (RPM)</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->speed_rpm ?? '-' }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500">Feed</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->feed ?? '-' }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500">Max Thrust (A)</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->max_thrust_a ?? '-' }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500">Min Torque (A)</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->min_torque_a ?? '-' }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500">Quantita Fori</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->quantita_fori ?? '-' }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sezione QR Code -->
|
||||
<div class="lg:col-span-1">
|
||||
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
|
||||
<div class="p-6">
|
||||
<h3 class="text-lg font-medium text-gray-900 mb-4 pb-2 border-b">QR Code</h3>
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="bg-white p-4 border rounded-lg mb-4">
|
||||
<img src="{{ route('admin.articoli.qrcode', $articolo) }}" alt="QR Code" class="w-48 h-48">
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 mb-4 text-center break-all">
|
||||
{{ $articolo->qr_url }}
|
||||
</p>
|
||||
<div class="space-y-2 w-full">
|
||||
<a href="{{ route('admin.articoli.qrcode.download', $articolo) }}"
|
||||
class="block w-full text-center bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">
|
||||
Scarica QR Code
|
||||
</a>
|
||||
<button onclick="window.print()"
|
||||
class="block w-full text-center bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded">
|
||||
Stampa
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info -->
|
||||
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg mt-6">
|
||||
<div class="p-6">
|
||||
<h3 class="text-lg font-medium text-gray-900 mb-4 pb-2 border-b">Informazioni</h3>
|
||||
<dl class="space-y-2">
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500">Creato il</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->created_at->format('d/m/Y H:i') }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500">Ultima modifica</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->updated_at->format('d/m/Y H:i') }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
Reference in New Issue
Block a user