Aggiungi campi per immagini e diametro del foro nel modello Articolo e nelle relative migrazioni; aggiorna i form e le viste per gestire i nuovi campi

This commit is contained in:
2026-05-18 16:23:12 +02:00
parent f3a1d816b7
commit 83412247a7
11 changed files with 373 additions and 33 deletions

View File

@@ -1,3 +1,4 @@
@use('Illuminate\Support\Facades\Storage')
<x-app-layout>
<x-slot name="header">
<div class="flex justify-between items-center">
@@ -15,11 +16,11 @@
</div>
</x-slot>
<div class="py-12">
<div class="py-12" x-data="{ modalImg: null }">
<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) }}">
<form method="POST" action="{{ route('admin.articoli.update', $articolo) }}" enctype="multipart/form-data">
@csrf
@method('PUT')
@@ -42,6 +43,12 @@
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="hole_diameter" class="block text-sm font-medium text-gray-700">Hole Diameter</label>
<input type="text" name="hole_diameter" id="hole_diameter" value="{{ old('hole_diameter', $articolo->hole_diameter) }}"
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) }}"
@@ -65,6 +72,26 @@
<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 class="md:col-span-2">
<label class="block text-sm font-medium text-gray-700">Immagine Articolo</label>
@if ($articolo->immagine_articolo)
<div class="mt-2 mb-3 flex items-center gap-4">
<img src="{{ Storage::url($articolo->immagine_articolo) }}" alt="Immagine Articolo"
class="h-16 w-16 object-cover rounded border cursor-pointer hover:opacity-80 transition-opacity"
@click="modalImg = '{{ Storage::url($articolo->immagine_articolo) }}'">
<label class="flex items-center gap-2 text-sm text-red-600 cursor-pointer">
<input type="checkbox" name="rimuovi_immagine_articolo" value="1" class="rounded border-gray-300">
Rimuovi immagine
</label>
</div>
@endif
<input type="file" name="immagine_articolo" id="immagine_articolo" accept="image/*"
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100">
@error('immagine_articolo')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
</div>
</div>
@@ -108,12 +135,52 @@
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Immagine Thrust</label>
@if ($articolo->immagine_thrust)
<div class="mt-2 mb-3 flex items-center gap-4">
<img src="{{ Storage::url($articolo->immagine_thrust) }}" alt="Immagine Thrust"
class="h-16 w-16 object-cover rounded border cursor-pointer hover:opacity-80 transition-opacity"
@click="modalImg = '{{ Storage::url($articolo->immagine_thrust) }}'">
<label class="flex items-center gap-2 text-sm text-red-600 cursor-pointer">
<input type="checkbox" name="rimuovi_immagine_thrust" value="1" class="rounded border-gray-300">
Rimuovi immagine
</label>
</div>
@endif
<input type="file" name="immagine_thrust" id="immagine_thrust" accept="image/*"
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100">
@error('immagine_thrust')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
</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 class="block text-sm font-medium text-gray-700">Immagine Tourque</label>
@if ($articolo->immagine_tourque)
<div class="mt-2 mb-3 flex items-center gap-4">
<img src="{{ Storage::url($articolo->immagine_tourque) }}" alt="Immagine Tourque"
class="h-16 w-16 object-cover rounded border cursor-pointer hover:opacity-80 transition-opacity"
@click="modalImg = '{{ Storage::url($articolo->immagine_tourque) }}'">
<label class="flex items-center gap-2 text-sm text-red-600 cursor-pointer">
<input type="checkbox" name="rimuovi_immagine_tourque" value="1" class="rounded border-gray-300">
Rimuovi immagine
</label>
</div>
@endif
<input type="file" name="immagine_tourque" id="immagine_tourque" accept="image/*"
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100">
@error('immagine_tourque')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
</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"
@@ -134,5 +201,14 @@
</div>
</div>
</div>
<!-- Image Modal -->
<div x-show="modalImg" x-cloak
class="fixed inset-0 bg-black/80 flex items-center justify-center z-50 p-4"
@click="modalImg = null"
@keydown.escape.window="modalImg = null">
<img :src="modalImg" @click.stop class="max-h-[90vh] max-w-full rounded-lg shadow-2xl">
</div>
</div>
</x-app-layout>

View File

@@ -288,7 +288,7 @@
}
function handleFileSelect(file) {
if (file && (file.name.endsWith('.xlsx') || file.name.endsWith('.xls'))) {
if (file && (file.name.toLowerCase().endsWith('.xlsx') || file.name.toLowerCase().endsWith('.xls'))) {
const dataTransfer = new DataTransfer();
dataTransfer.items.add(file);
fileInput.files = dataTransfer.files;

View File

@@ -1,3 +1,4 @@
@use('Illuminate\Support\Facades\Storage')
<x-app-layout>
<x-slot name="header">
<div class="flex justify-between items-center">
@@ -15,7 +16,7 @@
</div>
</x-slot>
<div class="py-12">
<div class="py-12" x-data="{ modalImg: null }">
<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">
@@ -39,6 +40,10 @@
<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">Hole Diameter</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->hole_diameter ?? '-' }}</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>
@@ -55,6 +60,16 @@
<dt class="text-sm font-medium text-gray-500">Descrizione</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $articolo->descrizione ?? '-' }}</dd>
</div>
@if ($articolo->immagine_articolo)
<div>
<dt class="text-sm font-medium text-gray-500">Immagine Articolo</dt>
<dd class="mt-2">
<img src="{{ Storage::url($articolo->immagine_articolo) }}" alt="Immagine Articolo"
class="h-16 w-16 object-cover rounded border cursor-pointer hover:opacity-80 transition-opacity"
@click="modalImg = '{{ Storage::url($articolo->immagine_articolo) }}'">
</dd>
</div>
@endif
</dl>
</div>
</div>
@@ -88,10 +103,30 @@
<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>
@if ($articolo->immagine_thrust)
<div>
<dt class="text-sm font-medium text-gray-500">Immagine Thrust</dt>
<dd class="mt-2">
<img src="{{ Storage::url($articolo->immagine_thrust) }}" alt="Immagine Thrust"
class="h-16 w-16 object-cover rounded border cursor-pointer hover:opacity-80 transition-opacity"
@click="modalImg = '{{ Storage::url($articolo->immagine_thrust) }}'">
</dd>
</div>
@endif
<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>
@if ($articolo->immagine_tourque)
<div>
<dt class="text-sm font-medium text-gray-500">Immagine Tourque</dt>
<dd class="mt-2">
<img src="{{ Storage::url($articolo->immagine_tourque) }}" alt="Immagine Tourque"
class="h-16 w-16 object-cover rounded border cursor-pointer hover:opacity-80 transition-opacity"
@click="modalImg = '{{ Storage::url($articolo->immagine_tourque) }}'">
</dd>
</div>
@endif
<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>
@@ -146,5 +181,13 @@
</div>
</div>
</div>
<!-- Image Modal -->
<div x-show="modalImg" x-cloak
class="fixed inset-0 bg-black/80 flex items-center justify-center z-50 p-4"
@click="modalImg = null"
@keydown.escape.window="modalImg = null">
<img :src="modalImg" @click.stop class="max-h-[90vh] max-w-full rounded-lg shadow-2xl">
</div>
</div>
</x-app-layout>

View File

@@ -1,3 +1,4 @@
@use('Illuminate\Support\Facades\Storage')
<!DOCTYPE html>
<html lang="it">
<head>
@@ -5,13 +6,15 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ $articolo->codice_articolo }} - HTT Locator</title>
<script src="https://cdn.tailwindcss.com"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<style>
.gradient-bg {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
[x-cloak] { display: none !important; }
</style>
</head>
<body class="bg-gray-100 min-h-screen">
<body class="bg-gray-100 min-h-screen" x-data="{ modalImg: null }">
<!-- Header -->
<header class="gradient-bg text-white py-4 px-4 shadow-lg">
<div class="max-w-lg mx-auto">
@@ -35,7 +38,7 @@
</div>
<!-- Ubicazione -->
<div class="bg-white rounded-2xl shadow-lg overflow-hidden mb-6">
<div class="bg-white rounded-2xl shadow-lg overflow-hidden mb-2">
<div class="px-4 py-3 bg-gray-50 border-b">
<h3 class="font-semibold text-gray-700 flex items-center">
<svg class="w-5 h-5 mr-2 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -46,12 +49,26 @@
</h3>
</div>
<div class="divide-y">
@if($articolo->immagine_articolo)
<div class="flex justify-between items-center px-4 py-3">
<span class="text-gray-500 text-sm">Immagine</span>
<img src="{{ Storage::url($articolo->immagine_articolo) }}" alt="Immagine Articolo"
class="h-12 w-12 object-cover rounded cursor-pointer hover:opacity-80 transition-opacity"
@click="modalImg = '{{ Storage::url($articolo->immagine_articolo) }}'">
</div>
@endif
@if($articolo->ciclo)
<div class="flex justify-between items-center px-4 py-3">
<span class="text-gray-500 text-sm">Ciclo</span>
<span class="font-medium text-gray-900">{{ $articolo->ciclo }}</span>
</div>
@endif
@if($articolo->hole_diameter)
<div class="flex justify-between items-center px-4 py-3">
<span class="text-gray-500 text-sm">Hole Diameter</span>
<span class="font-medium text-gray-900">{{ $articolo->hole_diameter }}</span>
</div>
@endif
@if($articolo->diametro)
<div class="flex justify-between items-center px-4 py-3">
<span class="text-gray-500 text-sm">Diametro</span>
@@ -121,12 +138,28 @@
<span class="font-medium text-gray-900">{{ $articolo->max_thrust_a }}</span>
</div>
@endif
@if($articolo->immagine_thrust)
<div class="flex justify-between items-center px-4 py-3">
<span class="text-gray-500 text-sm">Immagine Thrust</span>
<img src="{{ Storage::url($articolo->immagine_thrust) }}" alt="Immagine Thrust"
class="h-12 w-12 object-cover rounded cursor-pointer hover:opacity-80 transition-opacity"
@click="modalImg = '{{ Storage::url($articolo->immagine_thrust) }}'">
</div>
@endif
@if($articolo->min_torque_a)
<div class="flex justify-between items-center px-4 py-3">
<span class="text-gray-500 text-sm">Min Torque (A)</span>
<span class="font-medium text-gray-900">{{ $articolo->min_torque_a }}</span>
</div>
@endif
@if($articolo->immagine_tourque)
<div class="flex justify-between items-center px-4 py-3">
<span class="text-gray-500 text-sm">Immagine Tourque</span>
<img src="{{ Storage::url($articolo->immagine_tourque) }}" alt="Immagine Tourque"
class="h-12 w-12 object-cover rounded cursor-pointer hover:opacity-80 transition-opacity"
@click="modalImg = '{{ Storage::url($articolo->immagine_tourque) }}'">
</div>
@endif
@if($articolo->quantita_fori)
<div class="flex justify-between items-center px-4 py-3">
<span class="text-gray-500 text-sm">Quantita Fori</span>
@@ -136,8 +169,13 @@
</div>
</div>
<!-- Footer Info -->
<div class="text-center text-gray-400 text-xs">
<p>Ultimo aggiornamento: {{ $articolo->updated_at->format('d/m/Y H:i') }}</p>
</div>
<!-- Scan New QR Button -->
<div class="mb-6">
<div class="mb-6 mt-3">
<a href="{{ route('scanner') }}" class="flex items-center justify-center gap-3 w-full bg-blue-600 hover:bg-blue-700 text-white font-semibold py-4 px-6 rounded-2xl shadow-lg transition-all">
<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="M12 4v1m6 11h2m-6 0h-2v4m0-11v3m0 0h.01M12 12h4.01M16 20h4M4 12h4m12 0h.01M5 8h2a1 1 0 001-1V5a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1zm12 0h2a1 1 0 001-1V5a1 1 0 00-1-1h-2a1 1 0 00-1 1v2a1 1 0 001 1zM5 20h2a1 1 0 001-1v-2a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1z"></path>
@@ -146,10 +184,25 @@
</a>
</div>
<!-- Footer Info -->
<div class="text-center text-gray-400 text-xs">
<p>Ultimo aggiornamento: {{ $articolo->updated_at->format('d/m/Y H:i') }}</p>
<!-- Back to Home Button (Mobile Only) -->
<div class="bottom-4 left-4 right-4 md:hidden">
<a href="/" class="flex items-center justify-center gap-3 w-full bg-gray-800 hover:bg-gray-900 text-white font-semibold py-3 px-6 rounded-full shadow-lg transition-all">
<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="M3 12l9-9m0 0l9 9m-9-9v18"></path>
</svg>
Torna alla Home
</a>
</div>
</main>
<!-- Image Modal -->
<div x-show="modalImg" x-cloak
class="fixed inset-0 bg-black/80 flex items-center justify-center z-50 p-4"
@click="modalImg = null"
@keydown.escape.window="modalImg = null">
<img :src="modalImg" @click.stop class="max-h-[90vh] max-w-full rounded-lg shadow-2xl">
</div>
</body>
</html>