Merge branch 'master' of github.com:bagisto/bagisto into social-share

This commit is contained in:
Carlos Augusto Gartner 2020-08-05 09:13:43 -03:00
commit b6e1e9b8bd
95 changed files with 1405 additions and 386 deletions

View File

@ -45,6 +45,19 @@ class OrderInvoicesDataGrid extends DataGrid
'filterable' => true,
]);
$this->addColumn([
'index' => 'created_at',
'label' => trans('admin::app.datagrid.invoice-date'),
'type' => 'string',
'searchable' => true,
'sortable' => true,
'filterable' => true,
'closure' => true,
'wrapper' => function ($value) {
return \Carbon\Carbon::parse($value->created_at)->format('d-m-Y');
}
]);
$this->addColumn([
'index' => 'base_grand_total',
'label' => trans('admin::app.datagrid.grand-total'),
@ -55,12 +68,22 @@ class OrderInvoicesDataGrid extends DataGrid
]);
$this->addColumn([
'index' => 'created_at',
'label' => trans('admin::app.datagrid.invoice-date'),
'type' => 'datetime',
'index' => 'state',
'label' => trans('admin::app.datagrid.state'),
'type' => 'string',
'closure' => true,
'searchable' => true,
'sortable' => true,
'filterable' => true,
'wrapper' => function ($value) {
if ($value->state == 'paid') {
return '<span class="badge badge-md badge-success">'. trans('admin::app.sales.orders.invoice-status-paid') .'</span>';
} elseif ($value->state == "pending") {
return '<span class="badge badge-md badge-warning">'. trans('admin::app.sales.orders.invoice-status-pending') .'</span>';
} elseif ($value->state == "overdue") {
return '<span class="badge badge-md badge-danger">'. trans('admin::app.sales.orders.invoice-status-overdue') . '</span>';
}
}
]);
}

View File

@ -64,12 +64,12 @@ class CustomerController extends Controller
CustomerGroupRepository $customerGroupRepository,
ChannelRepository $channelRepository
)
{
$this->_config = request('_config');
$this->middleware('admin');
$this->customerRepository = $customerRepository;
$this->customerAddressRepository = $customerAddressRepository;
$this->customerGroupRepository = $customerGroupRepository;
$this->channelRepository = $channelRepository;
@ -200,12 +200,19 @@ class CustomerController extends Controller
$customer = $this->customerRepository->findorFail($id);
try {
$this->customerRepository->delete($id);
if (! $this->customerRepository->checkIfCustomerHasOrderPendingOrProcessing($customer)) {
$this->customerRepository->delete($id);
} else {
return response()->json(['message' => false], 400);
}
session()->flash('success', trans('admin::app.response.delete-success', ['name' => 'Customer']));
return response()->json(['message' => true], 200);
} catch (\Exception $e) {
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Customer']));
}
@ -279,12 +286,18 @@ class CustomerController extends Controller
{
$customerIds = explode(',', request()->input('indexes'));
foreach ($customerIds as $customerId) {
$this->customerRepository->deleteWhere(['id' => $customerId]);
if (!$this->customerRepository->checkBulkCustomerIfTheyHaveOrderPendingOrProcessing($customerIds)) {
foreach ($customerIds as $customerId) {
$this->customerRepository->deleteWhere(['id' => $customerId]);
}
session()->flash('success', trans('admin::app.customers.customers.mass-destroy-success'));
return redirect()->back();
}
session()->flash('success', trans('admin::app.customers.customers.mass-destroy-success'));
session()->flash('error', trans('admin::app.response.order-pending', ['name' => 'Customers']));
return redirect()->back();
}
}

View File

@ -2,9 +2,12 @@
namespace Webkul\Admin\Http\Controllers\Sales;
use Illuminate\Http\Request;
use Webkul\Admin\Http\Controllers\Controller;
use Webkul\Sales\Repositories\OrderRepository;
use Webkul\Sales\Repositories\InvoiceRepository;
use PDF;
class InvoiceController extends Controller
@ -97,7 +100,7 @@ class InvoiceController extends Controller
$data = request()->all();
$haveProductToInvoice = false;
foreach ($data['invoice']['items'] as $itemId => $qty) {
if ($qty) {
$haveProductToInvoice = true;
@ -145,4 +148,29 @@ class InvoiceController extends Controller
return $pdf->download('invoice-' . $invoice->created_at->format('d-m-Y') . '.pdf');
}
/**
* Update the invoice state.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function updateState($id, Request $request)
{
$invoice = $this->invoiceRepository->findOrFail($id);
$task = $this->invoiceRepository->updateInvoiceState($invoice, $request->state);
if($request->state == 'paid'){
$order = $this->orderRepository->findOrFail($invoice->order->id);
$this->orderRepository->updateOrderStatus($order);
}
if ($task){
session()->flash('success', trans('admin::app.sales.orders.invoice-status-confirmed'));
} else {
session()->flash('success', trans('admin::app.sales.orders.invoice-status-error'));
}
return back();
}
}

View File

@ -29,9 +29,17 @@ class ConfigurationForm extends FormRequest
if (request()->has('general.design.admin_logo.logo_image')
&& ! request()->input('general.design.admin_logo.logo_image.delete')
) {
$this->rules = [
'general.design.admin_logo.logo_image' => 'required|mimes:jpeg,bmp,png,jpg',
];
$this->rules = array_merge($this->rules, [
'general.design.admin_logo.logo_image' => 'required|mimes:jpeg,bmp,png,jpg|max:5000',
]);
}
if (request()->has('general.design.admin_logo.favicon')
&& ! request()->input('general.design.admin_logo.favicon.delete')
) {
$this->rules = array_merge($this->rules, [
'general.design.admin_logo.favicon' => 'required|mimes:jpeg,bmp,png,jpg|max:5000',
]);
}
return $this->rules;
@ -48,4 +56,15 @@ class ConfigurationForm extends FormRequest
'general.design.admin_logo.logo_image.mimes' => 'Invalid file format. Use only jpeg, bmp, png, jpg.',
];
}
}
/**
* Set the attribute name.
*/
public function attributes()
{
return [
'general.design.admin_logo.logo_image' => 'Logo Image',
'general.design.admin_logo.favicon' => 'Favicon Image'
];
}
}

View File

@ -211,6 +211,10 @@ Route::group(['middleware' => ['web']], function () {
'view' => 'admin::sales.invoices.print',
])->name('admin.sales.invoices.print');
Route::post('/invoices/update/state/{order_id}', 'Webkul\Admin\Http\Controllers\Sales\InvoiceController@updateState')->defaults('_config', [
'redirect' => 'admin.sales.orders.view',
])->name('admin.sales.invoices.update.state');
// Sales Shipments Routes
Route::get('/shipments', 'Webkul\Admin\Http\Controllers\Sales\ShipmentController@index')->defaults('_config', [

View File

@ -3,14 +3,15 @@
namespace Webkul\Admin\Listeners;
use Illuminate\Support\Facades\Mail;
use Webkul\Admin\Mail\NewOrderNotification;
use Webkul\Admin\Mail\NewAdminNotification;
use Webkul\Admin\Mail\NewInvoiceNotification;
use Webkul\Admin\Mail\NewShipmentNotification;
use Webkul\Admin\Mail\NewInventorySourceNotification;
use Webkul\Admin\Mail\CancelOrderNotification;
use Webkul\Admin\Mail\NewOrderNotification;
use Webkul\Admin\Mail\NewRefundNotification;
use Webkul\Admin\Mail\NewInvoiceNotification;
use Webkul\Admin\Mail\CancelOrderNotification;
use Webkul\Admin\Mail\NewShipmentNotification;
use Webkul\Admin\Mail\OrderCommentNotification;
use Webkul\Admin\Mail\CancelOrderAdminNotification;
use Webkul\Admin\Mail\NewInventorySourceNotification;
class Order
{
@ -117,10 +118,18 @@ class Order
public function sendCancelOrderMail($order)
{
try {
/* email to customer */
$configKey = 'emails.general.notifications.emails.general.notifications.cancel-order';
if (core()->getConfigData($configKey)) {
Mail::queue(new CancelOrderNotification($order));
}
/* email to admin */
$configKey = 'emails.general.notifications.emails.general.notifications.new-admin';
if (core()->getConfigData($configKey)) {
app()->setLocale(env('APP_LOCALE'));
Mail::queue(new CancelOrderAdminNotification($order));
}
} catch (\Exception $e) {
report($e);
}

View File

@ -0,0 +1,31 @@
<?php
namespace Webkul\Admin\Listeners;
use Illuminate\Support\Facades\Mail;
use Webkul\User\Notifications\AdminUpdatePassword;
use Webkul\Customer\Notifications\CustomerUpdatePassword;
class PasswordChange
{
/**
* Send mail on updating password.
*
* @param \Webkul\Customer\Models\Customer|\Webkul\User\Models\Admin $adminOrCustomer
* @return void
*/
public function sendUpdatePasswordMail($adminOrCustomer)
{
try {
if ($adminOrCustomer instanceof \Webkul\Customer\Models\Customer) {
Mail::queue(new CustomerUpdatePassword($adminOrCustomer));
}
if ($adminOrCustomer instanceof \Webkul\User\Models\Admin) {
Mail::queue(new AdminUpdatePassword($adminOrCustomer));
}
} catch (\Exception $e) {
report($e);
}
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace Webkul\Admin\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class CancelOrderAdminNotification extends Mailable
{
use Queueable, SerializesModels;
/**
* @var \Webkul\Sales\Contracts\Order
*/
public $order;
/**
* @param \Webkul\Sales\Contracts\Order $order
* @return void
*/
public function __construct($order)
{
$this->order = $order;
}
public function build()
{
return $this->from(core()->getSenderEmailDetails()['email'], core()->getSenderEmailDetails()['name'])
->to(core()->getAdminEmailDetails()['email'])
->subject(trans('shop::app.mail.order.cancel.subject'))
->view('shop::emails.sales.order-cancel-admin');
}
}

View File

@ -38,7 +38,7 @@ class OrderCommentNotification extends Mailable
{
return $this->from(core()->getSenderEmailDetails()['email'], core()->getSenderEmailDetails()['name'])
->to($this->comment->order->customer_email, $this->comment->order->customer_full_name)
->subject(trans('shop::app.mail.order.comment.subject'))
->subject(trans('shop::app.mail.order.comment.subject', ['order_id' => $this->comment->order->increment_id]))
->view('shop::emails.sales.new-order-comment');
}
}

View File

@ -14,6 +14,8 @@ class EventServiceProvider extends ServiceProvider
*/
public function boot()
{
Event::listen('user.admin.update-password', 'Webkul\Admin\Listeners\PasswordChange@sendUpdatePasswordMail');
Event::listen('checkout.order.save.after', 'Webkul\Admin\Listeners\Order@sendNewOrderMail');
Event::listen('sales.invoice.save.after', 'Webkul\Admin\Listeners\Order@sendNewInvoiceMail');

View File

@ -320,6 +320,14 @@ return array (
'invoice-btn-title' => 'Rechnung',
'info' => 'Informationen',
'invoices' => 'Rechnungen',
'invoices-change-title' => 'Change invoice state',
'invoices-change-state-desc' => 'Please select the new invoice state:',
'invoice-status-paid' => 'Paid',
'invoice-status-pending' => 'Pending',
'invoice-status-overdue' => 'Overdue',
'invoice-status-update' => 'Save changes',
'invoice-status-confirmed' => 'The invoice state has been changed.',
'invoice-status-error' => 'Could not update the invoice state. ',
'shipments' => 'Sendungen',
'order-and-account' => 'Bestellung und Rechnung',
'order-info' => 'Bestellinformationen',

View File

@ -319,6 +319,14 @@ return [
'invoice-btn-title' => 'Invoice',
'info' => 'Information',
'invoices' => 'Invoices',
'invoices-change-title' => 'Change invoice state',
'invoices-change-state-desc' => 'Please select the new invoice state:',
'invoice-status-paid' => 'Paid',
'invoice-status-pending' => 'Pending',
'invoice-status-overdue' => 'Overdue',
'invoice-status-update' => 'Save changes',
'invoice-status-confirmed' => 'The invoice state has been changed.',
'invoice-status-error' => 'Could not update the invoice state. ',
'shipments' => 'Shipments',
'order-and-account' => 'Order and Account',
'order-info' => 'Order Information',
@ -1219,7 +1227,7 @@ return [
'cancel-success' => ':name canceled successfully.',
'cancel-error' => ':name can not be canceled.',
'already-taken' => 'The :name has already been taken.',
'order-pending' => 'Cannot delete account because some Order(s) are pending or processing state.'
'order-pending' => 'Cannot delete :name account because some Order(s) are pending or processing state.'
],
'footer' => [

View File

@ -318,6 +318,14 @@ return [
'invoice-btn-title' => 'صورت حساب',
'info' => 'اطلاعات',
'invoices' => 'صورت حساب ها',
'invoices-change-title' => 'Change invoice state',
'invoices-change-state-desc' => 'Please select the new invoice state:',
'invoice-status-paid' => 'Paid',
'invoice-status-pending' => 'Pending',
'invoice-status-overdue' => 'Overdue',
'invoice-status-update' => 'Save changes',
'invoice-status-confirmed' => 'The invoice state has been changed.',
'invoice-status-error' => 'Could not update the invoice state. ',
'shipments' => 'حمل و نقل ها',
'order-and-account' => 'سفارش و حساب',
'order-info' => 'اطلاعات سفارش',

View File

@ -318,6 +318,14 @@ return [
'invoice-btn-title' => 'Fattura',
'info' => 'Informazoni',
'invoices' => 'Fatture',
'invoices-change-title' => 'Change invoice state',
'invoices-change-state-desc' => 'Please select the new invoice state:',
'invoice-status-paid' => 'Paid',
'invoice-status-pending' => 'Pending',
'invoice-status-overdue' => 'Overdue',
'invoice-status-update' => 'Save changes',
'invoice-status-confirmed' => 'The invoice state has been changed.',
'invoice-status-error' => 'Could not update the invoice state. ',
'shipments' => 'Spedizioni',
'order-and-account' => 'Ordine e Account',
'order-info' => 'informazioni Ordine',

View File

@ -318,6 +318,14 @@ return [
'invoice-btn-title' => 'Factuur',
'info' => 'Informatie',
'invoices' => 'Facturen',
'invoices-change-title' => 'Change invoice state',
'invoices-change-state-desc' => 'Please select the new invoice state:',
'invoice-status-paid' => 'Paid',
'invoice-status-pending' => 'Pending',
'invoice-status-overdue' => 'Overdue',
'invoice-status-update' => 'Save changes',
'invoice-status-confirmed' => 'The invoice state has been changed.',
'invoice-status-error' => 'Could not update the invoice state. ',
'shipments' => 'Verzendingen',
'order-and-account' => 'Order and Account',
'order-info' => 'Order Information',

View File

@ -317,6 +317,14 @@ return [
'invoice-btn-title' => 'Faktura',
'info' => 'Informacje',
'invoices' => 'Faktury',
'invoices-change-title' => 'Change invoice state',
'invoices-change-state-desc' => 'Please select the new invoice state:',
'invoice-status-paid' => 'Paid',
'invoice-status-pending' => 'Pending',
'invoice-status-overdue' => 'Overdue',
'invoice-status-update' => 'Save changes',
'invoice-status-confirmed' => 'The invoice state has been changed.',
'invoice-status-error' => 'Could not update the invoice state. ',
'shipments' => 'Przesyłki',
'order-and-account' => 'Zamówienie i konto',
'order-info' => 'Informacje o zamówieniu',

View File

@ -318,6 +318,14 @@ return [
'invoice-btn-title' => 'Faturar',
'info' => 'Informação',
'invoices' => 'Faturas',
'invoices-change-title' => 'Change invoice state',
'invoices-change-state-desc' => 'Please select the new invoice state:',
'invoice-status-paid' => 'Paid',
'invoice-status-pending' => 'Pending',
'invoice-status-overdue' => 'Overdue',
'invoice-status-update' => 'Save changes',
'invoice-status-confirmed' => 'The invoice state has been changed.',
'invoice-status-error' => 'Could not update the invoice state. ',
'shipments' => 'Envios',
'order-and-account' => 'Pedido e Conta',
'order-info' => 'Informação do Pedido',

View File

@ -316,6 +316,14 @@ return [
'invoice-btn-title' => 'Fatura',
'info' => 'Bilgi',
'invoices' => 'Faturalar',
'invoices-change-title' => 'Change invoice state',
'invoices-change-state-desc' => 'Please select the new invoice state:',
'invoice-status-paid' => 'Paid',
'invoice-status-pending' => 'Pending',
'invoice-status-overdue' => 'Overdue',
'invoice-status-update' => 'Save changes',
'invoice-status-confirmed' => 'The invoice state has been changed.',
'invoice-status-error' => 'Could not update the invoice state. ',
'shipments' => 'Kargo',
'order-and-account' => 'Sipariş ve Hesap',
'order-info' => 'Sipariş Bilgisi',

View File

@ -13,10 +13,7 @@
<div class="page-action">
<div class="export-import" @click="showModal('downloadDataGrid')">
<i class="export-icon"></i>
<span>
{{ __('admin::app.export.export') }}
</span>
<i class="export-icon"></i> <span>{{ __('admin::app.export.export') }}</span>
</div>
</div>
</div>

View File

@ -1,10 +1,10 @@
@extends('admin::layouts.master')
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.sales.invoices.view-title', ['invoice_id' => $invoice->id]) }}
@stop
@section('content-wrapper')
@section('content')
<?php $order = $invoice->order; ?>
@ -15,11 +15,18 @@
{!! view_render_event('sales.invoice.title.before', ['order' => $order]) !!}
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ route('admin.dashboard.index') }}';"></i>
{{ __('admin::app.sales.invoices.view-title', ['invoice_id' => $invoice->id]) }}
{!! view_render_event('sales.invoice.title.after', ['order' => $order]) !!}
</h1>
@if($invoice->state == 'paid')
<small><span class="badge badge-md badge-success">{{ __('admin::app.sales.orders.invoice-status-paid') }}</span></small>
@elseif($invoice->state == 'pending')
<span class="badge badge-md badge-warning">{{ __('admin::app.sales.orders.invoice-status-pending') }}</span>
@else
<span class="badge badge-md badge-danger">{{ __('admin::app.sales.orders.invoice-status-overdue') }}</span>
@endif
</div>
<div class="page-action">
@ -29,6 +36,10 @@
{{ __('admin::app.sales.invoices.print') }}
</a>
@if($invoice->state == "pending" || $invoice->state == "overdue")
<a href="#" id="ChangeStatus" class="btn btn-lg btn-primary" @click="showModal('changeInvoiceState')">{{ __('admin::app.sales.orders.invoices-change-title') }}</a>
@endif
{!! view_render_event('sales.invoice.page_action.after', ['order' => $order]) !!}
</div>
</div>
@ -37,7 +48,7 @@
<div class="sale-container">
<accordian :title="'{{ __('admin::app.sales.orders.order-and-account') }}'" :active="true">
<div slot="body">
<div slot="body" style="display: flex; overflow:auto;">
<div class="sale-section">
<div class="secton-title">
@ -46,10 +57,7 @@
<div class="section-content">
<div class="row">
<span class="title">
{{ __('admin::app.sales.invoices.order-id') }}
</span>
<span class="title">{{ __('admin::app.sales.invoices.order-id') }}</span>
<span class="value">
<a href="{{ route('admin.sales.orders.view', $order->id) }}">#{{ $order->increment_id }}</a>
</span>
@ -58,69 +66,55 @@
{!! view_render_event('sales.invoice.increment_id.after', ['order' => $order]) !!}
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.order-date') }}
</span>
<span class="value">
{{ $order->created_at }}
</span>
<span class="title">{{ __('admin::app.sales.orders.order-date') }}</span>
<span class="value">{{ $order->created_at }}</span>
</div>
{!! view_render_event('sales.invoice.created_at.after', ['order' => $order]) !!}
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.order-status') }}
</span>
<span class="value">
{{ $order->status_label }}
</span>
<span class="title">{{ __('admin::app.sales.orders.order-status') }}</span>
<span class="value">{{ $order->status_label }}</span>
</div>
{!! view_render_event('sales.invoice.status_label.after', ['order' => $order]) !!}
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.channel') }}
</span>
<span class="value">
{{ $order->channel_name }}
</span>
<span class="title">{{ __('admin::app.sales.orders.channel') }}</span>
<span class="value">{{ $order->channel_name }}</span>
</div>
{!! view_render_event('sales.invoice.channel_name.after', ['order' => $order]) !!}
<div class="row">
<span class="title">{{ __('admin::app.sales.orders.payment-method') }}</span>
<span class="value">{{ core()->getConfigData('sales.paymentmethods.' . $order->payment->method . '.title') }}</span>
</div>
<div class="row">
<span class="title">{{ __('admin::app.sales.orders.shipping-method') }}</span>
<span class="value">{{ $order->shipping_title }}</span>
</div>
{!! view_render_event('sales.invoice.shipping-method.after', ['order' => $order]) !!}
</div>
</div>
<div class="sale-section">
<div class="sale-section" style="margin: 0 0 0 300px;">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.account-info') }}</span>
</div>
<div class="section-content">
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.customer-name') }}
</span>
<span class="value">
{{ $invoice->address->name }}
</span>
<span class="title">{{ __('admin::app.sales.orders.customer-name') }}</span>
<span class="value">{{ $invoice->address->name }}</span>
</div>
{!! view_render_event('sales.invoice.customer_name.after', ['order' => $order]) !!}
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.email') }}
</span>
<span class="value">
{{ $invoice->address->email }}
</span>
<span class="title">{{ __('admin::app.sales.orders.email') }}</span>
<span class="value">{{ $invoice->address->email }}</span>
</div>
{!! view_render_event('sales.invoice.customer_email.after', ['order' => $order]) !!}
@ -131,14 +125,14 @@
</accordian>
<accordian :title="'{{ __('admin::app.sales.orders.address') }}'" :active="true">
<div slot="body">
<div slot="body" style="display: flex; overflow:auto;">
<div class="sale-section">
<div class="secton-title">
<div class="secton-title" style="width: 380px;">
<span>{{ __('admin::app.sales.orders.billing-address') }}</span>
</div>
<div class="section-content">
<div class="section-content" style="width: 380px;">
@include ('admin::sales.address', ['address' => $order->billing_address])
{!! view_render_event('sales.invoice.billing_address.after', ['order' => $order]) !!}
@ -146,86 +140,18 @@
</div>
@if ($order->shipping_address)
<div class="sale-section">
<div class="secton-title">
<div class="sale-section" style="margin: 0 0 0 300px;">
<div class="secton-title" style="width: 400px;">
<span>{{ __('admin::app.sales.orders.shipping-address') }}</span>
</div>
<div class="section-content">
<div class="section-content" style="width: 400px;">
@include ('admin::sales.address', ['address' => $order->shipping_address])
{!! view_render_event('sales.invoice.shipping_address.after', ['order' => $order]) !!}
</div>
</div>
@endif
</div>
</accordian>
<accordian :title="'{{ __('admin::app.sales.orders.payment-and-shipping') }}'" :active="true">
<div slot="body">
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.payment-info') }}</span>
</div>
<div class="section-content">
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.payment-method') }}
</span>
<span class="value">
{{ core()->getConfigData('sales.paymentmethods.' . $order->payment->method . '.title') }}
</span>
</div>
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.currency') }}
</span>
<span class="value">
{{ $order->order_currency_code }}
</span>
</div>
{!! view_render_event('sales.invoice.payment-method.after', ['order' => $order]) !!}
</div>
</div>
@if ($order->shipping_address)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.shipping-info') }}</span>
</div>
<div class="section-content">
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.shipping-method') }}
</span>
<span class="value">
{{ $order->shipping_title }}
</span>
</div>
<div class="row">
<span class="title">
{{ __('admin::app.sales.orders.shipping-price') }}
</span>
<span class="value">
{{ core()->formatBasePrice($order->base_shipping_amount) }}
</span>
</div>
{!! view_render_event('sales.invoice.shipping-method.after', ['order' => $order]) !!}
</div>
</div>
@endif
</div>
</accordian>
@ -254,9 +180,7 @@
@foreach ($invoice->items as $item)
<tr>
<td>{{ $item->getTypeInstance()->getOrderedItem($item)->sku }}</td>
<td>
{{ $item->name }}
<td>{{ $item->name }}
@if (isset($item->additional['attributes']))
<div class="item-options">
@ -264,19 +188,14 @@
@foreach ($item->additional['attributes'] as $attribute)
<b>{{ $attribute['attribute_name'] }} : </b>{{ $attribute['option_label'] }}</br>
@endforeach
</div>
@endif
</td>
<td>{{ core()->formatBasePrice($item->base_price) }}</td>
<td>{{ $item->qty }}</td>
<td>{{ core()->formatBasePrice($item->base_total) }}</td>
<td>{{ core()->formatBasePrice($item->base_tax_amount) }}</td>
@if ($invoice->base_discount_amount > 0)
<td>{{ core()->formatBasePrice($item->base_discount_amount) }}</td>
@endif
@ -284,7 +203,6 @@
<td>{{ core()->formatBasePrice($item->base_total + $item->base_tax_amount - $item->base_discount_amount) }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@ -322,12 +240,61 @@
<td>{{ core()->formatBasePrice($invoice->base_grand_total) }}</td>
</tr>
</table>
</div>
</accordian>
</div>
</div>
</div>
@stop
</div>
<modal id="changeInvoiceState" :is-open="modalIds.changeInvoiceState">
<h3 slot="header">{{ __('admin::app.sales.orders.invoices-change-title') }}</h3>
<div slot="body">
<option-wrapper></option-wrapper>
</div>
</modal>
@stop
@push('scripts')
<script type="text/x-template" id="options-template">
<form method="POST" action="{{ route('admin.sales.invoices.update.state', $invoice->id) }}">
<div class="page-content">
<p>Please select the new invoice state:</p>
<div class="form-container">
@csrf()
<div>
<input type="radio" name="state" id="paid" value="paid">
<label for="paid">{{ __('admin::app.sales.orders.invoice-status-paid') }}</label>
</div>
<div>
<input type="radio" name="state" id="pending" value="pending" @if($invoice->state == "pending") checked @endif>
<label for="pending">{{ __('admin::app.sales.orders.invoice-status-pending') }}</label>
</div>
<div>
<input type="radio" name="state" id="overdue" value="overdue" @if($invoice->state == "overdue") checked @endif>
<label for="overdue">{{ __('admin::app.sales.orders.invoice-status-overdue') }}</label>
</div>
</div>
<br />
<button type="submit" class="btn btn-md btn-primary">{{ __('admin::app.sales.orders.invoice-status-update')}}</button>
</div>
</form>
</script>
<script>
Vue.component('option-wrapper', {
template: '#options-template',
methods: {
onSubmit: function(e) {
// e.target.submit();
}
}
});
</script>
@endpush

View File

@ -157,37 +157,41 @@
</div>
</accordian>
<accordian :title="'{{ __('admin::app.sales.orders.address') }}'" :active="true">
<div slot="body">
@if ($order->billing_address || $order->shipping_address)
<accordian :title="'{{ __('admin::app.sales.orders.address') }}'" :active="true">
<div slot="body">
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.billing-address') }}</span>
</div>
@if($order->billing_address)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.billing-address') }}</span>
</div>
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->billing_address])
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->billing_address])
{!! view_render_event('sales.order.billing_address.after', ['order' => $order]) !!}
</div>
</div>
@endif
@if ($order->shipping_address)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.shipping-address') }}</span>
</div>
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->shipping_address])
{!! view_render_event('sales.order.shipping_address.after', ['order' => $order]) !!}
</div>
</div>
@endif
{!! view_render_event('sales.order.billing_address.after', ['order' => $order]) !!}
</div>
</div>
@if ($order->shipping_address)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.shipping-address') }}</span>
</div>
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->shipping_address])
{!! view_render_event('sales.order.shipping_address.after', ['order' => $order]) !!}
</div>
</div>
@endif
</div>
</accordian>
</accordian>
@endif
<accordian :title="'{{ __('admin::app.sales.orders.payment-and-shipping') }}'" :active="true">
<div slot="body">
@ -470,7 +474,15 @@
<td>{{ $invoice->created_at }}</td>
<td>#{{ $invoice->order->increment_id }}</td>
<td>{{ $invoice->address->name }}</td>
<td>{{ $invoice->status_label }}</td>
<td>
@if($invoice->state == "paid")
{{ __('admin::app.sales.orders.invoice-status-paid') }}
@elseif($invoice->state == "overdue")
{{ __('admin::app.sales.orders.invoice-status-overdue') }}
@else
{{ __('admin::app.sales.orders.invoice-status-pending') }}
@endif
</td>
<td>{{ core()->formatBasePrice($invoice->base_grand_total) }}</td>
<td class="action">
<a href="{{ route('admin.sales.invoices.view', $invoice->id) }}">

View File

@ -107,37 +107,41 @@
</div>
</accordian>
<accordian :title="'{{ __('admin::app.sales.orders.address') }}'" :active="true">
<div slot="body">
@if ($order->billing_address || $order->shipping_address)
<accordian :title="'{{ __('admin::app.sales.orders.address') }}'" :active="true">
<div slot="body">
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.billing-address') }}</span>
</div>
@if ($order->billing_address)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.billing-address') }}</span>
</div>
<div class="section-content">
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->billing_address])
@include ('admin::sales.address', ['address' => $order->billing_address])
</div>
</div>
@endif
@if ($order->shipping_address)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.shipping-address') }}</span>
</div>
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->shipping_address])
</div>
</div>
@endif
</div>
</div>
@if ($order->shipping_address)
<div class="sale-section">
<div class="secton-title">
<span>{{ __('admin::app.sales.orders.shipping-address') }}</span>
</div>
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->shipping_address])
</div>
</div>
@endif
</div>
</accordian>
</accordian>
@endif
<accordian :title="'{{ __('admin::app.sales.orders.payment-and-shipping') }}'" :active="true">
<div slot="body">

View File

@ -2,6 +2,7 @@
namespace Webkul\BookingProduct\Repositories;
use Illuminate\Support\Facades\Event;
use Webkul\Core\Eloquent\Repository;
use Illuminate\Support\Str;
@ -18,12 +19,16 @@ class BookingProductEventTicketRepository extends Repository
}
/**
* @param array $data
* @param \Webkul\BookingProduct\Contracts\BookingProduct $bookingProduct
* @param array $data
* @param \Webkul\BookingProduct\Contracts\BookingProduct $bookingProduct
*
* @return void
* @throws \Prettus\Validator\Exceptions\ValidatorException
*/
public function saveEventTickets($data, $bookingProduct)
public function saveEventTickets($data, $bookingProduct): void
{
Event::dispatch('booking_product.booking.event-ticket.save.before', ['data' => $data, 'bookingProduct' => $bookingProduct]);
$previousTicketIds = $bookingProduct->event_tickets()->pluck('id');
if (isset($data['tickets'])) {
@ -54,7 +59,7 @@ class BookingProductEventTicketRepository extends Repository
}
if (Str::contains($ticketId, 'ticket_')) {
$this->create(array_merge([
$ticket = $this->create(array_merge([
'booking_product_id' => $bookingProduct->id,
], $ticketInputs));
} else {
@ -62,13 +67,18 @@ class BookingProductEventTicketRepository extends Repository
$previousTicketIds->forget($index);
}
$this->update($ticketInputs, $ticketId);
$ticket = $this->update($ticketInputs, $ticketId);
}
$savedTickets[$ticketId]['ticket'] = $ticket;
$savedTickets[$ticketId]['ticketInputs'] = $ticketInputs;
}
}
foreach ($previousTicketIds as $previousTicketId) {
$this->delete($previousTicketId);
}
Event::dispatch('booking_product.booking.event-ticket.save.after', ['tickets' => $savedTickets]);
}
}

View File

@ -7,8 +7,11 @@ namespace Webkul\Core\Helpers;
use Faker\Factory;
use Codeception\Module\Laravel5;
use Webkul\BookingProduct\Models\BookingProduct;
use Webkul\BookingProduct\Models\BookingProductEventTicket;
use Webkul\Checkout\Models\Cart;
use Webkul\Checkout\Models\CartItem;
use Webkul\Customer\Models\Customer;
use Webkul\Product\Models\Product;
use Webkul\Attribute\Models\Attribute;
use Webkul\Checkout\Models\CartAddress;
@ -31,21 +34,19 @@ class Laravel5Helper extends Laravel5
public const SIMPLE_PRODUCT = 1;
public const VIRTUAL_PRODUCT = 2;
public const DOWNLOADABLE_PRODUCT = 3;
public const BOOKING_EVENT_PRODUCT = 4;
/**
* Returns the field name of the given attribute in which a value should be saved inside
* the 'product_attribute_values' table. Depends on the type.
*
* @param string $attribute
* @param string $type
*
* @return string|null
* @part ORM
*/
public static function getAttributeFieldName(string $type): ?string
{
$attributes = [];
$possibleTypes = [
'text' => 'text_value',
'select' => 'integer_value',
@ -60,7 +61,7 @@ class Laravel5Helper extends Laravel5
public function prepareCart(array $options = []): array
{
$faker = \Faker\Factory::create();
$faker = Factory::create();
$I = $this;
@ -108,7 +109,7 @@ class Laravel5Helper extends Laravel5
$cartItems = [];
$generatedCartItems = rand(3, 10);
$generatedCartItems = random_int(3, 10);
for ($i = 2; $i <= $generatedCartItems; $i++) {
$quantity = random_int(1, 10);
@ -178,6 +179,10 @@ class Laravel5Helper extends Laravel5
$I = $this;
switch ($productType) {
case self::BOOKING_EVENT_PRODUCT:
$product = $I->haveBookingEventProduct($configs, $productStates);
break;
case self::DOWNLOADABLE_PRODUCT:
$product = $I->haveDownloadableProduct($configs, $productStates);
break;
@ -205,7 +210,6 @@ class Laravel5Helper extends Laravel5
$productStates = array_merge($productStates, ['simple']);
}
/** @var Product $product */
$product = $I->createProduct($configs['productAttributes'] ?? [], $productStates);
$I->createAttributeValues($product->id, $configs['attributeValues'] ?? []);
@ -222,7 +226,6 @@ class Laravel5Helper extends Laravel5
$productStates = array_merge($productStates, ['virtual']);
}
/** @var Product $product */
$product = $I->createProduct($configs['productAttributes'] ?? [], $productStates);
$I->createAttributeValues($product->id, $configs['attributeValues'] ?? []);
@ -239,7 +242,6 @@ class Laravel5Helper extends Laravel5
$productStates = array_merge($productStates, ['downloadable']);
}
/** @var Product $product */
$product = $I->createProduct($configs['productAttributes'] ?? [], $productStates);
$I->createAttributeValues($product->id, $configs['attributeValues'] ?? []);
@ -249,6 +251,22 @@ class Laravel5Helper extends Laravel5
return $product->refresh();
}
private function haveBookingEventProduct(array $configs = [], array $productStates = []): Product
{
$I = $this;
if (! in_array('booking', $productStates)) {
$productStates = array_merge($productStates, ['booking']);
}
$product = $I->createProduct($configs['productAttributes'] ?? [], $productStates);
$I->createAttributeValues($product->id, $configs['attributeValues'] ?? []);
$I->createBookingEventProduct($product->id);
return $product->refresh();
}
private function createProduct(array $attributes = [], array $states = []): Product
{
return factory(Product::class)->states($states)->create($attributes);
@ -275,6 +293,18 @@ class Laravel5Helper extends Laravel5
]);
}
private function createBookingEventProduct(int $productId): void
{
$I = $this;
$bookingProduct = $I->have(BookingProduct::class, [
'product_id' => $productId,
]);
$I->have(BookingProductEventTicket::class, [
'booking_product_id' => $bookingProduct->id,
]);
}
private function createAttributeValues(int $productId, array $attributeValues = []): void
{
$I = $this;
@ -295,7 +325,7 @@ class Laravel5Helper extends Laravel5
}
/** @var array $defaultAttributeValues
/**
* Some defaults that should apply to all generated products.
* By defaults products will be generated as saleable.
* If you do not want this, this defaults can be overriden by $attributeValues.
@ -314,7 +344,7 @@ class Laravel5Helper extends Laravel5
'special_price' => null,
'price' => $faker->randomFloat(2, 1, 1000),
'weight' => '1.00', // necessary for shipping
'brand' => AttributeOption::firstWhere('attribute_id', $brand->id)->id,
'brand' => AttributeOption::query()->firstWhere('attribute_id', $brand->id)->id,
];
$attributeValues = array_merge($defaultAttributeValues, $attributeValues);

View File

@ -82,6 +82,7 @@ class CustomerController extends Controller
*/
public function update()
{
$isPasswordChanged = false;
$id = auth()->guard('customer')->user()->id;
$this->validate(request(), [
@ -104,6 +105,7 @@ class CustomerController extends Controller
if (isset ($data['oldpassword'])) {
if ($data['oldpassword'] != "" || $data['oldpassword'] != null) {
if (Hash::check($data['oldpassword'], auth()->guard('customer')->user()->password)) {
$isPasswordChanged = true;
$data['password'] = bcrypt($data['password']);
} else {
session()->flash('warning', trans('shop::app.customer.account.profile.unmatch'));
@ -119,6 +121,10 @@ class CustomerController extends Controller
if ($customer = $this->customerRepository->update($data, $id)) {
if ($isPasswordChanged) {
Event::dispatch('user.admin.update-password', $customer);
}
Event::dispatch('customer.update.after', $customer);
Session()->flash('success', trans('shop::app.customer.account.profile.edit-success'));
@ -150,7 +156,7 @@ class CustomerController extends Controller
$orders = $customerRepository->all_orders->whereIn('status', ['pending', 'processing'])->first();
if ($orders) {
session()->flash('error', trans('admin::app.response.order-pending'));
session()->flash('error', trans('admin::app.response.order-pending', ['name' => 'Customer']));
return redirect()->route($this->_config['redirect']);
} else {

View File

@ -0,0 +1,43 @@
<?php
namespace Webkul\Customer\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class CustomerUpdatePassword extends Mailable
{
use Queueable, SerializesModels;
/**
* The customer instance.
*
* @var \Webkul\Customer\Models\Customer $customer
*/
public $customer;
/**
* Create a new message instance.
*
* @param \Webkul\Customer\Models\Customer $customer
* @return void
*/
public function __construct($customer)
{
$this->customer = $customer;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->from(core()->getSenderEmailDetails()['email'], core()->getSenderEmailDetails()['name'])
->to($this->customer->email, $this->customer->name)
->subject(trans('shop::app.mail.update-password.subject'))
->view('shop::emails.customer.update-password', ['user' => $this->customer]);
}
}

View File

@ -16,4 +16,36 @@ class CustomerRepository extends Repository
{
return 'Webkul\Customer\Contracts\Customer';
}
/**
* Check if customer has order pending or processing.
*
* @param Webkul\Customer\Models\Customer
* @return boolean
*/
public function checkIfCustomerHasOrderPendingOrProcessing($customer)
{
return $customer->all_orders->pluck('status')->contains(function ($val) {
return $val === 'pending' || $val === 'processing';
});
}
/**
* Check if bulk customers, if they have order pending or processing.
*
* @param array
* @return boolean
*/
public function checkBulkCustomerIfTheyHaveOrderPendingOrProcessing($customerIds)
{
foreach ($customerIds as $customerId) {
$customer = $this->findorFail($customerId);
if ($this->checkIfCustomerHasOrderPendingOrProcessing($customer)) {
return true;
}
}
return false;
}
}

View File

@ -6,12 +6,8 @@ use Faker\Generator as Faker;
use Webkul\Product\Models\Product;
$factory->define(Product::class, function (Faker $faker) {
$now = date("Y-m-d H:i:s");
return [
'sku' => $faker->uuid,
'created_at' => $now,
'updated_at' => $now,
'attribute_family_id' => 1,
];
});
@ -26,4 +22,8 @@ $factory->state(Product::class, 'virtual', [
$factory->state(Product::class, 'downloadable', [
'type' => 'downloadable',
]);
$factory->state(Product::class, 'booking', [
'type' => 'booking',
]);

View File

@ -2,9 +2,10 @@
namespace Webkul\Product\Type;
use Webkul\Product\Models\ProductAttributeValue;
use Webkul\Product\Models\ProductFlat;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;
use Webkul\Product\Models\ProductFlat;
use Webkul\Product\Models\ProductAttributeValue;
class Configurable extends AbstractType
{
@ -351,14 +352,16 @@ class Configurable extends AbstractType
{
$minPrices = [];
/* method is calling many time so using variable */
$tablePrefix = DB::getTablePrefix();
$result = ProductFlat::join('products', 'product_flat.product_id', '=', 'products.id')
->distinct()
->where('products.parent_id', $this->product->id)
->selectRaw('IF( product_flat.special_price_from IS NOT NULL
AND product_flat.special_price_to IS NOT NULL , IF( NOW( ) >= product_flat.special_price_from
AND NOW( ) <= product_flat.special_price_to, IF( product_flat.special_price IS NULL OR product_flat.special_price = 0 , product_flat.price, LEAST( product_flat.special_price, product_flat.price ) ) , product_flat.price ) , IF( product_flat.special_price_from IS NULL , IF( product_flat.special_price_to IS NULL , IF( product_flat.special_price IS NULL OR product_flat.special_price = 0 , product_flat.price, LEAST( product_flat.special_price, product_flat.price ) ) , IF( NOW( ) <= product_flat.special_price_to, IF( product_flat.special_price IS NULL OR product_flat.special_price = 0 , product_flat.price, LEAST( product_flat.special_price, product_flat.price ) ) , product_flat.price ) ) , IF( product_flat.special_price_to IS NULL , IF( NOW( ) >= product_flat.special_price_from, IF( product_flat.special_price IS NULL OR product_flat.special_price = 0 , product_flat.price, LEAST( product_flat.special_price, product_flat.price ) ) , product_flat.price ) , product_flat.price ) ) ) AS min_price')
->selectRaw("IF( {$tablePrefix}product_flat.special_price_from IS NOT NULL
AND {$tablePrefix}product_flat.special_price_to IS NOT NULL , IF( NOW( ) >= {$tablePrefix}product_flat.special_price_from
AND NOW( ) <= {$tablePrefix}product_flat.special_price_to, IF( {$tablePrefix}product_flat.special_price IS NULL OR {$tablePrefix}product_flat.special_price = 0 , {$tablePrefix}product_flat.price, LEAST( {$tablePrefix}product_flat.special_price, {$tablePrefix}product_flat.price ) ) , {$tablePrefix}product_flat.price ) , IF( {$tablePrefix}product_flat.special_price_from IS NULL , IF( {$tablePrefix}product_flat.special_price_to IS NULL , IF( {$tablePrefix}product_flat.special_price IS NULL OR {$tablePrefix}product_flat.special_price = 0 , {$tablePrefix}product_flat.price, LEAST( {$tablePrefix}product_flat.special_price, {$tablePrefix}product_flat.price ) ) , IF( NOW( ) <= {$tablePrefix}product_flat.special_price_to, IF( {$tablePrefix}product_flat.special_price IS NULL OR {$tablePrefix}product_flat.special_price = 0 , {$tablePrefix}product_flat.price, LEAST( {$tablePrefix}product_flat.special_price, {$tablePrefix}product_flat.price ) ) , {$tablePrefix}product_flat.price ) ) , IF( {$tablePrefix}product_flat.special_price_to IS NULL , IF( NOW( ) >= {$tablePrefix}product_flat.special_price_from, IF( {$tablePrefix}product_flat.special_price IS NULL OR {$tablePrefix}product_flat.special_price = 0 , {$tablePrefix}product_flat.price, LEAST( {$tablePrefix}product_flat.special_price, {$tablePrefix}product_flat.price ) ) , {$tablePrefix}product_flat.price ) , {$tablePrefix}product_flat.price ) ) ) AS min_price")
->where('product_flat.channel', core()->getCurrentChannelCode())
->where('product_flat.locale', app()->getLocale())
->get();
foreach ($result as $price) {
@ -382,7 +385,7 @@ class Configurable extends AbstractType
$productFlat = ProductFlat::join('products', 'product_flat.product_id', '=', 'products.id')
->distinct()
->where('products.parent_id', $this->product->id)
->selectRaw('MAX(product_flat.price) AS max_price')
->selectRaw('MAX('.DB::getTablePrefix().'product_flat.price) AS max_price')
->where('product_flat.channel', core()->getCurrentChannelCode())
->where('product_flat.locale', app()->getLocale())
->first();

View File

@ -277,6 +277,12 @@ class Order extends Model implements OrderContract
return false;
}
foreach ($this->invoices as $item) {
if ($item->state == "pending" || $item->state == "overdue") {
return false;
}
}
foreach ($this->items as $item) {
if ($item->qty_to_refund > 0) {
return true;

View File

@ -97,7 +97,7 @@ class InvoiceRepository extends Repository
$invoice = $this->model->create([
'order_id' => $order->id,
'total_qty' => $totalQty,
'state' => 'paid',
'state' => 'pending',
'base_currency_code' => $order->base_currency_code,
'channel_currency_code' => $order->channel_currency_code,
'order_currency_code' => $order->order_currency_code,
@ -106,7 +106,7 @@ class InvoiceRepository extends Repository
foreach ($data['invoice']['items'] as $itemId => $qty) {
if (! $qty) {
continue;
continue;
}
$orderItem = $this->orderItemRepository->find($itemId);
@ -192,11 +192,8 @@ class InvoiceRepository extends Repository
}
$this->collectTotals($invoice);
$this->orderRepository->collectTotals($order);
$this->orderRepository->updateOrderStatus($order);
Event::dispatch('sales.invoice.save.after', $invoice);
} catch (\Exception $e) {
DB::rollBack();
@ -256,4 +253,16 @@ class InvoiceRepository extends Repository
return $invoice;
}
/**
* @param \Webkul\Sales\Contracts\Invoice $invoice
* @return void
*/
public function updateInvoiceState($invoice, $status)
{
$invoice->state = $status;
$invoice->save();
return true;
}
}

View File

@ -579,6 +579,15 @@ return [
'final-summary' => 'شكرا لإظهارك إهتمامك بمتجرنا سنرسل لك رقم التتبع بمجرد شحنه',
'help' => ': support_email إذا كنت بحاجة إلى أي نوع من المساعدة يرجى الاتصال بنا على',
'thanks' => 'شكرا!',
'comment' => [
'subject' => '#:order_id تمت إضافة تعليق جديد إلى طلبك',
'dear' => ':customer_name العزيز',
'final-summary' => 'شكرا لإظهار اهتمامك بمتجرنا',
'help' => ':support_email إذا كنت بحاجة إلى أي نوع من المساعدة يرجى الاتصال بنا على',
'thanks' => 'شكر!',
],
'cancel' => [
'subject' => 'تأكيد إلغاء الأمر',
'heading' => 'تم الغاء الأمر او الطلب',
@ -635,6 +644,13 @@ return [
'thanks' => 'شكرا!'
],
'update-password' => [
'subject' => 'تم تحديث كلمة السر',
'dear' => ':name عزيزي',
'info' => 'أنت تتلقى هذا البريد الإلكتروني لأنك قمت بتحديث كلمة المرور الخاصة بك.',
'thanks' => 'شكرا!'
],
'customer' => [
'new' => [
'dear' => ':customer_name العزيز',

View File

@ -573,6 +573,15 @@ return [
'final-summary' => 'Vielen Dank für Ihr Interesse an unserem Shop. Nach dem Versand senden wir Ihnen die Sendungsverfolgungsnummer',
'help' => 'Wenn Sie Hilfe benötigen, kontaktieren Sie uns bitte unter :support_email',
'thanks' => 'Vielen Dank!',
'comment' => [
'subject' => 'Neuer Kommentar zu Ihrer Bestellung hinzugefügt #:order_id',
'dear' => 'sehr geehrter :customer_name',
'final-summary' => 'Vielen Dank für Ihr Interesse an unserem Shop',
'help' => 'Wenn Sie Hilfe benötigen, kontaktieren Sie uns bitte unter :support_email',
'thanks' => 'Vielen Dank!',
],
'cancel' => [
'subject' => 'Bestätigung der Bestellungsstornierung',
'heading' => 'Bestellung storniert',
@ -629,6 +638,13 @@ return [
'thanks' => 'Vielen Dank!'
],
'update-password' => [
'subject' => 'Passwort aktualisiert',
'dear' => 'Sehr geehrte/r :name',
'info' => 'Sie erhalten diese E-Mail, weil Sie Ihr Passwort aktualisiert haben.',
'thanks' => 'Vielen Dank!'
],
'customer' => [
'new' => [
'dear' => 'Sehr geehrte/r :customer_name',

View File

@ -581,7 +581,7 @@ return [
'thanks' => 'Thanks!',
'comment' => [
'subject' => 'New comment added to your order',
'subject' => 'New comment added to your order #:order_id',
'dear' => 'Dear :customer_name',
'final-summary' => 'Thanks for showing your interest in our store',
'help' => 'If you need any kind of help please contact us at :support_email',
@ -592,7 +592,7 @@ return [
'subject' => 'Order Cancel Confirmation',
'heading' => 'Order Cancelled',
'dear' => 'Dear :customer_name',
'greeting' => 'You Order with order id #:order_id placed on :created_at has been cancelled',
'greeting' => 'Your Order with order id :order_id placed on :created_at has been cancelled',
'summary' => 'Summary of Order',
'shipping-address' => 'Shipping Address',
'billing-address' => 'Billing Address',
@ -644,6 +644,13 @@ return [
'thanks' => 'Thanks!'
],
'update-password' => [
'subject' => 'Password Updated',
'dear' => 'Dear :name',
'info' => 'You are receiving this email because you have updated your password.',
'thanks' => 'Thanks!'
],
'customer' => [
'new' => [
'dear' => 'Dear :customer_name',

View File

@ -538,6 +538,15 @@ return [
'final-summary' => 'Gracias por tu pedido, te enviaremos el número de seguimiento una vez enviado',
'help' => 'Si necesitas ayuda contacta con nosotros a través de :support_email',
'thanks' => '¡Gracias!',
'comment' => [
'subject' => 'Nuevo comentario agregado a su pedido #:order_id',
'dear' => 'Querida :customer_name',
'final-summary' => 'Gracias por mostrar su interés en nuestra tienda.',
'help' => 'Si necesita algún tipo de ayuda, contáctenos en :support_email',
'thanks' => '¡Gracias!',
],
'cancel' => [
'subject' => 'Confirmación de pedido cancelado',
'heading' => 'Pedido cancelado',
@ -582,6 +591,12 @@ return [
'final-summary' => 'Si no has solicitado cambiar de contraseña, ninguna acción es requerida por tu parte.',
'thanks' => '¡Gracias!'
],
'update-password' => [
'subject' => 'Contraseña actualiza',
'dear' => 'Estimado/a :name',
'info' => 'Está recibiendo este correo electrónico porque ha actualizado su contraseña.',
'thanks' => '¡Gracias!'
],
'customer' => [
'new' => [
'dear' => 'Estimado/a :customer_name',

View File

@ -578,6 +578,15 @@ return [
'final-summary' => 'با تشکر از علاقه شما به فروشگاه ما ، شماره حمل و نقل را برای شما ارسال می کنیم',
'help' => 'در صورت نیاز به هر نوع کمک ، لطفا با ما تماس بگیرید :support_email',
'thanks' => 'با تشکر!',
'comment' => [
'subject' => '#:order_id نظر جدیدی به سفارش شما اضافه شد',
'dear' => ':customer_name عزیز',
'final-summary' => 'با تشکر از علاقه شما به فروشگاه ما',
'help' => ':support_email در صورت نیاز به هر نوع کمک ، لطفا با ما تماس بگیرید',
'thanks' => 'با تشکر!',
],
'cancel' => [
'subject' => 'تأیید سفارش را لغو کنید',
'heading' => 'سفارش لغو شد',
@ -634,6 +643,13 @@ return [
'thanks' => 'با تشکر'
],
'update-password' => [
'subject' => 'پسورد آپدیت شد',
'dear' => ':name عزیز',
'info' => 'شما این ایمیل را دریافت می کنید زیرا رمز خود را به روز کرده اید.',
'thanks' => 'با تشکر'
],
'customer' => [
'new' => [
'dear' => ':customer_name عزیز',

View File

@ -580,7 +580,7 @@ return [
'thanks' => 'Grazie!',
'comment' => [
'subject' => 'Nuovo commento aggiunto al tuo ordine',
'subject' => 'Nuovo commento aggiunto al tuo ordine #:order_id',
'dear' => ':customer_name',
'final-summary' => 'Grazie per aver mostrato interesse per il nostro store',
'help' => 'Se hai bisogno di aiuto contattaci all\'indirizzo :support_email',
@ -643,6 +643,13 @@ return [
'thanks' => 'Grazie!'
],
'update-password' => [
'subject' => 'Password aggiornata',
'dear' => 'Cara :name',
'info' => 'Ricevi questa email perché hai aggiornato la password.',
'thanks' => 'Grazie!'
],
'customer' => [
'new' => [
'dear' => 'Gentile :customer_name',
@ -675,7 +682,7 @@ return [
'subject' => 'Email Iscrizione',
'greeting' => ' Benvenuto ' . config('app.name') . ' - Email Iscrizione',
'unsubscribe' => 'Cancellati',
'summary' => 'Grazie per avere scelto di ricevere le nostre email. È passato un po\' di tempo da quando hai letto le email di ' . config('app.name') . '. Non è un nostro desidero inondare la tua casella email con le nostre comunicazioni. Se desideri comunque
'summary' => 'Grazie per avere scelto di ricevere le nostre email. È passato un po\' di tempo da quando hai letto le email di ' . config('app.name') . '. Non è un nostro desidero inondare la tua casella email con le nostre comunicazioni. Se desideri comunque
non ricevere più le nostre news clicca il bottone qui sotto.'
]
]

View File

@ -529,7 +529,16 @@ return [
'grand-total' => '合計',
'final-summary' => '発送手続き完了後、お知らせメールを配信いたしますので、今しばらくお待ちください。',
'help' => 'お問合せなどは下記メールアドレスへご連絡ください。:support_email',
'thanks' => 'Gracias!',
'thanks' => 'ありがとう!',
'comment' => [
'subject' => '注文に新しいコメントが追加されました #:order_id',
'dear' => '親愛な :customer_name',
'final-summary' => '当店へのご関心をお寄せいただきありがとうございます',
'help' => '何か助けが必要な場合は、私たちに連絡してください :support_email',
'thanks' => 'ありがとう!',
],
'cancel' => [
'subject' => '注文がキャンセルされました',
'heading' => '注文がキャンセルされました',
@ -548,7 +557,7 @@ return [
'grand-total' => '合計',
'final-summary' => '私たちのお店にお越しいただき、ありがとうございます。',
'help' => 'お問合せなどは下記メールアドレスへご連絡ください。 :support_email',
'thanks' => 'Gracias!',
'thanks' => 'ありがとう!',
]
],
'invoice' => [
@ -574,6 +583,12 @@ return [
'final-summary' => 'Si no has solicitado cambiar de contraseña, ninguna acción es requerida por tu parte.',
'thanks' => 'ありがとうございます。'
],
'update-password' => [
'subject' => 'パスワードが更新されました',
'dear' => '様 :name',
'info' => 'パスワードを更新したため、このメールをお送りしています。',
'thanks' => 'ありがとうございます。'
],
'customer' => [
'new' => [
'dear' => '様 :customer_name',

View File

@ -582,7 +582,16 @@ return [
'grand-total' => 'Eindtotaal',
'final-summary' => 'Bedankt voor het tonen van uw interesse in onze winkel.We sturen u een trackingnummer zodra het is verzonden',
'help' => 'Als u hulp nodig heeft, neem dan contact met ons op via :support_email',
'thanks' => 'Thanks!',
'thanks' => 'Bedankt!',
'comment' => [
'subject' => 'Nieuwe opmerking toegevoegd aan uw bestelling #:order_id',
'dear' => 'Lieve :customer_name',
'final-summary' => 'Bedankt voor het tonen van uw interesse in onze winkel',
'help' => 'Als u hulp nodig heeft, neem dan contact met ons op via :support_email',
'thanks' => 'Bedankt!',
],
'cancel' => [
'subject' => 'Order Annuleren Bevestiging',
'heading' => 'Bestelling geannuleerd',
@ -639,6 +648,13 @@ return [
'thanks' => 'Bedankt!'
],
'update-password' => [
'subject' => 'Wachtwoord bijgewerkt',
'dear' => 'Lieve :name',
'info' => 'Je ontvangt deze e-mail omdat je je wachtwoord hebt bijgewerkt.',
'thanks' => 'Bedankt!'
],
'customer' => [
'new' => [
'dear' => 'Lieve :customer_name',

View File

@ -577,6 +577,15 @@ return [
'final-summary' => 'TDziękujemy za zainteresowanie naszym sklepem, a po podsumowaniu wyślemy ci numer śledzenia',
'help' => 'Jeśli potrzebujesz jakiejkolwiek pomocy, skontaktuj się z nami pod adresem :support_email',
'thanks' => 'Dzięki!',
'comment' => [
'subject' => 'Dodano nowy komentarz do Twojego zamówienia #:order_id',
'dear' => 'Drogi :customer_name',
'final-summary' => 'Dziękujemy za zainteresowanie naszym sklepem',
'help' => 'Jeśli potrzebujesz pomocy, skontaktuj się z nami pod adresem :support_email',
'thanks' => 'Dzięki!',
],
'cancel' => [
'subject' => 'Potwierdź anulowanie zamówienia',
'heading' => 'Zamówienie anulowane',
@ -633,6 +642,13 @@ return [
'thanks' => 'Dzięki!'
],
'update-password' => [
'subject' => 'Hasło zaktualizowane',
'dear' => 'Drogi/a :name',
'info' => 'Otrzymujesz tę wiadomość e-mail, ponieważ zaktualizowałeś swoje hasło.',
'thanks' => 'Dzięki!'
],
'customer' => [
'new' => [
'dear' => 'Drogi/a :customer_name',

View File

@ -554,6 +554,15 @@ return [
'final-summary' => 'Obrigado por mostrar o seu interesse em nossa loja nós lhe enviaremos o número de rastreamento assim que for despachado',
'help' => 'Se você precisar de algum tipo de ajuda, por favor entre em contato conosco :support_email',
'thanks' => 'Muito Obrigado!',
'comment' => [
'subject' => 'Novo comentário adicionado ao seu pedido #: order_id',
'dear' => 'Prezado :customer_name',
'final-summary' => 'Obrigado por mostrar seu interesse em nossa loja',
'help' => 'Se você precisar de algum tipo de ajuda, entre em contato conosco :support_email',
'thanks' => 'Obrigada!',
],
'cancel' => [
'subject' => 'Confirmação de Cancelamento de Pedido',
'heading' => 'Pedido Cancelado',
@ -607,6 +616,13 @@ return [
'thanks' => 'Obrigado!'
],
'update-password' => [
'subject' => 'Senha atualizada',
'dear' => 'Caro :name',
'info' => 'Você está recebendo este e-mail porque atualizou sua senha.',
'thanks' => 'Obrigado!'
],
'customer' => [
'new' => [
'dear' => 'Caro :customer_name',

View File

@ -574,9 +574,9 @@ return [
'final-summary' => 'Bizi tercih ettiğiniz için teşekkür ederiz. Ürün kargoya teslim edildikten sonra takip numarası iletilecektir.',
'help' => 'Soru ve görüşleriniz için lütfen bizimle iletişime geçiniz: :support_email',
'thanks' => 'Teşekkürler!',
'comment' => [
'subject' => 'Siparişinize yeni yorum yapıldı.',
'subject' => 'Siparişinize #:order_id yeni yorum yapıldı.',
'dear' => 'Sayın :customer_name',
'final-summary' => 'Bizi tercih ettiğiniz için teşekkür ederiz.',
'help' => 'Soru ve görüşleriniz için lütfen bizimle iletişime geçiniz: :support_email',
@ -639,6 +639,13 @@ return [
'thanks' => 'Teşekkürler!'
],
'update-password' => [
'subject' => 'Şifre güncellendi',
'dear' => 'Sayın :name',
'info' => 'Bu e-postayı, şifrenizi güncellediğiniz için alıyorsunuz.',
'thanks' => 'Teşekkürler!'
],
'customer' => [
'new' => [
'dear' => 'Sayın :customer_name',

View File

@ -0,0 +1,25 @@
@component('shop::emails.layouts.master')
<div style="text-align: center;">
<a href="{{ config('app.url') }}">
@if (core()->getConfigData('general.design.admin_logo.logo_image'))
<img src="{{ \Illuminate\Support\Facades\Storage::url(core()->getConfigData('general.design.admin_logo.logo_image')) }}" alt="{{ config('app.name') }}" style="height: 40px; width: 110px;"/>
@else
<img src="{{ asset('vendor/webkul/ui/assets/images/logo.png') }}" alt="{{ config('app.name') }}"/>
@endif
</a>
</div>
<div style="padding: 30px;">
<p style="font-size: 16px;color: #5E5E5E;line-height: 24px;">
{{ __('shop::app.mail.update-password.dear', ['name' => $user->name]) }},
</p>
<p style="font-size: 16px;color: #5E5E5E;line-height: 24px;">
{{ __('shop::app.mail.update-password.info') }}
</p>
<p style="font-size: 16px;color: #5E5E5E;line-height: 24px;">
{{ __('shop::app.mail.update-password.thanks') }}
</p>
</div>
@endcomponent

View File

@ -0,0 +1,21 @@
@component('shop::emails.layouts.master')
<div style="text-align: center;">
<a href="{{ config('app.url') }}">
@include ('shop::emails.layouts.logo')
</a>
</div>
<div style="padding: 30px;">
<p style="font-size: 16px;color: #5E5E5E;line-height: 24px;">
{{ __('shop::app.mail.update-password.dear', ['name' => $user->name]) }},
</p>
<p style="font-size: 16px;color: #5E5E5E;line-height: 24px;">
{{ __('shop::app.mail.update-password.info') }}
</p>
<p style="font-size: 16px;color: #5E5E5E;line-height: 24px;">
{{ __('shop::app.mail.update-password.thanks') }}
</p>
</div>
@endcomponent

View File

@ -0,0 +1,212 @@
@component('shop::emails.layouts.master')
<div style="text-align: center;">
<a href="{{ config('app.url') }}">
@if (core()->getConfigData('general.design.admin_logo.logo_image'))
<img src="{{ \Illuminate\Support\Facades\Storage::url(core()->getConfigData('general.design.admin_logo.logo_image')) }}" alt="{{ config('app.name') }}" style="height: 40px; width: 110px;"/>
@else
<img src="{{ asset('vendor/webkul/ui/assets/images/logo.png') }}" alt="{{ config('app.name') }}"/>
@endif
</a>
</div>
<div style="padding: 30px;">
<div style="font-size: 20px;color: #242424;line-height: 30px;margin-bottom: 34px;">
<span style="font-weight: bold;">
{{ __('shop::app.mail.order.cancel.heading') }}
</span> <br>
<p style="font-size: 16px;color: #5E5E5E;line-height: 24px;">
{{ __('shop::app.mail.order.cancel.dear', ['customer_name' => config('mail.from.name')]) }},
</p>
<p style="font-size: 16px;color: #5E5E5E;line-height: 24px;">
{!! __('shop::app.mail.order.cancel.greeting', [
'order_id' => '<a href="' . route('customer.orders.view', $order->id) . '" style="color: #0041FF; font-weight: bold;">#' . $order->increment_id . '</a>',
'created_at' => $order->created_at
])
!!}
</p>
</div>
<div style="font-weight: bold;font-size: 20px;color: #242424;line-height: 30px;margin-bottom: 20px !important;">
{{ __('shop::app.mail.order.cancel.summary') }}
</div>
<div style="display: flex;flex-direction: row;margin-top: 20px;justify-content: space-between;margin-bottom: 40px;">
<div style="line-height: 25px;">
<div style="font-weight: bold;font-size: 16px;color: #242424;">
{{ __('shop::app.mail.order.cancel.shipping-address') }}
</div>
<div>
{{ $order->shipping_address->company_name ?? '' }}
</div>
<div>
{{ $order->shipping_address->name }}
</div>
<div>
{{ $order->shipping_address->address1 }}, {{ $order->shipping_address->state }}
</div>
<div>
{{ core()->country_name($order->shipping_address->country) }} {{ $order->shipping_address->postcode }}
</div>
<div>---</div>
<div style="margin-bottom: 40px;">
{{ __('shop::app.mail.order.cancel.contact') }} : {{ $order->shipping_address->phone }}
</div>
<div style="font-size: 16px;color: #242424; font-weight: bold">
{{ __('shop::app.mail.order.cancel.shipping') }}
</div>
<div style="font-size: 16px;color: #242424;">
{{ $order->shipping_title }}
</div>
</div>
<div style="line-height: 25px;">
<div style="font-weight: bold;font-size: 16px;color: #242424;">
{{ __('shop::app.mail.order.cancel.billing-address') }}
</div>
<div>
{{ $order->billing_address->company_name ?? '' }}
</div>
<div>
{{ $order->billing_address->name }}
</div>
<div>
{{ $order->billing_address->address1 }}, {{ $order->billing_address->state }}
</div>
<div>
{{ core()->country_name($order->billing_address->country) }} {{ $order->billing_address->postcode }}
</div>
<div>---</div>
<div style="margin-bottom: 40px;">
{{ __('shop::app.mail.order.cancel.contact') }} : {{ $order->billing_address->phone }}
</div>
<div style="font-size: 16px; color: #242424; font-weight: bold">
{{ __('shop::app.mail.order.cancel.payment') }}
</div>
<div style="font-size: 16px; color: #242424;">
{{ core()->getConfigData('sales.paymentmethods.' . $order->payment->method . '.title') }}
</div>
</div>
</div>
<div class="section-content">
<div class="table mb-20">
<table style="overflow-x: auto; border-collapse: collapse;
border-spacing: 0;width: 100%">
<thead>
<tr style="background-color: #f2f2f2">
<th style="text-align: left;padding: 8px">{{ __('shop::app.customer.account.order.view.SKU') }}</th>
<th style="text-align: left;padding: 8px">{{ __('shop::app.customer.account.order.view.product-name') }}</th>
<th style="text-align: left;padding: 8px">{{ __('shop::app.customer.account.order.view.price') }}</th>
<th style="text-align: left;padding: 8px">{{ __('shop::app.customer.account.order.view.qty') }}</th>
</tr>
</thead>
<tbody>
@foreach ($order->items as $item)
<tr>
<td data-value="{{ __('shop::app.customer.account.order.view.SKU') }}" style="text-align: left;padding: 8px">
{{ $item->child ? $item->child->sku : $item->sku }}
</td>
<td data-value="{{ __('shop::app.customer.account.order.view.product-name') }}" style="text-align: left;padding: 8px">
{{ $item->name }}
@if (isset($item->additional['attributes']))
<div class="item-options">
@foreach ($item->additional['attributes'] as $attribute)
<b>{{ $attribute['attribute_name'] }} : </b>{{ $attribute['option_label'] }}</br>
@endforeach
</div>
@endif
</td>
<td data-value="{{ __('shop::app.customer.account.order.view.price') }}" style="text-align: left;padding: 8px">
{{ core()->formatPrice($item->price, $order->order_currency_code) }}
</td>
<td data-value="{{ __('shop::app.customer.account.order.view.qty') }}" style="text-align: left;padding: 8px">
{{ $item->qty_canceled }}
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<div style="font-size: 16px;color: #242424;line-height: 30px;float: right;width: 40%;margin-top: 20px;">
<div>
<span>{{ __('shop::app.mail.order.cancel.subtotal') }}</span>
<span style="float: right;">
{{ core()->formatPrice($order->sub_total, $order->order_currency_code) }}
</span>
</div>
<div>
<span>{{ __('shop::app.mail.order.cancel.shipping-handling') }}</span>
<span style="float: right;">
{{ core()->formatPrice($order->shipping_amount, $order->order_currency_code) }}
</span>
</div>
@foreach (Webkul\Tax\Helpers\Tax::getTaxRatesWithAmount($order, false) as $taxRate => $taxAmount )
<div>
<span id="taxrate-{{ core()->taxRateAsIdentifier($taxRate) }}">{{ __('shop::app.mail.order.cancel.tax') }} {{ $taxRate }} %</span>
<span id="taxamount-{{ core()->taxRateAsIdentifier($taxRate) }}" style="float: right;">
{{ core()->formatPrice($taxAmount, $order->order_currency_code) }}
</span>
</div>
@endforeach
@if ($order->discount_amount > 0)
<div>
<span>{{ __('shop::app.mail.order.cancel.discount') }}</span>
<span style="float: right;">
{{ core()->formatPrice($order->discount_amount, $order->order_currency_code) }}
</span>
</div>
@endif
<div style="font-weight: bold">
<span>{{ __('shop::app.mail.order.cancel.grand-total') }}</span>
<span style="float: right;">
{{ core()->formatPrice($order->grand_total, $order->order_currency_code) }}
</span>
</div>
</div>
<div style="margin-top: 65px;font-size: 16px;color: #5E5E5E;line-height: 24px;display: inline-block">
<p style="font-size: 16px;color: #5E5E5E;line-height: 24px;">
{!!
__('shop::app.mail.order.cancel.help', [
'support_email' => '<a style="color:#0041FF" href="mailto:' . config('mail.from.address') . '">' . config('mail.from.address'). '</a>'
])
!!}
</p>
<p style="font-size: 16px;color: #5E5E5E;line-height: 24px;">
{{ __('shop::app.mail.order.cancel.thanks') }}
</p>
</div>
</div>
@endcomponent

View File

@ -91,6 +91,13 @@
: '{{ __('velocity::app.shop.general.no') }}'"
></span>
@break;
@case('file')
<a v-if="product.product['{{ $attribute['code'] }}']" :href="`${baseUrl}/storage/${product.product['{{ $attribute['code'] }}']}`">
<span v-text="product.product['{{ $attribute['code'] }}'].substr(product.product['{{ $attribute['code'] }}'].lastIndexOf('/') + 1)" class="fs16"></span>
<i class='icon sort-down-icon download'></i>
</a>
<a v-else class="fs16">__</span>
@break;
@default
<span v-html="product['{{ $attribute['code'] }}'] ? product['{{ $attribute['code'] }}'] : product.product['{{ $attribute['code'] }}'] ? product.product['{{ $attribute['code'] }}'] : '__'" class="fs16"></span>
@break;

View File

@ -5,20 +5,24 @@
@if ($total = $reviewHelper->getTotalReviews($product))
<div class="product-ratings mb-10">
<span class="stars">
@for ($i = 1; $i <= round($reviewHelper->getAverageRating($product)); $i++)
<span class="icon star-icon"></span>
@for ($i = 1; $i <= 5; $i++)
@if($i <= round($reviewHelper->getAverageRating($product)))
<span class="icon star-icon"></span>
@else
<span class="icon star-icon-blank"></span>
@endif
@endfor
</span>
<div class="total-reviews">
{{
{{
__('shop::app.products.total-rating', [
'total_rating' => $reviewHelper->getTotalRating($product),
'total_rating' => $reviewHelper->getAverageRating($product),
'total_reviews' => $total,
])
])
}}
</div>
</div>
@endif
{!! view_render_event('bagisto.shop.products.review.after', ['product' => $product]) !!}
{!! view_render_event('bagisto.shop.products.review.after', ['product' => $product]) !!}

View File

@ -55,16 +55,20 @@
</span>
<span class="stars">
@for ($i = 1; $i <= $reviewHelper->getAverageRating($product); $i++)
@for ($i = 1; $i <= 5; $i++)
@if($i <= round($reviewHelper->getAverageRating($product)))
<span class="icon star-icon"></span>
@else
<span class="icon star-icon-blank"></span>
@endif
@endfor
</span>
<div class="total-reviews mt-5">
{{ __('shop::app.reviews.ratingreviews', [
'rating' => $reviewHelper->getTotalRating($product),
'rating' => $reviewHelper->getAverageRating($product),
'review' => $reviewHelper->getTotalReviews($product)])
}}
</div>
@ -101,9 +105,13 @@
</div>
<span class="stars">
@for ($i = 1; $i <= $review->rating; $i++)
@for ($i = 1; $i <= 5; $i++)
@if($i <= $review->rating)
<span class="icon star-icon"></span>
@else
<span class="icon star-icon-blank"></span>
@endif
@endfor
</span>
@ -154,4 +162,4 @@
</script>
@endpush
@endpush

View File

@ -10,22 +10,24 @@
<span>{{ __('shop::app.products.qty') }}</span>
</li>
@foreach ($product->grouped_products as $groupedProduct)
<li>
<span class="name">
{{ $groupedProduct->associated_product->name }}
@if($groupedProduct->associated_product->getTypeInstance()->isSaleable())
<li>
<span class="name">
{{ $groupedProduct->associated_product->name }}
@include ('shop::products.price', ['product' => $groupedProduct->associated_product])
</span>
@include ('shop::products.price', ['product' => $groupedProduct->associated_product])
</span>
<span class="qty">
<quantity-changer
:control-name="'qty[{{$groupedProduct->associated_product_id}}]'"
:validations="'required|numeric|min_value:0'"
quantity="{{ $groupedProduct->qty }}"
min-quantity="0">
</quantity-changer>
</span>
</li>
<span class="qty">
<quantity-changer
:control-name="'qty[{{$groupedProduct->associated_product_id}}]'"
:validations="'required|numeric|min_value:0'"
quantity="{{ $groupedProduct->qty }}"
min-quantity="0">
</quantity-changer>
</span>
</li>
@endif
@endforeach
</ul>
</div>

View File

@ -16,9 +16,13 @@
</span>
<span class="stars">
@for ($i = 1; $i <= round($reviewHelper->getAverageRating($product)); $i++)
@for ($i = 1; $i <= 5; $i++)
@if($i <= round($reviewHelper->getAverageRating($product)))
<span class="icon star-icon"></span>
@else
<span class="icon star-icon-blank"></span>
@endif
@endfor
</span>
@ -46,9 +50,13 @@
</div>
<span class="stars">
@for ($i = 1; $i <= $review->rating; $i++)
@for ($i = 1; $i <= 5; $i++)
@if($i <= $review->rating)
<span class="icon star-icon"></span>
@else
<span class="icon star-icon-blank"></span>
@endif
@endfor
</span>
@ -87,4 +95,4 @@
@endif
@endif
{!! view_render_event('bagisto.shop.products.view.reviews.after', ['product' => $product]) !!}
{!! view_render_event('bagisto.shop.products.view.reviews.after', ['product' => $product]) !!}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 50 (54983) - http://www.bohemiancoding.com/sketch -->
<title>Star-icon-blank</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Star-icon-blank" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<polygon id="Star" fill="#d4d4d4" fill-rule="nonzero" points="7.99999999 13.2668737 3.05572808 16 4 10.2111456 0 6.11145618 5.52786404 5.26687371 7.99999999 0 10.472136 5.26687371 16 6.11145618 12 10.2111456 12.9442719 16"></polygon>
</g>
</svg>

After

Width:  |  Height:  |  Size: 706 B

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
{
"/js/ui.js": "/js/ui.js?id=9f7467acd7ea119b7d87",
"/css/ui.css": "/css/ui.css?id=b5bedc0ff04a145ca18a"
"/js/ui.js": "/js/ui.js?id=706b63016a08ec91d32b",
"/css/ui.css": "/css/ui.css?id=54e0814214c81d98a101"
}

View File

@ -202,6 +202,12 @@ abstract class DataGrid
unset($parsedUrl['page']);
}
if (isset($parsedUrl['grand_total'])) {
foreach ($parsedUrl['grand_total'] as $key => $value) {
$parsedUrl['grand_total'][$key] = str_replace(',', '.', $parsedUrl['grand_total'][$key]);
}
}
$this->itemsPerPage = isset($parsedUrl['perPage']) ? $parsedUrl['perPage']['eq'] : $this->itemsPerPage;
unset($parsedUrl['perPage']);

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 50 (54983) - http://www.bohemiancoding.com/sketch -->
<title>Star-icon-blank</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Star-icon-blank" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<polygon id="Star" fill="#d4d4d4" fill-rule="nonzero" points="7.99999999 13.2668737 3.05572808 16 4 10.2111456 0 6.11145618 5.52786404 5.26687371 7.99999999 0 10.472136 5.26687371 16 6.11145618 12 10.2111456 12.9442719 16"></polygon>
</g>
</svg>

After

Width:  |  Height:  |  Size: 706 B

View File

@ -194,6 +194,12 @@
height: 24px;
}
.star-icon-blank {
background-image: url("../images/Star-Icon-Blank.svg");
width: 24px;
height: 24px;
}
.arrow-down-white-icon {
background-image: url("../images/down-arrow-white.svg");
width: 17px;
@ -346,4 +352,4 @@
background-image: url("../images/Camera.svg");
width: 24px;
height: 24px;
}
}

View File

@ -1,5 +1,5 @@
<tbody>
@if (count($records))
@if ($records instanceof \Illuminate\Pagination\LengthAwarePaginator && count($records))
@foreach ($records as $key => $record)
<tr>
@if ($enableMassActions)
@ -59,7 +59,7 @@
data-method="{{ $action['method'] }}"
data-action="{{ route($action['route'], $record->{$index}) }}"
data-token="{{ csrf_token() }}"
@if (isset($action['target']))
target="{{ $action['target'] }}"
@endif
@ -78,7 +78,9 @@
@endforeach
@else
<tr>
<td colspan="10" style="text-align: center;">{{ $norecords }}</td>
<td colspan="10">
<p style="text-align: center;">{{ $norecords }}</p>
</td>
</tr>
@endif
</tbody>

View File

@ -1,4 +1,4 @@
@if (gettype($results) == 'object')
@if ($results instanceof \Illuminate\Pagination\LengthAwarePaginator)
<div class="pagination">
{{ $results->links() }}
</div>

View File

@ -1,6 +1,6 @@
<thead v-if="massActionsToggle == false">
<tr style="height: 65px;">
@if (count($results['records']) && $results['enableMassActions'])
@if ($results['records'] instanceof \Illuminate\Pagination\LengthAwarePaginator && count($results['records']) && $results['enableMassActions'])
<th class="grid_head" id="mastercheckbox" style="width: 50px;">
<span class="checkbox">
<input type="checkbox" v-model="allSelected" v-on:change="selectAll">

View File

@ -8,22 +8,9 @@
@push('scripts')
<script type="text/x-template" id="datagrid-filters">
<div class="grid-container">
<div class="datagrid-filters" id="datagrid-filters">
<div class="datagrid-filters">
<div class="filter-left">
<div class="search-filter">
<input type="search" id="search-field" class="control"
placeholder="{{ __('ui::app.datagrid.search') }}" v-model="searchValue"
v-on:keyup.enter="searchCollection(searchValue)"/>
<div class="icon-wrapper">
<span class="icon search-icon search-btn"
v-on:click="searchCollection(searchValue)"></span>
</div>
</div>
</div>
<div class="filter-right">
@if (isset($results['extraFilters']['channels']))
<div class="dropdown-filters per-page">
<div class="control-group">
@ -82,7 +69,24 @@
</div>
</div>
@endif
</div>
</div>
<div class="datagrid-filters" id="datagrid-filters">
<div class="filter-left">
<div class="search-filter">
<input type="search" id="search-field" class="control"
placeholder="{{ __('ui::app.datagrid.search') }}" v-model="searchValue"
v-on:keyup.enter="searchCollection(searchValue)"/>
<div class="icon-wrapper">
<span class="icon search-icon search-btn"
v-on:click="searchCollection(searchValue)"></span>
</div>
</div>
</div>
<div class="filter-right">
<div class="dropdown-filters per-page">
<div class="control-group">
<label class="per-page-label" for="perPage">
@ -167,9 +171,7 @@
<li v-if='numberCondition != null'>
<div class="control-group">
<input type="number" class="control response-number"
placeholder="{{ __('ui::app.datagrid.numeric-value-here') }}"
v-model="numberValue"/>
<input type="text" class="control response-number" v-on:input="filterNumberInput" placeholder="{{ __('ui::app.datagrid.numeric-value-here') }}" v-model="numberValue"/>
</div>
</li>
@ -382,7 +384,11 @@
this.numberCondition = null;
},
getResponse: function () {
filterNumberInput: function(e){
this.numberValue = e.target.value.replace(/[^0-9\,\.]+/g, '');
},
getResponse: function() {
label = '';
for (let colIndex in this.columns) {

View File

@ -3,6 +3,7 @@
namespace Webkul\User\Http\Controllers;
use Hash;
use Illuminate\Support\Facades\Event;
class AccountController extends Controller
{
@ -26,7 +27,7 @@ class AccountController extends Controller
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\View\View
* @return \Illuminate\View\View
*/
public function edit()
{
@ -42,6 +43,7 @@ class AccountController extends Controller
*/
public function update()
{
$isPasswordChanged = false;
$user = auth()->guard('admin')->user();
$this->validate(request(), [
@ -62,11 +64,16 @@ class AccountController extends Controller
if (! $data['password']) {
unset($data['password']);
} else {
$isPasswordChanged = true;
$data['password'] = bcrypt($data['password']);
}
$user->update($data);
if ($isPasswordChanged) {
Event::dispatch('user.admin.update-password', $user);
}
session()->flash('success', trans('admin::app.users.users.account-save'));
return back();

View File

@ -2,12 +2,12 @@
namespace Webkul\User\Http\Controllers;
use Hash;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Event;
use Webkul\User\Repositories\AdminRepository;
use Webkul\User\Repositories\RoleRepository;
use Webkul\User\Http\Requests\UserForm;
use Hash;
use Webkul\User\Repositories\RoleRepository;
use Webkul\User\Repositories\AdminRepository;
class UserController extends Controller
{
@ -125,11 +125,14 @@ class UserController extends Controller
*/
public function update(UserForm $request, $id)
{
$isPasswordChanged = false;
$data = $request->all();
if (! $data['password']) {
unset($data['password']);
} else {
$isPasswordChanged = true;
$data['password'] = bcrypt($data['password']);
}
@ -143,6 +146,10 @@ class UserController extends Controller
$admin = $this->adminRepository->update($data, $id);
if ($isPasswordChanged) {
Event::dispatch('user.admin.update-password', $admin);
}
Event::dispatch('user.admin.update.after', $admin);
session()->flash('success', trans('admin::app.response.update-success', ['name' => 'User']));

View File

@ -0,0 +1,43 @@
<?php
namespace Webkul\User\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class AdminUpdatePassword extends Mailable
{
use Queueable, SerializesModels;
/**
* The admin instance.
*
* @var \Webkul\User\Contracts\Admin $admin
*/
public $admin;
/**
* Create a new admin instance.
*
* @param \Webkul\User\Contracts\Admin $admin
* @return void
*/
public function __construct($admin)
{
$this->admin = $admin;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->from(core()->getSenderEmailDetails()['email'], core()->getSenderEmailDetails()['name'])
->to($this->admin->email, $this->admin->name)
->subject(trans('shop::app.mail.update-password.subject'))
->view('shop::emails.admin.update-password', ['user' => $this->admin]);
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
{
"/js/velocity.js": "/js/velocity.js?id=c18e7d7ccfb80712f078",
"/js/velocity.js": "/js/velocity.js?id=0dcf3ed371cdd1a97616",
"/css/velocity-admin.css": "/css/velocity-admin.css?id=612d35e452446366eef7",
"/css/velocity.css": "/css/velocity.css?id=36aea00f600c674a2a60"
"/css/velocity.css": "/css/velocity.css?id=fde6d681177207bbbbb1"
}

View File

@ -77,7 +77,7 @@ class ContentDataGrid extends DataGrid
'type' => 'string',
'sortable' => true,
'searchable' => true,
'filterable' => true,
'filterable' => false,
'wrapper' => function($value) {
if ($value->content_type == 'category') {
return 'Category Slug';

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddHeaderContentCountVelocityMetaDataTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('velocity_meta_data', function (Blueprint $table) {
$table->text('header_content_count');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('velocity_meta_data', function (Blueprint $table) {
$table->dropColumn('header_content_count');
});
}
}

View File

@ -20,6 +20,7 @@ class VelocityMetaDataSeeder extends Seeder
'locale' => 'en',
'home_page_content' => "<p>@include('shop::home.advertisements.advertisement-four')@include('shop::home.featured-products') @include('shop::home.product-policy') @include('shop::home.advertisements.advertisement-three') @include('shop::home.new-products') @include('shop::home.advertisements.advertisement-two')</p>",
'header_content_count' => "5",
'footer_left_content' => __('velocity::app.admin.meta-data.footer-left-raw-content'),
'footer_middle_content' => '<div class="col-lg-6 col-md-12 col-sm-12 no-padding"><ul type="none"><li><a href="https://webkul.com/about-us/company-profile/">About Us</a></li><li><a href="https://webkul.com/about-us/company-profile/">Customer Service</a></li><li><a href="https://webkul.com/about-us/company-profile/">What&rsquo;s New</a></li><li><a href="https://webkul.com/about-us/company-profile/">Contact Us </a></li></ul></div><div class="col-lg-6 col-md-12 col-sm-12 no-padding"><ul type="none"><li><a href="https://webkul.com/about-us/company-profile/"> Order and Returns </a></li><li><a href="https://webkul.com/about-us/company-profile/"> Payment Policy </a></li><li><a href="https://webkul.com/about-us/company-profile/"> Shipping Policy</a></li><li><a href="https://webkul.com/about-us/company-profile/"> Privacy and Cookies Policy </a></li></ul></div>',

View File

@ -116,7 +116,7 @@ class ConfigurationController extends Controller
// update row
$product = $this->velocityMetaDataRepository->update($params, $id);
session()->flash('success', trans('admin::app.response.update-success', ['name' => 'Velocity Theme']));
session()->flash('success', trans('admin::app.response.update-success', ['name' => trans('velocity::app.admin.meta-data.title')]));
return redirect()->route($this->_config['redirect'], ['locale' => $this->locale]);
}

View File

@ -96,7 +96,7 @@ class ContentController extends Controller
$this->contentRepository->create($params);
session()->flash('success', trans('admin::app.response.create-success', ['name' => 'Content Page']));
session()->flash('success', trans('admin::app.response.create-success', ['name' => trans('velocity::app.admin.layouts.header-content')]));
return redirect()->route($this->_config['redirect']);
}
@ -131,7 +131,7 @@ class ContentController extends Controller
$content = $this->contentRepository->update($params, $id);
session()->flash('success', trans('admin::app.response.update-success', ['name' => 'Content']));
session()->flash('success', trans('admin::app.response.update-success', ['name' => trans('velocity::app.admin.layouts.header-content')]));
return redirect()->route($this->_config['redirect']);
}

View File

@ -129,6 +129,11 @@ class ContentRepository extends Repository
{
$query = $this->model::orderBy('position', 'ASC');
$velocityMetaData = app('Webkul\Velocity\Helpers\Helper')->getVelocityMetaData();
$headerContentCount = $velocityMetaData->header_content_count;
$headerContentCount = $headerContentCount != '' ? $headerContentCount : 5;
$contentCollection = $query
->select(
'velocity_contents.content_type',
@ -140,7 +145,7 @@ class ContentRepository extends Repository
->leftJoin('velocity_contents_translations', 'velocity_contents.id', 'velocity_contents_translations.content_id')
->distinct('velocity_contents_translations.id')
->where('velocity_contents_translations.locale', app()->getLocale())
->limit(5)
->limit($headerContentCount)
->get();
$formattedContent = [];

View File

@ -1,12 +1,12 @@
<template>
<div class="col-12 lg-card-container list-card product-card row" v-if="list">
<div class="product-image">
<div class="product-image" style="margin: auto;">
<a :title="product.name" :href="`${baseUrl}/${product.slug}`">
<img
:src="product.image"
:onerror="`this.src='${this.$root.baseUrl}/vendor/webkul/ui/assets/images/product/large-product-placeholder.png'`" />
<product-quick-view-btn :quick-view-details="product"></product-quick-view-btn>
<product-quick-view-btn :quick-view-details="product" v-if="!isMobile()"></product-quick-view-btn>
</a>
</div>
@ -101,5 +101,15 @@
'addToCartHtml': '',
}
},
methods: {
'isMobile': function () {
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
return true;
} else {
return false;
}
}
}
}
</script>

View File

@ -8,7 +8,6 @@ import ar from 'vee-validate/dist/locale/ar';
import VeeValidate, { Validator } from 'vee-validate';
import axios from 'axios';
window.axios = axios;
window.VeeValidate = VeeValidate;
window.jQuery = window.$ = require("jquery");

View File

@ -56,6 +56,7 @@
margin-bottom: 1rem;
margin-top: 68px;
color: #212529;
overflow-x: auto;
}
.per-page {
@ -79,6 +80,21 @@
margin-top: 10px;
margin-left: -158px;
}
.lg-card-container.list-card .product-image {
max-height: 85px;
}
.quick-view-btn-container {
left: -26px;
width: 109px;
}
.quick-view-btn-container span {
left: 24%;
top: -24px;
font-size: 13px;
}
}
@media only screen and (max-width: 992px) {
@ -396,6 +412,13 @@
}
}
}
.dropdown-filters {
&.per-page {
margin-top: 0;
position: relative;
}
}
}
}
@ -445,20 +468,23 @@
td {
width: 100%;
display: block;
border-top: none;
border-right: 1px solid $border-common !important;
&:before {
content: attr(data-value);
font-size: 15px;
font-weight: 600;
display: inline-block;
width: 120px;
}
.action {
display: inline-block;
}
&:first-child {
font-weight: bold;
}
}
}
}
@ -984,4 +1010,12 @@
}
}
}
}
#sort-by.sorter select {
top: 2px;
left: 25px;
padding: 0 10px;
position: absolute;
display: inline-block;
}
}

View File

@ -59,6 +59,13 @@ body {
}
}
}
#mini-cart {
.badge {
top: -8px;
left: 73%;
}
}
}
}

View File

@ -97,6 +97,7 @@ return [
'footer-left-content' => 'تذييل يسار المحتوى',
'subscription-content' => 'محتوى شريط الاشتراك',
'sidebar-categories' => 'فئات الشريط الجانبي',
'header_content_count' => 'Header Content Count',
'footer-left-raw-content' => '<p>نحن نحب صياغة البرامج وحل مشاكل العالم الحقيقي مع الثنائيات. نحن ملتزمون للغاية بأهدافنا. نحن نستثمر مواردنا لإنشاء برامج وتطبيقات سهلة الاستخدام على مستوى عالمي للأعمال التجارية مع أرفع مستوى ، على أعلى مستوى من الخبرة التقنية.</p>',
'slider-path' => 'مسار المنزلق',
'category-logo' => 'شعار الفئة',
@ -262,12 +263,14 @@ return [
'view' => 'رأي',
'filter' => 'منقي',
'update' => 'تحديث',
'download' => 'تحميل',
'addresses' => 'عناوين',
'reviews' => 'التعليقات',
'orders' => 'الطلب #٪ s',
'currencies' => 'Currencies',
'reviews' => 'التعليقات',
'top-brands' => 'ارقى الماركات',
'new-password' => 'كلمة مرور جديدة',
'no-file-available' => 'لا يوجد ملف متاح!',
'downloadables' => 'المنتجات القابلة للتحميل',
'confirm-new-password' => 'تأكيد كلمة المرور الجديدة',
'enter-current-password' => 'أدخل كلمة المرور الحالية',

View File

@ -96,6 +96,7 @@ return [
'home-page-content' => 'Inhalt der Startseite',
'footer-left-content' => 'Fußzeile Linker Inhalt',
'subscription-content' => 'Abonnementleiste Inhalt',
'header_content_count' => 'Header Content Count',
'sidebar-categories' => 'Seitenleisten-Kategorien',
'footer-left-raw-content' => '<p>Wir lieben es, Software zu erstellen und die Probleme der realen Welt mit den Binärdateien zu lösen. Wir fühlen uns unseren Zielen sehr verpflichtet. Wir investieren unsere Ressourcen, um benutzerfreundliche Software und Anwendungen von Weltklasse für das Unternehmensgeschäft mit erstklassiger Technologie zu entwickeln.</p>',
'slider-path' => 'Slider Pfad',
@ -271,6 +272,8 @@ return [
'downloadables' => 'Herunterladbare Produkte',
'confirm-new-password' => 'Bestätigen Sie Ihr neues Passwort',
'enter-current-password' => 'Geben Sie Ihr aktuelles Passwort ein',
'download' => 'Downloaden',
'no-file-available' => 'Geen bestand beschikbaar!',
'alert' => [
'info' => 'Information',

View File

@ -90,27 +90,28 @@ return [
]
],
'meta-data' => [
'footer' => 'Footer',
'title' => 'Velocity meta data',
'activate-slider' => 'Activate Slider',
'home-page-content' => 'Home Page Content',
'footer-left-content' => 'Footer Left Content',
'subscription-content' => 'Subscription bar Content',
'sidebar-categories' => 'Sidebar Categories',
'footer-left-raw-content' => '<p>We love to craft softwares and solve the real world problems with the binaries. We are highly committed to our goals. We invest our resources to create world class easy to use softwares and applications for the enterprise business with the top notch, on the edge technology expertise.</p>',
'slider-path' => 'Slider Path',
'category-logo' => 'Category logo',
'product-policy' => 'Product Policy',
'update-meta-data' => 'Update Meta Data',
'product-view-image' => 'Product View Image',
'advertisement-two' => 'Advertisement Two Images',
'advertisement-one' => 'Advertisement One Images',
'footer-middle-content' => 'Footer Middle Content',
'advertisement-four' => 'Advertisement Four Images',
'advertisement-three' => 'Advertisement Three Images',
'images' => 'Images',
'general' => 'General',
'add-image-btn-title' => 'Add Image'
'footer' => 'Footer',
'title' => 'Velocity meta data',
'activate-slider' => 'Activate Slider',
'home-page-content' => 'Home Page Content',
'footer-left-content' => 'Footer Left Content',
'subscription-content' => 'Subscription bar Content',
'sidebar-categories' => 'Sidebar Categories',
'header_content_count' => 'Header Content Count',
'footer-left-raw-content' => '<p>We love to craft softwares and solve the real world problems with the binaries. We are highly committed to our goals. We invest our resources to create world class easy to use softwares and applications for the enterprise business with the top notch, on the edge technology expertise.</p>',
'slider-path' => 'Slider Path',
'category-logo' => 'Category logo',
'product-policy' => 'Product Policy',
'update-meta-data' => 'Update Meta Data',
'product-view-image' => 'Product View Image',
'advertisement-two' => 'Advertisement Two Images',
'advertisement-one' => 'Advertisement One Images',
'footer-middle-content' => 'Footer Middle Content',
'advertisement-four' => 'Advertisement Four Images',
'advertisement-three' => 'Advertisement Three Images',
'images' => 'Images',
'general' => 'General',
'add-image-btn-title' => 'Add Image'
],
'category' => [
'save-btn-title' => 'Save Menu',
@ -264,10 +265,12 @@ return [
'orders' => 'Orders',
'update' => 'Update',
'reviews' => 'Reviews',
'download' => 'Download',
'currencies' => 'Currencies',
'addresses' => 'Addresses',
'top-brands' => 'Top Brands',
'new-password' => 'New password',
'no-file-available' => 'No File Available!',
'downloadables' => 'Downloadable Products',
'confirm-new-password' => 'Confirm new password',
'enter-current-password' => 'Enter your current password',

View File

@ -97,6 +97,7 @@ return [
'footer-left-content' => 'بالا و پایین صفحه',
'subscription-content' => 'نوار اشتراک محتوا',
'sidebar-categories' => 'دسته بندی های نوار کناری',
'header_content_count' => 'Header Content Count',
'footer-left-raw-content' => '<p>ما دوست داریم که نرم افزارهایی را تهیه کرده و مشکلات دنیای واقعی را با باینری حل کنیم. ما به اهداف خود بسیار متعهد هستیم. ما منابع خود را برای ایجاد کلاس های نرم افزاری و برنامه های کاربردی برای تجارت سازمانی با درجه برتر ، در لبه تخصص فناوری سرمایه گذاری می کنیم..</p>',
'slider-path' => 'مسیر کشویی',
'category-logo' => 'آرم دسته',
@ -259,16 +260,18 @@ return [
'general' => [
'no' => 'No',
'yes' => 'Yes',
'view' => 'چشم انداز',
'filter' => 'فیلتر',
'view' => 'چشم انداز',
'orders' => 'سفارشات',
'update' => 'به روز رسانی',
'download' => 'دانلود',
'reviews' => 'بررسی ها',
'addresses' => 'آدرس ها',
'update' => 'به روز رسانی',
'currencies' => 'Currencies',
'top-brands' => 'برندهای برتر',
'new-password' => 'رمز عبور جدید',
'downloadables' => 'محصولات دانلودی',
'no-file-available' => 'هیچ پرونده ای موجود نیست',
'confirm-new-password' => 'رمزعبور جدید را تأیید کنید',
'enter-current-password' => 'رمز عبور فعلی خود را وارد کنید',

View File

@ -98,6 +98,7 @@ return [
'footer-left-content' => 'Contenuti Footer Sinistra',
'subscription-content' => 'Conenuti Subscription bar',
'sidebar-categories' => 'Categorie Sidebar',
'header_content_count' => 'Header Content Count',
'footer-left-raw-content' => '<p>Ci piace personalizzare software e risolvere problemi del mondo reale. Siamo fortemente to our goals. We invest our resources to create world class easy to use softwares and applications for the enterprise business with the top notch, on the edge technology expertise.</p>',
'slider-path' => 'Percorso Slider',
'category-logo' => 'Logo Categoria',
@ -273,6 +274,8 @@ return [
'downloadables' => 'Prodotti Scaricabili',
'confirm-new-password' => 'Conferma nuova password',
'enter-current-password' => 'Inserisci la password attuale',
'download' => 'Scarica',
'no-file-available' => 'Nessun file disponibile!',
'alert' => [
'info' => 'Info',

View File

@ -97,6 +97,7 @@ return [
'footer-left-content' => 'Inhoud voettekst links',
'subscription-content' => 'Abonnementsbalk Inhoud',
'sidebar-categories' => 'Sidebar categorieën',
'header_content_count' => 'Header Content Count',
'footer-left-raw-content' => '<p>We houden ervan om software te maken en de echte wereldproblemen met de binaire bestanden op te lossen. We zijn zeer toegewijd aan onze doelen. We investeren onze middelen om gebruiksvriendelijke software en applicaties van wereldklasse te creëren met de allerbeste, geavanceerde technologie-expertise.</p>',
'slider-path' => 'Schuifpad',
'category-logo' => 'Category logo',
@ -265,12 +266,14 @@ return [
'update' => 'Bijwerken',
'reviews' => 'Reviews',
'addresses' => 'Adressen',
'download' => 'Downloaden',
'currencies' => 'Currencies',
'top-brands' => 'Top merken',
'new-password' => 'Nieuw wachtwoord',
'downloadables' => 'Downloadable Products',
'confirm-new-password' => 'Bevestig uw nieuw wachtwoord',
'enter-current-password' => 'Huidig wachtwoord',
'no-file-available' => 'Geen bestand beschikbaar!',
'confirm-new-password' => 'Bevestig uw nieuw wachtwoord',
'alert' => [
'info' => 'Info',

View File

@ -97,6 +97,7 @@ return [
'footer-left-content' => 'Zawartość lewejstrony stopki',
'subscription-content' => 'Treść paska subskrypcji',
'sidebar-categories' => 'kategorie paska bocznego',
'header_content_count' => 'Header Content Count',
'footer-left-raw-content' => '<p>Uwielbiamy tworzyć oprogramowanie i rozwiązywać rzeczywiste problemy z plikami binarnymi. Jesteśmy bardzo zaangażowani w realizację naszych celów. Inwestujemy olbrzymie zasoby w tworzenie światowej klasy łatwego w użyciu oprogramowania oraz aplikacji dla firm oraz użytkowników prywatnych , w oparciu o najnowszą wiedzę technologiczną</p>',
'slider-path' => 'Ścieżka Slidera (suwaka)',
'category-logo' => 'Logo kategorii',
@ -269,6 +270,8 @@ return [
'downloadables' => 'Produkty do pobrania',
'confirm-new-password' => 'Potwierdź nowe hasło',
'enter-current-password' => 'Wpisz swoje aktualne hasło',
'download' => 'Pobieranie',
'no-file-available' => 'Brak dostępnego pliku!',
'alert' => [
'info' => 'Info',

View File

@ -97,6 +97,7 @@ return [
'footer-left-content' => 'Conteúdo Rodapé Esquerdo',
'subscription-content' => 'Conteúdo da Barra de Inscrição',
'sidebar-categories' => 'Sidebar Categories',
'header_content_count' => 'Header Content Count',
'footer-left-raw-content' => '<p>We love to craft softwares and solve the real world problems with the binaries. We are highly committed to our goals. We invest our resources to create world class easy to use softwares and applications for the enterprise business with the top notch, on the edge technology expertise.</p>',
'slider-path' => 'Caminho do Slider',
'category-logo' => 'Logo da Categoria',
@ -272,6 +273,8 @@ return [
'downloadables' => 'Produtos para download',
'confirm-new-password' => 'Confirme a nova senha',
'enter-current-password' => 'Digite sua senha atual',
'download' => 'Baixar',
'no-file-available' => 'Nenhum arquivo disponível!',
'alert' => [
'info' => 'Informações',

View File

@ -97,6 +97,7 @@ return [
'footer-left-content' => 'Alt Sol İçeriği',
'subscription-content' => 'Abonelik Çubuğu İçeriği',
'sidebar-categories' => 'Yan Kategoriler',
'header_content_count' => 'Header Content Count',
'footer-left-raw-content' => '<p>Yazılımlar üretmeyi ve dünyada karşılaştığımız sorunları bu şekilde çözmeyi çok seviyoruz. Hedeflerimize büyük önem veriyor, en iyi olduğumuz teknoloji uzmanlığı ile kurumsal işleriniz için birin sınıf kullanıcı dostu yazılım ve uygulamalar oluşturmak için kaynaklarımıza yatırım yapıyoruz.</p>',
'slider-path' => 'Slider Yolu',
'category-logo' => 'Kategori Logosu',
@ -268,6 +269,8 @@ return [
'downloadables' => 'İndirilebilir Ürünler',
'confirm-new-password' => 'Parola Doğrula',
'enter-current-password' => 'Mevcut Parolanızı Girin',
'download' => 'İndir',
'no-file-available' => 'Dosya Yok!',
'alert' => [
'info' => 'Bilgi',

View File

@ -14,9 +14,10 @@
type="text"
id="page_link"
class="control"
value="{{ $pageTarget }}"
name="{{$locale}}[page_link]"
v-validate="'required|max:150'"
value="{{ $pageTarget }}"
@input="$event.target.value=$event.target.value.toLowerCase()"
data-vv-as="&quot;{{ __('velocity::app.admin.contents.content.category-slug') }}&quot;" />
<span class="control-error" v-if="errors.has('{!!$locale!!}[page_link]')">

View File

@ -78,6 +78,17 @@
value="{{ $metaData ? $metaData->sidebar_category_count : '10' }}" />
</div>
<div class="control-group">
<label>{{ __('velocity::app.admin.meta-data.header_content_count') }}</label>
<input
type="text"
class="control"
id="header_content_count"
name="header_content_count"
value="{{ $metaData ? $metaData->header_content_count : '5' }}" />
</div>
<div class="control-group">
<label>{{ __('shop::app.home.featured-products') }}</label>

View File

@ -110,7 +110,14 @@
? '{{ __('velocity::app.shop.general.yes') }}'
: '{{ __('velocity::app.shop.general.no') }}'"
></span>
@break;
@break;
@case('file')
<a v-if="product.product['{{ $attribute['code'] }}']" :href="`${$root.baseUrl}/storage/${product.product['{{ $attribute['code'] }}']}`">
<span v-text="product.product['{{ $attribute['code'] }}'].substr(product.product['{{ $attribute['code'] }}'].lastIndexOf('/') + 1)" class="fs16"></span>
<i class='material-icons'>arrow_downward</i>
</a>
<a v-else class="fs16">__</span>
@break;
@default
<span v-html="product['{{ $attribute['code'] }}'] ? product['{{ $attribute['code'] }}'] : product.product['{{ $attribute['code'] }}'] ? product.product['{{ $attribute['code'] }}'] : '__'" class="fs16"></span>
@break;

View File

@ -114,6 +114,12 @@
{{-- <product-quick-view-btn :quick-view-details="product"></product-quick-view-btn> --}}
<product-quick-view-btn :quick-view-details="{{ json_encode($product) }}"></product-quick-view-btn>
</a>
@if ($product->new)
<div class="sticker new">
{{ __('shop::app.products.new') }}
</div>
@endif
<div class="card-body">
<div class="product-name col-12 no-padding">

View File

@ -96,17 +96,17 @@
</div>
<div class="col-4">
<a
class="unset"
href="{{
$toolbarHelper->isOrderCurrent('name-asc')
? $toolbarHelper->getOrderUrl('name-asc')
: $toolbarHelper->getOrderUrl('name-desc')
}}">
<div class="sorter" id="sort-by">
<i class="material-icons">sort_by_alpha</i>
<span>{{ __('shop::app.products.sort-by') }}</span>
</a>
<select class="selective-div no-border" onchange="window.location.href = this.value">
@foreach ($toolbarHelper->getAvailableOrders() as $key => $order)
<option value="{{ $toolbarHelper->getOrderUrl($key) }}" {{ $toolbarHelper->isOrderCurrent($key) ? 'selected' : '' }}>
{{ __('shop::app.products.' . $order) }}
</option>
@endforeach
</select>
</div>
</div>
<div class="col-4">
@ -154,7 +154,7 @@
methods: {
toggleLayeredNavigation: function ({event, actionType}) {
this.layeredNavigation = !this.layeredNavigation;
}
},
}
})
})()

View File

@ -8,7 +8,7 @@
$total = $reviewHelper->getTotalReviews($product);
$avgRatings = $reviewHelper->getAverageRating($product);
$avgStarRating = ceil($avgRatings);
$avgStarRating = round($avgRatings);
$productImages = [];
$images = $productImageHelper->getGalleryImages($product);

View File

@ -27,8 +27,8 @@
@if ($attribute['type'] == 'file' && $attribute['value'])
<td>
<a href="{{ route('shop.product.file.download', [$product->product_id, $attribute['id']])}}">
<i class="icon sort-down-icon download"></i>
<a href="{{ route('shop.product.file.download', [$product->product_id, $attribute['id']])}}" style="color:black;">
<i class="icon rango-download-1"></i>
</a>
</td>
@elseif ($attribute['type'] == 'image' && $attribute['value'])

View File

@ -10,22 +10,24 @@
<span>{{ __('shop::app.products.qty') }}</span>
</li>
@foreach ($product->grouped_products as $groupedProduct)
<li>
<span class="name">
{{ $groupedProduct->associated_product->name }}
@if($groupedProduct->associated_product->getTypeInstance()->isSaleable())
<li>
<span class="name">
{{ $groupedProduct->associated_product->name }}
@include ('shop::products.price', ['product' => $groupedProduct->associated_product])
</span>
@include ('shop::products.price', ['product' => $groupedProduct->associated_product])
</span>
<span class="qty">
<quantity-changer
:control-name="'qty[{{$groupedProduct->associated_product_id}}]'"
:validations="'required|numeric|min_value:0'"
quantity="{{ $groupedProduct->qty }}"
min-quantity="0">
</quantity-changer>
</span>
</li>
<span class="qty">
<quantity-changer
:control-name="'qty[{{$groupedProduct->associated_product_id}}]'"
:validations="'required|numeric|min_value:0'"
quantity="{{ $groupedProduct->qty }}"
min-quantity="0">
</quantity-changer>
</span>
</li>
@endif
@endforeach
</ul>
</div>

View File

@ -6,7 +6,7 @@
$total = $reviewHelper->getTotalReviews($product);
$avgRatings = $reviewHelper->getAverageRating($product);
$avgStarRating = ceil($avgRatings);
$avgStarRating = round($avgRatings);
}
$percentageRatings = $reviewHelper->getPercentageRating($product);
@ -62,7 +62,7 @@
<div style="width: {{ $percentageRatings[$i] }}%"></div>
</div>
<span class="col-2 fs16">{{ $countRatings[$i] }}</span>
<span class="col-2 no-padding fs16">{{ $percentageRatings[$i] }} %</span>
</div>
@endfor
@ -106,7 +106,7 @@
<div style="width: {{ $percentageRatings[$i] }}%"></div>
</div>
<span class="col-2 fs16">{{ $countRatings[$i] }}</span>
<span class="col-2 no-padding fs16">{{ $percentageRatings[$i] }} %</span>
</div>
@endfor