@actuate-media/cms-admin 0.9.0 → 0.11.0
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/AdminRoot.d.ts.map +1 -1
- package/dist/AdminRoot.js +8 -5
- package/dist/AdminRoot.js.map +1 -1
- package/dist/__tests__/layout/primitives.test.d.ts +2 -0
- package/dist/__tests__/layout/primitives.test.d.ts.map +1 -0
- package/dist/__tests__/layout/primitives.test.js +34 -0
- package/dist/__tests__/layout/primitives.test.js.map +1 -0
- package/dist/__tests__/lib/cv.test.d.ts +2 -0
- package/dist/__tests__/lib/cv.test.d.ts.map +1 -0
- package/dist/__tests__/lib/cv.test.js +66 -0
- package/dist/__tests__/lib/cv.test.js.map +1 -0
- package/dist/actuate-admin.css +1 -1
- package/dist/assets/actuate-logo.d.ts +36 -0
- package/dist/assets/actuate-logo.d.ts.map +1 -0
- package/dist/assets/actuate-logo.js +15 -0
- package/dist/assets/actuate-logo.js.map +1 -0
- package/dist/components/Breadcrumbs.js +2 -2
- package/dist/components/CommandPalette.js +10 -10
- package/dist/components/ContentOverviewChart.js +3 -3
- package/dist/components/ErrorBoundary.js +1 -1
- package/dist/components/FocalPointPicker.js +2 -2
- package/dist/components/FolderTree.js +20 -20
- package/dist/components/LivePreview.js +3 -3
- package/dist/components/LocaleSwitcher.js +1 -1
- package/dist/components/MediaPickerModal.js +4 -4
- package/dist/components/PresenceIndicator.js +1 -1
- package/dist/components/SEOConfigPanel.d.ts +2 -0
- package/dist/components/SEOConfigPanel.d.ts.map +1 -0
- package/dist/components/SEOConfigPanel.js +174 -0
- package/dist/components/SEOConfigPanel.js.map +1 -0
- package/dist/components/SEOPanel.js +9 -9
- package/dist/components/SEOPerformance.js +2 -2
- package/dist/components/SchedulePublishDialog.d.ts +18 -0
- package/dist/components/SchedulePublishDialog.d.ts.map +1 -0
- package/dist/components/SchedulePublishDialog.js +106 -0
- package/dist/components/SchedulePublishDialog.js.map +1 -0
- package/dist/components/SharePreviewLinkDialog.d.ts +17 -0
- package/dist/components/SharePreviewLinkDialog.d.ts.map +1 -0
- package/dist/components/SharePreviewLinkDialog.js +83 -0
- package/dist/components/SharePreviewLinkDialog.js.map +1 -0
- package/dist/components/TipTapEditor.js +5 -5
- package/dist/components/VersionHistory.js +2 -2
- package/dist/components/ui/Badge.d.ts +33 -3
- package/dist/components/ui/Badge.d.ts.map +1 -1
- package/dist/components/ui/Badge.js +42 -8
- package/dist/components/ui/Badge.js.map +1 -1
- package/dist/components/ui/Button.d.ts +19 -8
- package/dist/components/ui/Button.d.ts.map +1 -1
- package/dist/components/ui/Button.js +35 -14
- package/dist/components/ui/Button.js.map +1 -1
- package/dist/components/ui/Card.d.ts +26 -0
- package/dist/components/ui/Card.d.ts.map +1 -0
- package/dist/components/ui/Card.js +45 -0
- package/dist/components/ui/Card.js.map +1 -0
- package/dist/components/ui/DataTable.js +1 -1
- package/dist/components/ui/Input.d.ts +15 -0
- package/dist/components/ui/Input.d.ts.map +1 -0
- package/dist/components/ui/Input.js +23 -0
- package/dist/components/ui/Input.js.map +1 -0
- package/dist/components/ui/SearchInput.js +1 -1
- package/dist/components/ui/Select.d.ts +16 -0
- package/dist/components/ui/Select.d.ts.map +1 -0
- package/dist/components/ui/Select.js +25 -0
- package/dist/components/ui/Select.js.map +1 -0
- package/dist/components/ui/Toast.js +1 -1
- package/dist/components/ui/index.d.ts +10 -4
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +5 -2
- package/dist/components/ui/index.js.map +1 -1
- package/dist/fields/BlockBuilderField.js +3 -3
- package/dist/fields/DateField.js +1 -1
- package/dist/fields/RelationshipField.js +3 -3
- package/dist/fields/TextField.js +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/layout/Header.js +1 -1
- package/dist/layout/Layout.d.ts +14 -0
- package/dist/layout/Layout.d.ts.map +1 -1
- package/dist/layout/Layout.js +17 -11
- package/dist/layout/Layout.js.map +1 -1
- package/dist/layout/Sidebar.d.ts.map +1 -1
- package/dist/layout/Sidebar.js +21 -11
- package/dist/layout/Sidebar.js.map +1 -1
- package/dist/layout/primitives/AdminShell.d.ts +43 -0
- package/dist/layout/primitives/AdminShell.d.ts.map +1 -0
- package/dist/layout/primitives/AdminShell.js +51 -0
- package/dist/layout/primitives/AdminShell.js.map +1 -0
- package/dist/layout/primitives/Box.d.ts +19 -0
- package/dist/layout/primitives/Box.d.ts.map +1 -0
- package/dist/layout/primitives/Box.js +12 -0
- package/dist/layout/primitives/Box.js.map +1 -0
- package/dist/layout/primitives/Cluster.d.ts +27 -0
- package/dist/layout/primitives/Cluster.d.ts.map +1 -0
- package/dist/layout/primitives/Cluster.js +37 -0
- package/dist/layout/primitives/Cluster.js.map +1 -0
- package/dist/layout/primitives/Grid.d.ts +45 -0
- package/dist/layout/primitives/Grid.d.ts.map +1 -0
- package/dist/layout/primitives/Grid.js +59 -0
- package/dist/layout/primitives/Grid.js.map +1 -0
- package/dist/layout/primitives/PageContainer.d.ts +36 -0
- package/dist/layout/primitives/PageContainer.d.ts.map +1 -0
- package/dist/layout/primitives/PageContainer.js +41 -0
- package/dist/layout/primitives/PageContainer.js.map +1 -0
- package/dist/layout/primitives/Split.d.ts +34 -0
- package/dist/layout/primitives/Split.d.ts.map +1 -0
- package/dist/layout/primitives/Split.js +27 -0
- package/dist/layout/primitives/Split.js.map +1 -0
- package/dist/layout/primitives/Stack.d.ts +23 -0
- package/dist/layout/primitives/Stack.d.ts.map +1 -0
- package/dist/layout/primitives/Stack.js +34 -0
- package/dist/layout/primitives/Stack.js.map +1 -0
- package/dist/layout/primitives/index.d.ts +30 -0
- package/dist/layout/primitives/index.d.ts.map +1 -0
- package/dist/layout/primitives/index.js +22 -0
- package/dist/layout/primitives/index.js.map +1 -0
- package/dist/layout/primitives/tokens.d.ts +48 -0
- package/dist/layout/primitives/tokens.d.ts.map +1 -0
- package/dist/layout/primitives/tokens.js +54 -0
- package/dist/layout/primitives/tokens.js.map +1 -0
- package/dist/lib/cv.d.ts +53 -0
- package/dist/lib/cv.d.ts.map +1 -0
- package/dist/lib/cv.js +39 -0
- package/dist/lib/cv.js.map +1 -0
- package/dist/views/ApiKeys.d.ts.map +1 -1
- package/dist/views/ApiKeys.js +13 -11
- package/dist/views/ApiKeys.js.map +1 -1
- package/dist/views/CollectionList.js +8 -8
- package/dist/views/Dashboard.d.ts.map +1 -1
- package/dist/views/Dashboard.js +333 -78
- package/dist/views/Dashboard.js.map +1 -1
- package/dist/views/DocumentEdit.d.ts.map +1 -1
- package/dist/views/DocumentEdit.js +17 -5
- package/dist/views/DocumentEdit.js.map +1 -1
- package/dist/views/ForgotPassword.js +2 -2
- package/dist/views/FormEditor.js +5 -5
- package/dist/views/FormSubmissions.js +6 -6
- package/dist/views/Forms.js +2 -2
- package/dist/views/Login.d.ts +16 -1
- package/dist/views/Login.d.ts.map +1 -1
- package/dist/views/Login.js +17 -7
- package/dist/views/Login.js.map +1 -1
- package/dist/views/MediaBrowser.js +16 -16
- package/dist/views/PageEditor.js +2 -2
- package/dist/views/Pages.js +10 -10
- package/dist/views/PostEditor.js +2 -2
- package/dist/views/Posts.js +4 -4
- package/dist/views/Redirects.js +4 -4
- package/dist/views/ResetPassword.js +2 -2
- package/dist/views/SEO.js +6 -6
- package/dist/views/ScriptTagEditor.js +4 -4
- package/dist/views/ScriptTags.js +2 -2
- package/dist/views/Settings.d.ts.map +1 -1
- package/dist/views/Settings.js +9 -8
- package/dist/views/Settings.js.map +1 -1
- package/dist/views/SetupWizard.js +2 -2
- package/dist/views/Users.js +4 -4
- package/dist/views/page-builder/AIBlockAssist.js +1 -1
- package/dist/views/page-builder/AIGenerateDialog.js +10 -10
- package/dist/views/page-builder/BlockEditor.js +10 -10
- package/dist/views/page-builder/BlockPicker.js +4 -4
- package/dist/views/page-builder/BottomBar.js +1 -1
- package/dist/views/page-builder/BuilderToolbar.js +2 -2
- package/dist/views/page-builder/ContextPanel.js +2 -2
- package/dist/views/page-builder/DesignScore.js +9 -9
- package/dist/views/page-builder/NodeSettings.js +8 -8
- package/dist/views/page-builder/PageBuilder.js +3 -3
- package/dist/views/page-builder/PageSettings.js +1 -1
- package/dist/views/page-builder/PageTemplates.js +2 -2
- package/dist/views/page-builder/SEOPanel.js +13 -13
- package/dist/views/page-builder/SavedSections.js +5 -5
- package/dist/views/page-builder/TemplatePicker.js +2 -2
- package/dist/views/page-builder/block-renderers/CTAPreview.js +5 -5
- package/dist/views/page-builder/block-renderers/CardsPreview.js +1 -1
- package/dist/views/page-builder/block-renderers/CodePreview.js +1 -1
- package/dist/views/page-builder/block-renderers/FAQPreview.js +3 -3
- package/dist/views/page-builder/block-renderers/FallbackPreview.js +1 -1
- package/dist/views/page-builder/block-renderers/FormPreview.js +3 -3
- package/dist/views/page-builder/block-renderers/GalleryPreview.js +5 -5
- package/dist/views/page-builder/block-renderers/HeroPreview.js +3 -3
- package/dist/views/page-builder/block-renderers/ImagePreview.js +3 -3
- package/dist/views/page-builder/block-renderers/TextPreview.js +3 -3
- package/dist/views/page-builder/block-renderers/VideoPreview.js +4 -4
- package/dist/views/page-builder/canvas/BlockRenderer.js +1 -1
- package/dist/views/page-builder/canvas/BuilderCanvas.js +3 -3
- package/dist/views/page-builder/canvas/ColumnRenderer.js +2 -2
- package/dist/views/page-builder/canvas/ContainerRenderer.js +2 -2
- package/dist/views/page-builder/canvas/RowRenderer.js +2 -2
- package/dist/views/page-builder/canvas/SectionRenderer.js +2 -2
- package/package.json +6 -2
- package/src/AdminRoot.tsx +21 -11
- package/src/__tests__/layout/primitives.test.ts +37 -0
- package/src/__tests__/lib/cv.test.ts +74 -0
- package/src/assets/actuate-logo.tsx +72 -0
- package/src/components/Breadcrumbs.tsx +6 -6
- package/src/components/CommandPalette.tsx +34 -34
- package/src/components/ContentOverviewChart.tsx +3 -3
- package/src/components/ErrorBoundary.tsx +3 -3
- package/src/components/FocalPointPicker.tsx +4 -4
- package/src/components/FolderTree.tsx +38 -38
- package/src/components/LivePreview.tsx +16 -16
- package/src/components/LocaleSwitcher.tsx +7 -7
- package/src/components/MediaPickerModal.tsx +21 -21
- package/src/components/PresenceIndicator.tsx +2 -2
- package/src/components/SEOConfigPanel.tsx +582 -0
- package/src/components/SEOPanel.tsx +46 -46
- package/src/components/SEOPerformance.tsx +21 -21
- package/src/components/SchedulePublishDialog.tsx +241 -0
- package/src/components/SharePreviewLinkDialog.tsx +227 -0
- package/src/components/TipTapEditor.tsx +33 -33
- package/src/components/VersionHistory.tsx +16 -16
- package/src/components/ui/Badge.tsx +66 -14
- package/src/components/ui/Button.tsx +70 -33
- package/src/components/ui/Card.tsx +101 -0
- package/src/components/ui/DataTable.tsx +1 -1
- package/src/components/ui/Input.tsx +35 -0
- package/src/components/ui/SearchInput.tsx +4 -4
- package/src/components/ui/Select.tsx +56 -0
- package/src/components/ui/Toast.tsx +1 -1
- package/src/components/ui/index.ts +18 -4
- package/src/fields/BlockBuilderField.tsx +3 -3
- package/src/fields/DateField.tsx +1 -1
- package/src/fields/RelationshipField.tsx +10 -10
- package/src/fields/TextField.tsx +1 -1
- package/src/index.ts +32 -0
- package/src/layout/Header.tsx +28 -28
- package/src/layout/Layout.tsx +39 -46
- package/src/layout/Sidebar.tsx +37 -64
- package/src/layout/primitives/AdminShell.tsx +118 -0
- package/src/layout/primitives/Box.tsx +30 -0
- package/src/layout/primitives/Cluster.tsx +74 -0
- package/src/layout/primitives/Grid.tsx +120 -0
- package/src/layout/primitives/PageContainer.tsx +96 -0
- package/src/layout/primitives/Split.tsx +73 -0
- package/src/layout/primitives/Stack.tsx +67 -0
- package/src/layout/primitives/index.ts +36 -0
- package/src/layout/primitives/tokens.ts +76 -0
- package/src/lib/cv.ts +96 -0
- package/src/styles/build-input.css +1 -1
- package/src/views/ApiKeys.tsx +57 -57
- package/src/views/CollectionList.tsx +30 -30
- package/src/views/Dashboard.tsx +737 -186
- package/src/views/DocumentEdit.tsx +90 -10
- package/src/views/ForgotPassword.tsx +18 -18
- package/src/views/FormEditor.tsx +75 -75
- package/src/views/FormSubmissions.tsx +76 -76
- package/src/views/Forms.tsx +27 -27
- package/src/views/Login.tsx +65 -25
- package/src/views/MediaBrowser.tsx +127 -127
- package/src/views/PageEditor.tsx +25 -25
- package/src/views/Pages.tsx +59 -59
- package/src/views/PostEditor.tsx +37 -37
- package/src/views/Posts.tsx +48 -48
- package/src/views/Redirects.tsx +21 -21
- package/src/views/ResetPassword.tsx +28 -28
- package/src/views/SEO.tsx +144 -144
- package/src/views/ScriptTagEditor.tsx +24 -24
- package/src/views/ScriptTags.tsx +10 -10
- package/src/views/Settings.tsx +88 -80
- package/src/views/SetupWizard.tsx +28 -28
- package/src/views/Users.tsx +20 -20
- package/src/views/page-builder/AIBlockAssist.tsx +1 -1
- package/src/views/page-builder/AIGenerateDialog.tsx +63 -63
- package/src/views/page-builder/BlockEditor.tsx +26 -26
- package/src/views/page-builder/BlockPicker.tsx +22 -22
- package/src/views/page-builder/BottomBar.tsx +8 -8
- package/src/views/page-builder/BuilderToolbar.tsx +17 -17
- package/src/views/page-builder/ContextPanel.tsx +3 -3
- package/src/views/page-builder/DesignScore.tsx +21 -21
- package/src/views/page-builder/NodeSettings.tsx +27 -27
- package/src/views/page-builder/PageBuilder.tsx +11 -11
- package/src/views/page-builder/PageSettings.tsx +4 -4
- package/src/views/page-builder/PageTemplates.tsx +18 -18
- package/src/views/page-builder/SEOPanel.tsx +53 -53
- package/src/views/page-builder/SavedSections.tsx +37 -37
- package/src/views/page-builder/TemplatePicker.tsx +17 -17
- package/src/views/page-builder/block-renderers/CTAPreview.tsx +13 -13
- package/src/views/page-builder/block-renderers/CardsPreview.tsx +5 -5
- package/src/views/page-builder/block-renderers/CodePreview.tsx +6 -6
- package/src/views/page-builder/block-renderers/FAQPreview.tsx +13 -13
- package/src/views/page-builder/block-renderers/FallbackPreview.tsx +3 -3
- package/src/views/page-builder/block-renderers/FormPreview.tsx +20 -20
- package/src/views/page-builder/block-renderers/GalleryPreview.tsx +8 -8
- package/src/views/page-builder/block-renderers/HeroPreview.tsx +16 -16
- package/src/views/page-builder/block-renderers/ImagePreview.tsx +4 -4
- package/src/views/page-builder/block-renderers/TextPreview.tsx +14 -14
- package/src/views/page-builder/block-renderers/VideoPreview.tsx +12 -12
- package/src/views/page-builder/canvas/BlockRenderer.tsx +4 -4
- package/src/views/page-builder/canvas/BuilderCanvas.tsx +6 -6
- package/src/views/page-builder/canvas/ColumnRenderer.tsx +3 -3
- package/src/views/page-builder/canvas/ContainerRenderer.tsx +2 -2
- package/src/views/page-builder/canvas/RowRenderer.tsx +2 -2
- package/src/views/page-builder/canvas/SectionRenderer.tsx +2 -2
package/dist/views/Posts.js
CHANGED
|
@@ -62,12 +62,12 @@ export function Posts({ onNavigate }) {
|
|
|
62
62
|
};
|
|
63
63
|
function SortHeader({ label, sortKey }) {
|
|
64
64
|
const active = sortConfig?.key === sortKey;
|
|
65
|
-
return (_jsxs("button", { type: "button", onClick: () => setSortConfig(toggleSort(sortConfig, sortKey)), className: "flex items-center gap-1 text-xs font-medium text-gray-700 hover:text-gray-900
|
|
65
|
+
return (_jsxs("button", { type: "button", onClick: () => setSortConfig(toggleSort(sortConfig, sortKey)), className: "flex items-center gap-1 text-xs font-medium text-gray-700 transition-colors hover:text-gray-900", children: [label, active ? (sortConfig.direction === 'asc' ? (_jsx(ArrowUp, { className: "h-3 w-3" })) : (_jsx(ArrowDown, { className: "h-3 w-3" }))) : (_jsx(ArrowUpDown, { className: "h-3 w-3 text-gray-400" }))] }));
|
|
66
66
|
}
|
|
67
67
|
if (loading) {
|
|
68
|
-
return (_jsx("div", { className: "p-3 pr-6 sm:p-4 sm:pr-8
|
|
68
|
+
return (_jsx("div", { className: "flex h-64 items-center justify-center p-3 pr-6 sm:p-4 sm:pr-8", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-blue-600" }) }));
|
|
69
69
|
}
|
|
70
|
-
return (_jsxs("div", { className: "p-3 pr-6 sm:p-4 sm:pr-8
|
|
71
|
-
filteredAndSorted.length > 0, onChange: (e) => handleSelectAll(e.target.checked), className: "rounded border-gray-300" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Title", sortKey: "title" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Author", sortKey: "author" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Category", sortKey: "category" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Status", sortKey: "status" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Date", sortKey: "date" }) }), _jsx("th", { className: "px-3 py-2 text-left text-xs font-medium text-gray-700", children: "Actions" })] }) }), _jsx("tbody", { className: "divide-y divide-gray-200", children: filteredAndSorted.map((post) => (_jsxs("tr", { className: "hover:bg-gray-50
|
|
70
|
+
return (_jsxs("div", { className: "flex h-full flex-col p-3 pr-6 sm:p-4 sm:pr-8", children: [error && (_jsxs("div", { className: "mb-4 flex items-center gap-3 rounded-lg border border-red-200 bg-red-50 p-3", children: [_jsx(AlertTriangle, { className: "h-5 w-5 shrink-0 text-red-600" }), _jsx("span", { className: "flex-1 text-sm text-red-800", children: error }), _jsx("button", { onClick: refetch, className: "rounded-lg border border-red-300 px-3 py-1 text-sm text-red-700 transition-colors hover:bg-red-100", children: "Retry" })] })), _jsxs("div", { className: "mb-4 flex flex-col justify-between gap-3 sm:flex-row sm:items-center", children: [_jsxs("div", { children: [_jsx("h1", { className: "mb-1 text-xl font-semibold text-gray-900 sm:text-2xl", children: "Posts" }), _jsxs("p", { className: "text-sm text-gray-600", children: [filteredAndSorted.length, " total posts"] })] }), _jsxs("button", { onClick: () => onNavigate?.('/posts/new'), className: "flex items-center justify-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm text-white transition-colors hover:bg-blue-700", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { className: "hidden sm:inline", children: "New Post" }), _jsx("span", { className: "sm:hidden", children: "New" })] })] }), _jsx("div", { className: "mb-4 rounded-lg border border-gray-200 bg-white", children: _jsxs("div", { className: "flex flex-col gap-3 p-3", children: [_jsxs("div", { className: "relative", children: [_jsx(Search, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-gray-400" }), _jsx("input", { type: "text", placeholder: "Search posts...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "w-full rounded-lg border border-gray-300 py-2 pr-3 pl-9 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" })] }), _jsxs("div", { className: "flex flex-col gap-2 sm:flex-row", children: [_jsxs("select", { value: filterStatus, onChange: (e) => setFilterStatus(e.target.value), className: "flex-1 rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", children: [_jsx("option", { value: "all", children: "All Status" }), _jsx("option", { value: "published", children: "Published" }), _jsx("option", { value: "draft", children: "Draft" })] }), _jsxs("select", { value: filterCategory, onChange: (e) => setFilterCategory(e.target.value), className: "flex-1 rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", children: [_jsx("option", { value: "all", children: "All Categories" }), _jsx("option", { value: "technology", children: "Technology" }), _jsx("option", { value: "design", children: "Design" }), _jsx("option", { value: "business", children: "Business" })] }), _jsxs("button", { type: "button", className: "flex items-center justify-center gap-2 rounded-lg border border-gray-300 px-3 py-2 text-sm transition-colors hover:bg-gray-50", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), _jsx("span", { className: "hidden sm:inline", children: "More Filters" })] })] })] }) }), selectedPosts.length > 0 && (_jsx("div", { className: "mb-4 rounded-lg border border-blue-200 bg-blue-50 p-3", children: _jsxs("div", { className: "flex flex-col justify-between gap-2 sm:flex-row sm:items-center", children: [_jsxs("span", { className: "text-sm text-blue-900", children: [selectedPosts.length, " post", selectedPosts.length !== 1 ? 's' : '', " selected"] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { type: "button", onClick: handleBulkDelete, className: "flex-1 rounded-lg bg-red-600 px-3 py-1.5 text-sm text-white transition-colors hover:bg-red-700 sm:flex-none", children: "Delete" }), _jsx("button", { type: "button", onClick: () => setSelectedPosts([]), className: "flex-1 rounded-lg border border-gray-300 bg-white px-3 py-1.5 text-sm transition-colors hover:bg-gray-50 sm:flex-none", children: "Cancel" })] })] }) })), filteredAndSorted.length === 0 && !error ? (_jsxs("div", { className: "flex flex-1 flex-col items-center justify-center rounded-lg border border-gray-200 bg-white p-8 text-center", children: [_jsx("p", { className: "mb-2 text-sm text-gray-500", children: "No posts yet" }), _jsx("button", { onClick: () => onNavigate?.('/posts/new'), className: "rounded-lg bg-blue-600 px-4 py-2 text-sm text-white transition-colors hover:bg-blue-700", children: "Create your first post" })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "hidden flex-1 overflow-hidden rounded-lg border border-gray-200 bg-white md:block", children: _jsx("div", { className: "h-full overflow-x-auto", children: _jsxs("table", { className: "w-full", children: [_jsx("thead", { className: "sticky top-0 border-b border-gray-200 bg-gray-50", children: _jsxs("tr", { children: [_jsx("th", { className: "w-8 px-3 py-2 text-left", children: _jsx("input", { type: "checkbox", checked: selectedPosts.length === filteredAndSorted.length &&
|
|
71
|
+
filteredAndSorted.length > 0, onChange: (e) => handleSelectAll(e.target.checked), className: "rounded border-gray-300" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Title", sortKey: "title" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Author", sortKey: "author" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Category", sortKey: "category" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Status", sortKey: "status" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Date", sortKey: "date" }) }), _jsx("th", { className: "px-3 py-2 text-left text-xs font-medium text-gray-700", children: "Actions" })] }) }), _jsx("tbody", { className: "divide-y divide-gray-200", children: filteredAndSorted.map((post) => (_jsxs("tr", { className: "transition-colors hover:bg-gray-50", children: [_jsx("td", { className: "px-3 py-2", children: _jsx("input", { type: "checkbox", checked: selectedPosts.includes(post.id), onChange: () => handleSelectPost(post.id), className: "rounded border-gray-300" }) }), _jsx("td", { className: "px-3 py-2", children: _jsx("button", { type: "button", onClick: () => onNavigate?.(`/posts/${post.id}`), className: "text-left text-sm font-medium text-gray-900 hover:text-blue-600", children: post.title }) }), _jsx("td", { className: "px-3 py-2 text-sm text-gray-600", children: post.author }), _jsx("td", { className: "px-3 py-2 text-sm text-gray-600", children: post.category }), _jsx("td", { className: "px-3 py-2", children: _jsx("span", { className: `inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${post.status === 'Published' ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800'}`, children: post.status }) }), _jsx("td", { className: "px-3 py-2 text-sm text-gray-600", children: post.date }), _jsx("td", { className: "px-3 py-2", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { type: "button", onClick: () => onNavigate?.(`/posts/${post.id}`), className: "rounded p-1.5 transition-colors hover:bg-gray-100", title: "Edit", children: _jsx(Pencil, { className: "h-4 w-4 text-gray-600" }) }), _jsx("button", { type: "button", onClick: () => handleDelete(post.id), className: "rounded p-1.5 transition-colors hover:bg-gray-100", title: "Delete", children: _jsx(Trash2, { className: "h-4 w-4 text-red-600" }) })] }) })] }, post.id))) })] }) }) }), _jsx("div", { className: "flex-1 overflow-auto rounded-lg border border-gray-200 bg-white md:hidden", children: _jsx("div", { className: "divide-y divide-gray-200", children: filteredAndSorted.map((post) => (_jsx("div", { className: "p-3", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("input", { type: "checkbox", checked: selectedPosts.includes(post.id), onChange: () => handleSelectPost(post.id), className: "mt-1 rounded border-gray-300" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("button", { type: "button", onClick: () => onNavigate?.(`/posts/${post.id}`), className: "mb-1 block text-left text-sm font-medium text-gray-900 hover:text-blue-600", children: post.title }), _jsxs("div", { className: "mb-2 flex flex-wrap items-center gap-2 text-xs text-gray-600", children: [_jsx("span", { children: post.author }), _jsx("span", { children: "\u2022" }), _jsx("span", { children: post.date }), _jsx("span", { className: `rounded-full px-2 py-0.5 text-xs font-medium ${post.status === 'Published' ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800'}`, children: post.status })] })] }), _jsx("button", { type: "button", onClick: () => handleDelete(post.id), className: "rounded p-1.5 transition-colors hover:bg-gray-100", children: _jsx(Trash2, { className: "h-4 w-4 text-red-600" }) })] }) }, post.id))) }) })] }))] }));
|
|
72
72
|
}
|
|
73
73
|
//# sourceMappingURL=Posts.js.map
|
package/dist/views/Redirects.js
CHANGED
|
@@ -77,15 +77,15 @@ export function Redirects({ onNavigate }) {
|
|
|
77
77
|
};
|
|
78
78
|
function SortHeader({ label, sortKey }) {
|
|
79
79
|
const active = sortConfig?.key === sortKey;
|
|
80
|
-
return (_jsxs("button", { type: "button", onClick: () => setSortConfig(toggleSort(sortConfig, sortKey)), className: "flex items-center gap-1 text-xs font-medium text-gray-700 hover:text-gray-900
|
|
80
|
+
return (_jsxs("button", { type: "button", onClick: () => setSortConfig(toggleSort(sortConfig, sortKey)), className: "flex items-center gap-1 text-xs font-medium text-gray-700 transition-colors hover:text-gray-900", children: [label, active ? (sortConfig.direction === 'asc' ? (_jsx(ArrowUp, { className: "h-3 w-3" })) : (_jsx(ArrowDown, { className: "h-3 w-3" }))) : (_jsx(ArrowUpDown, { className: "h-3 w-3 text-gray-400" }))] }));
|
|
81
81
|
}
|
|
82
82
|
if (loading) {
|
|
83
|
-
return (_jsx("div", { className: "p-3 pr-6 sm:p-4 sm:pr-8
|
|
83
|
+
return (_jsx("div", { className: "flex h-64 items-center justify-center p-3 pr-6 sm:p-4 sm:pr-8", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-blue-600" }) }));
|
|
84
84
|
}
|
|
85
|
-
return (_jsxs("div", { className: "p-3 pr-6 sm:p-4 sm:pr-8", children: [error && (_jsxs("div", { className: "mb-4 flex items-center gap-3 rounded-lg border border-red-200 bg-red-50 p-3", children: [_jsx(AlertTriangle, { className: "
|
|
85
|
+
return (_jsxs("div", { className: "p-3 pr-6 sm:p-4 sm:pr-8", children: [error && (_jsxs("div", { className: "mb-4 flex items-center gap-3 rounded-lg border border-red-200 bg-red-50 p-3", children: [_jsx(AlertTriangle, { className: "h-5 w-5 shrink-0 text-red-600" }), _jsx("span", { className: "flex-1 text-sm text-red-800", children: error }), _jsx("button", { onClick: refetch, className: "rounded-lg border border-red-300 px-3 py-1 text-sm text-red-700 transition-colors hover:bg-red-100", children: "Retry" })] })), _jsxs("div", { className: "mb-4 flex items-center justify-between", children: [_jsxs("div", { children: [_jsx("h1", { className: "mb-1 text-xl font-semibold text-gray-900 sm:text-2xl", children: "Redirects" }), _jsxs("p", { className: "text-sm text-gray-600", children: [filteredAndSorted.length, " total redirects"] })] }), _jsxs("button", { type: "button", onClick: () => setShowAddDialog(true), className: "flex items-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm text-white transition-colors hover:bg-blue-700", children: [_jsx(Plus, { className: "h-4 w-4" }), "Add Redirect"] })] }), _jsx("div", { className: "mb-4 rounded-lg border border-gray-200 bg-white", children: _jsxs("div", { className: "flex flex-col gap-3 p-3 sm:flex-row", children: [_jsxs("div", { className: "relative flex-1", children: [_jsx(Search, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-gray-400" }), _jsx("input", { type: "text", placeholder: "Search by source or destination URL...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "w-full rounded-lg border border-gray-300 py-2 pr-3 pl-9 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" })] }), _jsxs("select", { value: filterType, onChange: (e) => setFilterType(e.target.value), className: "rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", children: [_jsx("option", { value: "all", children: "All Types" }), _jsx("option", { value: "301", children: "301 (Permanent)" }), _jsx("option", { value: "302", children: "302 (Temporary)" })] })] }) }), filteredAndSorted.length === 0 && !loading ? (_jsxs("div", { className: "flex flex-col items-center justify-center py-16 text-center", children: [_jsx("div", { className: "mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-gray-100", children: _jsx(ArrowRightLeft, { className: "h-6 w-6 text-gray-400" }) }), _jsx("h3", { className: "mb-1 text-sm font-medium text-gray-900", children: "No redirects yet" }), _jsx("p", { className: "text-sm text-gray-500", children: "Add your first redirect to get started." })] })) : (_jsx("div", { className: "rounded-lg border border-gray-200 bg-white", children: _jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "w-full", children: [_jsx("thead", { className: "border-b border-gray-200 bg-gray-50", children: _jsxs("tr", { children: [_jsx("th", { className: "px-4 py-2 text-left", children: _jsx(SortHeader, { label: "Source URL", sortKey: "from" }) }), _jsx("th", { className: "px-4 py-2 text-left", children: _jsx(SortHeader, { label: "Destination URL", sortKey: "to" }) }), _jsx("th", { className: "px-4 py-2 text-left", children: _jsx(SortHeader, { label: "Type", sortKey: "type" }) }), _jsx("th", { className: "px-4 py-2 text-left", children: _jsx(SortHeader, { label: "Hits", sortKey: "hits" }) }), _jsx("th", { className: "px-4 py-2 text-left", children: _jsx(SortHeader, { label: "Status", sortKey: "active" }) }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Actions" })] }) }), _jsx("tbody", { className: "divide-y divide-gray-200", children: filteredAndSorted.map((redirect) => (_jsxs("tr", { className: "transition-colors hover:bg-gray-50", children: [_jsx("td", { className: "px-4 py-3", children: _jsx("code", { className: "rounded bg-gray-100 px-2 py-1 text-xs text-gray-900", children: redirect.from }) }), _jsx("td", { className: "px-4 py-3", children: _jsx("code", { className: "rounded bg-gray-100 px-2 py-1 text-xs text-gray-900", children: redirect.to }) }), _jsx("td", { className: "px-4 py-3", children: _jsx("span", { className: `inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${redirect.type === '301'
|
|
86
86
|
? 'bg-blue-100 text-blue-800'
|
|
87
87
|
: 'bg-purple-100 text-purple-800'}`, children: redirect.type }) }), _jsx("td", { className: "px-4 py-3 text-sm text-gray-600", children: redirect.hits.toLocaleString() }), _jsx("td", { className: "px-4 py-3", children: _jsx("span", { className: `inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${redirect.active
|
|
88
88
|
? 'bg-green-100 text-green-800'
|
|
89
|
-
: 'bg-gray-100 text-gray-800'}`, children: redirect.active ? 'Active' : 'Inactive' }) }), _jsx("td", { className: "px-4 py-3", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { type: "button", onClick: () => onNavigate?.(`/redirects/${redirect.id}/edit`), className: "rounded p-1.5 transition-colors hover:bg-gray-100", "aria-label": "Edit redirect", children: _jsx(Pencil, { className: "h-4 w-4 text-gray-600" }) }), _jsx("button", { type: "button", onClick: () => handleDelete(redirect.id), className: "rounded p-1.5 transition-colors hover:bg-gray-100", "aria-label": "Delete redirect", children: _jsx(Trash2, { className: "h-4 w-4 text-red-600" }) })] }) })] }, redirect.id))) })] }) }) })), _jsx(Dialog.Root, { open: showAddDialog, onOpenChange: setShowAddDialog, children: _jsxs(Dialog.Portal, { children: [_jsx(Dialog.Overlay, { className: "fixed inset-0 z-50 bg-black/50" }), _jsxs(Dialog.Content, { className: "fixed
|
|
89
|
+
: 'bg-gray-100 text-gray-800'}`, children: redirect.active ? 'Active' : 'Inactive' }) }), _jsx("td", { className: "px-4 py-3", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { type: "button", onClick: () => onNavigate?.(`/redirects/${redirect.id}/edit`), className: "rounded p-1.5 transition-colors hover:bg-gray-100", "aria-label": "Edit redirect", children: _jsx(Pencil, { className: "h-4 w-4 text-gray-600" }) }), _jsx("button", { type: "button", onClick: () => handleDelete(redirect.id), className: "rounded p-1.5 transition-colors hover:bg-gray-100", "aria-label": "Delete redirect", children: _jsx(Trash2, { className: "h-4 w-4 text-red-600" }) })] }) })] }, redirect.id))) })] }) }) })), _jsx(Dialog.Root, { open: showAddDialog, onOpenChange: setShowAddDialog, children: _jsxs(Dialog.Portal, { children: [_jsx(Dialog.Overlay, { className: "fixed inset-0 z-50 bg-black/50" }), _jsxs(Dialog.Content, { className: "fixed top-1/2 left-1/2 z-50 w-full max-w-md -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-6 shadow-lg", children: [_jsx(Dialog.Title, { className: "mb-4 text-lg font-semibold text-gray-900", children: "Add Redirect" }), _jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [_jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "Source URL" }), _jsx("input", { type: "text", value: newRedirect.source, onChange: (e) => setNewRedirect({ ...newRedirect, source: e.target.value }), placeholder: "/old-page", className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", required: true })] }), _jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "Destination URL" }), _jsx("input", { type: "text", value: newRedirect.destination, onChange: (e) => setNewRedirect({ ...newRedirect, destination: e.target.value }), placeholder: "/new-page", className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", required: true })] }), _jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "Redirect Type" }), _jsxs("select", { value: newRedirect.type, onChange: (e) => setNewRedirect({ ...newRedirect, type: e.target.value }), className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", children: [_jsx("option", { value: "301", children: "301 (Permanent)" }), _jsx("option", { value: "302", children: "302 (Temporary)" })] })] }), _jsxs("div", { className: "flex items-center justify-end gap-3 pt-4", children: [_jsx(Dialog.Close, { asChild: true, children: _jsx("button", { type: "button", className: "rounded-lg border border-gray-300 px-4 py-2 text-sm transition-colors hover:bg-gray-50", children: "Cancel" }) }), _jsx("button", { type: "submit", className: "rounded-lg bg-blue-600 px-4 py-2 text-sm text-white transition-colors hover:bg-blue-700", children: "Add Redirect" })] })] })] })] }) })] }));
|
|
90
90
|
}
|
|
91
91
|
//# sourceMappingURL=Redirects.js.map
|
|
@@ -11,7 +11,7 @@ export function ResetPassword({ onNavigate, token }) {
|
|
|
11
11
|
const [success, setSuccess] = useState(false);
|
|
12
12
|
const [error, setError] = useState('');
|
|
13
13
|
if (!token) {
|
|
14
|
-
return (_jsx("div", { className: "min-h-screen
|
|
14
|
+
return (_jsx("div", { className: "flex min-h-screen items-center justify-center bg-gray-50 px-4", children: _jsxs("div", { className: "w-full max-w-md", children: [_jsxs("div", { className: "mb-8 text-center", children: [_jsx("div", { className: "mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-xl bg-red-100", children: _jsx(XCircle, { className: "h-7 w-7 text-red-600" }) }), _jsx("h1", { className: "text-2xl font-bold text-gray-900", children: "Invalid Reset Link" }), _jsx("p", { className: "mt-2 text-gray-600", children: "This password reset link is invalid or has expired." })] }), _jsxs("div", { className: "space-y-4 rounded-xl border border-gray-200 bg-white p-6 text-center shadow-sm", children: [_jsx("button", { type: "button", onClick: () => onNavigate('/forgot-password'), className: "w-full rounded-lg bg-blue-600 py-2.5 font-medium text-white transition-colors hover:bg-blue-700", children: "Request New Reset Link" }), _jsx("button", { type: "button", onClick: () => onNavigate('/login'), className: "w-full text-sm text-gray-600 transition-colors hover:text-gray-800", children: "Back to Sign In" })] })] }) }));
|
|
15
15
|
}
|
|
16
16
|
const passwordsMatch = password === confirmPassword;
|
|
17
17
|
const meetsLength = password.length >= 8;
|
|
@@ -41,6 +41,6 @@ export function ResetPassword({ onNavigate, token }) {
|
|
|
41
41
|
setSubmitting(false);
|
|
42
42
|
}
|
|
43
43
|
};
|
|
44
|
-
return (_jsx("div", { className: "min-h-screen
|
|
44
|
+
return (_jsx("div", { className: "flex min-h-screen items-center justify-center bg-gray-50 px-4", children: _jsxs("div", { className: "w-full max-w-md", children: [_jsxs("div", { className: "mb-8 text-center", children: [_jsx("div", { className: "mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-xl bg-blue-600", children: _jsx(Shield, { className: "h-7 w-7 text-white" }) }), _jsx("h1", { className: "text-2xl font-bold text-gray-900", children: success ? 'Password Reset' : 'Choose New Password' }), _jsx("p", { className: "mt-2 text-gray-600", children: success ? 'Your password has been updated' : 'Enter your new password below' })] }), _jsx("div", { className: "space-y-5 rounded-xl border border-gray-200 bg-white p-6 shadow-sm", children: success ? (_jsxs("div", { className: "space-y-4 text-center", children: [_jsx("div", { className: "mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100", children: _jsx(CheckCircle2, { className: "h-6 w-6 text-green-600" }) }), _jsx("p", { className: "text-sm text-gray-600", children: "Your password has been successfully reset. All existing sessions have been revoked for security." }), _jsx("button", { type: "button", onClick: () => onNavigate('/login'), className: "w-full rounded-lg bg-blue-600 py-2.5 font-medium text-white transition-colors hover:bg-blue-700", children: "Sign In with New Password" })] })) : (_jsxs("form", { onSubmit: handleSubmit, className: "space-y-5", children: [error && (_jsxs("div", { className: "flex items-start gap-3 rounded-lg border border-red-200 bg-red-50 p-3", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-5 w-5 shrink-0 text-red-600" }), _jsx("p", { className: "text-sm text-red-800", children: error })] })), _jsxs("div", { children: [_jsx("label", { htmlFor: "reset-password", className: "mb-1.5 block text-sm font-medium text-gray-700", children: "New Password" }), _jsxs("div", { className: "relative", children: [_jsx("input", { id: "reset-password", type: showPassword ? 'text' : 'password', value: password, onChange: (e) => setPassword(e.target.value), placeholder: "Enter new password", className: "w-full rounded-lg border border-gray-300 px-3 py-2.5 pr-10 text-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none", required: true, autoFocus: true, autoComplete: "new-password", minLength: 8 }), _jsx("button", { type: "button", onClick: () => setShowPassword(!showPassword), className: "absolute top-1/2 right-3 -translate-y-1/2 text-gray-400 hover:text-gray-600", tabIndex: -1, children: showPassword ? _jsx(EyeOff, { className: "h-4 w-4" }) : _jsx(Eye, { className: "h-4 w-4" }) })] }), password && !meetsLength && (_jsx("p", { className: "mt-1 text-xs text-red-600", children: "Password must be at least 8 characters" }))] }), _jsxs("div", { children: [_jsx("label", { htmlFor: "reset-confirm", className: "mb-1.5 block text-sm font-medium text-gray-700", children: "Confirm Password" }), _jsx("input", { id: "reset-confirm", type: showPassword ? 'text' : 'password', value: confirmPassword, onChange: (e) => setConfirmPassword(e.target.value), placeholder: "Confirm new password", className: "w-full rounded-lg border border-gray-300 px-3 py-2.5 text-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none", required: true, autoComplete: "new-password" }), confirmPassword && !passwordsMatch && (_jsx("p", { className: "mt-1 text-xs text-red-600", children: "Passwords do not match" }))] }), _jsx("button", { type: "submit", disabled: !canSubmit, className: "flex w-full items-center justify-center gap-2 rounded-lg bg-blue-600 py-2.5 font-medium text-white transition-colors hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-50", children: submitting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), "Resetting..."] })) : ('Reset Password') })] })) })] }) }));
|
|
45
45
|
}
|
|
46
46
|
//# sourceMappingURL=ResetPassword.js.map
|
package/dist/views/SEO.js
CHANGED
|
@@ -125,19 +125,19 @@ export function SEO({ onNavigate, initialTab = 'pages' }) {
|
|
|
125
125
|
}
|
|
126
126
|
function scoreIcon(score) {
|
|
127
127
|
if (score >= 80)
|
|
128
|
-
return _jsx(CheckCircle2, { className: "
|
|
128
|
+
return _jsx(CheckCircle2, { className: "h-4 w-4 text-green-600" });
|
|
129
129
|
if (score >= 50)
|
|
130
|
-
return _jsx(AlertTriangle, { className: "
|
|
131
|
-
return _jsx(XCircle, { className: "
|
|
130
|
+
return _jsx(AlertTriangle, { className: "h-4 w-4 text-yellow-600" });
|
|
131
|
+
return _jsx(XCircle, { className: "h-4 w-4 text-red-600" });
|
|
132
132
|
}
|
|
133
133
|
const tabClass = 'px-4 py-2 text-sm font-medium text-gray-600 transition-colors hover:text-gray-900 data-[state=active]:border-b-2 data-[state=active]:border-blue-600 data-[state=active]:text-blue-600 shrink-0';
|
|
134
134
|
const isLoading = seoLoading || redirectsLoading || linkHealthLoading;
|
|
135
135
|
if (isLoading) {
|
|
136
|
-
return (_jsx("div", { className: "p-3 pr-6 sm:p-4 sm:pr-8
|
|
136
|
+
return (_jsx("div", { className: "flex h-64 items-center justify-center p-3 pr-6 sm:p-4 sm:pr-8", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-blue-600" }) }));
|
|
137
137
|
}
|
|
138
|
-
return (_jsxs("div", { className: "p-3 pr-6 sm:p-4 sm:pr-8
|
|
138
|
+
return (_jsxs("div", { className: "flex h-full flex-col p-3 pr-6 sm:p-4 sm:pr-8", children: [(seoError || redirectsError) && (_jsxs("div", { className: "mb-4 flex items-center gap-3 rounded-lg border border-red-200 bg-red-50 p-3", children: [_jsx(AlertTriangle, { className: "h-5 w-5 shrink-0 text-red-600" }), _jsx("span", { className: "flex-1 text-sm text-red-800", children: seoError || redirectsError }), _jsx("button", { onClick: () => {
|
|
139
139
|
seoRefetch();
|
|
140
140
|
redirectsRefetch();
|
|
141
|
-
}, className: "px-3 py-1 text-sm text-red-700 border border-red-300 rounded-lg hover:bg-red-100 transition-colors", children: "Retry" })] })), _jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center justify-between mb-4 gap-3", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-xl sm:text-2xl font-semibold text-gray-900 mb-1", children: "SEO & Redirects" }), _jsx("p", { className: "text-sm text-gray-600", children: "Search optimization, redirects, canonicalization, and link health" })] }), _jsxs("button", { onClick: handleScan, disabled: scanning, className: "flex items-center justify-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors text-sm disabled:opacity-60", children: [_jsx(RefreshCw, { className: `w-4 h-4 ${scanning ? 'animate-spin' : ''}` }), scanning ? 'Scanning...' : 'Run SEO Scan'] })] }), _jsxs(Tabs.Root, { value: activeTab, onValueChange: handleTabChange, children: [_jsxs(Tabs.List, { className: "mb-4 flex gap-1 border-b border-gray-200 overflow-x-auto", children: [_jsx(Tabs.Trigger, { value: "pages", className: tabClass, children: _jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(BarChart3, { className: "w-4 h-4" }), "Pages"] }) }), _jsx(Tabs.Trigger, { value: "redirects", className: tabClass, children: _jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(ArrowRightLeft, { className: "w-4 h-4" }), "Redirects"] }) }), _jsx(Tabs.Trigger, { value: "canonicals", className: tabClass, children: _jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(Copy, { className: "w-4 h-4" }), "Canonicalization"] }) }), _jsx(Tabs.Trigger, { value: "links", className: tabClass, children: _jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(Link2, { className: "w-4 h-4" }), "Link Health"] }) })] }), _jsxs(Tabs.Content, { value: "pages", className: "flex flex-col flex-1 min-h-0", children: [_jsxs("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-3 mb-4", children: [_jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx(BarChart3, { className: "w-4 h-4 text-blue-600" }), _jsx("span", { className: "text-xs font-medium text-gray-600", children: "Avg SEO Score" })] }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: avgScore }), _jsx("div", { className: `text-xs mt-1 ${avgScore >= 80 ? 'text-green-600' : avgScore >= 50 ? 'text-yellow-600' : 'text-red-600'}`, children: avgScore >= 80 ? 'Good' : avgScore >= 50 ? 'Needs improvement' : 'Critical' })] }), _jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx(AlertTriangle, { className: "w-4 h-4 text-yellow-600" }), _jsx("span", { className: "text-xs font-medium text-gray-600", children: "Total Issues" })] }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: totalIssues }), _jsxs("div", { className: "text-xs text-gray-500 mt-1", children: ["Across ", seoPages.filter((p) => p.issues > 0).length, " pages"] })] }), _jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx(FileCode2, { className: "w-4 h-4 text-purple-600" }), _jsx("span", { className: "text-xs font-medium text-gray-600", children: "Missing Meta" })] }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: missingMeta }), _jsx("div", { className: "text-xs text-gray-500 mt-1", children: "Title or description" })] }), _jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx(Globe, { className: "w-4 h-4 text-green-600" }), _jsx("span", { className: "text-xs font-medium text-gray-600", children: "Missing Schema" })] }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: missingSchema }), _jsx("div", { className: "text-xs text-gray-500 mt-1", children: "No Schema.org markup" })] })] }), _jsx("div", { className: "bg-linear-to-r from-indigo-50 to-purple-50 border border-indigo-200 rounded-lg p-4 mb-4", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx(Bot, { className: "w-5 h-5 text-indigo-600 mt-0.5 shrink-0" }), _jsxs("div", { className: "flex-1", children: [_jsx("h3", { className: "text-sm font-semibold text-indigo-900 mb-1", children: "AI SEO Recommendations" }), _jsxs("p", { className: "text-sm text-indigo-700 mb-2", children: [missingMeta, " pages missing meta descriptions. ", missingCanonical.length, " pages without canonical URLs. AI can auto-generate these from page content."] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { onClick: () => onNavigate?.('/settings'), className: "px-3 py-1.5 text-xs bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition-colors", children: "Configure AI" }), _jsx("button", { className: "px-3 py-1.5 text-xs border border-indigo-300 text-indigo-700 rounded-lg hover:bg-indigo-50 transition-colors", children: "Auto-fix All" })] })] })] }) }), _jsx("div", { className: "bg-white rounded-lg border border-gray-200 mb-4", children: _jsxs("div", { className: "p-3 flex flex-col sm:flex-row gap-3", children: [_jsxs("div", { className: "relative flex-1", children: [_jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" }), _jsx("input", { type: "text", placeholder: "Search pages by URL or title...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "w-full pl-9 pr-3 py-2 text-sm border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" })] }), _jsxs("select", { value: filterScore, onChange: (e) => setFilterScore(e.target.value), className: "px-3 py-2 text-sm border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500", children: [_jsx("option", { value: "all", children: "All Scores" }), _jsx("option", { value: "good", children: "Good (80+)" }), _jsx("option", { value: "warning", children: "Needs Work (50-79)" }), _jsx("option", { value: "critical", children: "Critical (<50)" })] })] }) }), _jsx("div", { className: "bg-white rounded-lg border border-gray-200 flex-1 overflow-hidden", children: _jsx("div", { className: "overflow-x-auto h-full", children: _jsxs("table", { className: "w-full", children: [_jsx("thead", { className: "bg-gray-50 border-b border-gray-200 sticky top-0", children: _jsxs("tr", { children: [_jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Page" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Score" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Readability" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Schema" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Meta" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Issues" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Actions" })] }) }), _jsx("tbody", { className: "divide-y divide-gray-200", children: filtered.map((page) => (_jsxs("tr", { className: "hover:bg-gray-50 transition-colors", children: [_jsxs("td", { className: "px-4 py-3", children: [_jsx("div", { className: "text-sm font-medium text-gray-900", children: page.title }), _jsx("div", { className: "text-xs text-gray-500", children: page.url })] }), _jsx("td", { className: "px-4 py-3", children: _jsxs("div", { className: "flex items-center gap-2", children: [scoreIcon(page.score), _jsx("span", { className: `px-2 py-0.5 rounded-full text-xs font-medium ${scoreBadge(page.score)}`, children: page.score })] }) }), _jsx("td", { className: "px-4 py-3", children: page.readability > 0 ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(BookOpen, { className: "w-3.5 h-3.5 text-gray-400" }), _jsx("span", { className: `text-sm ${page.readability >= 80 ? 'text-green-700' : page.readability >= 60 ? 'text-yellow-700' : 'text-red-700'}`, children: page.readability })] })) : (_jsx("span", { className: "text-xs text-gray-400", children: "\u2014" })) }), _jsx("td", { className: "px-4 py-3", children: page.schemaType ? (_jsx("span", { className: "px-2 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-800", children: page.schemaType })) : (_jsx("span", { className: "px-2 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800", children: "Missing" })) }), _jsx("td", { className: "px-4 py-3", children: _jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: `text-xs ${page.metaTitle ? 'text-green-700' : 'text-red-600'}`, children: page.metaTitle ? '✓ Title' : '✗ Title' }), _jsx("span", { className: `text-xs ${page.metaDescription ? 'text-green-700' : 'text-red-600'}`, children: page.metaDescription ? '✓ Desc' : '✗ Desc' })] }) }), _jsx("td", { className: "px-4 py-3", children: page.issues > 0 ? (_jsx("span", { className: "px-2 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800", children: page.issues })) : (_jsx("span", { className: "px-2 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800", children: "\u2713" })) }), _jsx("td", { className: "px-4 py-3", children: _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { onClick: () => onNavigate?.(`/pages/${page.id}`), className: "p-1.5 hover:bg-gray-100 rounded transition-colors", title: "Edit", children: _jsx(ArrowUpRight, { className: "w-4 h-4 text-gray-600" }) }), _jsx("button", { className: "p-1.5 hover:bg-gray-100 rounded transition-colors", title: "AI analyze", children: _jsx(Bot, { className: "w-4 h-4 text-indigo-600" }) })] }) })] }, page.id))) })] }) }) })] }), _jsxs(Tabs.Content, { value: "redirects", className: "flex flex-col flex-1 min-h-0", children: [_jsxs("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-3 mb-4", children: [_jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsx("div", { className: "text-xs text-gray-600 mb-1", children: "Total Redirects" }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: redirects.length })] }), _jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsx("div", { className: "text-xs text-gray-600 mb-1", children: "Active" }), _jsx("div", { className: "text-2xl font-semibold text-green-600", children: redirects.filter((r) => r.active).length })] }), _jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsx("div", { className: "text-xs text-gray-600 mb-1", children: "Total Hits" }), _jsx("div", { className: "text-2xl font-semibold text-blue-600", children: redirects.reduce((s, r) => s + r.hits, 0).toLocaleString() })] }), _jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsx("div", { className: "text-xs text-gray-600 mb-1", children: "301 Permanent" }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: redirects.filter((r) => r.type === '301').length })] })] }), _jsxs("div", { className: "flex items-center gap-3 mb-4", children: [_jsxs("div", { className: "relative flex-1 max-w-md", children: [_jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" }), _jsx("input", { type: "text", placeholder: "Search redirects...", value: redirectSearch, onChange: (e) => setRedirectSearch(e.target.value), className: "w-full pl-9 pr-3 py-2 text-sm border border-gray-300 rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-blue-500" })] }), _jsxs("button", { onClick: () => setShowAddRedirect(true), className: "flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors text-sm shrink-0", children: [_jsx(Plus, { className: "w-4 h-4" }), "Add Redirect"] })] }), _jsx("div", { className: "bg-white rounded-lg border border-gray-200 flex-1 overflow-hidden", children: _jsx("div", { className: "overflow-x-auto h-full", children: _jsxs("table", { className: "w-full", children: [_jsx("thead", { className: "bg-gray-50 border-b border-gray-200 sticky top-0", children: _jsxs("tr", { children: [_jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Source" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Destination" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Type" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Hits" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Status" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Actions" })] }) }), _jsx("tbody", { className: "divide-y divide-gray-200", children: filteredRedirects.map((r) => (_jsxs("tr", { className: "hover:bg-gray-50 transition-colors", children: [_jsx("td", { className: "px-4 py-3", children: _jsx("code", { className: "rounded bg-gray-100 px-2 py-1 text-xs text-gray-900", children: r.from }) }), _jsx("td", { className: "px-4 py-3", children: _jsx("code", { className: "rounded bg-gray-100 px-2 py-1 text-xs text-gray-900", children: r.to }) }), _jsx("td", { className: "px-4 py-3", children: _jsx("span", { className: `px-2 py-0.5 rounded-full text-xs font-medium ${r.type === '301' ? 'bg-blue-100 text-blue-800' : 'bg-purple-100 text-purple-800'}`, children: r.type }) }), _jsx("td", { className: "px-4 py-3 text-sm text-gray-600", children: r.hits.toLocaleString() }), _jsx("td", { className: "px-4 py-3", children: _jsx("span", { className: `px-2 py-0.5 rounded-full text-xs font-medium ${r.active ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800'}`, children: r.active ? 'Active' : 'Inactive' }) }), _jsx("td", { className: "px-4 py-3", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { className: "p-1.5 hover:bg-gray-100 rounded transition-colors", children: _jsx(Pencil, { className: "w-4 h-4 text-gray-600" }) }), _jsx("button", { onClick: () => handleDeleteRedirect(r.id), className: "p-1.5 hover:bg-gray-100 rounded transition-colors", children: _jsx(Trash2, { className: "w-4 h-4 text-red-600" }) })] }) })] }, r.id))) })] }) }) }), _jsx(Dialog.Root, { open: showAddRedirect, onOpenChange: setShowAddRedirect, children: _jsxs(Dialog.Portal, { children: [_jsx(Dialog.Overlay, { className: "fixed inset-0 z-50 bg-black/50" }), _jsxs(Dialog.Content, { className: "fixed left-1/2 top-1/2 z-50 w-full max-w-md -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-6 shadow-lg", children: [_jsx(Dialog.Title, { className: "mb-4 text-lg font-semibold text-gray-900", children: "Add Redirect" }), _jsxs("form", { onSubmit: handleAddRedirect, className: "space-y-4", children: [_jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "Source URL" }), _jsx("input", { type: "text", value: newRedirect.source, onChange: (e) => setNewRedirect({ ...newRedirect, source: e.target.value }), placeholder: "/old-page", className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500", required: true })] }), _jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "Destination URL" }), _jsx("input", { type: "text", value: newRedirect.destination, onChange: (e) => setNewRedirect({ ...newRedirect, destination: e.target.value }), placeholder: "/new-page", className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500", required: true })] }), _jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "Type" }), _jsxs("select", { value: newRedirect.type, onChange: (e) => setNewRedirect({ ...newRedirect, type: e.target.value }), className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500", children: [_jsx("option", { value: "301", children: "301 (Permanent)" }), _jsx("option", { value: "302", children: "302 (Temporary)" })] })] }), _jsxs("div", { className: "flex justify-end gap-3 pt-4", children: [_jsx(Dialog.Close, { asChild: true, children: _jsx("button", { type: "button", className: "rounded-lg border border-gray-300 px-4 py-2 text-sm hover:bg-gray-50", children: "Cancel" }) }), _jsx("button", { type: "submit", className: "rounded-lg bg-blue-600 px-4 py-2 text-sm text-white hover:bg-blue-700", children: "Add Redirect" })] })] })] })] }) })] }), _jsxs(Tabs.Content, { value: "canonicals", className: "flex flex-col flex-1 min-h-0 space-y-4", children: [_jsxs("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-3", children: [_jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx(ShieldCheck, { className: "w-4 h-4 text-green-600" }), _jsx("span", { className: "text-xs font-medium text-gray-600", children: "With Canonical" })] }), _jsx("div", { className: "text-2xl font-semibold text-green-700", children: allCanonicals.length })] }), _jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx(AlertTriangle, { className: "w-4 h-4 text-red-600" }), _jsx("span", { className: "text-xs font-medium text-gray-600", children: "Missing Canonical" })] }), _jsx("div", { className: "text-2xl font-semibold text-red-700", children: missingCanonical.length })] }), _jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx(Globe, { className: "w-4 h-4 text-blue-600" }), _jsx("span", { className: "text-xs font-medium text-gray-600", children: "Canonical Domains" })] }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: canonicalDomains.length })] }), _jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx(CheckCircle2, { className: "w-4 h-4 text-green-600" }), _jsx("span", { className: "text-xs font-medium text-gray-600", children: "Self-Referencing" })] }), _jsx("div", { className: "text-2xl font-semibold text-green-700", children: allCanonicals.length }), _jsx("div", { className: "text-xs text-gray-500 mt-1", children: "Correct pattern" })] })] }), missingCanonical.length > 0 && (_jsx("div", { className: "bg-yellow-50 border border-yellow-200 rounded-lg p-4", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx(AlertTriangle, { className: "w-5 h-5 text-yellow-600 mt-0.5 shrink-0" }), _jsxs("div", { className: "flex-1", children: [_jsxs("h3", { className: "text-sm font-semibold text-yellow-900 mb-1", children: [missingCanonical.length, " page", missingCanonical.length !== 1 ? 's' : '', " missing canonical URLs"] }), _jsx("p", { className: "text-sm text-yellow-700 mb-2", children: "Without canonical tags, search engines may index duplicate versions of these pages, diluting your ranking signals." }), _jsx("div", { className: "flex flex-wrap gap-2", children: missingCanonical.map((p) => (_jsxs("button", { onClick: () => onNavigate?.(`/pages/${p.id}`), className: "px-2.5 py-1 text-xs bg-yellow-100 text-yellow-900 rounded-lg hover:bg-yellow-200 transition-colors", children: [p.title, " (", p.url, ")"] }, p.id))) })] })] }) })), _jsx("div", { className: "bg-white rounded-lg border border-gray-200 flex-1 overflow-hidden", children: _jsx("div", { className: "overflow-x-auto h-full", children: _jsxs("table", { className: "w-full", children: [_jsx("thead", { className: "bg-gray-50 border-b border-gray-200 sticky top-0", children: _jsxs("tr", { children: [_jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Page" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "URL" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Canonical URL" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Status" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Actions" })] }) }), _jsx("tbody", { className: "divide-y divide-gray-200", children: seoPages.map((page) => (_jsxs("tr", { className: "hover:bg-gray-50 transition-colors", children: [_jsx("td", { className: "px-4 py-3 text-sm font-medium text-gray-900", children: page.title }), _jsx("td", { className: "px-4 py-3", children: _jsx("code", { className: "text-xs bg-gray-100 px-2 py-1 rounded text-gray-700", children: page.url }) }), _jsx("td", { className: "px-4 py-3", children: page.canonical ? (_jsx("code", { className: "text-xs bg-gray-100 px-2 py-1 rounded text-gray-700 truncate max-w-[200px] block", children: page.canonical })) : (_jsx("span", { className: "text-xs text-red-600 font-medium", children: "Not set" })) }), _jsx("td", { className: "px-4 py-3", children: page.canonical ? (_jsx("span", { className: "px-2 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800", children: "\u2713 Set" })) : (_jsx("span", { className: "px-2 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800", children: "Missing" })) }), _jsx("td", { className: "px-4 py-3", children: _jsx("button", { onClick: () => onNavigate?.(`/pages/${page.id}`), className: "p-1.5 hover:bg-gray-100 rounded transition-colors", title: "Edit", children: _jsx(Pencil, { className: "w-4 h-4 text-gray-600" }) }) })] }, page.id))) })] }) }) })] }), _jsxs(Tabs.Content, { value: "links", className: "flex flex-col flex-1 min-h-0 space-y-4", children: [_jsxs("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-3", children: [_jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsx("div", { className: "text-xs text-gray-600 mb-1", children: "Broken Links" }), _jsx("div", { className: "text-2xl font-semibold text-red-600", children: linkHealth.filter((l) => l.status === 404).length })] }), _jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsx("div", { className: "text-xs text-gray-600 mb-1", children: "Redirect Chains" }), _jsx("div", { className: "text-2xl font-semibold text-yellow-600", children: linkHealth.filter((l) => l.status === 301).length })] }), _jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsx("div", { className: "text-xs text-gray-600 mb-1", children: "Internal Issues" }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: linkHealth.filter((l) => l.type === 'internal').length })] }), _jsxs("div", { className: "bg-white rounded-lg border border-gray-200 p-4", children: [_jsx("div", { className: "text-xs text-gray-600 mb-1", children: "External Issues" }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: linkHealth.filter((l) => l.type === 'external').length })] })] }), _jsx("div", { className: "bg-white rounded-lg border border-gray-200 flex-1 overflow-hidden", children: _jsx("div", { className: "overflow-x-auto h-full", children: _jsxs("table", { className: "w-full", children: [_jsx("thead", { className: "bg-gray-50 border-b border-gray-200 sticky top-0", children: _jsxs("tr", { children: [_jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Found On" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Broken URL" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Status" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Type" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Last Checked" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Actions" })] }) }), _jsx("tbody", { className: "divide-y divide-gray-200", children: linkHealth.map((link) => (_jsxs("tr", { className: "hover:bg-gray-50 transition-colors", children: [_jsx("td", { className: "px-4 py-3", children: _jsx("code", { className: "text-xs bg-gray-100 px-2 py-1 rounded text-gray-700", children: link.page }) }), _jsx("td", { className: "px-4 py-3", children: _jsx("code", { className: "text-xs bg-red-50 px-2 py-1 rounded text-red-800 truncate max-w-[200px] block", children: link.url }) }), _jsx("td", { className: "px-4 py-3", children: _jsx("span", { className: `px-2 py-0.5 rounded-full text-xs font-medium ${link.status === 404 ? 'bg-red-100 text-red-800' : 'bg-yellow-100 text-yellow-800'}`, children: link.status }) }), _jsx("td", { className: "px-4 py-3", children: _jsx("span", { className: `px-2 py-0.5 rounded-full text-xs font-medium ${link.type === 'internal' ? 'bg-blue-100 text-blue-800' : 'bg-gray-100 text-gray-800'}`, children: link.type }) }), _jsx("td", { className: "px-4 py-3 text-sm text-gray-600", children: link.lastChecked }), _jsx("td", { className: "px-4 py-3", children: _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { className: "p-1.5 hover:bg-gray-100 rounded transition-colors", title: "Create redirect", children: _jsx(ArrowRightLeft, { className: "w-4 h-4 text-gray-600" }) }), _jsx("button", { className: "p-1.5 hover:bg-gray-100 rounded transition-colors", title: "Open URL", children: _jsx(ExternalLink, { className: "w-4 h-4 text-gray-600" }) })] }) })] }, link.id))) })] }) }) })] })] })] }));
|
|
141
|
+
}, className: "rounded-lg border border-red-300 px-3 py-1 text-sm text-red-700 transition-colors hover:bg-red-100", children: "Retry" })] })), _jsxs("div", { className: "mb-4 flex flex-col justify-between gap-3 sm:flex-row sm:items-center", children: [_jsxs("div", { children: [_jsx("h1", { className: "mb-1 text-xl font-semibold text-gray-900 sm:text-2xl", children: "SEO & Redirects" }), _jsx("p", { className: "text-sm text-gray-600", children: "Search optimization, redirects, canonicalization, and link health" })] }), _jsxs("button", { onClick: handleScan, disabled: scanning, className: "flex items-center justify-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm text-white transition-colors hover:bg-blue-700 disabled:opacity-60", children: [_jsx(RefreshCw, { className: `h-4 w-4 ${scanning ? 'animate-spin' : ''}` }), scanning ? 'Scanning...' : 'Run SEO Scan'] })] }), _jsxs(Tabs.Root, { value: activeTab, onValueChange: handleTabChange, children: [_jsxs(Tabs.List, { className: "mb-4 flex gap-1 overflow-x-auto border-b border-gray-200", children: [_jsx(Tabs.Trigger, { value: "pages", className: tabClass, children: _jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(BarChart3, { className: "h-4 w-4" }), "Pages"] }) }), _jsx(Tabs.Trigger, { value: "redirects", className: tabClass, children: _jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(ArrowRightLeft, { className: "h-4 w-4" }), "Redirects"] }) }), _jsx(Tabs.Trigger, { value: "canonicals", className: tabClass, children: _jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(Copy, { className: "h-4 w-4" }), "Canonicalization"] }) }), _jsx(Tabs.Trigger, { value: "links", className: tabClass, children: _jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(Link2, { className: "h-4 w-4" }), "Link Health"] }) })] }), _jsxs(Tabs.Content, { value: "pages", className: "flex min-h-0 flex-1 flex-col", children: [_jsxs("div", { className: "mb-4 grid grid-cols-2 gap-3 lg:grid-cols-4", children: [_jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx(BarChart3, { className: "h-4 w-4 text-blue-600" }), _jsx("span", { className: "text-xs font-medium text-gray-600", children: "Avg SEO Score" })] }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: avgScore }), _jsx("div", { className: `mt-1 text-xs ${avgScore >= 80 ? 'text-green-600' : avgScore >= 50 ? 'text-yellow-600' : 'text-red-600'}`, children: avgScore >= 80 ? 'Good' : avgScore >= 50 ? 'Needs improvement' : 'Critical' })] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx(AlertTriangle, { className: "h-4 w-4 text-yellow-600" }), _jsx("span", { className: "text-xs font-medium text-gray-600", children: "Total Issues" })] }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: totalIssues }), _jsxs("div", { className: "mt-1 text-xs text-gray-500", children: ["Across ", seoPages.filter((p) => p.issues > 0).length, " pages"] })] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx(FileCode2, { className: "h-4 w-4 text-purple-600" }), _jsx("span", { className: "text-xs font-medium text-gray-600", children: "Missing Meta" })] }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: missingMeta }), _jsx("div", { className: "mt-1 text-xs text-gray-500", children: "Title or description" })] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx(Globe, { className: "h-4 w-4 text-green-600" }), _jsx("span", { className: "text-xs font-medium text-gray-600", children: "Missing Schema" })] }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: missingSchema }), _jsx("div", { className: "mt-1 text-xs text-gray-500", children: "No Schema.org markup" })] })] }), _jsx("div", { className: "mb-4 rounded-lg border border-indigo-200 bg-linear-to-r from-indigo-50 to-purple-50 p-4", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx(Bot, { className: "mt-0.5 h-5 w-5 shrink-0 text-indigo-600" }), _jsxs("div", { className: "flex-1", children: [_jsx("h3", { className: "mb-1 text-sm font-semibold text-indigo-900", children: "AI SEO Recommendations" }), _jsxs("p", { className: "mb-2 text-sm text-indigo-700", children: [missingMeta, " pages missing meta descriptions. ", missingCanonical.length, " pages without canonical URLs. AI can auto-generate these from page content."] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { onClick: () => onNavigate?.('/settings'), className: "rounded-lg bg-indigo-600 px-3 py-1.5 text-xs text-white transition-colors hover:bg-indigo-700", children: "Configure AI" }), _jsx("button", { className: "rounded-lg border border-indigo-300 px-3 py-1.5 text-xs text-indigo-700 transition-colors hover:bg-indigo-50", children: "Auto-fix All" })] })] })] }) }), _jsx("div", { className: "mb-4 rounded-lg border border-gray-200 bg-white", children: _jsxs("div", { className: "flex flex-col gap-3 p-3 sm:flex-row", children: [_jsxs("div", { className: "relative flex-1", children: [_jsx(Search, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-gray-400" }), _jsx("input", { type: "text", placeholder: "Search pages by URL or title...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "w-full rounded-lg border border-gray-300 py-2 pr-3 pl-9 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" })] }), _jsxs("select", { value: filterScore, onChange: (e) => setFilterScore(e.target.value), className: "rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", children: [_jsx("option", { value: "all", children: "All Scores" }), _jsx("option", { value: "good", children: "Good (80+)" }), _jsx("option", { value: "warning", children: "Needs Work (50-79)" }), _jsx("option", { value: "critical", children: "Critical (<50)" })] })] }) }), _jsx("div", { className: "flex-1 overflow-hidden rounded-lg border border-gray-200 bg-white", children: _jsx("div", { className: "h-full overflow-x-auto", children: _jsxs("table", { className: "w-full", children: [_jsx("thead", { className: "sticky top-0 border-b border-gray-200 bg-gray-50", children: _jsxs("tr", { children: [_jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Page" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Score" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Readability" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Schema" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Meta" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Issues" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Actions" })] }) }), _jsx("tbody", { className: "divide-y divide-gray-200", children: filtered.map((page) => (_jsxs("tr", { className: "transition-colors hover:bg-gray-50", children: [_jsxs("td", { className: "px-4 py-3", children: [_jsx("div", { className: "text-sm font-medium text-gray-900", children: page.title }), _jsx("div", { className: "text-xs text-gray-500", children: page.url })] }), _jsx("td", { className: "px-4 py-3", children: _jsxs("div", { className: "flex items-center gap-2", children: [scoreIcon(page.score), _jsx("span", { className: `rounded-full px-2 py-0.5 text-xs font-medium ${scoreBadge(page.score)}`, children: page.score })] }) }), _jsx("td", { className: "px-4 py-3", children: page.readability > 0 ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(BookOpen, { className: "h-3.5 w-3.5 text-gray-400" }), _jsx("span", { className: `text-sm ${page.readability >= 80 ? 'text-green-700' : page.readability >= 60 ? 'text-yellow-700' : 'text-red-700'}`, children: page.readability })] })) : (_jsx("span", { className: "text-xs text-gray-400", children: "\u2014" })) }), _jsx("td", { className: "px-4 py-3", children: page.schemaType ? (_jsx("span", { className: "rounded-full bg-purple-100 px-2 py-0.5 text-xs font-medium text-purple-800", children: page.schemaType })) : (_jsx("span", { className: "rounded-full bg-red-100 px-2 py-0.5 text-xs font-medium text-red-800", children: "Missing" })) }), _jsx("td", { className: "px-4 py-3", children: _jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: `text-xs ${page.metaTitle ? 'text-green-700' : 'text-red-600'}`, children: page.metaTitle ? '✓ Title' : '✗ Title' }), _jsx("span", { className: `text-xs ${page.metaDescription ? 'text-green-700' : 'text-red-600'}`, children: page.metaDescription ? '✓ Desc' : '✗ Desc' })] }) }), _jsx("td", { className: "px-4 py-3", children: page.issues > 0 ? (_jsx("span", { className: "rounded-full bg-yellow-100 px-2 py-0.5 text-xs font-medium text-yellow-800", children: page.issues })) : (_jsx("span", { className: "rounded-full bg-green-100 px-2 py-0.5 text-xs font-medium text-green-800", children: "\u2713" })) }), _jsx("td", { className: "px-4 py-3", children: _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { onClick: () => onNavigate?.(`/pages/${page.id}`), className: "rounded p-1.5 transition-colors hover:bg-gray-100", title: "Edit", children: _jsx(ArrowUpRight, { className: "h-4 w-4 text-gray-600" }) }), _jsx("button", { className: "rounded p-1.5 transition-colors hover:bg-gray-100", title: "AI analyze", children: _jsx(Bot, { className: "h-4 w-4 text-indigo-600" }) })] }) })] }, page.id))) })] }) }) })] }), _jsxs(Tabs.Content, { value: "redirects", className: "flex min-h-0 flex-1 flex-col", children: [_jsxs("div", { className: "mb-4 grid grid-cols-2 gap-3 lg:grid-cols-4", children: [_jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsx("div", { className: "mb-1 text-xs text-gray-600", children: "Total Redirects" }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: redirects.length })] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsx("div", { className: "mb-1 text-xs text-gray-600", children: "Active" }), _jsx("div", { className: "text-2xl font-semibold text-green-600", children: redirects.filter((r) => r.active).length })] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsx("div", { className: "mb-1 text-xs text-gray-600", children: "Total Hits" }), _jsx("div", { className: "text-2xl font-semibold text-blue-600", children: redirects.reduce((s, r) => s + r.hits, 0).toLocaleString() })] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsx("div", { className: "mb-1 text-xs text-gray-600", children: "301 Permanent" }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: redirects.filter((r) => r.type === '301').length })] })] }), _jsxs("div", { className: "mb-4 flex items-center gap-3", children: [_jsxs("div", { className: "relative max-w-md flex-1", children: [_jsx(Search, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-gray-400" }), _jsx("input", { type: "text", placeholder: "Search redirects...", value: redirectSearch, onChange: (e) => setRedirectSearch(e.target.value), className: "w-full rounded-lg border border-gray-300 bg-white py-2 pr-3 pl-9 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" })] }), _jsxs("button", { onClick: () => setShowAddRedirect(true), className: "flex shrink-0 items-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm text-white transition-colors hover:bg-blue-700", children: [_jsx(Plus, { className: "h-4 w-4" }), "Add Redirect"] })] }), _jsx("div", { className: "flex-1 overflow-hidden rounded-lg border border-gray-200 bg-white", children: _jsx("div", { className: "h-full overflow-x-auto", children: _jsxs("table", { className: "w-full", children: [_jsx("thead", { className: "sticky top-0 border-b border-gray-200 bg-gray-50", children: _jsxs("tr", { children: [_jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Source" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Destination" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Type" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Hits" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Status" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Actions" })] }) }), _jsx("tbody", { className: "divide-y divide-gray-200", children: filteredRedirects.map((r) => (_jsxs("tr", { className: "transition-colors hover:bg-gray-50", children: [_jsx("td", { className: "px-4 py-3", children: _jsx("code", { className: "rounded bg-gray-100 px-2 py-1 text-xs text-gray-900", children: r.from }) }), _jsx("td", { className: "px-4 py-3", children: _jsx("code", { className: "rounded bg-gray-100 px-2 py-1 text-xs text-gray-900", children: r.to }) }), _jsx("td", { className: "px-4 py-3", children: _jsx("span", { className: `rounded-full px-2 py-0.5 text-xs font-medium ${r.type === '301' ? 'bg-blue-100 text-blue-800' : 'bg-purple-100 text-purple-800'}`, children: r.type }) }), _jsx("td", { className: "px-4 py-3 text-sm text-gray-600", children: r.hits.toLocaleString() }), _jsx("td", { className: "px-4 py-3", children: _jsx("span", { className: `rounded-full px-2 py-0.5 text-xs font-medium ${r.active ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800'}`, children: r.active ? 'Active' : 'Inactive' }) }), _jsx("td", { className: "px-4 py-3", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { className: "rounded p-1.5 transition-colors hover:bg-gray-100", children: _jsx(Pencil, { className: "h-4 w-4 text-gray-600" }) }), _jsx("button", { onClick: () => handleDeleteRedirect(r.id), className: "rounded p-1.5 transition-colors hover:bg-gray-100", children: _jsx(Trash2, { className: "h-4 w-4 text-red-600" }) })] }) })] }, r.id))) })] }) }) }), _jsx(Dialog.Root, { open: showAddRedirect, onOpenChange: setShowAddRedirect, children: _jsxs(Dialog.Portal, { children: [_jsx(Dialog.Overlay, { className: "fixed inset-0 z-50 bg-black/50" }), _jsxs(Dialog.Content, { className: "fixed top-1/2 left-1/2 z-50 w-full max-w-md -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-6 shadow-lg", children: [_jsx(Dialog.Title, { className: "mb-4 text-lg font-semibold text-gray-900", children: "Add Redirect" }), _jsxs("form", { onSubmit: handleAddRedirect, className: "space-y-4", children: [_jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "Source URL" }), _jsx("input", { type: "text", value: newRedirect.source, onChange: (e) => setNewRedirect({ ...newRedirect, source: e.target.value }), placeholder: "/old-page", className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", required: true })] }), _jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "Destination URL" }), _jsx("input", { type: "text", value: newRedirect.destination, onChange: (e) => setNewRedirect({ ...newRedirect, destination: e.target.value }), placeholder: "/new-page", className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", required: true })] }), _jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "Type" }), _jsxs("select", { value: newRedirect.type, onChange: (e) => setNewRedirect({ ...newRedirect, type: e.target.value }), className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", children: [_jsx("option", { value: "301", children: "301 (Permanent)" }), _jsx("option", { value: "302", children: "302 (Temporary)" })] })] }), _jsxs("div", { className: "flex justify-end gap-3 pt-4", children: [_jsx(Dialog.Close, { asChild: true, children: _jsx("button", { type: "button", className: "rounded-lg border border-gray-300 px-4 py-2 text-sm hover:bg-gray-50", children: "Cancel" }) }), _jsx("button", { type: "submit", className: "rounded-lg bg-blue-600 px-4 py-2 text-sm text-white hover:bg-blue-700", children: "Add Redirect" })] })] })] })] }) })] }), _jsxs(Tabs.Content, { value: "canonicals", className: "flex min-h-0 flex-1 flex-col space-y-4", children: [_jsxs("div", { className: "grid grid-cols-2 gap-3 lg:grid-cols-4", children: [_jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx(ShieldCheck, { className: "h-4 w-4 text-green-600" }), _jsx("span", { className: "text-xs font-medium text-gray-600", children: "With Canonical" })] }), _jsx("div", { className: "text-2xl font-semibold text-green-700", children: allCanonicals.length })] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx(AlertTriangle, { className: "h-4 w-4 text-red-600" }), _jsx("span", { className: "text-xs font-medium text-gray-600", children: "Missing Canonical" })] }), _jsx("div", { className: "text-2xl font-semibold text-red-700", children: missingCanonical.length })] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx(Globe, { className: "h-4 w-4 text-blue-600" }), _jsx("span", { className: "text-xs font-medium text-gray-600", children: "Canonical Domains" })] }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: canonicalDomains.length })] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 text-green-600" }), _jsx("span", { className: "text-xs font-medium text-gray-600", children: "Self-Referencing" })] }), _jsx("div", { className: "text-2xl font-semibold text-green-700", children: allCanonicals.length }), _jsx("div", { className: "mt-1 text-xs text-gray-500", children: "Correct pattern" })] })] }), missingCanonical.length > 0 && (_jsx("div", { className: "rounded-lg border border-yellow-200 bg-yellow-50 p-4", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-5 w-5 shrink-0 text-yellow-600" }), _jsxs("div", { className: "flex-1", children: [_jsxs("h3", { className: "mb-1 text-sm font-semibold text-yellow-900", children: [missingCanonical.length, " page", missingCanonical.length !== 1 ? 's' : '', " missing canonical URLs"] }), _jsx("p", { className: "mb-2 text-sm text-yellow-700", children: "Without canonical tags, search engines may index duplicate versions of these pages, diluting your ranking signals." }), _jsx("div", { className: "flex flex-wrap gap-2", children: missingCanonical.map((p) => (_jsxs("button", { onClick: () => onNavigate?.(`/pages/${p.id}`), className: "rounded-lg bg-yellow-100 px-2.5 py-1 text-xs text-yellow-900 transition-colors hover:bg-yellow-200", children: [p.title, " (", p.url, ")"] }, p.id))) })] })] }) })), _jsx("div", { className: "flex-1 overflow-hidden rounded-lg border border-gray-200 bg-white", children: _jsx("div", { className: "h-full overflow-x-auto", children: _jsxs("table", { className: "w-full", children: [_jsx("thead", { className: "sticky top-0 border-b border-gray-200 bg-gray-50", children: _jsxs("tr", { children: [_jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Page" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "URL" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Canonical URL" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Status" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Actions" })] }) }), _jsx("tbody", { className: "divide-y divide-gray-200", children: seoPages.map((page) => (_jsxs("tr", { className: "transition-colors hover:bg-gray-50", children: [_jsx("td", { className: "px-4 py-3 text-sm font-medium text-gray-900", children: page.title }), _jsx("td", { className: "px-4 py-3", children: _jsx("code", { className: "rounded bg-gray-100 px-2 py-1 text-xs text-gray-700", children: page.url }) }), _jsx("td", { className: "px-4 py-3", children: page.canonical ? (_jsx("code", { className: "block max-w-[200px] truncate rounded bg-gray-100 px-2 py-1 text-xs text-gray-700", children: page.canonical })) : (_jsx("span", { className: "text-xs font-medium text-red-600", children: "Not set" })) }), _jsx("td", { className: "px-4 py-3", children: page.canonical ? (_jsx("span", { className: "rounded-full bg-green-100 px-2 py-0.5 text-xs font-medium text-green-800", children: "\u2713 Set" })) : (_jsx("span", { className: "rounded-full bg-red-100 px-2 py-0.5 text-xs font-medium text-red-800", children: "Missing" })) }), _jsx("td", { className: "px-4 py-3", children: _jsx("button", { onClick: () => onNavigate?.(`/pages/${page.id}`), className: "rounded p-1.5 transition-colors hover:bg-gray-100", title: "Edit", children: _jsx(Pencil, { className: "h-4 w-4 text-gray-600" }) }) })] }, page.id))) })] }) }) })] }), _jsxs(Tabs.Content, { value: "links", className: "flex min-h-0 flex-1 flex-col space-y-4", children: [_jsxs("div", { className: "grid grid-cols-2 gap-3 lg:grid-cols-4", children: [_jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsx("div", { className: "mb-1 text-xs text-gray-600", children: "Broken Links" }), _jsx("div", { className: "text-2xl font-semibold text-red-600", children: linkHealth.filter((l) => l.status === 404).length })] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsx("div", { className: "mb-1 text-xs text-gray-600", children: "Redirect Chains" }), _jsx("div", { className: "text-2xl font-semibold text-yellow-600", children: linkHealth.filter((l) => l.status === 301).length })] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsx("div", { className: "mb-1 text-xs text-gray-600", children: "Internal Issues" }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: linkHealth.filter((l) => l.type === 'internal').length })] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsx("div", { className: "mb-1 text-xs text-gray-600", children: "External Issues" }), _jsx("div", { className: "text-2xl font-semibold text-gray-900", children: linkHealth.filter((l) => l.type === 'external').length })] })] }), _jsx("div", { className: "flex-1 overflow-hidden rounded-lg border border-gray-200 bg-white", children: _jsx("div", { className: "h-full overflow-x-auto", children: _jsxs("table", { className: "w-full", children: [_jsx("thead", { className: "sticky top-0 border-b border-gray-200 bg-gray-50", children: _jsxs("tr", { children: [_jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Found On" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Broken URL" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Status" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Type" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Last Checked" }), _jsx("th", { className: "px-4 py-2 text-left text-xs font-medium text-gray-700", children: "Actions" })] }) }), _jsx("tbody", { className: "divide-y divide-gray-200", children: linkHealth.map((link) => (_jsxs("tr", { className: "transition-colors hover:bg-gray-50", children: [_jsx("td", { className: "px-4 py-3", children: _jsx("code", { className: "rounded bg-gray-100 px-2 py-1 text-xs text-gray-700", children: link.page }) }), _jsx("td", { className: "px-4 py-3", children: _jsx("code", { className: "block max-w-[200px] truncate rounded bg-red-50 px-2 py-1 text-xs text-red-800", children: link.url }) }), _jsx("td", { className: "px-4 py-3", children: _jsx("span", { className: `rounded-full px-2 py-0.5 text-xs font-medium ${link.status === 404 ? 'bg-red-100 text-red-800' : 'bg-yellow-100 text-yellow-800'}`, children: link.status }) }), _jsx("td", { className: "px-4 py-3", children: _jsx("span", { className: `rounded-full px-2 py-0.5 text-xs font-medium ${link.type === 'internal' ? 'bg-blue-100 text-blue-800' : 'bg-gray-100 text-gray-800'}`, children: link.type }) }), _jsx("td", { className: "px-4 py-3 text-sm text-gray-600", children: link.lastChecked }), _jsx("td", { className: "px-4 py-3", children: _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { className: "rounded p-1.5 transition-colors hover:bg-gray-100", title: "Create redirect", children: _jsx(ArrowRightLeft, { className: "h-4 w-4 text-gray-600" }) }), _jsx("button", { className: "rounded p-1.5 transition-colors hover:bg-gray-100", title: "Open URL", children: _jsx(ExternalLink, { className: "h-4 w-4 text-gray-600" }) })] }) })] }, link.id))) })] }) }) })] })] })] }));
|
|
142
142
|
}
|
|
143
143
|
//# sourceMappingURL=SEO.js.map
|
|
@@ -97,14 +97,14 @@ export function ScriptTagEditor({ tagId, onNavigate }) {
|
|
|
97
97
|
}
|
|
98
98
|
};
|
|
99
99
|
if (loading && !isNew) {
|
|
100
|
-
return (_jsx("div", { className: "p-3 pr-6 sm:p-4 sm:pr-8
|
|
100
|
+
return (_jsx("div", { className: "flex h-64 items-center justify-center p-3 pr-6 sm:p-4 sm:pr-8", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-blue-600" }) }));
|
|
101
101
|
}
|
|
102
|
-
return (_jsxs("div", { className: "p-3 pr-6 sm:p-4 sm:pr-8
|
|
103
|
-
'Best for chat widgets, deferred scripts, and tracking pixels.'] })] }), _jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "Scope" }), _jsxs("select", { value: scope, onChange: (e) => setScope(e.target.value), className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:
|
|
102
|
+
return (_jsxs("div", { className: "max-w-3xl p-3 pr-6 sm:p-4 sm:pr-8", children: [error && (_jsxs("div", { className: "mb-4 flex items-center gap-3 rounded-lg border border-red-200 bg-red-50 p-3", children: [_jsx(AlertTriangle, { className: "h-5 w-5 shrink-0 text-red-600" }), _jsx("span", { className: "flex-1 text-sm text-red-800", children: error })] })), _jsxs("div", { className: "mb-6", children: [_jsxs("button", { type: "button", onClick: () => onNavigate?.('/script-tags'), className: "mb-3 flex items-center gap-1.5 text-sm text-gray-500 transition-colors hover:text-gray-700", children: [_jsx(ArrowLeft, { className: "h-4 w-4" }), "Back to Script Tags"] }), _jsx("h1", { className: "text-2xl font-semibold text-gray-900", children: isNew ? 'New Script Tag' : 'Edit Script Tag' })] }), _jsx("div", { className: "mb-6 rounded-lg border border-amber-200 bg-amber-50 p-3", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-600" }), _jsx("p", { className: "text-sm text-amber-800", children: "This code will run on public pages matching the scope below. Only add trusted code from verified sources (e.g. Google Analytics, Meta Pixel)." })] }) }), _jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "space-y-4 rounded-lg border border-gray-200 bg-white p-4", children: [_jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "Name" }), _jsx("input", { type: "text", value: name, onChange: (e) => setName(e.target.value), placeholder: "e.g. Google Tag Manager, Facebook Pixel", className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" })] }), _jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "Code" }), _jsx("textarea", { value: code, onChange: (e) => setCode(e.target.value), placeholder: "Paste your HTML/JavaScript snippet here...", rows: 10, className: "w-full rounded-lg border border-gray-300 px-3 py-2 font-mono text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", spellCheck: false }), _jsxs("p", { className: "mt-1 text-xs text-gray-500", children: ["Paste the full code snippet including ", '<script>', " tags."] })] })] }), _jsxs("div", { className: "space-y-4 rounded-lg border border-gray-200 bg-white p-4", children: [_jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Placement & Scope" }), _jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "Placement" }), _jsxs("select", { value: placement, onChange: (e) => setPlacement(e.target.value), className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", children: [_jsxs("option", { value: "head", children: ["Head \u2014 inside ", '<head>'] }), _jsxs("option", { value: "body_open", children: ["Body Open \u2014 right after ", '<body>'] }), _jsxs("option", { value: "body_close", children: ["Body Close \u2014 before ", '</body>'] })] }), _jsxs("p", { className: "mt-1 text-xs text-gray-500", children: [placement === 'head' && 'Best for analytics scripts, meta tags, and custom CSS.', placement === 'body_open' && 'Best for GTM noscript tags and early-loading scripts.', placement === 'body_close' &&
|
|
103
|
+
'Best for chat widgets, deferred scripts, and tracking pixels.'] })] }), _jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "Scope" }), _jsxs("select", { value: scope, onChange: (e) => setScope(e.target.value), className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none", children: [_jsx("option", { value: "site", children: "Entire Website" }), _jsx("option", { value: "parents", children: "Specific Parent Pages (includes child pages)" }), _jsx("option", { value: "urls", children: "Specific URLs (exact match)" })] })] }), scope !== 'site' && (_jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: scope === 'parents' ? 'Parent Paths' : 'URL Paths' }), _jsxs("div", { className: "flex gap-2", children: [_jsx("input", { type: "text", value: pathInput, onChange: (e) => setPathInput(e.target.value), onKeyDown: (e) => {
|
|
104
104
|
if (e.key === 'Enter') {
|
|
105
105
|
e.preventDefault();
|
|
106
106
|
addPath();
|
|
107
107
|
}
|
|
108
|
-
}, placeholder: "/services", className: "flex-1 rounded-lg border border-gray-300 px-3 py-2
|
|
108
|
+
}, placeholder: "/services", className: "flex-1 rounded-lg border border-gray-300 px-3 py-2 font-mono text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" }), _jsx("button", { type: "button", onClick: addPath, className: "rounded-lg border border-gray-300 px-3 py-2 text-sm transition-colors hover:bg-gray-50", children: _jsx(Plus, { className: "h-4 w-4" }) })] }), scope === 'parents' && (_jsx("p", { className: "mt-1 text-xs text-gray-500", children: "This tag will also apply to all child pages under each path." })), targetPaths.length > 0 && (_jsx("div", { className: "mt-2 flex flex-wrap gap-2", children: targetPaths.map((p) => (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-gray-100 px-3 py-1 font-mono text-xs text-gray-700", children: [p, _jsx("button", { type: "button", onClick: () => removePath(p), className: "ml-0.5 text-gray-400 hover:text-gray-600", children: _jsx(X, { className: "h-3 w-3" }) })] }, p))) }))] })), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "Priority" }), _jsx("input", { type: "number", value: priority, onChange: (e) => setPriority(parseInt(e.target.value, 10) || 0), min: 0, className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" }), _jsx("p", { className: "mt-1 text-xs text-gray-500", children: "Lower numbers load first (e.g. 1 = first, 100 = default)" })] }), _jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "Enabled" }), _jsx("div", { className: "pt-2", children: _jsx("button", { type: "button", onClick: () => setEnabled(!enabled), className: `relative h-6 w-11 shrink-0 rounded-full transition-colors ${enabled ? 'bg-blue-600' : 'bg-gray-300'}`, "aria-pressed": enabled, children: _jsx("span", { className: `absolute top-0.5 block h-5 w-5 rounded-full bg-white transition-transform ${enabled ? 'translate-x-[22px]' : 'translate-x-0.5'}` }) }) })] })] })] }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("div", { children: !isNew && (_jsx(_Fragment, { children: showDeleteConfirm ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-sm text-red-600", children: "Delete this tag?" }), _jsx("button", { type: "button", onClick: handleDelete, disabled: deleting, className: "rounded-lg bg-red-600 px-3 py-1.5 text-sm text-white hover:bg-red-700 disabled:opacity-50", children: deleting ? 'Deleting...' : 'Confirm' }), _jsx("button", { type: "button", onClick: () => setShowDeleteConfirm(false), className: "rounded-lg border border-gray-300 px-3 py-1.5 text-sm hover:bg-gray-50", children: "Cancel" })] })) : (_jsxs("button", { type: "button", onClick: () => setShowDeleteConfirm(true), className: "flex items-center gap-1.5 text-sm text-red-600 transition-colors hover:text-red-700", children: [_jsx(Trash2, { className: "h-4 w-4" }), "Delete"] })) })) }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("button", { type: "button", onClick: () => onNavigate?.('/script-tags'), className: "rounded-lg border border-gray-300 px-4 py-2 text-sm text-gray-700 transition-colors hover:bg-gray-50", children: "Cancel" }), _jsx("button", { type: "button", onClick: handleSave, disabled: saving, className: "rounded-lg bg-blue-600 px-6 py-2 text-sm text-white transition-colors hover:bg-blue-700 disabled:opacity-50", children: saving ? 'Saving...' : isNew ? 'Create Tag' : 'Save Changes' })] })] })] })] }));
|
|
109
109
|
}
|
|
110
110
|
//# sourceMappingURL=ScriptTagEditor.js.map
|
package/dist/views/ScriptTags.js
CHANGED
|
@@ -49,8 +49,8 @@ export function ScriptTags({ onNavigate }) {
|
|
|
49
49
|
}
|
|
50
50
|
};
|
|
51
51
|
if (loading) {
|
|
52
|
-
return (_jsx("div", { className: "p-3 pr-6 sm:p-4 sm:pr-8
|
|
52
|
+
return (_jsx("div", { className: "flex h-64 items-center justify-center p-3 pr-6 sm:p-4 sm:pr-8", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-blue-600" }) }));
|
|
53
53
|
}
|
|
54
|
-
return (_jsxs("div", { className: "p-3 pr-6 sm:p-4 sm:pr-8", children: [error && (_jsxs("div", { className: "mb-4 flex items-center gap-3 rounded-lg border border-red-200 bg-red-50 p-3", children: [_jsx(AlertTriangle, { className: "
|
|
54
|
+
return (_jsxs("div", { className: "p-3 pr-6 sm:p-4 sm:pr-8", children: [error && (_jsxs("div", { className: "mb-4 flex items-center gap-3 rounded-lg border border-red-200 bg-red-50 p-3", children: [_jsx(AlertTriangle, { className: "h-5 w-5 shrink-0 text-red-600" }), _jsx("span", { className: "flex-1 text-sm text-red-800", children: error }), _jsx("button", { onClick: refetch, className: "rounded-lg border border-red-300 px-3 py-1 text-sm text-red-700 transition-colors hover:bg-red-100", children: "Retry" })] })), _jsxs("div", { className: "mb-4 flex items-center justify-between", children: [_jsxs("div", { children: [_jsx("h1", { className: "mb-1 text-2xl font-semibold text-gray-900", children: "Script Tags" }), _jsx("p", { className: "text-sm text-gray-600", children: "Manage tracking codes, analytics, and custom scripts injected into your site" })] }), _jsxs("button", { type: "button", onClick: () => onNavigate?.('/script-tags/new'), className: "flex items-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-700", children: [_jsx(Plus, { className: "h-4 w-4" }), "New Tag"] })] }), tags.length === 0 && !error ? (_jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-12 text-center", children: [_jsx(Code2, { className: "mx-auto mb-3 h-10 w-10 text-gray-300" }), _jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "No script tags yet" }), _jsx("p", { className: "mt-1 text-sm text-gray-500", children: "Add tracking codes like Google Analytics, Tag Manager, or Facebook Pixel." }), _jsxs("button", { type: "button", onClick: () => onNavigate?.('/script-tags/new'), className: "mt-4 inline-flex items-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-700", children: [_jsx(Plus, { className: "h-4 w-4" }), "Add Your First Tag"] })] })) : (_jsx("div", { className: "overflow-hidden rounded-lg border border-gray-200 bg-white", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b border-gray-200 bg-gray-50", children: [_jsx("th", { className: "px-4 py-3 text-left font-medium text-gray-600", children: "Name" }), _jsx("th", { className: "px-4 py-3 text-left font-medium text-gray-600", children: "Placement" }), _jsx("th", { className: "px-4 py-3 text-left font-medium text-gray-600", children: "Scope" }), _jsx("th", { className: "px-4 py-3 text-center font-medium text-gray-600", children: "Priority" }), _jsx("th", { className: "px-4 py-3 text-center font-medium text-gray-600", children: "Enabled" })] }) }), _jsx("tbody", { children: tags.map((tag) => (_jsxs("tr", { className: "border-b border-gray-100 transition-colors last:border-0 hover:bg-gray-50", children: [_jsx("td", { className: "px-4 py-3", children: _jsx("button", { type: "button", onClick: () => onNavigate?.(`/script-tags/${tag.id}`), className: "font-medium text-blue-600 hover:text-blue-800 hover:underline", children: tag.name }) }), _jsx("td", { className: "px-4 py-3", children: _jsx("span", { className: `inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${PLACEMENT_COLORS[tag.placement] ?? 'bg-gray-100 text-gray-700'}`, children: PLACEMENT_LABELS[tag.placement] ?? tag.placement }) }), _jsx("td", { className: "px-4 py-3 text-gray-600", children: scopeLabel(tag) }), _jsx("td", { className: "px-4 py-3 text-center font-mono text-gray-600", children: tag.priority }), _jsx("td", { className: "px-4 py-3 text-center", children: _jsx("button", { type: "button", onClick: () => toggleEnabled(tag), disabled: togglingId === tag.id, className: `relative h-6 w-11 shrink-0 rounded-full transition-colors ${tag.enabled ? 'bg-blue-600' : 'bg-gray-300'}`, "aria-pressed": tag.enabled, children: _jsx("span", { className: `absolute top-0.5 block h-5 w-5 rounded-full bg-white transition-transform ${tag.enabled ? 'translate-x-[22px]' : 'translate-x-0.5'}` }) }) })] }, tag.id))) })] }) }))] }));
|
|
55
55
|
}
|
|
56
56
|
//# sourceMappingURL=ScriptTags.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Settings.d.ts","sourceRoot":"","sources":["../../src/views/Settings.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Settings.d.ts","sourceRoot":"","sources":["../../src/views/Settings.tsx"],"names":[],"mappings":"AA+BA,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,MAAM,CAAC,EAAE,GAAG,CAAA;CACb;AAED,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,GAAE,aAAkB,2CA4nBjE"}
|