@sales-planner/react 0.2.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,129 @@
1
+ # @sales-planner/react
2
+
3
+ React hooks for the Sales Planner API, powered by [TanStack Query](https://tanstack.com/query).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @sales-planner/react @tanstack/react-query
9
+ ```
10
+
11
+ ## Setup
12
+
13
+ ```tsx
14
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
15
+ import { SalesPlannerProvider } from '@sales-planner/react';
16
+
17
+ const queryClient = new QueryClient();
18
+
19
+ function App() {
20
+ return (
21
+ <QueryClientProvider client={queryClient}>
22
+ <SalesPlannerProvider config={{ baseUrl: '/api', apiKey: 'your-key' }}>
23
+ <MyApp />
24
+ </SalesPlannerProvider>
25
+ </QueryClientProvider>
26
+ );
27
+ }
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ### Queries
33
+
34
+ ```tsx
35
+ import { skus, brands, useMe } from '@sales-planner/react';
36
+
37
+ function SkuList() {
38
+ const ctx = { shopId: 1, tenantId: 1 };
39
+ const { data, isLoading } = skus.useList(ctx, { limit: 20 });
40
+
41
+ if (isLoading) return <div>Loading...</div>;
42
+
43
+ return (
44
+ <ul>
45
+ {data?.items.map((sku) => (
46
+ <li key={sku.id}>{sku.title}</li>
47
+ ))}
48
+ </ul>
49
+ );
50
+ }
51
+ ```
52
+
53
+ ### Mutations
54
+
55
+ ```tsx
56
+ import { brands } from '@sales-planner/react';
57
+
58
+ function CreateBrand() {
59
+ const ctx = { shopId: 1, tenantId: 1 };
60
+ const create = brands.useCreate(ctx);
61
+
62
+ return (
63
+ <button onClick={() => create.mutate({ code: 'NIKE', title: 'Nike' })}>
64
+ Create Brand
65
+ </button>
66
+ );
67
+ }
68
+ ```
69
+
70
+ ### CSV Import
71
+
72
+ ```tsx
73
+ import { suppliers } from '@sales-planner/react';
74
+
75
+ function ImportSuppliers() {
76
+ const ctx = { shopId: 1, tenantId: 1 };
77
+ const importCsv = suppliers.useImportCsv(ctx);
78
+
79
+ const handleFileUpload = (file: File) => {
80
+ file.text().then((csv) => importCsv.mutate(csv));
81
+ };
82
+
83
+ return <input type="file" onChange={(e) => handleFileUpload(e.target.files![0]!)} />;
84
+ }
85
+ ```
86
+
87
+ ## Available Hooks
88
+
89
+ ### Coded entities
90
+
91
+ `brands`, `categories`, `groups`, `statuses`, `suppliers`, `warehouses`, `marketplaces`, `skus` — each provides:
92
+
93
+ - `.useList(ctx, query?)` — paginated list
94
+ - `.useById(ctx, id)` — single entity
95
+ - `.useByCode(ctx, code)` — lookup by code
96
+ - `.useCreate(ctx)` — create mutation
97
+ - `.useUpdate(ctx)` — update mutation (`{ id, data }`)
98
+ - `.useDelete(ctx)` — delete mutation
99
+ - `.useImportJson(ctx)` — JSON import mutation
100
+ - `.useImportCsv(ctx)` — CSV import mutation
101
+ - `.useExportJson(ctx)` — JSON export (manual trigger)
102
+ - `.useExportCsv(ctx)` — CSV export (manual trigger)
103
+
104
+ ### Shop-scoped entities
105
+
106
+ `salesHistory`, `leftovers`, `seasonalCoefficients`, `skuCompetitorMappings`, `competitorProducts`, `competitorSales` — same as above minus `useByCode`.
107
+
108
+ ### Specialized
109
+
110
+ - `useMe()` — current user
111
+ - `useEntitiesMetadata()` — entity field metadata
112
+ - `useSkuMetrics(ctx, query?)` — paginated SKU metrics
113
+ - `useSkuMetricsById(ctx, id)` — single SKU metric
114
+ - `useSkuMetricsByAbcClass(ctx, 'A' | 'B' | 'C')` — filter by ABC class
115
+ - `useSkuMetricsExportCsv(ctx)` — CSV export
116
+ - `useComputedViews(ctx)` — list materialized views
117
+ - `useRefreshAllViews(ctx)` — refresh all views mutation
118
+
119
+ ## Cache Invalidation
120
+
121
+ All mutations automatically invalidate related query caches. The `queryKeys` object is exported for custom cache management:
122
+
123
+ ```tsx
124
+ import { queryKeys } from '@sales-planner/react';
125
+ import { useQueryClient } from '@tanstack/react-query';
126
+
127
+ const queryClient = useQueryClient();
128
+ queryClient.invalidateQueries({ queryKey: queryKeys.entity('skus', ctx) });
129
+ ```
@@ -0,0 +1,128 @@
1
+ import type { Brand, Category, Group, Status, Supplier, Warehouse, Marketplace } from '@sales-planner/shared';
2
+ export declare const brands: {
3
+ useList: (ctx: import("./keys.js").ShopContext, query?: import("@sales-planner/shared").PaginationQuery, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").PaginatedResponse<Brand>, Error, import("@sales-planner/shared").PaginatedResponse<Brand>, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").PaginatedResponse<Brand>, Error>;
4
+ useById: (ctx: import("./keys.js").ShopContext, id: number, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Brand, Error, Brand, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Brand, Error>;
5
+ useByCode: (ctx: import("./keys.js").ShopContext, code: string, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Brand, Error, Brand, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Brand, Error>;
6
+ useExportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").CodedTitledItem[], Error, import("@sales-planner/shared").CodedTitledItem[], readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").CodedTitledItem[], Error>;
7
+ useExportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseQueryOptions<string>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<string, Error>;
8
+ useCreate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Brand, Error, import("@sales-planner/shared").CodedTitledItem, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Brand, Error, import("@sales-planner/shared").CodedTitledItem, unknown>;
9
+ useUpdate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Brand, Error, {
10
+ id: number;
11
+ data: import("@sales-planner/shared").CodedTitledUpdateDto;
12
+ }, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Brand, Error, {
13
+ id: number;
14
+ data: import("@sales-planner/shared").CodedTitledUpdateDto;
15
+ }, unknown>;
16
+ useDelete: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<void, Error, number>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<void, Error, number, unknown>;
17
+ useImportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<import("@sales-planner/shared").ImportResult, Error, import("@sales-planner/shared").CodedTitledItem[], unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<import("@sales-planner/shared").ImportResult, Error, import("@sales-planner/shared").CodedTitledItem[], unknown>;
18
+ useImportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<import("@sales-planner/shared").ImportResult, Error, string>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<import("@sales-planner/shared").ImportResult, Error, string, unknown>;
19
+ };
20
+ export declare const categories: {
21
+ useList: (ctx: import("./keys.js").ShopContext, query?: import("@sales-planner/shared").PaginationQuery, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").PaginatedResponse<Category>, Error, import("@sales-planner/shared").PaginatedResponse<Category>, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").PaginatedResponse<Category>, Error>;
22
+ useById: (ctx: import("./keys.js").ShopContext, id: number, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Category, Error, Category, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Category, Error>;
23
+ useByCode: (ctx: import("./keys.js").ShopContext, code: string, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Category, Error, Category, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Category, Error>;
24
+ useExportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").CodedTitledItem[], Error, import("@sales-planner/shared").CodedTitledItem[], readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").CodedTitledItem[], Error>;
25
+ useExportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseQueryOptions<string>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<string, Error>;
26
+ useCreate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Category, Error, import("@sales-planner/shared").CodedTitledItem, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Category, Error, import("@sales-planner/shared").CodedTitledItem, unknown>;
27
+ useUpdate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Category, Error, {
28
+ id: number;
29
+ data: import("@sales-planner/shared").CodedTitledUpdateDto;
30
+ }, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Category, Error, {
31
+ id: number;
32
+ data: import("@sales-planner/shared").CodedTitledUpdateDto;
33
+ }, unknown>;
34
+ useDelete: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<void, Error, number>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<void, Error, number, unknown>;
35
+ useImportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<import("@sales-planner/shared").ImportResult, Error, import("@sales-planner/shared").CodedTitledItem[], unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<import("@sales-planner/shared").ImportResult, Error, import("@sales-planner/shared").CodedTitledItem[], unknown>;
36
+ useImportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<import("@sales-planner/shared").ImportResult, Error, string>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<import("@sales-planner/shared").ImportResult, Error, string, unknown>;
37
+ };
38
+ export declare const groups: {
39
+ useList: (ctx: import("./keys.js").ShopContext, query?: import("@sales-planner/shared").PaginationQuery, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").PaginatedResponse<Group>, Error, import("@sales-planner/shared").PaginatedResponse<Group>, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").PaginatedResponse<Group>, Error>;
40
+ useById: (ctx: import("./keys.js").ShopContext, id: number, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Group, Error, Group, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Group, Error>;
41
+ useByCode: (ctx: import("./keys.js").ShopContext, code: string, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Group, Error, Group, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Group, Error>;
42
+ useExportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").CodedTitledItem[], Error, import("@sales-planner/shared").CodedTitledItem[], readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").CodedTitledItem[], Error>;
43
+ useExportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseQueryOptions<string>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<string, Error>;
44
+ useCreate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Group, Error, import("@sales-planner/shared").CodedTitledItem, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Group, Error, import("@sales-planner/shared").CodedTitledItem, unknown>;
45
+ useUpdate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Group, Error, {
46
+ id: number;
47
+ data: import("@sales-planner/shared").CodedTitledUpdateDto;
48
+ }, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Group, Error, {
49
+ id: number;
50
+ data: import("@sales-planner/shared").CodedTitledUpdateDto;
51
+ }, unknown>;
52
+ useDelete: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<void, Error, number>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<void, Error, number, unknown>;
53
+ useImportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<import("@sales-planner/shared").ImportResult, Error, import("@sales-planner/shared").CodedTitledItem[], unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<import("@sales-planner/shared").ImportResult, Error, import("@sales-planner/shared").CodedTitledItem[], unknown>;
54
+ useImportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<import("@sales-planner/shared").ImportResult, Error, string>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<import("@sales-planner/shared").ImportResult, Error, string, unknown>;
55
+ };
56
+ export declare const statuses: {
57
+ useList: (ctx: import("./keys.js").ShopContext, query?: import("@sales-planner/shared").PaginationQuery, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").PaginatedResponse<Status>, Error, import("@sales-planner/shared").PaginatedResponse<Status>, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").PaginatedResponse<Status>, Error>;
58
+ useById: (ctx: import("./keys.js").ShopContext, id: number, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Status, Error, Status, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Status, Error>;
59
+ useByCode: (ctx: import("./keys.js").ShopContext, code: string, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Status, Error, Status, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Status, Error>;
60
+ useExportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").CodedTitledItem[], Error, import("@sales-planner/shared").CodedTitledItem[], readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").CodedTitledItem[], Error>;
61
+ useExportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseQueryOptions<string>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<string, Error>;
62
+ useCreate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Status, Error, import("@sales-planner/shared").CodedTitledItem, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Status, Error, import("@sales-planner/shared").CodedTitledItem, unknown>;
63
+ useUpdate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Status, Error, {
64
+ id: number;
65
+ data: import("@sales-planner/shared").CodedTitledUpdateDto;
66
+ }, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Status, Error, {
67
+ id: number;
68
+ data: import("@sales-planner/shared").CodedTitledUpdateDto;
69
+ }, unknown>;
70
+ useDelete: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<void, Error, number>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<void, Error, number, unknown>;
71
+ useImportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<import("@sales-planner/shared").ImportResult, Error, import("@sales-planner/shared").CodedTitledItem[], unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<import("@sales-planner/shared").ImportResult, Error, import("@sales-planner/shared").CodedTitledItem[], unknown>;
72
+ useImportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<import("@sales-planner/shared").ImportResult, Error, string>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<import("@sales-planner/shared").ImportResult, Error, string, unknown>;
73
+ };
74
+ export declare const suppliers: {
75
+ useList: (ctx: import("./keys.js").ShopContext, query?: import("@sales-planner/shared").PaginationQuery, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").PaginatedResponse<Supplier>, Error, import("@sales-planner/shared").PaginatedResponse<Supplier>, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").PaginatedResponse<Supplier>, Error>;
76
+ useById: (ctx: import("./keys.js").ShopContext, id: number, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Supplier, Error, Supplier, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Supplier, Error>;
77
+ useByCode: (ctx: import("./keys.js").ShopContext, code: string, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Supplier, Error, Supplier, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Supplier, Error>;
78
+ useExportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").CodedTitledItem[], Error, import("@sales-planner/shared").CodedTitledItem[], readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").CodedTitledItem[], Error>;
79
+ useExportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseQueryOptions<string>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<string, Error>;
80
+ useCreate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Supplier, Error, import("@sales-planner/shared").CodedTitledItem, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Supplier, Error, import("@sales-planner/shared").CodedTitledItem, unknown>;
81
+ useUpdate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Supplier, Error, {
82
+ id: number;
83
+ data: import("@sales-planner/shared").CodedTitledUpdateDto;
84
+ }, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Supplier, Error, {
85
+ id: number;
86
+ data: import("@sales-planner/shared").CodedTitledUpdateDto;
87
+ }, unknown>;
88
+ useDelete: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<void, Error, number>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<void, Error, number, unknown>;
89
+ useImportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<import("@sales-planner/shared").ImportResult, Error, import("@sales-planner/shared").CodedTitledItem[], unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<import("@sales-planner/shared").ImportResult, Error, import("@sales-planner/shared").CodedTitledItem[], unknown>;
90
+ useImportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<import("@sales-planner/shared").ImportResult, Error, string>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<import("@sales-planner/shared").ImportResult, Error, string, unknown>;
91
+ };
92
+ export declare const warehouses: {
93
+ useList: (ctx: import("./keys.js").ShopContext, query?: import("@sales-planner/shared").PaginationQuery, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").PaginatedResponse<Warehouse>, Error, import("@sales-planner/shared").PaginatedResponse<Warehouse>, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").PaginatedResponse<Warehouse>, Error>;
94
+ useById: (ctx: import("./keys.js").ShopContext, id: number, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Warehouse, Error, Warehouse, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Warehouse, Error>;
95
+ useByCode: (ctx: import("./keys.js").ShopContext, code: string, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Warehouse, Error, Warehouse, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Warehouse, Error>;
96
+ useExportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").CodedTitledItem[], Error, import("@sales-planner/shared").CodedTitledItem[], readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").CodedTitledItem[], Error>;
97
+ useExportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseQueryOptions<string>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<string, Error>;
98
+ useCreate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Warehouse, Error, import("@sales-planner/shared").CodedTitledItem, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Warehouse, Error, import("@sales-planner/shared").CodedTitledItem, unknown>;
99
+ useUpdate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Warehouse, Error, {
100
+ id: number;
101
+ data: import("@sales-planner/shared").CodedTitledUpdateDto;
102
+ }, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Warehouse, Error, {
103
+ id: number;
104
+ data: import("@sales-planner/shared").CodedTitledUpdateDto;
105
+ }, unknown>;
106
+ useDelete: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<void, Error, number>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<void, Error, number, unknown>;
107
+ useImportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<import("@sales-planner/shared").ImportResult, Error, import("@sales-planner/shared").CodedTitledItem[], unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<import("@sales-planner/shared").ImportResult, Error, import("@sales-planner/shared").CodedTitledItem[], unknown>;
108
+ useImportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<import("@sales-planner/shared").ImportResult, Error, string>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<import("@sales-planner/shared").ImportResult, Error, string, unknown>;
109
+ };
110
+ export declare const marketplaces: {
111
+ useList: (ctx: import("./keys.js").ShopContext, query?: import("@sales-planner/shared").PaginationQuery, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").PaginatedResponse<Marketplace>, Error, import("@sales-planner/shared").PaginatedResponse<Marketplace>, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").PaginatedResponse<Marketplace>, Error>;
112
+ useById: (ctx: import("./keys.js").ShopContext, id: number, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Marketplace, Error, Marketplace, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Marketplace, Error>;
113
+ useByCode: (ctx: import("./keys.js").ShopContext, code: string, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Marketplace, Error, Marketplace, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Marketplace, Error>;
114
+ useExportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").CodedTitledItem[], Error, import("@sales-planner/shared").CodedTitledItem[], readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").CodedTitledItem[], Error>;
115
+ useExportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseQueryOptions<string>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<string, Error>;
116
+ useCreate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Marketplace, Error, import("@sales-planner/shared").CodedTitledItem, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Marketplace, Error, import("@sales-planner/shared").CodedTitledItem, unknown>;
117
+ useUpdate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Marketplace, Error, {
118
+ id: number;
119
+ data: import("@sales-planner/shared").CodedTitledUpdateDto;
120
+ }, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Marketplace, Error, {
121
+ id: number;
122
+ data: import("@sales-planner/shared").CodedTitledUpdateDto;
123
+ }, unknown>;
124
+ useDelete: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<void, Error, number>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<void, Error, number, unknown>;
125
+ useImportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<import("@sales-planner/shared").ImportResult, Error, import("@sales-planner/shared").CodedTitledItem[], unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<import("@sales-planner/shared").ImportResult, Error, import("@sales-planner/shared").CodedTitledItem[], unknown>;
126
+ useImportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<import("@sales-planner/shared").ImportResult, Error, string>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<import("@sales-planner/shared").ImportResult, Error, string, unknown>;
127
+ };
128
+ //# sourceMappingURL=coded-entities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coded-entities.d.ts","sourceRoot":"","sources":["../src/coded-entities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EAKL,QAAQ,EAKR,KAAK,EAKL,MAAM,EAKN,QAAQ,EAKR,SAAS,EAKT,WAAW,EAKZ,MAAM,uBAAuB,CAAC;AAG/B,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;CAMS,CAAC;AAE7B,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;CAMa,CAAC;AAErC,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;CAMS,CAAC;AAE7B,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;CAMW,CAAC;AAEjC,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;CAMY,CAAC;AAEnC,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;CAMa,CAAC;AAErC,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;CAMe,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { createCodedEntityHooks } from './create-coded-entity-hooks.js';
2
+ export const brands = createCodedEntityHooks('brands', (c) => c.brands);
3
+ export const categories = createCodedEntityHooks('categories', (c) => c.categories);
4
+ export const groups = createCodedEntityHooks('groups', (c) => c.groups);
5
+ export const statuses = createCodedEntityHooks('statuses', (c) => c.statuses);
6
+ export const suppliers = createCodedEntityHooks('suppliers', (c) => c.suppliers);
7
+ export const warehouses = createCodedEntityHooks('warehouses', (c) => c.warehouses);
8
+ export const marketplaces = createCodedEntityHooks('marketplaces', (c) => c.marketplaces);
@@ -0,0 +1,39 @@
1
+ import type { UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
2
+ import type { PaginatedResponse, PaginationQuery, ImportResult, ShopContextParams } from '@sales-planner/shared';
3
+ import { useSalesPlannerClient } from './provider.js';
4
+ import type { ShopContext } from './keys.js';
5
+ type CodedEntityClientLike<TEntity, TCreate, TUpdate, TImport, TExport> = {
6
+ getAll(ctx: ShopContextParams, query?: PaginationQuery): Promise<PaginatedResponse<TEntity>>;
7
+ getById(ctx: ShopContextParams, id: number): Promise<TEntity>;
8
+ getByCode(ctx: ShopContextParams, code: string): Promise<TEntity>;
9
+ create(ctx: ShopContextParams, request: TCreate): Promise<TEntity>;
10
+ update(ctx: ShopContextParams, id: number, request: TUpdate): Promise<TEntity>;
11
+ delete(ctx: ShopContextParams, id: number): Promise<void>;
12
+ importJson(ctx: ShopContextParams, items: TImport[]): Promise<ImportResult>;
13
+ importCsv(ctx: ShopContextParams, csvContent: string): Promise<ImportResult>;
14
+ exportJson(ctx: ShopContextParams): Promise<TExport[]>;
15
+ exportCsv(ctx: ShopContextParams): Promise<string>;
16
+ };
17
+ /**
18
+ * Creates a set of React Query hooks for a coded entity (brands, categories, etc.)
19
+ */
20
+ export declare function createCodedEntityHooks<TEntity, TCreate, TUpdate, TImport, TExport>(entityName: string, getClient: (client: ReturnType<typeof useSalesPlannerClient>) => CodedEntityClientLike<TEntity, TCreate, TUpdate, TImport, TExport>): {
21
+ useList: (ctx: ShopContext, query?: PaginationQuery, options?: Omit<UseQueryOptions<PaginatedResponse<TEntity>>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<PaginatedResponse<TEntity>, Error>;
22
+ useById: (ctx: ShopContext, id: number, options?: Omit<UseQueryOptions<TEntity>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<import("@tanstack/react-query").NoInfer<TEntity>, Error>;
23
+ useByCode: (ctx: ShopContext, code: string, options?: Omit<UseQueryOptions<TEntity>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<import("@tanstack/react-query").NoInfer<TEntity>, Error>;
24
+ useExportJson: (ctx: ShopContext, options?: Omit<UseQueryOptions<TExport[]>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<TExport[], Error>;
25
+ useExportCsv: (ctx: ShopContext, options?: Omit<UseQueryOptions<string>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<string, Error>;
26
+ useCreate: (ctx: ShopContext, options?: Omit<UseMutationOptions<TEntity, Error, TCreate>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<TEntity, Error, TCreate, unknown>;
27
+ useUpdate: (ctx: ShopContext, options?: Omit<UseMutationOptions<TEntity, Error, {
28
+ id: number;
29
+ data: TUpdate;
30
+ }>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<TEntity, Error, {
31
+ id: number;
32
+ data: TUpdate;
33
+ }, unknown>;
34
+ useDelete: (ctx: ShopContext, options?: Omit<UseMutationOptions<void, Error, number>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<void, Error, number, unknown>;
35
+ useImportJson: (ctx: ShopContext, options?: Omit<UseMutationOptions<ImportResult, Error, TImport[]>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<ImportResult, Error, TImport[], unknown>;
36
+ useImportCsv: (ctx: ShopContext, options?: Omit<UseMutationOptions<ImportResult, Error, string>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<ImportResult, Error, string, unknown>;
37
+ };
38
+ export {};
39
+ //# sourceMappingURL=create-coded-entity-hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-coded-entity-hooks.d.ts","sourceRoot":"","sources":["../src/create-coded-entity-hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
2
+ import { useSalesPlannerClient } from './provider.js';
3
+ import { queryKeys, toShopContextParams } from './keys.js';
4
+ /**
5
+ * Creates a set of React Query hooks for a coded entity (brands, categories, etc.)
6
+ */
7
+ export function createCodedEntityHooks(entityName, getClient) {
8
+ function useList(ctx, query, options) {
9
+ const client = useSalesPlannerClient();
10
+ return useQuery({
11
+ queryKey: queryKeys.entityList(entityName, ctx, query),
12
+ queryFn: () => getClient(client).getAll(toShopContextParams(ctx), query),
13
+ ...options,
14
+ });
15
+ }
16
+ function useById(ctx, id, options) {
17
+ const client = useSalesPlannerClient();
18
+ return useQuery({
19
+ queryKey: queryKeys.entityDetail(entityName, ctx, id),
20
+ queryFn: () => getClient(client).getById(toShopContextParams(ctx), id),
21
+ ...options,
22
+ });
23
+ }
24
+ function useByCode(ctx, code, options) {
25
+ const client = useSalesPlannerClient();
26
+ return useQuery({
27
+ queryKey: queryKeys.entityByCode(entityName, ctx, code),
28
+ queryFn: () => getClient(client).getByCode(toShopContextParams(ctx), code),
29
+ ...options,
30
+ });
31
+ }
32
+ function useExportJson(ctx, options) {
33
+ const client = useSalesPlannerClient();
34
+ return useQuery({
35
+ queryKey: queryKeys.entityExport(entityName, ctx, 'json'),
36
+ queryFn: () => getClient(client).exportJson(toShopContextParams(ctx)),
37
+ enabled: false, // manual trigger only
38
+ ...options,
39
+ });
40
+ }
41
+ function useExportCsv(ctx, options) {
42
+ const client = useSalesPlannerClient();
43
+ return useQuery({
44
+ queryKey: queryKeys.entityExport(entityName, ctx, 'csv'),
45
+ queryFn: () => getClient(client).exportCsv(toShopContextParams(ctx)),
46
+ enabled: false,
47
+ ...options,
48
+ });
49
+ }
50
+ function useCreate(ctx, options) {
51
+ const client = useSalesPlannerClient();
52
+ const queryClient = useQueryClient();
53
+ return useMutation({
54
+ mutationFn: (request) => getClient(client).create(toShopContextParams(ctx), request),
55
+ onSuccess: () => {
56
+ queryClient.invalidateQueries({ queryKey: queryKeys.entity(entityName, ctx) });
57
+ },
58
+ ...options,
59
+ });
60
+ }
61
+ function useUpdate(ctx, options) {
62
+ const client = useSalesPlannerClient();
63
+ const queryClient = useQueryClient();
64
+ return useMutation({
65
+ mutationFn: ({ id, data }) => getClient(client).update(toShopContextParams(ctx), id, data),
66
+ onSuccess: () => {
67
+ queryClient.invalidateQueries({ queryKey: queryKeys.entity(entityName, ctx) });
68
+ },
69
+ ...options,
70
+ });
71
+ }
72
+ function useDelete(ctx, options) {
73
+ const client = useSalesPlannerClient();
74
+ const queryClient = useQueryClient();
75
+ return useMutation({
76
+ mutationFn: (id) => getClient(client).delete(toShopContextParams(ctx), id),
77
+ onSuccess: () => {
78
+ queryClient.invalidateQueries({ queryKey: queryKeys.entity(entityName, ctx) });
79
+ },
80
+ ...options,
81
+ });
82
+ }
83
+ function useImportJson(ctx, options) {
84
+ const client = useSalesPlannerClient();
85
+ const queryClient = useQueryClient();
86
+ return useMutation({
87
+ mutationFn: (items) => getClient(client).importJson(toShopContextParams(ctx), items),
88
+ onSuccess: () => {
89
+ queryClient.invalidateQueries({ queryKey: queryKeys.entity(entityName, ctx) });
90
+ },
91
+ ...options,
92
+ });
93
+ }
94
+ function useImportCsv(ctx, options) {
95
+ const client = useSalesPlannerClient();
96
+ const queryClient = useQueryClient();
97
+ return useMutation({
98
+ mutationFn: (csvContent) => getClient(client).importCsv(toShopContextParams(ctx), csvContent),
99
+ onSuccess: () => {
100
+ queryClient.invalidateQueries({ queryKey: queryKeys.entity(entityName, ctx) });
101
+ },
102
+ ...options,
103
+ });
104
+ }
105
+ return {
106
+ useList,
107
+ useById,
108
+ useByCode,
109
+ useExportJson,
110
+ useExportCsv,
111
+ useCreate,
112
+ useUpdate,
113
+ useDelete,
114
+ useImportJson,
115
+ useImportCsv,
116
+ };
117
+ }
@@ -0,0 +1,38 @@
1
+ import type { UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
2
+ import type { PaginatedResponse, ShopContextParams } from '@sales-planner/shared';
3
+ import { useSalesPlannerClient } from './provider.js';
4
+ import type { ShopContext } from './keys.js';
5
+ type ShopScopedClientLike<TEntity, TCreate, TUpdate, TImport, TExport, TImportResult, TQuery> = {
6
+ getAll(ctx: ShopContextParams, query?: TQuery): Promise<PaginatedResponse<TEntity>>;
7
+ getById(ctx: ShopContextParams, id: number): Promise<TEntity>;
8
+ create(ctx: ShopContextParams, request: TCreate): Promise<TEntity>;
9
+ update(ctx: ShopContextParams, id: number, request: TUpdate): Promise<TEntity>;
10
+ delete(ctx: ShopContextParams, id: number): Promise<void>;
11
+ importJson(ctx: ShopContextParams, items: TImport[]): Promise<TImportResult>;
12
+ importCsv(ctx: ShopContextParams, csvContent: string): Promise<TImportResult>;
13
+ exportJson(ctx: ShopContextParams, query?: TQuery): Promise<TExport[]>;
14
+ exportCsv(ctx: ShopContextParams, query?: TQuery): Promise<string>;
15
+ };
16
+ /**
17
+ * Creates a set of React Query hooks for a shop-scoped entity
18
+ * (sales history, leftovers, seasonal coefficients, competitor entities)
19
+ */
20
+ export declare function createShopScopedHooks<TEntity, TCreate, TUpdate, TImport, TExport, TImportResult, TQuery = Record<string, never>>(entityName: string, getClient: (client: ReturnType<typeof useSalesPlannerClient>) => ShopScopedClientLike<TEntity, TCreate, TUpdate, TImport, TExport, TImportResult, TQuery>): {
21
+ useList: (ctx: ShopContext, query?: TQuery, options?: Omit<UseQueryOptions<PaginatedResponse<TEntity>>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<PaginatedResponse<TEntity>, Error>;
22
+ useById: (ctx: ShopContext, id: number, options?: Omit<UseQueryOptions<TEntity>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<import("@tanstack/react-query").NoInfer<TEntity>, Error>;
23
+ useExportJson: (ctx: ShopContext, query?: TQuery, options?: Omit<UseQueryOptions<TExport[]>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<TExport[], Error>;
24
+ useExportCsv: (ctx: ShopContext, query?: TQuery, options?: Omit<UseQueryOptions<string>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<string, Error>;
25
+ useCreate: (ctx: ShopContext, options?: Omit<UseMutationOptions<TEntity, Error, TCreate>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<TEntity, Error, TCreate, unknown>;
26
+ useUpdate: (ctx: ShopContext, options?: Omit<UseMutationOptions<TEntity, Error, {
27
+ id: number;
28
+ data: TUpdate;
29
+ }>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<TEntity, Error, {
30
+ id: number;
31
+ data: TUpdate;
32
+ }, unknown>;
33
+ useDelete: (ctx: ShopContext, options?: Omit<UseMutationOptions<void, Error, number>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<void, Error, number, unknown>;
34
+ useImportJson: (ctx: ShopContext, options?: Omit<UseMutationOptions<TImportResult, Error, TImport[]>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<TImportResult, Error, TImport[], unknown>;
35
+ useImportCsv: (ctx: ShopContext, options?: Omit<UseMutationOptions<TImportResult, Error, string>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<TImportResult, Error, string, unknown>;
36
+ };
37
+ export {};
38
+ //# sourceMappingURL=create-shop-scoped-hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-shop-scoped-hooks.d.ts","sourceRoot":"","sources":["../src/create-shop-scoped-hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACjF,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAClF,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,KAAK,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,IAAI;IAC9F,MAAM,CAAC,GAAG,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC;IACpF,OAAO,CAAC,GAAG,EAAE,iBAAiB,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9D,MAAM,CAAC,GAAG,EAAE,iBAAiB,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnE,MAAM,CAAC,GAAG,EAAE,iBAAiB,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/E,MAAM,CAAC,GAAG,EAAE,iBAAiB,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,UAAU,CAAC,GAAG,EAAE,iBAAiB,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC7E,SAAS,CAAC,GAAG,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC9E,UAAU,CAAC,GAAG,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACvE,SAAS,CAAC,GAAG,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACpE,CAAC;AAEF;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EACP,OAAO,EACP,OAAO,EACP,OAAO,EACP,OAAO,EACP,aAAa,EACb,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAE9B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,CACT,MAAM,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,KAC7C,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,CAAC;mBAGtF,WAAW,UACR,MAAM,YACJ,IAAI,CAAC,eAAe,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;mBAW9E,WAAW,MACZ,MAAM,YACA,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;yBAW3D,WAAW,UACR,MAAM,YACJ,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;wBAY7D,WAAW,UACR,MAAM,YACJ,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;qBAY1D,WAAW,YACN,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC;qBAcpE,WAAW,YACN,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,EAAE,YAAY,CAAC;YAK5D,MAAM;cAAQ,OAAO;;qBAUnD,WAAW,YACN,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,YAAY,CAAC;yBAchE,WAAW,YACN,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,YAAY,CAAC;wBAe5E,WAAW,YACN,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,YAAY,CAAC;EAyBjF"}
@@ -0,0 +1,109 @@
1
+ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
2
+ import { useSalesPlannerClient } from './provider.js';
3
+ import { queryKeys, toShopContextParams } from './keys.js';
4
+ /**
5
+ * Creates a set of React Query hooks for a shop-scoped entity
6
+ * (sales history, leftovers, seasonal coefficients, competitor entities)
7
+ */
8
+ export function createShopScopedHooks(entityName, getClient) {
9
+ function useList(ctx, query, options) {
10
+ const client = useSalesPlannerClient();
11
+ return useQuery({
12
+ queryKey: queryKeys.entityList(entityName, ctx, query),
13
+ queryFn: () => getClient(client).getAll(toShopContextParams(ctx), query),
14
+ ...options,
15
+ });
16
+ }
17
+ function useById(ctx, id, options) {
18
+ const client = useSalesPlannerClient();
19
+ return useQuery({
20
+ queryKey: queryKeys.entityDetail(entityName, ctx, id),
21
+ queryFn: () => getClient(client).getById(toShopContextParams(ctx), id),
22
+ ...options,
23
+ });
24
+ }
25
+ function useExportJson(ctx, query, options) {
26
+ const client = useSalesPlannerClient();
27
+ return useQuery({
28
+ queryKey: queryKeys.entityExport(entityName, ctx, 'json'),
29
+ queryFn: () => getClient(client).exportJson(toShopContextParams(ctx), query),
30
+ enabled: false,
31
+ ...options,
32
+ });
33
+ }
34
+ function useExportCsv(ctx, query, options) {
35
+ const client = useSalesPlannerClient();
36
+ return useQuery({
37
+ queryKey: queryKeys.entityExport(entityName, ctx, 'csv'),
38
+ queryFn: () => getClient(client).exportCsv(toShopContextParams(ctx), query),
39
+ enabled: false,
40
+ ...options,
41
+ });
42
+ }
43
+ function useCreate(ctx, options) {
44
+ const client = useSalesPlannerClient();
45
+ const queryClient = useQueryClient();
46
+ return useMutation({
47
+ mutationFn: (request) => getClient(client).create(toShopContextParams(ctx), request),
48
+ onSuccess: () => {
49
+ queryClient.invalidateQueries({ queryKey: queryKeys.entity(entityName, ctx) });
50
+ },
51
+ ...options,
52
+ });
53
+ }
54
+ function useUpdate(ctx, options) {
55
+ const client = useSalesPlannerClient();
56
+ const queryClient = useQueryClient();
57
+ return useMutation({
58
+ mutationFn: ({ id, data }) => getClient(client).update(toShopContextParams(ctx), id, data),
59
+ onSuccess: () => {
60
+ queryClient.invalidateQueries({ queryKey: queryKeys.entity(entityName, ctx) });
61
+ },
62
+ ...options,
63
+ });
64
+ }
65
+ function useDelete(ctx, options) {
66
+ const client = useSalesPlannerClient();
67
+ const queryClient = useQueryClient();
68
+ return useMutation({
69
+ mutationFn: (id) => getClient(client).delete(toShopContextParams(ctx), id),
70
+ onSuccess: () => {
71
+ queryClient.invalidateQueries({ queryKey: queryKeys.entity(entityName, ctx) });
72
+ },
73
+ ...options,
74
+ });
75
+ }
76
+ function useImportJson(ctx, options) {
77
+ const client = useSalesPlannerClient();
78
+ const queryClient = useQueryClient();
79
+ return useMutation({
80
+ mutationFn: (items) => getClient(client).importJson(toShopContextParams(ctx), items),
81
+ onSuccess: () => {
82
+ queryClient.invalidateQueries({ queryKey: queryKeys.entity(entityName, ctx) });
83
+ },
84
+ ...options,
85
+ });
86
+ }
87
+ function useImportCsv(ctx, options) {
88
+ const client = useSalesPlannerClient();
89
+ const queryClient = useQueryClient();
90
+ return useMutation({
91
+ mutationFn: (csvContent) => getClient(client).importCsv(toShopContextParams(ctx), csvContent),
92
+ onSuccess: () => {
93
+ queryClient.invalidateQueries({ queryKey: queryKeys.entity(entityName, ctx) });
94
+ },
95
+ ...options,
96
+ });
97
+ }
98
+ return {
99
+ useList,
100
+ useById,
101
+ useExportJson,
102
+ useExportCsv,
103
+ useCreate,
104
+ useUpdate,
105
+ useDelete,
106
+ useImportJson,
107
+ useImportCsv,
108
+ };
109
+ }
@@ -0,0 +1,22 @@
1
+ export { SalesPlannerProvider, useSalesPlannerClient } from './provider.js';
2
+ export type { SalesPlannerProviderProps, ClientConfig } from './provider.js';
3
+ export { queryKeys, toShopContextParams } from './keys.js';
4
+ export type { ShopContext } from './keys.js';
5
+ export { createCodedEntityHooks } from './create-coded-entity-hooks.js';
6
+ export { createShopScopedHooks } from './create-shop-scoped-hooks.js';
7
+ export { brands } from './coded-entities.js';
8
+ export { categories } from './coded-entities.js';
9
+ export { groups } from './coded-entities.js';
10
+ export { statuses } from './coded-entities.js';
11
+ export { suppliers } from './coded-entities.js';
12
+ export { warehouses } from './coded-entities.js';
13
+ export { marketplaces } from './coded-entities.js';
14
+ export { skus } from './shop-scoped-entities.js';
15
+ export { salesHistory } from './shop-scoped-entities.js';
16
+ export { leftovers } from './shop-scoped-entities.js';
17
+ export { seasonalCoefficients } from './shop-scoped-entities.js';
18
+ export { skuCompetitorMappings } from './shop-scoped-entities.js';
19
+ export { competitorProducts } from './shop-scoped-entities.js';
20
+ export { competitorSales } from './shop-scoped-entities.js';
21
+ export { useMe, useEntitiesMetadata, useSkuMetrics, useSkuMetricsById, useSkuMetricsByAbcClass, useSkuMetricsExportCsv, useComputedViews, useRefreshAllViews, } from './specialized.js';
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC5E,YAAY,EAAE,yBAAyB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAG7E,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC3D,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAG7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAGtE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAG5D,OAAO,EACL,KAAK,EACL,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ // Provider
2
+ export { SalesPlannerProvider, useSalesPlannerClient } from './provider.js';
3
+ // Query keys for custom cache management
4
+ export { queryKeys, toShopContextParams } from './keys.js';
5
+ // Hook factories (for advanced use)
6
+ export { createCodedEntityHooks } from './create-coded-entity-hooks.js';
7
+ export { createShopScopedHooks } from './create-shop-scoped-hooks.js';
8
+ // ── Coded entity hooks ──
9
+ export { brands } from './coded-entities.js';
10
+ export { categories } from './coded-entities.js';
11
+ export { groups } from './coded-entities.js';
12
+ export { statuses } from './coded-entities.js';
13
+ export { suppliers } from './coded-entities.js';
14
+ export { warehouses } from './coded-entities.js';
15
+ export { marketplaces } from './coded-entities.js';
16
+ // ── Shop-scoped entity hooks ──
17
+ export { skus } from './shop-scoped-entities.js';
18
+ export { salesHistory } from './shop-scoped-entities.js';
19
+ export { leftovers } from './shop-scoped-entities.js';
20
+ export { seasonalCoefficients } from './shop-scoped-entities.js';
21
+ export { skuCompetitorMappings } from './shop-scoped-entities.js';
22
+ export { competitorProducts } from './shop-scoped-entities.js';
23
+ export { competitorSales } from './shop-scoped-entities.js';
24
+ // ── Specialized hooks ──
25
+ export { useMe, useEntitiesMetadata, useSkuMetrics, useSkuMetricsById, useSkuMetricsByAbcClass, useSkuMetricsExportCsv, useComputedViews, useRefreshAllViews, } from './specialized.js';
package/dist/keys.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ import type { ShopContextParams } from '@sales-planner/shared';
2
+ /**
3
+ * Common shop context required by most hooks
4
+ */
5
+ export interface ShopContext {
6
+ shopId: number;
7
+ tenantId: number;
8
+ }
9
+ export declare function toShopContextParams(ctx: ShopContext): ShopContextParams;
10
+ /**
11
+ * Standard query key factory for cache management
12
+ */
13
+ export declare const queryKeys: {
14
+ readonly me: () => readonly ["sales-planner", "me"];
15
+ readonly metadata: () => readonly ["sales-planner", "metadata"];
16
+ readonly entity: (entity: string, ctx: ShopContext) => readonly ["sales-planner", string, number, number];
17
+ readonly entityList: (entity: string, ctx: ShopContext, query?: Record<string, unknown>) => readonly ["sales-planner", string, number, number, "list", Record<string, unknown>];
18
+ readonly entityDetail: (entity: string, ctx: ShopContext, id: number) => readonly ["sales-planner", string, number, number, number];
19
+ readonly entityByCode: (entity: string, ctx: ShopContext, code: string) => readonly ["sales-planner", string, number, number, "code", string];
20
+ readonly entityExport: (entity: string, ctx: ShopContext, format: "json" | "csv") => readonly ["sales-planner", string, number, number, "export", "json" | "csv"];
21
+ readonly skuMetrics: (ctx: ShopContext) => readonly ["sales-planner", "sku-metrics", number, number];
22
+ readonly skuMetricsList: (ctx: ShopContext, query?: Record<string, unknown>) => readonly ["sales-planner", "sku-metrics", number, number, "list", Record<string, unknown>];
23
+ readonly skuMetricsDetail: (ctx: ShopContext, id: number) => readonly ["sales-planner", "sku-metrics", number, number, number];
24
+ readonly skuMetricsAbc: (ctx: ShopContext, abcClass: string) => readonly ["sales-planner", "sku-metrics", number, number, "abc", string];
25
+ readonly computed: (ctx: ShopContext) => readonly ["sales-planner", "computed", number, number];
26
+ };
27
+ //# sourceMappingURL=keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,WAAW,GAAG,iBAAiB,CAEvE;AAED;;GAEG;AACH,eAAO,MAAM,SAAS;;;8BAIH,MAAM,OAAO,WAAW;kCAGpB,MAAM,OAAO,WAAW,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;oCAGvD,MAAM,OAAO,WAAW,MAAM,MAAM;oCAGpC,MAAM,OAAO,WAAW,QAAQ,MAAM;oCAGtC,MAAM,OAAO,WAAW,UAAU,MAAM,GAAG,KAAK;+BAGrD,WAAW;mCAEP,WAAW,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;qCAE1C,WAAW,MAAM,MAAM;kCAC1B,WAAW,YAAY,MAAM;6BAGlC,WAAW;CACnB,CAAC"}
package/dist/keys.js ADDED
@@ -0,0 +1,20 @@
1
+ export function toShopContextParams(ctx) {
2
+ return { shop_id: ctx.shopId, tenant_id: ctx.tenantId };
3
+ }
4
+ /**
5
+ * Standard query key factory for cache management
6
+ */
7
+ export const queryKeys = {
8
+ me: () => ['sales-planner', 'me'],
9
+ metadata: () => ['sales-planner', 'metadata'],
10
+ entity: (entity, ctx) => ['sales-planner', entity, ctx.shopId, ctx.tenantId],
11
+ entityList: (entity, ctx, query) => [...queryKeys.entity(entity, ctx), 'list', query ?? {}],
12
+ entityDetail: (entity, ctx, id) => [...queryKeys.entity(entity, ctx), id],
13
+ entityByCode: (entity, ctx, code) => [...queryKeys.entity(entity, ctx), 'code', code],
14
+ entityExport: (entity, ctx, format) => [...queryKeys.entity(entity, ctx), 'export', format],
15
+ skuMetrics: (ctx) => ['sales-planner', 'sku-metrics', ctx.shopId, ctx.tenantId],
16
+ skuMetricsList: (ctx, query) => [...queryKeys.skuMetrics(ctx), 'list', query ?? {}],
17
+ skuMetricsDetail: (ctx, id) => [...queryKeys.skuMetrics(ctx), id],
18
+ skuMetricsAbc: (ctx, abcClass) => [...queryKeys.skuMetrics(ctx), 'abc', abcClass],
19
+ computed: (ctx) => ['sales-planner', 'computed', ctx.shopId, ctx.tenantId],
20
+ };
@@ -0,0 +1,36 @@
1
+ import { SalesPlannerClient } from '@sales-planner/http-client';
2
+ import type { ClientConfig } from '@sales-planner/http-client';
3
+ export type { ClientConfig } from '@sales-planner/http-client';
4
+ export interface SalesPlannerProviderProps {
5
+ config: ClientConfig;
6
+ children: React.ReactNode;
7
+ }
8
+ /**
9
+ * Provides a SalesPlannerClient instance to all child components.
10
+ * Must be used inside a TanStack QueryClientProvider.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
15
+ * import { SalesPlannerProvider } from '@sales-planner/react';
16
+ *
17
+ * const queryClient = new QueryClient();
18
+ *
19
+ * function App() {
20
+ * return (
21
+ * <QueryClientProvider client={queryClient}>
22
+ * <SalesPlannerProvider config={{ baseUrl: '/api', apiKey: 'key' }}>
23
+ * <MyApp />
24
+ * </SalesPlannerProvider>
25
+ * </QueryClientProvider>
26
+ * );
27
+ * }
28
+ * ```
29
+ */
30
+ export declare function SalesPlannerProvider({ config, children }: SalesPlannerProviderProps): import("react/jsx-runtime").JSX.Element;
31
+ /**
32
+ * Returns the SalesPlannerClient instance from context.
33
+ * Must be used inside a SalesPlannerProvider.
34
+ */
35
+ export declare function useSalesPlannerClient(): SalesPlannerClient;
36
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,YAAY,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAI/D,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,yBAAyB,2CAGnF;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,kBAAkB,CAM1D"}
@@ -0,0 +1,41 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext } from 'react';
3
+ import { SalesPlannerClient } from '@sales-planner/http-client';
4
+ const SalesPlannerContext = createContext(null);
5
+ /**
6
+ * Provides a SalesPlannerClient instance to all child components.
7
+ * Must be used inside a TanStack QueryClientProvider.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
12
+ * import { SalesPlannerProvider } from '@sales-planner/react';
13
+ *
14
+ * const queryClient = new QueryClient();
15
+ *
16
+ * function App() {
17
+ * return (
18
+ * <QueryClientProvider client={queryClient}>
19
+ * <SalesPlannerProvider config={{ baseUrl: '/api', apiKey: 'key' }}>
20
+ * <MyApp />
21
+ * </SalesPlannerProvider>
22
+ * </QueryClientProvider>
23
+ * );
24
+ * }
25
+ * ```
26
+ */
27
+ export function SalesPlannerProvider({ config, children }) {
28
+ const client = new SalesPlannerClient(config);
29
+ return _jsx(SalesPlannerContext, { value: client, children: children });
30
+ }
31
+ /**
32
+ * Returns the SalesPlannerClient instance from context.
33
+ * Must be used inside a SalesPlannerProvider.
34
+ */
35
+ export function useSalesPlannerClient() {
36
+ const client = useContext(SalesPlannerContext);
37
+ if (!client) {
38
+ throw new Error('useSalesPlannerClient must be used within a SalesPlannerProvider');
39
+ }
40
+ return client;
41
+ }
@@ -0,0 +1,122 @@
1
+ import type { Sku, CreateSkuRequest, ImportSkuItem, SkuExportItem, PaginationQuery, SalesHistory, CreateSalesHistoryRequest, ImportSalesHistoryItem, SalesHistoryExportItem, SalesHistoryImportResult, SalesHistoryQuery, Leftover, CreateLeftoverRequest, ImportLeftoverItem, LeftoverExportItem, ImportResult, LeftoverQuery, SeasonalCoefficient, CreateSeasonalCoefficientRequest, ImportSeasonalCoefficientItem, SeasonalCoefficientExportItem, SkuCompetitorMapping, CreateSkuCompetitorMappingRequest, ImportSkuCompetitorMappingItem, SkuCompetitorMappingExportItem, CompetitorProduct, CreateCompetitorProductRequest, ImportCompetitorProductItem, CompetitorProductExportItem, CompetitorSale, CreateCompetitorSaleRequest, ImportCompetitorSaleItem, CompetitorSaleExportItem, CompetitorProductQuery, CompetitorSaleQuery } from '@sales-planner/shared';
2
+ export declare const skus: {
3
+ useList: (ctx: import("./keys.js").ShopContext, query?: PaginationQuery, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").PaginatedResponse<Sku>, Error, import("@sales-planner/shared").PaginatedResponse<Sku>, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").PaginatedResponse<Sku>, Error>;
4
+ useById: (ctx: import("./keys.js").ShopContext, id: number, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Sku, Error, Sku, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Sku, Error>;
5
+ useByCode: (ctx: import("./keys.js").ShopContext, code: string, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Sku, Error, Sku, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Sku, Error>;
6
+ useExportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseQueryOptions<SkuExportItem[], Error, SkuExportItem[], readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<SkuExportItem[], Error>;
7
+ useExportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseQueryOptions<string>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<string, Error>;
8
+ useCreate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Sku, Error, CreateSkuRequest, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Sku, Error, CreateSkuRequest, unknown>;
9
+ useUpdate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Sku, Error, {
10
+ id: number;
11
+ data: import("@sales-planner/shared").UpdateSkuDto;
12
+ }, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Sku, Error, {
13
+ id: number;
14
+ data: import("@sales-planner/shared").UpdateSkuDto;
15
+ }, unknown>;
16
+ useDelete: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<void, Error, number>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<void, Error, number, unknown>;
17
+ useImportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<ImportResult, Error, ImportSkuItem[], unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<ImportResult, Error, ImportSkuItem[], unknown>;
18
+ useImportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<ImportResult, Error, string>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<ImportResult, Error, string, unknown>;
19
+ };
20
+ export declare const salesHistory: {
21
+ useList: (ctx: import("./keys.js").ShopContext, query?: SalesHistoryQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").PaginatedResponse<SalesHistory>, Error, import("@sales-planner/shared").PaginatedResponse<SalesHistory>, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").PaginatedResponse<SalesHistory>, Error>;
22
+ useById: (ctx: import("./keys.js").ShopContext, id: number, options?: Omit<import("@tanstack/react-query").UseQueryOptions<SalesHistory, Error, SalesHistory, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<SalesHistory, Error>;
23
+ useExportJson: (ctx: import("./keys.js").ShopContext, query?: SalesHistoryQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<SalesHistoryExportItem[], Error, SalesHistoryExportItem[], readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<SalesHistoryExportItem[], Error>;
24
+ useExportCsv: (ctx: import("./keys.js").ShopContext, query?: SalesHistoryQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<string>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<string, Error>;
25
+ useCreate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<SalesHistory, Error, CreateSalesHistoryRequest, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<SalesHistory, Error, CreateSalesHistoryRequest, unknown>;
26
+ useUpdate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<SalesHistory, Error, {
27
+ id: number;
28
+ data: import("@sales-planner/shared").UpdateSalesHistoryDto;
29
+ }, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<SalesHistory, Error, {
30
+ id: number;
31
+ data: import("@sales-planner/shared").UpdateSalesHistoryDto;
32
+ }, unknown>;
33
+ useDelete: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<void, Error, number>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<void, Error, number, unknown>;
34
+ useImportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<SalesHistoryImportResult, Error, ImportSalesHistoryItem[], unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<SalesHistoryImportResult, Error, ImportSalesHistoryItem[], unknown>;
35
+ useImportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<SalesHistoryImportResult, Error, string, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<SalesHistoryImportResult, Error, string, unknown>;
36
+ };
37
+ export declare const leftovers: {
38
+ useList: (ctx: import("./keys.js").ShopContext, query?: LeftoverQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").PaginatedResponse<Leftover>, Error, import("@sales-planner/shared").PaginatedResponse<Leftover>, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").PaginatedResponse<Leftover>, Error>;
39
+ useById: (ctx: import("./keys.js").ShopContext, id: number, options?: Omit<import("@tanstack/react-query").UseQueryOptions<Leftover, Error, Leftover, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<Leftover, Error>;
40
+ useExportJson: (ctx: import("./keys.js").ShopContext, query?: LeftoverQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<LeftoverExportItem[], Error, LeftoverExportItem[], readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<LeftoverExportItem[], Error>;
41
+ useExportCsv: (ctx: import("./keys.js").ShopContext, query?: LeftoverQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<string>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<string, Error>;
42
+ useCreate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Leftover, Error, CreateLeftoverRequest, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Leftover, Error, CreateLeftoverRequest, unknown>;
43
+ useUpdate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<Leftover, Error, {
44
+ id: number;
45
+ data: import("@sales-planner/shared").UpdateLeftoverDto;
46
+ }, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<Leftover, Error, {
47
+ id: number;
48
+ data: import("@sales-planner/shared").UpdateLeftoverDto;
49
+ }, unknown>;
50
+ useDelete: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<void, Error, number>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<void, Error, number, unknown>;
51
+ useImportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<ImportResult, Error, ImportLeftoverItem[], unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<ImportResult, Error, ImportLeftoverItem[], unknown>;
52
+ useImportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<ImportResult, Error, string, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<ImportResult, Error, string, unknown>;
53
+ };
54
+ export declare const seasonalCoefficients: {
55
+ useList: (ctx: import("./keys.js").ShopContext, query?: PaginationQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").PaginatedResponse<SeasonalCoefficient>, Error, import("@sales-planner/shared").PaginatedResponse<SeasonalCoefficient>, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").PaginatedResponse<SeasonalCoefficient>, Error>;
56
+ useById: (ctx: import("./keys.js").ShopContext, id: number, options?: Omit<import("@tanstack/react-query").UseQueryOptions<SeasonalCoefficient, Error, SeasonalCoefficient, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<SeasonalCoefficient, Error>;
57
+ useExportJson: (ctx: import("./keys.js").ShopContext, query?: PaginationQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<SeasonalCoefficientExportItem[], Error, SeasonalCoefficientExportItem[], readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<SeasonalCoefficientExportItem[], Error>;
58
+ useExportCsv: (ctx: import("./keys.js").ShopContext, query?: PaginationQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<string>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<string, Error>;
59
+ useCreate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<SeasonalCoefficient, Error, CreateSeasonalCoefficientRequest, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<SeasonalCoefficient, Error, CreateSeasonalCoefficientRequest, unknown>;
60
+ useUpdate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<SeasonalCoefficient, Error, {
61
+ id: number;
62
+ data: import("@sales-planner/shared").UpdateSeasonalCoefficientDto;
63
+ }, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<SeasonalCoefficient, Error, {
64
+ id: number;
65
+ data: import("@sales-planner/shared").UpdateSeasonalCoefficientDto;
66
+ }, unknown>;
67
+ useDelete: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<void, Error, number>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<void, Error, number, unknown>;
68
+ useImportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<ImportResult, Error, ImportSeasonalCoefficientItem[], unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<ImportResult, Error, ImportSeasonalCoefficientItem[], unknown>;
69
+ useImportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<ImportResult, Error, string, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<ImportResult, Error, string, unknown>;
70
+ };
71
+ export declare const skuCompetitorMappings: {
72
+ useList: (ctx: import("./keys.js").ShopContext, query?: PaginationQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").PaginatedResponse<SkuCompetitorMapping>, Error, import("@sales-planner/shared").PaginatedResponse<SkuCompetitorMapping>, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").PaginatedResponse<SkuCompetitorMapping>, Error>;
73
+ useById: (ctx: import("./keys.js").ShopContext, id: number, options?: Omit<import("@tanstack/react-query").UseQueryOptions<SkuCompetitorMapping, Error, SkuCompetitorMapping, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<SkuCompetitorMapping, Error>;
74
+ useExportJson: (ctx: import("./keys.js").ShopContext, query?: PaginationQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<SkuCompetitorMappingExportItem[], Error, SkuCompetitorMappingExportItem[], readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<SkuCompetitorMappingExportItem[], Error>;
75
+ useExportCsv: (ctx: import("./keys.js").ShopContext, query?: PaginationQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<string>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<string, Error>;
76
+ useCreate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<SkuCompetitorMapping, Error, CreateSkuCompetitorMappingRequest, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<SkuCompetitorMapping, Error, CreateSkuCompetitorMappingRequest, unknown>;
77
+ useUpdate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<SkuCompetitorMapping, Error, {
78
+ id: number;
79
+ data: import("@sales-planner/shared").UpdateSkuCompetitorMappingDto;
80
+ }, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<SkuCompetitorMapping, Error, {
81
+ id: number;
82
+ data: import("@sales-planner/shared").UpdateSkuCompetitorMappingDto;
83
+ }, unknown>;
84
+ useDelete: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<void, Error, number>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<void, Error, number, unknown>;
85
+ useImportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<ImportResult, Error, ImportSkuCompetitorMappingItem[], unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<ImportResult, Error, ImportSkuCompetitorMappingItem[], unknown>;
86
+ useImportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<ImportResult, Error, string, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<ImportResult, Error, string, unknown>;
87
+ };
88
+ export declare const competitorProducts: {
89
+ useList: (ctx: import("./keys.js").ShopContext, query?: CompetitorProductQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").PaginatedResponse<CompetitorProduct>, Error, import("@sales-planner/shared").PaginatedResponse<CompetitorProduct>, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").PaginatedResponse<CompetitorProduct>, Error>;
90
+ useById: (ctx: import("./keys.js").ShopContext, id: number, options?: Omit<import("@tanstack/react-query").UseQueryOptions<CompetitorProduct, Error, CompetitorProduct, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<CompetitorProduct, Error>;
91
+ useExportJson: (ctx: import("./keys.js").ShopContext, query?: CompetitorProductQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<CompetitorProductExportItem[], Error, CompetitorProductExportItem[], readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<CompetitorProductExportItem[], Error>;
92
+ useExportCsv: (ctx: import("./keys.js").ShopContext, query?: CompetitorProductQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<string>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<string, Error>;
93
+ useCreate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<CompetitorProduct, Error, CreateCompetitorProductRequest, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<CompetitorProduct, Error, CreateCompetitorProductRequest, unknown>;
94
+ useUpdate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<CompetitorProduct, Error, {
95
+ id: number;
96
+ data: import("@sales-planner/shared").UpdateCompetitorProductDto;
97
+ }, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<CompetitorProduct, Error, {
98
+ id: number;
99
+ data: import("@sales-planner/shared").UpdateCompetitorProductDto;
100
+ }, unknown>;
101
+ useDelete: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<void, Error, number>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<void, Error, number, unknown>;
102
+ useImportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<ImportResult, Error, ImportCompetitorProductItem[], unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<ImportResult, Error, ImportCompetitorProductItem[], unknown>;
103
+ useImportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<ImportResult, Error, string, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<ImportResult, Error, string, unknown>;
104
+ };
105
+ export declare const competitorSales: {
106
+ useList: (ctx: import("./keys.js").ShopContext, query?: CompetitorSaleQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<import("@sales-planner/shared").PaginatedResponse<CompetitorSale>, Error, import("@sales-planner/shared").PaginatedResponse<CompetitorSale>, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<import("@sales-planner/shared").PaginatedResponse<CompetitorSale>, Error>;
107
+ useById: (ctx: import("./keys.js").ShopContext, id: number, options?: Omit<import("@tanstack/react-query").UseQueryOptions<CompetitorSale, Error, CompetitorSale, readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<CompetitorSale, Error>;
108
+ useExportJson: (ctx: import("./keys.js").ShopContext, query?: CompetitorSaleQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<CompetitorSaleExportItem[], Error, CompetitorSaleExportItem[], readonly unknown[]>, "queryKey" | "queryFn"> | undefined) => import("@tanstack/react-query").UseQueryResult<CompetitorSaleExportItem[], Error>;
109
+ useExportCsv: (ctx: import("./keys.js").ShopContext, query?: CompetitorSaleQuery | undefined, options?: Omit<import("@tanstack/react-query").UseQueryOptions<string>, "queryKey" | "queryFn">) => import("@tanstack/react-query").UseQueryResult<string, Error>;
110
+ useCreate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<CompetitorSale, Error, CreateCompetitorSaleRequest, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<CompetitorSale, Error, CreateCompetitorSaleRequest, unknown>;
111
+ useUpdate: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<CompetitorSale, Error, {
112
+ id: number;
113
+ data: import("@sales-planner/shared").UpdateCompetitorSaleDto;
114
+ }, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<CompetitorSale, Error, {
115
+ id: number;
116
+ data: import("@sales-planner/shared").UpdateCompetitorSaleDto;
117
+ }, unknown>;
118
+ useDelete: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<void, Error, number>, "mutationFn">) => import("@tanstack/react-query").UseMutationResult<void, Error, number, unknown>;
119
+ useImportJson: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<ImportResult, Error, ImportCompetitorSaleItem[], unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<ImportResult, Error, ImportCompetitorSaleItem[], unknown>;
120
+ useImportCsv: (ctx: import("./keys.js").ShopContext, options?: Omit<import("@tanstack/react-query").UseMutationOptions<ImportResult, Error, string, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<ImportResult, Error, string, unknown>;
121
+ };
122
+ //# sourceMappingURL=shop-scoped-entities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shop-scoped-entities.d.ts","sourceRoot":"","sources":["../src/shop-scoped-entities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,GAAG,EACH,gBAAgB,EAEhB,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,yBAAyB,EAEzB,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,iBAAiB,EACjB,QAAQ,EACR,qBAAqB,EAErB,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,gCAAgC,EAEhC,6BAA6B,EAC7B,6BAA6B,EAC7B,oBAAoB,EACpB,iCAAiC,EAEjC,8BAA8B,EAC9B,8BAA8B,EAC9B,iBAAiB,EACjB,8BAA8B,EAE9B,2BAA2B,EAC3B,2BAA2B,EAC3B,cAAc,EACd,2BAA2B,EAE3B,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,uBAAuB,CAAC;AAK/B,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;CAMO,CAAC;AAEzB,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;CAQgB,CAAC;AAE1C,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;CAQY,CAAC;AAEnC,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;CAQwB,CAAC;AAE1D,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;CAQ0B,CAAC;AAE7D,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;CAQsB,CAAC;AAEtD,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;CAQmB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { createShopScopedHooks } from './create-shop-scoped-hooks.js';
2
+ import { createCodedEntityHooks } from './create-coded-entity-hooks.js';
3
+ // SKUs use a custom client, but the interface is the same as CodedEntityClient
4
+ export const skus = createCodedEntityHooks('skus', (c) => c.skus);
5
+ export const salesHistory = createShopScopedHooks('sales-history', (c) => c.salesHistory);
6
+ export const leftovers = createShopScopedHooks('leftovers', (c) => c.leftovers);
7
+ export const seasonalCoefficients = createShopScopedHooks('seasonal-coefficients', (c) => c.seasonalCoefficients);
8
+ export const skuCompetitorMappings = createShopScopedHooks('sku-competitor-mappings', (c) => c.skuCompetitorMappings);
9
+ export const competitorProducts = createShopScopedHooks('competitor-products', (c) => c.competitorProducts);
10
+ export const competitorSales = createShopScopedHooks('competitor-sales', (c) => c.competitorSales);
@@ -0,0 +1,28 @@
1
+ import type { UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
2
+ import type { UserWithRolesAndTenants, EntitiesMetadata, PaginatedResponse, PaginationQuery, SkuMetrics } from '@sales-planner/shared';
3
+ import type { ShopContext } from './keys.js';
4
+ /** Info about a materialized view */
5
+ export interface ViewInfo {
6
+ name: string;
7
+ description: string;
8
+ }
9
+ /** Result of refreshing all materialized views */
10
+ export interface RefreshAllResult {
11
+ results: Array<{
12
+ view: string;
13
+ duration: number;
14
+ success: boolean;
15
+ error?: string;
16
+ }>;
17
+ totalDuration: number;
18
+ success: boolean;
19
+ }
20
+ export declare function useMe(options?: Omit<UseQueryOptions<UserWithRolesAndTenants>, 'queryKey' | 'queryFn'>): import("@tanstack/react-query").UseQueryResult<UserWithRolesAndTenants, Error>;
21
+ export declare function useEntitiesMetadata(options?: Omit<UseQueryOptions<EntitiesMetadata>, 'queryKey' | 'queryFn'>): import("@tanstack/react-query").UseQueryResult<EntitiesMetadata, Error>;
22
+ export declare function useSkuMetrics(ctx: ShopContext, query?: PaginationQuery, options?: Omit<UseQueryOptions<PaginatedResponse<SkuMetrics>>, 'queryKey' | 'queryFn'>): import("@tanstack/react-query").UseQueryResult<PaginatedResponse<SkuMetrics>, Error>;
23
+ export declare function useSkuMetricsById(ctx: ShopContext, id: number, options?: Omit<UseQueryOptions<SkuMetrics>, 'queryKey' | 'queryFn'>): import("@tanstack/react-query").UseQueryResult<SkuMetrics, Error>;
24
+ export declare function useSkuMetricsByAbcClass(ctx: ShopContext, abcClass: 'A' | 'B' | 'C', options?: Omit<UseQueryOptions<SkuMetrics[]>, 'queryKey' | 'queryFn'>): import("@tanstack/react-query").UseQueryResult<SkuMetrics[], Error>;
25
+ export declare function useSkuMetricsExportCsv(ctx: ShopContext, options?: Omit<UseQueryOptions<string>, 'queryKey' | 'queryFn'>): import("@tanstack/react-query").UseQueryResult<string, Error>;
26
+ export declare function useComputedViews(ctx: ShopContext, options?: Omit<UseQueryOptions<ViewInfo[]>, 'queryKey' | 'queryFn'>): import("@tanstack/react-query").UseQueryResult<ViewInfo[], Error>;
27
+ export declare function useRefreshAllViews(ctx: ShopContext, options?: Omit<UseMutationOptions<RefreshAllResult, Error, void>, 'mutationFn'>): import("@tanstack/react-query").UseMutationResult<RefreshAllResult, Error, void, unknown>;
28
+ //# sourceMappingURL=specialized.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specialized.d.ts","sourceRoot":"","sources":["../src/specialized.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACjF,OAAO,KAAK,EACV,uBAAuB,EACvB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,UAAU,EACX,MAAM,uBAAuB,CAAC;AAG/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,qCAAqC;AACrC,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,kDAAkD;AAClD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrF,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;CAClB;AAID,wBAAgB,KAAK,CACnB,OAAO,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,uBAAuB,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC,kFAQjF;AAID,wBAAgB,mBAAmB,CACjC,OAAO,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC,2EAS1E;AAID,wBAAgB,aAAa,CAC3B,GAAG,EAAE,WAAW,EAChB,KAAK,CAAC,EAAE,eAAe,EACvB,OAAO,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC,wFAQvF;AAED,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,WAAW,EAChB,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC,qEAQpE;AAED,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,WAAW,EAChB,QAAQ,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,EACzB,OAAO,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC,uEAQtE;AAED,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,WAAW,EAChB,OAAO,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC,iEAShE;AAID,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,WAAW,EAChB,OAAO,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC,qEAQpE;AAED,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,WAAW,EAChB,OAAO,CAAC,EAAE,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,YAAY,CAAC,6FAYhF"}
@@ -0,0 +1,77 @@
1
+ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
2
+ import { useSalesPlannerClient } from './provider.js';
3
+ import { queryKeys } from './keys.js';
4
+ // ── Me ──
5
+ export function useMe(options) {
6
+ const client = useSalesPlannerClient();
7
+ return useQuery({
8
+ queryKey: queryKeys.me(),
9
+ queryFn: () => client.me.getMe(),
10
+ ...options,
11
+ });
12
+ }
13
+ // ── Metadata ──
14
+ export function useEntitiesMetadata(options) {
15
+ const client = useSalesPlannerClient();
16
+ return useQuery({
17
+ queryKey: queryKeys.metadata(),
18
+ queryFn: () => client.metadata.getEntitiesMetadata(),
19
+ staleTime: Number.POSITIVE_INFINITY, // metadata rarely changes
20
+ ...options,
21
+ });
22
+ }
23
+ // ── SKU Metrics ──
24
+ export function useSkuMetrics(ctx, query, options) {
25
+ const client = useSalesPlannerClient();
26
+ return useQuery({
27
+ queryKey: queryKeys.skuMetricsList(ctx, query),
28
+ queryFn: () => client.skuMetrics.list(ctx.shopId, ctx.tenantId, query),
29
+ ...options,
30
+ });
31
+ }
32
+ export function useSkuMetricsById(ctx, id, options) {
33
+ const client = useSalesPlannerClient();
34
+ return useQuery({
35
+ queryKey: queryKeys.skuMetricsDetail(ctx, id),
36
+ queryFn: () => client.skuMetrics.get(id, ctx.shopId, ctx.tenantId),
37
+ ...options,
38
+ });
39
+ }
40
+ export function useSkuMetricsByAbcClass(ctx, abcClass, options) {
41
+ const client = useSalesPlannerClient();
42
+ return useQuery({
43
+ queryKey: queryKeys.skuMetricsAbc(ctx, abcClass),
44
+ queryFn: () => client.skuMetrics.getByAbcClass(abcClass, ctx.shopId, ctx.tenantId),
45
+ ...options,
46
+ });
47
+ }
48
+ export function useSkuMetricsExportCsv(ctx, options) {
49
+ const client = useSalesPlannerClient();
50
+ return useQuery({
51
+ queryKey: [...queryKeys.skuMetrics(ctx), 'export', 'csv'],
52
+ queryFn: () => client.skuMetrics.exportCsv(ctx.shopId, ctx.tenantId),
53
+ enabled: false,
54
+ ...options,
55
+ });
56
+ }
57
+ // ── Computed Entities (Materialized Views) ──
58
+ export function useComputedViews(ctx, options) {
59
+ const client = useSalesPlannerClient();
60
+ return useQuery({
61
+ queryKey: [...queryKeys.computed(ctx), 'views'],
62
+ queryFn: () => client.computed.getViews(ctx.shopId, ctx.tenantId),
63
+ ...options,
64
+ });
65
+ }
66
+ export function useRefreshAllViews(ctx, options) {
67
+ const client = useSalesPlannerClient();
68
+ const queryClient = useQueryClient();
69
+ return useMutation({
70
+ mutationFn: () => client.computed.refreshAll(ctx.shopId, ctx.tenantId),
71
+ onSuccess: () => {
72
+ // Refresh sku-metrics cache since views were refreshed
73
+ queryClient.invalidateQueries({ queryKey: queryKeys.skuMetrics(ctx) });
74
+ },
75
+ ...options,
76
+ });
77
+ }
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@sales-planner/react",
3
+ "version": "0.2.0",
4
+ "description": "React hooks for Sales Planner API powered by TanStack Query",
5
+ "author": "Damir Manapov",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "sales-planner",
9
+ "react",
10
+ "hooks",
11
+ "tanstack-query",
12
+ "react-query"
13
+ ],
14
+ "type": "module",
15
+ "main": "./dist/index.js",
16
+ "types": "./dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.js"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "README.md"
26
+ ],
27
+ "dependencies": {
28
+ "@sales-planner/http-client": "0.19.2",
29
+ "@sales-planner/shared": "0.17.2"
30
+ },
31
+ "peerDependencies": {
32
+ "@tanstack/react-query": ">=5.0.0",
33
+ "react": ">=18.0.0"
34
+ },
35
+ "devDependencies": {
36
+ "@tanstack/react-query": "^5.80.7",
37
+ "@types/react": "^19.1.8",
38
+ "react": "^19.1.0",
39
+ "typescript": "^5.7.3"
40
+ },
41
+ "scripts": {
42
+ "build": "tsc",
43
+ "typecheck": "tsc --noEmit",
44
+ "lint": "biome lint --error-on-warnings src",
45
+ "format": "biome format --write src",
46
+ "format:check": "biome format src"
47
+ }
48
+ }