feat: Add Blade templates for ops QR interface (Phase 2)
Create state-driven UI templates: Main Template (ops/order-detail.blade.php): - Display order summary with status, type, customer, date - Render QR code SVG for shop-floor access - Conditionally include state-specific action forms - Show order items, packing details, shipment info Action Templates: - ops/actions/packing.blade.php: Form to input weight/dimensions - ops/actions/inspection.blade.php: Pass/Fail inspection with optional notes - ops/actions/read-only.blade.php: Status display for read-only states Error Pages: - ops/order-not-found.blade.php: Invalid/expired QR token - ops/unauthorized.blade.php: Insufficient permissions All forms use AJAX submission with confirmation dialogs
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
<!-- Packing Action Form -->
|
||||
<div class="bg-white rounded-lg shadow-md p-6 mb-8">
|
||||
<h2 class="text-2xl font-bold mb-4">📦 Confirm Packing</h2>
|
||||
|
||||
<form id="packingForm" action="{{ route('ops.order.pack', $order) }}" method="POST" class="space-y-4">
|
||||
@csrf
|
||||
|
||||
<div class="grid grid-cols-2 gap-4 md:grid-cols-4">
|
||||
<!-- Width -->
|
||||
<div>
|
||||
<label for="width" class="block text-sm font-medium text-gray-700 mb-1">
|
||||
Width (cm)
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
id="width"
|
||||
name="width"
|
||||
step="0.1"
|
||||
min="1"
|
||||
required
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="e.g., 30"
|
||||
>
|
||||
@error('width')
|
||||
<p class="text-red-600 text-xs mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<!-- Length -->
|
||||
<div>
|
||||
<label for="length" class="block text-sm font-medium text-gray-700 mb-1">
|
||||
Length (cm)
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
id="length"
|
||||
name="length"
|
||||
step="0.1"
|
||||
min="1"
|
||||
required
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="e.g., 40"
|
||||
>
|
||||
@error('length')
|
||||
<p class="text-red-600 text-xs mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<!-- Height -->
|
||||
<div>
|
||||
<label for="height" class="block text-sm font-medium text-gray-700 mb-1">
|
||||
Height (cm)
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
id="height"
|
||||
name="height"
|
||||
step="0.1"
|
||||
min="1"
|
||||
required
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="e.g., 10"
|
||||
>
|
||||
@error('height')
|
||||
<p class="text-red-600 text-xs mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<!-- Weight -->
|
||||
<div>
|
||||
<label for="weight" class="block text-sm font-medium text-gray-700 mb-1">
|
||||
Weight (kg)
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
id="weight"
|
||||
name="weight"
|
||||
step="0.1"
|
||||
min="0.1"
|
||||
required
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="e.g., 2.5"
|
||||
>
|
||||
@error('weight')
|
||||
<p class="text-red-600 text-xs mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<div class="flex gap-3 mt-6">
|
||||
<button
|
||||
type="submit"
|
||||
class="bg-green-600 hover:bg-green-700 text-white font-bold py-2 px-6 rounded-lg transition duration-200"
|
||||
>
|
||||
✓ Confirm Packed
|
||||
</button>
|
||||
<button
|
||||
type="reset"
|
||||
class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-6 rounded-lg transition duration-200"
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
document.getElementById('packingForm').addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const formData = new FormData(this);
|
||||
|
||||
try {
|
||||
const response = await fetch(this.action, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: formData,
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
alert('✓ Order packed successfully!');
|
||||
window.location.reload();
|
||||
} else {
|
||||
alert('Error: ' + (data.message || data.error || 'Unknown error'));
|
||||
}
|
||||
} catch (error) {
|
||||
alert('Error submitting form: ' + error.message);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
Reference in New Issue
Block a user