400 lines
16 KiB
PHP
400 lines
16 KiB
PHP
@extends('layouts.winemaker')
|
|
|
|
@section('title', 'Harvests - Winemaker')
|
|
|
|
@section('content')
|
|
<style>
|
|
.page-header {
|
|
text-align: center;
|
|
margin-bottom: 3rem;
|
|
}
|
|
|
|
.page-title {
|
|
font-size: 2rem;
|
|
font-weight: 700;
|
|
color: #2d3748;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.page-subtitle {
|
|
color: #718096;
|
|
font-size: 1rem;
|
|
}
|
|
|
|
.content-card {
|
|
background: white;
|
|
border-radius: 12px;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.table-container {
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.harvests-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
.harvests-table thead {
|
|
background: linear-gradient(135deg, #f7fafc 0%, #edf2f7 100%);
|
|
}
|
|
|
|
.harvests-table th {
|
|
padding: 1rem 1.5rem;
|
|
text-align: left;
|
|
font-size: 0.875rem;
|
|
font-weight: 600;
|
|
color: #4a5568;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
border-bottom: 2px solid #e2e8f0;
|
|
}
|
|
|
|
.harvests-table td {
|
|
padding: 1rem 1.5rem;
|
|
border-bottom: 1px solid #e2e8f0;
|
|
color: #2d3748;
|
|
}
|
|
|
|
.harvests-table tbody tr {
|
|
transition: background 0.2s;
|
|
}
|
|
|
|
.harvests-table tbody tr:hover {
|
|
background: #f7fafc;
|
|
}
|
|
|
|
.harvest-id {
|
|
font-weight: 600;
|
|
color: #4a5568;
|
|
}
|
|
|
|
.variety-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.375rem;
|
|
padding: 0.375rem 0.75rem;
|
|
background: linear-gradient(135deg, #ddd6fe 0%, #c4b5fd 100%);
|
|
color: #5b21b6;
|
|
border-radius: 6px;
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.status-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.375rem;
|
|
padding: 0.375rem 0.75rem;
|
|
border-radius: 6px;
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.status-available {
|
|
background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);
|
|
color: #065f46;
|
|
}
|
|
|
|
.status-used {
|
|
background: linear-gradient(135deg, #e5e7eb 0%, #d1d5db 100%);
|
|
color: #374151;
|
|
}
|
|
|
|
.status-partial {
|
|
background: linear-gradient(135deg, #fed7aa 0%, #fdba74 100%);
|
|
color: #92400e;
|
|
}
|
|
|
|
.btn-bottle {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.5rem 1rem;
|
|
background: linear-gradient(135deg, #89b4d9 0%, #a8cce5 100%);
|
|
color: #1a365d;
|
|
border: none;
|
|
border-radius: 8px;
|
|
font-weight: 500;
|
|
font-size: 0.875rem;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.btn-bottle:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 4px 12px rgba(137, 180, 217, 0.4);
|
|
}
|
|
|
|
.btn-bottle:disabled {
|
|
opacity: 0.5;
|
|
cursor: not-allowed;
|
|
transform: none;
|
|
}
|
|
|
|
.btn-delete {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.5rem 1rem;
|
|
background: linear-gradient(135deg, #fca5a5 0%, #f87171 100%);
|
|
color: #7f1d1d;
|
|
border: none;
|
|
border-radius: 8px;
|
|
font-weight: 500;
|
|
font-size: 0.875rem;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.btn-delete:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 4px 12px rgba(252, 165, 165, 0.4);
|
|
}
|
|
|
|
.metric {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.375rem;
|
|
color: #4a5568;
|
|
}
|
|
|
|
.date-text {
|
|
color: #4a5568;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.empty-state {
|
|
text-align: center;
|
|
padding: 4rem 2rem;
|
|
}
|
|
|
|
.empty-icon {
|
|
width: 80px;
|
|
height: 80px;
|
|
margin: 0 auto 1.5rem;
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.empty-title {
|
|
font-size: 1.5rem;
|
|
font-weight: 600;
|
|
color: #2d3748;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.empty-description {
|
|
color: #718096;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.btn-primary {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.75rem 1.5rem;
|
|
background: linear-gradient(135deg, #89b4d9 0%, #a8cce5 100%);
|
|
color: #1a365d;
|
|
border: none;
|
|
border-radius: 8px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.btn-primary:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 4px 12px rgba(137, 180, 217, 0.4);
|
|
}
|
|
|
|
.icon {
|
|
width: 20px;
|
|
height: 20px;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.harvests-table {
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.harvests-table th,
|
|
.harvests-table td {
|
|
padding: 0.75rem 1rem;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<div style="position: relative; margin-bottom: 3rem;">
|
|
<div class="page-header">
|
|
<h1 class="page-title">Harvest Records</h1>
|
|
<p class="page-subtitle">Manage harvested grapes and bottle wines</p>
|
|
</div>
|
|
|
|
<a href="{{ route('winemaker.cellar.blend.create') }}" class="btn-primary" style="position: absolute; right: 0; top: 50%; transform: translateY(-50%);">
|
|
<svg class="icon" fill="currentColor" viewBox="0 0 24 24">
|
|
<path d="M12,2C11.5,2 11,2.19 10.59,2.59L2.59,10.59C1.8,11.37 1.8,12.63 2.59,13.41L10.59,21.41C11.37,22.2 12.63,22.2 13.41,21.41L21.41,13.41C22.2,12.63 22.2,11.37 21.41,10.59L13.41,2.59C13,2.19 12.5,2 12,2M12,4L20,12L12,20L4,12L12,4M12,7C9.79,7 8,8.79 8,11C8,12.5 9,13.77 10.5,14.37L12,16L13.5,14.37C15,13.77 16,12.5 16,11C16,8.79 14.21,7 12,7M12,9A2,2 0 0,1 14,11A2,2 0 0,1 12,13A2,2 0 0,1 10,11A2,2 0 0,1 12,9Z"/>
|
|
</svg>
|
|
Create Blended Wine
|
|
</a>
|
|
</div>
|
|
|
|
<div class="content-card">
|
|
@if($harvests->count() > 0)
|
|
<div class="table-container">
|
|
<table class="harvests-table">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>Date</th>
|
|
<th>Grape Variety</th>
|
|
<th>Weight</th>
|
|
<th>Sugar Content</th>
|
|
<th>Quality</th>
|
|
<th>Status</th>
|
|
<th>Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach($harvests as $harvest)
|
|
<tr>
|
|
<td>
|
|
<span class="harvest-id">#{{ $harvest->id }}</span>
|
|
</td>
|
|
<td>
|
|
<div class="date-text">
|
|
<svg class="icon" style="width: 16px; height: 16px; display: inline-block; vertical-align: middle;" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z" clip-rule="evenodd"/>
|
|
</svg>
|
|
@if($harvest->plannedTask && $harvest->plannedTask->execution_date)
|
|
{{ \Carbon\Carbon::parse($harvest->plannedTask->execution_date)->format('d M Y') }}
|
|
@else
|
|
{{ \Carbon\Carbon::parse($harvest->date)->format('d M Y') }}
|
|
@endif
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<span class="variety-badge">
|
|
<svg class="icon" style="width: 16px; height: 16px;" fill="currentColor" viewBox="0 0 24 24">
|
|
<path d="M12,2C11.5,2 11,2.19 10.59,2.59L2.59,10.59C1.8,11.37 1.8,12.63 2.59,13.41L10.59,21.41C11.37,22.2 12.63,22.2 13.41,21.41L21.41,13.41C22.2,12.63 22.2,11.37 21.41,10.59L13.41,2.59C13,2.19 12.5,2 12,2M12,4L20,12L12,20L4,12L12,4M12,7C9.79,7 8,8.79 8,11C8,12.5 9,13.77 10.5,14.37L12,16L13.5,14.37C15,13.77 16,12.5 16,11C16,8.79 14.21,7 12,7M12,9A2,2 0 0,1 14,11A2,2 0 0,1 12,13A2,2 0 0,1 10,11A2,2 0 0,1 12,9Z"/>
|
|
</svg>
|
|
{{ $harvest->varietyVariation->grapeVariety->variety_name ?? 'Unknown' }}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<div class="metric">
|
|
<svg class="icon" style="width: 16px; height: 16px;" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M10 2a4 4 0 00-4 4v1H5a1 1 0 00-.994.89l-1 9A1 1 0 004 18h12a1 1 0 00.994-1.11l-1-9A1 1 0 0015 7h-1V6a4 4 0 00-4-4zm2 5V6a2 2 0 10-4 0v1h4zm-6 3a1 1 0 112 0 1 1 0 01-2 0zm7-1a1 1 0 100 2 1 1 0 000-2z" clip-rule="evenodd"/>
|
|
</svg>
|
|
{{ number_format($harvest->weight, 2) }} kg
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div class="metric">
|
|
<svg class="icon" style="width: 16px; height: 16px;" fill="currentColor" viewBox="0 0 20 20">
|
|
<path d="M9 2a1 1 0 000 2h2a1 1 0 100-2H9z"/>
|
|
<path fill-rule="evenodd" d="M4 5a2 2 0 012-2 3 3 0 003 3h2a3 3 0 003-3 2 2 0 012 2v11a2 2 0 01-2 2H6a2 2 0 01-2-2V5zm3 4a1 1 0 000 2h.01a1 1 0 100-2H7zm3 0a1 1 0 000 2h3a1 1 0 100-2h-3zm-3 4a1 1 0 100 2h.01a1 1 0 100-2H7zm3 0a1 1 0 100 2h3a1 1 0 100-2h-3z" clip-rule="evenodd"/>
|
|
</svg>
|
|
{{ number_format($harvest->sugar_content, 1) }}°NM
|
|
</div>
|
|
</td>
|
|
<td>
|
|
@php
|
|
$qualityColors = [
|
|
'excellent' => ['bg' => 'linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%)', 'color' => '#065f46'],
|
|
'good' => ['bg' => 'linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%)', 'color' => '#1e40af'],
|
|
'fair' => ['bg' => 'linear-gradient(135deg, #fef9c3 0%, #fde68a 100%)', 'color' => '#78350f'],
|
|
'poor' => ['bg' => 'linear-gradient(135deg, #fecaca 0%, #fca5a5 100%)', 'color' => '#7f1d1d'],
|
|
];
|
|
$quality = $harvest->quality ?? 'good';
|
|
$colors = $qualityColors[$quality] ?? $qualityColors['good'];
|
|
@endphp
|
|
<span class="status-badge" style="background: {{ $colors['bg'] }}; color: {{ $colors['color'] }};">
|
|
{{ ucfirst($quality) }}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
@if($harvest->isFullyUsed())
|
|
<span class="status-badge status-used">
|
|
<svg class="icon" style="width: 16px; height: 16px;" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
|
|
</svg>
|
|
Fully Used
|
|
</span>
|
|
@elseif($harvest->isPartiallyUsed())
|
|
<span class="status-badge status-partial">
|
|
<svg class="icon" style="width: 16px; height: 16px;" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-11a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V7z" clip-rule="evenodd"/>
|
|
</svg>
|
|
{{ number_format($harvest->usage_percentage, 0) }}% Used
|
|
</span>
|
|
<div style="font-size: 0.75rem; color: #718096; margin-top: 0.25rem;">
|
|
{{ number_format($harvest->remaining_weight, 2) }} kg left
|
|
</div>
|
|
@else
|
|
<span class="status-badge status-available">
|
|
<svg class="icon" style="width: 16px; height: 16px;" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-11a1 1 0 10-2 0v2H7a1 1 0 100 2h2v2a1 1 0 102 0v-2h2a1 1 0 100-2h-2V7z" clip-rule="evenodd"/>
|
|
</svg>
|
|
Available
|
|
</span>
|
|
@endif
|
|
</td>
|
|
<td>
|
|
@if($harvest->canBeDeleted())
|
|
<form action="{{ route('winemaker.harvests.destroy', $harvest) }}" method="POST" style="display: inline;" onsubmit="return confirm('Are you sure you want to delete this harvest record? This action cannot be undone.');">
|
|
@csrf
|
|
@method('DELETE')
|
|
<button type="submit" class="btn-delete">
|
|
<svg class="icon" style="width: 16px; height: 16px;" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd"/>
|
|
</svg>
|
|
Delete
|
|
</button>
|
|
</form>
|
|
@elseif(!$harvest->isFullyUsed())
|
|
<a href="{{ route('winemaker.harvests.bottle', $harvest->id) }}" class="btn-bottle">
|
|
<svg class="icon" style="width: 16px; height: 16px;" fill="currentColor" viewBox="0 0 24 24">
|
|
<path d="M6,2V10C6,11.11 6.9,12 8,12H10V22H14V12H16C17.11,12 18,11.11 18,10V2H6M8,4H10V6H8V4M12,4H14V6H12V4M16,4H18V6H16V4M8,8H10V10H8V8M12,8H14V10H12V8M16,8H18V10H16V8Z"/>
|
|
</svg>
|
|
Bottle
|
|
</a>
|
|
@else
|
|
<span class="text-muted" style="font-size: 0.875rem; color: #6b7280;">
|
|
Wines in cellar
|
|
</span>
|
|
@endif
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
@if($harvests->hasPages())
|
|
<div style="padding: 1.5rem; border-top: 1px solid #e2e8f0;">
|
|
{{ $harvests->links() }}
|
|
</div>
|
|
@endif
|
|
|
|
@else
|
|
<div class="empty-state">
|
|
<svg class="empty-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"/>
|
|
</svg>
|
|
<h2 class="empty-title">No Harvests Yet</h2>
|
|
<p class="empty-description">Start recording your grape harvests to bottle wines.</p>
|
|
<a href="{{ route('harvests.create') }}" class="btn-primary">
|
|
<svg class="icon" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-11a1 1 0 10-2 0v2H7a1 1 0 100 2h2v2a1 1 0 102 0v-2h2a1 1 0 100-2h-2V7z" clip-rule="evenodd"/>
|
|
</svg>
|
|
Record Harvest
|
|
</a>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
@endsection
|