From 6a8ea048ea52e6bd3c146b4ec311e9633fce269a Mon Sep 17 00:00:00 2001 From: Nikita Kiselev Date: Mon, 14 Jul 2025 22:34:51 +0300 Subject: [PATCH] feat: add Categories --- .../src/Handlers/CategoriesHandler.php | 70 ++++++++++++++++ .../src/Handlers/ProductsHandler.php | 51 +++++++++--- .../upload/oc_telegram_shop/src/routes.php | 3 + spa/src/components/BottomDrawer.vue | 1 - spa/src/components/CategoriesInline.vue | 28 +++++++ spa/src/components/NoProducts.vue | 19 +++++ spa/src/router.js | 4 + spa/src/utils/ftch.js | 9 ++ spa/src/views/CategoriesList.vue | 30 +++++++ spa/src/views/Hero.vue | 48 +++++++++++ spa/src/views/Home.vue | 82 +------------------ spa/src/views/Product.vue | 3 +- spa/src/views/ProductsList.vue | 64 +++++++++++++++ 13 files changed, 320 insertions(+), 92 deletions(-) create mode 100755 module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/CategoriesHandler.php create mode 100644 spa/src/components/CategoriesInline.vue create mode 100644 spa/src/components/NoProducts.vue create mode 100644 spa/src/utils/ftch.js create mode 100644 spa/src/views/CategoriesList.vue create mode 100644 spa/src/views/Hero.vue create mode 100644 spa/src/views/ProductsList.vue diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/CategoriesHandler.php b/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/CategoriesHandler.php new file mode 100755 index 0000000..2b80edd --- /dev/null +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/CategoriesHandler.php @@ -0,0 +1,70 @@ +queryBuilder = $queryBuilder; + } + + public function index(Request $request): JsonResponse + { + $languageId = 1; + $perPage = $request->get('perPage', 10); + + $imageWidth = 150; + $imageHeight = 150; + + $categories = $this->queryBuilder->newQuery() + ->select([ + 'categories.category_id' => 'id', + 'categories.image' => 'image', + 'descriptions.name' => 'name', + 'descriptions.description' => 'description', + ]) + ->from(db_table('category'), 'categories') + ->join( + db_table('category_description') . ' AS descriptions', + function (JoinClause $join) use ($languageId) { + $join->on('categories.category_id', '=', 'descriptions.category_id') + ->where('descriptions.language_id', '=', $languageId); + } + ) + ->where('categories.parent_id', '=', 0) + ->where('categories.status', '=', 1) + ->orderBy('sort_order') + ->limit($perPage) + ->get(); + + /** @var Closure $resize */ + $resize = Application::getInstance()->get('image_resize'); + + return new JsonResponse([ + 'data' => array_map(static function ($category) use ($resize, $imageWidth, $imageHeight) { + if ($category['image']) { + $image = $resize($category['image'], $imageWidth, $imageHeight); + } else { + $image = $resize('no_image.png', $imageWidth, $imageHeight); + } + + return [ + 'id' => (int)$category['id'], + 'image' => $image, + 'name' => $category['name'], + 'description' => $category['description'], + ]; + }, $categories), + ]); + } +} diff --git a/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/ProductsHandler.php b/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/ProductsHandler.php index ca6bbc0..993df51 100755 --- a/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/ProductsHandler.php +++ b/module/oc_telegram_shop/upload/oc_telegram_shop/src/Handlers/ProductsHandler.php @@ -33,10 +33,21 @@ class ProductsHandler $languageId = 1; $page = $request->get('page', 1); $perPage = $request->get('perPage', 10); + $categoryId = (int)$request->get('categoryId', 0); + $categoryName = ''; $imageWidth = 200; $imageHeight = 200; + if ($categoryId) { + $categoryName = $this->queryBuilder->newQuery() + ->select(['name']) + ->from(db_table('category_description'), 'category') + ->where('language_id', '=', $languageId) + ->where('category_id', '=', $categoryId) + ->value('name'); + } + $products = $this->queryBuilder->newQuery() ->select([ 'products.product_id' => 'product_id', @@ -54,20 +65,34 @@ class ProductsHandler ->where('product_description.language_id', '=', $languageId); } ) + ->when($categoryId !== 0, function (Builder $query) use ($categoryId) { + $query->join( + db_table('product_to_category') . ' AS product_to_category', + function (JoinClause $join) use ($categoryId) { + $join->on('product_to_category.product_id', '=', 'products.product_id') + ->where('product_to_category.category_id', '=', $categoryId); + } + ); + }) ->forPage($page, $perPage) ->orderBy('date_added', 'DESC') ->get(); $productIds = Arr::pluck($products, 'product_id'); - $productsImages = $this->queryBuilder->newQuery() - ->select([ - 'products_images.product_id' => 'product_id', - 'products_images.image' => 'image', - ]) - ->from(db_table('product_image'), 'products_images') - ->orderBy('products_images.sort_order', 'ASC') - ->whereIn('product_id', $productIds) - ->get(); + $productsImages = []; + + if ($productIds) { + $productsImages = $this->queryBuilder->newQuery() + ->select([ + 'products_images.product_id' => 'product_id', + 'products_images.image' => 'image', + ]) + ->from(db_table('product_image'), 'products_images') + ->orderBy('products_images.sort_order', 'ASC') + ->whereIn('product_id', $productIds) + ->get(); + } + /** @var Closure $resize */ $resize = Application::getInstance()->get('image_resize'); @@ -103,7 +128,7 @@ class ProductsHandler $this->settings->get('oc_currency'), ); - if (! empty($productsImagesMap[$product['product_id']])) { + if (!empty($productsImagesMap[$product['product_id']])) { $allImages = array_merge($allImages, $productsImagesMap[$product['product_id']]); } @@ -115,12 +140,16 @@ class ProductsHandler 'images' => $allImages, ]; }, $products), + + 'meta' => [ + 'currentCategoryName' => $categoryName, + ] ]); } public function show(Request $request): JsonResponse { - $productId = (int) $request->get('id'); + $productId = (int)$request->get('id'); $languageId = 1; $imageWidth = 500; $imageHeight = 500; 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 ab14cfa..6c334e1 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,5 +1,6 @@ [ProductsHandler::class, 'handle'], 'product_show' => [ProductsHandler::class, 'show'], 'order_create' => [OrderCreateHandler::class, 'handle'], + + 'categoriesList' => [CategoriesHandler::class, 'index'], ]; diff --git a/spa/src/components/BottomDrawer.vue b/spa/src/components/BottomDrawer.vue index 2d545ed..b8a3952 100644 --- a/spa/src/components/BottomDrawer.vue +++ b/spa/src/components/BottomDrawer.vue @@ -18,7 +18,6 @@ diff --git a/spa/src/components/NoProducts.vue b/spa/src/components/NoProducts.vue new file mode 100644 index 0000000..408c73b --- /dev/null +++ b/spa/src/components/NoProducts.vue @@ -0,0 +1,19 @@ + + + diff --git a/spa/src/router.js b/spa/src/router.js index c42f60b..ac8d0cf 100644 --- a/spa/src/router.js +++ b/spa/src/router.js @@ -1,10 +1,14 @@ import {createRouter, createWebHistory} from 'vue-router'; import Home from './views/Home.vue'; import Product from './views/Product.vue'; +import CategoriesList from "./views/CategoriesList.vue"; +import ProductsList from "./views/ProductsList.vue"; const routes = [ {path: '/', component: Home}, {path: '/product/:id', component: Product}, + {path: '/categories', component: CategoriesList}, + {path: '/category/:id', component: ProductsList}, ]; export const router = createRouter({ diff --git a/spa/src/utils/ftch.js b/spa/src/utils/ftch.js new file mode 100644 index 0000000..e7f78ee --- /dev/null +++ b/spa/src/utils/ftch.js @@ -0,0 +1,9 @@ +import {$fetch} from "ofetch"; + +const BASE_URL = '/'; + +export default async function (action, query) { + return await $fetch(`${BASE_URL}index.php?route=extension/tgshop/handle&api_action=${action}`, { + query: query, + }); +}; diff --git a/spa/src/views/CategoriesList.vue b/spa/src/views/CategoriesList.vue new file mode 100644 index 0000000..862c941 --- /dev/null +++ b/spa/src/views/CategoriesList.vue @@ -0,0 +1,30 @@ + + + diff --git a/spa/src/views/Hero.vue b/spa/src/views/Hero.vue new file mode 100644 index 0000000..3537ef2 --- /dev/null +++ b/spa/src/views/Hero.vue @@ -0,0 +1,48 @@ + + + + + \ No newline at end of file diff --git a/spa/src/views/Home.vue b/spa/src/views/Home.vue index 4c605b5..92cb22b 100644 --- a/spa/src/views/Home.vue +++ b/spa/src/views/Home.vue @@ -1,95 +1,21 @@ \ No newline at end of file diff --git a/spa/src/views/ProductsList.vue b/spa/src/views/ProductsList.vue new file mode 100644 index 0000000..1ef9684 --- /dev/null +++ b/spa/src/views/ProductsList.vue @@ -0,0 +1,64 @@ + + +