@raxonltd/raxon-core 1.1.6 → 1.1.8

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.
Files changed (66) hide show
  1. package/core/component/general.image.tsx +86 -0
  2. package/core/context/cart.context.tsx +446 -0
  3. package/core/context/security.context.tsx +151 -0
  4. package/core/feature/address/api/places.api.ts +76 -0
  5. package/core/feature/address/form/address-search-input.tsx +125 -0
  6. package/core/feature/address/hook/use.addres.tsx +63 -0
  7. package/core/feature/address/hook/use.address-autocomplete.ts +116 -0
  8. package/core/feature/address/util/address.types.ts +38 -0
  9. package/core/feature/address/util/parse-google-place.ts +66 -0
  10. package/core/feature/analytic-event/analytic.event.api.ts +27 -0
  11. package/core/feature/analytic-event/analytic.event.context.tsx +180 -0
  12. package/core/feature/analytic-event/analytic.event.util.ts +42 -0
  13. package/core/feature/analytic-event/use.analytic.auto.tsx +114 -0
  14. package/core/feature/article/hook/use.article.tsx +33 -0
  15. package/core/feature/attribute/hook/use.attribute.tsx +24 -0
  16. package/core/feature/auth/hook/use.auth.tsx +141 -0
  17. package/core/feature/auth/modal/modal.auth.tsx +80 -0
  18. package/core/feature/auth/view/view.login.tsx +199 -0
  19. package/core/feature/auth/view/view.register.tsx +333 -0
  20. package/core/feature/bank-account/hook/use.bank.account.tsx +47 -0
  21. package/core/feature/brand/hook/use.brand.tsx +24 -0
  22. package/core/feature/cart/component/cart.order.summary.tsx +89 -0
  23. package/core/feature/cart/component/cart.promo.code.section.tsx +208 -0
  24. package/core/feature/cart/hook/use.cart.tsx +267 -0
  25. package/core/feature/cart/util/basket-pay.response.ts +67 -0
  26. package/core/feature/cart/util/cart-optimistic.ts +425 -0
  27. package/core/feature/cart/util/garanti-payment.ts +27 -0
  28. package/core/feature/collection/hook/use.collection.tsx +32 -0
  29. package/core/feature/delivery-method/hook/use.delivery.method.tsx +40 -0
  30. package/core/feature/delivery-method/util/checkout.delivery.method.ts +11 -0
  31. package/core/feature/faq/hook/use.faq.tsx +23 -0
  32. package/core/feature/favorite/hook/use.favorite.tsx +48 -0
  33. package/core/feature/form-submit/form/form.contact.tsx +118 -0
  34. package/core/feature/form-submit/hook/use.form.submit.tsx +16 -0
  35. package/core/feature/invoice/hook/use.invoice.tsx +51 -0
  36. package/core/feature/newsletter/hook/use.newsletter.tsx +124 -0
  37. package/core/feature/newsletter/modal/modal.newsletter.product.tsx +163 -0
  38. package/core/feature/order/hook/use.order.tsx +31 -0
  39. package/core/feature/payment-method/checkout.payment.options.ts +117 -0
  40. package/core/feature/payment-method/hook/use.payment.method.tsx +44 -0
  41. package/core/feature/product/hook/use.product.tsx +122 -0
  42. package/core/feature/profile/hook/use.profile.tsx +126 -0
  43. package/core/feature/promo-code/hook/use.promo.code.tsx +27 -0
  44. package/core/interface/basket.interface.ts +360 -0
  45. package/core/interface/bootstrap.interface.ts +39 -0
  46. package/core/interface/context.interface.ts +9 -0
  47. package/core/interface/inventory.interface.ts +88 -0
  48. package/core/interface/nexine.interface.ts +4 -0
  49. package/core/interface/prisma.interface.ts +8844 -0
  50. package/core/interface/product.interface.ts +111 -0
  51. package/core/raxon.context.tsx +256 -0
  52. package/core/schema/checkout.schema.ts +103 -0
  53. package/core/util/basket.item.display.ts +19 -0
  54. package/core/util/category.nav.ts +46 -0
  55. package/core/util/client-ip.ts +35 -0
  56. package/core/util/collection.util.ts +433 -0
  57. package/core/util/fetch.bootstrap.ts +21 -0
  58. package/core/util/garanti-payment.ts +5 -0
  59. package/core/util/nexine.axios.tsx +104 -0
  60. package/core/util/no-cache.ts +6 -0
  61. package/core/util/util.ts +191 -0
  62. package/core/view/view.checkout.tsx +1964 -0
  63. package/dist/core/view/view.checkout.js +2 -2
  64. package/dist/tsconfig.tsbuildinfo +1 -1
  65. package/package.json +12 -3
  66. package/tailwind.css +11 -0
@@ -0,0 +1,425 @@
1
+ import { BasketItemSummaryInterface, BasketSummaryInterface } from '@/core/interface/basket.interface';
2
+ import { SaleType } from '@/core/interface/prisma.interface';
3
+ import type { QueryClient } from '@tanstack/react-query';
4
+
5
+ export const CART_QUERY_KEY = ['organization', 'cart'] as const;
6
+
7
+ export const CART_QUANTITY_DEBOUNCE_MS = 400;
8
+
9
+ export function createEmptyOptimisticCart(): BasketSummaryInterface {
10
+ return {
11
+ id: 'optimistic-cart',
12
+ acceptedAlternativeProduct: false,
13
+ items: [],
14
+ info: {
15
+ count: { VKE: 0, Basis: 0, Gesamt: 0, Artikel: 0 },
16
+ basePrice: { total: 0, tax: 0, pay: 0 },
17
+ deposit: { total: 0, tax: 0, pay: 0 },
18
+ tax: [],
19
+ delivery: { total: 0, tax: 0, pay: 0 },
20
+ discount: { total: 0, tax: 0, pay: 0 },
21
+ promotion: { total: 0, tax: 0, pay: 0 },
22
+ campaign: { info: { status: null, message: null, name: null }, total: 0, tax: 0, pay: 0 },
23
+ payPrice: { total: 0, tax: 0, pay: 0, delivery: 0, discount: 0, deposit: 0, promotion: 0, campaign: 0 },
24
+ },
25
+ } as unknown as BasketSummaryInterface;
26
+ }
27
+
28
+ export interface PendingCartAdd {
29
+ productId: string;
30
+ variantId?: string;
31
+ quantity: number;
32
+ linePay?: number;
33
+ }
34
+
35
+ export function unionMergeCarts(carts: (BasketSummaryInterface | undefined)[]): BasketSummaryInterface | undefined {
36
+ const valid = carts.filter((c): c is BasketSummaryInterface => Boolean(c));
37
+ if (valid.length === 0) return undefined;
38
+
39
+ const lineMap = new Map<string, BasketItemSummaryInterface>();
40
+
41
+ for (const cart of valid) {
42
+ for (const item of cart.items ?? []) {
43
+ const identity = cartLineIdentity(item);
44
+ const existing = lineMap.get(identity);
45
+ if (!existing) {
46
+ lineMap.set(identity, item);
47
+ continue;
48
+ }
49
+
50
+ const existingOptimistic = String(existing.id).startsWith('optimistic-');
51
+ const itemOptimistic = String(item.id).startsWith('optimistic-');
52
+
53
+ if (existingOptimistic && !itemOptimistic) {
54
+ lineMap.set(identity, item);
55
+ continue;
56
+ }
57
+
58
+ if (!existingOptimistic && !itemOptimistic && Number(item.quantity) >= Number(existing.quantity)) {
59
+ lineMap.set(identity, item);
60
+ }
61
+ }
62
+ }
63
+
64
+ if (lineMap.size === 0) return valid[valid.length - 1];
65
+
66
+ const base = valid.find((cart) => (cart.items?.length ?? 0) > 0) ?? valid[0];
67
+ return recalcCartTotals(base, Array.from(lineMap.values()));
68
+ }
69
+
70
+ export function readCartCache(queryClient: QueryClient): BasketSummaryInterface | undefined {
71
+ const direct = queryClient.getQueryData<BasketSummaryInterface>(CART_QUERY_KEY);
72
+ const entries = queryClient.getQueriesData<BasketSummaryInterface>({ queryKey: CART_QUERY_KEY });
73
+ const snapshots = [direct, ...entries.map(([, data]) => data)];
74
+ return unionMergeCarts(snapshots);
75
+ }
76
+
77
+ export function patchCartCache(
78
+ queryClient: QueryClient,
79
+ updater: (old: BasketSummaryInterface | undefined) => BasketSummaryInterface
80
+ ) {
81
+ queryClient.setQueryData(CART_QUERY_KEY, (old: BasketSummaryInterface | undefined) => updater(old));
82
+ }
83
+
84
+ export function cartLineKey(productId: string | number, variantId?: string | number | null) {
85
+ return `${productId}:${variantId ?? ''}`;
86
+ }
87
+
88
+ export function cartLineIdentity(item: BasketItemSummaryInterface) {
89
+ const variantId = item.variant?.id ?? item.variantId ?? '';
90
+ return cartLineKey(item.productId, variantId);
91
+ }
92
+
93
+ export function findCartLine(
94
+ cart: BasketSummaryInterface | null | undefined,
95
+ productId: string | number,
96
+ variantId?: string | number | null
97
+ ) {
98
+ if (!cart?.items) return undefined;
99
+
100
+ return cart.items.find((item) => {
101
+ const sameProduct = String(item.productId) === String(productId);
102
+ if (!sameProduct) return false;
103
+
104
+ const itemVariantId = item.variant?.id ?? item.variantId ?? '';
105
+ const targetVariantId = variantId ?? '';
106
+ return String(itemVariantId) === String(targetVariantId);
107
+ });
108
+ }
109
+
110
+ export function findConfirmedCartLine(
111
+ cart: BasketSummaryInterface | null | undefined,
112
+ productId: string | number,
113
+ variantId?: string | number | null
114
+ ) {
115
+ const line = findCartLine(cart, productId, variantId);
116
+ if (!line || String(line.id).startsWith('optimistic-')) return undefined;
117
+ return line;
118
+ }
119
+
120
+ export function isFullBasketSnapshot(basket: BasketSummaryInterface, cached?: BasketSummaryInterface): boolean {
121
+ if (!cached?.items?.length) return true;
122
+
123
+ const basketItems = basket.items ?? [];
124
+ if (basketItems.length >= cached.items.length) return true;
125
+
126
+ const basketKeys = new Set(basketItems.map(cartLineIdentity));
127
+ return cached.items.every((item) => basketKeys.has(cartLineIdentity(item)));
128
+ }
129
+
130
+ export function mergeCartWithOptimisticExtras(
131
+ server: BasketSummaryInterface,
132
+ cached?: BasketSummaryInterface
133
+ ): BasketSummaryInterface {
134
+ if (!cached?.items?.length) return server;
135
+ if (!server?.items?.length) return cached;
136
+
137
+ const serverKeys = new Set(server.items.map(cartLineIdentity));
138
+ const optimisticExtras = cached.items.filter(
139
+ (item) => !serverKeys.has(cartLineIdentity(item)) && String(item.id).startsWith('optimistic-')
140
+ );
141
+
142
+ if (optimisticExtras.length === 0) return server;
143
+
144
+ return recalcCartTotals(server, [...server.items, ...optimisticExtras]);
145
+ }
146
+
147
+ export function applyBasketInsertResponse(
148
+ basket: BasketSummaryInterface,
149
+ cached?: BasketSummaryInterface
150
+ ): BasketSummaryInterface {
151
+ if (!cached?.items?.length) return basket;
152
+
153
+ if (isFullBasketSnapshot(basket, cached)) {
154
+ return mergeCartWithOptimisticExtras(basket, cached);
155
+ }
156
+
157
+ return (
158
+ basket.items?.reduce(
159
+ (acc, item) =>
160
+ mergeInsertItemIntoCart(acc, {
161
+ id: String(item.id),
162
+ productId: String(item.productId),
163
+ variantId: item.variantId != null ? String(item.variantId) : null,
164
+ quantity: Number(item.quantity || 1),
165
+ }),
166
+ cached
167
+ ) ?? cached
168
+ );
169
+ }
170
+
171
+ export function removeCartLineByKey(cart: BasketSummaryInterface, lineKey: string): BasketSummaryInterface {
172
+ const items = (cart.items ?? []).filter((item) => {
173
+ if (String(item.id) === `optimistic-${lineKey}`) return false;
174
+ return cartLineKey(item.productId, item.variant?.id ?? item.variantId) !== lineKey;
175
+ });
176
+ return recalcCartTotals(cart, items);
177
+ }
178
+
179
+ export function createOptimisticCartLine(add: PendingCartAdd): BasketItemSummaryInterface {
180
+ const linePay = Number(add.linePay || 0);
181
+ const quantity = Number(add.quantity || 1);
182
+
183
+ return {
184
+ id: `optimistic-${cartLineKey(add.productId, add.variantId)}`,
185
+ productId: String(add.productId),
186
+ variantId: add.variantId ? String(add.variantId) : null,
187
+ variant: add.variantId ? { id: String(add.variantId) } as BasketItemSummaryInterface['variant'] : null,
188
+ taxPercentage: 0,
189
+ images: [],
190
+ product: {
191
+ articleNumber: '',
192
+ type: 'product',
193
+ baseUnit: { id: '', name: '' },
194
+ productUnits: [],
195
+ id: String(add.productId),
196
+ name: '',
197
+ },
198
+ productUnit: { id: '', name: '' },
199
+ productSaleUnit: '',
200
+ unitName: '',
201
+ quantityPerUnitOfMeasure: 1,
202
+ quantity,
203
+ saleType: SaleType.UNIT,
204
+ weight: 0,
205
+ stock: 0,
206
+ basePrice: linePay / quantity,
207
+ discountPrice: 0,
208
+ lineTotal: linePay,
209
+ lineTax: 0,
210
+ linePay,
211
+ taxAmount: { baseTaxAmount: 0, payTaxAmount: 0 },
212
+ };
213
+ }
214
+
215
+ export function applyPendingAdds(
216
+ cart: BasketSummaryInterface,
217
+ pendingAdds: Record<string, PendingCartAdd>
218
+ ): BasketSummaryInterface {
219
+ const entries = Object.entries(pendingAdds);
220
+ if (entries.length === 0) return cart;
221
+
222
+ let items = [...(cart.items || [])];
223
+
224
+ for (const [, add] of entries) {
225
+ const existingIndex = items.findIndex((item) => {
226
+ const sameProduct = String(item.productId) === String(add.productId);
227
+ const itemVariantId = item.variant?.id ?? item.variantId ?? '';
228
+ const targetVariantId = add.variantId ?? '';
229
+ return sameProduct && String(itemVariantId) === String(targetVariantId);
230
+ });
231
+
232
+ if (existingIndex >= 0) {
233
+ const existing = items[existingIndex];
234
+ const unitPrice = Number(existing.linePay || add.linePay || 0) / (Number(existing.quantity || add.quantity) || 1);
235
+ items[existingIndex] = {
236
+ ...existing,
237
+ quantity: add.quantity,
238
+ linePay: unitPrice * add.quantity,
239
+ };
240
+ continue;
241
+ }
242
+
243
+ items = [...items, createOptimisticCartLine(add)];
244
+ }
245
+
246
+ return recalcCartTotals(cart, items);
247
+ }
248
+
249
+ export function extractBasketFromInsertResponse(data: unknown): BasketSummaryInterface | null {
250
+ if (!data || typeof data !== 'object') return null;
251
+
252
+ const payload = data as Record<string, unknown>;
253
+ if (Array.isArray(payload.items)) return payload as unknown as BasketSummaryInterface;
254
+
255
+ const nested = payload.data;
256
+ if (nested && typeof nested === 'object' && Array.isArray((nested as BasketSummaryInterface).items)) {
257
+ return nested as unknown as BasketSummaryInterface;
258
+ }
259
+
260
+ return null;
261
+ }
262
+
263
+ export interface InsertCartItemResponse {
264
+ id: string;
265
+ productId: string;
266
+ variantId?: string | null;
267
+ quantity: number;
268
+ }
269
+
270
+ export function extractInsertCartItem(data: unknown): InsertCartItemResponse | null {
271
+ if (!data || typeof data !== 'object') return null;
272
+
273
+ const payload = data as Record<string, unknown>;
274
+ const raw =
275
+ payload.data && typeof payload.data === 'object' && !Array.isArray(payload.data)
276
+ ? (payload.data as Record<string, unknown>)
277
+ : payload;
278
+
279
+ if (!raw.id || !raw.productId) return null;
280
+
281
+ return {
282
+ id: String(raw.id),
283
+ productId: String(raw.productId),
284
+ variantId: raw.variantId != null ? String(raw.variantId) : null,
285
+ quantity: Number(raw.quantity || 1),
286
+ };
287
+ }
288
+
289
+ function recalcCartTotals(cart: BasketSummaryInterface, items: BasketItemSummaryInterface[]): BasketSummaryInterface {
290
+ const newGesamt = items.reduce((sum, item) => sum + Number(item.quantity || 0), 0);
291
+ const newPay = items.reduce((sum, item) => sum + Number(item.linePay || 0), 0);
292
+
293
+ return {
294
+ ...cart,
295
+ items,
296
+ info: {
297
+ ...cart.info,
298
+ count: {
299
+ ...cart.info?.count,
300
+ Gesamt: newGesamt,
301
+ Artikel: items.length,
302
+ },
303
+ payPrice: {
304
+ ...cart.info?.payPrice,
305
+ total: newPay,
306
+ pay: newPay,
307
+ },
308
+ },
309
+ };
310
+ }
311
+
312
+ export function mergeInsertItemIntoCart(
313
+ cart: BasketSummaryInterface,
314
+ insertItem: InsertCartItemResponse,
315
+ pendingAdd?: PendingCartAdd
316
+ ): BasketSummaryInterface {
317
+ const items = [...(cart.items || [])];
318
+ const targetQuantity = Math.max(Number(pendingAdd?.quantity || 0), Number(insertItem.quantity || 1));
319
+
320
+ const index = items.findIndex((item) => {
321
+ if (String(item.id) === `optimistic-${cartLineKey(insertItem.productId, insertItem.variantId)}`) {
322
+ return true;
323
+ }
324
+
325
+ const sameProduct = String(item.productId) === String(insertItem.productId);
326
+ const itemVariantId = item.variant?.id ?? item.variantId ?? '';
327
+ const targetVariantId = insertItem.variantId ?? '';
328
+ return sameProduct && String(itemVariantId) === String(targetVariantId);
329
+ });
330
+
331
+ const unitPrice =
332
+ index >= 0
333
+ ? Number(items[index].linePay || 0) / (Number(items[index].quantity || 0) || 1)
334
+ : Number(pendingAdd?.linePay || 0) / (Number(pendingAdd?.quantity || 0) || 1);
335
+
336
+ const nextLine = {
337
+ ...(index >= 0
338
+ ? items[index]
339
+ : createOptimisticCartLine({
340
+ productId: insertItem.productId,
341
+ variantId: insertItem.variantId ?? undefined,
342
+ quantity: targetQuantity,
343
+ linePay: unitPrice * targetQuantity,
344
+ })),
345
+ id: insertItem.id,
346
+ productId: insertItem.productId,
347
+ variantId: insertItem.variantId ?? null,
348
+ variant: insertItem.variantId ? ({ id: insertItem.variantId } as BasketItemSummaryInterface['variant']) : null,
349
+ quantity: targetQuantity,
350
+ linePay: unitPrice * targetQuantity,
351
+ };
352
+
353
+ if (index >= 0) {
354
+ items[index] = nextLine;
355
+ } else {
356
+ items.push(nextLine);
357
+ }
358
+
359
+ return recalcCartTotals(cart, items);
360
+ }
361
+
362
+ export function patchCartItemQuantity(
363
+ cart: BasketSummaryInterface,
364
+ itemId: string,
365
+ quantity: number,
366
+ productId?: string,
367
+ variantId?: string | number | null
368
+ ): BasketSummaryInterface {
369
+ if (!cart.items?.length) return cart;
370
+
371
+ let targetId = itemId;
372
+ const hasTarget = cart.items.some((item) => String(item.id) === itemId);
373
+
374
+ if (!hasTarget && productId) {
375
+ const line = findCartLine(cart, productId, variantId);
376
+ if (line) targetId = String(line.id);
377
+ }
378
+
379
+ if (!cart.items.some((item) => String(item.id) === targetId)) return cart;
380
+
381
+ let priceDiff = 0;
382
+ const updatedItems = cart.items.map((item) => {
383
+ if (String(item.id) !== targetId) return item;
384
+
385
+ const oldQty = Number(item.quantity || 0);
386
+ const unitPrice = Number(item.linePay || 0) / (oldQty || 1);
387
+ priceDiff = (quantity - oldQty) * unitPrice;
388
+
389
+ return {
390
+ ...item,
391
+ quantity,
392
+ linePay: quantity * unitPrice,
393
+ };
394
+ });
395
+
396
+ const newGesamt = updatedItems.reduce((sum, item) => sum + Number(item.quantity || 0), 0);
397
+
398
+ return {
399
+ ...cart,
400
+ items: updatedItems,
401
+ info: {
402
+ ...cart.info,
403
+ count: {
404
+ ...cart.info?.count,
405
+ Gesamt: newGesamt,
406
+ Artikel: updatedItems.length,
407
+ },
408
+ payPrice: {
409
+ ...cart.info?.payPrice,
410
+ total: Number(cart.info?.payPrice?.total || 0) + priceDiff,
411
+ pay: Number(cart.info?.payPrice?.pay || 0) + priceDiff,
412
+ },
413
+ },
414
+ };
415
+ }
416
+
417
+ export function applyPendingQuantities(
418
+ cart: BasketSummaryInterface,
419
+ pendingQuantities: Record<string, number>
420
+ ): BasketSummaryInterface {
421
+ return Object.entries(pendingQuantities).reduce(
422
+ (acc, [itemId, quantity]) => patchCartItemQuantity(acc, itemId, quantity),
423
+ cart
424
+ );
425
+ }
@@ -0,0 +1,27 @@
1
+ const GARANTI_PAYMENT_HTML_KEY_PREFIX = 'payment:garanti:';
2
+
3
+ export function storeGarantiPaymentHtml(transactionId: string, html: string) {
4
+ if (typeof window === 'undefined') return;
5
+ sessionStorage.setItem(`${GARANTI_PAYMENT_HTML_KEY_PREFIX}${transactionId}`, html);
6
+ }
7
+
8
+ export function consumeGarantiPaymentHtml(transactionId: string): string | null {
9
+ if (typeof window === 'undefined') return null;
10
+ const key = `${GARANTI_PAYMENT_HTML_KEY_PREFIX}${transactionId}`;
11
+ const html = sessionStorage.getItem(key);
12
+ if (html) {
13
+ sessionStorage.removeItem(key);
14
+ }
15
+ return html;
16
+ }
17
+
18
+ export function submitGarantiPaymentHtml(html: string) {
19
+ const wrapper = document.createElement('div');
20
+ wrapper.innerHTML = html;
21
+ const form = wrapper.querySelector('form');
22
+ if (!(form instanceof HTMLFormElement)) {
23
+ throw new Error('Garanti ödeme formu bulunamadı.');
24
+ }
25
+ document.body.appendChild(form);
26
+ form.submit();
27
+ }
@@ -0,0 +1,32 @@
1
+ import { nexineAxios } from "@/core/util/nexine.axios";
2
+ import { IData } from "@/core/interface/nexine.interface";
3
+ import { Address, Campaign, Collection, Order, PromoCode } from "@/core/interface/prisma.interface";
4
+ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
5
+
6
+ export const useCollection = () => {
7
+
8
+ const queryClient = useQueryClient();
9
+
10
+ return {
11
+ fetch : (params?: any) => {
12
+ return useQuery({
13
+ queryKey: ['web','collection','list',params],
14
+ queryFn: async () => {
15
+ var response = await nexineAxios.get<IData<Collection>>(`/customer/collection`, {
16
+ params: params
17
+ })
18
+ return response.data;
19
+ },
20
+ })
21
+ },
22
+ detail : (id:string) => {
23
+ return useQuery({
24
+ queryKey: ['web','collection','detail',id],
25
+ queryFn: async () => {
26
+ var response = await nexineAxios.get<Collection>(`/customer/collection/${id}`)
27
+ return response.data;
28
+ },
29
+ })
30
+ }
31
+ }
32
+ };
@@ -0,0 +1,40 @@
1
+ import { nexineAxios } from '@/core/util/nexine.axios';
2
+ import { IData } from '@/core/interface/nexine.interface';
3
+ import { DeliveryMethod } from '@/core/interface/prisma.interface';
4
+ import { useQuery } from '@tanstack/react-query';
5
+ import { getCheckoutDeliveryMethods } from '@/core/feature/delivery-method/util/checkout.delivery.method';
6
+
7
+ async function fetchDeliveryMethods() {
8
+ const withTags = await nexineAxios.get<IData<DeliveryMethod>>('/customer/delivery/method', {
9
+ params: {
10
+ isCompanySpecificVisible: true,
11
+ tags: ['WEB'],
12
+ },
13
+ });
14
+
15
+ const tagged = withTags.data?.data ?? [];
16
+ if (tagged.length > 0) {
17
+ return { ...withTags.data, data: getCheckoutDeliveryMethods(tagged) };
18
+ }
19
+
20
+ const fallback = await nexineAxios.get<IData<DeliveryMethod>>('/customer/delivery/method', {
21
+ params: {
22
+ isCompanySpecificVisible: true,
23
+ },
24
+ });
25
+
26
+ const methods = fallback.data?.data ?? [];
27
+ return { ...fallback.data, data: getCheckoutDeliveryMethods(methods) };
28
+ }
29
+
30
+ export const useDeliveryMethod = () => {
31
+ return {
32
+ fetch: (opts?: { enabled?: boolean }) => {
33
+ return useQuery({
34
+ queryKey: ['delivery-method', 'web'],
35
+ queryFn: fetchDeliveryMethods,
36
+ enabled: opts?.enabled !== false,
37
+ });
38
+ },
39
+ };
40
+ };
@@ -0,0 +1,11 @@
1
+ import { DeliveryMethod } from '@/core/interface/prisma.interface';
2
+
3
+ export function isCashDeskDeliveryMethod(method: Pick<DeliveryMethod, 'name'>): boolean {
4
+ const name = method.name.toLowerCase();
5
+ return name.includes('kasadan') || name.includes('cash desk');
6
+ }
7
+
8
+ /** Web checkout'ta gösterilecek kargo yöntemleri (kasadan satış hariç). */
9
+ export function getCheckoutDeliveryMethods(methods: DeliveryMethod[]): DeliveryMethod[] {
10
+ return methods.filter((m) => !isCashDeskDeliveryMethod(m));
11
+ }
@@ -0,0 +1,23 @@
1
+ import { nexineAxios } from "@/core/util/nexine.axios";
2
+ import { IData } from "@/core/interface/nexine.interface";
3
+ import { Brand, Category, Faq } from "@/core/interface/prisma.interface";
4
+ import { useQuery } from "@tanstack/react-query";
5
+
6
+ export const useFaq = () => {
7
+ return {
8
+ fetch: (params: { page: number, amount: number }) => {
9
+ return useQuery({
10
+ queryKey: ["faq"],
11
+ queryFn: async ( ) => {
12
+ var response = await nexineAxios.get<IData<Faq>>("/customer/faq", {
13
+ params: {
14
+ page: params.page,
15
+ amount: params.amount
16
+ }
17
+ });
18
+ return response.data;
19
+ },
20
+ });
21
+ },
22
+ };
23
+ };
@@ -0,0 +1,48 @@
1
+ import { nexineAxios } from "@/core/util/nexine.axios";
2
+ import { IData } from "@/core/interface/nexine.interface";
3
+ import { Favorite } from "@/core/interface/prisma.interface";
4
+ import { useMutation, useQuery, useQueryClient, UseQueryOptions } from "@tanstack/react-query";
5
+ import toast from "react-hot-toast";
6
+
7
+ export interface FavoriteListResponse extends IData<Favorite> {
8
+ info?: {
9
+ count?: {
10
+ Artikel?: number;
11
+ };
12
+ };
13
+ }
14
+
15
+ export const useFavorite = () => {
16
+
17
+ const queryClient = useQueryClient();
18
+
19
+ return {
20
+ list: (params?: Record<string, unknown>, options?: Omit<UseQueryOptions<FavoriteListResponse>, 'queryKey' | 'queryFn'>) => {
21
+ return useQuery<FavoriteListResponse>({
22
+ queryKey: ['favorite', 'list', params],
23
+ queryFn: async () => {
24
+ const response = await nexineAxios.get<FavoriteListResponse>('/customer/favorite', { params });
25
+ return response.data;
26
+ },
27
+ ...options
28
+ });
29
+ },
30
+ toggle: () => {
31
+ return useMutation({
32
+ mutationFn: async (data: { productId: string }) => {
33
+ const response = await nexineAxios.post('/customer/favorite', data);
34
+ return response.data;
35
+ },
36
+ onSuccess: (data, variables) => {
37
+ queryClient.invalidateQueries({ queryKey: ['product'] });
38
+ queryClient.invalidateQueries({ queryKey: ['campaign'] });
39
+ queryClient.invalidateQueries({ queryKey: ['favorite'] });
40
+ toast.success('Favori durumu güncellendi');
41
+ },
42
+ onError: () => {
43
+ toast.error('Favori işlemi başarısız oldu');
44
+ }
45
+ });
46
+ },
47
+ };
48
+ };