@djangocfg/ext-support 1.0.14 → 1.0.17

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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ![DjangoCFG Extension Preview](https://unpkg.com/@djangocfg/ext-support@latest/preview.png)
4
4
 
5
- **[📦 View in Marketplace](https://hub.djangocfg.com/extensions/djangocfg-ext-support)** **[📖 Documentation](https://djangocfg.com)** **[GitHub](https://github.com/markolofsen/django-cfg)**
5
+ **[View in Marketplace](https://hub.djangocfg.com/extensions/djangocfg-ext-support)** | **[Documentation](https://djangocfg.com)** | **[GitHub](https://github.com/markolofsen/django-cfg)**
6
6
 
7
7
  </div>
8
8
 
@@ -14,14 +14,17 @@ Customer support and ticketing system extension for DjangoCFG.
14
14
 
15
15
  ## Features
16
16
 
17
- - 🎫 **Ticket Management** - Create, track, and resolve support tickets
18
- - 💬 **Real-time Chat** - Live chat support integration
19
- - 📧 **Email Integration** - Convert emails to tickets automatically
20
- - 🏷️ **Categories & Tags** - Organize tickets with custom categories
21
- - 👥 **Team Assignment** - Assign tickets to support agents
22
- - 📊 **Analytics** - Track response times and resolution rates
23
- - 🔔 **Notifications** - Real-time ticket updates
24
- - 📎 **Attachments** - Support for file attachments
17
+ - Ticket Management - Create, track, and resolve support tickets
18
+ - Real-time Messaging - Live chat within tickets
19
+ - Categories & Priority - Organize tickets efficiently
20
+ - Analytics - Track response times and resolution rates
21
+
22
+ ## Requirements
23
+
24
+ - Next.js 16+
25
+ - React 19+
26
+ - @djangocfg/ui-core
27
+ - @djangocfg/ext-base
25
28
 
26
29
  ## Install
27
30
 
@@ -29,169 +32,102 @@ Customer support and ticketing system extension for DjangoCFG.
29
32
  pnpm add @djangocfg/ext-support
30
33
  ```
31
34
 
32
- ## Usage
35
+ ## Quick Start (Next.js App Router)
33
36
 
34
- ### Provider Setup
37
+ ### 1. Create layout.tsx (Server Component for metadata)
35
38
 
36
39
  ```typescript
37
- import { SupportExtensionProvider } from '@djangocfg/ext-support/hooks';
38
-
39
- export default function RootLayout({ children }) {
40
- return (
41
- <SupportExtensionProvider>
42
- {children}
43
- </SupportExtensionProvider>
44
- );
40
+ // app/support/layout.tsx
41
+ import type { Metadata } from 'next';
42
+
43
+ export const metadata: Metadata = {
44
+ title: 'Support',
45
+ description: 'Help and support center',
46
+ };
47
+
48
+ export default function SupportLayout({
49
+ children,
50
+ }: {
51
+ children: React.ReactNode;
52
+ }) {
53
+ return children;
45
54
  }
46
55
  ```
47
56
 
48
- ### Create Support Ticket
57
+ ### 2. Create page.tsx (Client Component)
49
58
 
50
59
  ```typescript
51
- import { useSupportContext } from '@djangocfg/ext-support/hooks';
60
+ // app/support/page.tsx
61
+ 'use client';
52
62
 
53
- function ContactSupport() {
54
- const { createTicket, isCreatingTicket } = useSupportContext();
55
-
56
- const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
57
- e.preventDefault();
58
- const formData = new FormData(e.currentTarget);
59
-
60
- await createTicket({
61
- subject: formData.get('subject') as string,
62
- description: formData.get('description') as string,
63
- category: 'technical',
64
- priority: 'medium',
65
- });
66
- };
63
+ import { SupportLayout } from '@djangocfg/ext-support';
67
64
 
65
+ export default function SupportPage() {
68
66
  return (
69
- <form onSubmit={handleSubmit}>
70
- <input name="subject" placeholder="Subject" required />
71
- <textarea name="description" placeholder="Describe your issue" required />
72
- <button type="submit" disabled={isCreatingTicket}>
73
- {isCreatingTicket ? 'Submitting...' : 'Submit Ticket'}
74
- </button>
75
- </form>
67
+ <SupportLayout>
68
+ {/* Optional: custom content */}
69
+ </SupportLayout>
76
70
  );
77
71
  }
78
72
  ```
79
73
 
80
- ### View Tickets
74
+ That's it! `SupportLayout` includes everything: providers, ticket list, chat panel, and create ticket dialog.
81
75
 
82
- ```typescript
83
- import { useSupportContext } from '@djangocfg/ext-support/hooks';
76
+ ## Custom Integration
84
77
 
85
- function TicketsPage() {
86
- const { tickets, isLoadingTickets, updateTicket } = useSupportContext();
78
+ If you need more control, use individual components:
87
79
 
88
- const handleStatusChange = async (ticketId: string, status: string) => {
89
- await updateTicket(ticketId, { status });
90
- };
91
-
92
- return (
93
- <div>
94
- <h2>Support Tickets</h2>
95
- {tickets.map(ticket => (
96
- <div key={ticket.id}>
97
- <h3>{ticket.subject}</h3>
98
- <p>{ticket.description}</p>
99
- <span>Status: {ticket.status}</span>
100
- <span>Priority: {ticket.priority}</span>
101
- <select
102
- value={ticket.status}
103
- onChange={(e) => handleStatusChange(ticket.id, e.target.value)}
104
- >
105
- <option value="open">Open</option>
106
- <option value="in_progress">In Progress</option>
107
- <option value="resolved">Resolved</option>
108
- <option value="closed">Closed</option>
109
- </select>
110
- </div>
111
- ))}
112
- </div>
113
- );
114
- }
115
- ```
116
-
117
- ### Ticket Details with Comments
80
+ ### Provider Setup
118
81
 
119
82
  ```typescript
120
- import { useSupportContext } from '@djangocfg/ext-support/hooks';
121
-
122
- function TicketDetails({ ticketId }: { ticketId: string }) {
123
- const { getTicketById, addComment } = useSupportContext();
124
- const [ticket, setTicket] = useState(null);
83
+ // app/providers.tsx
84
+ 'use client';
125
85
 
126
- useEffect(() => {
127
- getTicketById(ticketId).then(setTicket);
128
- }, [ticketId]);
129
-
130
- const handleAddComment = async (text: string) => {
131
- await addComment(ticketId, {
132
- text,
133
- is_internal: false,
134
- });
135
- // Refresh ticket
136
- getTicketById(ticketId).then(setTicket);
137
- };
138
-
139
- if (!ticket) return <div>Loading...</div>;
86
+ import { SupportProvider } from '@djangocfg/ext-support/hooks';
140
87
 
88
+ export function Providers({ children }: { children: React.ReactNode }) {
141
89
  return (
142
- <div>
143
- <h2>{ticket.subject}</h2>
144
- <p>{ticket.description}</p>
145
-
146
- <div>
147
- <h3>Comments</h3>
148
- {ticket.comments?.map(comment => (
149
- <div key={comment.id}>
150
- <strong>{comment.author}</strong>
151
- <p>{comment.text}</p>
152
- <span>{new Date(comment.created_at).toLocaleString()}</span>
153
- </div>
154
- ))}
155
- </div>
156
-
157
- <textarea
158
- placeholder="Add a comment..."
159
- onKeyDown={(e) => {
160
- if (e.key === 'Enter' && !e.shiftKey) {
161
- e.preventDefault();
162
- handleAddComment(e.currentTarget.value);
163
- e.currentTarget.value = '';
164
- }
165
- }}
166
- />
167
- </div>
90
+ <SupportProvider>
91
+ {children}
92
+ </SupportProvider>
168
93
  );
169
94
  }
170
95
  ```
171
96
 
172
- ### Ticket Filters
97
+ ### Using Context Hooks
173
98
 
174
99
  ```typescript
100
+ 'use client';
101
+
175
102
  import { useSupportContext } from '@djangocfg/ext-support/hooks';
176
103
 
177
- function TicketFilters() {
178
- const { tickets, filterTickets } = useSupportContext();
104
+ function MyTicketList() {
105
+ const {
106
+ tickets,
107
+ isLoadingTickets,
108
+ createTicket,
109
+ refreshTickets
110
+ } = useSupportContext();
179
111
 
180
- const handleFilter = (status: string) => {
181
- filterTickets({ status });
112
+ const handleCreate = async () => {
113
+ await createTicket({
114
+ subject: 'New ticket',
115
+ message: 'Description here',
116
+ });
117
+ await refreshTickets();
182
118
  };
183
119
 
120
+ if (isLoadingTickets) return <div>Loading...</div>;
121
+
184
122
  return (
185
123
  <div>
186
- <button onClick={() => handleFilter('open')}>
187
- Open ({tickets.filter(t => t.status === 'open').length})
188
- </button>
189
- <button onClick={() => handleFilter('in_progress')}>
190
- In Progress ({tickets.filter(t => t.status === 'in_progress').length})
191
- </button>
192
- <button onClick={() => handleFilter('resolved')}>
193
- Resolved ({tickets.filter(t => t.status === 'resolved').length})
194
- </button>
124
+ <button onClick={handleCreate}>Create Ticket</button>
125
+ {tickets?.map(ticket => (
126
+ <div key={ticket.uuid}>
127
+ <h3>{ticket.subject}</h3>
128
+ <span>Status: {ticket.status}</span>
129
+ </div>
130
+ ))}
195
131
  </div>
196
132
  );
197
133
  }
@@ -199,38 +135,69 @@ function TicketFilters() {
199
135
 
200
136
  ## API Reference
201
137
 
202
- ### Support Context
138
+ ### SupportContext
203
139
 
204
- - `tickets` - List of all tickets
205
- - `createTicket(data)` - Create new ticket
206
- - `updateTicket(id, data)` - Update ticket
207
- - `deleteTicket(id)` - Delete ticket
208
- - `getTicketById(id)` - Get ticket details
209
- - `addComment(ticketId, data)` - Add comment to ticket
210
- - `assignTicket(ticketId, agentId)` - Assign ticket to agent
211
- - `closeTicket(id)` - Close ticket
212
- - `reopenTicket(id)` - Reopen closed ticket
213
- - `filterTickets(filters)` - Filter tickets by criteria
214
- - `isLoadingTickets` - Loading state
215
- - `isCreatingTicket` - Creation state
140
+ ```typescript
141
+ interface SupportContextValue {
142
+ // Tickets
143
+ tickets: Ticket[] | undefined;
144
+ isLoadingTickets: boolean;
145
+ ticketsError: Error | undefined;
146
+ refreshTickets: () => Promise<void>;
147
+
148
+ // Ticket operations
149
+ getTicket: (uuid: string) => Promise<Ticket | undefined>;
150
+ createTicket: (data: TicketRequest) => Promise<Ticket>;
151
+ updateTicket: (uuid: string, data: TicketRequest) => Promise<Ticket>;
152
+ partialUpdateTicket: (uuid: string, data: PatchedTicketRequest) => Promise<Ticket>;
153
+ deleteTicket: (uuid: string) => Promise<void>;
154
+
155
+ // Messages
156
+ getMessages: (ticketUuid: string) => Promise<Message[] | undefined>;
157
+ createMessage: (ticketUuid: string, data: MessageCreateRequest) => Promise<Message>;
158
+ updateMessage: (ticketUuid: string, messageUuid: string, data: MessageRequest) => Promise<Message>;
159
+ deleteMessage: (ticketUuid: string, messageUuid: string) => Promise<void>;
160
+ refreshMessages: (ticketUuid: string) => Promise<void>;
161
+ }
162
+ ```
216
163
 
217
- ## Ticket Properties
164
+ ### Ticket Type
218
165
 
219
166
  ```typescript
220
167
  interface Ticket {
221
- id: string;
168
+ uuid: string;
222
169
  subject: string;
223
- description: string;
224
170
  status: 'open' | 'in_progress' | 'resolved' | 'closed';
225
- priority: 'low' | 'medium' | 'high' | 'urgent';
226
- category: string;
227
- assigned_to?: string;
228
171
  created_at: string;
229
172
  updated_at: string;
230
- comments?: Comment[];
231
173
  }
232
174
  ```
233
175
 
176
+ ### TicketRequest Type
177
+
178
+ ```typescript
179
+ interface TicketRequest {
180
+ subject: string;
181
+ message: string;
182
+ }
183
+ ```
184
+
185
+ ## Exports
186
+
187
+ ```typescript
188
+ // Main layout (includes all UI)
189
+ import { SupportLayout } from '@djangocfg/ext-support';
190
+
191
+ // Hooks and context
192
+ import {
193
+ SupportProvider,
194
+ useSupportContext
195
+ } from '@djangocfg/ext-support/hooks';
196
+
197
+ // Server-safe config
198
+ import { extensionConfig } from '@djangocfg/ext-support/config';
199
+ ```
200
+
234
201
  ## License
235
202
 
236
203
  MIT
package/dist/config.cjs CHANGED
@@ -27,7 +27,7 @@ var import_ext_base = require("@djangocfg/ext-base");
27
27
  // package.json
28
28
  var package_default = {
29
29
  name: "@djangocfg/ext-support",
30
- version: "1.0.14",
30
+ version: "1.0.17",
31
31
  description: "Support ticket system extension for DjangoCFG",
32
32
  keywords: [
33
33
  "django",
@@ -95,7 +95,7 @@ var package_default = {
95
95
  next: "^16",
96
96
  "p-retry": "^7.0.0",
97
97
  react: "^19",
98
- "react-hook-form": "7.65.0",
98
+ "react-hook-form": "^7.69.0",
99
99
  swr: "^2.3.7",
100
100
  zod: "^4.1.13"
101
101
  },
package/dist/config.js CHANGED
@@ -4,7 +4,7 @@ import { createExtensionConfig } from "@djangocfg/ext-base";
4
4
  // package.json
5
5
  var package_default = {
6
6
  name: "@djangocfg/ext-support",
7
- version: "1.0.14",
7
+ version: "1.0.17",
8
8
  description: "Support ticket system extension for DjangoCFG",
9
9
  keywords: [
10
10
  "django",
@@ -72,7 +72,7 @@ var package_default = {
72
72
  next: "^16",
73
73
  "p-retry": "^7.0.0",
74
74
  react: "^19",
75
- "react-hook-form": "7.65.0",
75
+ "react-hook-form": "^7.69.0",
76
76
  swr: "^2.3.7",
77
77
  zod: "^4.1.13"
78
78
  },
package/dist/hooks.cjs CHANGED
@@ -2656,7 +2656,7 @@ var SupportLayout = () => {
2656
2656
  // package.json
2657
2657
  var package_default = {
2658
2658
  name: "@djangocfg/ext-support",
2659
- version: "1.0.14",
2659
+ version: "1.0.17",
2660
2660
  description: "Support ticket system extension for DjangoCFG",
2661
2661
  keywords: [
2662
2662
  "django",
@@ -2724,7 +2724,7 @@ var package_default = {
2724
2724
  next: "^16",
2725
2725
  "p-retry": "^7.0.0",
2726
2726
  react: "^19",
2727
- "react-hook-form": "7.65.0",
2727
+ "react-hook-form": "^7.69.0",
2728
2728
  swr: "^2.3.7",
2729
2729
  zod: "^4.1.13"
2730
2730
  },
package/dist/hooks.js CHANGED
@@ -2646,7 +2646,7 @@ var SupportLayout = () => {
2646
2646
  // package.json
2647
2647
  var package_default = {
2648
2648
  name: "@djangocfg/ext-support",
2649
- version: "1.0.14",
2649
+ version: "1.0.17",
2650
2650
  description: "Support ticket system extension for DjangoCFG",
2651
2651
  keywords: [
2652
2652
  "django",
@@ -2714,7 +2714,7 @@ var package_default = {
2714
2714
  next: "^16",
2715
2715
  "p-retry": "^7.0.0",
2716
2716
  react: "^19",
2717
- "react-hook-form": "7.65.0",
2717
+ "react-hook-form": "^7.69.0",
2718
2718
  swr: "^2.3.7",
2719
2719
  zod: "^4.1.13"
2720
2720
  },
package/dist/index.cjs CHANGED
@@ -2656,7 +2656,7 @@ var SupportLayout = () => {
2656
2656
  // package.json
2657
2657
  var package_default = {
2658
2658
  name: "@djangocfg/ext-support",
2659
- version: "1.0.14",
2659
+ version: "1.0.17",
2660
2660
  description: "Support ticket system extension for DjangoCFG",
2661
2661
  keywords: [
2662
2662
  "django",
@@ -2724,7 +2724,7 @@ var package_default = {
2724
2724
  next: "^16",
2725
2725
  "p-retry": "^7.0.0",
2726
2726
  react: "^19",
2727
- "react-hook-form": "7.65.0",
2727
+ "react-hook-form": "^7.69.0",
2728
2728
  swr: "^2.3.7",
2729
2729
  zod: "^4.1.13"
2730
2730
  },
package/dist/index.js CHANGED
@@ -2646,7 +2646,7 @@ var SupportLayout = () => {
2646
2646
  // package.json
2647
2647
  var package_default = {
2648
2648
  name: "@djangocfg/ext-support",
2649
- version: "1.0.14",
2649
+ version: "1.0.17",
2650
2650
  description: "Support ticket system extension for DjangoCFG",
2651
2651
  keywords: [
2652
2652
  "django",
@@ -2714,7 +2714,7 @@ var package_default = {
2714
2714
  next: "^16",
2715
2715
  "p-retry": "^7.0.0",
2716
2716
  react: "^19",
2717
- "react-hook-form": "7.65.0",
2717
+ "react-hook-form": "^7.69.0",
2718
2718
  swr: "^2.3.7",
2719
2719
  zod: "^4.1.13"
2720
2720
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/ext-support",
3
- "version": "1.0.14",
3
+ "version": "1.0.17",
4
4
  "description": "Support ticket system extension for DjangoCFG",
5
5
  "keywords": [
6
6
  "django",
@@ -59,24 +59,24 @@
59
59
  "check": "tsc --noEmit"
60
60
  },
61
61
  "peerDependencies": {
62
- "@djangocfg/api": "^2.1.107",
63
- "@djangocfg/ext-base": "^1.0.9",
64
- "@djangocfg/ui-core": "^2.1.107",
62
+ "@djangocfg/api": "^2.1.108",
63
+ "@djangocfg/ext-base": "^1.0.12",
64
+ "@djangocfg/ui-core": "^2.1.108",
65
65
  "consola": "^3.4.2",
66
66
  "lucide-react": "^0.545.0",
67
67
  "moment": "^2.30.1",
68
68
  "next": "^16",
69
69
  "p-retry": "^7.0.0",
70
70
  "react": "^19",
71
- "react-hook-form": "7.65.0",
71
+ "react-hook-form": "^7.69.0",
72
72
  "swr": "^2.3.7",
73
73
  "zod": "^4.1.13"
74
74
  },
75
75
  "devDependencies": {
76
- "@djangocfg/api": "^2.1.107",
77
- "@djangocfg/ext-base": "^1.0.9",
78
- "@djangocfg/ui-core": "^2.1.107",
79
- "@djangocfg/typescript-config": "^2.1.107",
76
+ "@djangocfg/api": "^2.1.108",
77
+ "@djangocfg/ext-base": "^1.0.12",
78
+ "@djangocfg/ui-core": "^2.1.108",
79
+ "@djangocfg/typescript-config": "^2.1.108",
80
80
  "@types/node": "^24.7.2",
81
81
  "@types/react": "^19.0.0",
82
82
  "consola": "^3.4.2",