@djangocfg/layouts 1.0.1

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 (138) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +77 -0
  3. package/package.json +86 -0
  4. package/src/auth/README.md +962 -0
  5. package/src/auth/context/AuthContext.tsx +458 -0
  6. package/src/auth/context/index.ts +2 -0
  7. package/src/auth/context/types.ts +63 -0
  8. package/src/auth/hooks/index.ts +6 -0
  9. package/src/auth/hooks/useAuthForm.ts +329 -0
  10. package/src/auth/hooks/useAuthGuard.ts +23 -0
  11. package/src/auth/hooks/useAuthRedirect.ts +51 -0
  12. package/src/auth/hooks/useAutoAuth.ts +42 -0
  13. package/src/auth/hooks/useLocalStorage.ts +211 -0
  14. package/src/auth/hooks/useSessionStorage.ts +186 -0
  15. package/src/auth/index.ts +10 -0
  16. package/src/auth/middlewares/index.ts +1 -0
  17. package/src/auth/middlewares/proxy.ts +24 -0
  18. package/src/auth/server.ts +6 -0
  19. package/src/auth/utils/errors.ts +34 -0
  20. package/src/auth/utils/index.ts +2 -0
  21. package/src/auth/utils/validation.ts +14 -0
  22. package/src/index.ts +15 -0
  23. package/src/layouts/AppLayout/AppLayout.tsx +123 -0
  24. package/src/layouts/AppLayout/README.md +204 -0
  25. package/src/layouts/AppLayout/SUMMARY.md +240 -0
  26. package/src/layouts/AppLayout/USAGE.md +312 -0
  27. package/src/layouts/AppLayout/components/PageProgress.tsx +104 -0
  28. package/src/layouts/AppLayout/components/Seo.tsx +87 -0
  29. package/src/layouts/AppLayout/components/index.ts +6 -0
  30. package/src/layouts/AppLayout/context/AppContext.tsx +146 -0
  31. package/src/layouts/AppLayout/context/index.ts +5 -0
  32. package/src/layouts/AppLayout/hooks/index.ts +6 -0
  33. package/src/layouts/AppLayout/hooks/useLayoutMode.ts +26 -0
  34. package/src/layouts/AppLayout/hooks/useNavigation.ts +49 -0
  35. package/src/layouts/AppLayout/index.ts +31 -0
  36. package/src/layouts/AppLayout/layouts/AuthLayout/AuthContext.tsx +51 -0
  37. package/src/layouts/AppLayout/layouts/AuthLayout/AuthHelp.tsx +111 -0
  38. package/src/layouts/AppLayout/layouts/AuthLayout/AuthLayout.tsx +40 -0
  39. package/src/layouts/AppLayout/layouts/AuthLayout/IdentifierForm.tsx +330 -0
  40. package/src/layouts/AppLayout/layouts/AuthLayout/OTPForm.tsx +158 -0
  41. package/src/layouts/AppLayout/layouts/AuthLayout/index.ts +13 -0
  42. package/src/layouts/AppLayout/layouts/AuthLayout/types.ts +61 -0
  43. package/src/layouts/AppLayout/layouts/PrivateLayout/PrivateLayout.tsx +92 -0
  44. package/src/layouts/AppLayout/layouts/PrivateLayout/components/DashboardContent.tsx +60 -0
  45. package/src/layouts/AppLayout/layouts/PrivateLayout/components/DashboardHeader.tsx +170 -0
  46. package/src/layouts/AppLayout/layouts/PrivateLayout/components/DashboardSidebar.tsx +164 -0
  47. package/src/layouts/AppLayout/layouts/PrivateLayout/components/index.ts +7 -0
  48. package/src/layouts/AppLayout/layouts/PrivateLayout/index.ts +5 -0
  49. package/src/layouts/AppLayout/layouts/PublicLayout/PublicLayout.tsx +44 -0
  50. package/src/layouts/AppLayout/layouts/PublicLayout/components/DesktopUserMenu.tsx +136 -0
  51. package/src/layouts/AppLayout/layouts/PublicLayout/components/Footer.tsx +262 -0
  52. package/src/layouts/AppLayout/layouts/PublicLayout/components/MobileMenu.tsx +289 -0
  53. package/src/layouts/AppLayout/layouts/PublicLayout/components/Navigation.tsx +159 -0
  54. package/src/layouts/AppLayout/layouts/PublicLayout/index.ts +5 -0
  55. package/src/layouts/AppLayout/layouts/index.ts +7 -0
  56. package/src/layouts/AppLayout/providers/CoreProviders.tsx +47 -0
  57. package/src/layouts/AppLayout/providers/index.ts +5 -0
  58. package/src/layouts/AppLayout/types/config.ts +40 -0
  59. package/src/layouts/AppLayout/types/index.ts +10 -0
  60. package/src/layouts/AppLayout/types/layout.ts +47 -0
  61. package/src/layouts/AppLayout/types/navigation.ts +41 -0
  62. package/src/layouts/AppLayout/types/routes.ts +45 -0
  63. package/src/layouts/AppLayout/utils/index.ts +5 -0
  64. package/src/layouts/AppLayout/utils/routeDetection.ts +31 -0
  65. package/src/layouts/PaymentsLayout/PaymentsLayout.tsx +125 -0
  66. package/src/layouts/PaymentsLayout/README.md +133 -0
  67. package/src/layouts/PaymentsLayout/components/CreateApiKeyDialog.tsx +172 -0
  68. package/src/layouts/PaymentsLayout/components/CreatePaymentDialog.tsx +203 -0
  69. package/src/layouts/PaymentsLayout/components/DeleteApiKeyDialog.tsx +100 -0
  70. package/src/layouts/PaymentsLayout/components/index.ts +4 -0
  71. package/src/layouts/PaymentsLayout/events.ts +106 -0
  72. package/src/layouts/PaymentsLayout/index.ts +20 -0
  73. package/src/layouts/PaymentsLayout/types.ts +19 -0
  74. package/src/layouts/PaymentsLayout/views/apikeys/components/ApiKeyMetrics.tsx +109 -0
  75. package/src/layouts/PaymentsLayout/views/apikeys/components/ApiKeysList.tsx +194 -0
  76. package/src/layouts/PaymentsLayout/views/apikeys/components/index.ts +3 -0
  77. package/src/layouts/PaymentsLayout/views/apikeys/index.tsx +19 -0
  78. package/src/layouts/PaymentsLayout/views/overview/components/BalanceCard.tsx +99 -0
  79. package/src/layouts/PaymentsLayout/views/overview/components/MetricsCards.tsx +103 -0
  80. package/src/layouts/PaymentsLayout/views/overview/components/RecentPayments.tsx +138 -0
  81. package/src/layouts/PaymentsLayout/views/overview/components/index.ts +4 -0
  82. package/src/layouts/PaymentsLayout/views/overview/index.tsx +23 -0
  83. package/src/layouts/PaymentsLayout/views/payments/components/PaymentsList.tsx +282 -0
  84. package/src/layouts/PaymentsLayout/views/payments/components/index.ts +2 -0
  85. package/src/layouts/PaymentsLayout/views/payments/index.tsx +18 -0
  86. package/src/layouts/PaymentsLayout/views/tariffs/index.tsx +29 -0
  87. package/src/layouts/PaymentsLayout/views/transactions/index.tsx +29 -0
  88. package/src/layouts/ProfileLayout/ProfileLayout.tsx +110 -0
  89. package/src/layouts/ProfileLayout/components/AvatarSection.tsx +146 -0
  90. package/src/layouts/ProfileLayout/components/ProfileForm.tsx +208 -0
  91. package/src/layouts/ProfileLayout/components/index.ts +3 -0
  92. package/src/layouts/ProfileLayout/index.ts +3 -0
  93. package/src/layouts/SupportLayout/README.md +91 -0
  94. package/src/layouts/SupportLayout/SupportLayout.tsx +178 -0
  95. package/src/layouts/SupportLayout/components/CreateTicketDialog.tsx +154 -0
  96. package/src/layouts/SupportLayout/components/MessageInput.tsx +92 -0
  97. package/src/layouts/SupportLayout/components/MessageList.tsx +312 -0
  98. package/src/layouts/SupportLayout/components/TicketCard.tsx +96 -0
  99. package/src/layouts/SupportLayout/components/TicketList.tsx +152 -0
  100. package/src/layouts/SupportLayout/components/index.ts +6 -0
  101. package/src/layouts/SupportLayout/context/SupportLayoutContext.tsx +260 -0
  102. package/src/layouts/SupportLayout/context/index.ts +2 -0
  103. package/src/layouts/SupportLayout/events.ts +31 -0
  104. package/src/layouts/SupportLayout/hooks/index.ts +2 -0
  105. package/src/layouts/SupportLayout/hooks/useInfiniteMessages.ts +118 -0
  106. package/src/layouts/SupportLayout/hooks/useInfiniteTickets.ts +91 -0
  107. package/src/layouts/SupportLayout/index.ts +6 -0
  108. package/src/layouts/SupportLayout/types.ts +23 -0
  109. package/src/layouts/index.ts +9 -0
  110. package/src/snippets/AuthDialog/AuthDialog.tsx +88 -0
  111. package/src/snippets/AuthDialog/events.ts +21 -0
  112. package/src/snippets/AuthDialog/index.ts +3 -0
  113. package/src/snippets/AuthDialog/useAuthDialog.ts +27 -0
  114. package/src/snippets/Breadcrumbs.tsx +80 -0
  115. package/src/snippets/Chat/ChatUIContext.tsx +110 -0
  116. package/src/snippets/Chat/ChatWidget.tsx +476 -0
  117. package/src/snippets/Chat/README.md +122 -0
  118. package/src/snippets/Chat/components/MessageInput.tsx +124 -0
  119. package/src/snippets/Chat/components/MessageList.tsx +168 -0
  120. package/src/snippets/Chat/components/SessionList.tsx +192 -0
  121. package/src/snippets/Chat/components/index.ts +9 -0
  122. package/src/snippets/Chat/hooks/index.ts +6 -0
  123. package/src/snippets/Chat/hooks/useInfiniteSessions.ts +83 -0
  124. package/src/snippets/Chat/index.tsx +44 -0
  125. package/src/snippets/Chat/types.ts +79 -0
  126. package/src/snippets/VideoPlayer/README.md +203 -0
  127. package/src/snippets/VideoPlayer/VideoControls.tsx +133 -0
  128. package/src/snippets/VideoPlayer/VideoPlayer.tsx +114 -0
  129. package/src/snippets/VideoPlayer/index.ts +8 -0
  130. package/src/snippets/VideoPlayer/types.ts +61 -0
  131. package/src/snippets/index.ts +10 -0
  132. package/src/styles/dashboard.css +41 -0
  133. package/src/styles/index.css +20 -0
  134. package/src/styles/sources.css +6 -0
  135. package/src/types/index.ts +1 -0
  136. package/src/types/pageConfig.ts +103 -0
  137. package/src/utils/index.ts +6 -0
  138. package/src/utils/logger.ts +57 -0
@@ -0,0 +1,9 @@
1
+ // ============================================================================
2
+ // Layouts - Page Layout Components
3
+ // ============================================================================
4
+
5
+
6
+ export * from './ProfileLayout';
7
+ export * from './SupportLayout';
8
+ export * from './PaymentsLayout';
9
+ export * from './AppLayout';
@@ -0,0 +1,88 @@
1
+ 'use client';
2
+
3
+ import { LogIn } from 'lucide-react';
4
+ import { useRouter } from 'next/navigation';
5
+ import React, { useState } from 'react';
6
+
7
+ import {
8
+ Button,
9
+ Dialog,
10
+ DialogContent,
11
+ DialogHeader,
12
+ DialogTitle,
13
+ } from '@djangocfg/ui/components';
14
+ import { useEventListener } from '@djangocfg/ui/hooks';
15
+
16
+ // Re-export events for backwards compatibility
17
+ export const DIALOG_EVENTS = {
18
+ OPEN_AUTH_DIALOG: 'OPEN_AUTH_DIALOG',
19
+ CLOSE_AUTH_DIALOG: 'CLOSE_AUTH_DIALOG',
20
+ AUTH_SUCCESS: 'AUTH_SUCCESS',
21
+ AUTH_FAILURE: 'AUTH_FAILURE',
22
+ } as const;
23
+
24
+ interface AuthDialogProps {
25
+ onAuthRequired?: () => void;
26
+ authPath?: string;
27
+ }
28
+
29
+ export const AuthDialog: React.FC<AuthDialogProps> = ({
30
+ onAuthRequired,
31
+ authPath = '/auth'
32
+ }) => {
33
+ const [open, setOpen] = useState(false);
34
+ const [message, setMessage] = useState<string>('Please sign in to continue');
35
+ const router = useRouter();
36
+
37
+ // Listen for open auth dialog event
38
+ useEventListener(DIALOG_EVENTS.OPEN_AUTH_DIALOG, (payload: any) => {
39
+ if (payload?.message) {
40
+ setMessage(payload.message);
41
+ }
42
+ setOpen(true);
43
+ });
44
+
45
+ // Listen for close auth dialog event
46
+ useEventListener(DIALOG_EVENTS.CLOSE_AUTH_DIALOG, () => {
47
+ setOpen(false);
48
+ });
49
+
50
+ const handleClose = () => {
51
+ setMessage('Please sign in to continue');
52
+ setOpen(false);
53
+ };
54
+
55
+ const handleGoToAuth = () => {
56
+ // Save current URL for redirect after successful auth
57
+ if (typeof window !== 'undefined') {
58
+ sessionStorage.setItem('redirectAfterAuth', window.location.pathname);
59
+ }
60
+
61
+ if (onAuthRequired) {
62
+ onAuthRequired();
63
+ } else {
64
+ router.push(authPath);
65
+ }
66
+
67
+ handleClose();
68
+ };
69
+
70
+ return (
71
+ <Dialog open={open} onOpenChange={handleClose}>
72
+ <DialogContent className="max-w-sm">
73
+ <DialogHeader>
74
+ <DialogTitle>Authentication Required</DialogTitle>
75
+ </DialogHeader>
76
+
77
+ <div className="space-y-4">
78
+ <p className="text-sm text-muted-foreground">{message}</p>
79
+
80
+ <Button onClick={handleGoToAuth} className="w-full">
81
+ <LogIn className="h-4 w-4 mr-2" />
82
+ Go to Sign In
83
+ </Button>
84
+ </div>
85
+ </DialogContent>
86
+ </Dialog>
87
+ );
88
+ };
@@ -0,0 +1,21 @@
1
+ export const AUTH_EVENTS = {
2
+ OPEN_AUTH_DIALOG: 'OPEN_AUTH_DIALOG',
3
+ CLOSE_AUTH_DIALOG: 'CLOSE_AUTH_DIALOG',
4
+ AUTH_SUCCESS: 'AUTH_SUCCESS',
5
+ AUTH_FAILURE: 'AUTH_FAILURE',
6
+ } as const;
7
+
8
+ export type AuthEventType = typeof AUTH_EVENTS[keyof typeof AUTH_EVENTS];
9
+
10
+ export interface OpenAuthDialogPayload {
11
+ message?: string;
12
+ redirectUrl?: string;
13
+ }
14
+
15
+ export interface AuthSuccessPayload {
16
+ user?: any;
17
+ }
18
+
19
+ export interface AuthFailurePayload {
20
+ error?: string;
21
+ }
@@ -0,0 +1,3 @@
1
+ export { AuthDialog, DIALOG_EVENTS } from './AuthDialog';
2
+ export * from './events';
3
+ export { useAuthDialog } from './useAuthDialog';
@@ -0,0 +1,27 @@
1
+ import { useCallback } from 'react';
2
+
3
+ import { AUTH_EVENTS, type OpenAuthDialogPayload } from './events';
4
+ import { events } from '@djangocfg/ui';
5
+
6
+ /**
7
+ * Hook to control auth dialog from anywhere in the app
8
+ */
9
+ export function useAuthDialog() {
10
+ const openAuthDialog = useCallback((options?: OpenAuthDialogPayload) => {
11
+ events.publish({
12
+ type: AUTH_EVENTS.OPEN_AUTH_DIALOG,
13
+ payload: options,
14
+ });
15
+ }, []);
16
+
17
+ const closeAuthDialog = useCallback(() => {
18
+ events.publish({
19
+ type: AUTH_EVENTS.CLOSE_AUTH_DIALOG,
20
+ });
21
+ }, []);
22
+
23
+ return {
24
+ openAuthDialog,
25
+ closeAuthDialog,
26
+ };
27
+ }
@@ -0,0 +1,80 @@
1
+ "use client";
2
+ import React from "react";
3
+ import Link from "next/link";
4
+ import { usePathname } from "next/navigation";
5
+ import { ChevronRight, Home } from "lucide-react";
6
+
7
+ export interface BreadcrumbItem {
8
+ path: string;
9
+ label: string;
10
+ isActive: boolean;
11
+ }
12
+
13
+ interface BreadcrumbsProps {
14
+ items?: BreadcrumbItem[];
15
+ className?: string;
16
+ }
17
+
18
+ const Breadcrumbs: React.FC<BreadcrumbsProps> = ({ items, className = "" }) => {
19
+ const pathname = usePathname();
20
+
21
+ // Use provided items or generate from pathname
22
+ const breadcrumbs = items || generateBreadcrumbsFromPath(pathname);
23
+
24
+ if (breadcrumbs.length <= 1) {
25
+ return null;
26
+ }
27
+
28
+ return (
29
+ <nav className={`flex items-center space-x-2 text-sm ${className}`} aria-label="Breadcrumb">
30
+ <ol className="flex items-center space-x-2">
31
+ {breadcrumbs.map((item: BreadcrumbItem, index: number) => (
32
+ <li key={item.path} className="flex items-center">
33
+ {index > 0 && (
34
+ <ChevronRight className="w-4 h-4 text-gray-400 mx-2" />
35
+ )}
36
+
37
+ {item.isActive ? (
38
+ <span className="text-gray-900 dark:text-white font-medium flex items-center gap-1">
39
+ {index === 0 && <Home className="w-4 h-4" />}
40
+ {item.label}
41
+ </span>
42
+ ) : (
43
+ <Link
44
+ href={item.path}
45
+ className="text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200
46
+ transition-colors duration-200 flex items-center gap-1 hover:underline"
47
+ >
48
+ {index === 0 && <Home className="w-4 h-4" />}
49
+ {item.label}
50
+ </Link>
51
+ )}
52
+ </li>
53
+ ))}
54
+ </ol>
55
+ </nav>
56
+ );
57
+ };
58
+
59
+ // Helper function to generate breadcrumbs from pathname
60
+ function generateBreadcrumbsFromPath(pathname: string): BreadcrumbItem[] {
61
+ const segments = pathname.split('/').filter(Boolean);
62
+ const breadcrumbs: BreadcrumbItem[] = [
63
+ { path: '/', label: 'Home', isActive: pathname === '/' }
64
+ ];
65
+
66
+ let currentPath = '';
67
+ segments.forEach((segment, index) => {
68
+ currentPath += `/${segment}`;
69
+ breadcrumbs.push({
70
+ path: currentPath,
71
+ label: segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, ' '),
72
+ isActive: index === segments.length - 1
73
+ });
74
+ });
75
+
76
+ return breadcrumbs;
77
+ }
78
+
79
+ export default Breadcrumbs;
80
+ export { generateBreadcrumbsFromPath };
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Chat UI Context
3
+ * Manages UI state for chat widget (toggle, expand, minimize)
4
+ */
5
+
6
+ 'use client';
7
+
8
+ import React, { createContext, useContext, useState, useCallback, type ReactNode } from 'react';
9
+ import type { ChatUIState } from './types';
10
+
11
+ // ─────────────────────────────────────────────────────────────────────────
12
+ // Context Type
13
+ // ─────────────────────────────────────────────────────────────────────────
14
+
15
+ export interface ChatUIContextValue {
16
+ uiState: ChatUIState;
17
+ toggleChat: () => void;
18
+ openChat: () => void;
19
+ closeChat: () => void;
20
+ expandChat: () => void;
21
+ collapseChat: () => void;
22
+ minimizeChat: () => void;
23
+ toggleSources: () => void;
24
+ toggleTimestamps: () => void;
25
+ }
26
+
27
+ // ─────────────────────────────────────────────────────────────────────────
28
+ // Context
29
+ // ─────────────────────────────────────────────────────────────────────────
30
+
31
+ const ChatUIContext = createContext<ChatUIContextValue | undefined>(undefined);
32
+
33
+ // ─────────────────────────────────────────────────────────────────────────
34
+ // Provider
35
+ // ─────────────────────────────────────────────────────────────────────────
36
+
37
+ export interface ChatUIProviderProps {
38
+ children: ReactNode;
39
+ initialState?: Partial<ChatUIState>;
40
+ }
41
+
42
+ export function ChatUIProvider({ children, initialState }: ChatUIProviderProps) {
43
+ const [uiState, setUIState] = useState<ChatUIState>({
44
+ isOpen: false,
45
+ isExpanded: false,
46
+ isMinimized: false,
47
+ showSources: true,
48
+ showTimestamps: false,
49
+ ...initialState,
50
+ });
51
+
52
+ const toggleChat = useCallback(() => {
53
+ setUIState((prev) => ({ ...prev, isOpen: !prev.isOpen }));
54
+ }, []);
55
+
56
+ const openChat = useCallback(() => {
57
+ setUIState((prev) => ({ ...prev, isOpen: true }));
58
+ }, []);
59
+
60
+ const closeChat = useCallback(() => {
61
+ setUIState((prev) => ({ ...prev, isOpen: false }));
62
+ }, []);
63
+
64
+ const expandChat = useCallback(() => {
65
+ setUIState((prev) => ({ ...prev, isExpanded: true, isMinimized: false }));
66
+ }, []);
67
+
68
+ const collapseChat = useCallback(() => {
69
+ setUIState((prev) => ({ ...prev, isExpanded: false }));
70
+ }, []);
71
+
72
+ const minimizeChat = useCallback(() => {
73
+ setUIState((prev) => ({ ...prev, isMinimized: true, isExpanded: false }));
74
+ }, []);
75
+
76
+ const toggleSources = useCallback(() => {
77
+ setUIState((prev) => ({ ...prev, showSources: !prev.showSources }));
78
+ }, []);
79
+
80
+ const toggleTimestamps = useCallback(() => {
81
+ setUIState((prev) => ({ ...prev, showTimestamps: !prev.showTimestamps }));
82
+ }, []);
83
+
84
+ const value: ChatUIContextValue = {
85
+ uiState,
86
+ toggleChat,
87
+ openChat,
88
+ closeChat,
89
+ expandChat,
90
+ collapseChat,
91
+ minimizeChat,
92
+ toggleSources,
93
+ toggleTimestamps,
94
+ };
95
+
96
+ return <ChatUIContext.Provider value={value}>{children}</ChatUIContext.Provider>;
97
+ }
98
+
99
+ // ─────────────────────────────────────────────────────────────────────────
100
+ // Hook
101
+ // ─────────────────────────────────────────────────────────────────────────
102
+
103
+ export function useChatUI(): ChatUIContextValue {
104
+ const context = useContext(ChatUIContext);
105
+ if (!context) {
106
+ throw new Error('useChatUI must be used within ChatUIProvider');
107
+ }
108
+ return context;
109
+ }
110
+