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.
- package/dist/services/notification-service.d.ts +2 -0
- package/dist/services/notification-service.js +6 -0
- package/dist/tools/vintasend-dashboard/app/components/auth-status.d.ts +1 -0
- package/dist/tools/vintasend-dashboard/app/components/auth-status.js +29 -0
- package/dist/tools/vintasend-dashboard/app/error.d.ts +6 -0
- package/dist/tools/vintasend-dashboard/app/error.js +40 -0
- package/dist/tools/vintasend-dashboard/app/layout.d.ts +6 -0
- package/dist/tools/vintasend-dashboard/app/layout.js +38 -0
- package/dist/tools/vintasend-dashboard/app/notifications/actions.d.ts +51 -0
- package/dist/tools/vintasend-dashboard/app/notifications/actions.js +224 -0
- package/dist/tools/vintasend-dashboard/app/notifications/components/columns.d.ts +6 -0
- package/dist/tools/vintasend-dashboard/app/notifications/components/columns.js +158 -0
- package/dist/tools/vintasend-dashboard/app/notifications/components/notifications-filters.d.ts +18 -0
- package/dist/tools/vintasend-dashboard/app/notifications/components/notifications-filters.js +162 -0
- package/dist/tools/vintasend-dashboard/app/notifications/components/notifications-table.d.ts +23 -0
- package/dist/tools/vintasend-dashboard/app/notifications/components/notifications-table.js +132 -0
- package/dist/tools/vintasend-dashboard/app/page.d.ts +1 -0
- package/dist/tools/vintasend-dashboard/app/page.js +32 -0
- package/dist/tools/vintasend-dashboard/app/sign-in/[[...sign-in]]/page.d.ts +1 -0
- package/dist/tools/vintasend-dashboard/app/sign-in/[[...sign-in]]/page.js +18 -0
- package/dist/tools/vintasend-dashboard/app/sign-out/[[...sign-out]]/page.d.ts +1 -0
- package/dist/tools/vintasend-dashboard/app/sign-out/[[...sign-out]]/page.js +16 -0
- package/dist/tools/vintasend-dashboard/components/ui/badge.d.ts +9 -0
- package/dist/tools/vintasend-dashboard/components/ui/badge.js +61 -0
- package/dist/tools/vintasend-dashboard/components/ui/button.d.ts +10 -0
- package/dist/tools/vintasend-dashboard/components/ui/button.js +72 -0
- package/dist/tools/vintasend-dashboard/components/ui/calendar.d.ts +8 -0
- package/dist/tools/vintasend-dashboard/components/ui/calendar.js +116 -0
- package/dist/tools/vintasend-dashboard/components/ui/dropdown-menu.d.ts +25 -0
- package/dist/tools/vintasend-dashboard/components/ui/dropdown-menu.js +119 -0
- package/dist/tools/vintasend-dashboard/components/ui/input.d.ts +3 -0
- package/dist/tools/vintasend-dashboard/components/ui/input.js +41 -0
- package/dist/tools/vintasend-dashboard/components/ui/pagination.d.ts +13 -0
- package/dist/tools/vintasend-dashboard/components/ui/pagination.js +79 -0
- package/dist/tools/vintasend-dashboard/components/ui/popover.d.ts +10 -0
- package/dist/tools/vintasend-dashboard/components/ui/popover.js +69 -0
- package/dist/tools/vintasend-dashboard/components/ui/select.d.ts +15 -0
- package/dist/tools/vintasend-dashboard/components/ui/select.js +106 -0
- package/dist/tools/vintasend-dashboard/components/ui/skeleton.d.ts +2 -0
- package/dist/tools/vintasend-dashboard/components/ui/skeleton.js +7 -0
- package/dist/tools/vintasend-dashboard/components/ui/table.d.ts +10 -0
- package/dist/tools/vintasend-dashboard/components/ui/table.js +72 -0
- package/dist/tools/vintasend-dashboard/lib/auth/auth-context.d.ts +23 -0
- package/dist/tools/vintasend-dashboard/lib/auth/auth-context.js +30 -0
- package/dist/tools/vintasend-dashboard/lib/auth/index.d.ts +5 -0
- package/dist/tools/vintasend-dashboard/lib/auth/index.js +12 -0
- package/dist/tools/vintasend-dashboard/lib/auth/resolve-strategy.d.ts +5 -0
- package/dist/tools/vintasend-dashboard/lib/auth/resolve-strategy.js +24 -0
- package/dist/tools/vintasend-dashboard/lib/auth/strategies/auth0-strategy.d.ts +17 -0
- package/dist/tools/vintasend-dashboard/lib/auth/strategies/auth0-strategy.js +76 -0
- package/dist/tools/vintasend-dashboard/lib/auth/strategies/clerk-strategy.d.ts +18 -0
- package/dist/tools/vintasend-dashboard/lib/auth/strategies/clerk-strategy.js +70 -0
- package/dist/tools/vintasend-dashboard/lib/auth/types.d.ts +50 -0
- package/dist/tools/vintasend-dashboard/lib/auth/types.js +2 -0
- package/dist/tools/vintasend-dashboard/lib/auth/validate-config.d.ts +2 -0
- package/dist/tools/vintasend-dashboard/lib/auth/validate-config.js +10 -0
- package/dist/tools/vintasend-dashboard/lib/auth0.d.ts +6 -0
- package/dist/tools/vintasend-dashboard/lib/auth0.js +14 -0
- package/dist/tools/vintasend-dashboard/lib/notifications/get-vintasend-service.d.ts +26 -0
- package/dist/tools/vintasend-dashboard/lib/notifications/get-vintasend-service.js +31 -0
- package/dist/tools/vintasend-dashboard/lib/notifications/serialize.d.ts +27 -0
- package/dist/tools/vintasend-dashboard/lib/notifications/serialize.js +75 -0
- package/dist/tools/vintasend-dashboard/lib/notifications/types.d.ts +62 -0
- package/dist/tools/vintasend-dashboard/lib/notifications/types.js +6 -0
- package/dist/tools/vintasend-dashboard/lib/utils.d.ts +2 -0
- package/dist/tools/vintasend-dashboard/lib/utils.js +8 -0
- package/dist/tools/vintasend-dashboard/next.config.d.ts +3 -0
- package/dist/tools/vintasend-dashboard/next.config.js +6 -0
- package/dist/tools/vintasend-dashboard/proxy.d.ts +5 -0
- package/dist/tools/vintasend-dashboard/proxy.js +83 -0
- 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 };
|