@altazion/commerce-sdk-vue 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,388 @@
1
+ import { createPinia, defineStore } from "pinia";
2
+ import { inject, ref, computed, defineComponent, openBlock, createElementBlock, createElementVNode, createCommentVNode, toDisplayString, unref, onMounted, Fragment, renderList, renderSlot, createTextVNode } from "vue";
3
+ const COMMERCE_CLIENT_KEY = Symbol("altazion:commerce-client");
4
+ const AltazionCommercePlugin = {
5
+ install(app, options) {
6
+ const { client, pinia } = options;
7
+ const piniaInstance = pinia ?? createPinia();
8
+ app.use(piniaInstance);
9
+ app.provide(COMMERCE_CLIENT_KEY, client);
10
+ }
11
+ };
12
+ function useCommerceClient() {
13
+ const client = inject(COMMERCE_CLIENT_KEY);
14
+ if (!client) {
15
+ throw new Error(
16
+ "[AltazionCommerce] useCommerceClient() : aucun client trouvé. Assurez-vous d'avoir installé AltazionCommercePlugin via app.use()."
17
+ );
18
+ }
19
+ return client;
20
+ }
21
+ const useSessionStore = defineStore("altazion:session", () => {
22
+ const client = useCommerceClient();
23
+ const session = ref(null);
24
+ const loading = ref(false);
25
+ const error = ref(null);
26
+ const isOnline = ref(client.connectivity.isOnline);
27
+ client.connectivity.subscribe((status) => {
28
+ isOnline.value = status === "online";
29
+ });
30
+ const mode = computed(() => client.context.mode);
31
+ const isKiosk = computed(() => mode.value === "kiosk");
32
+ const isReady = computed(() => session.value !== null || mode.value === "kiosk");
33
+ async function load() {
34
+ loading.value = true;
35
+ error.value = null;
36
+ try {
37
+ session.value = await client.session.getSession();
38
+ } catch (err) {
39
+ error.value = err instanceof Error ? err.message : String(err);
40
+ } finally {
41
+ loading.value = false;
42
+ }
43
+ }
44
+ async function associateStore(storeGuid) {
45
+ loading.value = true;
46
+ error.value = null;
47
+ try {
48
+ session.value = await client.session.associateStore(storeGuid);
49
+ } catch (err) {
50
+ error.value = err instanceof Error ? err.message : String(err);
51
+ } finally {
52
+ loading.value = false;
53
+ }
54
+ }
55
+ return { session, loading, error, isOnline, mode, isKiosk, isReady, load, associateStore };
56
+ });
57
+ const useCartStore = defineStore("altazion:cart", () => {
58
+ const client = useCommerceClient();
59
+ const cart = ref(null);
60
+ const loading = ref(false);
61
+ const error = ref(null);
62
+ const hasPendingOperations = ref(false);
63
+ client.onQueueEvent(async () => {
64
+ hasPendingOperations.value = await client.pendingOperationsCount > 0;
65
+ });
66
+ const isOffline = computed(() => client.isOffline);
67
+ const itemCount = computed(() => {
68
+ var _a;
69
+ return ((_a = cart.value) == null ? void 0 : _a.totalQuantity) ?? 0;
70
+ });
71
+ const total = computed(() => {
72
+ var _a;
73
+ return ((_a = cart.value) == null ? void 0 : _a.totalAmountWithTax) ?? 0;
74
+ });
75
+ const isEmpty = computed(() => itemCount.value === 0);
76
+ async function load() {
77
+ loading.value = true;
78
+ error.value = null;
79
+ try {
80
+ cart.value = await client.cart.getCart();
81
+ } catch (err) {
82
+ error.value = err instanceof Error ? err.message : String(err);
83
+ } finally {
84
+ loading.value = false;
85
+ }
86
+ }
87
+ async function addItem(reference, quantity, options) {
88
+ loading.value = true;
89
+ error.value = null;
90
+ try {
91
+ cart.value = await client.cart.addItem(reference, quantity, options);
92
+ } catch (err) {
93
+ error.value = err instanceof Error ? err.message : String(err);
94
+ } finally {
95
+ loading.value = false;
96
+ }
97
+ }
98
+ async function updateItem(lineId, quantity) {
99
+ loading.value = true;
100
+ error.value = null;
101
+ try {
102
+ cart.value = await client.cart.updateItem(lineId, quantity);
103
+ } catch (err) {
104
+ error.value = err instanceof Error ? err.message : String(err);
105
+ } finally {
106
+ loading.value = false;
107
+ }
108
+ }
109
+ async function removeItem(lineId) {
110
+ loading.value = true;
111
+ error.value = null;
112
+ try {
113
+ cart.value = await client.cart.removeItem(lineId);
114
+ } catch (err) {
115
+ error.value = err instanceof Error ? err.message : String(err);
116
+ } finally {
117
+ loading.value = false;
118
+ }
119
+ }
120
+ async function applyCoupon(code) {
121
+ loading.value = true;
122
+ error.value = null;
123
+ try {
124
+ cart.value = await client.cart.applyCoupon(code);
125
+ } catch (err) {
126
+ error.value = err instanceof Error ? err.message : String(err);
127
+ } finally {
128
+ loading.value = false;
129
+ }
130
+ }
131
+ return {
132
+ cart,
133
+ loading,
134
+ error,
135
+ isOffline,
136
+ hasPendingOperations,
137
+ itemCount,
138
+ total,
139
+ isEmpty,
140
+ load,
141
+ addItem,
142
+ updateItem,
143
+ removeItem,
144
+ applyCoupon
145
+ };
146
+ });
147
+ const useCatalogStore = defineStore("altazion:catalog", () => {
148
+ const client = useCommerceClient();
149
+ const currentProduct = ref(null);
150
+ const categoryResult = ref(null);
151
+ const loading = ref(false);
152
+ const error = ref(null);
153
+ const isOffline = computed(() => client.isOffline);
154
+ async function loadProduct(reference) {
155
+ loading.value = true;
156
+ error.value = null;
157
+ try {
158
+ currentProduct.value = await client.catalog.getProduct(reference);
159
+ } catch (err) {
160
+ error.value = err instanceof Error ? err.message : String(err);
161
+ } finally {
162
+ loading.value = false;
163
+ }
164
+ }
165
+ async function loadCategory(categoryCode, pageIndex = 0, pageSize = 20) {
166
+ loading.value = true;
167
+ error.value = null;
168
+ try {
169
+ categoryResult.value = await client.catalog.getCategory(categoryCode, pageIndex, pageSize);
170
+ } catch (err) {
171
+ error.value = err instanceof Error ? err.message : String(err);
172
+ } finally {
173
+ loading.value = false;
174
+ }
175
+ }
176
+ return {
177
+ currentProduct,
178
+ categoryResult,
179
+ loading,
180
+ error,
181
+ isOffline,
182
+ loadProduct,
183
+ loadCategory
184
+ };
185
+ });
186
+ const useSearchStore = defineStore("altazion:search", () => {
187
+ const client = useCommerceClient();
188
+ const result = ref(null);
189
+ const suggestions = ref([]);
190
+ const loading = ref(false);
191
+ const error = ref(null);
192
+ const query = ref("");
193
+ async function search(request) {
194
+ query.value = request.q ?? "";
195
+ loading.value = true;
196
+ error.value = null;
197
+ try {
198
+ result.value = await client.catalog.search(request);
199
+ } catch (err) {
200
+ error.value = err instanceof Error ? err.message : String(err);
201
+ } finally {
202
+ loading.value = false;
203
+ }
204
+ }
205
+ async function suggest(q) {
206
+ if (!q.trim()) {
207
+ suggestions.value = [];
208
+ return;
209
+ }
210
+ try {
211
+ suggestions.value = await client.catalog.suggest(q);
212
+ } catch {
213
+ suggestions.value = [];
214
+ }
215
+ }
216
+ function clear() {
217
+ result.value = null;
218
+ suggestions.value = [];
219
+ query.value = "";
220
+ }
221
+ return { result, suggestions, loading, error, query, search, suggest, clear };
222
+ });
223
+ const _hoisted_1$2 = { class: "altz-product-card" };
224
+ const _hoisted_2$1 = ["href"];
225
+ const _hoisted_3$1 = ["src", "alt"];
226
+ const _hoisted_4$1 = { class: "altz-product-card__body" };
227
+ const _hoisted_5$1 = { class: "altz-product-card__title" };
228
+ const _hoisted_6$1 = ["href"];
229
+ const _hoisted_7$1 = { class: "altz-product-card__price" };
230
+ const _hoisted_8$1 = {
231
+ key: 0,
232
+ class: "altz-product-card__price--original"
233
+ };
234
+ const _hoisted_9$1 = { class: "altz-product-card__price--current" };
235
+ const _hoisted_10$1 = {
236
+ key: 0,
237
+ class: "altz-product-card__unavailable"
238
+ };
239
+ const _hoisted_11 = ["disabled"];
240
+ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
241
+ __name: "ProductCard",
242
+ props: {
243
+ product: {},
244
+ showAddToCart: { type: Boolean }
245
+ },
246
+ setup(__props) {
247
+ const props = __props;
248
+ const cartStore = useCartStore();
249
+ async function addToCart() {
250
+ await cartStore.addItem(props.product.sku ?? props.product.guid, 1);
251
+ }
252
+ return (_ctx, _cache) => {
253
+ return openBlock(), createElementBlock("article", _hoisted_1$2, [
254
+ createElementVNode("a", {
255
+ href: __props.product.externalUrl ?? "#",
256
+ class: "altz-product-card__image-link"
257
+ }, [
258
+ __props.product.mainImage ? (openBlock(), createElementBlock("img", {
259
+ key: 0,
260
+ src: __props.product.mainImage,
261
+ alt: __props.product.label ?? void 0,
262
+ class: "altz-product-card__image",
263
+ loading: "lazy"
264
+ }, null, 8, _hoisted_3$1)) : createCommentVNode("", true)
265
+ ], 8, _hoisted_2$1),
266
+ createElementVNode("div", _hoisted_4$1, [
267
+ createElementVNode("h3", _hoisted_5$1, [
268
+ createElementVNode("a", {
269
+ href: __props.product.externalUrl ?? "#"
270
+ }, toDisplayString(__props.product.label), 9, _hoisted_6$1)
271
+ ]),
272
+ createElementVNode("div", _hoisted_7$1, [
273
+ __props.product.discountedPrice ? (openBlock(), createElementBlock("span", _hoisted_8$1, toDisplayString(__props.product.price.toFixed(2)) + " € ", 1)) : createCommentVNode("", true),
274
+ createElementVNode("span", _hoisted_9$1, toDisplayString((__props.product.discountedPrice ?? __props.product.price).toFixed(2)) + " € ", 1)
275
+ ]),
276
+ !__props.product.availableForOrder ? (openBlock(), createElementBlock("p", _hoisted_10$1, " Indisponible ")) : createCommentVNode("", true),
277
+ __props.showAddToCart && __props.product.availableForOrder ? (openBlock(), createElementBlock("button", {
278
+ key: 1,
279
+ class: "altz-product-card__add-to-cart",
280
+ disabled: unref(cartStore).loading,
281
+ onClick: addToCart
282
+ }, " Ajouter au panier ", 8, _hoisted_11)) : createCommentVNode("", true)
283
+ ])
284
+ ]);
285
+ };
286
+ }
287
+ });
288
+ const _hoisted_1$1 = { class: "altz-cart-summary" };
289
+ const _hoisted_2 = {
290
+ key: 0,
291
+ class: "altz-cart-summary__loading"
292
+ };
293
+ const _hoisted_3 = {
294
+ key: 1,
295
+ class: "altz-cart-summary__empty"
296
+ };
297
+ const _hoisted_4 = {
298
+ key: 0,
299
+ class: "altz-cart-summary__lines"
300
+ };
301
+ const _hoisted_5 = { class: "altz-cart-summary__line-label" };
302
+ const _hoisted_6 = { class: "altz-cart-summary__line-qty" };
303
+ const _hoisted_7 = { class: "altz-cart-summary__line-price" };
304
+ const _hoisted_8 = { class: "altz-cart-summary__total" };
305
+ const _hoisted_9 = { class: "altz-cart-summary__total-amount" };
306
+ const _hoisted_10 = {
307
+ key: 1,
308
+ class: "altz-cart-summary__offline-notice"
309
+ };
310
+ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
311
+ __name: "CartSummary",
312
+ props: {
313
+ showLines: { type: Boolean }
314
+ },
315
+ setup(__props) {
316
+ const cartStore = useCartStore();
317
+ onMounted(() => {
318
+ cartStore.load();
319
+ });
320
+ return (_ctx, _cache) => {
321
+ var _a, _b;
322
+ return openBlock(), createElementBlock("div", _hoisted_1$1, [
323
+ unref(cartStore).loading ? (openBlock(), createElementBlock("div", _hoisted_2, " Chargement du panier… ")) : unref(cartStore).isEmpty ? (openBlock(), createElementBlock("div", _hoisted_3, " Votre panier est vide. ")) : (openBlock(), createElementBlock(Fragment, { key: 2 }, [
324
+ __props.showLines ? (openBlock(), createElementBlock("div", _hoisted_4, [
325
+ (openBlock(true), createElementBlock(Fragment, null, renderList((_b = (_a = unref(cartStore).cart) == null ? void 0 : _a.content) == null ? void 0 : _b.flatMap((g) => g.lines ?? []), (line) => {
326
+ return openBlock(), createElementBlock("div", {
327
+ key: line.id,
328
+ class: "altz-cart-summary__line"
329
+ }, [
330
+ createElementVNode("span", _hoisted_5, toDisplayString(line.label), 1),
331
+ createElementVNode("span", _hoisted_6, "× " + toDisplayString(line.quantity), 1),
332
+ createElementVNode("span", _hoisted_7, toDisplayString((line.finalUnitPriceInclTax * line.quantity).toFixed(2)) + " €", 1)
333
+ ]);
334
+ }), 128))
335
+ ])) : createCommentVNode("", true),
336
+ createElementVNode("div", _hoisted_8, [
337
+ _cache[0] || (_cache[0] = createElementVNode("span", { class: "altz-cart-summary__total-label" }, "Total", -1)),
338
+ createElementVNode("span", _hoisted_9, toDisplayString(unref(cartStore).total.toFixed(2)) + " €", 1)
339
+ ]),
340
+ unref(cartStore).hasPendingOperations ? (openBlock(), createElementBlock("div", _hoisted_10, " Modifications en attente de synchronisation… ")) : createCommentVNode("", true)
341
+ ], 64))
342
+ ]);
343
+ };
344
+ }
345
+ });
346
+ const _hoisted_1 = ["disabled", "aria-busy"];
347
+ const _sfc_main = /* @__PURE__ */ defineComponent({
348
+ __name: "AddToCartButton",
349
+ props: {
350
+ reference: {},
351
+ quantity: {},
352
+ label: {},
353
+ disabled: { type: Boolean }
354
+ },
355
+ setup(__props) {
356
+ const props = __props;
357
+ const cartStore = useCartStore();
358
+ async function handleClick() {
359
+ if (props.disabled) return;
360
+ await cartStore.addItem(props.reference, props.quantity ?? 1);
361
+ }
362
+ return (_ctx, _cache) => {
363
+ return openBlock(), createElementBlock("button", {
364
+ class: "altz-add-to-cart",
365
+ disabled: __props.disabled || unref(cartStore).loading,
366
+ "aria-busy": unref(cartStore).loading,
367
+ onClick: handleClick
368
+ }, [
369
+ renderSlot(_ctx.$slots, "default", {}, () => [
370
+ createTextVNode(toDisplayString(__props.label ?? "Ajouter au panier"), 1)
371
+ ])
372
+ ], 8, _hoisted_1);
373
+ };
374
+ }
375
+ });
376
+ export {
377
+ _sfc_main as AddToCartButton,
378
+ AltazionCommercePlugin,
379
+ COMMERCE_CLIENT_KEY,
380
+ _sfc_main$1 as CartSummary,
381
+ _sfc_main$2 as ProductCard,
382
+ useCartStore,
383
+ useCatalogStore,
384
+ useCommerceClient,
385
+ useSearchStore,
386
+ useSessionStore
387
+ };
388
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/plugin.ts","../src/composables/useCommerceClient.ts","../src/stores/useSessionStore.ts","../src/stores/useCartStore.ts","../src/stores/useCatalogStore.ts","../src/stores/useSearchStore.ts","../src/components/ProductCard.vue","../src/components/CartSummary.vue","../src/components/AddToCartButton.vue"],"sourcesContent":["import type { App } from 'vue'\nimport { createPinia, type Pinia } from 'pinia'\nimport type { CommerceClient } from '@altazion/commerce-sdk-core'\n\nexport const COMMERCE_CLIENT_KEY = Symbol('altazion:commerce-client')\n\nexport interface AltazionCommercePluginOptions {\n client: CommerceClient\n /** Pinia instance existante (optionnel — le plugin en crée une si absent) */\n pinia?: Pinia\n}\n\n/**\n * Plugin Vue 3 pour le SDK Altazion Commerce.\n *\n * Usage :\n * ```ts\n * import { createApp } from 'vue'\n * import { CommerceClient } from '@altazion/commerce-sdk-core'\n * import { AltazionCommercePlugin } from '@altazion/commerce-sdk-vue'\n *\n * const client = new CommerceClient({ baseUrl: '...', siteUrl: window.location.href })\n * await client.initialize()\n *\n * createApp(App)\n * .use(AltazionCommercePlugin, { client })\n * .mount('#app')\n * ```\n */\nexport const AltazionCommercePlugin = {\n install(app: App, options: AltazionCommercePluginOptions): void {\n const { client, pinia } = options\n\n // Installer Pinia si pas déjà présente\n const piniaInstance = pinia ?? createPinia()\n app.use(piniaInstance)\n\n // Rendre le client accessible via inject()\n app.provide(COMMERCE_CLIENT_KEY, client)\n }\n}\n","import { inject } from 'vue'\nimport { COMMERCE_CLIENT_KEY } from '../plugin.js'\nimport type { CommerceClient } from '@altazion/commerce-sdk-core'\n\n/**\n * Composable pour accéder au CommerceClient injecté par AltazionCommercePlugin.\n * Doit être utilisé dans un composant Vue (setup()) ou un store Pinia.\n */\nexport function useCommerceClient(): CommerceClient {\n const client = inject<CommerceClient>(COMMERCE_CLIENT_KEY)\n if (!client) {\n throw new Error(\n '[AltazionCommerce] useCommerceClient() : aucun client trouvé. ' +\n 'Assurez-vous d\\'avoir installé AltazionCommercePlugin via app.use().'\n )\n }\n return client\n}\n","import { defineStore } from 'pinia'\nimport { ref, computed } from 'vue'\nimport { useCommerceClient } from '../composables/useCommerceClient.js'\nimport type { SessionInfo, ConnectivityStatus } from '@altazion/commerce-sdk-core'\n\nexport const useSessionStore = defineStore('altazion:session', () => {\n const client = useCommerceClient()\n\n const session = ref<SessionInfo | null>(null)\n const loading = ref(false)\n const error = ref<string | null>(null)\n\n const isOnline = ref(client.connectivity.isOnline)\n client.connectivity.subscribe((status: ConnectivityStatus) => {\n isOnline.value = status === 'online'\n })\n\n const mode = computed(() => client.context.mode)\n const isKiosk = computed(() => mode.value === 'kiosk')\n const isReady = computed(() => session.value !== null || mode.value === 'kiosk')\n\n async function load(): Promise<void> {\n loading.value = true\n error.value = null\n try {\n session.value = await client.session.getSession()\n } catch (err) {\n error.value = err instanceof Error ? err.message : String(err)\n } finally {\n loading.value = false\n }\n }\n\n async function associateStore(storeGuid: string): Promise<void> {\n loading.value = true\n error.value = null\n try {\n session.value = await client.session.associateStore(storeGuid)\n } catch (err) {\n error.value = err instanceof Error ? err.message : String(err)\n } finally {\n loading.value = false\n }\n }\n\n return { session, loading, error, isOnline, mode, isKiosk, isReady, load, associateStore }\n})\n","import { defineStore } from 'pinia'\nimport { ref, computed } from 'vue'\nimport { useCommerceClient } from '../composables/useCommerceClient.js'\nimport type { Cart } from '@altazion/commerce-sdk-core'\n\nexport const useCartStore = defineStore('altazion:cart', () => {\n const client = useCommerceClient()\n\n const cart = ref<Cart | null>(null)\n const loading = ref(false)\n const error = ref<string | null>(null)\n const hasPendingOperations = ref(false)\n\n // Mise à jour de hasPendingOperations via la file offline\n client.onQueueEvent(async () => {\n hasPendingOperations.value = (await client.pendingOperationsCount) > 0\n })\n\n const isOffline = computed(() => client.isOffline)\n const itemCount = computed(() => cart.value?.totalQuantity ?? 0)\n const total = computed(() => cart.value?.totalAmountWithTax ?? 0)\n const isEmpty = computed(() => itemCount.value === 0)\n\n async function load(): Promise<void> {\n loading.value = true\n error.value = null\n try {\n cart.value = await client.cart.getCart()\n } catch (err) {\n error.value = err instanceof Error ? err.message : String(err)\n } finally {\n loading.value = false\n }\n }\n\n async function addItem(reference: string, quantity: number, options?: Record<string, unknown>): Promise<void> {\n loading.value = true\n error.value = null\n try {\n cart.value = await client.cart.addItem(reference, quantity, options)\n } catch (err) {\n error.value = err instanceof Error ? err.message : String(err)\n } finally {\n loading.value = false\n }\n }\n\n async function updateItem(lineId: string, quantity: number): Promise<void> {\n loading.value = true\n error.value = null\n try {\n cart.value = await client.cart.updateItem(lineId, quantity)\n } catch (err) {\n error.value = err instanceof Error ? err.message : String(err)\n } finally {\n loading.value = false\n }\n }\n\n async function removeItem(lineId: string): Promise<void> {\n loading.value = true\n error.value = null\n try {\n cart.value = await client.cart.removeItem(lineId)\n } catch (err) {\n error.value = err instanceof Error ? err.message : String(err)\n } finally {\n loading.value = false\n }\n }\n\n async function applyCoupon(code: string): Promise<void> {\n loading.value = true\n error.value = null\n try {\n cart.value = await client.cart.applyCoupon(code)\n } catch (err) {\n error.value = err instanceof Error ? err.message : String(err)\n } finally {\n loading.value = false\n }\n }\n\n return {\n cart, loading, error, isOffline, hasPendingOperations,\n itemCount, total, isEmpty,\n load, addItem, updateItem, removeItem, applyCoupon\n }\n})\n","import { defineStore } from 'pinia'\nimport { ref, computed } from 'vue'\nimport { useCommerceClient } from '../composables/useCommerceClient.js'\nimport type { ProductDetails, SearchResult, SearchRequest } from '@altazion/commerce-sdk-core'\n\nexport const useCatalogStore = defineStore('altazion:catalog', () => {\n const client = useCommerceClient()\n\n const currentProduct = ref<ProductDetails | null>(null)\n const categoryResult = ref<SearchResult | null>(null)\n const loading = ref(false)\n const error = ref<string | null>(null)\n\n const isOffline = computed(() => client.isOffline)\n\n async function loadProduct(reference: string): Promise<void> {\n loading.value = true\n error.value = null\n try {\n currentProduct.value = await client.catalog.getProduct(reference)\n } catch (err) {\n error.value = err instanceof Error ? err.message : String(err)\n } finally {\n loading.value = false\n }\n }\n\n async function loadCategory(categoryCode: string, pageIndex = 0, pageSize = 20): Promise<void> {\n loading.value = true\n error.value = null\n try {\n categoryResult.value = await client.catalog.getCategory(categoryCode, pageIndex, pageSize)\n } catch (err) {\n error.value = err instanceof Error ? err.message : String(err)\n } finally {\n loading.value = false\n }\n }\n\n return {\n currentProduct, categoryResult, loading, error, isOffline,\n loadProduct, loadCategory\n }\n})\n","import { defineStore } from 'pinia'\nimport { ref } from 'vue'\nimport { useCommerceClient } from '../composables/useCommerceClient.js'\nimport type { SearchResult, SearchRequest } from '@altazion/commerce-sdk-core'\n\nexport const useSearchStore = defineStore('altazion:search', () => {\n const client = useCommerceClient()\n\n const result = ref<SearchResult | null>(null)\n const suggestions = ref<string[]>([])\n const loading = ref(false)\n const error = ref<string | null>(null)\n const query = ref('')\n\n async function search(request: SearchRequest): Promise<void> {\n query.value = request.q ?? ''\n loading.value = true\n error.value = null\n try {\n result.value = await client.catalog.search(request)\n } catch (err) {\n error.value = err instanceof Error ? err.message : String(err)\n } finally {\n loading.value = false\n }\n }\n\n async function suggest(q: string): Promise<void> {\n if (!q.trim()) { suggestions.value = []; return }\n try {\n suggestions.value = await client.catalog.suggest(q)\n } catch {\n suggestions.value = []\n }\n }\n\n function clear(): void {\n result.value = null\n suggestions.value = []\n query.value = ''\n }\n\n return { result, suggestions, loading, error, query, search, suggest, clear }\n})\n","<script setup lang=\"ts\">\nimport type { WebProduct } from '@altazion/commerce-sdk-core'\nimport { useCartStore } from '../stores/useCartStore.js'\n\nconst props = defineProps<{\n product: WebProduct\n showAddToCart?: boolean\n}>()\n\nconst cartStore = useCartStore()\n\nasync function addToCart(): Promise<void> {\n await cartStore.addItem(props.product.sku ?? props.product.guid, 1)\n}\n</script>\n\n<template>\n <article class=\"altz-product-card\">\n <a :href=\"product.externalUrl ?? '#'\" class=\"altz-product-card__image-link\">\n <img\n v-if=\"product.mainImage\"\n :src=\"product.mainImage\"\n :alt=\"product.label ?? undefined\"\n class=\"altz-product-card__image\"\n loading=\"lazy\"\n />\n </a>\n\n <div class=\"altz-product-card__body\">\n <h3 class=\"altz-product-card__title\">\n <a :href=\"product.externalUrl ?? '#'\">{{ product.label }}</a>\n </h3>\n\n <div class=\"altz-product-card__price\">\n <span\n v-if=\"product.discountedPrice\"\n class=\"altz-product-card__price--original\"\n >\n {{ product.price.toFixed(2) }} &#8364;\n </span>\n <span class=\"altz-product-card__price--current\">\n {{ (product.discountedPrice ?? product.price).toFixed(2) }} &#8364;\n </span>\n </div>\n\n <p v-if=\"!product.availableForOrder\" class=\"altz-product-card__unavailable\">\n Indisponible\n </p>\n\n <button\n v-if=\"showAddToCart && product.availableForOrder\"\n class=\"altz-product-card__add-to-cart\"\n :disabled=\"cartStore.loading\"\n @click=\"addToCart\"\n >\n Ajouter au panier\n </button>\n </div>\n </article>\n</template>\n","<script setup lang=\"ts\">\nimport { onMounted } from 'vue'\nimport { useCartStore } from '../stores/useCartStore.js'\n\nconst props = defineProps<{\n showLines?: boolean\n}>()\n\nconst cartStore = useCartStore()\n\nonMounted(() => { cartStore.load() })\n</script>\n\n<template>\n <div class=\"altz-cart-summary\">\n <div v-if=\"cartStore.loading\" class=\"altz-cart-summary__loading\">\n Chargement du panier…\n </div>\n\n <div v-else-if=\"cartStore.isEmpty\" class=\"altz-cart-summary__empty\">\n Votre panier est vide.\n </div>\n\n <template v-else>\n <div v-if=\"showLines\" class=\"altz-cart-summary__lines\">\n <div\n v-for=\"line in cartStore.cart?.content?.flatMap(g => g.lines ?? [])\"\n :key=\"line.id\"\n class=\"altz-cart-summary__line\"\n >\n <span class=\"altz-cart-summary__line-label\">{{ line.label }}</span>\n <span class=\"altz-cart-summary__line-qty\">× {{ line.quantity }}</span>\n <span class=\"altz-cart-summary__line-price\">{{ (line.finalUnitPriceInclTax * line.quantity).toFixed(2) }} €</span>\n </div>\n </div>\n\n <div class=\"altz-cart-summary__total\">\n <span class=\"altz-cart-summary__total-label\">Total</span>\n <span class=\"altz-cart-summary__total-amount\">{{ cartStore.total.toFixed(2) }} €</span>\n </div>\n\n <div v-if=\"cartStore.hasPendingOperations\" class=\"altz-cart-summary__offline-notice\">\n Modifications en attente de synchronisation…\n </div>\n </template>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { useCartStore } from '../stores/useCartStore.js'\n\nconst props = defineProps<{\n reference: string\n quantity?: number\n label?: string\n disabled?: boolean\n}>()\n\nconst cartStore = useCartStore()\n\nasync function handleClick(): Promise<void> {\n if (props.disabled) return\n await cartStore.addItem(props.reference, props.quantity ?? 1)\n}\n</script>\n\n<template>\n <button\n class=\"altz-add-to-cart\"\n :disabled=\"disabled || cartStore.loading\"\n :aria-busy=\"cartStore.loading\"\n @click=\"handleClick\"\n >\n <slot>{{ label ?? 'Ajouter au panier' }}</slot>\n </button>\n</template>\n"],"names":["_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_4","_hoisted_5","_toDisplayString","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_unref","_Fragment","_renderList","_renderSlot"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@altazion/commerce-sdk-vue",
3
+ "version": "1.0.0",
4
+ "description": "Altazion Commerce SDK — Plugin Vue 3 avec stores Pinia et composants",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs",
13
+ "types": "./dist/index.d.ts"
14
+ }
15
+ },
16
+ "files": ["dist"],
17
+ "scripts": {
18
+ "build": "vite build",
19
+ "dev": "vite build --watch",
20
+ "typecheck": "tsc --noEmit",
21
+ "clean": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\""
22
+ },
23
+ "dependencies": {
24
+ "@altazion/commerce-sdk-core": "*"
25
+ },
26
+ "peerDependencies": {
27
+ "vue": "^3.4.0",
28
+ "pinia": "^2.1.0"
29
+ },
30
+ "devDependencies": {
31
+ "@vitejs/plugin-vue": "^5.0.0",
32
+ "typescript": "^5.4.0",
33
+ "vite": "^5.2.0",
34
+ "vite-plugin-dts": "^3.9.0",
35
+ "vue": "^3.4.0",
36
+ "pinia": "^2.1.0"
37
+ },
38
+ "engines": {
39
+ "node": ">=20"
40
+ }
41
+ }