425 lines
14 KiB
PHP
425 lines
14 KiB
PHP
@extends('layouts.winemaker')
|
|
|
|
@section('title', 'Sales Management - 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;
|
|
}
|
|
|
|
.wines-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
.wines-table thead {
|
|
background: linear-gradient(135deg, #f7fafc 0%, #edf2f7 100%);
|
|
}
|
|
|
|
.wines-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;
|
|
}
|
|
|
|
.wines-table td {
|
|
padding: 1rem 1.5rem;
|
|
border-bottom: 1px solid #e2e8f0;
|
|
color: #2d3748;
|
|
}
|
|
|
|
.wines-table tbody tr {
|
|
transition: background 0.2s;
|
|
}
|
|
|
|
.wines-table tbody tr:hover {
|
|
background: #f7fafc;
|
|
}
|
|
|
|
.wine-id {
|
|
font-weight: 600;
|
|
color: #4a5568;
|
|
}
|
|
|
|
.wine-name-cell {
|
|
font-weight: 600;
|
|
color: #2d3748;
|
|
font-size: 1rem;
|
|
}
|
|
|
|
.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;
|
|
}
|
|
|
|
.type-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;
|
|
}
|
|
|
|
.type-red {
|
|
background: linear-gradient(135deg, #fecaca 0%, #fca5a5 100%);
|
|
color: #7f1d1d;
|
|
}
|
|
|
|
.type-white {
|
|
background: linear-gradient(135deg, #fef9c3 0%, #fde68a 100%);
|
|
color: #78350f;
|
|
}
|
|
|
|
.type-rose {
|
|
background: linear-gradient(135deg, #fbcfe8 0%, #f9a8d4 100%);
|
|
color: #831843;
|
|
}
|
|
|
|
.catalog-status {
|
|
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-in-catalog {
|
|
background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);
|
|
color: #065f46;
|
|
}
|
|
|
|
.status-not-in-catalog {
|
|
background: linear-gradient(135deg, #e5e7eb 0%, #d1d5db 100%);
|
|
color: #374151;
|
|
}
|
|
|
|
.btn-add-sale {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.5rem 1rem;
|
|
background: linear-gradient(135deg, #48bb78 0%, #38a169 100%);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 8px;
|
|
font-weight: 500;
|
|
font-size: 0.875rem;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.btn-add-sale:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 4px 12px rgba(72, 187, 120, 0.4);
|
|
}
|
|
|
|
.btn-add-sale:disabled {
|
|
opacity: 0.5;
|
|
cursor: not-allowed;
|
|
transform: none;
|
|
}
|
|
|
|
.btn-remove-sale {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.5rem 1rem;
|
|
background: linear-gradient(135deg, #f56565 0%, #e53e3e 100%);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 8px;
|
|
font-weight: 500;
|
|
font-size: 0.875rem;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.btn-remove-sale:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 4px 12px rgba(245, 101, 101, 0.4);
|
|
}
|
|
|
|
.btn-edit {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.5rem 1rem;
|
|
background: white;
|
|
color: #4a5568;
|
|
border: 2px solid #e2e8f0;
|
|
border-radius: 8px;
|
|
font-weight: 500;
|
|
font-size: 0.875rem;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.btn-edit:hover {
|
|
background: #f7fafc;
|
|
border-color: #cbd5e0;
|
|
}
|
|
|
|
.price-cell {
|
|
font-weight: 600;
|
|
color: #2d3748;
|
|
font-size: 1rem;
|
|
}
|
|
|
|
.stock-cell {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
color: #4a5568;
|
|
}
|
|
|
|
.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;
|
|
}
|
|
|
|
.actions-cell {
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
align-items: center;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.wines-table {
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.wines-table th,
|
|
.wines-table td {
|
|
padding: 0.75rem 1rem;
|
|
}
|
|
|
|
.actions-cell {
|
|
flex-direction: column;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<div class="page-header">
|
|
<h1 class="page-title">Sales Management</h1>
|
|
<p class="page-subtitle">Manage wines available for sale in the catalog</p>
|
|
</div>
|
|
|
|
<div class="content-card">
|
|
@if($wines->count() > 0)
|
|
<div class="table-container">
|
|
<table class="wines-table">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>Wine Name</th>
|
|
<th>Vintage</th>
|
|
<th>Type</th>
|
|
<th>Variety</th>
|
|
<th>Stock</th>
|
|
<th>Price</th>
|
|
<th>Catalog Status</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach($wines as $wine)
|
|
<tr>
|
|
<td>
|
|
<span class="wine-id">#{{ $wine->id }}</span>
|
|
</td>
|
|
<td>
|
|
<div class="wine-name-cell">{{ $wine->wine_name }}</div>
|
|
</td>
|
|
<td>
|
|
<span class="variety-badge">{{ $wine->vintage }}</span>
|
|
</td>
|
|
<td>
|
|
<span class="type-badge type-{{ $wine->wine_type }}">
|
|
{{ ucfirst($wine->wine_type) }}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
{{ $wine->grapeVariety->variety_name ?? 'N/A' }}
|
|
</td>
|
|
<td>
|
|
<div class="stock-cell">
|
|
<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>
|
|
{{ $wine->bottles_in_stock }}
|
|
</div>
|
|
</td>
|
|
<td>
|
|
@if($wine->price_per_bottle)
|
|
<div class="price-cell">${{ number_format($wine->price_per_bottle, 2) }}</div>
|
|
@else
|
|
<span style="color: #dc3545; font-size: 0.875rem;">Not set</span>
|
|
@endif
|
|
</td>
|
|
<td>
|
|
@if($wine->status == 'ready' && $wine->bottles_in_stock > 0 && $wine->price_per_bottle)
|
|
<span class="catalog-status status-in-catalog">
|
|
<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>
|
|
In Catalog
|
|
</span>
|
|
@else
|
|
<span class="catalog-status status-not-in-catalog">
|
|
<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 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
|
|
</svg>
|
|
Not Listed
|
|
</span>
|
|
@endif
|
|
</td>
|
|
<td>
|
|
<div class="actions-cell">
|
|
@if($wine->status == 'ready' && $wine->bottles_in_stock > 0 && $wine->price_per_bottle)
|
|
<form action="{{ route('winemaker.wines.remove-from-sales', $wine->id) }}" method="POST" style="display: inline;">
|
|
@csrf
|
|
<button type="submit" class="btn-remove-sale">
|
|
<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 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
|
|
</svg>
|
|
Remove from Catalog
|
|
</button>
|
|
</form>
|
|
@else
|
|
<form action="{{ route('winemaker.wines.add-to-sales', $wine->id) }}" method="POST" style="display: inline;">
|
|
@csrf
|
|
<button type="submit" class="btn-add-sale"
|
|
@if(!$wine->price_per_bottle) disabled title="Set price first"
|
|
@elseif($wine->status === 'in_production') disabled title="Wine still in production" @endif>
|
|
<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>
|
|
Add to Catalog
|
|
</button>
|
|
</form>
|
|
@endif
|
|
<a href="{{ route('wines.edit', $wine->id) }}" class="btn-edit">
|
|
<svg class="icon" style="width: 16px; height: 16px;" fill="currentColor" viewBox="0 0 20 20">
|
|
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z"/>
|
|
</svg>
|
|
Edit
|
|
</a>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
@if($wines->hasPages())
|
|
<div style="padding: 1.5rem; border-top: 1px solid #e2e8f0;">
|
|
{{ $wines->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="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"/>
|
|
</svg>
|
|
<h2 class="empty-title">No Wines Ready for Sale</h2>
|
|
<p class="empty-description">Wines must have "Ready" status and available stock to be listed for sale.</p>
|
|
<a href="{{ route('winemaker.cellar.index') }}" class="btn-primary">
|
|
<svg class="icon" 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>
|
|
View Cellar
|
|
</a>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
@endsection
|