Recettes : c'est bon sur l'ajout des produits, on ataque la liste des étapes

This commit is contained in:
2021-05-08 10:02:07 +02:00
parent 5e1fe56d56
commit 9a57b8f701
16 changed files with 246 additions and 178 deletions

View File

@@ -20,8 +20,9 @@
<route id="recipe.search_product" path="/admin/module/Recettes/search-product"> <route id="recipe.search_product" path="/admin/module/Recettes/search-product">
<default key="_controller">Recettes\Controller\BackController::searchProduct</default> <default key="_controller">Recettes\Controller\BackController::searchProduct</default>
</route> </route>
<route id="recipe.search_combination" path="/admin/module/Recettes/search-combination"> <route id="recipe.add_product" path="/admin/module/Recettes/add-product/{contentId}">
<default key="_controller">Recettes\Controller\BackController::searchCombination</default> <default key="_controller">Recettes\Controller\BackController::addProduct</default>
<requirement key="contentId">\d+</requirement>
</route> </route>
</routes> </routes>

View File

@@ -19,12 +19,18 @@ use Thelia\Core\Event\Content\ContentUpdateEvent;
use Thelia\Core\HttpFoundation\JsonResponse; use Thelia\Core\HttpFoundation\JsonResponse;
use Thelia\Core\HttpFoundation\Request; use Thelia\Core\HttpFoundation\Request;
use Thelia\Form\BaseForm; use Thelia\Form\BaseForm;
use Thelia\Model\AttributeAvI18n;
use Thelia\Model\AttributeAvI18nQuery;
use Thelia\Model\AttributeCombinationQuery; use Thelia\Model\AttributeCombinationQuery;
use Thelia\Model\AttributeI18n;
use Thelia\Model\AttributeI18nQuery;
use Thelia\Model\AttributeQuery;
use Thelia\Model\ContentI18nQuery; use Thelia\Model\ContentI18nQuery;
use Thelia\Model\ContentQuery; use Thelia\Model\ContentQuery;
use Thelia\Model\Map\ProductI18nTableMap; use Thelia\Model\Map\ProductI18nTableMap;
use Thelia\Model\Map\ProductTableMap; use Thelia\Model\Map\ProductTableMap;
use Thelia\Model\ProductQuery; use Thelia\Model\ProductQuery;
use Thelia\Model\ProductSaleElementsQuery;
use Thelia\Tools\URL; use Thelia\Tools\URL;
@@ -37,9 +43,7 @@ class BackController extends BaseAdminController
public function saveRecipe(Request $request) public function saveRecipe(Request $request)
{ {
$error = "";
$con = Propel::getConnection(); $con = Propel::getConnection();
$nouvelleRecette = false;
$form = new RecetteCreateForm($request); $form = new RecetteCreateForm($request);
try { try {
@@ -88,10 +92,40 @@ class BackController extends BaseAdminController
{ {
RecipeProductsQuery::create()->filterByRecipeId($recipeId)->filterByPseId($pseId)->delete(); RecipeProductsQuery::create()->filterByRecipeId($recipeId)->filterByPseId($pseId)->delete();
return new RedirectResponse(URL::getInstance()->absoluteUrl("/admin/content/update/" . $contentId . "#recipe")); return new RedirectResponse(URL::getInstance()->absoluteUrl("/admin/content/update/" . $contentId . "?current_tab=recipe"));
} }
public function getData($product_id)
{
$locale = $this->getCurrentEditionLocale();
$combinations = [];
$con = Propel::getConnection();
$pse = ProductSaleElementsQuery::create()
->filterByProductId($product_id)
->find($con);
foreach ($pse as $pseItem)
{
$combinationsArray = AttributeCombinationQuery::create()
->filterByProductSaleElements($pseItem)
->find($con);
foreach ($combinationsArray as $combination) {
$pseId = $pseItem->getId();
$label = AttributeAvI18nQuery::create()
->filterByLocale($locale)
->findOneById($combination->getAttributeAvId())
->getTitle();
array_push($combinations, [$pseId => $label]);
}
}
return $combinations;
}
public function searchProduct() public function searchProduct()
{ {
$locale = $this->getCurrentEditionLocale(); $locale = $this->getCurrentEditionLocale();
@@ -115,17 +149,13 @@ class BackController extends BaseAdminController
foreach ($data as $item) { foreach ($data as $item) {
$combinations = AttributeCombinationQuery::create() $combinations = self::getData($item['product.id']);
->filterByProductSaleElementsId($item->getId())
$item
$result[] = [ $result[] = [
'id' => $item[ProductTableMap::COL_ID], 'id' => $item[ProductTableMap::COL_ID],
'ref' => $item[ProductTableMap::COL_REF], 'ref' => $item[ProductTableMap::COL_REF],
'title' => $item['title'], 'title' => $item['title'],
'combinations' => [] 'combinations' => $combinations,
]; ];
} }
} }
@@ -133,27 +163,22 @@ class BackController extends BaseAdminController
return JsonResponse::create($result); return JsonResponse::create($result);
} }
public function searchCombination()
{
$locale = $this->getCurrentEditionLocale();
$ref = $this->getRequest()->get('query', null);
$result = [];
return JsonResponse::create($result);
}
/*
public function addProduct($contentId) public function addProduct($contentId)
{ {
$productId = (int) $this->getRequest()->get('product_id'); $pseId = (int) $this->getRequest()->get('pse_id');
$quantityNeeded = (string) $this->getRequest()->get('quantity_needed');
$recipeId = (int) $this->getRequest()->get('recipe_id');
$quantityProposed = (int) $this->getRequest()->get('quantity_proposed');
(new AgendaRelatedProduct()) (new RecipeProducts())
->setProductId($productId) ->setRecipeId($recipeId)
->setContentId($contentId) ->setPseId($pseId)
->setQuantity($quantityNeeded)
->setNbOfProducts($quantityProposed)
->save(); ->save();
return $this->render('ajax/related-products', [ 'content_id' => $contentId ]); return $this->render('ajax/related-products', [ 'content_id' => $contentId ]);
} }
*/
} }

View File

@@ -8,7 +8,7 @@ return array(
'Number of people' => 'Nombre de couverts', 'Number of people' => 'Nombre de couverts',
'Product' => 'Produit', 'Product' => 'Produit',
'Quantity' => 'Quantité', 'Quantity' => 'Quantité',
'Summary' => 'Détail', 'Summary' => 'Petit résumé de la recette',
'Other ingredients' => 'Ingrédients supplémentaires', 'Other ingredients' => 'Ingrédients supplémentaires',
'Ingredients' => 'Ingrédients', 'Ingredients' => 'Ingrédients',
'Ingredient' => 'Nos produits', 'Ingredient' => 'Nos produits',
@@ -22,4 +22,5 @@ return array(
'Some products may not be in stock' => '* ce produit n\'est plus en stock, désolé', 'Some products may not be in stock' => '* ce produit n\'est plus en stock, désolé',
'Name' => 'Notre recette', 'Name' => 'Notre recette',
'Created on' => 'Rédigée le', 'Created on' => 'Rédigée le',
'Save recipe' => 'Sauvegarder la recette',
); );

View File

@@ -1,15 +1,22 @@
<table class="table table-condensed"> {loop type="recipe" name="recipe-loop" content_id=$content_id limit="1"}
{loop type="recipe" name="recipe-loop" content_id=$content_id limit="1"}
{assign var="recipe_id" value="$ID"} {assign var="recipe_id" value="$ID"}
{/loop} <input type="hidden" id="recipe_id" value="{$ID}">
{/loop}
<table class="table table-condensed">
<thead>
<th>{intl l="Product" d="recettes"}</th>
<th>{intl l="Quantity needed" d="recettes"}</th>
<th colspan="2">{intl l="Quantity proposed" d="recettes"}</th>
</thead>
<tbody>
{loop type="recipe_products" name="products-loop" recipe_id=$recipe_id} {loop type="recipe_products" name="products-loop" recipe_id=$recipe_id}
{loop type="product" visible='*' name="related-product" id=$PRODUCT_ID} {loop type="product" visible="*" name="related-product" id=$PRODUCT_ID}
<tr> <tr>
<td>{$TITLE}<input type="hidden" value="{$PSE_ID}"</input></td> <td>{$TITLE}<input type="hidden" value="{$PSE_ID}"</input></td>
<td>{$UNITY}</td> <td>{$QUANTITY_NEEDED}</td>
<td>{$QUANTITY_PROPOSED}</td> <td>{$QUANTITY_PROPOSED}</td>
<td>{$UNITY}</td>
<td class="text-center"> <td class="text-center">
<a href="{url path='/admin/module/Recettes/remove-product/%recipeId/%pseId/%contentId' recipeId=$recipe_id pseId=$PSE_ID contentId=$content_id}" class="delete-product"><i class="glyphicon glyphicon-trash"></i></a> <a href="{url path='/admin/module/Recettes/remove-product/%recipeId/%pseId/%contentId' recipeId=$recipe_id pseId=$PSE_ID contentId=$content_id}" class="delete-product"><i class="glyphicon glyphicon-trash"></i></a>
</td> </td>
@@ -28,20 +35,29 @@
<tr> <tr>
<td colspan="3"> <td colspan="3">
<input class="form-control" type="text" id="product_ref" autocomplete="off" data-content-id="{$recipe_id}" placeholder="Indiquez une référence de produit"> <input class="form-control" type="text" id="product_ref" autocomplete="off" data-content-id="{$recipe_id}" placeholder="Saisir une référence de produit">
</td> </td>
</tr> </tr>
<tr> <tr>
<td colspan="3"> <td colspan="3">
<input class="form-control" type="text" id="pse_id" autocomplete="off" data-content-id="{$pse_id}" placeholder="Choisissez une déclinaison"> <input class="form-control" type="text" id="quantity_needed" autocomplete="off" placeholder="Quantité nécessaire (texte libre)">
</td>
</tr>
<tr>
<td colspan="3">
<label class="control-label">Choix de la déclinaison</label>
<input type="hidden" id="combinations" name="combinations" value="---">
<select id="select-combination" name="select-combination" class="form-control input-sm pse-option">
</select>
</td> </td>
</tr> </tr>
<tr> <tr>
<td colspan="2"> <td colspan="2">
<input class="form-control" type="text" id="quantity" autocomplete="off" placeholder="Saisir une quantité"> <input class="form-control" type="text" id="quantity_proposed" autocomplete="off" placeholder="Quantité proposée, en fonction de la déclinaison">
</td> </td>
<td class="text-center"> <td class="text-center">
<a href="{url path='/admin/module/Recettes/add-product/%recipeId' recipeId=$recipe_id}" class="btn btn-sm btn-primary add-product"><i class="glyphicon glyphicon-plus-sign"></i></a> <a href="{url path='/admin/module/Recettes/add-product/%contentId' contentId=$content_id}" class="btn btn-sm btn-primary add-product"><i class="glyphicon glyphicon-plus-sign"></i></a>
</td> </td>
</tr> </tr>
</tbody>
</table> </table>

View File

@@ -0,0 +1,16 @@
<input type="hidden" id="recipe_id" value="{$recipe_id}">
<table class="table table-condensed">
<thead>
<th>{intl l="Step" d="recettes"}</th>
<th colspan="2">{intl l="Detail" d="recettes"}</th>
</thead>
<tbody>
{loop name="steps-loop" type="recipe_steps" recipe_id=$recipe_id}
<tr>
<td>{$STEP}</td>
<td>{$DESCRIPTION}</td>
</tr>
{/loop}
</tbody>
</table>

View File

@@ -24,38 +24,42 @@
}, },
afterSelect: function (item) { afterSelect: function (item) {
this.$element[0].value = item.title this.$element[0].value = item.title
$('#product_ref').data('product-id', item.id); $("#select-combination").attr('disabled', null);
$("#pse_id").attr('disabled', null); $("#quantity_needed").attr('disabled', null);
}
});
$('#pse_id').typeahead({ $('#select-combination')
source: function (query, process) { .empty()
return $.getJSON( .append($('<option>').val("").text("Choisissez une déclinaison"));
'{url path="/admin/module/Recettes/search-combination"}',
{ item.combinations.forEach(function(key, value) {
query: query for (var id in key) {
}, $('#select-combination')
function (data) { .append($('<option>').val(id).text(key[id]));
process(data)
}
);
},
displayText: function (item) {
return item.title
},
afterSelect: function (item) {
this.$element[0].value = item.title
$('#product_ref').data('product-id', item.id);
$("#pse_id").attr('disabled', null);
} }
}); });
} }
});
$('#select-combination').change(function() {
var option = $("#select-combination option:selected").val();
if (option != "") {
$("#quantity_proposed").attr('disabled', null);
$('#product_ref').data('pse-id', option);
}
else
$("#quantity_proposed").attr('disabled', 'disabled');
});
$('#quantity_proposed').change(function() {
if ($('#quantity_proposed').val() <= 0) {
alert("Veuillez saisir une quantité positive.");
$("#quantity_proposed").attr('disabled', null);
}
else
$(".add-product").attr('disabled', null);
});
}
$(document).on('click', '.add-product', function(event) { $(document).on('click', '.add-product', function(event) {
event.preventDefault(); event.preventDefault();
@@ -63,7 +67,10 @@
$('#related-products-block').load( $('#related-products-block').load(
$(this).attr('href'), $(this).attr('href'),
{ {
product_id: $('#product_ref').data('product-id') quantity_needed: $('#quantity_needed').val(),
pse_id: $('#product_ref').data('pse-id'),
quantity_proposed: $('#quantity_proposed').val(),
recipe_id : $("#recipe_id").val()
}, },
function() { function() {
setupTypeAhead(); setupTypeAhead();
@@ -73,8 +80,11 @@
setupTypeAhead(); setupTypeAhead();
$("#pse_id").attr('disabled', 'disabled');
$("#quantity").attr('disabled', 'disabled'); // Par défaut, les champs de saisie du produit sont désactivés.
$("#quantity_needed").attr('disabled', 'disabled');
$("#select-combination").attr('disabled', 'disabled');
$("#quantity_proposed").attr('disabled', 'disabled');
$(".add-product").attr('disabled', 'disabled'); $(".add-product").attr('disabled', 'disabled');
}); });

View File

@@ -8,10 +8,9 @@
{assign var="other_ingredients" value=$OTHER_INGREDIENTS} {assign var="other_ingredients" value=$OTHER_INGREDIENTS}
{/loop} {/loop}
<div id="wrapper" class="container"> <div class="form-container">
<div class="row">
{form name="recette_create_form"} {form name="recette_create_form"}
<form id="admin-comment-form" method="post" action="{url path='/admin/module/Recettes/save'}" {form_enctype form=$form}> <form id="admin-comment-form" method="post" action="{url path='/admin/module/Recettes/save'}" {form_enctype form=$form} class="clearfix">
{form_hidden_fields form=$form} {form_hidden_fields form=$form}
@@ -120,14 +119,13 @@
<br> <br>
<label class="control-label">Etapes de la recette</label> <label class="control-label">Etapes de la recette</label>
<div id="steps-block"> <div id="steps-block">
{include file="ajax/steps.html"} {include file="ajax/steps.html" content_id=$content_id}
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<button type="submit" class="btn btn-primary">{intl l="Save" d="recettes"}</button> <button type="submit" class="btn btn-primary">{intl l="Save recipe" d="recettes"}</button>
</div> </div>
</form> </form>
{/form} {/form}
</div>
</div> </div>

View File

@@ -132,6 +132,7 @@ td.table-liste-recettes-image {
text-align: right; text-align: right;
width: auto; width: auto;
vertical-align: middle !important; vertical-align: middle !important;
margin: auto;
} }
.table-liste-recettes-image img { .table-liste-recettes-image img {
width: 65px; width: 65px;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB