Compare commits

...
Sign in to create a new pull request.

36 commits

Author SHA1 Message Date
Vincent BRIDIER
972ce0cf6f
Merge branch 'trunk' 2022-12-14 08:37:41 +01:00
Vincent BRIDIER
033ce42b42
Merge branch 'develop' into trunk 2022-12-14 08:37:26 +01:00
Vincent BRIDIER
481b39d856
Add Sentry 2022-12-14 08:03:33 +01:00
Vincent BRIDIER
262ea2871c
Merge branch 'trunk' 2022-12-14 07:48:35 +01:00
Vincent BRIDIER
8ba5feff18
Merge branch 'develop' into trunk 2022-12-14 07:48:19 +01:00
Vincent BRIDIER
a247dba2b2 Merge branch 'fix-todays-orders' into 'develop'
fix todays orders

See merge request service-web-lab/boutique-cnc!4
2022-12-14 06:46:07 +00:00
Olivier Legat
4873cd7fc2 fix todays orders
localise sorting to current route
2022-12-13 13:55:42 +01:00
Vincent BRIDIER
69ce45d5cb
Merge branch 'trunk' 2022-12-13 10:33:59 +01:00
Vincent BRIDIER
a6d0e1ae2d
Merge branch 'develop' into trunk 2022-12-13 10:32:56 +01:00
Vincent BRIDIER
d8464a34ac Merge branch 'evol-sh-01' into 'develop'
Evol sh 01

See merge request service-web-lab/boutique-cnc!3
2022-12-13 09:30:00 +00:00
S. Hattry
4359c85b8c Fix filter order bug 2022-12-08 09:35:28 +01:00
S. Hattry
7ba2c3b2fe Fix null order bug (review feedback) 2022-11-28 13:07:49 +01:00
S. Hattry
1f235efebe Delete comment 2022-11-28 13:07:25 +01:00
S. Hattry
6eef17a390 Add translateable title (review feedback) 2022-11-28 12:59:14 +01:00
S. Hattry
5872d670fe Add translatables column names (review feedback) 2022-11-28 12:49:10 +01:00
S. Hattry
0c22695c77 Fix type input email bug (review feedback) 2022-11-28 12:38:59 +01:00
S. Hattry
1aceb54b0e Fix contact request rule bug (review feedback) 2022-11-28 12:31:25 +01:00
S. Hattry
e9085b681a Fix canceled order mail (review feedback) 2022-11-28 12:30:40 +01:00
S. Hattry
e8d1669bae Fix contact mail bug (review feedback) 2022-11-28 12:08:55 +01:00
S. Hattry
9e7fad8ebb Fix confirm admin mail bug (review feedback) 2022-11-28 12:03:19 +01:00
S. Hattry
6b3145eb8f Fix filters orders (review feedback) 2022-11-28 11:55:25 +01:00
S. Hattry
30e53b81b3 Fix sort date bug (review feedback) 2022-11-28 11:04:22 +01:00
S. Hattry
1cca69c933 BO - Add order filters 2022-11-25 15:22:16 +01:00
S. Hattry
11dad23fe2 Add confirm admin email according to shop 2022-11-25 14:42:18 +01:00
S. Hattry
9b5a68c121 Fix magasin migration bug 2022-11-25 09:51:40 +01:00
S. Hattry
6f14d1d975 Sort orders list by desc date 2022-11-24 17:10:28 +01:00
S. Hattry
039587d1e3 Add shop email destination in form contact 2022-11-24 16:31:54 +01:00
S. Hattry
825d47797b Add cancel order button for the customer 2022-11-24 13:15:21 +01:00
Vincent BRIDIER
e1820ba1ac
Merge branch 'trunk' 2022-11-24 09:23:21 +01:00
Olivier Legat
b72988b20c Merge branch 'develop' into trunk 2022-09-12 17:02:32 +02:00
Olivier Legat
3000e1663f Merge branch 'develop' into trunk 2022-09-12 16:31:57 +02:00
Olivier Legat
d48c9aa99b Merge branch 'develop' into trunk 2022-09-12 08:57:51 +02:00
Olivier Legat
b7c0e12429 Merge branch 'trunk' 2022-09-09 08:33:17 +02:00
Olivier Legat
2d65de573c Merge branch 'develop' into trunk 2022-09-09 08:32:17 +02:00
Vincent BRIDIER
4bbb98e3c8
Merge branch 'trunk' 2022-08-25 12:52:07 +02:00
Vincent BRIDIER
80d426f470
Merge branch 'develop' into trunk 2022-08-25 12:51:56 +02:00
20 changed files with 1827 additions and 67 deletions

View file

@ -4,8 +4,6 @@ namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Support\Facades\Mail;
use Throwable;
class Handler extends ExceptionHandler
{
@ -33,6 +31,12 @@ class Handler extends ExceptionHandler
*/
public function register()
{
$this->reportable(function (\Throwable $e) {
if (app()->bound('sentry')) {
app('sentry')->captureException($e);
}
});
}
/**
@ -61,37 +65,4 @@ class Handler extends ExceptionHandler
// Session::forget('url.intented'); .
return redirect()->guest(route($login));
}
/**
* Report or log an exception.
*
* @param \Throwable $e
* @return void
*/
public function report(Throwable $e)
{
if (get_class($e) == RedirectTo::class) {
abort(redirect($e->url));
}
if (config('app.debug') === false) {
if ($this->shouldntReport($e)) {
return;
}
Mail::send([
'html' => 'emails.exception',
'text' => 'emails.exception-plain'
], [
'exception' => $e,
'appName' => config('app.name')
], function ($m) {
$m->to(
config('mail.contactsList.serviceweb'),
sprintf('%s Exception Handler', config('app.name'))
)->subject('Need help !, an error occured in your application, please check Logs ASAP');
});
}
parent::report($e);
}
}

View file

@ -40,6 +40,8 @@ class MagasinsController extends Controller
{
$request->validate([
'name' => 'required|string|max:255',
'email_contact' => 'required|email:rfc,dns,spoof|max:255',
'email_confirm' => 'nullable|email:rfc,dns,spoof|max:255',
'address' => 'required|string|max:255',
'postcode' => 'required',
'city' => 'required|string|max:255',
@ -73,6 +75,8 @@ class MagasinsController extends Controller
{
$request->validate([
'name' => 'required|string|max:255',
'email_contact' => 'required|email:rfc,dns,spoof|max:255',
'email_confirm' => 'nullable|email:rfc,dns,spoof|max:255',
'address' => 'required|string|max:255',
'postcode' => 'required',
'city' => 'required|string|max:255',

View file

@ -16,11 +16,13 @@ use App\Mail\OrderConfirmMail;
use App\Mail\OrderConfirmAdminMail;
use App\Jobs\CsvOrderWrite;
use App\Models\Customers;
use App\Models\OrdersStatus;
use App\Models\Setting;
use Carbon\Carbon;
use Carbon\CarbonImmutable;
use Carbon\CarbonInterval;
use Gloudemans\Shoppingcart\Facades\Cart;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session;
@ -37,9 +39,33 @@ class OrdersController extends Controller
{
$orders = $this->filterOrders($request);
$status_orders = OrdersStatus::all();
$magasins = Magasin::all();
$filter_status_order = $request->query('filter_status_order');
$filter_magasin = $request->query('filter_magasin');
$filter_reference = $request->query('filter_reference');
if (!empty($filter_status_order)) {
$orders = $orders->where('status_id', $filter_status_order);
}
if (!empty($filter_magasin)) {
$orders = $orders->whereHas(
'timeslot',
function (Builder $q) use ($filter_magasin) {
$q->where('timeslots.magasin_id', $filter_magasin);
}
);
}
if (!empty($filter_reference)) {
$orders = $orders->where('reference', 'like', "%{$filter_reference}%");
}
$orders = $orders->paginate(10);
return view('bo.orders.index', compact('orders'));
return view(
'bo.orders.index',
compact('orders', 'status_orders', 'magasins', 'filter_status_order', 'filter_magasin', 'filter_reference')
);
}
/**
@ -73,7 +99,6 @@ class OrdersController extends Controller
{
$orders = Order::query();
if ($request->rst) {
Session::remove('orders.sort_col');
Session::remove('orders.sort_way');
@ -110,7 +135,9 @@ class OrdersController extends Controller
case 'customer_id':
$orders = $orders->orderBy('customer_id', Session::get('orders.sort_way'));
break;
}//end switch
} //end switch
} else {
$orders->orderByDesc('date');
}//end if
return $orders;
@ -486,6 +513,7 @@ class OrdersController extends Controller
*
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
* @throws \RuntimeException If email missing.
*/
public function setTimeSlot(Request $request)
{
@ -495,7 +523,6 @@ class OrdersController extends Controller
'ok_cgv' => 'accepted',
]);
$time_slot = Carbon::createFromFormat('d/m/Y-H:i', $request->selectedcreneau);
$tsday = explode('-', $request->selectedcreneau)[0];
$tstime = explode('-', $request->selectedcreneau)[1];
$magasin_id = $request->selectedmagasin;
@ -520,12 +547,25 @@ class OrdersController extends Controller
Mail::to($order->customer->email)->queue(new OrderConfirmMail($order));
// Envoi du mail de confirmation aux admins site.
$toMailSetting = Setting::where('key', 'send_order_confirm_mail_to')->first();
if (empty($toMailSetting->value)) {
$toMail = config('mail.from.address');
/** @var \App\Model\Magasin|null */
$shop = Magasin::where('id', $magasin_id)->first();
if ($shop and $shop->email_confirm) {
/** @var string */
$toMail = $shop->email_confirm;
} else {
$toMail = $toMailSetting->value;
/** @var string|null */
$toMail = \optional(Setting::where('key', 'send_order_confirm_mail_to')->first())->value;
if (!$toMail) {
/** @var string|null */
$toMail = config('mail.from.address');
}
}
if (!$toMail) {
throw new \RuntimeException('Impossible de trouver un mail');
}
Mail::to($toMail)->queue(new OrderConfirmAdminMail($order));
// Export commande.

View file

@ -25,11 +25,12 @@ class ContactController extends Controller
// @phpcs:enable
$status = $request->session()->get('status');
// 1er magasin en base pour le moment
$magasin = Magasin::first();
$magasin = Magasin::first();
$magasins = Magasin::all();
$content = Content::where('key', 'contact')->first();
return view('contact', compact('status', 'magasin', 'content'));
return view('contact', compact('status', 'magasins', 'magasin', 'content'));
}
/**
@ -37,17 +38,29 @@ class ContactController extends Controller
*
* @param ContactFormRequest $request
* @return \Illuminate\Http\Response
* @throws \RuntimeException If email missing.
*/
public function contactSubmit(ContactFormRequest $request)
{
$data = $request->all();
/** @var \App\Model\Magasin|null */
$shop = Magasin::where('name', $request->shop)->first();
$toMailSetting = Setting::where('key', 'send_contact_mail_to')->first();
if (empty($toMailSetting->value)) {
$toMail = config('mail.from.address');
if ($shop and $shop->email_contact) {
/** @var string */
$toMail = $shop->email_contact;
} else {
$toMail = $toMailSetting->value;
/** @var string|null */
$toMail = \optional(Setting::where('key', 'send_contact_mail_to')->first())->value;
if (!$toMail) {
/** @var string|null */
$toMail = config('mail.from.address');
}
}
if (!$toMail) {
throw new \RuntimeException('Impossible de trouver un mail');
}
// Envoi du mail d'alerte.
Mail::to($toMail)->send(new SendContactMail($request));

View file

@ -5,6 +5,7 @@ namespace App\Http\Controllers;
use App\Http\Requests\CustomerRegisterRequest;
use App\Http\Requests\LoginRequest;
use App\Http\Requests\UpdateInfosRequest;
use App\Mail\OrderCanceledConfirmMail;
use App\Mail\PasswordResetMail;
use App\Mail\RegisterConfirmMail;
use App\Models\Customers;
@ -12,6 +13,7 @@ use App\Models\Magasin;
use App\Models\Order;
use App\Models\PasswordReset;
use App\Models\Salarie;
use App\Models\Setting;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
@ -455,6 +457,40 @@ class CustomerController extends Controller
return view('customer.order-detail', compact('order', 'magasin'));
}
/**
* mise au statut annulé d'une commande
*
* @param string $reference
* @return \Illuminate\Http\RedirectResponse
* @throws \RuntimeException If email missing.
*/
public function cancelOrder(string $reference)
{
/** @var \App\Models\Order|null */
$order = Order::where('reference', $reference)->first();
if (!$order) {
throw new \RuntimeException('Impossible de trouver un enregistrement Order');
}
$order->status_id = 7;
$order->save();
// Envoi du mail d'annulation aux admins site.
/** @var string|null */
$toMail = \optional(Setting::where('key', 'send_order_confirm_mail_to')->first())->value;
if (!$toMail) {
/** @var string|null */
$toMail = config('mail.from.address');
}
if (!$toMail) {
throw new \RuntimeException('Impossible de trouver un mail');
}
Mail::to($toMail)->queue(new OrderCanceledConfirmMail($order));
return back()->with('success', "La commande " . $order->reference . " à été annulée.");
}
/**
* delete customers
*

View file

@ -27,6 +27,7 @@ class ContactFormRequest extends FormRequest
'last_name' => 'required|min:2',
'first_name' => 'required|min:2',
'email' => 'required|email:rfc,dns,spoof',
'shop' => 'present|nullable|string|exists:magasins,name',
'subject' => 'required|min:2',
'order_ref' => 'sometimes',
'message' => 'required|min:20|max:1900',
@ -46,6 +47,7 @@ class ContactFormRequest extends FormRequest
'ok_cgv.accepted' => __('You must accept the terms and conditions and the privacy policy'),
'file.max' => __('La taille du fichier ne peut pas dépasser :max kilo-octets.'),
'file.mimes' => __('Le fichier doit être de type : :values.'),
'shop.exists' => __('Le magasin :exists est introuvable.')
];
}
}

View file

@ -0,0 +1,190 @@
<?php
namespace App\Lib;
class ExceptionsHelper
{
/**
* Handle sentry event
*
* @param \Sentry\Event $event
* @return null|\Sentry\Event
*/
public static function sentryEventHandler(\Sentry\Event $event): ?\Sentry\Event
{
// Remove unwanted reports.
$event->setModules([]);
$event->setOsContext(null);
/** @var \Sentry\ExceptionDataBag[] */
$exceptionBag = [];
foreach ($event->getExceptions() as $exceptionDataBag) {
$exceptionBag[] = self::getAnonymizedSentryException($exceptionDataBag);
}
$event->setExceptions($exceptionBag);
return $event;
}
/**
* Anonimize Sentry Exception bag
*
* @param \Sentry\ExceptionDataBag $exceptionDataBag
* @return \Sentry\ExceptionDataBag
*/
private static function getAnonymizedSentryException(
\Sentry\ExceptionDataBag $exceptionDataBag
): \Sentry\ExceptionDataBag {
$exceptionDataBag->setValue(self::getAnonymizedMessage($exceptionDataBag->getValue()));
if ($stackTrace = $exceptionDataBag->getStacktrace()) {
$exceptionDataBag->setStacktrace(self::getAnonymizedSentryStackTrace($stackTrace));
}
return $exceptionDataBag;
}
/**
* Anonymise sentry stacktrace
*
* @param \Sentry\Stacktrace $stackTrace
* @return \Sentry\Stacktrace
*/
private static function getAnonymizedSentryStackTrace(\Sentry\Stacktrace $stackTrace): \Sentry\Stacktrace
{
/** @var \Sentry\Frame[] */
$frames = \array_reverse($stackTrace->getFrames(), true);
$i = \count($frames) - 1;
// * Remove all but keep first (index.php).
while ($i-- > 0) {
$stackTrace->removeFrame(count($stackTrace->getFrames()) - 1);
}
foreach ($frames as $index => $frame) {
$frame->setPostContext([]);
$frame->setPreContext([]);
$frame->setContextLine('');
$frame->setVars(self::getAnonymizedSentryParams($frame->getVars()));
$stackTrace->addFrame($frame);
if ($index === 0) {
$stackTrace->removeFrame(count($stackTrace->getFrames()) - 1);
}
}
return $stackTrace;
}
/**
* Get anonymized sentry params
*
* @param mixed[] $params
* @return string[]
*/
private static function getAnonymizedSentryParams(array $params): array
{
foreach ($params as &$param) {
$type = \strtolower(\gettype($param));
if (\is_string($param)) {
$type = \explode(' ', \trim($param))[0] ?? null;
}
switch ($type) {
case 'Lambda':
case 'Object':
continue 2;
case 'array':
$param = sprintf('Array(%d)', \count($param));
continue 2;
default:
if (\is_numeric($param)) {
$param = \ucfirst($type);
continue 2;
}
if (\is_string($param)) {
$param = sprintf('String(%d)', \strlen($param));
continue 2;
}
} //end switch
} //end foreach
return $params;
}
/**
* Anonymize at least Sql queries
*
* @param string $message
* @return string
*/
public static function getAnonymizedMessage(string $message): string
{
$message = \preg_replace('/^(.*)( \(SQL:.*\))$/', '$1', $message) ?? $message;
if ($sqlPos = \strpos($message, 'to use near')) {
$message = \mb_strcut($message, 0, $sqlPos);
}
return $message;
}
/**
* Anonymize stack trace
*
* @param \Throwable $e
* @return string
*/
public static function getAnonymizedStackTrace(\Throwable $e): string
{
$projectPath = \realpath(\sprintf('%s/../', \app_path()));
$traceStack = $e->getTrace();
$traceStr = '';
$maxStackStage = 0;
foreach ($traceStack as $stackStage => $stack) {
$maxStackStage = $stackStage;
$traceStr .= \sprintf(
'#%s %s(%d): ',
$stackStage,
str_replace($projectPath, '', $stack['file'] ?? ''),
$stack['line'] ?? ''
);
if (isset($stack['class'])) {
$traceStr .= "{$stack['class']}->{$stack['function']}(";
if (isset($stack['args'])) {
$traceStr .= self::handleArgs($stack);
}
$traceStr .= ")\n";
} elseif (isset($stack['function'])) {
$traceStr .= "{$stack['function']}(";
if (isset($stack['args'])) {
$traceStr .= self::handleArgs($stack);
}
$traceStr .= ")\n";
}
} //end foreach
$maxStackStage++;
$traceStr .= "#$maxStackStage {main}";
return $traceStr;
}
/**
* Handle Args
*
* @param array $stack
* @return string
*/
public static function handleArgs(array $stack): string
{
$traceArgs = '';
$argsCount = count($stack['args']);
for ($i = 0; $i < $argsCount; $i++) {
$type = \gettype($stack['args'][$i]);
switch ($type) {
case 'object':
$traceArgs .= sprintf('Object(%s)', \get_class($stack['args'][$i]));
break;
case 'array':
$traceArgs .= sprintf('Array(%d)', \count($stack['args'][$i]));
break;
case 'string':
$traceArgs .= sprintf('String(%d)', \strlen($stack['args'][$i]));
break;
default:
$traceArgs .= \gettype($stack['args'][$i]);
}
$traceArgs .= ($i !== ($argsCount - 1) ? ',' : '');
}
return $traceArgs;
}
}

View file

@ -0,0 +1,47 @@
<?php
namespace App\Mail;
use App\Models\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class OrderCanceledConfirmMail extends Mailable
{
use Queueable;
use SerializesModels;
/**
* The Order
*
* @var \App\Models\Order
*/
private $order;
/**
* Create a new message instance.
*
* @param \App\Models\Order $order
*
* @return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$order = $this->order;
return $this->subject(
"Commande " . config('theme.site_name') . " n°" . $order->reference . " a été annulée."
)->view('mails.order-canceled-confirm', compact('order'));
}
}

View file

@ -15,7 +15,7 @@ class Magasin extends Model
* @var array
*/
protected $fillable = [
'name', 'address', 'postcode', 'city', 'phone',
'name', 'email_contact', 'email_confirm', 'address', 'postcode', 'city', 'phone',
'latitude', 'longitude',
'gmaps_placeid', 'gmaps_embed_href', 'gmaps_link_href',
];

View file

@ -18,6 +18,7 @@
"laravel/framework": "^8.12",
"laravel/tinker": "^2.5",
"ldc/ldccrmv2client": "^3.0",
"sentry/sentry-laravel": "^3.1",
"spatie/laravel-sitemap": "^5.8"
},
"require-dev": {

1282
composer.lock generated

File diff suppressed because it is too large Load diff

62
config/sentry.php Normal file
View file

@ -0,0 +1,62 @@
<?php
return [
'dsn' => env('SENTRY_LARAVEL_DSN', env('SENTRY_DSN')),
// The release version of your application
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')).
'release' => env('SENTRY_RELEASE'),
// When left empty or `null` the Laravel environment will be used.
'environment' => env('SENTRY_ENVIRONMENT'),
'breadcrumbs' => [
// Capture Laravel logs in breadcrumbs.
'logs' => true,
// Capture SQL queries in breadcrumbs.
'sql_queries' => true,
// Capture bindings on SQL queries logged in breadcrumbs.
'sql_bindings' => false,
// Capture queue job information in breadcrumbs.
'queue_info' => true,
// Capture command information in breadcrumbs.
'command_info' => true,
],
'tracing' => [
// Trace queue jobs as their own transactions.
'queue_job_transactions' => env('SENTRY_TRACE_QUEUE_ENABLED', false),
// Capture queue jobs as spans when executed on the sync driver.
'queue_jobs' => true,
// Capture SQL queries as spans.
'sql_queries' => true,
// Try to find out where the SQL query originated from and add it to the query spans.
'sql_origin' => true,
// Capture views as spans.
'views' => true,
// Indicates if the tracing integrations supplied by Sentry should be loaded.
'default_integrations' => true,
// Indicates that requests without a matching route should be traced.
'missing_routes' => false,
],
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#send-default-pii
'send_default_pii' => env('SENTRY_SEND_DEFAULT_PII', false),
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#traces-sample-rate
'traces_sample_rate' => env('SENTRY_TRACES_SAMPLE_RATE') === null ? null : (float)env('SENTRY_TRACES_SAMPLE_RATE'),
'before_send' => [\App\Lib\ExceptionsHelper::class, 'sentryEventHandler'],
];

View file

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddFieldToMagasins extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('magasins', function (Blueprint $table) {
$table->string('email_contact')->after('name');
$table->string('email_confirm')->nullable()->after('email_contact');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('magasins', function (Blueprint $table) {
$table->dropColumn('email_contact');
$table->dropColumn('email_confirm');
});
}
}

View file

@ -14,13 +14,14 @@ class MagasinsSeeder extends Seeder
*/
public function run()
{
$shop = new Magasin();
$shop->name = 'Point de retrait';
$shop->address = 'l\'adresse';
$shop->postcode = '72000';
$shop->city = 'Le Mans';
$shop = new Magasin();
$shop->name = 'Point de retrait';
$shop->email_contact = 'adresse@domaine.fr';
$shop->address = 'l\'adresse';
$shop->postcode = '72000';
$shop->city = 'Le Mans';
$shop->gmaps_embed_href = "https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d5338.425979915083!2d0.1977634707405403!3d48.00959481914027!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x47e288cfcdc1a263%3A0x7acf6d8dc923c25a!2zQ2l0w6kgUGxhbnRhZ2Vuw6p0!5e0!3m2!1sfr!2sfr!4v1619612657653!5m2!1sfr!2sfr";
$shop->gmaps_link_href = 'https://goo.gl/maps/sxuj7FevRSHsDb8MA';
$shop->gmaps_link_href = 'https://goo.gl/maps/sxuj7FevRSHsDb8MA';
$shop->save();
}
}

View file

@ -22,6 +22,20 @@
<label for="name">Nom *</label>
<input type="text" id="name" name="name" class="form-control" placeholder="Nom *" value="{{ old('name') }}" required>
</div>
<div class="row">
<div class="col-6">
<div class="form-group">
<label>Email de contact *</label>
<input type="email" id="email_contact" name="email_contact" class="form-control" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$" placeholder="adresse@pole-sbv.fr *" value="{{ old('email_contact') }}" required>
</div>
</div>
<div class="col-6">
<div class="form-group">
<label>Email de confirmation de commande</label>
<input type="email" id="email_confirm" name="email_confirm" class="form-control" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$" placeholder="adresse@pole-sbv.fr" value="{{ old('email_confirm') }}">
</div>
</div>
</div>
<div class="form-group">
<label>Adresse *</label>
<input type="text" id="address" name="address" class="form-control" placeholder="Adresse *" value="{{ old('address') }}" required>

View file

@ -31,6 +31,20 @@
<a class="btn btn-sm btn-primary" href="{{route('bo.creneaux.settings', $magasin->id)}}">Editer Créneaux de collecte</a>
</div>
</div>
<div class="row">
<div class="col-6">
<div class="form-group">
<label>Email de contact *</label>
<input type="email" id="email_contact" name="email_contact" class="form-control" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$" placeholder="adresse@pole-sbv.fr *" value="{{ old('email_contact',$magasin->email_contact) }}" required>
</div>
</div>
<div class="col-6">
<div class="form-group">
<label>Email de confirmation de commande</label>
<input type="email" id="email_confirm" name="email_confirm" class="form-control" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$" placeholder="adresse@pole-sbv.fr" value="{{ old('email_confirm',$magasin->email_confirm) }}">
</div>
</div>
</div>
<div class="form-group">
<label>Adresse *</label>
<input type="text" id="address" name="address" class="form-control" placeholder="Adresse *" value="{{ old('address',$magasin->address) }}" required>

View file

@ -14,9 +14,11 @@
<table class="table">
<thead>
<th scope="col"></th>
<th scope="col">Nom</th>
<th scope="col">Adresse</th>
<th scope="col">Téléphone</th>
<th scope="col">{{ __('Nom') }}</th>
<th scope="col">{{ __('Email de contact') }}</th>
<th scope="col">{{ __('Email de confirmation') }}<br>{{ __('de commande') }}</th>
<th scope="col">{{ __('Adresse') }}</th>
<th scope="col">{{ __('Téléphone') }}</th>
<th scope="col"></th>
</thead>
<tbody>
@ -24,6 +26,8 @@
<tr>
<td></td>
<td>{{$magasin->name}}</td>
<td>{{$magasin->email_contact}}</td>
<td>{{$magasin->email_confirm}}</td>
<td>{{$magasin->address}}, {{$magasin->postcode}} {{$magasin->city}}</td>
<td>{{$magasin->phone}}</td>
<td class="text-center">

View file

@ -1,6 +1,6 @@
@if(!session($list.'.sort_way') or session($list.'.sort_col') !== $colname or (session($list.'.sort_way') === 'desc' and session($list.'.sort_col') === $colname))
<a class="col_sort text-secondary lead asc" href="{{ route('bo.orders', ['sort_col' => $colname, 'sort_way' => 'asc']) }}">&nbsp;&darr;&nbsp;</a>
<a class="col_sort text-secondary lead asc" href="{{ route(Route::currentRouteName(), ['sort_col' => $colname, 'sort_way' => 'asc']) }}">&nbsp;&darr;&nbsp;</a>
@endif
@if(!session($list.'.sort_way') or session($list.'.sort_col') !== $colname or (session($list.'.sort_way') === 'asc' and session($list.'.sort_col') === $colname))
<a class="col_sort text-secondary lead desc" href="{{ route('bo.orders', ['sort_col' => $colname, 'sort_way' => 'desc']) }}">&nbsp;&uarr;&nbsp;</a>
<a class="col_sort text-secondary lead desc" href="{{ route(Route::currentRouteName(), ['sort_col' => $colname, 'sort_way' => 'desc']) }}">&nbsp;&uarr;&nbsp;</a>
@endif

View file

@ -1,10 +1,56 @@
@extends('layouts.bo-layout')
@section('content')
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Commandes @if (isset($today)) à retirer aujourd'hui @endif</h1>
<div class="d-flex flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2 pe-5">{{ __('Commandes') }} @if (isset($today)) <br>{{ __('à retirer aujourd\'hui') }} @endif</h1>
@if (!isset($today))
<form method="GET">
<div class="row">
<div class="col-6">
<label for="filter_status_order" class="col-form-label">Etat de commande</label>
<div class="col">
<select class="form-control" id="filter_status_order" name="filter_status_order">
<option value="" @if ($filter_status_order == '') selected @endif>Tous</option>
@foreach($status_orders as $status_order)
<option value="{{$status_order->id}}" @if ($status_order->id == $filter_status_order) selected @endif>{{$status_order->label}}</option>
@endforeach
</select>
</div>
</div>
<div class="col-6">
<label for="filter_magasin" class="col-form-label">Lieu de retrait</label>
<div class="col">
<select class="form-control" id="filter_magasin" name="filter_magasin">
<option value="" @if ($filter_magasin == '') selected @endif>Tous</option>
@foreach($magasins as $magasin)
<option value="{{$magasin->id}}" @if ($magasin->id == $filter_magasin) selected @endif>{{$magasin->name}}</option>
@endforeach
</select>
</div>
</div>
<div class="col-12">
<div class="row align-items-end">
<div class="col-6">
<label for="filter_reference" class="col-form-label">Référence commande</label>
<div class="col">
<input class="form-control" type="text"
placeholder="Référence commande"
id="filter_reference" name="filter_reference"
value="{{ $filter_reference ?? ''}}">
</div>
</div>
<div class="col-6">
<button class="btn btn-primary">Filtrer</button>
<a class="btn btn-info" href="{{ route('bo.orders') }}">Effacer le filtre</a>
</div>
</div>
</div>
</div>
</form>
@endif
@if (session('success'))
<span class="float-center text-success">{{ session('success') }}</span>
<span class="float-center text-success ms-3">{{ session('success') }}</span>
@endif
</div>
<table class="table">

View file

@ -222,6 +222,7 @@ Route::name('account.')
)->name('change-password');
Route::get('/commandes', [CustomerController::class, 'myOrders'])->name('my-orders');
Route::get('/commandes/{reference}', [CustomerController::class, 'orderDetail'])->name('order-detail');
Route::get('/commandes/{reference}/annuler', [CustomerController::class, 'cancelOrder'])->name('cancel-order');
}
);