@djangocfg/layouts 1.4.29 → 2.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 (119) hide show
  1. package/README.md +277 -18
  2. package/package.json +15 -24
  3. package/src/auth/context/AuthContext.tsx +8 -5
  4. package/src/auth/hooks/useAuthGuard.ts +1 -1
  5. package/src/auth/hooks/useAutoAuth.ts +8 -7
  6. package/src/components/ErrorBoundary.tsx +78 -0
  7. package/src/components/JsonLd.tsx +31 -0
  8. package/src/components/LucideIcon.tsx +91 -0
  9. package/src/components/PageProgress.tsx +127 -0
  10. package/src/components/Suspense.tsx +29 -0
  11. package/src/{layouts/AppLayout/components → components}/UpdateNotifier/UpdateNotifier.tsx +56 -49
  12. package/src/components/index.ts +10 -0
  13. package/src/index.ts +25 -7
  14. package/src/layouts/AdminLayout/AdminLayout.tsx +46 -0
  15. package/src/layouts/AdminLayout/index.ts +7 -0
  16. package/src/layouts/AppLayout/AppLayout.tsx +278 -326
  17. package/src/layouts/AppLayout/index.ts +2 -39
  18. package/src/layouts/{AppLayout/layouts/AuthLayout → AuthLayout}/AuthContext.tsx +3 -2
  19. package/src/layouts/{AppLayout/layouts/AuthLayout → AuthLayout}/AuthHelp.tsx +1 -0
  20. package/src/layouts/AuthLayout/AuthLayout.tsx +61 -0
  21. package/src/layouts/{AppLayout/layouts/AuthLayout → AuthLayout}/IdentifierForm.tsx +47 -34
  22. package/src/layouts/{AppLayout/layouts/AuthLayout → AuthLayout}/OTPForm.tsx +2 -3
  23. package/src/layouts/AuthLayout/index.ts +24 -0
  24. package/src/layouts/{AppLayout/layouts/AuthLayout → AuthLayout}/types.ts +1 -0
  25. package/src/layouts/PrivateLayout/PrivateLayout.tsx +144 -0
  26. package/src/layouts/PrivateLayout/components/PrivateContent.tsx +32 -0
  27. package/src/layouts/PrivateLayout/components/PrivateHeader.tsx +57 -0
  28. package/src/layouts/PrivateLayout/components/PrivateSidebar.tsx +141 -0
  29. package/src/layouts/PrivateLayout/components/index.ts +8 -0
  30. package/src/layouts/PrivateLayout/index.ts +7 -0
  31. package/src/layouts/ProfileLayout/ProfileLayout.tsx +15 -7
  32. package/src/layouts/PublicLayout/PublicLayout.tsx +121 -0
  33. package/src/layouts/PublicLayout/components/PublicFooter.tsx +190 -0
  34. package/src/layouts/PublicLayout/components/PublicMobileDrawer.tsx +117 -0
  35. package/src/layouts/PublicLayout/components/PublicNavigation.tsx +101 -0
  36. package/src/layouts/PublicLayout/components/index.ts +8 -0
  37. package/src/layouts/PublicLayout/index.ts +7 -0
  38. package/src/layouts/_components/UserMenu.tsx +160 -0
  39. package/src/layouts/_components/index.ts +7 -0
  40. package/src/layouts/index.ts +15 -8
  41. package/src/snippets/Analytics/AnalyticsProvider.tsx +8 -4
  42. package/src/snippets/Analytics/useAnalytics.ts +11 -21
  43. package/src/snippets/Chat/ChatWidget.tsx +4 -4
  44. package/src/snippets/ContactForm/ContactFormProvider.tsx +32 -19
  45. package/src/snippets/ContactForm/ContactPage.tsx +2 -4
  46. package/src/snippets/ContactForm/types.ts +3 -2
  47. package/src/snippets/index.ts +0 -1
  48. package/src/layouts/AppLayout/README.md +0 -204
  49. package/src/layouts/AppLayout/SUMMARY.md +0 -240
  50. package/src/layouts/AppLayout/USAGE.md +0 -312
  51. package/src/layouts/AppLayout/components/ErrorBoundary.tsx +0 -112
  52. package/src/layouts/AppLayout/components/PageProgress.tsx +0 -123
  53. package/src/layouts/AppLayout/components/Seo.tsx +0 -171
  54. package/src/layouts/AppLayout/components/UserMenu.tsx +0 -385
  55. package/src/layouts/AppLayout/components/index.ts +0 -11
  56. package/src/layouts/AppLayout/context/AppContext.tsx +0 -151
  57. package/src/layouts/AppLayout/context/index.ts +0 -5
  58. package/src/layouts/AppLayout/hooks/index.ts +0 -8
  59. package/src/layouts/AppLayout/hooks/useLayoutMode.ts +0 -26
  60. package/src/layouts/AppLayout/hooks/useNavigation.ts +0 -51
  61. package/src/layouts/AppLayout/layouts/AdminLayout/AdminLayout.tsx +0 -224
  62. package/src/layouts/AppLayout/layouts/AdminLayout/README.md +0 -409
  63. package/src/layouts/AppLayout/layouts/AdminLayout/components/PagePreloader.example.tsx +0 -98
  64. package/src/layouts/AppLayout/layouts/AdminLayout/components/PagePreloader.tsx +0 -149
  65. package/src/layouts/AppLayout/layouts/AdminLayout/components/ParentSync.tsx +0 -146
  66. package/src/layouts/AppLayout/layouts/AdminLayout/components/index.ts +0 -3
  67. package/src/layouts/AppLayout/layouts/AdminLayout/context/CfgAppContext.tsx +0 -48
  68. package/src/layouts/AppLayout/layouts/AdminLayout/context/index.ts +0 -2
  69. package/src/layouts/AppLayout/layouts/AdminLayout/hooks/index.ts +0 -6
  70. package/src/layouts/AppLayout/layouts/AdminLayout/hooks/useApp.ts +0 -279
  71. package/src/layouts/AppLayout/layouts/AdminLayout/index.ts +0 -24
  72. package/src/layouts/AppLayout/layouts/AdminLayout/lottie/energizing.json +0 -1
  73. package/src/layouts/AppLayout/layouts/AdminLayout/types/index.ts +0 -45
  74. package/src/layouts/AppLayout/layouts/AuthLayout/AuthLayout.tsx +0 -41
  75. package/src/layouts/AppLayout/layouts/AuthLayout/index.ts +0 -15
  76. package/src/layouts/AppLayout/layouts/PrivateLayout/PrivateLayout.tsx +0 -82
  77. package/src/layouts/AppLayout/layouts/PrivateLayout/components/DashboardContent.tsx +0 -62
  78. package/src/layouts/AppLayout/layouts/PrivateLayout/components/DashboardHeader.tsx +0 -89
  79. package/src/layouts/AppLayout/layouts/PrivateLayout/components/DashboardSidebar.tsx +0 -181
  80. package/src/layouts/AppLayout/layouts/PrivateLayout/components/index.ts +0 -9
  81. package/src/layouts/AppLayout/layouts/PrivateLayout/index.ts +0 -5
  82. package/src/layouts/AppLayout/layouts/PublicLayout/PublicLayout.tsx +0 -44
  83. package/src/layouts/AppLayout/layouts/PublicLayout/components/Footer.tsx +0 -242
  84. package/src/layouts/AppLayout/layouts/PublicLayout/components/MobileDrawer.tsx +0 -150
  85. package/src/layouts/AppLayout/layouts/PublicLayout/components/Navigation.tsx +0 -169
  86. package/src/layouts/AppLayout/layouts/PublicLayout/index.ts +0 -5
  87. package/src/layouts/AppLayout/layouts/index.ts +0 -7
  88. package/src/layouts/AppLayout/providers/CoreProviders.tsx +0 -80
  89. package/src/layouts/AppLayout/providers/index.ts +0 -5
  90. package/src/layouts/AppLayout/types/config.ts +0 -79
  91. package/src/layouts/AppLayout/types/index.ts +0 -11
  92. package/src/layouts/AppLayout/types/layout.ts +0 -54
  93. package/src/layouts/AppLayout/types/navigation.ts +0 -43
  94. package/src/layouts/AppLayout/types/page.ts +0 -80
  95. package/src/layouts/AppLayout/types/routes.ts +0 -43
  96. package/src/layouts/AppLayout/utils/index.ts +0 -5
  97. package/src/layouts/AppLayout/utils/routeDetection.ts +0 -31
  98. package/src/layouts/ErrorLayout/ErrorLayout.tsx +0 -173
  99. package/src/layouts/ErrorLayout/errorConfig.tsx +0 -152
  100. package/src/layouts/ErrorLayout/index.ts +0 -8
  101. package/src/layouts/SimpleLayout/SimpleLayout.tsx +0 -72
  102. package/src/layouts/SimpleLayout/index.ts +0 -3
  103. package/src/snippets/VideoPlayer/README.md +0 -238
  104. package/src/snippets/VideoPlayer/VideoControls.tsx +0 -137
  105. package/src/snippets/VideoPlayer/VideoPlayer.tsx +0 -248
  106. package/src/snippets/VideoPlayer/index.ts +0 -8
  107. package/src/snippets/VideoPlayer/types.ts +0 -61
  108. package/src/types/index.ts +0 -2
  109. package/src/types/pageConfig.ts +0 -100
  110. /package/src/{validation → components/ErrorsTracker}/README.md +0 -0
  111. /package/src/{validation → components/ErrorsTracker}/components/ErrorButtons.tsx +0 -0
  112. /package/src/{validation → components/ErrorsTracker}/components/ErrorToast.tsx +0 -0
  113. /package/src/{validation → components/ErrorsTracker}/hooks.ts +0 -0
  114. /package/src/{validation → components/ErrorsTracker}/index.ts +0 -0
  115. /package/src/{validation → components/ErrorsTracker}/providers/ErrorTrackingProvider.tsx +0 -0
  116. /package/src/{validation → components/ErrorsTracker}/types.ts +0 -0
  117. /package/src/{validation → components/ErrorsTracker}/utils/curl-generator.ts +0 -0
  118. /package/src/{validation → components/ErrorsTracker}/utils/formatters.ts +0 -0
  119. /package/src/{layouts/AppLayout/components → components}/UpdateNotifier/index.ts +0 -0
@@ -1,79 +0,0 @@
1
- /**
2
- * Configuration Types
3
- */
4
-
5
- import type { ReactNode } from 'react';
6
- import type { PublicLayoutConfig, PrivateLayoutConfig, AdminLayoutConfig } from './layout';
7
- import type { RouteConfig } from './routes';
8
-
9
- /**
10
- * Main AppLayout configuration
11
- */
12
- export interface AppLayoutConfig {
13
- /** Application metadata */
14
- app: {
15
- name: string;
16
- description?: string;
17
- logoPath: string;
18
- siteUrl?: string;
19
- icons?: {
20
- logo192?: string;
21
- logo384?: string;
22
- logo512?: string;
23
- logoVector?: string;
24
- };
25
- };
26
-
27
- /** Theme configuration */
28
- theme?: {
29
- /** Default theme (default: 'light') */
30
- defaultTheme?: 'light' | 'dark';
31
- /** Storage key for theme persistence (default: 'theme') */
32
- storageKey?: string;
33
- };
34
-
35
- /** API configuration */
36
- api: {
37
- baseUrl: string;
38
- };
39
-
40
- /** Route configuration */
41
- routes: RouteConfig;
42
-
43
- /** Public layout configuration */
44
- publicLayout: PublicLayoutConfig;
45
-
46
- /** Private layout configuration */
47
- privateLayout: PrivateLayoutConfig;
48
-
49
- /** Admin layout configuration (optional) */
50
- adminLayout?: AdminLayoutConfig;
51
-
52
- /** Error handling configuration */
53
- errors?: {
54
- /** Enable automatic error boundary (default: true) */
55
- enableErrorBoundary?: boolean;
56
- /** Support email for error pages */
57
- supportEmail?: string;
58
- /** Custom error handler callback */
59
- onError?: (error: Error, errorInfo?: React.ErrorInfo) => void;
60
- };
61
-
62
- /** Auth configuration */
63
- auth?: {
64
- /** Terms of Service URL */
65
- termsUrl?: string;
66
- /** Privacy Policy URL */
67
- privacyUrl?: string;
68
- /** Support URL for auth help */
69
- supportUrl?: string;
70
- /** Enable phone authentication (default: false) */
71
- enablePhoneAuth?: boolean;
72
- };
73
-
74
- /** Analytics configuration */
75
- analytics?: {
76
- /** Google Analytics Tracking ID (e.g., 'G-XXXXXXXXXX' or 'UA-XXXXXXXXX-X') */
77
- googleTrackingId?: string;
78
- };
79
- }
@@ -1,11 +0,0 @@
1
- /**
2
- * AppLayout Type Definitions
3
- *
4
- * All types for the unified AppLayout system
5
- */
6
-
7
- export * from './config';
8
- export * from './layout';
9
- export * from './navigation';
10
- export * from './routes';
11
- export * from './page';
@@ -1,54 +0,0 @@
1
- /**
2
- * Layout Configuration Types
3
- */
4
-
5
- import type { ReactNode } from 'react';
6
- import type { LucideIcon } from 'lucide-react';
7
- import type { NavigationSection, DashboardMenuGroup } from './navigation';
8
-
9
- /**
10
- * Public layout configuration
11
- */
12
- export interface PublicLayoutConfig {
13
- navigation: {
14
- homePath: string;
15
- menuSections: NavigationSection[];
16
- };
17
- userMenu: {
18
- dashboardPath?: string;
19
- profilePath: string;
20
- };
21
- footer: {
22
- badge: {
23
- icon: LucideIcon;
24
- text: string;
25
- };
26
- links: {
27
- docs?: string;
28
- privacy?: string;
29
- terms?: string;
30
- security?: string;
31
- cookies?: string;
32
- };
33
- menuSections: NavigationSection[];
34
- };
35
- }
36
-
37
- /**
38
- * Private/Dashboard layout configuration
39
- */
40
- export interface PrivateLayoutConfig {
41
- homeHref: string;
42
- profileHref: string;
43
- showChat?: boolean;
44
- menuGroups: DashboardMenuGroup[];
45
- contentPadding?: 'default' | 'none';
46
- headerActions?: ReactNode;
47
- }
48
-
49
- /**
50
- * Admin layout configuration
51
- */
52
- export interface AdminLayoutConfig {
53
- menuSections: NavigationSection[];
54
- }
@@ -1,43 +0,0 @@
1
- /**
2
- * Navigation Types
3
- */
4
-
5
- import type { LucideIcon } from 'lucide-react';
6
-
7
- /**
8
- * Navigation menu item
9
- */
10
- export interface NavigationItem {
11
- label: string;
12
- path: string;
13
- icon?: LucideIcon;
14
- badge?: string | number;
15
- }
16
-
17
- /**
18
- * Navigation menu section
19
- */
20
- export interface NavigationSection {
21
- title: string;
22
- items: NavigationItem[];
23
- }
24
-
25
- /**
26
- * Dashboard menu item with icon
27
- */
28
- export interface DashboardMenuItem {
29
- path: string;
30
- label: string;
31
- icon: LucideIcon;
32
- badge?: string | number;
33
- subItems?: DashboardMenuItem[]; // Support nested menu items
34
- }
35
-
36
- /**
37
- * Dashboard menu group
38
- */
39
- export interface DashboardMenuGroup {
40
- label: string;
41
- order: number;
42
- items: DashboardMenuItem[];
43
- }
@@ -1,80 +0,0 @@
1
- /**
2
- * Page Type Definitions
3
- *
4
- * Universal types for Next.js pages with layout and SEO support
5
- */
6
-
7
- import type { ReactElement, ReactNode } from 'react';
8
- import type { NextPage } from 'next';
9
- import type { PageConfig } from '../../../types/pageConfig';
10
-
11
- /**
12
- * Layout mode types
13
- *
14
- * - 'public': Public layout (landing, docs, etc.)
15
- * - 'private': Private layout (dashboard, authenticated pages)
16
- * - 'auth': Auth layout (login, register, OTP)
17
- * - 'admin': Admin layout (Django CFG iframe integration)
18
- * - 'none': No layout (fully custom page)
19
- */
20
- export type LayoutMode = 'public' | 'private' | 'auth' | 'admin' | 'none';
21
-
22
- /**
23
- * Universal Page Type - combines layout and SEO configuration
24
- *
25
- * Extends NextPage with:
26
- * - Layout control (getLayout, layoutMode)
27
- * - SEO metadata (pageConfig)
28
- *
29
- * @example
30
- * ```tsx
31
- * // Custom layout using getLayout
32
- * const Page: PageWithLayout = () => <div>Content</div>;
33
- * Page.getLayout = (page) => <CustomLayout>{page}</CustomLayout>;
34
- *
35
- * // Force specific layout mode
36
- * const DashboardPage: PageWithLayout = () => <div>Dashboard</div>;
37
- * DashboardPage.layoutMode = 'private';
38
- *
39
- * // With SEO config
40
- * const HomePage: PageWithLayout = () => <div>Home</div>;
41
- * HomePage.pageConfig = {
42
- * title: 'Home Page',
43
- * description: 'Welcome to our site',
44
- * ogImage: { title: 'Home', subtitle: 'Welcome' }
45
- * };
46
- *
47
- * // Disable all layouts
48
- * const LandingPage: PageWithLayout = () => <FullPageDesign />;
49
- * LandingPage.layoutMode = 'none';
50
- * ```
51
- */
52
- export type PageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
53
- /**
54
- * Custom layout function
55
- * When provided, AppLayout will use this instead of automatic layout detection
56
- *
57
- * @param page - The page component wrapped in React element
58
- * @returns Layout-wrapped page
59
- */
60
- getLayout?: (page: ReactElement) => ReactNode;
61
-
62
- /**
63
- * Force specific layout mode
64
- * Overrides automatic route detection
65
- *
66
- * - undefined: Auto-detect based on route
67
- * - 'public': Always use PublicLayout
68
- * - 'private': Always use PrivateLayout
69
- * - 'auth': Always use AuthLayout
70
- * - 'admin': Always use AdminLayout
71
- * - 'none': No layout (page renders directly)
72
- */
73
- layoutMode?: LayoutMode;
74
-
75
- /**
76
- * Page SEO and metadata configuration
77
- * Used for <head> tags, OpenGraph, Twitter cards, etc.
78
- */
79
- pageConfig?: PageConfig;
80
- };
@@ -1,43 +0,0 @@
1
- /**
2
- * Route Types
3
- */
4
-
5
- /**
6
- * Route configuration
7
- */
8
- export interface RouteConfig {
9
- /** Authentication route */
10
- auth: string;
11
-
12
- /** Default redirect after login */
13
- defaultCallback: string;
14
-
15
- /** Redirect for authenticated users on auth page */
16
- defaultAuthCallback?: string;
17
-
18
- /** Route detector functions */
19
- detectors: RouteDetectors;
20
- }
21
-
22
- /**
23
- * Route detection functions
24
- */
25
- export interface RouteDetectors {
26
- /** Check if route is public */
27
- isPublicRoute: (path: string) => boolean;
28
-
29
- /** Check if route is private/protected */
30
- isPrivateRoute: (path: string) => boolean;
31
-
32
- /** Check if route is admin */
33
- isAdminRoute: (path: string) => boolean;
34
-
35
- /** Check if route is auth page */
36
- isAuthRoute: (path: string) => boolean;
37
-
38
- /** Get redirect URL for unauthenticated users */
39
- getUnauthenticatedRedirect: (path: string) => string | null;
40
-
41
- /** Get page title for route */
42
- getPageTitle: (path: string) => string;
43
- }
@@ -1,5 +0,0 @@
1
- /**
2
- * Utilities Module
3
- */
4
-
5
- export * from './routeDetection';
@@ -1,31 +0,0 @@
1
- /**
2
- * Route Detection Utilities
3
- */
4
-
5
- import type { LayoutMode, RouteDetectors } from '../types';
6
-
7
- /**
8
- * Determine layout mode from pathname
9
- */
10
- export function determineLayoutMode(
11
- pathname: string,
12
- detectors: RouteDetectors
13
- ): LayoutMode {
14
- if (detectors.isAuthRoute(pathname)) return 'auth';
15
- if (detectors.isPrivateRoute(pathname)) return 'private';
16
- return 'public';
17
- }
18
-
19
- /**
20
- * Check if redirect is needed for unauthenticated user
21
- */
22
- export function getRedirectUrl(
23
- pathname: string,
24
- isAuthenticated: boolean,
25
- detectors: RouteDetectors
26
- ): string | null {
27
- if (!isAuthenticated) {
28
- return detectors.getUnauthenticatedRedirect(pathname);
29
- }
30
- return null;
31
- }
@@ -1,173 +0,0 @@
1
- /**
2
- * ErrorLayout - Universal Error Display
3
- *
4
- * Minimalist error page with customizable content
5
- * Works with Next.js error pages (404.tsx, 500.tsx, error.tsx)
6
- *
7
- * Usage:
8
- * ```tsx
9
- * // pages/404.tsx
10
- * import { ErrorLayout } from '@djangocfg/layouts/AppLayout';
11
- *
12
- * export default function NotFound() {
13
- * return (
14
- * <ErrorLayout
15
- * code="404"
16
- * title="Page Not Found"
17
- * description="The page you're looking for doesn't exist."
18
- * />
19
- * );
20
- * }
21
- * ```
22
- */
23
-
24
- 'use client';
25
-
26
- import React from 'react';
27
- import { Button } from '@djangocfg/ui/components';
28
- import { getErrorContent } from './errorConfig';
29
-
30
- export interface ErrorLayoutProps {
31
- /** Error code (e.g., "404", "500", "403") - if provided, auto-configures title/description/icon */
32
- code?: string | number;
33
- /** Error title (auto-generated from code if not provided) */
34
- title?: string;
35
- /** Error description (auto-generated from code if not provided) */
36
- description?: string;
37
- /** Custom action buttons */
38
- actions?: React.ReactNode;
39
- /** Show default actions (back, home) */
40
- showDefaultActions?: boolean;
41
- /** Custom illustration/icon (auto-generated from code if not provided) */
42
- illustration?: React.ReactNode;
43
- /** Support email for contact link */
44
- supportEmail?: string;
45
- }
46
-
47
- /**
48
- * ErrorLayout Component
49
- *
50
- * Clean, minimal error display with semantic colors
51
- * Standalone layout - doesn't depend on AppLayout context
52
- *
53
- * Smart auto-configuration:
54
- * - Pass only `code` prop and everything is configured automatically
55
- * - Or override with custom title/description/illustration
56
- */
57
- export function ErrorLayout({
58
- code,
59
- title,
60
- description,
61
- actions,
62
- showDefaultActions = true,
63
- illustration,
64
- supportEmail = 'support@example.com',
65
- }: ErrorLayoutProps) {
66
- // Auto-configure content from error code if not provided
67
- const autoContent = code && (!title || !description || !illustration)
68
- ? getErrorContent(code)
69
- : null;
70
-
71
- // Use provided values or fall back to auto-generated
72
- const finalTitle = title || autoContent?.title || 'Error';
73
- const finalDescription = description || autoContent?.description;
74
- const finalIllustration = illustration || autoContent?.icon;
75
-
76
- const handleGoBack = () => {
77
- // Use native navigation with full page reload instead of Next.js client-side navigation
78
- if (document.referrer && document.referrer !== window.location.href) {
79
- // Navigate to referrer with full reload
80
- window.location.href = document.referrer;
81
- } else if (window.history.length > 1) {
82
- // Fallback: go back in history
83
- window.history.back();
84
- } else {
85
- // Last resort: go to home
86
- window.location.href = '/';
87
- }
88
- };
89
-
90
- const handleGoHome = () => {
91
- // Full page reload to home
92
- window.location.href = '/';
93
- };
94
-
95
- return (
96
- <div className="min-h-screen flex items-center justify-center px-4">
97
- <div className="max-w-2xl w-full text-center space-y-8">
98
- {/* Error Code */}
99
- {code && (
100
- <div className="relative">
101
- <h1
102
- className="text-[12rem] font-bold leading-none text-muted/20 select-none"
103
- aria-hidden="true"
104
- >
105
- {code}
106
- </h1>
107
- </div>
108
- )}
109
-
110
- {/* Illustration */}
111
- {finalIllustration && (
112
- <div className="flex justify-center py-8">
113
- {finalIllustration}
114
- </div>
115
- )}
116
-
117
- {/* Error Content */}
118
- <div className="space-y-4">
119
- <h2 className="text-4xl font-bold text-foreground">
120
- {finalTitle}
121
- </h2>
122
-
123
- {finalDescription && (
124
- <p className="text-lg text-muted-foreground max-w-md mx-auto">
125
- {finalDescription}
126
- </p>
127
- )}
128
- </div>
129
-
130
- {/* Actions */}
131
- <div className="flex flex-col sm:flex-row items-center justify-center gap-4 pt-4">
132
- {/* Custom actions */}
133
- {actions}
134
-
135
- {/* Default actions */}
136
- {showDefaultActions && !actions && (
137
- <>
138
- <Button
139
- variant="outline"
140
- size="lg"
141
- onClick={handleGoBack}
142
- style={{ minWidth: '140px', padding: '12px 32px' }}
143
- >
144
- Go Back
145
- </Button>
146
- <Button
147
- variant="default"
148
- size="lg"
149
- onClick={handleGoHome}
150
- style={{ minWidth: '140px', padding: '12px 32px' }}
151
- >
152
- Go Home
153
- </Button>
154
- </>
155
- )}
156
- </div>
157
-
158
- {/* Additional Info */}
159
- <div className="pt-8 text-sm text-muted-foreground">
160
- <p>
161
- Need help? Contact{' '}
162
- <a
163
- href={`mailto:${supportEmail}`}
164
- className="text-primary hover:underline"
165
- >
166
- support
167
- </a>
168
- </p>
169
- </div>
170
- </div>
171
- </div>
172
- );
173
- }
@@ -1,152 +0,0 @@
1
- /**
2
- * Universal Error Configuration
3
- *
4
- * Provides standard error content for common HTTP status codes
5
- * Use this to maintain consistency across error pages
6
- */
7
-
8
- import React from 'react';
9
- import { FileQuestion, ServerCrash, ShieldAlert, Clock, AlertTriangle, Ban } from 'lucide-react';
10
-
11
- export interface ErrorContent {
12
- title: string;
13
- description: string;
14
- icon: React.ReactNode;
15
- }
16
-
17
- /**
18
- * Get standardized error content based on status code
19
- *
20
- * @param statusCode - HTTP status code or custom error type
21
- * @returns Error content configuration
22
- *
23
- * @example
24
- * ```tsx
25
- * const { title, description, icon } = getErrorContent(404);
26
- * <ErrorLayout title={title} description={description} illustration={icon} />
27
- * ```
28
- */
29
- export function getErrorContent(statusCode?: number | string): ErrorContent {
30
- const code = typeof statusCode === 'string' ? parseInt(statusCode, 10) : statusCode;
31
-
32
- switch (code) {
33
- // 400 Bad Request
34
- case 400:
35
- return {
36
- title: 'Bad Request',
37
- description: 'The request could not be understood. Please check your input and try again.',
38
- icon: <AlertTriangle className="w-24 h-24 text-warning/50" strokeWidth={1.5} />,
39
- };
40
-
41
- // 401 Unauthorized
42
- case 401:
43
- return {
44
- title: 'Authentication Required',
45
- description: 'You need to sign in to access this page.',
46
- icon: <ShieldAlert className="w-24 h-24 text-warning/50" strokeWidth={1.5} />,
47
- };
48
-
49
- // 403 Forbidden
50
- case 403:
51
- return {
52
- title: 'Access Denied',
53
- description: "You don't have permission to access this resource.",
54
- icon: <Ban className="w-24 h-24 text-destructive/50" strokeWidth={1.5} />,
55
- };
56
-
57
- // 404 Not Found
58
- case 404:
59
- return {
60
- title: 'Page Not Found',
61
- description: "The page you're looking for doesn't exist or has been moved.",
62
- icon: <FileQuestion className="w-24 h-24 text-muted-foreground/50" strokeWidth={1.5} />,
63
- };
64
-
65
- // 408 Request Timeout
66
- case 408:
67
- return {
68
- title: 'Request Timeout',
69
- description: 'The request took too long to process. Please try again.',
70
- icon: <Clock className="w-24 h-24 text-warning/50" strokeWidth={1.5} />,
71
- };
72
-
73
- // 500 Internal Server Error
74
- case 500:
75
- return {
76
- title: 'Server Error',
77
- description: "Something went wrong on our end. We're working to fix it.",
78
- icon: <ServerCrash className="w-24 h-24 text-destructive/50" strokeWidth={1.5} />,
79
- };
80
-
81
- // 502 Bad Gateway
82
- case 502:
83
- return {
84
- title: 'Bad Gateway',
85
- description: 'The server received an invalid response. Please try again later.',
86
- icon: <ServerCrash className="w-24 h-24 text-destructive/50" strokeWidth={1.5} />,
87
- };
88
-
89
- // 503 Service Unavailable
90
- case 503:
91
- return {
92
- title: 'Service Unavailable',
93
- description: 'The service is temporarily unavailable. Please try again later.',
94
- icon: <ServerCrash className="w-24 h-24 text-destructive/50" strokeWidth={1.5} />,
95
- };
96
-
97
- // 504 Gateway Timeout
98
- case 504:
99
- return {
100
- title: 'Gateway Timeout',
101
- description: 'The server took too long to respond. Please try again.',
102
- icon: <Clock className="w-24 h-24 text-warning/50" strokeWidth={1.5} />,
103
- };
104
-
105
- // Default / Unknown Error
106
- default:
107
- return {
108
- title: 'Something Went Wrong',
109
- description: 'An unexpected error occurred. Please try again or contact support.',
110
- icon: <AlertTriangle className="w-24 h-24 text-warning/50" strokeWidth={1.5} />,
111
- };
112
- }
113
- }
114
-
115
- /**
116
- * Common error codes as constants
117
- */
118
- export const ERROR_CODES = {
119
- BAD_REQUEST: 400,
120
- UNAUTHORIZED: 401,
121
- FORBIDDEN: 403,
122
- NOT_FOUND: 404,
123
- TIMEOUT: 408,
124
- SERVER_ERROR: 500,
125
- BAD_GATEWAY: 502,
126
- SERVICE_UNAVAILABLE: 503,
127
- GATEWAY_TIMEOUT: 504,
128
- } as const;
129
-
130
- /**
131
- * Ready-to-use getInitialProps for Next.js _error.tsx page
132
- *
133
- * Extracts status code from response or error automatically
134
- * Works for both server-side and client-side errors
135
- *
136
- * @example
137
- * ```tsx
138
- * // pages/_error.tsx
139
- * import { ErrorLayout, errorPageGetInitialProps } from '@djangocfg/layouts';
140
- *
141
- * function ErrorPage({ statusCode }) {
142
- * return <ErrorLayout code={statusCode} />;
143
- * }
144
- *
145
- * ErrorPage.getInitialProps = errorPageGetInitialProps;
146
- * export default ErrorPage;
147
- * ```
148
- */
149
- export const errorPageGetInitialProps = ({ res, err }: any) => {
150
- const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
151
- return { statusCode };
152
- };
@@ -1,8 +0,0 @@
1
- /**
2
- * ErrorLayout Module
3
- */
4
-
5
- export { ErrorLayout } from './ErrorLayout';
6
- export type { ErrorLayoutProps } from './ErrorLayout';
7
- export { getErrorContent, ERROR_CODES, errorPageGetInitialProps } from './errorConfig';
8
- export type { ErrorContent } from './errorConfig';