@djangocfg/layouts 2.0.5 → 2.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/package.json +10 -5
  2. package/src/contexts/LeadsContext.tsx +156 -0
  3. package/src/contexts/NewsletterContext.tsx +263 -0
  4. package/src/contexts/SupportContext.tsx +256 -0
  5. package/src/contexts/index.ts +59 -0
  6. package/src/contexts/knowbase/ChatContext.tsx +174 -0
  7. package/src/contexts/knowbase/DocumentsContext.tsx +304 -0
  8. package/src/contexts/knowbase/SessionsContext.tsx +174 -0
  9. package/src/contexts/knowbase/index.ts +61 -0
  10. package/src/contexts/payments/BalancesContext.tsx +65 -0
  11. package/src/contexts/payments/CurrenciesContext.tsx +66 -0
  12. package/src/contexts/payments/OverviewContext.tsx +174 -0
  13. package/src/contexts/payments/PaymentsContext.tsx +132 -0
  14. package/src/contexts/payments/README.md +201 -0
  15. package/src/contexts/payments/RootPaymentsContext.tsx +68 -0
  16. package/src/contexts/payments/index.ts +50 -0
  17. package/src/index.ts +4 -1
  18. package/src/layouts/AppLayout/AppLayout.tsx +20 -10
  19. package/src/layouts/PaymentsLayout/PaymentsLayout.tsx +1 -1
  20. package/src/layouts/PaymentsLayout/components/CreatePaymentDialog.tsx +1 -1
  21. package/src/layouts/PaymentsLayout/views/overview/components/BalanceCard.tsx +1 -1
  22. package/src/layouts/PaymentsLayout/views/overview/components/RecentPayments.tsx +1 -1
  23. package/src/layouts/PaymentsLayout/views/transactions/components/TransactionsList.tsx +1 -1
  24. package/src/layouts/ProfileLayout/components/ProfileForm.tsx +1 -1
  25. package/src/layouts/SupportLayout/SupportLayout.tsx +1 -1
  26. package/src/layouts/SupportLayout/components/TicketCard.tsx +1 -1
  27. package/src/layouts/SupportLayout/context/SupportLayoutContext.tsx +1 -1
  28. package/src/layouts/SupportLayout/index.ts +2 -0
  29. package/src/layouts/SupportLayout/types.ts +2 -4
  30. package/src/snippets/Chat/ChatWidget.tsx +1 -1
  31. package/src/snippets/Chat/components/SessionList.tsx +1 -1
  32. package/src/snippets/Chat/index.tsx +1 -1
  33. package/src/snippets/Chat/types.ts +7 -5
  34. package/src/snippets/ContactForm/ContactForm.tsx +20 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/layouts",
3
- "version": "2.0.5",
3
+ "version": "2.0.6",
4
4
  "description": "Simple, straightforward layout components for Next.js - import and use with props",
5
5
  "keywords": [
6
6
  "layouts",
@@ -74,6 +74,11 @@
74
74
  "import": "./src/pages/index.ts",
75
75
  "default": "./src/pages/index.ts"
76
76
  },
77
+ "./contexts": {
78
+ "types": "./src/contexts/index.ts",
79
+ "import": "./src/contexts/index.ts",
80
+ "default": "./src/contexts/index.ts"
81
+ },
77
82
  "./styles": "./src/styles/index.css",
78
83
  "./styles/dashboard": "./src/styles/dashboard.css"
79
84
  },
@@ -87,9 +92,9 @@
87
92
  "check": "tsc --noEmit"
88
93
  },
89
94
  "peerDependencies": {
90
- "@djangocfg/api": "^1.4.35",
91
- "@djangocfg/centrifugo": "^1.4.35",
92
- "@djangocfg/ui": "^1.4.35",
95
+ "@djangocfg/api": "^1.4.36",
96
+ "@djangocfg/centrifugo": "^1.4.36",
97
+ "@djangocfg/ui": "^1.4.36",
93
98
  "@hookform/resolvers": "^5.2.0",
94
99
  "consola": "^3.4.2",
95
100
  "lucide-react": "^0.468.0",
@@ -108,7 +113,7 @@
108
113
  "react-ga4": "^2.1.0"
109
114
  },
110
115
  "devDependencies": {
111
- "@djangocfg/typescript-config": "^1.4.35",
116
+ "@djangocfg/typescript-config": "^1.4.36",
112
117
  "@types/node": "^24.7.2",
113
118
  "@types/react": "19.2.2",
114
119
  "@types/react-dom": "19.2.1",
@@ -0,0 +1,156 @@
1
+ 'use client';
2
+
3
+ import React, { createContext, useContext, type ReactNode } from 'react';
4
+ import { SWRConfig } from 'swr';
5
+ import { api } from '@djangocfg/api';
6
+ import {
7
+ useLeadsList,
8
+ useLeadsRetrieve,
9
+ useCreateLeadsCreate,
10
+ useUpdateLeadsUpdate,
11
+ usePartialUpdateLeadsPartialUpdate,
12
+ useDeleteLeadsDestroy,
13
+ } from '@djangocfg/api';
14
+ import type { API } from '@djangocfg/api';
15
+ import type {
16
+ LeadSubmission,
17
+ LeadSubmissionRequest,
18
+ PatchedLeadSubmissionRequest,
19
+ PaginatedLeadSubmissionList,
20
+ } from '@djangocfg/api';
21
+
22
+ // ─────────────────────────────────────────────────────────────────────────
23
+ // Context Type
24
+ // ─────────────────────────────────────────────────────────────────────────
25
+
26
+ export interface LeadsContextValue {
27
+ // List operations
28
+ leads: PaginatedLeadSubmissionList | undefined;
29
+ isLoadingLeads: boolean;
30
+ leadsError: Error | undefined;
31
+ refreshLeads: () => Promise<void>;
32
+
33
+ // CRUD operations
34
+ getLead: (id: number) => Promise<LeadSubmission | undefined>;
35
+ createLead: (data: LeadSubmissionRequest) => Promise<LeadSubmission>;
36
+ updateLead: (id: number, data: LeadSubmissionRequest) => Promise<LeadSubmission>;
37
+ partialUpdateLead: (id: number, data: PatchedLeadSubmissionRequest) => Promise<LeadSubmission>;
38
+ deleteLead: (id: number) => Promise<void>;
39
+ }
40
+
41
+ // ─────────────────────────────────────────────────────────────────────────
42
+ // Context
43
+ // ─────────────────────────────────────────────────────────────────────────
44
+
45
+ const LeadsContext = createContext<LeadsContextValue | undefined>(undefined);
46
+
47
+ // ─────────────────────────────────────────────────────────────────────────
48
+ // Provider
49
+ // ─────────────────────────────────────────────────────────────────────────
50
+
51
+ export function LeadsProvider({ children }: { children: ReactNode }) {
52
+ const swrConfig = {
53
+ revalidateOnFocus: false,
54
+ revalidateOnReconnect: false,
55
+ revalidateIfStale: false,
56
+ };
57
+
58
+ // List leads
59
+ const {
60
+ data: leads,
61
+ error: leadsError,
62
+ isLoading: isLoadingLeads,
63
+ mutate: mutateLeads,
64
+ } = useLeadsList({}, api as unknown as API);
65
+
66
+ const refreshLeads = async () => {
67
+ await mutateLeads();
68
+ };
69
+
70
+ // Mutations
71
+ const createMutation = useCreateLeadsCreate();
72
+ const updateMutation = useUpdateLeadsUpdate();
73
+ const partialUpdateMutation = usePartialUpdateLeadsPartialUpdate();
74
+ const deleteMutation = useDeleteLeadsDestroy();
75
+
76
+ // Get single lead
77
+ const getLead = async (id: number): Promise<LeadSubmission | undefined> => {
78
+ const { data } = useLeadsRetrieve(id, api as unknown as API);
79
+ return data;
80
+ };
81
+
82
+ // Create lead
83
+ const createLead = async (data: LeadSubmissionRequest): Promise<LeadSubmission> => {
84
+ const result = await createMutation(data, api as unknown as API);
85
+ await refreshLeads();
86
+ return result as LeadSubmission;
87
+ };
88
+
89
+ // Update lead
90
+ const updateLead = async (id: number, data: LeadSubmissionRequest): Promise<LeadSubmission> => {
91
+ const result = await updateMutation(id, data, api as unknown as API);
92
+ await refreshLeads();
93
+ return result as LeadSubmission;
94
+ };
95
+
96
+ // Partial update lead (currently not supported by generated API)
97
+ const partialUpdateLead = async (
98
+ id: number,
99
+ data: PatchedLeadSubmissionRequest
100
+ ): Promise<LeadSubmission> => {
101
+ // TODO: Fix generator to include data parameter for PATCH requests
102
+ // const result = await partialUpdateMutation(id, data, api as unknown as API);
103
+ // For now, fallback to full update
104
+ const result = await updateMutation(id, data as unknown as LeadSubmissionRequest, api as unknown as API);
105
+ await refreshLeads();
106
+ return result as LeadSubmission;
107
+ };
108
+
109
+ // Delete lead
110
+ const deleteLead = async (id: number): Promise<void> => {
111
+ await deleteMutation(id, api as unknown as API);
112
+ await refreshLeads();
113
+ };
114
+
115
+ const value: LeadsContextValue = {
116
+ leads,
117
+ isLoadingLeads,
118
+ leadsError,
119
+ refreshLeads,
120
+ getLead,
121
+ createLead,
122
+ updateLead,
123
+ partialUpdateLead,
124
+ deleteLead,
125
+ };
126
+
127
+ return (
128
+ <SWRConfig value={swrConfig}>
129
+ <LeadsContext.Provider value={value}>{children}</LeadsContext.Provider>
130
+ </SWRConfig>
131
+ );
132
+ }
133
+
134
+ // ─────────────────────────────────────────────────────────────────────────
135
+ // Hook
136
+ // ─────────────────────────────────────────────────────────────────────────
137
+
138
+ export function useLeadsContext(): LeadsContextValue {
139
+ const context = useContext(LeadsContext);
140
+ if (!context) {
141
+ throw new Error('useLeadsContext must be used within LeadsProvider');
142
+ }
143
+ return context;
144
+ }
145
+
146
+ // ─────────────────────────────────────────────────────────────────────────
147
+ // Re-export types for external use
148
+ // ─────────────────────────────────────────────────────────────────────────
149
+
150
+ export type {
151
+ LeadSubmission,
152
+ LeadSubmissionRequest,
153
+ PatchedLeadSubmissionRequest,
154
+ PaginatedLeadSubmissionList,
155
+ };
156
+
@@ -0,0 +1,263 @@
1
+ /**
2
+ * Newsletter Context
3
+ *
4
+ * Manages newsletter campaigns and subscriptions using generated SWR hooks
5
+ *
6
+ * Features:
7
+ * - Campaign management (create, update, delete, send)
8
+ * - Subscription management (subscribe, unsubscribe)
9
+ * - Campaign lists with pagination
10
+ * - Subscription lists with pagination
11
+ */
12
+
13
+ "use client";
14
+
15
+ import { createContext, useContext, ReactNode } from 'react';
16
+ import { SWRConfig, useSWRConfig } from 'swr';
17
+ import { api } from '@djangocfg/api';
18
+ import {
19
+ useNewsletterCampaignsList,
20
+ useNewsletterCampaignsRetrieve,
21
+ useCreateNewsletterCampaignsCreate,
22
+ useUpdateNewsletterCampaignsUpdate,
23
+ usePartialUpdateNewsletterCampaignsPartialUpdate,
24
+ useDeleteNewsletterCampaignsDestroy,
25
+ useCreateNewsletterCampaignsSendCreate,
26
+ useNewsletterSubscriptionsList,
27
+ useCreateNewsletterSubscribeCreate,
28
+ useCreateNewsletterUnsubscribeCreate,
29
+ } from '@djangocfg/api';
30
+ import type { API } from '@djangocfg/api';
31
+ import type {
32
+ NewsletterCampaign,
33
+ NewsletterCampaignRequest,
34
+ PatchedNewsletterCampaignRequest,
35
+ NewsletterSubscription,
36
+ PaginatedNewsletterCampaignList,
37
+ PaginatedNewsletterSubscriptionList,
38
+ SubscribeRequest,
39
+ SubscribeResponse,
40
+ UnsubscribeRequest,
41
+ SuccessResponse,
42
+ SendCampaignRequest,
43
+ SendCampaignResponse,
44
+ } from '@djangocfg/api';
45
+
46
+ // ─────────────────────────────────────────────────────────────────────────
47
+ // Context Type
48
+ // ─────────────────────────────────────────────────────────────────────────
49
+
50
+ export interface NewsletterContextValue {
51
+ // Campaigns list state
52
+ campaigns: NewsletterCampaign[];
53
+ isLoadingCampaigns: boolean;
54
+ campaignsError: Error | null;
55
+ pagination?: {
56
+ count: number;
57
+ next: number | null;
58
+ previous: number | null;
59
+ };
60
+
61
+ // Campaign operations
62
+ getCampaign: (id: number) => { data?: NewsletterCampaign; error?: Error; isLoading: boolean };
63
+ createCampaign: (data: NewsletterCampaignRequest) => Promise<NewsletterCampaign>;
64
+ updateCampaign: (id: number, data: NewsletterCampaignRequest) => Promise<NewsletterCampaign>;
65
+ partialUpdateCampaign: (id: number, data: PatchedNewsletterCampaignRequest) => Promise<NewsletterCampaign>;
66
+ deleteCampaign: (id: number) => Promise<void>;
67
+ sendCampaign: (campaignId: number) => Promise<SendCampaignResponse>;
68
+
69
+ // Subscriptions list state
70
+ subscriptions: NewsletterSubscription[];
71
+ isLoadingSubscriptions: boolean;
72
+ subscriptionsError: Error | null;
73
+
74
+ // Subscription operations
75
+ subscribe: (data: SubscribeRequest) => Promise<SubscribeResponse>;
76
+ unsubscribe: (data: UnsubscribeRequest) => Promise<SuccessResponse>;
77
+ }
78
+
79
+ // ─────────────────────────────────────────────────────────────────────────
80
+ // Context
81
+ // ─────────────────────────────────────────────────────────────────────────
82
+
83
+ const NewsletterContext = createContext<NewsletterContextValue | undefined>(undefined);
84
+
85
+ // ─────────────────────────────────────────────────────────────────────────
86
+ // Provider Props
87
+ // ─────────────────────────────────────────────────────────────────────────
88
+
89
+ interface NewsletterProviderProps {
90
+ children: ReactNode;
91
+ page?: number;
92
+ pageSize?: number;
93
+ }
94
+
95
+ // ─────────────────────────────────────────────────────────────────────────
96
+ // Provider Component
97
+ // ─────────────────────────────────────────────────────────────────────────
98
+
99
+ export function NewsletterProvider({
100
+ children,
101
+ page = 1,
102
+ pageSize = 100
103
+ }: NewsletterProviderProps) {
104
+ const { mutate } = useSWRConfig();
105
+
106
+ const swrConfig = {
107
+ revalidateOnFocus: false,
108
+ revalidateOnReconnect: false,
109
+ revalidateIfStale: false,
110
+ };
111
+
112
+ // List params for proper revalidation
113
+ const listParams = { page, page_size: pageSize };
114
+
115
+ // Campaigns list
116
+ const {
117
+ data: campaignsData,
118
+ error: campaignsError,
119
+ isLoading: isLoadingCampaigns,
120
+ } = useNewsletterCampaignsList(listParams, api as unknown as API);
121
+
122
+ // Subscriptions list
123
+ const {
124
+ data: subscriptionsData,
125
+ error: subscriptionsError,
126
+ isLoading: isLoadingSubscriptions,
127
+ } = useNewsletterSubscriptionsList(listParams, api as unknown as API);
128
+
129
+ // Mutation hooks
130
+ const createCampaignMutation = useCreateNewsletterCampaignsCreate();
131
+ const updateCampaignMutation = useUpdateNewsletterCampaignsUpdate();
132
+ const partialUpdateCampaignMutation = usePartialUpdateNewsletterCampaignsPartialUpdate();
133
+ const deleteCampaignMutation = useDeleteNewsletterCampaignsDestroy();
134
+ const sendCampaignMutation = useCreateNewsletterCampaignsSendCreate();
135
+ const subscribeMutation = useCreateNewsletterSubscribeCreate();
136
+ const unsubscribeMutation = useCreateNewsletterUnsubscribeCreate();
137
+
138
+ // Extract data from paginated responses
139
+ const campaigns = campaignsData?.results || [];
140
+ const subscriptions = subscriptionsData?.results || [];
141
+
142
+ // Get single campaign
143
+ const getCampaign = (id: number) => {
144
+ const { data, error, isLoading } = useNewsletterCampaignsRetrieve(id, api as unknown as API);
145
+ return { data, error, isLoading };
146
+ };
147
+
148
+ // Create campaign
149
+ const createCampaign = async (data: NewsletterCampaignRequest): Promise<NewsletterCampaign> => {
150
+ const result = await createCampaignMutation(data, api as unknown as API);
151
+ await mutate(['cfg-newsletter-campaigns-list', listParams]);
152
+ return result as NewsletterCampaign;
153
+ };
154
+
155
+ // Update campaign (full)
156
+ const updateCampaign = async (id: number, data: NewsletterCampaignRequest): Promise<NewsletterCampaign> => {
157
+ const result = await updateCampaignMutation(id, data, api as unknown as API);
158
+ await mutate(['cfg-newsletter-campaigns-list', listParams]);
159
+ await mutate(['cfg-newsletter-campaigns-retrieve', id]);
160
+ return result as NewsletterCampaign;
161
+ };
162
+
163
+ // Partial update campaign (currently not supported by generated API)
164
+ const partialUpdateCampaign = async (id: number, data: PatchedNewsletterCampaignRequest): Promise<NewsletterCampaign> => {
165
+ // TODO: Fix generator to include data parameter for PATCH requests
166
+ // const result = await partialUpdateCampaignMutation(id, data, api as unknown as API);
167
+ // For now, fallback to full update
168
+ const result = await updateCampaignMutation(id, data as NewsletterCampaignRequest, api as unknown as API);
169
+ await mutate(['cfg-newsletter-campaigns-list', listParams]);
170
+ await mutate(['cfg-newsletter-campaigns-retrieve', id]);
171
+ return result as NewsletterCampaign;
172
+ };
173
+
174
+ // Delete campaign
175
+ const deleteCampaign = async (id: number): Promise<void> => {
176
+ await deleteCampaignMutation(id, api as unknown as API);
177
+ await mutate(['cfg-newsletter-campaigns-list', listParams]);
178
+ };
179
+
180
+ // Send campaign
181
+ const sendCampaign = async (campaignId: number): Promise<SendCampaignResponse> => {
182
+ const result = await sendCampaignMutation({ campaign_id: campaignId }, api as unknown as API);
183
+ await mutate(['cfg-newsletter-campaigns-list', listParams]);
184
+ await mutate(['cfg-newsletter-campaigns-retrieve', campaignId]);
185
+ return result as SendCampaignResponse;
186
+ };
187
+
188
+ // Subscribe
189
+ const subscribe = async (data: SubscribeRequest): Promise<SubscribeResponse> => {
190
+ const result = await subscribeMutation(data, api as unknown as API);
191
+ await mutate(['cfg-newsletter-subscriptions-list', listParams]);
192
+ return result as SubscribeResponse;
193
+ };
194
+
195
+ // Unsubscribe
196
+ const unsubscribe = async (data: UnsubscribeRequest): Promise<SuccessResponse> => {
197
+ const result = await unsubscribeMutation(data, api as unknown as API);
198
+ await mutate(['cfg-newsletter-subscriptions-list', listParams]);
199
+ return result as SuccessResponse;
200
+ };
201
+
202
+ const value: NewsletterContextValue = {
203
+ campaigns,
204
+ isLoadingCampaigns,
205
+ campaignsError,
206
+ pagination: campaignsData ? {
207
+ count: campaignsData.count,
208
+ next: campaignsData.next_page ?? null,
209
+ previous: campaignsData.previous_page ?? null,
210
+ } : undefined,
211
+ getCampaign,
212
+ createCampaign,
213
+ updateCampaign,
214
+ partialUpdateCampaign,
215
+ deleteCampaign,
216
+ sendCampaign,
217
+ subscriptions,
218
+ isLoadingSubscriptions,
219
+ subscriptionsError,
220
+ subscribe,
221
+ unsubscribe,
222
+ };
223
+
224
+ return (
225
+ <SWRConfig value={swrConfig}>
226
+ <NewsletterContext.Provider value={value}>
227
+ {children}
228
+ </NewsletterContext.Provider>
229
+ </SWRConfig>
230
+ );
231
+ }
232
+
233
+ // ─────────────────────────────────────────────────────────────────────────
234
+ // Hook
235
+ // ─────────────────────────────────────────────────────────────────────────
236
+
237
+ export function useNewsletterContext(): NewsletterContextValue {
238
+ const context = useContext(NewsletterContext);
239
+ if (!context) {
240
+ throw new Error('useNewsletterContext must be used within NewsletterProvider');
241
+ }
242
+ return context;
243
+ }
244
+
245
+ // ─────────────────────────────────────────────────────────────────────────
246
+ // Re-export types for external use
247
+ // ─────────────────────────────────────────────────────────────────────────
248
+
249
+ export type {
250
+ NewsletterCampaign,
251
+ NewsletterCampaignRequest,
252
+ PatchedNewsletterCampaignRequest,
253
+ NewsletterSubscription,
254
+ PaginatedNewsletterCampaignList,
255
+ PaginatedNewsletterSubscriptionList,
256
+ SubscribeRequest,
257
+ SubscribeResponse,
258
+ UnsubscribeRequest,
259
+ SuccessResponse,
260
+ SendCampaignRequest,
261
+ SendCampaignResponse,
262
+ };
263
+