11 Commits

12 changed files with 204 additions and 78 deletions

View File

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

View File

@@ -26,6 +26,7 @@ class ArticleController extends Controller
'article_natures' => ArticleNatures::getOptions(),
'categories' => Categories::getOptions(),
'tags' => Tags::getOptionsFullName(),
'filters' => request()->only(['article_nature_id', 'category_id', 'tag_id']),
];
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)
{
return $query->whereHas('offers', function ($query) use ($saleChannelId) {
return $query->visible()->whereHas('offers', function ($query) use ($saleChannelId) {
$query->active()->byStockAvailable();
if ($saleChannelId) {

View File

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

View File

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

View File

@@ -50,11 +50,30 @@ class Tariffs
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()
{
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()
{
return Tariff::query();

View File

@@ -436,3 +436,17 @@ div.megamenu ul.megamenu li.megamenu.level1
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="col-9">
<div class="row mb-3">

View File

@@ -14,45 +14,66 @@
<div class="col-12">
<div class="row mb-3">
<div class="col-12">
@include('components.form.select', [
'name' => 'article_id',
'id_name' => 'article_id',
'list' => $articles ?? null,
'value' => $offer['article_id'] ?? null,
'with_empty' => '',
'class' => 'select2 select_article',
'label' => 'Article',
'required' => true,
])
<div class="d-flex align-items-end">
<div class="flex-grow-1">
@include('components.form.select', [
'name' => 'article_id',
'id_name' => 'article_id',
'list' => $articles ?? null,
'value' => $offer['article_id'] ?? null,
'with_empty' => '',
'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 class="row mb-3">
<div class="col-4">
@include('components.form.select', [
'name' => 'variation_id',
'id_name' => 'variation_id',
'list' => $variations ?? null,
'value' => $offer['variation_id'] ?? null,
'with_empty' => '',
'class' => 'select2 select_variation',
'label' => __('shop.packages.name'),
'required' => true,
])
<div class="d-flex align-items-end">
<div class="flex-grow-1">
@include('components.form.select', [
'name' => 'variation_id',
'id_name' => 'variation_id',
'list' => $variations ?? null,
'value' => $offer['variation_id'] ?? null,
'with_empty' => '',
'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 class="col-4">
@include('components.form.select', [
'name' => 'tariff_id',
'id_name' => 'tariff_id',
'list' => $tariffs ?? null,
'value' => $offer['tariff_id'] ?? null,
'with_empty' => '',
'class' => 'select2 select_tariffs',
'label' => 'Tarif',
'required' => true,
])
<div class="d-flex align-items-end">
<div class="flex-grow-1">
@include('components.form.select', [
'name' => 'tariff_id',
'id_name' => 'tariff_id',
'list' => $tariffs ?? null,
'value' => $offer['tariff_id'] ?? null,
'with_empty' => '',
'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 class="col-4">
<div class="col-2">
@include('components.form.input', [
'name' => 'weight',
'value' => $offer['weight'] ?? null,
@@ -60,6 +81,15 @@
'required' => true,
])
</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>
@component('components.card', ['title' => 'Disponibilité', 'class' => 'mt-5'])
@@ -122,5 +152,80 @@
initChevron();
initSaveForm('#offer-form');
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>
@endpush

View File

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

View File

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

View File

@@ -2,7 +2,7 @@
<div class="mb-5 bg-green-light shadow2">
<div class="row">
<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 class="col-6 text-right">
<a href="{{ route('Shop.Categories.show', ['id' => $shelve['id']]) }}"