WIP
This commit is contained in:
0
docs/create_telegram_bot.md
Normal file
0
docs/create_telegram_bot.md
Normal file
@@ -15,6 +15,7 @@
|
||||
* @property User $user
|
||||
* @property ModelCustomerCustomerGroup $model_customer_customer_group
|
||||
* @property ModelLocalisationOrderStatus $model_localisation_order_status
|
||||
* @property DB $db
|
||||
*/
|
||||
class ControllerExtensionModuleTgshop extends Controller
|
||||
{
|
||||
|
||||
@@ -161,7 +161,7 @@
|
||||
/>
|
||||
<script>
|
||||
$('#{{ settingKey }}-btn').click(function () {
|
||||
const telegramToken = $('#module_tgshop_bot_token').val(); // fetch from input
|
||||
const telegramToken = $('#module_tgshop_bot_token').val().trim(); // fetch from input
|
||||
if (! telegramToken) {
|
||||
alert('Сначала введите Telegram Bot Token!');
|
||||
return;
|
||||
@@ -251,19 +251,19 @@
|
||||
</div>
|
||||
<script>
|
||||
$('#{{ settingKey }}-btn-test').click(function () {
|
||||
const telegramToken = $('#module_tgshop_bot_token').val(); // fetch from input
|
||||
const telegramToken = $('#module_tgshop_bot_token').val().trim();
|
||||
if (! telegramToken) {
|
||||
alert('Сначала введите Telegram Bot Token!');
|
||||
return;
|
||||
}
|
||||
|
||||
const chatId = $('#module_tgshop_chat_id').val(); // fetch from input
|
||||
const chatId = $('#module_tgshop_chat_id').val().trim();
|
||||
if (! chatId) {
|
||||
alert('Сначала введите Chat ID!');
|
||||
return;
|
||||
}
|
||||
|
||||
const template = $('#{{ settingKey }}').val();
|
||||
const template = $('#{{ settingKey }}').val().trim();
|
||||
if (! template) {
|
||||
alert('Сначала задайте шаблон!');
|
||||
return;
|
||||
@@ -272,7 +272,7 @@
|
||||
fetch('/index.php?route=extension/tgshop/handle&api_action=testTgMessage', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
token: telegramToken,
|
||||
|
||||
@@ -55,7 +55,8 @@ class Application extends Container
|
||||
$dotenv->load();
|
||||
|
||||
$errorHandler = new ErrorHandler(
|
||||
$this->get(Logger::class)
|
||||
$this->get(Logger::class),
|
||||
$this,
|
||||
);
|
||||
|
||||
$errorHandler->register();
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Openguru\OpenCartFramework\Contracts;
|
||||
|
||||
use Openguru\OpenCartFramework\Http\JsonResponse;
|
||||
use Throwable;
|
||||
|
||||
interface ExceptionHandlerInterface
|
||||
{
|
||||
public function respond(Throwable $exception): ?JsonResponse;
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Openguru\OpenCartFramework;
|
||||
|
||||
use ErrorException;
|
||||
use Openguru\OpenCartFramework\Contracts\ExceptionHandlerInterface;
|
||||
use Openguru\OpenCartFramework\Exceptions\NonLoggableExceptionInterface;
|
||||
use Openguru\OpenCartFramework\Http\JsonResponse;
|
||||
use Openguru\OpenCartFramework\Http\Response;
|
||||
@@ -15,10 +16,12 @@ use Throwable;
|
||||
class ErrorHandler
|
||||
{
|
||||
private $logger;
|
||||
private Application $app;
|
||||
|
||||
public function __construct(Logger $logger)
|
||||
public function __construct(Logger $logger, Application $application)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
$this->app = $application;
|
||||
}
|
||||
|
||||
public function register(): void
|
||||
@@ -42,6 +45,15 @@ class ErrorHandler
|
||||
|
||||
public function handleException(Throwable $exception): void
|
||||
{
|
||||
if ($this->app->has(ExceptionHandlerInterface::class)) {
|
||||
$customHandler = $this->app->get(ExceptionHandlerInterface::class);
|
||||
$response = $customHandler->respond($exception);
|
||||
if ($response !== null) {
|
||||
$response->send();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$exception instanceof NonLoggableExceptionInterface) {
|
||||
$this->logger->logException($exception);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ class Request
|
||||
private $files;
|
||||
private $server;
|
||||
private $content;
|
||||
private array $headers = [];
|
||||
|
||||
public function __construct(
|
||||
array $query,
|
||||
@@ -20,26 +21,27 @@ class Request
|
||||
array $cookies,
|
||||
array $files,
|
||||
array $server,
|
||||
array $headers = [],
|
||||
string $content = null
|
||||
)
|
||||
{
|
||||
) {
|
||||
$this->query = $query;
|
||||
$this->request = $request;
|
||||
$this->cookies = $cookies;
|
||||
$this->files = $files;
|
||||
$this->server = $server;
|
||||
$this->headers = $headers;
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
public static function createFromGlobals(): Request
|
||||
{
|
||||
return new static($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
|
||||
return new static($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER, getallheaders());
|
||||
}
|
||||
|
||||
public function getContent(): string
|
||||
{
|
||||
if ($this->content === null || $this->content === '') {
|
||||
$this->content = (string)file_get_contents('php://input');
|
||||
$this->content = (string) file_get_contents('php://input');
|
||||
}
|
||||
|
||||
return $this->content;
|
||||
@@ -49,7 +51,7 @@ class Request
|
||||
{
|
||||
$content = $this->getContent();
|
||||
|
||||
if (!$content) {
|
||||
if (! $content) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
@@ -84,7 +86,7 @@ class Request
|
||||
public function header(string $name): ?string
|
||||
{
|
||||
$headers = [];
|
||||
foreach (getallheaders() as $key => $value) {
|
||||
foreach ($this->headers as $key => $value) {
|
||||
$headers[mb_strtolower($key)] = trim($value);
|
||||
}
|
||||
|
||||
|
||||
@@ -78,4 +78,13 @@ class SignatureValidator
|
||||
|
||||
return implode(PHP_EOL, $array);
|
||||
}
|
||||
|
||||
public function ensureUserWantsToReceiveMessages($request): void
|
||||
{
|
||||
$initDataString = rawurldecode($request->header('X-Telegram-Initdata'));
|
||||
|
||||
if (! $initDataString) {
|
||||
throw new TelegramInvalidSignatureException('Invalid Telegram signature!');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/TelegramInvalidSignatureException.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/TelegramInvalidSignatureException.php
Normal file → Executable file
@@ -3,6 +3,9 @@
|
||||
namespace Openguru\OpenCartFramework\Telegram;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use JsonException;
|
||||
use Openguru\OpenCartFramework\Application;
|
||||
use Openguru\OpenCartFramework\Http\Request;
|
||||
use Openguru\OpenCartFramework\Logger\Logger;
|
||||
|
||||
class TelegramService
|
||||
@@ -18,7 +21,8 @@ class TelegramService
|
||||
$this->client = $this->createGuzzleClient("https://api.telegram.org/bot{$botToken}/");
|
||||
}
|
||||
|
||||
public function escapeTelegramMarkdownV2(string $text): string {
|
||||
public function escapeTelegramMarkdownV2(string $text): string
|
||||
{
|
||||
$specials = ['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'];
|
||||
foreach ($specials as $char) {
|
||||
$text = str_replace($char, '\\' . $char, $text);
|
||||
@@ -33,10 +37,10 @@ class TelegramService
|
||||
return str_replace(array_keys($variables), $values, $template);
|
||||
}
|
||||
|
||||
public function sendMessage(int $chatId, string $text): bool
|
||||
public function sendMessage(int $chatId, string $text): void
|
||||
{
|
||||
if (! $this->botToken) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
$query = [
|
||||
@@ -48,8 +52,6 @@ class TelegramService
|
||||
$this->client->get('sendMessage', [
|
||||
'query' => $query,
|
||||
]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function createGuzzleClient(string $uri): Client
|
||||
@@ -66,4 +68,29 @@ class TelegramService
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function ensureUserWantsToReceiveMessages(): bool
|
||||
{
|
||||
/** @var Request $request */
|
||||
$request = Application::getInstance()->get(Request::class);
|
||||
|
||||
$initDataString = $request->header('X-Telegram-Initdata');
|
||||
|
||||
if (! $initDataString) {
|
||||
return false;
|
||||
}
|
||||
|
||||
parse_str($initDataString, $initData);
|
||||
if (! isset($initData['user'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$user = json_decode($initData['user'], true, 512, JSON_THROW_ON_ERROR);
|
||||
return ! empty($user['allows_write_to_pm']);
|
||||
} catch (JsonException $e) {
|
||||
$this->logger->logException($e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/TelegramValidateInitDataMiddleware.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/framework/Telegram/TelegramValidateInitDataMiddleware.php
Normal file → Executable file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Openguru\OpenCartFramework\Contracts\ExceptionHandlerInterface;
|
||||
use Openguru\OpenCartFramework\Http\JsonResponse;
|
||||
use Openguru\OpenCartFramework\Http\Response;
|
||||
use Openguru\OpenCartFramework\Telegram\TelegramInvalidSignatureException;
|
||||
use Throwable;
|
||||
|
||||
class CustomExceptionHandler implements ExceptionHandlerInterface
|
||||
{
|
||||
public function respond(Throwable $exception): ?JsonResponse
|
||||
{
|
||||
if ($exception instanceof TelegramInvalidSignatureException) {
|
||||
return new JsonResponse(['error' => 'Invalid Signature'], Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -89,10 +89,22 @@ class SettingsHandler
|
||||
$token = $request->json('token');
|
||||
$chatId = $request->json('chat_id');
|
||||
|
||||
if (! $token) {
|
||||
return new JsonResponse([
|
||||
'message' => 'Не задан Telegram BotToken',
|
||||
]);
|
||||
}
|
||||
|
||||
if (! $chatId) {
|
||||
return new JsonResponse([
|
||||
'message' => 'Не задан ChatID.',
|
||||
]);
|
||||
}
|
||||
|
||||
$variables = [
|
||||
'{store_name}' => $this->settings->get('oc_store_name'),
|
||||
'{order_id}' => 777,
|
||||
'{customer}' => 'Иван Вастльевич',
|
||||
'{customer}' => 'Иван Васильевич',
|
||||
'{email}' => 'telegram@opencart.com',
|
||||
'{phone}' => '+79999999999',
|
||||
'{comment}' => 'Это тестовый заказ',
|
||||
@@ -108,11 +120,13 @@ class SettingsHandler
|
||||
$this->telegramService
|
||||
->setBotToken($token)
|
||||
->sendMessage($chatId, $message);
|
||||
|
||||
return new JsonResponse([
|
||||
'message' => 'Сообщение отправлено. Проверьте Telegram.',
|
||||
]);
|
||||
} catch (ClientException $exception) {
|
||||
$json = json_decode($exception->getResponse()->getBody(), true);
|
||||
|
||||
return new JsonResponse([
|
||||
'message' => $json['description'],
|
||||
]);
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
namespace App\ServiceProviders;
|
||||
|
||||
use App\Exceptions\CustomExceptionHandler;
|
||||
use Openguru\OpenCartFramework\Container\ServiceProvider;
|
||||
use Openguru\OpenCartFramework\Contracts\ExceptionHandlerInterface;
|
||||
use Openguru\OpenCartFramework\Router\Router;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
@@ -10,5 +12,8 @@ class AppServiceProvider extends ServiceProvider
|
||||
public function register(): void
|
||||
{
|
||||
$this->container->get(Router::class)->loadRoutesFromFile(__DIR__ . '/../routes.php');
|
||||
$this->container->singleton(ExceptionHandlerInterface::class, function () {
|
||||
return new CustomExceptionHandler();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,11 +283,13 @@ class CartService
|
||||
|
||||
$lastTotal = $totals[count($totals) - 1] ?? false;
|
||||
$data['total'] = $lastTotal ? $lastTotal['value'] : 0;
|
||||
$data['total_text'] = $lastTotal ? $this->oc->currency->format($lastTotal['value'], $this->oc->session->data['currency']) : 0;
|
||||
$data['total_products_count'] = $this->oc->cart->countProducts();
|
||||
} else {
|
||||
$data['text_error'] = $this->oc->language->get('text_empty');
|
||||
$data['totals'] = [];
|
||||
$data['total'] = 0;
|
||||
$data['total_text'] = '';
|
||||
$data['products'] = [];
|
||||
$data['total_products_count'] = 0;
|
||||
unset($this->oc->session->data['success']);
|
||||
|
||||
@@ -8,6 +8,7 @@ use Exception;
|
||||
use Openguru\OpenCartFramework\Config\Settings;
|
||||
use Openguru\OpenCartFramework\Logger\Logger;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Connections\ConnectionInterface;
|
||||
use Openguru\OpenCartFramework\Support\Arr;
|
||||
use Openguru\OpenCartFramework\Telegram\TelegramService;
|
||||
use Rakit\Validation\Validator;
|
||||
use RuntimeException;
|
||||
@@ -82,7 +83,7 @@ class OrderCreateService
|
||||
$orderId = null;
|
||||
|
||||
$this->database->transaction(
|
||||
function () use ($orderData, $products, $totals, $orderStatusId, $now, &$orderId) {
|
||||
function () use (&$orderData, $products, $totals, $orderStatusId, $now, &$orderId) {
|
||||
$success = $this->database->insert(db_table('order'), $orderData);
|
||||
|
||||
if (! $success) {
|
||||
@@ -163,52 +164,10 @@ class OrderCreateService
|
||||
|
||||
$this->cartService->flush();
|
||||
|
||||
$chatId = $this->settings->get('telegram.chat_id');
|
||||
$template = $this->settings->get('telegram.owner_notification_template');
|
||||
$variables = [
|
||||
'{store_name}' => $orderData['store_name'],
|
||||
'{order_id}' => $orderId,
|
||||
'{customer}' => $orderData['firstname'] . ' ' . $orderData['lastname'],
|
||||
'{email}' => $orderData['email'],
|
||||
'{phone}' => $orderData['telephone'],
|
||||
'{comment}' => $orderData['comment'],
|
||||
'{address}' => $orderData['shipping_address_1'],
|
||||
'{total}' => $total,
|
||||
'{ip}' => $orderData['ip'],
|
||||
'{created_at}' => $now,
|
||||
];
|
||||
$orderData['order_id'] = $orderId;
|
||||
$orderData['total'] = $cart['total_text'] ?? '';
|
||||
|
||||
if ($chatId && $template) {
|
||||
$message = $this->telegramService->prepareMessage($template, $variables);
|
||||
try {
|
||||
$this->telegramService->sendMessage($chatId, $message);
|
||||
} catch (Exception $exception) {
|
||||
$this->logger->error(
|
||||
'Telegram sendMessage error: ' . json_encode([
|
||||
'chat_id' => $chatId,
|
||||
'text' => $message,
|
||||
])
|
||||
);
|
||||
$this->logger->logException($exception);
|
||||
}
|
||||
}
|
||||
|
||||
$customerChatId = $data['tgData']['id'] ?? null;
|
||||
$template = $this->settings->get('telegram.customer_notification_template');
|
||||
if ($customerChatId && $template) {
|
||||
$message = $this->telegramService->prepareMessage($template, $variables);
|
||||
try {
|
||||
$this->telegramService->sendMessage($customerChatId, $message);
|
||||
} catch (Exception $exception) {
|
||||
$this->logger->error(
|
||||
'Telegram sendMessage error: ' . json_encode([
|
||||
'chat_id' => $chatId,
|
||||
'text' => $message,
|
||||
])
|
||||
);
|
||||
$this->logger->logException($exception);
|
||||
}
|
||||
}
|
||||
$this->sendNotifications($orderData, $data['tgData']);
|
||||
}
|
||||
|
||||
private function validate(array $data): void
|
||||
@@ -230,4 +189,47 @@ class OrderCreateService
|
||||
throw new OrderValidationFailedException($validation->errors());
|
||||
}
|
||||
}
|
||||
|
||||
private function sendNotifications(array $orderData, array $tgInitData): void
|
||||
{
|
||||
$variables = [
|
||||
'{store_name}' => $orderData['store_name'],
|
||||
'{order_id}' => $orderData['order_id'],
|
||||
'{customer}' => $orderData['firstname'] . ' ' . $orderData['lastname'],
|
||||
'{email}' => $orderData['email'],
|
||||
'{phone}' => $orderData['telephone'],
|
||||
'{comment}' => $orderData['comment'],
|
||||
'{address}' => $orderData['shipping_address_1'],
|
||||
'{total}' => $orderData['total'],
|
||||
'{ip}' => $orderData['ip'],
|
||||
'{created_at}' => $orderData['date_added'],
|
||||
];
|
||||
|
||||
$chatId = $this->settings->get('telegram.chat_id');
|
||||
$template = $this->settings->get('telegram.owner_notification_template');
|
||||
|
||||
if ($chatId && $template) {
|
||||
$message = $this->telegramService->prepareMessage($template, $variables);
|
||||
try {
|
||||
$this->telegramService->sendMessage($chatId, $message);
|
||||
} catch (Exception $exception) {
|
||||
$this->logger->error("Telegram sendMessage to owner error. ChatID: $chatId, Message: $message");
|
||||
$this->logger->logException($exception);
|
||||
}
|
||||
}
|
||||
|
||||
$allowsWriteToPm = Arr::get($tgInitData, 'user.allows_write_to_pm', false);
|
||||
$customerChatId = Arr::get($tgInitData, 'user.id');
|
||||
$template = $this->settings->get('telegram.customer_notification_template');
|
||||
|
||||
if ($allowsWriteToPm && $customerChatId && $template) {
|
||||
$message = $this->telegramService->prepareMessage($template, $variables);
|
||||
try {
|
||||
$this->telegramService->sendMessage($customerChatId, $message);
|
||||
} catch (Exception $exception) {
|
||||
$this->logger->error("Telegram sendMessage to customer error. ChatID: $chatId, Message: $message");
|
||||
$this->logger->logException($exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,9 +19,6 @@ app
|
||||
.use(VueTelegramPlugin);
|
||||
|
||||
const settings = useSettingsStore();
|
||||
const categoriesStore = useCategoriesStore();
|
||||
categoriesStore.fetchTopCategories();
|
||||
categoriesStore.fetchCategories();
|
||||
|
||||
settings.load()
|
||||
.then(() => {
|
||||
@@ -37,6 +34,11 @@ settings.load()
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
const categoriesStore = useCategoriesStore();
|
||||
categoriesStore.fetchTopCategories();
|
||||
categoriesStore.fetchCategories();
|
||||
})
|
||||
.then(() => new AppMetaInitializer(settings).init())
|
||||
.then(() => app.mount('#app'))
|
||||
.then(() => window.Telegram.WebApp.ready())
|
||||
|
||||
@@ -16,7 +16,7 @@ export const useCartStore = defineStore('cart', {
|
||||
|
||||
getters: {
|
||||
canCheckout: (state) => {
|
||||
if (state.isLoading) {
|
||||
if (state.isLoading || state.error_warning.length > 0) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -15,6 +15,7 @@ export const useCheckoutStore = defineStore('checkout', {
|
||||
tgData: null,
|
||||
},
|
||||
|
||||
isLoading: false,
|
||||
validationErrors: {},
|
||||
}),
|
||||
|
||||
@@ -27,19 +28,28 @@ export const useCheckoutStore = defineStore('checkout', {
|
||||
actions: {
|
||||
async makeOrder() {
|
||||
try {
|
||||
this.isLoading = true;
|
||||
const data = window.Telegram.WebApp.initDataUnsafe;
|
||||
|
||||
if (! data.allows_write_to_pm) {
|
||||
await window.Telegram.WebApp.requestWriteAccess((granted) => {
|
||||
console.log("Allows write to PM: ", data.user.allows_write_to_pm);
|
||||
|
||||
if (! data.user.allows_write_to_pm) {
|
||||
console.log("Sending request");
|
||||
const granted = await new Promise(resolve => {
|
||||
window.Telegram.WebApp.requestWriteAccess((granted) => {
|
||||
resolve(granted);
|
||||
});
|
||||
});
|
||||
|
||||
if (granted) {
|
||||
data.user.allows_write_to_pm = true;
|
||||
console.log('Пользователь разрешил отправку сообщений');
|
||||
} else {
|
||||
alert('Вы не дали разрешение — бот не сможет отправлять вам уведомления');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.customer.tgData = data.user;
|
||||
this.customer.tgData = data;
|
||||
await storeOrder(this.customer);
|
||||
await window.Telegram.WebApp.HapticFeedback.notificationOccurred('success');
|
||||
await useCartStore().getProducts();
|
||||
@@ -53,6 +63,8 @@ export const useCheckoutStore = defineStore('checkout', {
|
||||
window.Telegram.WebApp.HapticFeedback.notificationOccurred('error');
|
||||
|
||||
throw error;
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -90,7 +90,9 @@
|
||||
class="btn btn-primary"
|
||||
:disabled="cart.canCheckout === false"
|
||||
@click="goToCheckout"
|
||||
>Перейти к оформлению</button>
|
||||
>
|
||||
Перейти к оформлению
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -55,7 +55,14 @@
|
||||
<div
|
||||
class="fixed px-4 pb-10 pt-4 bottom-0 left-0 w-full bg-base-200 z-50 flex flex-col justify-between items-center gap-2 border-t-1 border-t-base-300">
|
||||
<div v-if="error" class="text-error text-sm">{{ error }}</div>
|
||||
<button class="btn btn-primary w-full" @click="onCreateBtnClick">Создать заказ</button>
|
||||
<button
|
||||
:disabled="checkout.isLoading"
|
||||
class="btn btn-primary w-full"
|
||||
@click="onCreateBtnClick"
|
||||
>
|
||||
<span v-if="checkout.isLoading" class="loading loading-spinner loading-sm"></span>
|
||||
{{ btnText }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -65,13 +72,16 @@ import {useCheckoutStore} from "@/stores/CheckoutStore.js";
|
||||
import TgInput from "@/components/Form/TgInput.vue";
|
||||
import TgTextarea from "@/components/Form/TgTextarea.vue";
|
||||
import {useRouter} from "vue-router";
|
||||
import {ref} from "vue";
|
||||
import {computed, ref} from "vue";
|
||||
|
||||
const checkout = useCheckoutStore();
|
||||
const router = useRouter();
|
||||
|
||||
const error = ref(null);
|
||||
|
||||
const btnText = computed(() => {
|
||||
return checkout.isLoading ? 'Подождите...' : 'Создать заказ';
|
||||
});
|
||||
|
||||
async function onCreateBtnClick() {
|
||||
try {
|
||||
error.value = null;
|
||||
|
||||
@@ -72,9 +72,10 @@
|
||||
<button
|
||||
class="btn btn-primary btn-lg w-full"
|
||||
:class="isInCart ? 'btn-success' : 'btn-primary'"
|
||||
:disabled="canAddToCart === false"
|
||||
:disabled="cart.isLoading || canAddToCart === false"
|
||||
@click="actionBtnClick"
|
||||
>
|
||||
<span v-if="cart.isLoading" class="loading loading-spinner loading-sm"></span>
|
||||
{{ btnText }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user