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 3402a53..d32efe6 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 @@ -13,6 +13,7 @@ use Openguru\OpenCartFramework\ImageTool\ImageToolInterface; use Openguru\OpenCartFramework\QueryBuilder\Builder; use Openguru\OpenCartFramework\QueryBuilder\JoinClause; use Openguru\OpenCartFramework\Support\Arr; +use Openguru\OpenCartFramework\Support\PaginationHelper; class ProductsHandler { @@ -43,7 +44,7 @@ class ProductsHandler { $languageId = 1; $page = $request->get('page', 1); - $perPage = $request->get('perPage', 10); + $perPage = 10; $categoryId = (int) $request->get('categoryId', 0); $categoryName = ''; @@ -59,7 +60,7 @@ class ProductsHandler ->value('name'); } - $products = $this->queryBuilder->newQuery() + $productsQuery = $this->queryBuilder->newQuery() ->select([ 'products.product_id' => 'product_id', 'products.quantity' => 'product_quantity', @@ -84,7 +85,13 @@ class ProductsHandler ->where('product_to_category.category_id', '=', $categoryId); } ); - }) + }); + + $total = $productsQuery->count(); + $lastPage = PaginationHelper::calculateLastPage($total, $perPage); + $hasMore = $page + 1 <= $lastPage; + + $products = $productsQuery ->forPage($page, $perPage) ->orderBy('date_added', 'DESC') ->get(); @@ -152,6 +159,7 @@ class ProductsHandler 'meta' => [ 'currentCategoryName' => $categoryName, + 'hasMore' => $hasMore, ] ]); } diff --git a/spa/package-lock.json b/spa/package-lock.json index 2eba130..c27aea3 100644 --- a/spa/package-lock.json +++ b/spa/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@heroicons/vue": "^2.2.0", "@tailwindcss/vite": "^4.1.11", + "@vueuse/core": "^13.5.0", "crypto-js": "^4.2.0", "ofetch": "^1.4.1", "pinia": "^3.0.3", @@ -1093,6 +1094,12 @@ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "license": "MIT" + }, "node_modules/@vitejs/plugin-vue": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.0.tgz", @@ -1240,6 +1247,44 @@ "integrity": "sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==", "license": "MIT" }, + "node_modules/@vueuse/core": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-13.5.0.tgz", + "integrity": "sha512-wV7z0eUpifKmvmN78UBZX8T7lMW53Nrk6JP5+6hbzrB9+cJ3jr//hUlhl9TZO/03bUkMK6gGkQpqOPWoabr72g==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "13.5.0", + "@vueuse/shared": "13.5.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/@vueuse/metadata": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-13.5.0.tgz", + "integrity": "sha512-euhItU3b0SqXxSy8u1XHxUCdQ8M++bsRs+TYhOLDU/OykS7KvJnyIFfep0XM5WjIFry9uAPlVSjmVHiqeshmkw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-13.5.0.tgz", + "integrity": "sha512-K7GrQIxJ/ANtucxIXbQlUHdB0TPA8c+q5i+zbrjxuhJCnJ9GtBg75sBSnvmLSxHKPg2Yo8w62PWksl9kwH0Q8g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, "node_modules/autoprefixer": { "version": "10.4.21", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", diff --git a/spa/package.json b/spa/package.json index 165abcb..9ad533c 100644 --- a/spa/package.json +++ b/spa/package.json @@ -11,6 +11,7 @@ "dependencies": { "@heroicons/vue": "^2.2.0", "@tailwindcss/vite": "^4.1.11", + "@vueuse/core": "^13.5.0", "crypto-js": "^4.2.0", "ofetch": "^1.4.1", "pinia": "^3.0.3", diff --git a/spa/src/components/ProductsList.vue b/spa/src/components/ProductsList.vue index 1fa1a6a..ec9ffbe 100644 --- a/spa/src/components/ProductsList.vue +++ b/spa/src/components/ProductsList.vue @@ -1,7 +1,8 @@ diff --git a/spa/src/main.js b/spa/src/main.js index ec4b179..57f127f 100644 --- a/spa/src/main.js +++ b/spa/src/main.js @@ -5,14 +5,6 @@ import { VueTelegramPlugin } from 'vue-tg'; import { router } from './router'; import { createPinia } from 'pinia'; -const config = { - night_auto: true, - theme: { - light: 'light', - dark: 'dark', - } -}; - const pinia = createPinia(); const app = createApp(App); app @@ -22,21 +14,19 @@ app app.mount('#app'); -const productsStore = useProductsStore(); -productsStore.fetchHomeProducts(); +const settings = useSettingsStore(); const categoriesStore = useCategoriesStore(); categoriesStore.fetchTopCategories(); -import {useProductsStore} from "@/stores/ProductsStore.js"; import {useCategoriesStore} from "@/stores/CategoriesStore.js"; +import {useSettingsStore} from "@/stores/SettingsStore.js"; -if (config.night_auto) { - document.documentElement.setAttribute('data-theme', config.theme[this.colorScheme]); +if (settings.night_auto) { window.Telegram.WebApp.onEvent('themeChanged', function () { - document.documentElement.setAttribute('data-theme', config.theme[this.colorScheme]); + document.documentElement.setAttribute('data-theme', settings.theme[this.colorScheme]); }); } else { - document.documentElement.setAttribute('data-theme', config.theme.light); + document.documentElement.setAttribute('data-theme', settings.theme.light); } window.Telegram.WebApp.ready(); diff --git a/spa/src/stores/ProductsStore.js b/spa/src/stores/ProductsStore.js index f4d6f61..8afe8b3 100644 --- a/spa/src/stores/ProductsStore.js +++ b/spa/src/stores/ProductsStore.js @@ -3,34 +3,24 @@ import ftch from "../utils/ftch.js"; export const useProductsStore = defineStore('products', { state: () => ({ - homeProducts: { - data: [], - meta: {}, - }, products: { data: [], meta: {}, }, + page: 1, isLoading: false, + hasMore: true, + savedCategoryId: null, + savedScrollY: 0, }), actions: { - async fetchHomeProducts() { + async fetchProducts(categoryId = null, page = 1) { try { this.isLoading = true; - this.homeProducts = await ftch('products'); - } catch (error) { - console.error(error); - } finally { - this.isLoading = false; - } - }, - - async fetchProducts(categoryId = null) { - try { - this.isLoading = true; - this.products = await ftch('products', { + return await ftch('products', { categoryId: categoryId, + page: page, }); } catch (error) { console.error(error); @@ -38,5 +28,14 @@ export const useProductsStore = defineStore('products', { this.isLoading = false; } }, + + reset() { + this.page = 1; + this.hasMore = true; + this.products = { + data: [], + meta: {}, + }; + } }, }); diff --git a/spa/src/stores/SettingsStore.js b/spa/src/stores/SettingsStore.js new file mode 100644 index 0000000..36c2f20 --- /dev/null +++ b/spa/src/stores/SettingsStore.js @@ -0,0 +1,12 @@ +import {defineStore} from "pinia"; + +export const useSettingsStore = defineStore('settings', { + state: () => ({ + night_auto: true, + theme: { + light: 'light', + dark: 'dark', + }, + noMoreProductsMessage: '🔚 Ну всё, разгрузили всё, что было. Даже кладовщика разбудить не удалось.', + }), +}); diff --git a/spa/src/views/Home.vue b/spa/src/views/Home.vue index cf60e21..1b2c9e0 100644 --- a/spa/src/views/Home.vue +++ b/spa/src/views/Home.vue @@ -1,24 +1,11 @@ diff --git a/spa/src/views/Products.vue b/spa/src/views/Products.vue index 0406096..b9b16f0 100644 --- a/spa/src/views/Products.vue +++ b/spa/src/views/Products.vue @@ -1,22 +1,9 @@