@djangocfg/ext-support 1.0.6 → 1.0.7

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 (39) hide show
  1. package/dist/config.cjs +2 -0
  2. package/dist/config.js +2 -0
  3. package/dist/hooks.cjs +74 -79
  4. package/dist/hooks.js +73 -79
  5. package/dist/index.cjs +74 -79
  6. package/dist/index.d.cts +0 -97
  7. package/dist/index.d.ts +0 -97
  8. package/dist/index.js +73 -79
  9. package/package.json +9 -7
  10. package/src/api/generated/ext_support/CLAUDE.md +80 -0
  11. package/src/api/generated/ext_support/_utils/fetchers/ext_support__support.ts +1 -8
  12. package/src/api/generated/ext_support/_utils/fetchers/index.ts +1 -8
  13. package/src/api/generated/ext_support/_utils/hooks/ext_support__support.ts +1 -8
  14. package/src/api/generated/ext_support/_utils/hooks/index.ts +1 -8
  15. package/src/api/generated/ext_support/_utils/schemas/index.ts +1 -8
  16. package/src/api/generated/ext_support/api-instance.ts +1 -8
  17. package/src/api/generated/ext_support/enums.ts +1 -8
  18. package/src/api/generated/ext_support/errors.ts +1 -8
  19. package/src/api/generated/ext_support/ext_support__support/index.ts +1 -8
  20. package/src/api/generated/ext_support/ext_support__support/models.ts +1 -8
  21. package/src/api/generated/ext_support/http.ts +1 -8
  22. package/src/api/generated/ext_support/index.ts +1 -8
  23. package/src/api/generated/ext_support/logger.ts +1 -8
  24. package/src/api/generated/ext_support/retry.ts +1 -8
  25. package/src/api/generated/ext_support/storage.ts +1 -8
  26. package/src/api/generated/ext_support/validation-events.ts +1 -8
  27. package/src/api/index.ts +2 -1
  28. package/src/config.ts +1 -0
  29. package/src/contexts/SupportContext.tsx +9 -13
  30. package/src/contexts/SupportExtensionProvider.tsx +1 -0
  31. package/src/layouts/SupportLayout/SupportLayout.tsx +5 -13
  32. package/src/layouts/SupportLayout/components/CreateTicketDialog.tsx +8 -18
  33. package/src/layouts/SupportLayout/components/MessageInput.tsx +3 -1
  34. package/src/layouts/SupportLayout/components/MessageList.tsx +25 -22
  35. package/src/layouts/SupportLayout/components/TicketCard.tsx +8 -9
  36. package/src/layouts/SupportLayout/components/TicketList.tsx +6 -4
  37. package/src/layouts/SupportLayout/context/SupportLayoutContext.tsx +9 -2
  38. package/src/layouts/SupportLayout/hooks/useInfiniteMessages.ts +2 -0
  39. package/src/layouts/SupportLayout/hooks/useInfiniteTickets.ts +2 -0
package/dist/index.js CHANGED
@@ -2,13 +2,14 @@ import { createConsola, consola } from 'consola';
2
2
  import pRetry, { AbortError } from 'p-retry';
3
3
  import { z } from 'zod';
4
4
  import { createExtensionAPI } from '@djangocfg/ext-base/api';
5
+ import { ArrowLeft, LifeBuoy, Plus, MessageSquare, Loader2, Send, Headphones, User, Clock } from 'lucide-react';
5
6
  import React7, { createContext, useState, useCallback, useEffect, useContext, useRef } from 'react';
7
+ import { Button, ResizablePanelGroup, ResizablePanel, ResizableHandle, Skeleton, ScrollArea, useToast, Textarea, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Form, FormField, FormItem, FormLabel, FormControl, Input, FormMessage, Avatar, AvatarImage, AvatarFallback, Card, CardContent, cn, Badge } from '@djangocfg/ui-nextjs';
6
8
  import useSWR, { useSWRConfig } from 'swr';
7
9
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
+ import moment2 from 'moment';
8
11
  import { useAuth } from '@djangocfg/api/auth';
9
12
  import useSWRInfinite from 'swr/infinite';
10
- import { Button, ResizablePanelGroup, ResizablePanel, ResizableHandle, Skeleton, ScrollArea, useToast, Textarea, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Form, FormField, FormItem, FormLabel, FormControl, Input, FormMessage, Avatar, AvatarImage, AvatarFallback, Card, CardContent, cn, Badge } from '@djangocfg/ui-nextjs';
11
- import { ArrowLeft, LifeBuoy, Plus, MessageSquare, Loader2, Send, Headphones, User, Clock } from 'lucide-react';
12
13
  import { useForm } from 'react-hook-form';
13
14
  import { zodResolver } from '@hookform/resolvers/zod';
14
15
  import { createExtensionConfig } from '@djangocfg/ext-base';
@@ -1775,6 +1776,67 @@ function useSupportContext() {
1775
1776
  }
1776
1777
  return context;
1777
1778
  }
1779
+ var getStatusBadgeVariant = (status) => {
1780
+ switch (status) {
1781
+ case "open":
1782
+ return "default";
1783
+ case "waiting_for_user":
1784
+ return "secondary";
1785
+ case "waiting_for_admin":
1786
+ return "outline";
1787
+ case "resolved":
1788
+ return "outline";
1789
+ case "closed":
1790
+ return "secondary";
1791
+ default:
1792
+ return "default";
1793
+ }
1794
+ };
1795
+ var formatRelativeTime = (date) => {
1796
+ if (!date) return "N/A";
1797
+ const m = moment2.utc(date).local();
1798
+ const now = moment2();
1799
+ const diffInSeconds = now.diff(m, "seconds");
1800
+ if (diffInSeconds < 60) return "Just now";
1801
+ if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
1802
+ if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
1803
+ if (diffInSeconds < 604800) return `${Math.floor(diffInSeconds / 86400)}d ago`;
1804
+ return m.format("MMM D, YYYY");
1805
+ };
1806
+ var TicketCard = ({ ticket, isSelected, onClick }) => {
1807
+ return /* @__PURE__ */ jsx(
1808
+ Card,
1809
+ {
1810
+ className: cn(
1811
+ "cursor-pointer transition-all duration-200 ease-out",
1812
+ "hover:bg-accent/50 hover:shadow-md hover:scale-[1.02]",
1813
+ "active:scale-[0.98]",
1814
+ isSelected && "bg-accent border-primary shadow-sm"
1815
+ ),
1816
+ onClick,
1817
+ children: /* @__PURE__ */ jsxs(CardContent, { className: "p-4", children: [
1818
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between mb-2", children: [
1819
+ /* @__PURE__ */ jsx("h3", { className: "font-semibold text-sm line-clamp-2 flex-1", children: ticket.subject }),
1820
+ (ticket.unanswered_messages_count || 0) > 0 && /* @__PURE__ */ jsx(
1821
+ Badge,
1822
+ {
1823
+ variant: "destructive",
1824
+ className: "ml-2 shrink-0 animate-pulse",
1825
+ children: ticket.unanswered_messages_count
1826
+ }
1827
+ )
1828
+ ] }),
1829
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1830
+ /* @__PURE__ */ jsx(Badge, { variant: getStatusBadgeVariant(ticket.status || "open"), className: "text-xs", children: ticket.status || "open" }),
1831
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
1832
+ /* @__PURE__ */ jsx(Clock, { className: "h-3 w-3" }),
1833
+ /* @__PURE__ */ jsx("span", { children: formatRelativeTime(ticket.created_at) })
1834
+ ] })
1835
+ ] }) })
1836
+ ] })
1837
+ }
1838
+ );
1839
+ };
1778
1840
 
1779
1841
  // src/layouts/SupportLayout/events.ts
1780
1842
  var SUPPORT_LAYOUT_EVENTS = {
@@ -2039,71 +2101,6 @@ function useSupportLayoutContext() {
2039
2101
  }
2040
2102
  return context;
2041
2103
  }
2042
- var getStatusBadgeVariant = (status) => {
2043
- switch (status) {
2044
- case "open":
2045
- return "default";
2046
- case "waiting_for_user":
2047
- return "secondary";
2048
- case "waiting_for_admin":
2049
- return "outline";
2050
- case "resolved":
2051
- return "outline";
2052
- case "closed":
2053
- return "secondary";
2054
- default:
2055
- return "default";
2056
- }
2057
- };
2058
- var formatRelativeTime = (date) => {
2059
- if (!date) return "N/A";
2060
- const now = /* @__PURE__ */ new Date();
2061
- const messageDate = new Date(date);
2062
- const diffInSeconds = Math.floor((now.getTime() - messageDate.getTime()) / 1e3);
2063
- if (diffInSeconds < 60) return "Just now";
2064
- if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
2065
- if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
2066
- if (diffInSeconds < 604800) return `${Math.floor(diffInSeconds / 86400)}d ago`;
2067
- return new Date(date).toLocaleDateString("en-US", {
2068
- year: "numeric",
2069
- month: "short",
2070
- day: "numeric"
2071
- });
2072
- };
2073
- var TicketCard = ({ ticket, isSelected, onClick }) => {
2074
- return /* @__PURE__ */ jsx(
2075
- Card,
2076
- {
2077
- className: cn(
2078
- "cursor-pointer transition-all duration-200 ease-out",
2079
- "hover:bg-accent/50 hover:shadow-md hover:scale-[1.02]",
2080
- "active:scale-[0.98]",
2081
- isSelected && "bg-accent border-primary shadow-sm"
2082
- ),
2083
- onClick,
2084
- children: /* @__PURE__ */ jsxs(CardContent, { className: "p-4", children: [
2085
- /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between mb-2", children: [
2086
- /* @__PURE__ */ jsx("h3", { className: "font-semibold text-sm line-clamp-2 flex-1", children: ticket.subject }),
2087
- (ticket.unanswered_messages_count || 0) > 0 && /* @__PURE__ */ jsx(
2088
- Badge,
2089
- {
2090
- variant: "destructive",
2091
- className: "ml-2 shrink-0 animate-pulse",
2092
- children: ticket.unanswered_messages_count
2093
- }
2094
- )
2095
- ] }),
2096
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
2097
- /* @__PURE__ */ jsx(Badge, { variant: getStatusBadgeVariant(ticket.status || "open"), className: "text-xs", children: ticket.status || "open" }),
2098
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
2099
- /* @__PURE__ */ jsx(Clock, { className: "h-3 w-3" }),
2100
- /* @__PURE__ */ jsx("span", { children: formatRelativeTime(ticket.created_at) })
2101
- ] })
2102
- ] }) })
2103
- ] })
2104
- }
2105
- );
2106
- };
2107
2104
  var TicketList = () => {
2108
2105
  const { selectedTicket, selectTicket } = useSupportLayoutContext();
2109
2106
  const {
@@ -2209,28 +2206,23 @@ var TicketList = () => {
2209
2206
  };
2210
2207
  var formatTime = (date) => {
2211
2208
  if (!date) return "";
2212
- return new Date(date).toLocaleTimeString("en-US", {
2213
- hour: "2-digit",
2214
- minute: "2-digit"
2215
- });
2209
+ return moment2.utc(date).local().format("hh:mm A");
2216
2210
  };
2217
2211
  var formatDate = (date) => {
2218
2212
  if (!date) return "";
2219
- return new Date(date).toLocaleDateString("en-US", {
2220
- year: "numeric",
2221
- month: "short",
2222
- day: "numeric"
2223
- });
2213
+ return moment2.utc(date).local().format("MMM D, YYYY");
2224
2214
  };
2225
2215
  var MessageBubble = ({ message, isFromUser, currentUser }) => {
2226
2216
  const sender = message.sender;
2217
+ const senderInitial = sender?.display_username?.charAt(0)?.toUpperCase() || sender?.initials || "S";
2218
+ const userInitial = currentUser?.display_username?.charAt(0)?.toUpperCase() || currentUser?.email?.charAt(0)?.toUpperCase() || currentUser?.initials || null;
2227
2219
  return /* @__PURE__ */ jsxs(
2228
2220
  "div",
2229
2221
  {
2230
2222
  className: `flex gap-3 ${isFromUser ? "justify-end" : "justify-start"}
2231
2223
  animate-in fade-in slide-in-from-bottom-2 duration-300`,
2232
2224
  children: [
2233
- !isFromUser && /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: sender?.avatar ? /* @__PURE__ */ jsx(AvatarImage, { src: sender.avatar, alt: sender.display_username || "Support" }) : /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary text-primary-foreground", children: sender?.is_staff ? /* @__PURE__ */ jsx(Headphones, { className: "h-4 w-4" }) : sender?.display_username?.charAt(0)?.toUpperCase() || sender?.initials || "S" }) }),
2225
+ !isFromUser && /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: sender?.avatar ? /* @__PURE__ */ jsx(AvatarImage, { src: sender.avatar, alt: sender.display_username || "Support" }) : /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary text-primary-foreground", children: sender?.is_staff ? /* @__PURE__ */ jsx(Headphones, { className: "h-4 w-4" }) : senderInitial }) }),
2234
2226
  /* @__PURE__ */ jsxs("div", { className: `flex flex-col gap-1 flex-1 max-w-[80%] ${isFromUser ? "items-end" : "items-start"}`, children: [
2235
2227
  !isFromUser && sender && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground px-1", children: [
2236
2228
  sender.display_username || sender.email || "Support Team",
@@ -2245,7 +2237,7 @@ var MessageBubble = ({ message, isFromUser, currentUser }) => {
2245
2237
  ),
2246
2238
  /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground px-1", children: formatTime(message.created_at) })
2247
2239
  ] }),
2248
- isFromUser && /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: currentUser?.avatar ? /* @__PURE__ */ jsx(AvatarImage, { src: currentUser.avatar, alt: currentUser.display_username || currentUser.email || "You" }) : /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary/10 text-primary font-semibold", children: currentUser?.display_username?.charAt(0)?.toUpperCase() || currentUser?.email?.charAt(0)?.toUpperCase() || currentUser?.initials || /* @__PURE__ */ jsx(User, { className: "h-4 w-4" }) }) })
2240
+ isFromUser && /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: currentUser?.avatar ? /* @__PURE__ */ jsx(AvatarImage, { src: currentUser.avatar, alt: currentUser.display_username || currentUser.email || "You" }) : /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary/10 text-primary font-semibold", children: userInitial || /* @__PURE__ */ jsx(User, { className: "h-4 w-4" }) }) })
2249
2241
  ]
2250
2242
  }
2251
2243
  );
@@ -2363,7 +2355,7 @@ var MessageList = () => {
2363
2355
  messages.map((message, index) => {
2364
2356
  const isFromUser = message.sender?.id && user?.id && String(message.sender.id) === String(user.id) || message.sender?.email && user?.email && message.sender.email === user.email || message.is_from_author && selectedTicket?.user && user?.id && String(selectedTicket.user) === String(user.id);
2365
2357
  const previousMessage = index > 0 ? messages[index - 1] : null;
2366
- const showDateSeparator = previousMessage && new Date(previousMessage.created_at || "").toDateString() !== new Date(message.created_at || "").toDateString();
2358
+ const showDateSeparator = previousMessage && moment2.utc(previousMessage.created_at || "").format("YYYY-MM-DD") !== moment2.utc(message.created_at || "").format("YYYY-MM-DD");
2367
2359
  return /* @__PURE__ */ jsxs(React7.Fragment, { children: [
2368
2360
  showDateSeparator && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 my-4", children: [
2369
2361
  /* @__PURE__ */ jsx("div", { className: "flex-1 h-px bg-border" }),
@@ -2695,6 +2687,7 @@ var package_default = {
2695
2687
  "@djangocfg/ui-nextjs": "workspace:*",
2696
2688
  consola: "^3.4.2",
2697
2689
  "lucide-react": "^0.545.0",
2690
+ moment: "^2.30.1",
2698
2691
  next: "^15.5.7",
2699
2692
  "p-retry": "^7.0.0",
2700
2693
  react: "^18 || ^19",
@@ -2709,6 +2702,7 @@ var package_default = {
2709
2702
  "@types/node": "^24.7.2",
2710
2703
  "@types/react": "^19.0.0",
2711
2704
  consola: "^3.4.2",
2705
+ moment: "^2.30.1",
2712
2706
  "p-retry": "^7.0.0",
2713
2707
  swr: "^2.3.7",
2714
2708
  tsup: "^8.5.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/ext-support",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Support ticket system extension for DjangoCFG",
5
5
  "keywords": [
6
6
  "django",
@@ -59,11 +59,12 @@
59
59
  "check": "tsc --noEmit"
60
60
  },
61
61
  "peerDependencies": {
62
- "@djangocfg/api": "^2.1.37",
63
- "@djangocfg/ext-base": "^1.0.6",
64
- "@djangocfg/ui-nextjs": "^2.1.37",
62
+ "@djangocfg/api": "^2.1.43",
63
+ "@djangocfg/ext-base": "^1.0.7",
64
+ "@djangocfg/ui-nextjs": "^2.1.43",
65
65
  "consola": "^3.4.2",
66
66
  "lucide-react": "^0.545.0",
67
+ "moment": "^2.30.1",
67
68
  "next": "^15.5.7",
68
69
  "p-retry": "^7.0.0",
69
70
  "react": "^18 || ^19",
@@ -72,12 +73,13 @@
72
73
  "zod": "^4.1.13"
73
74
  },
74
75
  "devDependencies": {
75
- "@djangocfg/api": "^2.1.37",
76
- "@djangocfg/ext-base": "^1.0.6",
77
- "@djangocfg/typescript-config": "^2.1.37",
76
+ "@djangocfg/api": "^2.1.43",
77
+ "@djangocfg/ext-base": "^1.0.7",
78
+ "@djangocfg/typescript-config": "^2.1.43",
78
79
  "@types/node": "^24.7.2",
79
80
  "@types/react": "^19.0.0",
80
81
  "consola": "^3.4.2",
82
+ "moment": "^2.30.1",
81
83
  "p-retry": "^7.0.0",
82
84
  "swr": "^2.3.7",
83
85
  "tsup": "^8.5.0",
@@ -0,0 +1,80 @@
1
+ # Django CFG API - Typescript Client
2
+
3
+ Auto-generated. **Do not edit manually.**
4
+
5
+ ```bash
6
+ python manage.py generate_client --groups ext_support --typescript
7
+ ```
8
+
9
+ ## Stats
10
+
11
+ | | |
12
+ |---|---|
13
+ | Version | 3.0.3 |
14
+ | Operations | 12 |
15
+ | Schemas | 11 |
16
+
17
+ ## Resources
18
+
19
+ - **support** (12 ops)
20
+
21
+ ## Operations
22
+
23
+ **support:**
24
+ - `POST` /cfg/support/tickets/ → `cfg_support_tickets_create`
25
+ - `DELETE` /cfg/support/tickets/{uuid}/ → `cfg_support_tickets_destroy`
26
+ - `GET` /cfg/support/tickets/ → `cfg_support_tickets_list`
27
+ - `POST` /cfg/support/tickets/{ticket_uuid}/messages/ → `cfg_support_tickets_messages_create`
28
+ - `DELETE` /cfg/support/tickets/{ticket_uuid}/messages/{uuid}/ → `cfg_support_tickets_messages_destroy`
29
+ - `GET` /cfg/support/tickets/{ticket_uuid}/messages/ → `cfg_support_tickets_messages_list`
30
+ - `PATCH` /cfg/support/tickets/{ticket_uuid}/messages/{uuid}/ → `cfg_support_tickets_messages_partial_update`
31
+ - `GET` /cfg/support/tickets/{ticket_uuid}/messages/{uuid}/ → `cfg_support_tickets_messages_retrieve`
32
+ - `PUT` /cfg/support/tickets/{ticket_uuid}/messages/{uuid}/ → `cfg_support_tickets_messages_update`
33
+ - `PATCH` /cfg/support/tickets/{uuid}/ → `cfg_support_tickets_partial_update`
34
+ - `GET` /cfg/support/tickets/{uuid}/ → `cfg_support_tickets_retrieve`
35
+ - `PUT` /cfg/support/tickets/{uuid}/ → `cfg_support_tickets_update`
36
+
37
+ ## Usage
38
+
39
+ ```typescript
40
+ import { APIClient } from './';
41
+
42
+ const client = new APIClient({ baseUrl, token });
43
+
44
+ await client.support.list();
45
+ await client.support.retrieve({ id: 1 });
46
+ await client.support.create({ ... });
47
+ ```
48
+
49
+ **SWR Hooks:**
50
+ ```typescript
51
+ import { useSupportList } from './hooks';
52
+ const { data, isLoading } = useSupportList();
53
+ ```
54
+
55
+ ## How It Works
56
+
57
+ ```
58
+ DRF ViewSets → drf-spectacular → OpenAPI → IR Parser → Generator → This Client
59
+ ```
60
+
61
+ **Configuration** (`api/config.py`):
62
+ ```python
63
+ openapi_client = OpenAPIClientConfig(
64
+ enabled=True,
65
+ groups=[OpenAPIGroupConfig(name="ext_support", apps=["..."])],
66
+ generate_zod_schemas=True, # → schemas.ts
67
+ generate_fetchers=True, # → fetchers.ts
68
+ generate_swr_hooks=True, # → hooks.ts
69
+ )
70
+ ```
71
+
72
+ **Copy to Next.js** (if `nextjs_admin` configured):
73
+ ```python
74
+ nextjs_admin = NextJsAdminConfig(
75
+ project_path="../frontend/apps/...",
76
+ api_output_path="app/_lib/api/generated",
77
+ )
78
+ ```
79
+
80
+ @see https://djangocfg.com/docs/features/api-generation
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * Typed fetchers for Support
11
4
  *
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * Typed Fetchers - Universal API functions
11
4
  *
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  'use client';
10
3
 
11
4
  /**
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  'use client';
10
3
 
11
4
  /**
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * Zod Schemas - Runtime validation and type inference
11
4
  *
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * Global API Instance - Singleton configuration
11
4
  *
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * * `open` - Open
11
4
  * * `waiting_for_user` - Waiting for User
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * API Error Classes
11
4
  *
@@ -1,10 +1,3 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  export * from "./client";
10
3
  export * as Models from "./models";
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  import * as Enums from "../enums";
10
3
 
11
4
  /**
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * HTTP Client Adapter Pattern
11
4
  *
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * Django CFG API - API Client with JWT Management
11
4
  *
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * API Logger with Consola
11
4
  * Beautiful console logging for API requests and responses
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * Retry Configuration and Utilities
11
4
  *
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * Storage adapters for cross-platform token storage.
11
4
  *
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * Zod Validation Events - Browser CustomEvent integration
11
4
  *
package/src/api/index.ts CHANGED
@@ -1,9 +1,10 @@
1
+ import { createExtensionAPI } from '@djangocfg/ext-base/api';
2
+
1
3
  /**
2
4
  * Support Extension API
3
5
  *
4
6
  * Pre-configured API instance with shared authentication
5
7
  */
6
8
  import { API } from './generated/ext_support';
7
- import { createExtensionAPI } from '@djangocfg/ext-base/api';
8
9
 
9
10
  export const apiSupport = createExtensionAPI(API);
package/src/config.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import { createExtensionConfig } from '@djangocfg/ext-base';
6
+
6
7
  import packageJson from '../package.json';
7
8
 
8
9
  export const extensionConfig = createExtensionConfig(packageJson, {
@@ -1,20 +1,16 @@
1
1
  'use client';
2
2
 
3
- import React, { createContext, useContext, type ReactNode } from 'react';
3
+ import React, { createContext, ReactNode, useContext } from 'react';
4
+
4
5
  import {
5
- useSupportTicketsList,
6
- useSupportTicketsRetrieve,
7
- useCreateSupportTicketsCreate,
8
- useUpdateSupportTicketsUpdate,
9
- usePartialUpdateSupportTicketsPartialUpdate,
10
- useDeleteSupportTicketsDestroy,
11
- useSupportTicketsMessagesList,
12
- useSupportTicketsMessagesRetrieve,
13
- useCreateSupportTicketsMessagesCreate,
14
- useUpdateSupportTicketsMessagesUpdate,
15
- usePartialUpdateSupportTicketsMessagesPartialUpdate,
16
- useDeleteSupportTicketsMessagesDestroy,
6
+ useCreateSupportTicketsCreate, useCreateSupportTicketsMessagesCreate,
7
+ useDeleteSupportTicketsDestroy, useDeleteSupportTicketsMessagesDestroy,
8
+ usePartialUpdateSupportTicketsMessagesPartialUpdate,
9
+ usePartialUpdateSupportTicketsPartialUpdate, useSupportTicketsList,
10
+ useSupportTicketsMessagesList, useSupportTicketsMessagesRetrieve, useSupportTicketsRetrieve,
11
+ useUpdateSupportTicketsMessagesUpdate, useUpdateSupportTicketsUpdate
17
12
  } from '../api/generated/ext_support/_utils/hooks';
13
+
18
14
  import type {
19
15
  Ticket,
20
16
  TicketRequest,
@@ -8,6 +8,7 @@
8
8
 
9
9
  import type { ReactNode } from 'react';
10
10
  import { ExtensionProvider } from '@djangocfg/ext-base/hooks';
11
+
11
12
  import { extensionConfig } from '../config';
12
13
  import { SupportProvider } from './SupportContext';
13
14
 
@@ -6,22 +6,14 @@
6
6
 
7
7
  'use client';
8
8
 
9
+ import { ArrowLeft, LifeBuoy, Plus } from 'lucide-react';
9
10
  import React from 'react';
11
+
12
+ import { Button, ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@djangocfg/ui-nextjs';
13
+
10
14
  import { SupportProvider } from '../../contexts/SupportContext';
15
+ import { CreateTicketDialog, MessageInput, MessageList, TicketList } from './components';
11
16
  import { SupportLayoutProvider, useSupportLayoutContext } from './context';
12
- import {
13
- TicketList,
14
- MessageList,
15
- MessageInput,
16
- CreateTicketDialog,
17
- } from './components';
18
- import {
19
- Button,
20
- ResizablePanelGroup,
21
- ResizablePanel,
22
- ResizableHandle,
23
- } from '@djangocfg/ui-nextjs';
24
- import { Plus, LifeBuoy, ArrowLeft } from 'lucide-react';
25
17
 
26
18
  // ─────────────────────────────────────────────────────────────────────────
27
19
  // Support Layout Content (with context)