From 1c139eed971d40ec6d853fb0b5742b482a7c47f1 Mon Sep 17 00:00:00 2001 From: herirudini Date: Thu, 26 Feb 2026 15:35:37 +0700 Subject: [PATCH] feat: setup services, prepare API integration --- .env.development | 2 + .eslintrc.cjs | 4 +- env.example | 4 + package-lock.json | 214 +++++++++++++++++++--- package.json | 7 +- src/App.vue | 12 +- src/components/product/ProductCard.vue | 11 +- src/components/product/SerialItemCard.vue | 6 +- src/composables/useProducts.ts | 77 ++++++++ src/main.ts | 4 + src/services/api.ts | 45 +++++ src/services/product.service.ts | 10 + src/stores/loading.store.ts | 15 ++ src/stores/product.store.ts | 0 src/types/product.ts | 24 +++ src/views/product/ProductListPage.vue | 48 +++-- src/views/product/ProductSerialPage.vue | 56 ++---- 17 files changed, 453 insertions(+), 86 deletions(-) create mode 100644 .env.development create mode 100644 env.example create mode 100644 src/services/api.ts create mode 100644 src/stores/loading.store.ts delete mode 100644 src/stores/product.store.ts diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..4a24c23 --- /dev/null +++ b/.env.development @@ -0,0 +1,2 @@ +VITE_API_URL=http://fake.no/api +VITE_NODE_ENV=DEVELOPMENT \ No newline at end of file diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 8f71501..8345e23 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -12,8 +12,8 @@ module.exports = { ecmaVersion: 2020 }, rules: { - 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', - 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', + 'no-console': process.env.VITE_NODE_ENV === 'PRODUCTION' ? 'warn' : 'off', + 'no-debugger': process.env.VITE_NODE_ENV === 'PRODUCTION' ? 'warn' : 'off', 'vue/no-deprecated-slot-attribute': 'off', '@typescript-eslint/no-explicit-any': 'off', } diff --git a/env.example b/env.example new file mode 100644 index 0000000..890aac3 --- /dev/null +++ b/env.example @@ -0,0 +1,4 @@ +## mandatory to use VITE_ + +VITE_API_URL=fake.no/api +VITE_NODE_ENV=DEVELOPMENT \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a9f5f3f..1975f49 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,12 +17,16 @@ "@capacitor/status-bar": "8.0.1", "@ionic/vue": "^8.0.0", "@ionic/vue-router": "^8.0.0", + "axios": "^1.13.5", "ionicons": "^7.0.0", + "lodash-es": "^4.17.23", + "pinia": "^3.0.4", "vue": "^3.3.0", "vue-router": "^4.2.0" }, "devDependencies": { "@capacitor/cli": "8.1.0", + "@types/lodash-es": "^4.17.12", "@vitejs/plugin-legacy": "^5.0.0", "@vitejs/plugin-vue": "^4.0.0", "@vue/eslint-config-typescript": "^12.0.0", @@ -3194,6 +3198,23 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/lodash": { + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz", + "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/node": { "version": "25.3.0", "dev": true, @@ -3632,6 +3653,30 @@ "version": "6.6.4", "license": "MIT" }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", + "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.9", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", + "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, "node_modules/@vue/eslint-config-typescript": { "version": "12.0.0", "dev": true, @@ -3970,7 +4015,6 @@ }, "node_modules/asynckit": { "version": "0.4.0", - "dev": true, "license": "MIT" }, "node_modules/at-least-node": { @@ -4029,6 +4073,23 @@ "dev": true, "license": "MIT" }, + "node_modules/axios": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", + "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.15", "dev": true, @@ -4135,6 +4196,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/blob-util": { "version": "2.0.2", "dev": true, @@ -4284,7 +4354,6 @@ }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -4551,7 +4620,6 @@ }, "node_modules/combined-stream": { "version": "1.0.8", - "dev": true, "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -4605,6 +4673,21 @@ "dev": true, "license": "MIT" }, + "node_modules/copy-anything": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", + "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", + "license": "MIT", + "dependencies": { + "is-what": "^5.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, "node_modules/core-js": { "version": "3.48.0", "dev": true, @@ -4831,7 +4914,6 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -4899,7 +4981,6 @@ }, "node_modules/dunder-proto": { "version": "1.0.1", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -5026,7 +5107,6 @@ }, "node_modules/es-define-property": { "version": "1.0.1", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -5034,7 +5114,6 @@ }, "node_modules/es-errors": { "version": "1.3.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -5042,7 +5121,6 @@ }, "node_modules/es-object-atoms": { "version": "1.1.1", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -5053,7 +5131,6 @@ }, "node_modules/es-set-tostringtag": { "version": "2.1.0", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -5559,6 +5636,26 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/foreground-child": { "version": "3.3.1", "dev": true, @@ -5595,7 +5692,6 @@ }, "node_modules/form-data": { "version": "4.0.5", - "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -5655,7 +5751,6 @@ }, "node_modules/function-bind": { "version": "1.1.2", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5679,7 +5774,6 @@ }, "node_modules/get-intrinsic": { "version": "1.3.0", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -5702,7 +5796,6 @@ }, "node_modules/get-proto": { "version": "1.0.1", - "dev": true, "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -5854,7 +5947,6 @@ }, "node_modules/gopd": { "version": "1.2.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -5883,7 +5975,6 @@ }, "node_modules/has-symbols": { "version": "1.1.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -5894,7 +5985,6 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", - "dev": true, "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -5908,7 +5998,6 @@ }, "node_modules/hasown": { "version": "2.0.2", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -5925,6 +6014,12 @@ "he": "bin/he" } }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, "node_modules/html-encoding-sniffer": { "version": "3.0.0", "dev": true, @@ -6214,6 +6309,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-what": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, "node_modules/is-wsl": { "version": "2.2.0", "dev": true, @@ -6550,6 +6657,12 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash-es": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", + "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", + "license": "MIT" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "dev": true, @@ -6635,7 +6748,6 @@ }, "node_modules/math-intrinsics": { "version": "1.1.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -6679,7 +6791,6 @@ }, "node_modules/mime-db": { "version": "1.52.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -6687,7 +6798,6 @@ }, "node_modules/mime-types": { "version": "2.1.35", - "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -6745,6 +6855,12 @@ "node": ">= 18" } }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, "node_modules/mlly": { "version": "1.8.0", "dev": true, @@ -7129,6 +7245,12 @@ "dev": true, "license": "MIT" }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "license": "MIT" + }, "node_modules/performance-now": { "version": "2.1.0", "dev": true, @@ -7157,6 +7279,36 @@ "node": ">=0.10.0" } }, + "node_modules/pinia": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz", + "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^7.7.7" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.5.0", + "vue": "^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/pinia/node_modules/@vue/devtools-api": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz", + "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.9" + } + }, "node_modules/pirates": { "version": "4.0.7", "dev": true, @@ -7642,7 +7794,6 @@ }, "node_modules/rfdc": { "version": "1.4.1", - "dev": true, "license": "MIT" }, "node_modules/rimraf": { @@ -8169,6 +8320,15 @@ "source-map": "^0.6.0" } }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/split2": { "version": "4.2.0", "dev": true, @@ -8328,6 +8488,18 @@ "node": ">= 6" } }, + "node_modules/superjson": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", + "license": "MIT", + "dependencies": { + "copy-anything": "^4" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/supports-color": { "version": "8.1.1", "dev": true, diff --git a/package.json b/package.json index 284f73e..ae7519d 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "test:unit": "vitest", "lint": "eslint .", "ionic:build": "npm run build", - "ionic:serve": "npm run dev -- --open" + "ionic:serve": "npm run dev -- --open", + "start": "npm run dev --mode development" }, "dependencies": { "@capacitor/android": "8.1.0", @@ -23,12 +24,16 @@ "@capacitor/status-bar": "8.0.1", "@ionic/vue": "^8.0.0", "@ionic/vue-router": "^8.0.0", + "axios": "^1.13.5", "ionicons": "^7.0.0", + "lodash-es": "^4.17.23", + "pinia": "^3.0.4", "vue": "^3.3.0", "vue-router": "^4.2.0" }, "devDependencies": { "@capacitor/cli": "8.1.0", + "@types/lodash-es": "^4.17.12", "@vitejs/plugin-legacy": "^5.0.0", "@vitejs/plugin-vue": "^4.0.0", "@vue/eslint-config-typescript": "^12.0.0", diff --git a/src/App.vue b/src/App.vue index 30dd406..70fcf90 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,9 +1,19 @@ diff --git a/src/components/product/ProductCard.vue b/src/components/product/ProductCard.vue index fb2ef00..7dc32ef 100644 --- a/src/components/product/ProductCard.vue +++ b/src/components/product/ProductCard.vue @@ -19,13 +19,14 @@ - \ No newline at end of file diff --git a/src/components/product/SerialItemCard.vue b/src/components/product/SerialItemCard.vue index 4f35c3a..444c960 100644 --- a/src/components/product/SerialItemCard.vue +++ b/src/components/product/SerialItemCard.vue @@ -43,8 +43,8 @@ -
-
+
+
Icon tools
@@ -55,7 +55,7 @@
-
+
Icon calendar
diff --git a/src/composables/useProducts.ts b/src/composables/useProducts.ts index e69de29..5c3b114 100644 --- a/src/composables/useProducts.ts +++ b/src/composables/useProducts.ts @@ -0,0 +1,77 @@ +import { ref } from 'vue' +import { getProductById, getProducts } from '@/services/product.service' +import { IPagination } from '@/types/product'; + +const dummy_products = [ + { id: '1', name: 'APM CLOPPY', stock: 2 }, + { id: '2', name: 'SELKA POINT', stock: 0 }, + { id: '3', name: 'BARRIER GATE', stock: 0 }, + { id: '4', name: 'SMART PARKING', stock: 2 }, + { id: '5', name: 'PHOTO BOX', stock: 0 }, + { id: '6', name: 'MESIN ABSENSI', stock: 2 } +] + +const dummy_serials = [ + { + id: 'ididi', + serial: 'APM001 INT', + production: '04-02-2026', + status: 'used', + location: 'Dusun Bambu', + installation: '03-04-2026', + history: '2x Maintenance' + }, + { + id: 'ididi', + serial: 'APM002 INT', + production: '12-03-2026', + status: 'ready', + location: 'Standby WS', + installation: '', + history: '' + }, + { + id: 'ididi', + serial: 'APM003 INT', + production: '04-02-2026', + status: 'used', + location: 'Ancol', + installation: '03-04-2026', + history: '' + }, + { + id: 'ididi', + serial: 'APM004 INT', + production: '12-03-2026', + status: 'maintenance', + location: 'Park Zoo', + installation: '03-04-2026', + history: '1x Maintenance' + }, +] + +export function useProducts() { + const products = ref(dummy_products); + const serials = ref(dummy_serials); + const error = ref(null); + + const fetchProducts = async (params?: IPagination) => { + try { + const { data } = await getProducts(params) + products.value = data + } catch (err: any) { + error.value = err + } + } + + const fetchProductDetail = async (id_product: string, params?: IPagination) => { + try { + const { data } = await getProductById(id_product, params) + serials.value = data + } catch (err: any) { + error.value = err + } + } + + return { products, fetchProducts, serials, fetchProductDetail, error } +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 301189d..06c9a74 100644 --- a/src/main.ts +++ b/src/main.ts @@ -35,8 +35,12 @@ import '@ionic/vue/css/display.css'; import './theme/variables.css'; import './assets/styles/tailwind.scss'; +import { createPinia } from 'pinia'; + +export const pinia = createPinia(); const app = createApp(App) + .use(pinia) .use(IonicVue) .use(router); diff --git a/src/services/api.ts b/src/services/api.ts new file mode 100644 index 0000000..0399b96 --- /dev/null +++ b/src/services/api.ts @@ -0,0 +1,45 @@ +import axios from 'axios' +import { useLoadingStore } from '@/stores/loading.store' +import router from '@/router' + +const api = axios.create({ + baseURL: import.meta.env.VITE_API_URL, + timeout: 10000, +}) + +// Request Interceptor +api.interceptors.request.use((config) => { + console.log('BASE URL:', import.meta.env.VITE_API_URL) + const loader = config.params['loader'] ? JSON.parse(config.params['loader']) : true; + if (loader) { + const loadingStore = useLoadingStore() + loadingStore.start() + } + + // Attach token when available + const token = localStorage.getItem('access_token') + if (token) { + config.headers.Authorization = `Bearer ${token}` + } + + return config +}) + +// Response Interceptor +api.interceptors.response.use( + (response) => { + const loadingStore = useLoadingStore() + loadingStore.stop() + return response + }, + (error) => { + if (error.response?.status === 401) { + router.push('/login') + } + const loadingStore = useLoadingStore() + loadingStore.stop() + return Promise.reject(error) + } +) + +export default api \ No newline at end of file diff --git a/src/services/product.service.ts b/src/services/product.service.ts index e69de29..4046bfb 100644 --- a/src/services/product.service.ts +++ b/src/services/product.service.ts @@ -0,0 +1,10 @@ +import { IPagination } from '@/types/product' +import api from './api' + +export const getProducts = (params?: IPagination) => { + return api.get('/products', { params }) +} + +export const getProductById = (id: string, params?: IPagination) => { + return api.get(`/products/${id}`, { params }) +} \ No newline at end of file diff --git a/src/stores/loading.store.ts b/src/stores/loading.store.ts new file mode 100644 index 0000000..582af15 --- /dev/null +++ b/src/stores/loading.store.ts @@ -0,0 +1,15 @@ +import { defineStore } from 'pinia' + +export const useLoadingStore = defineStore('loading', { + state: () => ({ + isLoading: false, + }), + actions: { + start() { + this.isLoading = true + }, + stop() { + this.isLoading = false + }, + }, +}) \ No newline at end of file diff --git a/src/stores/product.store.ts b/src/stores/product.store.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/types/product.ts b/src/types/product.ts index e69de29..5dd9d8e 100644 --- a/src/types/product.ts +++ b/src/types/product.ts @@ -0,0 +1,24 @@ +export interface IPagination { + page?: number + size?: number + total?: number + sort_by?: string + sort_dir?: 'asc' | 'desc' + search?: string +} + +export interface IProduct { + id: string, + name: string, + stock: number +} + +export interface IProdSerie { + id: string, + serial: string, + production: string, + status: string, + location: string, + installation: string, + history: string +} \ No newline at end of file diff --git a/src/views/product/ProductListPage.vue b/src/views/product/ProductListPage.vue index 0f11c03..65c3b34 100644 --- a/src/views/product/ProductListPage.vue +++ b/src/views/product/ProductListPage.vue @@ -14,14 +14,15 @@

-
-
- +
+
@@ -44,16 +45,39 @@ \ No newline at end of file diff --git a/src/views/product/ProductSerialPage.vue b/src/views/product/ProductSerialPage.vue index 67245a1..e7b9908 100644 --- a/src/views/product/ProductSerialPage.vue +++ b/src/views/product/ProductSerialPage.vue @@ -86,10 +86,23 @@ import { OverlayEventDetail } from '@ionic/core/components'; import AppFooter from '@/components/common/AppFooter.vue' import SerialItemCard from '@/components/product/SerialItemCard.vue' import { funnelOutline, caretBackCircleSharp } from 'ionicons/icons' -import { useRouter } from 'vue-router'; -import { ref } from 'vue'; +import { useRoute, useRouter } from 'vue-router'; +import { onMounted, ref } from 'vue'; +import { useProducts } from '@/composables/useProducts'; +const route = useRoute(); const router = useRouter(); + +const productId = route.params.id; + +const { serials, fetchProductDetail } = useProducts(); +const serialItems = serials; + +onMounted(() => { + fetchProductDetail(productId as string); + console.log({ serials }) +}); + const modal = ref(); const selectedStatus = ref('') @@ -104,43 +117,4 @@ const onWillDismiss = (event: CustomEvent) => { const { role } = event.detail; console.log({ role }) }; - -const serialItems = [ - { - id: 'ididi', - serial: 'APM001 INT', - production: '04-02-2026', - status: 'used', - location: 'Dusun Bambu', - installation: '03-04-2026', - history: '2x Maintenance' - }, - { - id: 'ididi', - serial: 'APM002 INT', - production: '12-03-2026', - status: 'ready', - location: 'Standby WS', - installation: '09-02-2026', - history: '1x Maintenance' - }, - { - id: 'ididi', - serial: 'APM003 INT', - production: '04-02-2026', - status: 'used', - location: 'Ancol', - installation: '03-04-2026', - history: '2x Maintenance' - }, - { - id: 'ididi', - serial: 'APM004 INT', - production: '12-03-2026', - status: 'maintenance', - location: 'Park Zoo', - installation: '03-04-2026', - history: '1x Maintenance' - }, -] \ No newline at end of file