@raxonltd/raxon-core 1.0.8 → 1.1.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/README.md ADDED
@@ -0,0 +1,758 @@
1
+ # @raxonltd/raxon-core
2
+
3
+ **Raxon e-ticaret altyapısı için React / Next.js SDK'sı.**
4
+
5
+ Mağaza bootstrap verisi, kimlik doğrulama, sepet yönetimi, ödeme akışı, ürün listeleme ve analitik olaylarını tek bir pakette sunar. [TanStack Query](https://tanstack.com/query) tabanlı hook'lar ve hazır UI bileşenleriyle hızlı entegrasyon sağlar.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@raxonltd/raxon-core.svg)](https://www.npmjs.com/package/@raxonltd/raxon-core)
8
+ [![license](https://img.shields.io/npm/l/@raxonltd/raxon-core.svg)](https://github.com/raxonltd/raxon-core/blob/main/LICENSE)
9
+
10
+ ---
11
+
12
+ ## İçindekiler
13
+
14
+ - [Özellikler](#özellikler)
15
+ - [Gereksinimler](#gereksinimler)
16
+ - [Kurulum](#kurulum)
17
+ - [Hızlı Başlangıç](#hızlı-başlangıç)
18
+ - [Paket Yapısı](#paket-yapısı)
19
+ - [RaxonProvider](#raxonprovider)
20
+ - [useRaxon — Global Context](#useraxon--global-context)
21
+ - [Hook'lar](#hooklar)
22
+ - [Hazır Görünümler](#hazır-görünümler)
23
+ - [Analitik](#analitik)
24
+ - [Kimlik Doğrulama](#kimlik-doğrulama)
25
+ - [Sepet Yönetimi](#sepet-yönetimi)
26
+ - [TypeScript Arayüzleri](#typescript-arayüzleri)
27
+ - [Ortam Değişkenleri](#ortam-değişkenleri)
28
+ - [Next.js Entegrasyonu](#nextjs-entegrasyonu)
29
+ - [Geliştirme](#geliştirme)
30
+
31
+ ---
32
+
33
+ ## Özellikler
34
+
35
+ | Alan | Açıklama |
36
+ |------|----------|
37
+ | **Bootstrap** | Kategori, koleksiyon, kampanya, marka, ödeme/teslimat yöntemleri tek istekle yüklenir |
38
+ | **Kimlik doğrulama** | E-posta, misafir ve sosyal giriş; kayıt, şifre sıfırlama |
39
+ | **Sepet** | Optimistic güncelleme, debounce'lu miktar değişimi, çoklu ödeme sağlayıcısı |
40
+ | **Ürünler** | Listeleme, arama, detay, ilişkili ürünler |
41
+ | **Ödeme** | PayTR, Stripe, GarantiPay, kapıda ödeme, havale |
42
+ | **Hazır checkout** | Adres, fatura, promo kod ve ödeme adımlarını içeren tam sayfa bileşeni |
43
+ | **Analitik** | Ürün görüntüleme/tıklama ve e-posta kampanya takibi |
44
+ | **TypeScript** | Tam tip desteği |
45
+
46
+ ---
47
+
48
+ ## Gereksinimler
49
+
50
+ - **React** `19.x`
51
+ - **Next.js** `16.x` (App Router — `view` modülü için)
52
+ - **Node.js** `20+` (geliştirme ortamı)
53
+
54
+ Paket aşağıdaki bağımlılıkları kendi içinde getirir; ek kurulum gerekmez:
55
+
56
+ `@tanstack/react-query`, `axios`, `react-hook-form`, `zod`, `rizzui`, `lucide-react`, `react-hot-toast`
57
+
58
+ ---
59
+
60
+ ## Kurulum
61
+
62
+ ```bash
63
+ npm install @raxonltd/raxon-core
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Hızlı Başlangıç
69
+
70
+ ### 1. Provider'ı sarın
71
+
72
+ ```tsx
73
+ // app/layout.tsx
74
+ 'use client';
75
+
76
+ import { RaxonProvider } from '@raxonltd/raxon-core';
77
+ import { Toaster } from 'react-hot-toast';
78
+
79
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
80
+ return (
81
+ <html lang="tr">
82
+ <body>
83
+ <RaxonProvider
84
+ apiKey={process.env.NEXT_PUBLIC_API_KEY!}
85
+ apiUrl={process.env.NEXT_PUBLIC_API_URL!}
86
+ productPathPrefix="/urunler"
87
+ analyticAutoTrack
88
+ >
89
+ {children}
90
+ </RaxonProvider>
91
+ <Toaster position="top-right" />
92
+ </body>
93
+ </html>
94
+ );
95
+ }
96
+ ```
97
+
98
+ ### 2. Bootstrap verisini kullanın
99
+
100
+ ```tsx
101
+ 'use client';
102
+
103
+ import { useRaxon } from '@raxonltd/raxon-core';
104
+
105
+ export function Header() {
106
+ const { category, brand, isLoading, cartTotal, addToCart } = useRaxon();
107
+
108
+ if (isLoading) return <div>Yükleniyor...</div>;
109
+
110
+ return (
111
+ <header>
112
+ <nav>{category.map((c) => <a key={c.id} href={`/kategori/${c.slug}`}>{c.name}</a>)}</nav>
113
+ <span>Sepet: {cartTotal} ₺</span>
114
+ </header>
115
+ );
116
+ }
117
+ ```
118
+
119
+ ### 3. Hook ile veri çekin
120
+
121
+ ```tsx
122
+ 'use client';
123
+
124
+ import { useProduct } from '@raxonltd/raxon-core/hook';
125
+
126
+ export function ProductList({ categoryId }: { categoryId: string }) {
127
+ const { fetch } = useProduct();
128
+ const { data, isLoading } = fetch({ categoryId, page: 1, amount: 24 });
129
+
130
+ if (isLoading) return <p>Yükleniyor...</p>;
131
+
132
+ return (
133
+ <ul>
134
+ {data?.data.map((product) => (
135
+ <li key={product.id}>{product.name}</li>
136
+ ))}
137
+ </ul>
138
+ );
139
+ }
140
+ ```
141
+
142
+ ---
143
+
144
+ ## Paket Yapısı
145
+
146
+ Paket dört giriş noktası sunar:
147
+
148
+ | Import yolu | İçerik |
149
+ |-------------|--------|
150
+ | `@raxonltd/raxon-core` | `RaxonProvider`, `useRaxon`, `nexineAxios`, analitik |
151
+ | `@raxonltd/raxon-core/hook` | Tüm veri hook'ları |
152
+ | `@raxonltd/raxon-core/view` | Hazır sayfa bileşenleri |
153
+ | `@raxonltd/raxon-core/interface/*` | TypeScript arayüzleri |
154
+
155
+ ```ts
156
+ // Ana modül
157
+ import {
158
+ RaxonProvider,
159
+ useRaxon,
160
+ nexineAxios,
161
+ AnalyticEventProvider,
162
+ useAnalyticEvent,
163
+ } from '@raxonltd/raxon-core';
164
+
165
+ // Hook'lar
166
+ import { useProduct, useCart, useAuth } from '@raxonltd/raxon-core/hook';
167
+
168
+ // Görünümler
169
+ import { CheckoutView } from '@raxonltd/raxon-core/view';
170
+
171
+ // Tipler
172
+ import type { Product, Brand, Order } from '@raxonltd/raxon-core/interface/prisma.interface';
173
+ import type { IData } from '@raxonltd/raxon-core/interface/nexine.interface';
174
+ ```
175
+
176
+ ---
177
+
178
+ ## RaxonProvider
179
+
180
+ Uygulamanın kökünde bir kez sarılmalıdır. Şunları yapılandırır:
181
+
182
+ - Axios istemcisi (`nexineAxios`) — `baseURL` ve `x-api-key` header
183
+ - TanStack Query `QueryClient`
184
+ - Bootstrap verisi (`/customer/bootstrap`)
185
+ - Kimlik doğrulama durumu
186
+ - Sepet state'i (optimistic)
187
+ - Giriş ve bülten modalları
188
+ - Analitik sağlayıcı
189
+
190
+ ### Props
191
+
192
+ | Prop | Tip | Zorunlu | Açıklama |
193
+ |------|-----|---------|----------|
194
+ | `apiKey` | `string` | Evet | Mağaza API anahtarı (`x-api-key`) |
195
+ | `apiUrl` | `string` | Evet | Backend temel URL'i |
196
+ | `productPathPrefix` | `string` | Hayır | Ürün URL öneki (analitik için, varsayılan: `/urunler`) |
197
+ | `analyticAutoTrack` | `boolean` | Hayır | Otomatik ürün görüntüleme takibi |
198
+
199
+ ```tsx
200
+ <RaxonProvider
201
+ apiKey="your-api-key"
202
+ apiUrl="https://api.example.com"
203
+ productPathPrefix="/urunler"
204
+ analyticAutoTrack
205
+ >
206
+ {children}
207
+ </RaxonProvider>
208
+ ```
209
+
210
+ ### Mimari
211
+
212
+ ```mermaid
213
+ flowchart TB
214
+ subgraph Provider["RaxonProvider"]
215
+ QC[QueryClientProvider]
216
+ subgraph Inner["RaxonProviderInner"]
217
+ Bootstrap["/customer/bootstrap"]
218
+ Security[SecurityContext]
219
+ Cart[CartState]
220
+ Analytics[AnalyticEventProvider]
221
+ end
222
+ end
223
+
224
+ QC --> Inner
225
+ Bootstrap --> useRaxon
226
+ Security --> useRaxon
227
+ Cart --> useRaxon
228
+ Analytics --> useAnalyticEvent
229
+ ```
230
+
231
+ ---
232
+
233
+ ## useRaxon — Global Context
234
+
235
+ `RaxonProvider` altında `useRaxon()` ile erişilen merkezi state.
236
+
237
+ ### Bootstrap verileri
238
+
239
+ | Alan | Tip | Açıklama |
240
+ |------|-----|----------|
241
+ | `category` | `Category[]` | Hiyerarşik kategori ağacı |
242
+ | `flatCategory` | `Category[]` | Düzleştirilmiş kategori listesi |
243
+ | `collection` | `Collection[]` | Tüm koleksiyonlar |
244
+ | `banner` | `Collection[]` | `banner` etiketli koleksiyonlar |
245
+ | `subHeroCollection` | `Collection[]` | Alt hero koleksiyonları |
246
+ | `brand` | `Brand[]` | Markalar |
247
+ | `product` | `Product[]` | Öne çıkan ürünler |
248
+ | `bestSeller` | `Product[]` | Çok satanlar |
249
+ | `campaign` | `Campaign[]` | Kampanyalar |
250
+ | `basketCampaign` | `Campaign[]` | Sepet kampanyaları (koleksiyon hariç) |
251
+ | `paymentMethod` | `PaymentMethod[]` | Ödeme yöntemleri |
252
+ | `deliveryMethod` | `DeliveryMethod[]` | Teslimat yöntemleri |
253
+ | `defaultDeliveryMethod` | `DeliveryMethod \| null` | Varsayılan teslimat |
254
+ | `bankAccount` | `BankAccount[]` | Havale hesapları |
255
+ | `article` | `Article[]` | Blog / içerik |
256
+ | `faq` | `Faq[]` | SSS |
257
+ | `review` | `Review[]` | Yorumlar |
258
+ | `feed` | `Feed[]` | Feed verileri |
259
+ | `material` | `Material[]` | Materyaller |
260
+ | `holiday` | `Holiday[]` | Tatil günleri |
261
+ | `dynamicData` | `DynamicData[]` | Dinamik CMS verileri |
262
+ | `branch` | `Branch \| null` | Şube bilgisi |
263
+ | `isLoading` | `boolean` | Bootstrap yükleniyor mu |
264
+
265
+ ### Kimlik doğrulama
266
+
267
+ | Alan | Tip | Açıklama |
268
+ |------|-----|----------|
269
+ | `profile` | `User \| null \| undefined` | Oturum açmış kullanıcı |
270
+ | `authLoading` | `boolean` | Auth kontrolü devam ediyor |
271
+ | `isAuthenticated` | `boolean` | Giriş yapılmış mı |
272
+ | `isGuest` | `boolean` | Misafir oturumu mu |
273
+
274
+ ### Sepet (CartState)
275
+
276
+ | Alan / Metod | Açıklama |
277
+ |--------------|----------|
278
+ | `cart` | Güncel sepet özeti (`BasketSummaryInterface`) |
279
+ | `cartLoading` | Sepet yükleniyor |
280
+ | `cartTotal` | Toplam tutar |
281
+ | `addToCart(productId, quantity, variantId?)` | Ürün ekle (optimistic) |
282
+ | `updateQuantity(itemId, quantity)` | Miktar güncelle |
283
+ | `changeQuantity(itemId, delta)` | Miktar artır/azalt |
284
+ | `removeItem(itemId)` | Kalemi kaldır |
285
+ | `isProductAdding(productId, variantId?)` | Ekleme işlemi devam ediyor mu |
286
+ | `promoCode` / `setPromoCode` | Aktif promo kodu |
287
+
288
+ ### Modal referansları
289
+
290
+ ```tsx
291
+ const { modalAuthRef, modalNewsletterVariantProductRef } = useRaxon();
292
+
293
+ // Giriş modalını aç
294
+ modalAuthRef.current?.open();
295
+ ```
296
+
297
+ ---
298
+
299
+ ## Hook'lar
300
+
301
+ Tüm hook'lar `@raxonltd/raxon-core/hook` üzerinden import edilir. Her hook bir nesne döndürür; metodlar `useQuery` veya `useMutation` sonucu verir.
302
+
303
+ > **Kullanım kalıbı:** Hook'u bileşen gövdesinde çağırın, dönen metodu da aynı gövdede çağırın (React kuralları).
304
+
305
+ ```tsx
306
+ const { fetch } = useProduct();
307
+ const query = fetch({ categoryId: 'abc', page: 1 }); // useQuery sonucu
308
+ ```
309
+
310
+ ---
311
+
312
+ ### `useAuth`
313
+
314
+ Kimlik doğrulama işlemleri.
315
+
316
+ | Metod | Tip | Endpoint | Açıklama |
317
+ |-------|-----|----------|----------|
318
+ | `profile({ isEnabled })` | Query | `GET /customer/profile` | Profil bilgisi |
319
+ | `token()` | Mutation | `GET /auth/token` | Token al |
320
+ | `loginEmail()` | Mutation | `POST /auth/login/email` | E-posta ile giriş |
321
+ | `loginGuest()` | Mutation | `POST /auth/login/guest` | Misafir girişi |
322
+ | `loginSocial()` | Mutation | `GET /auth/login/social` | Sosyal giriş URL'i |
323
+ | `register()` | Mutation | `POST /auth/register` | Kayıt |
324
+ | `codeSend()` | Mutation | `POST /auth/code-send` | Şifre sıfırlama kodu |
325
+ | `verifyCode()` | Mutation | `POST /auth/code-verify` | Kod doğrulama |
326
+ | `resetPassword()` | Mutation | `POST /auth/reset-password` | Şifre sıfırlama |
327
+ | `logout()` | Fonksiyon | — | Token temizle ve yenile |
328
+
329
+ **Olaylar:** `LOGIN_SUCCESS_EVENT`, `LOGOUT_EVENT` — `window` üzerinde dinlenebilir.
330
+
331
+ ```tsx
332
+ const { loginEmail, logout } = useAuth();
333
+ const login = loginEmail();
334
+
335
+ login.mutate({ email: 'user@example.com', password: '***' });
336
+ ```
337
+
338
+ ---
339
+
340
+ ### `useProduct`
341
+
342
+ Ürün listeleme, arama ve detay.
343
+
344
+ | Metod | Açıklama |
345
+ |-------|----------|
346
+ | `fetch(params)` | Filtrelenmiş ürün listesi |
347
+ | `searchData(search)` | Canlı arama (min. 3 karakter) |
348
+ | `detail(slug)` | Ürün detayı |
349
+ | `related(productId)` | İlişkili ürünler |
350
+
351
+ **`fetch` parametreleri (öne çıkanlar):**
352
+
353
+ ```ts
354
+ {
355
+ categoryId?: string;
356
+ subCategoryId?: string;
357
+ brandId?: string[];
358
+ search?: string;
359
+ page?: number;
360
+ amount?: number; // varsayılan sayfa boyutu: 24
361
+ sortBy?: string;
362
+ collectionId?: string;
363
+ attributeOptionId?: string[];
364
+ minPrice?: number;
365
+ maxPrice?: number;
366
+ isFavorite?: boolean;
367
+ enabled?: boolean;
368
+ }
369
+ ```
370
+
371
+ ---
372
+
373
+ ### `useCart`
374
+
375
+ Sepet CRUD ve ödeme mutasyonları.
376
+
377
+ | Metod | Endpoint | Açıklama |
378
+ |-------|----------|----------|
379
+ | `fetch({ isEnabled, promoCodeId, campaignId, deliveryMethodId })` | `GET /customer/basket/me` | Sepet özeti |
380
+ | `insert()` | `POST /customer/basket/me/item` | Ürün ekle |
381
+ | `updateItem()` | `PUT /customer/basket/me/item` | Miktar güncelle |
382
+ | `remove()` | `DELETE /customer/basket/me/item/:id` | Kalem sil |
383
+ | `bulkInsert()` | `PATCH /customer/basket/me/item` | Toplu güncelleme |
384
+ | `update()` | `PUT /customer/basket` | Adres, ödeme, promo kod |
385
+ | `pay()` | `POST /customer/basket/me/pay` | Genel ödeme |
386
+ | `generatePaymentUrl()` | `POST /customer/basket/pay/paytr` | PayTR |
387
+ | `generateStripePaymentIntent()` | `POST /customer/basket/pay/stripe` | Stripe |
388
+ | `generateCashOnDeliveryPayment()` | `POST /customer/basket/pay/cash-on-delivery` | Kapıda ödeme |
389
+ | `createTransferCode()` | `POST /customer/payment/bank-transfer` | Havale kodu |
390
+
391
+ > Günlük sepet işlemleri için `useRaxon()` içindeki `addToCart`, `changeQuantity` gibi metodları tercih edin; bunlar optimistic güncelleme içerir.
392
+
393
+ ---
394
+
395
+ ### `useBrand`
396
+
397
+ Marka listesi (sadece okuma).
398
+
399
+ ```tsx
400
+ const { fetch } = useBrand();
401
+ const { data } = fetch({ page: 1, amount: 50, enabled: true });
402
+ // data: IData<Brand> → { data: Brand[], count: number }
403
+ ```
404
+
405
+ ---
406
+
407
+ ### `useCollection`
408
+
409
+ | Metod | Endpoint |
410
+ |-------|----------|
411
+ | `fetch(params?)` | `GET /customer/collection` |
412
+ | `detail(id)` | `GET /customer/collection/:id` |
413
+
414
+ ---
415
+
416
+ ### `useArticle`
417
+
418
+ | Metod | Endpoint |
419
+ |-------|----------|
420
+ | `fetch(params?)` | `GET /customer/article` |
421
+ | `detail(id)` | `GET /customer/article/:id` |
422
+
423
+ ---
424
+
425
+ ### `useFaq`
426
+
427
+ | Metod | Endpoint |
428
+ |-------|----------|
429
+ | `fetch({ page, amount })` | `GET /customer/faq` |
430
+
431
+ ---
432
+
433
+ ### `useAttribute`
434
+
435
+ | Metod | Endpoint |
436
+ |-------|----------|
437
+ | `fetch({ categoryId?, productId?, enabled? })` | `GET /customer/attribute` |
438
+
439
+ ---
440
+
441
+ ### `useAddress`
442
+
443
+ | Metod | Endpoint |
444
+ |-------|----------|
445
+ | `fetch()` | `GET /customer/address` |
446
+ | `detail(id)` | `GET /customer/address/:id` |
447
+ | `create()` | `POST /customer/address` |
448
+ | `update()` | `PUT /customer/address` |
449
+ | `delete()` | `DELETE /customer/address/:id` |
450
+
451
+ ---
452
+
453
+ ### `useAddressAutocomplete`
454
+
455
+ Google Places tabanlı adres arama (host uygulamada `/api/places/autocomplete` route'u gerekir).
456
+
457
+ ```tsx
458
+ const { query, setQuery, results, selectPlace, isSearching } = useAddressAutocomplete();
459
+ ```
460
+
461
+ ---
462
+
463
+ ### `useProfile`
464
+
465
+ | Metod | Endpoint |
466
+ |-------|----------|
467
+ | `fetch({ isEnabled })` | `GET /customer/profile` |
468
+ | `update()` | `PUT /customer/profile` |
469
+ | `verifyPhoneNumber()` | `POST /customer/profile/verify/phone` |
470
+ | `verifyEmail()` | `POST /customer/profile/verify/email` |
471
+ | `fetchCompany({ enabled })` | `GET /customer/profile/company` |
472
+ | `applyCompany()` | `POST /customer/profile/company` |
473
+ | `uploadCompanyDocument()` | `POST /customer/profile/company/document` |
474
+
475
+ ---
476
+
477
+ ### `useOrder`
478
+
479
+ | Metod | Endpoint |
480
+ |-------|----------|
481
+ | `fetch()` | `GET /customer/order` |
482
+ | `detail(id)` | `GET /customer/order/:id` |
483
+
484
+ ---
485
+
486
+ ### `useInvoice`
487
+
488
+ | Metod | Endpoint |
489
+ |-------|----------|
490
+ | `fetch()` | `GET /customer/invoice` |
491
+ | `detail(id)` | `GET /customer/invoice/:id` |
492
+ | `download()` | `GET /customer/invoice/:id/download` |
493
+ | `downloadByOrder()` | `GET /customer/invoice/order/:orderId/download` |
494
+
495
+ ---
496
+
497
+ ### `useFavorite`
498
+
499
+ | Metod | Endpoint |
500
+ |-------|----------|
501
+ | `list(params?, options?)` | `GET /customer/favorite` |
502
+ | `toggle()` | `POST /customer/favorite` |
503
+
504
+ ---
505
+
506
+ ### `useNewsletter`
507
+
508
+ | Metod | Endpoint |
509
+ |-------|----------|
510
+ | `subscribe` | `POST /customer/newsletter/subscribe` |
511
+ | `subscribeByVariant` | `POST /customer/newsletter/subscribe/variant` |
512
+
513
+ ---
514
+
515
+ ### `usePromoCode`
516
+
517
+ | Metod | Endpoint |
518
+ |-------|----------|
519
+ | `fetch({ status? })` | `GET /customer/promo-code` |
520
+ | `findByCode()` | `GET /customer/promo-code/:code` |
521
+
522
+ ---
523
+
524
+ ### `usePaymentMethod`
525
+
526
+ | Metod | Endpoint |
527
+ |-------|----------|
528
+ | `fetch({ enabled? })` | `GET /customer/payment/method` |
529
+
530
+ WEB etiketli yöntemlerle etiketsiz yöntemleri birleştirir.
531
+
532
+ ---
533
+
534
+ ### `useDeliveryMethod`
535
+
536
+ | Metod | Endpoint |
537
+ |-------|----------|
538
+ | `fetch({ enabled? })` | `GET /customer/delivery/method` |
539
+
540
+ ---
541
+
542
+ ### `useBankAccount`
543
+
544
+ | Metod | Endpoint |
545
+ |-------|----------|
546
+ | `fetch({ enabled? })` | `GET /customer/bank-account` |
547
+ | `createTransferCode()` | `POST /customer/payment/bank-transfer` |
548
+
549
+ ---
550
+
551
+ ### `useFormSubmit`
552
+
553
+ | Metod | Endpoint |
554
+ |-------|----------|
555
+ | `create()` | `POST /customer/form/submit` |
556
+
557
+ ---
558
+
559
+ ## Hazır Görünümler
560
+
561
+ `@raxonltd/raxon-core/view` modülünden import edilir.
562
+
563
+ ### `CheckoutView`
564
+
565
+ Tam özellikli ödeme sayfası: iletişim, adres, fatura, teslimat/ödeme yöntemi seçimi, promo kod ve ödeme entegrasyonları.
566
+
567
+ ```tsx
568
+ // app/sepet/odeme/page.tsx
569
+ 'use client';
570
+
571
+ import { CheckoutView } from '@raxonltd/raxon-core/view';
572
+
573
+ export default function OdemePage() {
574
+ return <CheckoutView webReturnUrl="/sepet/odeme" />;
575
+ }
576
+ ```
577
+
578
+ | Prop | Tip | Varsayılan | Açıklama |
579
+ |------|-----|------------|----------|
580
+ | `webReturnUrl` | `string` | `/sepet/odeme` | Ödeme sonrası dönüş URL'i |
581
+
582
+ ---
583
+
584
+ ## Analitik
585
+
586
+ `RaxonProvider` içinde `AnalyticEventProvider` otomatik etkinleşir.
587
+
588
+ ```tsx
589
+ import { useAnalyticEvent } from '@raxonltd/raxon-core';
590
+
591
+ function ProductCard({ productId, variantId }: { productId: string; variantId?: string }) {
592
+ const { trackProductView, trackProductClick } = useAnalyticEvent();
593
+
594
+ return (
595
+ <div
596
+ onMouseEnter={() => trackProductView({ productId, variantId })}
597
+ onClick={() => trackProductClick({ productId, variantId })}
598
+ >
599
+ ...
600
+ </div>
601
+ );
602
+ }
603
+ ```
604
+
605
+ | Metod | Açıklama |
606
+ |-------|----------|
607
+ | `trackProductView` | Ürün görüntüleme (2 sn buffer ile toplu gönderim) |
608
+ | `trackProductClick` | Ürün tıklama |
609
+ | `trackEmailClicked` | E-posta kampanya tıklaması (`tcx` parametresi) |
610
+
611
+ `analyticAutoTrack={true}` ile URL'deki ürün sayfaları otomatik izlenir (`productPathPrefix` ile yapılandırılır).
612
+
613
+ ---
614
+
615
+ ## Kimlik Doğrulama
616
+
617
+ Token `localStorage` içinde `koksal-token` anahtarıyla saklanır. `nexineAxios` her istekte `Authorization: Bearer <token>` header'ını otomatik ekler.
618
+
619
+ **Akış:**
620
+
621
+ 1. `loginEmail` / `loginGuest` / `loginSocial` ile giriş
622
+ 2. Token localStorage'a yazılır
623
+ 3. `LOGIN_SUCCESS_EVENT` tetiklenir
624
+ 4. Profil ve sepet sorguları invalidate edilir
625
+ 5. 401 yanıtında token temizlenir ve toast gösterilir
626
+
627
+ ```tsx
628
+ // Giriş sonrası dinleme
629
+ useEffect(() => {
630
+ const handler = () => router.refresh();
631
+ window.addEventListener('intermarkt-login-success', handler);
632
+ return () => window.removeEventListener('intermarkt-login-success', handler);
633
+ }, []);
634
+ ```
635
+
636
+ ---
637
+
638
+ ## Sepet Yönetimi
639
+
640
+ İki katman vardır:
641
+
642
+ 1. **`useRaxon()` sepet API'si** — UI için optimistic, debounce'lu; günlük kullanımda bunu tercih edin
643
+ 2. **`useCart()` hook'u** — Düşük seviye; checkout ve özel akışlar için
644
+
645
+ ```tsx
646
+ const { addToCart, cart, cartTotal, isProductAdding } = useRaxon();
647
+
648
+ <button
649
+ onClick={() => addToCart(product.id, 1, variantId)}
650
+ disabled={isProductAdding(product.id, variantId)}
651
+ >
652
+ Sepete Ekle
653
+ </button>
654
+ ```
655
+
656
+ Optimistic güncelleme: kullanıcı arayüzü anında güncellenir, arka planda API çağrısı yapılır; hata durumunda geri alınır.
657
+
658
+ ---
659
+
660
+ ## TypeScript Arayüzleri
661
+
662
+ ```ts
663
+ import type { Brand, Product, Order, Cart } from '@raxonltd/raxon-core/interface/prisma.interface';
664
+ import type { ProductDetail } from '@raxonltd/raxon-core/interface/product.interface';
665
+ import type { BasketSummaryInterface } from '@raxonltd/raxon-core/interface/basket.interface';
666
+ import type { IData } from '@raxonltd/raxon-core/interface/nexine.interface';
667
+ ```
668
+
669
+ ### `IData<T>` — Sayfalanmış liste yanıtı
670
+
671
+ ```ts
672
+ interface IData<T> {
673
+ data: T[];
674
+ count: number;
675
+ }
676
+ ```
677
+
678
+ ---
679
+
680
+ ## Ortam Değişkenleri
681
+
682
+ | Değişken | Açıklama |
683
+ |----------|----------|
684
+ | `NEXT_PUBLIC_API_KEY` | API anahtarı (SSR / sunucu tarafı istekler için) |
685
+ | `NEXT_PUBLIC_API_URL` | API temel URL'i |
686
+
687
+ Client tarafında `RaxonProvider` bu değerleri `window.__RAXON_API_KEY__` ve `window.__RAXON_API_URL__` üzerinden de ayarlar.
688
+
689
+ ---
690
+
691
+ ## Next.js Entegrasyonu
692
+
693
+ ### `'use client'` zorunluluğu
694
+
695
+ `RaxonProvider`, hook'lar ve view bileşenleri client component gerektirir. Server Component içinde doğrudan kullanmayın.
696
+
697
+ ### Toast bildirimleri
698
+
699
+ `nexineAxios` başarılı/hatalı mutasyonlarda `react-hot-toast` kullanır. Layout'a `<Toaster />` ekleyin.
700
+
701
+ ### Adres otomatik tamamlama
702
+
703
+ `useAddressAutocomplete` host uygulamada şu route'u bekler:
704
+
705
+ ```
706
+ GET /api/places/autocomplete?input=...&components=country:tr&language=tr
707
+ ```
708
+
709
+ ### Özel axios istekleri
710
+
711
+ ```ts
712
+ import { nexineAxios } from '@raxonltd/raxon-core';
713
+
714
+ const response = await nexineAxios.get('/customer/custom-endpoint');
715
+ ```
716
+
717
+ ---
718
+
719
+ ## Geliştirme
720
+
721
+ ```bash
722
+ git clone https://github.com/raxonltd/raxon-core.git
723
+ cd raxon-core
724
+ npm install
725
+ npm run build
726
+ ```
727
+
728
+ ### Yayınlama
729
+
730
+ ```bash
731
+ npm version patch # veya minor / major
732
+ npm run build
733
+ npm publish
734
+ ```
735
+
736
+ ---
737
+
738
+ ## Sorun Giderme
739
+
740
+ | Sorun | Çözüm |
741
+ |-------|-------|
742
+ | `useRaxon must be used within a RaxonProvider` | Bileşeni `RaxonProvider` ile sarın |
743
+ | Sepet boş görünüyor | `isAuthenticated` kontrol edin; misafir girişi gerekebilir |
744
+ | Toast görünmüyor | `<Toaster />` ekleyin |
745
+ | 401 hataları | Token süresi dolmuş; yeniden giriş yapın |
746
+ | Hook kuralları hatası | Hook metodlarını koşullu veya döngü içinde çağırmayın |
747
+
748
+ ---
749
+
750
+ ## Lisans
751
+
752
+ [ISC](LICENSE)
753
+
754
+ ## Bağlantılar
755
+
756
+ - [npm](https://www.npmjs.com/package/@raxonltd/raxon-core)
757
+ - [GitHub](https://github.com/raxonltd/raxon-core)
758
+ - [Sorun bildir](https://github.com/raxonltd/raxon-core/issues)