11 Commits

12 changed files with 204 additions and 78 deletions

View File

@@ -22,7 +22,7 @@ class TariffsDataTable extends DataTable
{ {
$datatables $datatables
->editColumn('status', function (Tariff $tariff) { ->editColumn('status', function (Tariff $tariff) {
return Tariffs::getStatus($tariff['status_id']); return Tariffs::getStatusBadge($tariff['status_id']);
}) })
->editColumn('sale_channels2', function (Tariff $tariff) { ->editColumn('sale_channels2', function (Tariff $tariff) {
$html = ''; $html = '';
@@ -32,7 +32,7 @@ class TariffsDataTable extends DataTable
return $html; return $html;
}) })
->rawColumns(['sale_channels2', 'action']); ->rawColumns(['status', 'sale_channels2', 'action']);
return parent::modifier($datatables); return parent::modifier($datatables);
} }

View File

@@ -26,6 +26,7 @@ class ArticleController extends Controller
'article_natures' => ArticleNatures::getOptions(), 'article_natures' => ArticleNatures::getOptions(),
'categories' => Categories::getOptions(), 'categories' => Categories::getOptions(),
'tags' => Tags::getOptionsFullName(), 'tags' => Tags::getOptionsFullName(),
'filters' => request()->only(['article_nature_id', 'category_id', 'tag_id']),
]; ];
return $dataTable->render('Admin.Shop.Articles.list', $data); return $dataTable->render('Admin.Shop.Articles.list', $data);

View File

@@ -218,7 +218,7 @@ class Article extends Model implements HasMedia
public function scopeWithAvailableOffers($query, $saleChannelId = false) public function scopeWithAvailableOffers($query, $saleChannelId = false)
{ {
return $query->whereHas('offers', function ($query) use ($saleChannelId) { return $query->visible()->whereHas('offers', function ($query) use ($saleChannelId) {
$query->active()->byStockAvailable(); $query->active()->byStockAvailable();
if ($saleChannelId) { if ($saleChannelId) {

View File

@@ -67,6 +67,11 @@ class Articles
return $data; return $data;
} }
public static function getVisibilityMap()
{
return Article::pluck('visible', 'id')->toArray();
}
public static function getAll() public static function getAll()
{ {
return Article::orderBy('name', 'asc')->get(); return Article::orderBy('name', 'asc')->get();
@@ -312,8 +317,6 @@ class Articles
case 'merchandise': case 'merchandise':
$model = $model->merchandise(); $model = $model->merchandise();
break; break;
default:
$model = $model->botanic();
} }
return $model; return $model;

View File

@@ -16,7 +16,11 @@ class Offers
{ {
return [ return [
'articles' => Articles::getOptionsWithNature(), 'articles' => Articles::getOptionsWithNature(),
'article_visibilities' => Articles::getVisibilityMap(),
'tariffs' => Tariffs::getOptions(), 'tariffs' => Tariffs::getOptions(),
'tariff_statuses' => Tariffs::getStatusMap(),
'tariff_status_labels' => Tariffs::getStatuses(),
'tariff_pricelist_counts' => Tariffs::getPriceListCountMap(),
'variations' => Variations::getOptions(), 'variations' => Variations::getOptions(),
]; ];
} }

View File

@@ -50,11 +50,30 @@ class Tariffs
return self::getStatuses()[$status_id]; return self::getStatuses()[$status_id];
} }
public static function getStatusBadge($status_id)
{
$colors = ['success', 'warning', 'secondary', 'danger'];
$label = self::getStatus($status_id);
$color = $colors[$status_id] ?? 'secondary';
return '<span class="badge badge-'.$color.'">'.$label.'</span>';
}
public static function getStatuses() public static function getStatuses()
{ {
return ['Actif', 'Suspendu', 'Invisible', 'Obsolete']; return ['Actif', 'Suspendu', 'Invisible', 'Obsolete'];
} }
public static function getStatusMap()
{
return Tariff::pluck('status_id', 'id')->toArray();
}
public static function getPriceListCountMap()
{
return Tariff::withCount('price_lists')->pluck('price_lists_count', 'id')->toArray();
}
public static function getModel() public static function getModel()
{ {
return Tariff::query(); return Tariff::query();

View File

@@ -436,3 +436,17 @@ div.megamenu ul.megamenu li.megamenu.level1
max-width: 100%; max-width: 100%;
} }
} }
/* -- Titres des rayons -- */
.shelve-title {
font-size: 2em;
}
/* -- Responsive: très petites résolutions (< 430px) -- */
@media (max-width: 429.98px) {
.shelve-title {
font-size: 1.4em;
}
}

View File

@@ -1,3 +1,12 @@
@if ($category['id'] ?? false)
<div class="d-flex justify-content-end mb-3">
<a href="{{ route('Admin.Shop.Articles.index', ['category_id' => $category['id']]) }}" class="btn btn-outline-primary">
Voir les articles de ce rayon
<i class="fa fa-external-link"></i>
</a>
</div>
@endif
<div class="row"> <div class="row">
<div class="col-9"> <div class="col-9">
<div class="row mb-3"> <div class="row mb-3">

View File

@@ -14,45 +14,66 @@
<div class="col-12"> <div class="col-12">
<div class="row mb-3"> <div class="row mb-3">
<div class="col-12"> <div class="col-12">
@include('components.form.select', [ <div class="d-flex align-items-end">
'name' => 'article_id', <div class="flex-grow-1">
'id_name' => 'article_id', @include('components.form.select', [
'list' => $articles ?? null, 'name' => 'article_id',
'value' => $offer['article_id'] ?? null, 'id_name' => 'article_id',
'with_empty' => '', 'list' => $articles ?? null,
'class' => 'select2 select_article', 'value' => $offer['article_id'] ?? null,
'label' => 'Article', 'with_empty' => '',
'required' => true, 'class' => 'select2 select_article',
]) 'label' => 'Article',
'required' => true,
])
</div>
<a id="edit-article-link" href="#" class="btn btn-sm btn-outline-secondary ml-2 mb-1" title="Modifier l'article" style="display:none;">
<i class="fa fa-external-link"></i>
</a>
</div>
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-4"> <div class="col-4">
@include('components.form.select', [ <div class="d-flex align-items-end">
'name' => 'variation_id', <div class="flex-grow-1">
'id_name' => 'variation_id', @include('components.form.select', [
'list' => $variations ?? null, 'name' => 'variation_id',
'value' => $offer['variation_id'] ?? null, 'id_name' => 'variation_id',
'with_empty' => '', 'list' => $variations ?? null,
'class' => 'select2 select_variation', 'value' => $offer['variation_id'] ?? null,
'label' => __('shop.packages.name'), 'with_empty' => '',
'required' => true, 'class' => 'select2 select_variation',
]) 'label' => __('shop.packages.name'),
'required' => true,
])
</div>
<a id="edit-variation-link" href="#" class="btn btn-sm btn-outline-secondary ml-2 mb-1" title="Modifier la déclinaison" style="display:none;">
<i class="fa fa-external-link"></i>
</a>
</div>
</div> </div>
<div class="col-4"> <div class="col-4">
@include('components.form.select', [ <div class="d-flex align-items-end">
'name' => 'tariff_id', <div class="flex-grow-1">
'id_name' => 'tariff_id', @include('components.form.select', [
'list' => $tariffs ?? null, 'name' => 'tariff_id',
'value' => $offer['tariff_id'] ?? null, 'id_name' => 'tariff_id',
'with_empty' => '', 'list' => $tariffs ?? null,
'class' => 'select2 select_tariffs', 'value' => $offer['tariff_id'] ?? null,
'label' => 'Tarif', 'with_empty' => '',
'required' => true, 'class' => 'select2 select_tariffs',
]) 'label' => 'Tarif',
'required' => true,
])
</div>
<a id="edit-tariff-link" href="#" class="btn btn-sm btn-outline-secondary ml-2 mb-1" title="Modifier le tarif" style="display:none;">
<i class="fa fa-external-link"></i>
</a>
</div>
</div> </div>
<div class="col-4"> <div class="col-2">
@include('components.form.input', [ @include('components.form.input', [
'name' => 'weight', 'name' => 'weight',
'value' => $offer['weight'] ?? null, 'value' => $offer['weight'] ?? null,
@@ -60,6 +81,15 @@
'required' => true, 'required' => true,
]) ])
</div> </div>
<div class="col-2">
<input type="hidden" name="status_id" value="0">
@include('components.form.toggle', [
'name' => 'status_id',
'value' => $offer['status_id'] ?? 0,
'label' => 'Actif',
'size' => 'md',
])
</div>
</div> </div>
@component('components.card', ['title' => 'Disponibilité', 'class' => 'mt-5']) @component('components.card', ['title' => 'Disponibilité', 'class' => 'mt-5'])
@@ -122,5 +152,80 @@
initChevron(); initChevron();
initSaveForm('#offer-form'); initSaveForm('#offer-form');
initSelect2(); initSelect2();
$('#status_id').bootstrapToggle();
// Article visibility badges in select2
var articleVisibilities = {!! json_encode($article_visibilities ?? (object)[]) !!};
function formatArticle(item) {
if (!item.id) return item.text;
var visible = articleVisibilities[item.id];
var badge = (visible == 1)
? '<span class="badge badge-success" style="font-size:0.75em;margin-left:4px;">Visible</span>'
: '<span class="badge badge-warning" style="font-size:0.75em;margin-left:4px;">Invisible</span>';
return $('<span style="display:flex;justify-content:space-between;align-items:center;width:100%;">' + item.text + badge + '</span>');
}
$('#article_id').select2('destroy').select2({
placeholder: "{{ __('select_a_value') }}",
allowClear: false,
width: { value: '100%' },
templateResult: formatArticle,
templateSelection: formatArticle
});
// Tariff status badges in select2
var tariffStatuses = {!! json_encode($tariff_statuses ?? (object)[]) !!};
var tariffStatusLabels = {!! json_encode($tariff_status_labels ?? []) !!};
var tariffStatusColors = {0: '#28a745', 1: '#ffc107', 2: '#6c757d', 3: '#dc3545'};
var tariffPLCounts = {!! json_encode($tariff_pricelist_counts ?? (object)[]) !!};
function formatTariff(item) {
if (!item.id) return item.text;
var statusId = tariffStatuses[item.id];
var color = tariffStatusColors[statusId] || '#6c757d';
var label = tariffStatusLabels[statusId] || '';
var plCount = tariffPLCounts[item.id] || 0;
var warning = plCount == 0 ? '<span style="margin-left:4px;cursor:help;" title="Aucune liste de prix"><i class="fas fa-exclamation-triangle text-danger" style="font-size:1.4em;vertical-align:-2px;"></i></span>' : '';
return $('<span style="display:flex;justify-content:space-between;align-items:center;width:100%;">' + item.text + '<span>' + warning + '<span class="badge" style="background:' + color + ';color:#fff;font-size:0.75em;margin-left:4px;">' + label + '</span></span></span>');
}
$('#tariff_id').select2('destroy').select2({
placeholder: "{{ __('select_a_value') }}",
allowClear: false,
width: { value: '100%' },
templateResult: formatTariff,
templateSelection: formatTariff
});
function updateEditLink(selectId, linkId, routeTemplate) {
var val = $('#' + selectId).val();
var $link = $('#' + linkId);
if (val) {
$link.attr('href', routeTemplate.replace('__ID__', val)).show();
} else {
$link.hide();
}
}
var articleRoute = '{{ route('Admin.Shop.Articles.edit', ['id' => '__ID__']) }}';
var variationRoute = '{{ route('Admin.Shop.Variations.edit', ['id' => '__ID__']) }}';
var tariffRoute = '{{ route('Admin.Shop.Tariffs.edit', ['id' => '__ID__']) }}';
// Init on page load
updateEditLink('article_id', 'edit-article-link', articleRoute);
updateEditLink('variation_id', 'edit-variation-link', variationRoute);
updateEditLink('tariff_id', 'edit-tariff-link', tariffRoute);
// Update on change
$('#article_id').on('change', function() {
updateEditLink('article_id', 'edit-article-link', articleRoute);
});
$('#variation_id').on('change', function() {
updateEditLink('variation_id', 'edit-variation-link', variationRoute);
});
$('#tariff_id').on('change', function() {
updateEditLink('tariff_id', 'edit-tariff-link', tariffRoute);
});
</script> </script>
@endpush @endpush

View File

@@ -1,9 +1,6 @@
@php @php
// Check if article is not visible OR has no offers at all // Check if article is not visible OR has no offers at all
$hasNoOffers = empty($article['offers']['semences'] ?? false) $hasNoOffers = empty($article['offers'] ?? false) || !array_filter($article['offers']);
&& empty($article['offers']['plants'] ?? false)
&& empty($article['offers']['legumes'] ?? false)
&& empty($article['offers']['marchandise'] ?? false);
$shouldShowComingSoon = !($article['visible'] ?? true) || $hasNoOffers; $shouldShowComingSoon = !($article['visible'] ?? true) || $hasNoOffers;
@endphp @endphp
@@ -19,41 +16,16 @@
</div> </div>
@else @else
{{-- Display normal offers for visible articles with available offers --}} {{-- Display normal offers for visible articles with available offers --}}
@if ($article['offers']['semences'] ?? false) @foreach ($article['offers'] as $natureKey => $natureOffers)
@include('Shop.Articles.partials.addBasket', [ @if (!empty($natureOffers))
'data' => $article['offers']['semences'], @include('Shop.Articles.partials.addBasket', [
'title' => 'Semences', 'data' => $natureOffers,
'model' => 'semences', 'title' => ucfirst($natureKey),
'bgClass' => 'bg-green-light', 'model' => $natureKey,
]) 'bgClass' => 'bg-green-light',
@endif ])
@endif
@if ($article['offers']['plants'] ?? false) @endforeach
@include('Shop.Articles.partials.addBasket', [
'data' => $article['offers']['plants'],
'title' => 'Plants',
'model' => 'plants',
'bgClass' => 'bg-green-light',
])
@endif
@if ($article['offers']['legumes'] ?? false)
@include('Shop.Articles.partials.addBasket', [
'data' => $article['offers']['legumes'],
'title' => 'Légumes',
'model' => 'legumes',
'bgClass' => 'bg-green-light',
])
@endif
@if ($article['offers']['marchandise'] ?? false)
@include('Shop.Articles.partials.addBasket', [
'data' => $article['offers']['marchandise'],
'title' => 'Marchandises',
'model' => 'marchandise',
'bgClass' => 'bg-green-light',
])
@endif
@endif @endif
@include('load.basket') @include('load.basket')

View File

@@ -19,9 +19,8 @@
</div> </div>
<div class="col-lg-5 col-xs-12 text-justify"> <div class="col-lg-5 col-xs-12 text-justify">
{!! $article['description']['variety'] ?? null !!} {!! $article['description']['variety'] ?? null !!}
{!! $article['description']['semences'] ?? null !!}
{!! $article['description']['plants'] ?? null !!}
{!! $article['description']['merchandise'] ?? null !!} {!! $article['description']['merchandise'] ?? null !!}
{!! $article['description']['description'] ?? null !!}
@if ($article['description']['plus'] ?? false) @if ($article['description']['plus'] ?? false)
<h3>Spécificités</h3> <h3>Spécificités</h3>

View File

@@ -2,7 +2,7 @@
<div class="mb-5 bg-green-light shadow2"> <div class="mb-5 bg-green-light shadow2">
<div class="row"> <div class="row">
<div class="col-6"> <div class="col-6">
<h1 class="p-2 green" style="font-size: 2em;">{{ $shelve['name'] }}</h1> <h1 class="p-2 green shelve-title">{{ $shelve['name'] }}</h1>
</div> </div>
<div class="col-6 text-right"> <div class="col-6 text-right">
<a href="{{ route('Shop.Categories.show', ['id' => $shelve['id']]) }}" <a href="{{ route('Shop.Categories.show', ['id' => $shelve['id']]) }}"