vintasend 0.5.0 → 0.5.2

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 (71) hide show
  1. package/dist/services/notification-service.d.ts +2 -0
  2. package/dist/services/notification-service.js +6 -0
  3. package/dist/tools/vintasend-dashboard/app/components/auth-status.d.ts +1 -0
  4. package/dist/tools/vintasend-dashboard/app/components/auth-status.js +29 -0
  5. package/dist/tools/vintasend-dashboard/app/error.d.ts +6 -0
  6. package/dist/tools/vintasend-dashboard/app/error.js +40 -0
  7. package/dist/tools/vintasend-dashboard/app/layout.d.ts +6 -0
  8. package/dist/tools/vintasend-dashboard/app/layout.js +38 -0
  9. package/dist/tools/vintasend-dashboard/app/notifications/actions.d.ts +51 -0
  10. package/dist/tools/vintasend-dashboard/app/notifications/actions.js +224 -0
  11. package/dist/tools/vintasend-dashboard/app/notifications/components/columns.d.ts +6 -0
  12. package/dist/tools/vintasend-dashboard/app/notifications/components/columns.js +158 -0
  13. package/dist/tools/vintasend-dashboard/app/notifications/components/notifications-filters.d.ts +18 -0
  14. package/dist/tools/vintasend-dashboard/app/notifications/components/notifications-filters.js +162 -0
  15. package/dist/tools/vintasend-dashboard/app/notifications/components/notifications-table.d.ts +23 -0
  16. package/dist/tools/vintasend-dashboard/app/notifications/components/notifications-table.js +132 -0
  17. package/dist/tools/vintasend-dashboard/app/page.d.ts +1 -0
  18. package/dist/tools/vintasend-dashboard/app/page.js +32 -0
  19. package/dist/tools/vintasend-dashboard/app/sign-in/[[...sign-in]]/page.d.ts +1 -0
  20. package/dist/tools/vintasend-dashboard/app/sign-in/[[...sign-in]]/page.js +18 -0
  21. package/dist/tools/vintasend-dashboard/app/sign-out/[[...sign-out]]/page.d.ts +1 -0
  22. package/dist/tools/vintasend-dashboard/app/sign-out/[[...sign-out]]/page.js +16 -0
  23. package/dist/tools/vintasend-dashboard/components/ui/badge.d.ts +9 -0
  24. package/dist/tools/vintasend-dashboard/components/ui/badge.js +61 -0
  25. package/dist/tools/vintasend-dashboard/components/ui/button.d.ts +10 -0
  26. package/dist/tools/vintasend-dashboard/components/ui/button.js +72 -0
  27. package/dist/tools/vintasend-dashboard/components/ui/calendar.d.ts +8 -0
  28. package/dist/tools/vintasend-dashboard/components/ui/calendar.js +116 -0
  29. package/dist/tools/vintasend-dashboard/components/ui/dropdown-menu.d.ts +25 -0
  30. package/dist/tools/vintasend-dashboard/components/ui/dropdown-menu.js +119 -0
  31. package/dist/tools/vintasend-dashboard/components/ui/input.d.ts +3 -0
  32. package/dist/tools/vintasend-dashboard/components/ui/input.js +41 -0
  33. package/dist/tools/vintasend-dashboard/components/ui/pagination.d.ts +13 -0
  34. package/dist/tools/vintasend-dashboard/components/ui/pagination.js +79 -0
  35. package/dist/tools/vintasend-dashboard/components/ui/popover.d.ts +10 -0
  36. package/dist/tools/vintasend-dashboard/components/ui/popover.js +69 -0
  37. package/dist/tools/vintasend-dashboard/components/ui/select.d.ts +15 -0
  38. package/dist/tools/vintasend-dashboard/components/ui/select.js +106 -0
  39. package/dist/tools/vintasend-dashboard/components/ui/skeleton.d.ts +2 -0
  40. package/dist/tools/vintasend-dashboard/components/ui/skeleton.js +7 -0
  41. package/dist/tools/vintasend-dashboard/components/ui/table.d.ts +10 -0
  42. package/dist/tools/vintasend-dashboard/components/ui/table.js +72 -0
  43. package/dist/tools/vintasend-dashboard/lib/auth/auth-context.d.ts +23 -0
  44. package/dist/tools/vintasend-dashboard/lib/auth/auth-context.js +30 -0
  45. package/dist/tools/vintasend-dashboard/lib/auth/index.d.ts +5 -0
  46. package/dist/tools/vintasend-dashboard/lib/auth/index.js +12 -0
  47. package/dist/tools/vintasend-dashboard/lib/auth/resolve-strategy.d.ts +5 -0
  48. package/dist/tools/vintasend-dashboard/lib/auth/resolve-strategy.js +24 -0
  49. package/dist/tools/vintasend-dashboard/lib/auth/strategies/auth0-strategy.d.ts +17 -0
  50. package/dist/tools/vintasend-dashboard/lib/auth/strategies/auth0-strategy.js +76 -0
  51. package/dist/tools/vintasend-dashboard/lib/auth/strategies/clerk-strategy.d.ts +18 -0
  52. package/dist/tools/vintasend-dashboard/lib/auth/strategies/clerk-strategy.js +70 -0
  53. package/dist/tools/vintasend-dashboard/lib/auth/types.d.ts +50 -0
  54. package/dist/tools/vintasend-dashboard/lib/auth/types.js +2 -0
  55. package/dist/tools/vintasend-dashboard/lib/auth/validate-config.d.ts +2 -0
  56. package/dist/tools/vintasend-dashboard/lib/auth/validate-config.js +10 -0
  57. package/dist/tools/vintasend-dashboard/lib/auth0.d.ts +6 -0
  58. package/dist/tools/vintasend-dashboard/lib/auth0.js +14 -0
  59. package/dist/tools/vintasend-dashboard/lib/notifications/get-vintasend-service.d.ts +26 -0
  60. package/dist/tools/vintasend-dashboard/lib/notifications/get-vintasend-service.js +31 -0
  61. package/dist/tools/vintasend-dashboard/lib/notifications/serialize.d.ts +27 -0
  62. package/dist/tools/vintasend-dashboard/lib/notifications/serialize.js +75 -0
  63. package/dist/tools/vintasend-dashboard/lib/notifications/types.d.ts +62 -0
  64. package/dist/tools/vintasend-dashboard/lib/notifications/types.js +6 -0
  65. package/dist/tools/vintasend-dashboard/lib/utils.d.ts +2 -0
  66. package/dist/tools/vintasend-dashboard/lib/utils.js +8 -0
  67. package/dist/tools/vintasend-dashboard/next.config.d.ts +3 -0
  68. package/dist/tools/vintasend-dashboard/next.config.js +6 -0
  69. package/dist/tools/vintasend-dashboard/proxy.d.ts +5 -0
  70. package/dist/tools/vintasend-dashboard/proxy.js +83 -0
  71. package/package.json +1 -1
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ 'use client';
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.NotificationsFilters = NotificationsFilters;
38
+ const react_1 = __importStar(require("react"));
39
+ const input_1 = require("@/components/ui/input");
40
+ const select_1 = require("@/components/ui/select");
41
+ const NOTIFICATION_STATUSES = ['PENDING_SEND', 'SENT', 'FAILED', 'READ', 'CANCELLED'];
42
+ const NOTIFICATION_TYPES = ['EMAIL', 'SMS', 'PUSH', 'IN_APP'];
43
+ /**
44
+ * Filter bar for notifications list.
45
+ * Allows filtering by status, type, and free-text search.
46
+ * Search input is debounced (300ms) before calling the change callback.
47
+ *
48
+ * @param onFiltersChange - Callback invoked when filters change (after debounce for search)
49
+ * @param isLoading - Whether data is currently loading
50
+ * @param initialFilters - Initial filter values
51
+ */
52
+ function NotificationsFilters({ onFiltersChange, isLoading = false, initialFilters, }) {
53
+ var _a, _b, _c;
54
+ const [status, setStatus] = (0, react_1.useState)((_a = initialFilters === null || initialFilters === void 0 ? void 0 : initialFilters.status) !== null && _a !== void 0 ? _a : 'all');
55
+ const [notificationType, setNotificationType] = (0, react_1.useState)((_b = initialFilters === null || initialFilters === void 0 ? void 0 : initialFilters.notificationType) !== null && _b !== void 0 ? _b : 'all');
56
+ const [search, setSearch] = (0, react_1.useState)((_c = initialFilters === null || initialFilters === void 0 ? void 0 : initialFilters.search) !== null && _c !== void 0 ? _c : '');
57
+ const debounceTimerRef = (0, react_1.useRef)(null);
58
+ // Debounced search handler
59
+ const handleSearchChange = (0, react_1.useCallback)((value) => {
60
+ setSearch(value);
61
+ // Clear previous timer
62
+ if (debounceTimerRef.current) {
63
+ clearTimeout(debounceTimerRef.current);
64
+ }
65
+ // Set new timer for debounced callback
66
+ debounceTimerRef.current = setTimeout(() => {
67
+ const filters = {};
68
+ if (status !== 'all')
69
+ filters.status = status;
70
+ if (notificationType !== 'all')
71
+ filters.notificationType = notificationType;
72
+ if (value)
73
+ filters.search = value;
74
+ onFiltersChange === null || onFiltersChange === void 0 ? void 0 : onFiltersChange(filters);
75
+ }, 300);
76
+ }, [status, notificationType, onFiltersChange]);
77
+ // Handle status change
78
+ const handleStatusChange = (value) => {
79
+ setStatus(value);
80
+ // Clear search debounce timer and fire immediately
81
+ if (debounceTimerRef.current) {
82
+ clearTimeout(debounceTimerRef.current);
83
+ }
84
+ const filters = {};
85
+ if (value !== 'all')
86
+ filters.status = value;
87
+ if (notificationType !== 'all')
88
+ filters.notificationType = notificationType;
89
+ if (search)
90
+ filters.search = search;
91
+ onFiltersChange === null || onFiltersChange === void 0 ? void 0 : onFiltersChange(filters);
92
+ };
93
+ // Handle type change
94
+ const handleTypeChange = (value) => {
95
+ setNotificationType(value);
96
+ // Clear search debounce timer and fire immediately
97
+ if (debounceTimerRef.current) {
98
+ clearTimeout(debounceTimerRef.current);
99
+ }
100
+ const filters = {};
101
+ if (status !== 'all')
102
+ filters.status = status;
103
+ if (value !== 'all')
104
+ filters.notificationType = value;
105
+ if (search)
106
+ filters.search = search;
107
+ onFiltersChange === null || onFiltersChange === void 0 ? void 0 : onFiltersChange(filters);
108
+ };
109
+ // Cleanup timer on unmount
110
+ (0, react_1.useEffect)(() => {
111
+ return () => {
112
+ if (debounceTimerRef.current) {
113
+ clearTimeout(debounceTimerRef.current);
114
+ }
115
+ };
116
+ }, []);
117
+ return (<div className="flex flex-col gap-4 p-4 border border-input rounded-lg bg-background sm:flex-row sm:items-end sm:gap-2">
118
+ {/* Search Input */}
119
+ <div className="flex-1 min-w-0">
120
+ <label htmlFor="search-notifications" className="text-sm font-medium text-muted-foreground mb-2 block">
121
+ Search
122
+ </label>
123
+ <input_1.Input id="search-notifications" placeholder="Search by title, ID, or email..." value={search} onChange={(e) => handleSearchChange(e.target.value)} disabled={isLoading} data-testid="search-input"/>
124
+ </div>
125
+
126
+ {/* Status Select */}
127
+ <div className="w-full sm:w-auto">
128
+ <label htmlFor="status-filter" className="text-sm font-medium text-muted-foreground mb-2 block">
129
+ Status
130
+ </label>
131
+ <select_1.Select value={status} onValueChange={handleStatusChange} disabled={isLoading}>
132
+ <select_1.SelectTrigger id="status-filter" data-testid="status-select">
133
+ <select_1.SelectValue />
134
+ </select_1.SelectTrigger>
135
+ <select_1.SelectContent>
136
+ <select_1.SelectItem value="all">All Statuses</select_1.SelectItem>
137
+ {NOTIFICATION_STATUSES.map((s) => (<select_1.SelectItem key={s} value={s}>
138
+ {s}
139
+ </select_1.SelectItem>))}
140
+ </select_1.SelectContent>
141
+ </select_1.Select>
142
+ </div>
143
+
144
+ {/* Type Select */}
145
+ <div className="w-full sm:w-auto">
146
+ <label htmlFor="type-filter" className="text-sm font-medium text-muted-foreground mb-2 block">
147
+ Type
148
+ </label>
149
+ <select_1.Select value={notificationType} onValueChange={handleTypeChange} disabled={isLoading}>
150
+ <select_1.SelectTrigger id="type-filter" data-testid="type-select">
151
+ <select_1.SelectValue />
152
+ </select_1.SelectTrigger>
153
+ <select_1.SelectContent>
154
+ <select_1.SelectItem value="all">All Types</select_1.SelectItem>
155
+ {NOTIFICATION_TYPES.map((t) => (<select_1.SelectItem key={t} value={t}>
156
+ {t}
157
+ </select_1.SelectItem>))}
158
+ </select_1.SelectContent>
159
+ </select_1.Select>
160
+ </div>
161
+ </div>);
162
+ }
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import type { AnyDashboardNotification } from '@/lib/notifications/types';
3
+ interface NotificationsTableProps {
4
+ data: AnyDashboardNotification[];
5
+ pageCount: number;
6
+ currentPage: number;
7
+ pageSize: number;
8
+ isLoading?: boolean;
9
+ onPaginationChange?: (page: number) => void;
10
+ }
11
+ /**
12
+ * Renders a paginated, filterable notifications table.
13
+ * Uses TanStack Table for headless table logic and shadcn/ui for components.
14
+ *
15
+ * @param data - Array of notifications to display
16
+ * @param pageCount - Total number of pages
17
+ * @param currentPage - Current page (1-indexed)
18
+ * @param pageSize - Items per page
19
+ * @param isLoading - Whether data is loading
20
+ * @param onPaginationChange - Callback when page changes
21
+ */
22
+ export declare function NotificationsTable({ data, pageCount, currentPage, pageSize, isLoading, onPaginationChange, }: NotificationsTableProps): React.JSX.Element;
23
+ export {};
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ 'use client';
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.NotificationsTable = NotificationsTable;
38
+ const react_1 = __importStar(require("react"));
39
+ const react_table_1 = require("@tanstack/react-table");
40
+ const columns_1 = require("./columns");
41
+ const table_1 = require("@/components/ui/table");
42
+ const button_1 = require("@/components/ui/button");
43
+ const skeleton_1 = require("@/components/ui/skeleton");
44
+ const lucide_react_1 = require("lucide-react");
45
+ /**
46
+ * Renders a paginated, filterable notifications table.
47
+ * Uses TanStack Table for headless table logic and shadcn/ui for components.
48
+ *
49
+ * @param data - Array of notifications to display
50
+ * @param pageCount - Total number of pages
51
+ * @param currentPage - Current page (1-indexed)
52
+ * @param pageSize - Items per page
53
+ * @param isLoading - Whether data is loading
54
+ * @param onPaginationChange - Callback when page changes
55
+ */
56
+ function NotificationsTable({ data, pageCount, currentPage, pageSize, isLoading = false, onPaginationChange, }) {
57
+ const [sorting, setSorting] = (0, react_1.useState)([]);
58
+ const table = (0, react_table_1.useReactTable)({
59
+ data,
60
+ columns: columns_1.columns,
61
+ getCoreRowModel: (0, react_table_1.getCoreRowModel)(),
62
+ getSortedRowModel: (0, react_table_1.getSortedRowModel)(),
63
+ manualPagination: true,
64
+ manualFiltering: true,
65
+ manualSorting: true,
66
+ state: {
67
+ sorting,
68
+ },
69
+ onSortingChange: setSorting,
70
+ });
71
+ const rows = table.getRowModel().rows;
72
+ // Show skeleton rows while loading
73
+ const displayRows = isLoading
74
+ ? Array.from({ length: pageSize }).map((_, i) => ({
75
+ id: `skeleton-${i}`,
76
+ original: null,
77
+ isSkeleton: true,
78
+ }))
79
+ : rows;
80
+ return (<div className="space-y-4">
81
+ {/* Table */}
82
+ <div className="border rounded-lg overflow-hidden">
83
+ <table_1.Table>
84
+ <table_1.TableHeader>
85
+ {table.getHeaderGroups().map((headerGroup) => (<table_1.TableRow key={headerGroup.id}>
86
+ {headerGroup.headers.map((header) => (<table_1.TableHead key={header.id} className="py-3 px-4">
87
+ {header.isPlaceholder ? null : (0, react_table_1.flexRender)(header.column.columnDef.header, header.getContext())}
88
+ </table_1.TableHead>))}
89
+ </table_1.TableRow>))}
90
+ </table_1.TableHeader>
91
+ <table_1.TableBody>
92
+ {displayRows.length === 0 && !isLoading ? (<table_1.TableRow>
93
+ <table_1.TableCell colSpan={columns_1.columns.length} className="h-24 text-center text-muted-foreground">
94
+ No notifications found.
95
+ </table_1.TableCell>
96
+ </table_1.TableRow>) : (displayRows.map((row) => (<table_1.TableRow key={row.id} data-testid={`notification-row-${row.id}`}>
97
+ {row.isSkeleton ? (
98
+ // Skeleton row
99
+ Array.from({ length: columns_1.columns.length }).map((_, i) => (<table_1.TableCell key={i} className="py-3 px-4">
100
+ <skeleton_1.Skeleton className="h-4 w-full"/>
101
+ </table_1.TableCell>))) : (
102
+ // Normal row
103
+ row.getVisibleCells().map((cell) => (<table_1.TableCell key={cell.id} className="py-3 px-4">
104
+ {(0, react_table_1.flexRender)(cell.column.columnDef.cell, cell.getContext())}
105
+ </table_1.TableCell>)))}
106
+ </table_1.TableRow>)))}
107
+ </table_1.TableBody>
108
+ </table_1.Table>
109
+ </div>
110
+
111
+ {/* Pagination Controls */}
112
+ {pageCount > 1 && (<div className="flex items-center justify-between px-2">
113
+ <div className="text-sm text-muted-foreground">
114
+ Page {currentPage} of {pageCount}
115
+ </div>
116
+ <div className="flex gap-2">
117
+ <button_1.Button variant="outline" size="sm" onClick={() => onPaginationChange === null || onPaginationChange === void 0 ? void 0 : onPaginationChange(1)} disabled={currentPage === 1 || isLoading} title="First page">
118
+ <lucide_react_1.ChevronsLeft className="h-4 w-4"/>
119
+ </button_1.Button>
120
+ <button_1.Button variant="outline" size="sm" onClick={() => onPaginationChange === null || onPaginationChange === void 0 ? void 0 : onPaginationChange(currentPage - 1)} disabled={currentPage === 1 || isLoading} title="Previous page">
121
+ <lucide_react_1.ChevronLeft className="h-4 w-4"/>
122
+ </button_1.Button>
123
+ <button_1.Button variant="outline" size="sm" onClick={() => onPaginationChange === null || onPaginationChange === void 0 ? void 0 : onPaginationChange(currentPage + 1)} disabled={currentPage >= pageCount || isLoading} title="Next page">
124
+ <lucide_react_1.ChevronRight className="h-4 w-4"/>
125
+ </button_1.Button>
126
+ <button_1.Button variant="outline" size="sm" onClick={() => onPaginationChange === null || onPaginationChange === void 0 ? void 0 : onPaginationChange(pageCount)} disabled={currentPage >= pageCount || isLoading} title="Last page">
127
+ <lucide_react_1.ChevronsRight className="h-4 w-4"/>
128
+ </button_1.Button>
129
+ </div>
130
+ </div>)}
131
+ </div>);
132
+ }
@@ -0,0 +1 @@
1
+ export default function Home(): import("react").JSX.Element;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = Home;
4
+ const auth_status_1 = require("./components/auth-status");
5
+ function Home() {
6
+ return (<div className="flex min-h-screen items-center justify-center bg-zinc-50 font-sans dark:bg-black">
7
+ <main className="flex min-h-screen w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black">
8
+ <div className="self-end">
9
+ <auth_status_1.AuthStatus />
10
+ </div>
11
+ <div className="flex flex-col items-center gap-6 text-center">
12
+ <h1 className="text-4xl font-bold tracking-tight text-black dark:text-zinc-50">
13
+ Vintasend Dashboard
14
+ </h1>
15
+ <p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
16
+ Authenticated with pluggable auth strategies (Clerk / Auth0)
17
+ </p>
18
+ <div className="mt-8 p-4 bg-blue-50 dark:bg-blue-950 rounded-lg">
19
+ <p className="text-sm text-blue-900 dark:text-blue-100">
20
+ Phase 4 Implementation Complete:
21
+ </p>
22
+ <ul className="text-sm text-blue-800 dark:text-blue-200 mt-2 space-y-1">
23
+ <li>✓ Middleware protecting routes</li>
24
+ <li>✓ Auth provider integrated in layout</li>
25
+ <li>✓ AuthContext providing user state</li>
26
+ <li>✓ AuthStatus component displaying user info</li>
27
+ </ul>
28
+ </div>
29
+ </div>
30
+ </main>
31
+ </div>);
32
+ }
@@ -0,0 +1 @@
1
+ export default function SignInPage(): import("react").JSX.Element;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = SignInPage;
4
+ const nextjs_1 = require("@clerk/nextjs");
5
+ const navigation_1 = require("next/navigation");
6
+ const auth_1 = require("@/lib/auth");
7
+ function SignInPage() {
8
+ const strategy = (0, auth_1.resolveAuthStrategy)();
9
+ const authProvider = process.env.AUTH_PROVIDER;
10
+ // For Auth0, redirect to the login endpoint
11
+ if (authProvider === "auth0") {
12
+ (0, navigation_1.redirect)(strategy.getSignInUrl());
13
+ }
14
+ // For Clerk, render the SignIn component
15
+ return (<main className="flex w-full justify-center pt-64">
16
+ <nextjs_1.SignIn />
17
+ </main>);
18
+ }
@@ -0,0 +1 @@
1
+ export default function SignOutPage(): import("react").JSX.Element;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = SignOutPage;
4
+ const nextjs_1 = require("@clerk/nextjs");
5
+ const auth_1 = require("@/lib/auth");
6
+ const navigation_1 = require("next/navigation");
7
+ function SignOutPage() {
8
+ const strategy = (0, auth_1.resolveAuthStrategy)();
9
+ const authProvider = process.env.AUTH_PROVIDER;
10
+ // For Auth0, redirect to the logout endpoint
11
+ if (authProvider === "auth0") {
12
+ (0, navigation_1.redirect)(strategy.getSignOutUrl());
13
+ }
14
+ // For Clerk, render the SignedOut component
15
+ return <nextjs_1.SignedOut />;
16
+ }
@@ -0,0 +1,9 @@
1
+ import * as React from "react";
2
+ import { type VariantProps } from "class-variance-authority";
3
+ declare const badgeVariants: (props?: ({
4
+ variant?: "link" | "default" | "outline" | "secondary" | "destructive" | "ghost" | null | undefined;
5
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
6
+ declare function Badge({ className, variant, asChild, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & {
7
+ asChild?: boolean;
8
+ }): React.JSX.Element;
9
+ export { Badge, badgeVariants };
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.badgeVariants = void 0;
37
+ exports.Badge = Badge;
38
+ const React = __importStar(require("react"));
39
+ const class_variance_authority_1 = require("class-variance-authority");
40
+ const radix_ui_1 = require("radix-ui");
41
+ const utils_1 = require("@/lib/utils");
42
+ const badgeVariants = (0, class_variance_authority_1.cva)("inline-flex items-center justify-center rounded-full border border-transparent px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", {
43
+ variants: {
44
+ variant: {
45
+ default: "bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
46
+ secondary: "bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
47
+ destructive: "bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
48
+ outline: "border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
49
+ ghost: "[a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
50
+ link: "text-primary underline-offset-4 [a&]:hover:underline",
51
+ },
52
+ },
53
+ defaultVariants: {
54
+ variant: "default",
55
+ },
56
+ });
57
+ exports.badgeVariants = badgeVariants;
58
+ function Badge({ className, variant = "default", asChild = false, ...props }) {
59
+ const Comp = asChild ? radix_ui_1.Slot.Root : "span";
60
+ return (<Comp data-slot="badge" data-variant={variant} className={(0, utils_1.cn)(badgeVariants({ variant }), className)} {...props}/>);
61
+ }
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ import { type VariantProps } from "class-variance-authority";
3
+ declare const buttonVariants: (props?: ({
4
+ variant?: "link" | "default" | "outline" | "secondary" | "destructive" | "ghost" | null | undefined;
5
+ size?: "default" | "icon" | "lg" | "sm" | "xs" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
6
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
7
+ declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
8
+ asChild?: boolean;
9
+ }): React.JSX.Element;
10
+ export { Button, buttonVariants };
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.buttonVariants = void 0;
37
+ exports.Button = Button;
38
+ const React = __importStar(require("react"));
39
+ const class_variance_authority_1 = require("class-variance-authority");
40
+ const radix_ui_1 = require("radix-ui");
41
+ const utils_1 = require("@/lib/utils");
42
+ const buttonVariants = (0, class_variance_authority_1.cva)("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", {
43
+ variants: {
44
+ variant: {
45
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
46
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
47
+ outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
48
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
49
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
50
+ link: "text-primary underline-offset-4 hover:underline",
51
+ },
52
+ size: {
53
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
54
+ xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
55
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
56
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
57
+ icon: "size-9",
58
+ "icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
59
+ "icon-sm": "size-8",
60
+ "icon-lg": "size-10",
61
+ },
62
+ },
63
+ defaultVariants: {
64
+ variant: "default",
65
+ size: "default",
66
+ },
67
+ });
68
+ exports.buttonVariants = buttonVariants;
69
+ function Button({ className, variant = "default", size = "default", asChild = false, ...props }) {
70
+ const Comp = asChild ? radix_ui_1.Slot.Root : "button";
71
+ return (<Comp data-slot="button" data-variant={variant} data-size={size} className={(0, utils_1.cn)(buttonVariants({ variant, size, className }))} {...props}/>);
72
+ }
@@ -0,0 +1,8 @@
1
+ import * as React from "react";
2
+ import { DayPicker, type DayButton } from "react-day-picker";
3
+ import { Button } from "@/components/ui/button";
4
+ declare function Calendar({ className, classNames, showOutsideDays, captionLayout, buttonVariant, formatters, components, ...props }: React.ComponentProps<typeof DayPicker> & {
5
+ buttonVariant?: React.ComponentProps<typeof Button>["variant"];
6
+ }): React.JSX.Element;
7
+ declare function CalendarDayButton({ className, day, modifiers, ...props }: React.ComponentProps<typeof DayButton>): React.JSX.Element;
8
+ export { Calendar, CalendarDayButton };