Skip to content

Commit

Permalink
[ADD] Product Attributes save.
Browse files Browse the repository at this point in the history
  • Loading branch information
Seiger committed Mar 6, 2024
1 parent f331a63 commit a3b3429
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 10 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ of Evolution CMS for seamless and efficient **online commerce**.
- [ ] DateTime Attribute.
- [ ] Image Attribute.
- [ ] File Attribute.
- [ ] Geolocation Attribute.
- [ ] Dynamic Filters for Product Search.
- [ ] Promo Code System.
- [ ] Customer Reviews and Ratings.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ public function up(): void
$table->unsignedInteger('category')->default(0)->index()->comment('Resource ID as Category');
});

Schema::create('s_product_attribute_values', function (Blueprint $table) {
$table->foreignId('product')->comment('Product ID')->constrained('s_products')->cascadeOnDelete();
$table->foreignId('attribute')->comment('Attribute ID')->constrained('s_attributes')->cascadeOnDelete();
$table->unsignedInteger('valueid')->default(0)->index()->comment('This is Id if the attribute value is given as an element from the data set of values');
$table->string('value', 1024)->index()->comment('It using for value if valueid is null');
});

/*
|--------------------------------------------------------------------------
| Create a Product template
Expand Down Expand Up @@ -141,13 +148,14 @@ public function down(): void
| The product's tables structure
|--------------------------------------------------------------------------
*/
Schema::dropIfExists('s_product_attribute_values');
Schema::dropIfExists('s_product_category');
Schema::dropIfExists('s_product_translates');
Schema::dropIfExists('s_products');

/*
|--------------------------------------------------------------------------
| The attributes's tables structure
| The attribute's tables structure
|--------------------------------------------------------------------------
*/
Schema::dropIfExists('s_attribute_category');
Expand Down
4 changes: 2 additions & 2 deletions docs/pages/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ permalink: /

## Welcome to sCommerce!

> [!IMPORTANT]
> sCommerce not stable yet. It active development.
{% include callout.html text="sCommerce not stable yet. It active development." color="skyred" %}

**sCommerce** stands as a comprehensive suite of **e-commerce** tools meticulously crafted
for Evolution CMS. Tailored to empower Evolution CMS users, this dynamic package
Expand Down Expand Up @@ -48,6 +47,7 @@ of Evolution CMS for seamless and efficient **online commerce**.
- [ ] DateTime Attribute.
- [ ] Image Attribute.
- [ ] File Attribute.
- [ ] Geolocation Attribute.
- [ ] Dynamic Filters for Product Search.
- [ ] Promo Code System.
- [ ] Customer Reviews and Ratings.
Expand Down
4 changes: 4 additions & 0 deletions lang/en/global.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
'type_attr_datetime' => 'Datetime Picker',
'type_attr_image' => 'Image',
'type_attr_file' => 'File',
'type_attr_geolocation' => 'Geolocation',
'helptext' => 'Help text',
'helptext_help' => 'Description about this Attribute in adminpanel.',
'attribute_name_help' => 'This name will be displayed when the attribute is output.',
Expand All @@ -123,4 +124,7 @@
'caption' => 'Caption',
'list_texts' => 'List of texts',
'text_block' => 'Text block',
'prodattributes' => 'Attributes',
'prodattributes_icon' => 'fas fa-paperclip',
'prodattributes_help' => 'List of product attributes.',
];
6 changes: 5 additions & 1 deletion lang/ru/global.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,15 @@
'type_attr_radio' => 'Радиокнопка',
'type_attr_select' => 'Вибор из списка',
'type_attr_multiselect' => 'Мультивибор',
'type_attr_text' => 'Текстовое поле',
'type_attr_text' => 'Текст',
'type_attr_textarea' => 'Текстовая область',
'type_attr_richtext' => 'Визуальный редактор',
'type_attr_color' => 'Палитра цветов',
'type_attr_date' => 'Вибор даты',
'type_attr_datetime' => 'Дата и время',
'type_attr_image' => 'Изображение',
'type_attr_file' => 'Файл',
'type_attr_geolocation' => 'Геолокация',
'helptext' => 'Справочный текст',
'helptext_help' => 'Описание этого атрибута в палитре администратора.',
'attribute_name_help' => 'Это название отображается при выводе атрибута.',
Expand All @@ -122,4 +123,7 @@
'caption' => 'Подпись',
'list_texts' => 'Список текстов',
'text_block' => 'Текстовый блок',
'prodattributes' => 'Атрибуты',
'prodattributes_icon' => 'fas fa-paperclip',
'prodattributes_help' => 'Список атрибутов товара.',
];
6 changes: 5 additions & 1 deletion lang/uk/global.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,15 @@
'type_attr_radio' => 'Радіокнопка',
'type_attr_select' => 'Вибір із списка',
'type_attr_multiselect' => 'Мультивибір',
'type_attr_text' => 'Текстове поле',
'type_attr_text' => 'Текст',
'type_attr_textarea' => 'Текстова область',
'type_attr_richtext' => 'Візуальний редактор',
'type_attr_color' => 'Палітра кольорів',
'type_attr_date' => 'Вибір дати',
'type_attr_datetime' => 'Дата й час',
'type_attr_image' => 'Зображення',
'type_attr_file' => 'Файл',
'type_attr_geolocation' => 'Геолокація',
'helptext' => 'Довідковий текст',
'helptext_help' => 'Опис цього атрибута в панелі адміністратора.',
'attribute_name_help' => 'Ця назва буде відображатись при виводі атрибута.',
Expand All @@ -122,4 +123,7 @@
'caption' => 'Підпис',
'list_texts' => 'Список текстів',
'text_block' => 'Текстовий блок',
'prodattributes' => 'Атрибути',
'prodattributes_icon' => 'fas fa-paperclip',
'prodattributes_help' => 'Список атрибутів товара.',
];
74 changes: 72 additions & 2 deletions module/sCommerceModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,68 @@
$q->whereIn('category', $categoryParentsIds);
})->get();

$attrValues = $product->attrValues->mapWithKeys(function($value){
return [$value->id => $value];
})->all();

$data['product'] = $product;
$data['items'] = $attributes;
$data['attrValues'] = $attrValues;
break;
case "prodattributesSave":
$filters = ['attribute'];
$all = request()->all();
$requestId = (int)request()->input('i', 0);
$product = sCommerce::getProduct($requestId);

if ($product) {
$product->attrValues()->detach();
$categoryParentsIds = $sCommerceController->categoryParentsIds($product->category);
$attributes = sAttribute::lang($sCommerceController->langDefault())->whereHas('categories', function ($q) use ($categoryParentsIds) {
$q->whereIn('category', $categoryParentsIds);
})->get();

foreach ($filters as $filter) {
foreach ($all as $key => $value) {
if (str_starts_with($key, $filter . '__')) {
$key = str_replace($filter . '__', '', $key);
$attribute = $attributes->where('id', $key)->first();
if ($attribute) {
switch ($attribute->type) {
case sAttribute::TYPE_ATTR_NUMBER :
if (trim($value)) {
if (is_float($value)) {
$value = floatval(str_replace(',', '.', $value));
} else {
$value = intval($value);
}
$product->attrValues()->attach($key, ['valueid' => 0, 'value' => $value]);
}
break;
case sAttribute::TYPE_ATTR_TEXT :
if (is_array($value) && count($value)) {
$vals = [];
foreach ($value as $k => $v) {
if (trim($v)) {
$vals[$k] = trim($v);
}
}
if (count($vals)) {
$product->attrValues()->attach($key, ['valueid' => 0, 'value' => json_encode($vals)]);
}
}
break;
}
}
}
}
}
}

$back = str_replace('&i=0', '&i=' . $product->id, (request()->back ?? '&get=prodattributes'));
return header('Location: ' . sCommerce::moduleUrl() . $back);
case "content":
$tabs = ['product', 'content'];
$tabs = ['product'];
$iUrl = trim($iUrl) ?: '&i=0';
$requestId = (int)request()->input('i', 0);
$requestLang = request()->input('lang');
Expand Down Expand Up @@ -248,10 +305,24 @@
}
}

$product = sCommerce::getProduct($content->product);
$categoryParentsIds = [0];
if ($product->category) {
$categoryParentsIds = $sCommerceController->categoryParentsIds($product->category);
}
$attributes = sAttribute::whereHas('categories', function ($q) use ($categoryParentsIds) {
$q->whereIn('category', $categoryParentsIds);
})->get();
if ($attributes->count()) {
$tabs[] = 'prodattributes';
}

$data['item'] = $content;
$data['buttons'] = $buttons;
$data['elements'] = $elements;
$data['chunks'] = $chunks;

$tabs[] = 'content';
break;
case "contentSave":
$requestId = (int)request()->input('i', 0);
Expand Down Expand Up @@ -330,7 +401,6 @@
default :
$query->orderBy($order, $direc);
break;

}

$data['items'] = $query->paginate($perpage);
Expand Down
2 changes: 2 additions & 0 deletions src/Models/sAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class sAttribute extends Model
//const TYPE_ATTR_DATETIME = 10;
//const TYPE_ATTR_IMAGE = 11;
//const TYPE_ATTR_FILE = 12;
//const TYPE_ATTR_GEOLOCATION = 13;
//const TYPE_ATTR_DATERANGE = 14;

/**
* Return list of type of input the attribute codes and labels
Expand Down
17 changes: 17 additions & 0 deletions src/Models/sProduct.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,23 @@ public function texts()
return $this->hasMany(sProductTranslate::class, 'product', 'id');
}

/**
* Get the attributes associated with the product.
*
* This method returns a BelongsToMany relationship with the sAttributeValue model.
* The intermediate table used for the relationship is 's_product_attribute_values'.
* The foreign key on the s_product_attribute_values table for the attribute model is 'attribute'.
* The foreign key on the s_product_attribute_values table for the product model is 'product'.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function attrValues()
{
return $this->belongsToMany(sAttribute::class, 's_product_attribute_values', 'product', 'attribute')
->withPivot('valueid', 'value')
->orderBy('position');
}

/**
* Get the link attribute for the current object
*
Expand Down
6 changes: 3 additions & 3 deletions views/partials/attributeNumber.blade.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<div class="row-col col-12">
<div class="row form-row">
<div class="col-auto col-title">
<label for="attributes{{$item->id}}">{{$item->pagetitle}}</label>
<label for="attribute__{{$item->id}}">{{$item->pagetitle}}</label>
@if(trim($item->helptext))<i class="fa fa-question-circle" data-tooltip="{{$item->helptext}}"></i>@endif
</div>
<div class="input-group col">
<span class="input-group-text"><i class="fab fa-draft2digital"></i></span>
<input type="number" id="attributes{{$item->id}}" name="attributes[{{$item->id}}]" class="form-control" value="" onchange="documentDirty=true;">
<span class="input-group-text"><small>@lang('sCommerce::global.type_attr_number')</small></span>
<input type="number" id="attribute__{{$item->id}}" name="attribute__{{$item->id}}" class="form-control" value="{{$attrValues[$item->id]->pivot->value ?? ''}}" onchange="documentDirty=true;">
</div>
</div>
</div>
15 changes: 15 additions & 0 deletions views/partials/attributeText.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@php($vals = json_decode($attrValues[$item->id]->pivot->value ?? '', true))
<div class="row-col col-12">
<div class="row form-row">
<div class="col-auto col-title">
<label for="attribute__{{$item->id}}">{{$item->pagetitle}}</label>
@if(trim($item->helptext))<i class="fa fa-question-circle" data-tooltip="{{$item->helptext}}"></i>@endif
</div>
<div class="col">
<div class="input-group">
<span class="input-group-text"><small>@lang('sCommerce::global.type_attr_text')</small></span>
<input type="text" id="attribute__{{$item->id}}" name="attribute__{{$item->id}}[base]" class="form-control" value="{{$vals['base'] ?? ''}}" onchange="documentDirty=true;">
</div>
</div>
</div>
</div>
3 changes: 3 additions & 0 deletions views/prodattributesTab.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
@case(\Seiger\sCommerce\Models\sAttribute::TYPE_ATTR_NUMBER)
@include('sCommerce::partials.attributeNumber')
@break
@case(\Seiger\sCommerce\Models\sAttribute::TYPE_ATTR_TEXT)
@include('sCommerce::partials.attributeText')
@break
@endswitch
@endforeach
</div>
Expand Down

0 comments on commit a3b3429

Please sign in to comment.