From db18f3ae16c5ab777bbcf7bb022eabfaed69d58b Mon Sep 17 00:00:00 2001 From: Nikita Kiselev Date: Tue, 22 Jul 2025 23:07:10 +0300 Subject: [PATCH] wip: shopping cart, product options --- .../{CheckoutHandler.php => CartHandler.php} | 44 +++--- .../upload/oc_telegram_shop/src/routes.php | 6 +- spa/src/App.vue | 2 + spa/src/components/CartButton.vue | 40 ++++++ spa/src/components/Price.vue | 13 ++ .../ProductOptions/Cart/OptionCheckbox.vue | 18 +++ .../ProductOptions/Cart/OptionRadio.vue | 18 +++ .../ProductOptions/Cart/OptionText.vue | 18 +++ .../ProductOptions/ProductOptions.vue | 22 ++- .../ProductOptions/Types/OptionSelect.vue | 2 +- spa/src/components/ProductsList.vue | 1 - spa/src/components/Quantity.vue | 22 ++- spa/src/constants/options.js | 7 + spa/src/helpers.js | 30 ++++ spa/src/main.js | 4 +- spa/src/router.js | 6 +- spa/src/stores/CartStore.js | 132 +++++++++++------- spa/src/stores/ProductsStore.js | 17 +++ spa/src/views/Cart.vue | 97 +++++++------ spa/src/views/Product.vue | 94 ++++++------- spa/src/views/Products.vue | 22 +++ 21 files changed, 429 insertions(+), 186 deletions(-) rename module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/{CheckoutHandler.php => CartHandler.php} (56%) create mode 100644 spa/src/components/CartButton.vue create mode 100644 spa/src/components/Price.vue create mode 100644 spa/src/components/ProductOptions/Cart/OptionCheckbox.vue create mode 100644 spa/src/components/ProductOptions/Cart/OptionRadio.vue create mode 100644 spa/src/components/ProductOptions/Cart/OptionText.vue create mode 100644 spa/src/constants/options.js create mode 100644 spa/src/helpers.js create mode 100644 spa/src/views/Products.vue diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/CheckoutHandler.php b/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/CartHandler.php similarity index 56% rename from module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/CheckoutHandler.php rename to module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/CartHandler.php index 660191f..23e7f7a 100644 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/CheckoutHandler.php +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/CartHandler.php @@ -5,39 +5,28 @@ namespace App\Handlers; use Cart\Cart; use Openguru\OpenCartFramework\Http\JsonResponse; use Openguru\OpenCartFramework\Http\Request; -use Openguru\OpenCartFramework\QueryBuilder\Connections\ConnectionInterface; +use Openguru\OpenCartFramework\ImageTool\ImageToolInterface; -class CheckoutHandler +class CartHandler { private Cart $cart; - private \DB $connection; + private ImageToolInterface $imageTool; - public function __construct(Cart $cart, \DB $database) + public function __construct(Cart $cart, \DB $database, ImageToolInterface $imageTool) { $this->cart = $cart; $this->database = $database; + $this->imageTool = $imageTool; } - public function addToCart(Request $request): JsonResponse + public function index(Request $request): JsonResponse { - $item = $request->json(); - - $options = []; - - foreach ($item['options'] as $option) { - if (! empty($option['value']) && ! empty($option['value']['product_option_value_id'])) { - $options[$option['product_option_id']] = $option['value']['product_option_value_id']; - } - } - - $this->cart->add( - $item['productId'], - $item['quantity'], - $options, - ); - return new JsonResponse([ - 'data' => $this->cart->getProducts(), + 'data' => [ + 'products' => $this->getProducts(), + 'count' => $this->cart->countProducts(), + 'total' => $this->cart->getTotal(), + ] ]); } @@ -65,4 +54,15 @@ class CheckoutHandler 'data' => $items, ]); } + + private function getProducts(): array + { + $products = $this->cart->getProducts(); + + foreach ($products as &$product) { + $product['thumb'] = $this->imageTool->resize($product['image'], 100, 100, 'placeholder.png'); + } + + return $products; + } } diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/src/routes.php b/module/oc_telegram_shop/upload/oc_telegram_shop/src/routes.php index bfb26ed..2643956 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/src/routes.php +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/src/routes.php @@ -1,7 +1,7 @@ [CategoriesHandler::class, 'index'], - 'checkout' => [CheckoutHandler::class, 'checkout'], - 'addToCart' => [CheckoutHandler::class, 'addToCart'], + 'checkout' => [CartHandler::class, 'checkout'], + 'cart' => [CartHandler::class, 'index'], ]; diff --git a/spa/src/App.vue b/spa/src/App.vue index 1061b72..dbf09ab 100644 --- a/spa/src/App.vue +++ b/spa/src/App.vue @@ -2,6 +2,7 @@
+
@@ -10,6 +11,7 @@ import {onMounted, ref, watch} from "vue"; import {useWebAppViewport, useBackButton} from 'vue-tg'; import {useMiniApp, FullscreenViewport} from 'vue-tg'; import {useRoute, useRouter} from "vue-router"; +import CartButton from "@/components/CartButton.vue"; const tg = useMiniApp(); const platform = ref(); diff --git a/spa/src/components/CartButton.vue b/spa/src/components/CartButton.vue new file mode 100644 index 0000000..e3bffae --- /dev/null +++ b/spa/src/components/CartButton.vue @@ -0,0 +1,40 @@ + + + + + + + \ No newline at end of file diff --git a/spa/src/components/Price.vue b/spa/src/components/Price.vue new file mode 100644 index 0000000..d58bc0b --- /dev/null +++ b/spa/src/components/Price.vue @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/spa/src/components/ProductOptions/Cart/OptionCheckbox.vue b/spa/src/components/ProductOptions/Cart/OptionCheckbox.vue new file mode 100644 index 0000000..3dd01f0 --- /dev/null +++ b/spa/src/components/ProductOptions/Cart/OptionCheckbox.vue @@ -0,0 +1,18 @@ + + + diff --git a/spa/src/components/ProductOptions/Cart/OptionRadio.vue b/spa/src/components/ProductOptions/Cart/OptionRadio.vue new file mode 100644 index 0000000..3dd01f0 --- /dev/null +++ b/spa/src/components/ProductOptions/Cart/OptionRadio.vue @@ -0,0 +1,18 @@ + + + diff --git a/spa/src/components/ProductOptions/Cart/OptionText.vue b/spa/src/components/ProductOptions/Cart/OptionText.vue new file mode 100644 index 0000000..3dd01f0 --- /dev/null +++ b/spa/src/components/ProductOptions/Cart/OptionText.vue @@ -0,0 +1,18 @@ + + + diff --git a/spa/src/components/ProductOptions/ProductOptions.vue b/spa/src/components/ProductOptions/ProductOptions.vue index 08b257d..21fea06 100644 --- a/spa/src/components/ProductOptions/ProductOptions.vue +++ b/spa/src/components/ProductOptions/ProductOptions.vue @@ -1,10 +1,13 @@ @@ -14,6 +17,15 @@ import OptionCheckbox from "./Types/OptionCheckbox.vue"; import OptionText from "./Types/OptionText.vue"; import OptionTextarea from "./Types/OptionTextarea.vue"; import OptionSelect from "./Types/OptionSelect.vue"; +import {SUPPORTED_OPTION_TYPES} from "@/constants/options.js"; + +const componentMap = { + radio: OptionRadio, + checkbox: OptionCheckbox, + text: OptionText, + textarea: OptionTextarea, + select: OptionSelect, +}; const options = defineModel(); diff --git a/spa/src/components/ProductOptions/Types/OptionSelect.vue b/spa/src/components/ProductOptions/Types/OptionSelect.vue index e9eb209..0fa151c 100644 --- a/spa/src/components/ProductOptions/Types/OptionSelect.vue +++ b/spa/src/components/ProductOptions/Types/OptionSelect.vue @@ -5,7 +5,7 @@ class="select" @change="onChange" > - +