create-nextblock 0.16.1 → 0.16.3
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/docker-template/.dockerignore +1 -1
- package/libs/db/tsconfig.lib.json +3 -3
- package/libs/editor/tsconfig.lib.json +3 -3
- package/libs/ui/tsconfig.lib.json +3 -3
- package/libs/utils/tsconfig.json +3 -3
- package/package.json +50 -50
- package/project.json +19 -19
- package/templates/nextblock-template/.dockerignore +1 -1
- package/templates/nextblock-template/.swcrc +30 -30
- package/templates/nextblock-template/AGENTS.md +9 -9
- package/templates/nextblock-template/CLAUDE.md +1 -1
- package/templates/nextblock-template/app/(auth-pages)/layout.tsx +9 -9
- package/templates/nextblock-template/app/(auth-pages)/post-sign-in/page.tsx +27 -27
- package/templates/nextblock-template/app/.well-known/ucp/route.ts +16 -16
- package/templates/nextblock-template/app/ToasterProvider.tsx +26 -26
- package/templates/nextblock-template/app/[slug]/pageClientActions.ts +7 -7
- package/templates/nextblock-template/app/actions/contactSellerActions.test.ts +280 -280
- package/templates/nextblock-template/app/actions/contactSellerActions.ts +222 -222
- package/templates/nextblock-template/app/actions/email-retry.test.ts +62 -62
- package/templates/nextblock-template/app/actions/email.ts +241 -241
- package/templates/nextblock-template/app/actions/formActions.ts +245 -245
- package/templates/nextblock-template/app/actions/interactions.ts +489 -489
- package/templates/nextblock-template/app/actions/threadActions.ts +166 -166
- package/templates/nextblock-template/app/actions/visibilityActions.ts +210 -210
- package/templates/nextblock-template/app/api/ai/seo/alt-text/route.ts +221 -221
- package/templates/nextblock-template/app/api/ai/seo/metadata/route.ts +186 -186
- package/templates/nextblock-template/app/api/checkout/freemius/sync/route.ts +29 -29
- package/templates/nextblock-template/app/api/checkout/route.ts +162 -162
- package/templates/nextblock-template/app/api/cron/reset-sandbox/route.ts +4 -4
- package/templates/nextblock-template/app/api/cron/reset-sandbox/sandboxResetSql.ts +4542 -2904
- package/templates/nextblock-template/app/api/mcp/route.ts +415 -415
- package/templates/nextblock-template/app/api/media/record/route.ts +160 -160
- package/templates/nextblock-template/app/api/search/route.ts +43 -43
- package/templates/nextblock-template/app/api/view/route.ts +114 -114
- package/templates/nextblock-template/app/api/visual-editing/block-draft/route.ts +47 -47
- package/templates/nextblock-template/app/api/visual-editing/product-draft/route.ts +47 -47
- package/templates/nextblock-template/app/auth/callback/route.ts +31 -31
- package/templates/nextblock-template/app/cart/page.tsx +7 -7
- package/templates/nextblock-template/app/checkout/UcpCartHydrator.tsx +20 -20
- package/templates/nextblock-template/app/checkout/page.tsx +57 -57
- package/templates/nextblock-template/app/cms/CmsClientLayout.tsx +558 -558
- package/templates/nextblock-template/app/cms/blocks/components/BlockEditorModal.tsx +241 -241
- package/templates/nextblock-template/app/cms/blocks/components/MediaLibraryModal.tsx +149 -149
- package/templates/nextblock-template/app/cms/blocks/editors/FormBlockEditor.tsx +304 -304
- package/templates/nextblock-template/app/cms/blocks/editors/ImageBlockEditor.tsx +406 -406
- package/templates/nextblock-template/app/cms/components/ContactReminderBanner.tsx +75 -75
- package/templates/nextblock-template/app/cms/components/CortexAiActiveContext.tsx +23 -23
- package/templates/nextblock-template/app/cms/components/CortexAiPageContext.tsx +58 -58
- package/templates/nextblock-template/app/cms/components/FeatureImageField.tsx +254 -254
- package/templates/nextblock-template/app/cms/components/FeedbackModal.tsx +36 -36
- package/templates/nextblock-template/app/cms/components/PaymentsReminderBanner.tsx +58 -58
- package/templates/nextblock-template/app/cms/components/SeoScoreBadge.tsx +40 -0
- package/templates/nextblock-template/app/cms/components/TablePagination.tsx +136 -0
- package/templates/nextblock-template/app/cms/components/VisibilityBadge.tsx +62 -62
- package/templates/nextblock-template/app/cms/components/VisibilityControl.tsx +542 -542
- package/templates/nextblock-template/app/cms/coupons/[id]/edit/page.tsx +16 -16
- package/templates/nextblock-template/app/cms/coupons/page.tsx +16 -16
- package/templates/nextblock-template/app/cms/dashboard/actions.ts +228 -228
- package/templates/nextblock-template/app/cms/dashboard/components/DashboardComponents.tsx +200 -200
- package/templates/nextblock-template/app/cms/inquiries/actions.ts +66 -66
- package/templates/nextblock-template/app/cms/inquiries/page.tsx +12 -12
- package/templates/nextblock-template/app/cms/interactions/page.tsx +12 -12
- package/templates/nextblock-template/app/cms/layout.tsx +101 -101
- package/templates/nextblock-template/app/cms/media/components/FolderNavigator.tsx +273 -273
- package/templates/nextblock-template/app/cms/media/components/FolderTree.tsx +122 -122
- package/templates/nextblock-template/app/cms/media/components/MediaGridClient.tsx +69 -69
- package/templates/nextblock-template/app/cms/messages/MessagesClient.tsx +661 -661
- package/templates/nextblock-template/app/cms/messages/actions.ts +404 -404
- package/templates/nextblock-template/app/cms/messages/loadInbox.ts +333 -333
- package/templates/nextblock-template/app/cms/messages/page.tsx +87 -87
- package/templates/nextblock-template/app/cms/messages/require-admin.ts +37 -37
- package/templates/nextblock-template/app/cms/navigation/components/NavigationMenuDnd.tsx +3 -3
- package/templates/nextblock-template/app/cms/pages/components/PageForm.tsx +649 -649
- package/templates/nextblock-template/app/cms/pages/page.tsx +273 -227
- package/templates/nextblock-template/app/cms/posts/[id]/edit/page.tsx +2 -0
- package/templates/nextblock-template/app/cms/posts/components/PostForm.tsx +624 -618
- package/templates/nextblock-template/app/cms/posts/page.tsx +251 -194
- package/templates/nextblock-template/app/cms/products/[id]/edit/page.tsx +370 -370
- package/templates/nextblock-template/app/cms/products/attributes/page.tsx +12 -12
- package/templates/nextblock-template/app/cms/products/inventory/page.tsx +13 -13
- package/templates/nextblock-template/app/cms/products/productFormData.ts +133 -133
- package/templates/nextblock-template/app/cms/products/settings/page.tsx +5 -5
- package/templates/nextblock-template/app/cms/revisions/actions.ts +332 -332
- package/templates/nextblock-template/app/cms/revisions/service.test.ts +498 -498
- package/templates/nextblock-template/app/cms/revisions/service.ts +569 -569
- package/templates/nextblock-template/app/cms/revisions/utils.ts +304 -304
- package/templates/nextblock-template/app/cms/settings/cortex-ai/CortexAiSettingsClient.tsx +948 -948
- package/templates/nextblock-template/app/cms/settings/cortex-ai/McpServerSettingsCard.tsx +628 -628
- package/templates/nextblock-template/app/cms/settings/cortex-ai/mcp-actions.ts +230 -230
- package/templates/nextblock-template/app/cms/settings/cortex-ai/require-admin.ts +34 -34
- package/templates/nextblock-template/app/cms/settings/currencies/actions.ts +331 -331
- package/templates/nextblock-template/app/cms/settings/currencies/page.tsx +494 -494
- package/templates/nextblock-template/app/cms/settings/email/components/EmailForm.tsx +227 -227
- package/templates/nextblock-template/app/cms/settings/extra-translations/ExtraTranslationsWorkspace.tsx +767 -767
- package/templates/nextblock-template/app/cms/settings/extra-translations/actions.ts +276 -276
- package/templates/nextblock-template/app/cms/settings/extra-translations/page.tsx +93 -93
- package/templates/nextblock-template/app/cms/settings/global-css/components/ThemeEditor.tsx +382 -382
- package/templates/nextblock-template/app/cms/settings/global-css/components/ThemeManager.tsx +267 -267
- package/templates/nextblock-template/app/cms/settings/global-css/page.tsx +40 -40
- package/templates/nextblock-template/app/cms/settings/global-css/theme-actions.ts +259 -259
- package/templates/nextblock-template/app/cms/settings/logos/[id]/edit/page.tsx +7 -7
- package/templates/nextblock-template/app/cms/settings/logos/components/BrandingSettingsForm.tsx +339 -339
- package/templates/nextblock-template/app/cms/settings/logos/new/page.tsx +8 -8
- package/templates/nextblock-template/app/cms/settings/seo/RedirectsCard.tsx +514 -514
- package/templates/nextblock-template/app/cms/settings/seo/RobotsCard.tsx +529 -529
- package/templates/nextblock-template/app/cms/settings/seo/SeoSettingsClient.tsx +57 -57
- package/templates/nextblock-template/app/cms/settings/seo/actions.ts +448 -448
- package/templates/nextblock-template/app/cms/settings/seo/mappers.ts +93 -93
- package/templates/nextblock-template/app/cms/settings/seo/page.tsx +46 -46
- package/templates/nextblock-template/app/cms/settings/seo/require-admin.ts +47 -47
- package/templates/nextblock-template/app/cms/settings/site-scripts/page.tsx +51 -51
- package/templates/nextblock-template/app/cms/settings/taxes/page.tsx +21 -21
- package/templates/nextblock-template/app/cms/shipping/page.tsx +20 -20
- package/templates/nextblock-template/app/cms/users/components/DeleteUserButton.tsx +12 -12
- package/templates/nextblock-template/app/layout.tsx +671 -671
- package/templates/nextblock-template/app/lib/seo.ts +319 -319
- package/templates/nextblock-template/app/lib/ucp/protocol.ts +190 -190
- package/templates/nextblock-template/app/lib/ucp/server.test.ts +56 -56
- package/templates/nextblock-template/app/product/[slug]/page.tsx +502 -502
- package/templates/nextblock-template/app/profile/ProfilePageHeader.tsx +16 -16
- package/templates/nextblock-template/app/profile/ProfilePageMissingState.tsx +9 -9
- package/templates/nextblock-template/app/profile/account-links.ts +22 -22
- package/templates/nextblock-template/app/profile/orders/CustomerOrdersPageClient.tsx +124 -124
- package/templates/nextblock-template/app/profile/orders/page.tsx +19 -19
- package/templates/nextblock-template/app/profile/password/PasswordSettingsPageClient.tsx +128 -128
- package/templates/nextblock-template/app/profile/password/actions.ts +59 -59
- package/templates/nextblock-template/app/profile/password/page.tsx +27 -27
- package/templates/nextblock-template/app/providers.tsx +96 -96
- package/templates/nextblock-template/app/robots.ts +123 -123
- package/templates/nextblock-template/app/thread/ThreadView.tsx +164 -164
- package/templates/nextblock-template/app/thread/[token]/route.ts +57 -57
- package/templates/nextblock-template/app/thread/layout.tsx +15 -15
- package/templates/nextblock-template/app/thread/page.tsx +98 -98
- package/templates/nextblock-template/app/ucp/v1/carts/[id]/cancel/route.ts +38 -38
- package/templates/nextblock-template/app/ucp/v1/carts/[id]/route.ts +68 -68
- package/templates/nextblock-template/app/ucp/v1/carts/route.ts +35 -35
- package/templates/nextblock-template/app/ucp/v1/catalog/lookup/route.ts +35 -35
- package/templates/nextblock-template/app/ucp/v1/catalog/product/route.ts +35 -35
- package/templates/nextblock-template/app/ucp/v1/catalog/search/route.ts +34 -34
- package/templates/nextblock-template/components/BlockRenderer.tsx +312 -312
- package/templates/nextblock-template/components/CartDrawerLoader.tsx +7 -7
- package/templates/nextblock-template/components/CartTranslator.tsx +210 -210
- package/templates/nextblock-template/components/ContactSellerSection.tsx +188 -188
- package/templates/nextblock-template/components/DeferredCartDrawer.tsx +23 -23
- package/templates/nextblock-template/components/DeferredCartTranslator.tsx +51 -51
- package/templates/nextblock-template/components/DeferredGlobalSearch.tsx +68 -68
- package/templates/nextblock-template/components/DeferredGoogleTagManager.tsx +70 -70
- package/templates/nextblock-template/components/DeferredSpeedInsights.tsx +69 -69
- package/templates/nextblock-template/components/FooterNavigation.tsx +32 -32
- package/templates/nextblock-template/components/GlobalSearch.tsx +557 -557
- package/templates/nextblock-template/components/Header.tsx +38 -38
- package/templates/nextblock-template/components/HtmlScriptExecutor.tsx +47 -47
- package/templates/nextblock-template/components/LanguageSwitcher.tsx +2 -2
- package/templates/nextblock-template/components/PostCommentsSection.tsx +378 -378
- package/templates/nextblock-template/components/ProductReviewsSection.tsx +426 -426
- package/templates/nextblock-template/components/SiteScripts.tsx +56 -56
- package/templates/nextblock-template/components/StaffReplies.tsx +102 -102
- package/templates/nextblock-template/components/blocks/PostCardSkeleton.tsx +12 -12
- package/templates/nextblock-template/components/blocks/PostsGridBlock.tsx +12 -12
- package/templates/nextblock-template/components/blocks/PostsGridClient.tsx +48 -48
- package/templates/nextblock-template/components/blocks/TestimonialBlock.tsx +9 -9
- package/templates/nextblock-template/components/blocks/ecommerceRendererLoaders.ts +23 -23
- package/templates/nextblock-template/components/blocks/publicRendererLoaders.ts +25 -25
- package/templates/nextblock-template/components/blocks/renderers/ButtonBlockRenderer.tsx +92 -92
- package/templates/nextblock-template/components/blocks/renderers/CartBlockRenderer.tsx +18 -18
- package/templates/nextblock-template/components/blocks/renderers/CheckoutBlockRenderer.tsx +20 -20
- package/templates/nextblock-template/components/blocks/renderers/FeaturedProductBlockRenderer.tsx +25 -25
- package/templates/nextblock-template/components/blocks/renderers/FormBlockRenderer.tsx +385 -385
- package/templates/nextblock-template/components/blocks/renderers/PostsGridBlockRenderer.tsx +24 -24
- package/templates/nextblock-template/components/blocks/renderers/ProductDetailsBlockRenderer.tsx +157 -157
- package/templates/nextblock-template/components/blocks/renderers/ProductGridBlockRenderer.tsx +34 -34
- package/templates/nextblock-template/components/blocks/renderers/SectionBlockRenderer.tsx +612 -612
- package/templates/nextblock-template/components/blocks/renderers/TestimonialBlockRenderer.tsx +57 -57
- package/templates/nextblock-template/components/blocks/renderers/inline/AlertWidgetRenderer.tsx +2 -2
- package/templates/nextblock-template/components/blocks/renderers/inline/CtaWidgetRenderer.tsx +2 -2
- package/templates/nextblock-template/components/blocks/types.ts +7 -7
- package/templates/nextblock-template/components/commerce/PaymentReadinessBoundary.tsx +32 -32
- package/templates/nextblock-template/components/env-var-warning.tsx +3 -3
- package/templates/nextblock-template/components/form-message.tsx +32 -32
- package/templates/nextblock-template/components/seo/GenerateMetaButton.tsx +137 -137
- package/templates/nextblock-template/components/seo/PageSeoAuditSection.tsx +251 -244
- package/templates/nextblock-template/components/seo/SeoAuditPanel.tsx +749 -749
- package/templates/nextblock-template/components/seo/SeoIssueList.tsx +195 -195
- package/templates/nextblock-template/components/seo/SeoScoreDial.tsx +144 -144
- package/templates/nextblock-template/components/seo/SocialPreview.tsx +243 -243
- package/templates/nextblock-template/components/seo/SocialPreviewDialog.tsx +110 -110
- package/templates/nextblock-template/components/submit-button.tsx +23 -23
- package/templates/nextblock-template/components/theme-icon.tsx +78 -78
- package/templates/nextblock-template/components/theme-switcher.tsx +85 -85
- package/templates/nextblock-template/context/AuthContext.tsx +23 -23
- package/templates/nextblock-template/context/ThemeCatalogContext.tsx +44 -44
- package/templates/nextblock-template/docs/01-PROJECT-OVERVIEW.md +94 -94
- package/templates/nextblock-template/docs/03-CMS-AND-EDITOR.md +77 -77
- package/templates/nextblock-template/docs/13-STAYING-UP-TO-DATE.md +372 -372
- package/templates/nextblock-template/docs/14-MESSAGES-INBOX.md +309 -309
- package/templates/nextblock-template/docs/README.md +42 -42
- package/templates/nextblock-template/docs/TECHNICAL_SPECIFICATION.md +12506 -12506
- package/templates/nextblock-template/hooks/use-hotkeys.ts +21 -21
- package/templates/nextblock-template/hooks/useGlobalSearch.ts +101 -101
- package/templates/nextblock-template/index.d.ts +7 -7
- package/templates/nextblock-template/lib/auth-redirects.ts +46 -46
- package/templates/nextblock-template/lib/blocks/blockColors.test.ts +134 -134
- package/templates/nextblock-template/lib/blocks/blockColors.ts +175 -175
- package/templates/nextblock-template/lib/blocks/blockRegistry.ts +761 -761
- package/templates/nextblock-template/lib/blocks/inlineScriptNonce.ts +20 -20
- package/templates/nextblock-template/lib/cms/contact-reminder.ts +64 -64
- package/templates/nextblock-template/lib/cms/payments-reminder.test.ts +135 -0
- package/templates/nextblock-template/lib/cms/payments-reminder.ts +30 -23
- package/templates/nextblock-template/lib/cms/unread-messages.ts +42 -42
- package/templates/nextblock-template/lib/commerce/seller-contact.ts +162 -162
- package/templates/nextblock-template/lib/config/email-settings.ts +323 -323
- package/templates/nextblock-template/lib/config/email-tls.test.ts +57 -57
- package/templates/nextblock-template/lib/cortex-ai/alt-text-request.ts +86 -86
- package/templates/nextblock-template/lib/cortex-ai/sandbox-headers.ts +60 -60
- package/templates/nextblock-template/lib/email/placeholder-address.test.ts +59 -59
- package/templates/nextblock-template/lib/email/placeholder-address.ts +39 -39
- package/templates/nextblock-template/lib/messages/thread-reference.test.ts +70 -70
- package/templates/nextblock-template/lib/messages/thread-token.test.ts +93 -93
- package/templates/nextblock-template/lib/messages/thread-token.ts +157 -157
- package/templates/nextblock-template/lib/messages/threads.ts +579 -579
- package/templates/nextblock-template/lib/posts/readTime.ts +60 -60
- package/templates/nextblock-template/lib/publishing/viewUrl.ts +26 -26
- package/templates/nextblock-template/lib/search/types.ts +27 -27
- package/templates/nextblock-template/lib/seo/alt-text-write-back.test.ts +154 -154
- package/templates/nextblock-template/lib/seo/alt-text-write-back.ts +109 -109
- package/templates/nextblock-template/lib/seo/block-content.ts +123 -123
- package/templates/nextblock-template/lib/seo/fix-prompts.test.ts +242 -242
- package/templates/nextblock-template/lib/seo/fix-prompts.ts +204 -204
- package/templates/nextblock-template/lib/seo/page-audit-context.tsx +157 -140
- package/templates/nextblock-template/lib/seo/page-document.test.ts +384 -350
- package/templates/nextblock-template/lib/seo/page-document.ts +463 -412
- package/templates/nextblock-template/lib/seo/redirect-store.test.ts +479 -479
- package/templates/nextblock-template/lib/seo/redirect-store.ts +466 -466
- package/templates/nextblock-template/lib/seo/robots-settings-signature.test.ts +102 -102
- package/templates/nextblock-template/lib/seo/robots-settings-signature.ts +41 -41
- package/templates/nextblock-template/lib/seo/robots-txt.test.ts +370 -370
- package/templates/nextblock-template/lib/seo/robots-txt.ts +510 -510
- package/templates/nextblock-template/lib/setup/migrations-bundle.ts +37 -22
- package/templates/nextblock-template/lib/site-scripts/revisions.ts +71 -71
- package/templates/nextblock-template/lib/site-scripts/types.ts +46 -46
- package/templates/nextblock-template/lib/site-url.test.ts +89 -89
- package/templates/nextblock-template/lib/site-url.ts +102 -102
- package/templates/nextblock-template/lib/themes/buildThemeCss.ts +124 -124
- package/templates/nextblock-template/lib/themes/tokenColor.ts +31 -31
- package/templates/nextblock-template/lib/themes/tokens.ts +143 -143
- package/templates/nextblock-template/lib/visual-editing/draft-content.test.ts +105 -105
- package/templates/nextblock-template/lib/visual-editing/draft-route.test.ts +42 -42
- package/templates/nextblock-template/lib/visual-editing/edit-info.test.ts +143 -143
- package/templates/nextblock-template/lib/visual-editing/edit-info.ts +94 -94
- package/templates/nextblock-template/lib/visual-editing/product-drafts.test.ts +81 -81
- package/templates/nextblock-template/lib/zod-config.ts +5 -5
- package/templates/nextblock-template/next-env.d.ts +1 -2
- package/templates/nextblock-template/package.json +1 -1
- package/templates/nextblock-template/postcss.config.js +6 -6
- package/templates/nextblock-template/scripts/backup.js +115 -115
- package/templates/nextblock-template/scripts/restore.js +385 -385
- package/templates/nextblock-template/scripts/validate-editor-block-schema.ts +112 -112
- package/templates/nextblock-template/tailwind.config.js +25 -25
- package/templates/nextblock-template/tools/build-migrate.mjs +102 -102
- package/templates/nextblock-template/tools/configure-supabase-auth.js +282 -282
- package/templates/nextblock-template/tools/deploy-supabase.js +159 -159
- package/templates/nextblock-template/tools/lib/migrate-core.mjs +569 -569
- package/templates/nextblock-template/tools/update.mjs +1303 -1303
- package/tsconfig.base.json +3 -3
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import Link from 'next/link';
|
|
4
|
-
import { useState } from 'react';
|
|
5
|
-
import { Button } from '@nextblock-cms/ui';
|
|
6
|
-
import { CreditCard, X } from 'lucide-react';
|
|
7
|
-
import { useAuth } from '../../../context/AuthContext';
|
|
8
|
-
import type { PaymentsReminder } from '../../../lib/cms/payments-reminder';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Shown when commerce is active but a payment provider isn't ready, so published
|
|
12
|
-
* products cannot actually be bought. ADMIN-only: /cms/payments is an admin route, so a
|
|
13
|
-
* WRITER would get a reminder they cannot act on. Dismissible for the session only —
|
|
14
|
-
* this is a real revenue problem and should come back until it's fixed.
|
|
15
|
-
*/
|
|
16
|
-
export default function PaymentsReminderBanner({ reminder }: { reminder: PaymentsReminder }) {
|
|
17
|
-
const { isAdmin } = useAuth();
|
|
18
|
-
const [dismissed, setDismissed] = useState(false);
|
|
19
|
-
|
|
20
|
-
if (!isAdmin || dismissed) return null;
|
|
21
|
-
|
|
22
|
-
const providerSummary = reminder.blocked
|
|
23
|
-
.map(({ label, missing }) => (missing.length ? `${label} (missing: ${missing.join(', ')})` : label))
|
|
24
|
-
.join(' and ');
|
|
25
|
-
|
|
26
|
-
return (
|
|
27
|
-
<div className="mb-6 flex items-start gap-3 rounded-lg border border-amber-300 bg-amber-50 px-4 py-3 text-amber-900 dark:border-amber-700/60 dark:bg-amber-900/20 dark:text-amber-200">
|
|
28
|
-
<CreditCard className="mt-0.5 h-5 w-5 shrink-0" />
|
|
29
|
-
<div className="min-w-0 flex-1">
|
|
30
|
-
<p className="text-sm font-medium">
|
|
31
|
-
Your store can’t take payments yet.
|
|
32
|
-
</p>
|
|
33
|
-
<p className="text-xs opacity-90">
|
|
34
|
-
{providerSummary} still needs setting up.{' '}
|
|
35
|
-
{reminder.affectedProducts > 0
|
|
36
|
-
? `${reminder.affectedProducts} published ${
|
|
37
|
-
reminder.affectedProducts === 1 ? 'product' : 'products'
|
|
38
|
-
} cannot be bought — visitors see a "Contact the seller" form instead of Add to cart.`
|
|
39
|
-
: 'Products you publish will show visitors a "Contact the seller" form instead of Add to cart.'}
|
|
40
|
-
</p>
|
|
41
|
-
</div>
|
|
42
|
-
<div className="flex shrink-0 items-center gap-2">
|
|
43
|
-
<Button asChild size="sm" variant="outline" className="border-amber-400">
|
|
44
|
-
<Link href="/cms/payments">Set up payments</Link>
|
|
45
|
-
</Button>
|
|
46
|
-
<Button
|
|
47
|
-
variant="ghost"
|
|
48
|
-
size="icon"
|
|
49
|
-
onClick={() => setDismissed(true)}
|
|
50
|
-
aria-label="Dismiss for now"
|
|
51
|
-
className="h-8 w-8"
|
|
52
|
-
>
|
|
53
|
-
<X className="h-4 w-4" />
|
|
54
|
-
</Button>
|
|
55
|
-
</div>
|
|
56
|
-
</div>
|
|
57
|
-
);
|
|
58
|
-
}
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import Link from 'next/link';
|
|
4
|
+
import { useState } from 'react';
|
|
5
|
+
import { Button } from '@nextblock-cms/ui';
|
|
6
|
+
import { CreditCard, X } from 'lucide-react';
|
|
7
|
+
import { useAuth } from '../../../context/AuthContext';
|
|
8
|
+
import type { PaymentsReminder } from '../../../lib/cms/payments-reminder';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Shown when commerce is active but a payment provider isn't ready, so published
|
|
12
|
+
* products cannot actually be bought. ADMIN-only: /cms/payments is an admin route, so a
|
|
13
|
+
* WRITER would get a reminder they cannot act on. Dismissible for the session only —
|
|
14
|
+
* this is a real revenue problem and should come back until it's fixed.
|
|
15
|
+
*/
|
|
16
|
+
export default function PaymentsReminderBanner({ reminder }: { reminder: PaymentsReminder }) {
|
|
17
|
+
const { isAdmin } = useAuth();
|
|
18
|
+
const [dismissed, setDismissed] = useState(false);
|
|
19
|
+
|
|
20
|
+
if (!isAdmin || dismissed) return null;
|
|
21
|
+
|
|
22
|
+
const providerSummary = reminder.blocked
|
|
23
|
+
.map(({ label, missing }) => (missing.length ? `${label} (missing: ${missing.join(', ')})` : label))
|
|
24
|
+
.join(' and ');
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<div className="mb-6 flex items-start gap-3 rounded-lg border border-amber-300 bg-amber-50 px-4 py-3 text-amber-900 dark:border-amber-700/60 dark:bg-amber-900/20 dark:text-amber-200">
|
|
28
|
+
<CreditCard className="mt-0.5 h-5 w-5 shrink-0" />
|
|
29
|
+
<div className="min-w-0 flex-1">
|
|
30
|
+
<p className="text-sm font-medium">
|
|
31
|
+
Your store can’t take payments yet.
|
|
32
|
+
</p>
|
|
33
|
+
<p className="text-xs opacity-90">
|
|
34
|
+
{providerSummary} still needs setting up.{' '}
|
|
35
|
+
{reminder.affectedProducts > 0
|
|
36
|
+
? `${reminder.affectedProducts} published ${
|
|
37
|
+
reminder.affectedProducts === 1 ? 'product' : 'products'
|
|
38
|
+
} cannot be bought — visitors see a "Contact the seller" form instead of Add to cart.`
|
|
39
|
+
: 'Products you publish will show visitors a "Contact the seller" form instead of Add to cart.'}
|
|
40
|
+
</p>
|
|
41
|
+
</div>
|
|
42
|
+
<div className="flex shrink-0 items-center gap-2">
|
|
43
|
+
<Button asChild size="sm" variant="outline" className="border-amber-400">
|
|
44
|
+
<Link href="/cms/payments">Set up payments</Link>
|
|
45
|
+
</Button>
|
|
46
|
+
<Button
|
|
47
|
+
variant="ghost"
|
|
48
|
+
size="icon"
|
|
49
|
+
onClick={() => setDismissed(true)}
|
|
50
|
+
aria-label="Dismiss for now"
|
|
51
|
+
className="h-8 w-8"
|
|
52
|
+
>
|
|
53
|
+
<X className="h-4 w-4" />
|
|
54
|
+
</Button>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Badge } from "@nextblock-cms/ui";
|
|
3
|
+
|
|
4
|
+
interface SeoScoreBadgeProps {
|
|
5
|
+
score: number;
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default function SeoScoreBadge({ score, className = "" }: SeoScoreBadgeProps) {
|
|
10
|
+
const normalizedScore = Math.max(0, Math.min(100, Math.round(score)));
|
|
11
|
+
|
|
12
|
+
let colorClass = "";
|
|
13
|
+
let dotClass = "";
|
|
14
|
+
let title = "";
|
|
15
|
+
|
|
16
|
+
if (normalizedScore >= 90) {
|
|
17
|
+
colorClass = "bg-emerald-100 text-emerald-800 border-emerald-200 dark:bg-emerald-950/50 dark:text-emerald-300 dark:border-emerald-800/60";
|
|
18
|
+
dotClass = "bg-emerald-500";
|
|
19
|
+
title = `SEO Score: ${normalizedScore}% — Optimal`;
|
|
20
|
+
} else if (normalizedScore >= 70) {
|
|
21
|
+
colorClass = "bg-amber-100 text-amber-800 border-amber-200 dark:bg-amber-950/50 dark:text-amber-300 dark:border-amber-800/60";
|
|
22
|
+
dotClass = "bg-amber-500";
|
|
23
|
+
title = `SEO Score: ${normalizedScore}% — Good (Minor warnings)`;
|
|
24
|
+
} else {
|
|
25
|
+
colorClass = "bg-rose-100 text-rose-800 border-rose-200 dark:bg-rose-950/50 dark:text-rose-300 dark:border-rose-800/60";
|
|
26
|
+
dotClass = "bg-rose-500";
|
|
27
|
+
title = `SEO Score: ${normalizedScore}% — Needs improvement`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<Badge
|
|
32
|
+
variant="outline"
|
|
33
|
+
title={title}
|
|
34
|
+
className={`inline-flex items-center px-2 py-0.5 text-xs font-semibold rounded-full border transition-colors ${colorClass} ${className}`}
|
|
35
|
+
>
|
|
36
|
+
<span className={`w-1.5 h-1.5 rounded-full mr-1.5 shrink-0 ${dotClass}`} />
|
|
37
|
+
{normalizedScore}%
|
|
38
|
+
</Badge>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { useRouter, useSearchParams } from "next/navigation";
|
|
5
|
+
import {
|
|
6
|
+
Button,
|
|
7
|
+
Select,
|
|
8
|
+
SelectContent,
|
|
9
|
+
SelectItem,
|
|
10
|
+
SelectTrigger,
|
|
11
|
+
SelectValue,
|
|
12
|
+
} from "@nextblock-cms/ui";
|
|
13
|
+
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
14
|
+
|
|
15
|
+
interface TablePaginationProps {
|
|
16
|
+
currentPage: number;
|
|
17
|
+
pageSize: number;
|
|
18
|
+
totalCount: number;
|
|
19
|
+
basePath: string;
|
|
20
|
+
itemLabel?: string;
|
|
21
|
+
pageSizeOptions?: number[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default function TablePagination({
|
|
25
|
+
currentPage,
|
|
26
|
+
pageSize,
|
|
27
|
+
totalCount,
|
|
28
|
+
basePath,
|
|
29
|
+
itemLabel = "items",
|
|
30
|
+
pageSizeOptions = [10, 25, 50, 100],
|
|
31
|
+
}: TablePaginationProps) {
|
|
32
|
+
const router = useRouter();
|
|
33
|
+
const searchParams = useSearchParams();
|
|
34
|
+
|
|
35
|
+
const totalPages = Math.max(1, Math.ceil(totalCount / pageSize));
|
|
36
|
+
const from = totalCount === 0 ? 0 : (currentPage - 1) * pageSize + 1;
|
|
37
|
+
const to = Math.min(totalCount, currentPage * pageSize);
|
|
38
|
+
|
|
39
|
+
const navigateTo = (newPage: number, newPageSize?: number) => {
|
|
40
|
+
const current = new URLSearchParams(Array.from(searchParams.entries()));
|
|
41
|
+
|
|
42
|
+
if (newPage > 1) {
|
|
43
|
+
current.set("page", newPage.toString());
|
|
44
|
+
} else {
|
|
45
|
+
current.delete("page");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const effectivePageSize = newPageSize ?? pageSize;
|
|
49
|
+
if (effectivePageSize !== 25) {
|
|
50
|
+
current.set("pageSize", effectivePageSize.toString());
|
|
51
|
+
} else {
|
|
52
|
+
current.delete("pageSize");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const query = current.toString();
|
|
56
|
+
router.push(`${basePath}${query ? `?${query}` : ""}`);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const handlePageSizeChange = (val: string) => {
|
|
60
|
+
const nextSize = parseInt(val, 10);
|
|
61
|
+
if (!Number.isNaN(nextSize) && nextSize > 0) {
|
|
62
|
+
// Reset to page 1 when changing page size
|
|
63
|
+
navigateTo(1, nextSize);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<div className="flex flex-col sm:flex-row items-center justify-between gap-4 px-4 py-3 bg-muted/20 border-t border-slate-200 dark:border-slate-700 text-xs sm:text-sm text-muted-foreground">
|
|
69
|
+
{/* Item summary */}
|
|
70
|
+
<div className="flex items-center gap-1">
|
|
71
|
+
<span>Showing</span>
|
|
72
|
+
<span className="font-medium text-foreground">{from}</span>
|
|
73
|
+
<span>to</span>
|
|
74
|
+
<span className="font-medium text-foreground">{to}</span>
|
|
75
|
+
<span>of</span>
|
|
76
|
+
<span className="font-medium text-foreground">{totalCount}</span>
|
|
77
|
+
<span>{itemLabel}</span>
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
{/* Controls: Page size + Pagination buttons */}
|
|
81
|
+
<div className="flex items-center gap-4 sm:gap-6 flex-wrap">
|
|
82
|
+
{/* Rows per page selector */}
|
|
83
|
+
<div className="flex items-center gap-2">
|
|
84
|
+
<span className="text-xs">Rows per page:</span>
|
|
85
|
+
<Select
|
|
86
|
+
value={pageSize.toString()}
|
|
87
|
+
onValueChange={handlePageSizeChange}
|
|
88
|
+
>
|
|
89
|
+
<SelectTrigger className="h-8 w-[72px] text-xs">
|
|
90
|
+
<SelectValue />
|
|
91
|
+
</SelectTrigger>
|
|
92
|
+
<SelectContent>
|
|
93
|
+
{pageSizeOptions.map((opt) => (
|
|
94
|
+
<SelectItem key={opt} value={opt.toString()} className="text-xs">
|
|
95
|
+
{opt}
|
|
96
|
+
</SelectItem>
|
|
97
|
+
))}
|
|
98
|
+
</SelectContent>
|
|
99
|
+
</Select>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
{/* Page counter */}
|
|
103
|
+
<div className="flex items-center gap-1 text-xs">
|
|
104
|
+
<span>Page</span>
|
|
105
|
+
<span className="font-medium text-foreground">{currentPage}</span>
|
|
106
|
+
<span>of</span>
|
|
107
|
+
<span className="font-medium text-foreground">{totalPages}</span>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
{/* Prev / Next buttons */}
|
|
111
|
+
<div className="flex items-center gap-1">
|
|
112
|
+
<Button
|
|
113
|
+
variant="outline"
|
|
114
|
+
size="sm"
|
|
115
|
+
className="h-8 w-8 p-0"
|
|
116
|
+
disabled={currentPage <= 1}
|
|
117
|
+
onClick={() => navigateTo(currentPage - 1)}
|
|
118
|
+
aria-label="Previous page"
|
|
119
|
+
>
|
|
120
|
+
<ChevronLeft className="h-4 w-4" />
|
|
121
|
+
</Button>
|
|
122
|
+
<Button
|
|
123
|
+
variant="outline"
|
|
124
|
+
size="sm"
|
|
125
|
+
className="h-8 w-8 p-0"
|
|
126
|
+
disabled={currentPage >= totalPages}
|
|
127
|
+
onClick={() => navigateTo(currentPage + 1)}
|
|
128
|
+
aria-label="Next page"
|
|
129
|
+
>
|
|
130
|
+
<ChevronRight className="h-4 w-4" />
|
|
131
|
+
</Button>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
import { Badge } from "@nextblock-cms/ui";
|
|
2
|
-
import {
|
|
3
|
-
LIVE_STATUS,
|
|
4
|
-
resolveVisibilityState,
|
|
5
|
-
type PublishableType,
|
|
6
|
-
type VisibilityState,
|
|
7
|
-
} from "@nextblock-cms/utils";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Status badge for the CMS list views.
|
|
11
|
-
*
|
|
12
|
-
* Reads the same (status, published_at) pair as the editor's top-bar control, so a
|
|
13
|
-
* scheduled row is labelled "Scheduled" here instead of claiming to be published
|
|
14
|
-
* while its URL still 404s.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
const LABEL: Record<VisibilityState, string> = {
|
|
18
|
-
draft: "Draft",
|
|
19
|
-
scheduled: "Scheduled",
|
|
20
|
-
published: "Published",
|
|
21
|
-
archived: "Archived",
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const CLASS_NAME: Record<VisibilityState, string> = {
|
|
25
|
-
published:
|
|
26
|
-
"bg-green-100 text-green-700 dark:bg-green-700/30 dark:text-green-300 dark:border-green-700/50",
|
|
27
|
-
scheduled:
|
|
28
|
-
"bg-amber-100 text-amber-700 dark:bg-amber-700/30 dark:text-amber-300 dark:border-amber-700/50",
|
|
29
|
-
draft:
|
|
30
|
-
"bg-yellow-100 text-yellow-700 dark:bg-yellow-700/30 dark:text-yellow-300 dark:border-yellow-700/50",
|
|
31
|
-
archived:
|
|
32
|
-
"bg-slate-100 text-slate-700 dark:bg-slate-700/30 dark:text-slate-300 dark:border-slate-600",
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const VARIANT: Record<VisibilityState, "default" | "secondary" | "destructive"> = {
|
|
36
|
-
published: "default",
|
|
37
|
-
scheduled: "secondary",
|
|
38
|
-
draft: "secondary",
|
|
39
|
-
archived: "destructive",
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export default function VisibilityBadge({
|
|
43
|
-
type,
|
|
44
|
-
status,
|
|
45
|
-
publishedAt,
|
|
46
|
-
}: {
|
|
47
|
-
type: PublishableType;
|
|
48
|
-
status: string;
|
|
49
|
-
publishedAt?: string | null;
|
|
50
|
-
}) {
|
|
51
|
-
const state = resolveVisibilityState({
|
|
52
|
-
status,
|
|
53
|
-
publishedAt,
|
|
54
|
-
liveStatus: LIVE_STATUS[type],
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<Badge variant={VARIANT[state]} className={CLASS_NAME[state]}>
|
|
59
|
-
{LABEL[state]}
|
|
60
|
-
</Badge>
|
|
61
|
-
);
|
|
62
|
-
}
|
|
1
|
+
import { Badge } from "@nextblock-cms/ui";
|
|
2
|
+
import {
|
|
3
|
+
LIVE_STATUS,
|
|
4
|
+
resolveVisibilityState,
|
|
5
|
+
type PublishableType,
|
|
6
|
+
type VisibilityState,
|
|
7
|
+
} from "@nextblock-cms/utils";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Status badge for the CMS list views.
|
|
11
|
+
*
|
|
12
|
+
* Reads the same (status, published_at) pair as the editor's top-bar control, so a
|
|
13
|
+
* scheduled row is labelled "Scheduled" here instead of claiming to be published
|
|
14
|
+
* while its URL still 404s.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const LABEL: Record<VisibilityState, string> = {
|
|
18
|
+
draft: "Draft",
|
|
19
|
+
scheduled: "Scheduled",
|
|
20
|
+
published: "Published",
|
|
21
|
+
archived: "Archived",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const CLASS_NAME: Record<VisibilityState, string> = {
|
|
25
|
+
published:
|
|
26
|
+
"bg-green-100 text-green-700 dark:bg-green-700/30 dark:text-green-300 dark:border-green-700/50",
|
|
27
|
+
scheduled:
|
|
28
|
+
"bg-amber-100 text-amber-700 dark:bg-amber-700/30 dark:text-amber-300 dark:border-amber-700/50",
|
|
29
|
+
draft:
|
|
30
|
+
"bg-yellow-100 text-yellow-700 dark:bg-yellow-700/30 dark:text-yellow-300 dark:border-yellow-700/50",
|
|
31
|
+
archived:
|
|
32
|
+
"bg-slate-100 text-slate-700 dark:bg-slate-700/30 dark:text-slate-300 dark:border-slate-600",
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const VARIANT: Record<VisibilityState, "default" | "secondary" | "destructive"> = {
|
|
36
|
+
published: "default",
|
|
37
|
+
scheduled: "secondary",
|
|
38
|
+
draft: "secondary",
|
|
39
|
+
archived: "destructive",
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default function VisibilityBadge({
|
|
43
|
+
type,
|
|
44
|
+
status,
|
|
45
|
+
publishedAt,
|
|
46
|
+
}: {
|
|
47
|
+
type: PublishableType;
|
|
48
|
+
status: string;
|
|
49
|
+
publishedAt?: string | null;
|
|
50
|
+
}) {
|
|
51
|
+
const state = resolveVisibilityState({
|
|
52
|
+
status,
|
|
53
|
+
publishedAt,
|
|
54
|
+
liveStatus: LIVE_STATUS[type],
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<Badge variant={VARIANT[state]} className={CLASS_NAME[state]}>
|
|
59
|
+
{LABEL[state]}
|
|
60
|
+
</Badge>
|
|
61
|
+
);
|
|
62
|
+
}
|