create-nextblock 0.14.1 → 0.14.4
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 +23 -23
- package/docker-template/.env.docker.example +69 -69
- package/docker-template/docker/db/init/99-jwt.sql +6 -6
- package/docker-template/docker/db/init/99-roles.sql +25 -25
- package/docker-template/docker/kong/kong.yml +112 -112
- package/docker-template/scripts/docker-setup.mjs +310 -310
- 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 +1 -1
- package/project.json +19 -19
- package/templates/nextblock-template/.browserslistrc +11 -11
- package/templates/nextblock-template/.dockerignore +23 -23
- package/templates/nextblock-template/README.md +34 -34
- 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/(auth-pages)/sign-up/page.tsx +46 -46
- package/templates/nextblock-template/app/(auth-pages)/two-factor/page.tsx +51 -51
- package/templates/nextblock-template/app/ToasterProvider.tsx +17 -17
- package/templates/nextblock-template/app/[slug]/pageClientActions.ts +7 -7
- package/templates/nextblock-template/app/actions/consent.ts +57 -57
- package/templates/nextblock-template/app/actions/postActions.ts +146 -146
- package/templates/nextblock-template/app/actions/twoFactorEmail.ts +22 -22
- package/templates/nextblock-template/app/api/ai/cortex/build-widget/route.ts +153 -153
- package/templates/nextblock-template/app/api/ai/generate-blocks/route.ts +96 -96
- package/templates/nextblock-template/app/api/brand/email-logo/route.ts +48 -48
- package/templates/nextblock-template/app/api/cms/check-updates/route.ts +44 -44
- package/templates/nextblock-template/app/api/cms/full-backup/export/route.ts +33 -33
- package/templates/nextblock-template/app/api/cms/full-backup/restore/route.ts +63 -63
- package/templates/nextblock-template/app/api/cron/reset-sandbox/route.ts +3490 -3490
- package/templates/nextblock-template/app/api/cron/reset-sandbox/sandboxResetSql.ts +5881 -5623
- package/templates/nextblock-template/app/api/cron/sync-currencies/route.ts +39 -39
- package/templates/nextblock-template/app/api/custom-blocks/db-relations/route.ts +92 -92
- package/templates/nextblock-template/app/api/custom-blocks/editor-definitions/route.ts +43 -43
- package/templates/nextblock-template/app/api/media/library/route.ts +69 -69
- package/templates/nextblock-template/app/api/media/r2-presigned/route.ts +53 -53
- 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/article/[slug]/PostClientContent.tsx +441 -441
- 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/cms/CmsClientLayout.tsx +2 -2
- package/templates/nextblock-template/app/cms/blocks/components/ColumnEditor.tsx +17 -22
- package/templates/nextblock-template/app/cms/blocks/components/CustomBlockEditorPreview.tsx +160 -160
- package/templates/nextblock-template/app/cms/blocks/components/EditableBlock.tsx +13 -19
- package/templates/nextblock-template/app/cms/blocks/components/MediaLibraryModal.tsx +149 -149
- package/templates/nextblock-template/app/cms/blocks/editors/DynamicCustomBlockEditor.tsx +167 -167
- package/templates/nextblock-template/app/cms/blocks/editors/HeadingBlockEditor.tsx +45 -34
- package/templates/nextblock-template/app/cms/blocks/editors/ImageBlockEditor.tsx +4 -2
- package/templates/nextblock-template/app/cms/blocks/editors/TextBlockEditor.tsx +90 -90
- package/templates/nextblock-template/app/cms/components/ConnectGitHubButton.tsx +122 -122
- package/templates/nextblock-template/app/cms/components/CortexAiPageContext.tsx +58 -58
- package/templates/nextblock-template/app/cms/components/FeedbackModal.tsx +36 -36
- package/templates/nextblock-template/app/cms/components/SystemAlertsBanner.tsx +112 -112
- package/templates/nextblock-template/app/cms/components/TwoFactorReminderBanner.tsx +45 -45
- package/templates/nextblock-template/app/cms/components/github-connect-actions.ts +102 -102
- package/templates/nextblock-template/app/cms/components/system-alerts-actions.ts +31 -31
- package/templates/nextblock-template/app/cms/custom-blocks/[id]/edit/page.tsx +66 -66
- package/templates/nextblock-template/app/cms/custom-blocks/actions.ts +519 -519
- package/templates/nextblock-template/app/cms/custom-blocks/components/BlocksLibraryTransferControls.tsx +256 -256
- package/templates/nextblock-template/app/cms/custom-blocks/components/DBRelationSelect.tsx +384 -384
- package/templates/nextblock-template/app/cms/custom-blocks/components/ImageR2Picker.tsx +221 -221
- package/templates/nextblock-template/app/cms/custom-blocks/new/page.tsx +12 -12
- package/templates/nextblock-template/app/cms/custom-blocks/page.tsx +438 -438
- package/templates/nextblock-template/app/cms/dashboard/actions.ts +228 -228
- package/templates/nextblock-template/app/cms/dashboard/components/DashboardOnboarding.tsx +130 -130
- package/templates/nextblock-template/app/cms/import-export/actions.ts +226 -226
- package/templates/nextblock-template/app/cms/layout.tsx +73 -73
- 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/MediaEditForm.tsx +26 -26
- package/templates/nextblock-template/app/cms/media/components/MediaGridClient.tsx +69 -69
- package/templates/nextblock-template/app/cms/navigation/components/NavigationMenuDnd.tsx +3 -3
- package/templates/nextblock-template/app/cms/products/attributes/page.tsx +12 -12
- package/templates/nextblock-template/app/cms/products/categories/page.tsx +12 -12
- package/templates/nextblock-template/app/cms/products/inventory/page.tsx +13 -13
- package/templates/nextblock-template/app/cms/products/new/page.tsx +135 -135
- 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/promotions/PromotionsWorkspace.tsx +456 -456
- package/templates/nextblock-template/app/cms/promotions/actions.ts +115 -115
- package/templates/nextblock-template/app/cms/promotions/page.tsx +31 -31
- package/templates/nextblock-template/app/cms/revisions/service.ts +19 -19
- package/templates/nextblock-template/app/cms/revisions/utils.ts +132 -132
- package/templates/nextblock-template/app/cms/settings/backup-restore/BackupRestoreWorkspace.tsx +1004 -1004
- package/templates/nextblock-template/app/cms/settings/backup-restore/page.tsx +29 -29
- package/templates/nextblock-template/app/cms/settings/bot-protection/page.tsx +24 -24
- package/templates/nextblock-template/app/cms/settings/cortex-ai/SandboxCortexAiSettingsClient.tsx +688 -688
- 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/page.tsx +28 -28
- package/templates/nextblock-template/app/cms/settings/extra-translations/ExtraTranslationsWorkspace.tsx +767 -767
- 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 -0
- package/templates/nextblock-template/app/cms/settings/global-css/components/ThemeManager.tsx +267 -0
- package/templates/nextblock-template/app/cms/settings/global-css/page.tsx +40 -24
- package/templates/nextblock-template/app/cms/settings/global-css/theme-actions.ts +259 -0
- package/templates/nextblock-template/app/cms/settings/google-analytics/page.tsx +26 -26
- 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/components/DeleteLogoButton.tsx +21 -21
- package/templates/nextblock-template/app/cms/settings/logos/components/LogoForm.tsx +23 -21
- package/templates/nextblock-template/app/cms/settings/logos/components/SetActiveLogoButton.tsx +42 -42
- package/templates/nextblock-template/app/cms/settings/logos/components/SiteSeoSettingsForm.tsx +133 -133
- package/templates/nextblock-template/app/cms/settings/logos/new/page.tsx +8 -8
- package/templates/nextblock-template/app/cms/settings/packages/package-card.tsx +122 -122
- package/templates/nextblock-template/app/cms/settings/privacy/page.tsx +27 -27
- package/templates/nextblock-template/app/cms/settings/registration/page.tsx +27 -27
- package/templates/nextblock-template/app/cms/settings/security/components/SecurityPanel.tsx +9 -7
- package/templates/nextblock-template/app/cms/settings/security/page.tsx +33 -33
- 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 +49 -0
- package/templates/nextblock-template/app/lib/site-settings.ts +105 -105
- 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 +16 -4
- package/templates/nextblock-template/app/setup/SetupWizard.tsx +678 -678
- package/templates/nextblock-template/app/setup/layout.tsx +13 -13
- package/templates/nextblock-template/app/setup/page.tsx +111 -111
- package/templates/nextblock-template/app/sitemap.ts +130 -130
- package/templates/nextblock-template/components/CartDrawerLoader.tsx +7 -7
- package/templates/nextblock-template/components/DeferredCartDrawer.tsx +23 -23
- package/templates/nextblock-template/components/DeferredGoogleAnalytics.tsx +70 -70
- package/templates/nextblock-template/components/DeferredGoogleTagManager.tsx +70 -70
- package/templates/nextblock-template/components/DeferredSpeedInsights.tsx +69 -69
- package/templates/nextblock-template/components/FeatureImageHero.tsx +47 -47
- package/templates/nextblock-template/components/FooterNavigation.tsx +32 -32
- package/templates/nextblock-template/components/HtmlScriptExecutor.tsx +47 -47
- package/templates/nextblock-template/components/LanguageSwitcher.tsx +2 -2
- package/templates/nextblock-template/components/PublicEnvBootstrap.tsx +30 -30
- package/templates/nextblock-template/components/ResponsiveNav.tsx +14 -14
- package/templates/nextblock-template/components/auth/AuthBotProtection.tsx +182 -182
- 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/ecommerceRendererLoaders.ts +23 -23
- package/templates/nextblock-template/components/blocks/renderers/FormBlockRenderer.tsx +249 -249
- package/templates/nextblock-template/components/blocks/renderers/HeadingBlockRenderer.tsx +7 -10
- package/templates/nextblock-template/components/blocks/types.ts +7 -7
- 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/media/YouTubeFacade.tsx +105 -105
- package/templates/nextblock-template/components/media/youtube-embed-replace.tsx +32 -32
- package/templates/nextblock-template/components/privacy/ConsentBanner.tsx +170 -170
- package/templates/nextblock-template/components/privacy/ConsentGatedAnalytics.tsx +70 -70
- package/templates/nextblock-template/components/renderers/CachedDynamicLayoutEngine.tsx +28 -28
- package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.test.tsx +166 -166
- package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.tsx +471 -471
- package/templates/nextblock-template/components/submit-button.tsx +23 -23
- package/templates/nextblock-template/components/theme-icon.tsx +78 -0
- package/templates/nextblock-template/components/theme-switcher.tsx +77 -82
- package/templates/nextblock-template/components/visual-editing/DeferredVisualEditing.tsx +21 -21
- package/templates/nextblock-template/context/AuthContext.tsx +23 -23
- package/templates/nextblock-template/context/ThemeCatalogContext.tsx +44 -0
- package/templates/nextblock-template/context/language-rest-client.ts +32 -32
- package/templates/nextblock-template/docker/db/init/99-jwt.sql +6 -6
- package/templates/nextblock-template/docker/db/init/99-roles.sql +25 -25
- package/templates/nextblock-template/docker/kong/kong.yml +112 -112
- package/templates/nextblock-template/docs/01-PROJECT-OVERVIEW.md +94 -94
- package/templates/nextblock-template/docs/02-ECOMMERCE-CAPABILITIES.md +364 -364
- package/templates/nextblock-template/docs/03-CMS-AND-EDITOR.md +279 -202
- package/templates/nextblock-template/docs/04-DATABASE-AND-AUTH.md +246 -246
- package/templates/nextblock-template/docs/06-CLI-AND-SCAFFOLDING.md +176 -176
- package/templates/nextblock-template/docs/07-BLOCK-SDK-AND-EXTENSIBILITY.md +146 -146
- package/templates/nextblock-template/docs/10-CUSTOM-BLOCKS.md +222 -222
- package/templates/nextblock-template/docs/11-SELF-HOSTED-DOCKER.md +173 -173
- package/templates/nextblock-template/docs/12-VERCEL-DEPLOYMENT.md +170 -170
- package/templates/nextblock-template/docs/13-STAYING-UP-TO-DATE.md +151 -151
- package/templates/nextblock-template/docs/README.md +39 -39
- 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/app-secrets.ts +39 -39
- package/templates/nextblock-template/lib/auth/cookies.ts +47 -47
- package/templates/nextblock-template/lib/auth/crypto.ts +45 -45
- package/templates/nextblock-template/lib/auth/trustedDevices.ts +92 -92
- package/templates/nextblock-template/lib/auth-redirects.ts +46 -46
- package/templates/nextblock-template/lib/blocks/README.md +13 -13
- package/templates/nextblock-template/lib/blocks/blockColors.test.ts +114 -0
- package/templates/nextblock-template/lib/blocks/blockColors.ts +132 -0
- package/templates/nextblock-template/lib/blocks/blockRegistry.ts +17 -1
- package/templates/nextblock-template/lib/botProtection/verify.ts +134 -134
- package/templates/nextblock-template/lib/cms-transfer/server.ts +2243 -2243
- package/templates/nextblock-template/lib/cms-transfer/types.ts +145 -145
- package/templates/nextblock-template/lib/custom-block-definitions.ts +87 -87
- package/templates/nextblock-template/lib/custom-block-r2-upload-shared.ts +178 -178
- package/templates/nextblock-template/lib/custom-block-r2-upload.test.ts +140 -140
- package/templates/nextblock-template/lib/custom-block-r2-upload.ts +88 -88
- package/templates/nextblock-template/lib/custom-block-relations.test.ts +227 -227
- package/templates/nextblock-template/lib/custom-block-relations.ts +279 -279
- package/templates/nextblock-template/lib/custom-block-safelist.ts +14 -14
- package/templates/nextblock-template/lib/editor/dynamic-extension-core.test.ts +172 -172
- package/templates/nextblock-template/lib/editor/dynamic-extension-core.ts +213 -213
- package/templates/nextblock-template/lib/editor/dynamic-extension-loader.ts +22 -22
- package/templates/nextblock-template/lib/editor/dynamic-extensions.tsx +193 -193
- package/templates/nextblock-template/lib/email/branding-format.test.ts +133 -133
- package/templates/nextblock-template/lib/email/branding-format.ts +123 -123
- package/templates/nextblock-template/lib/email/branding.ts +76 -76
- package/templates/nextblock-template/lib/full-backup/manifest.test.ts +121 -121
- package/templates/nextblock-template/lib/full-backup/manifest.ts +206 -206
- package/templates/nextblock-template/lib/full-backup/server.ts +743 -743
- package/templates/nextblock-template/lib/logos/active-logo.ts +53 -53
- package/templates/nextblock-template/lib/media/resolveMediaUrl.ts +54 -54
- package/templates/nextblock-template/lib/media/youtube.ts +99 -99
- package/templates/nextblock-template/lib/onboarding/actions.ts +31 -31
- package/templates/nextblock-template/lib/onboarding/status.ts +222 -222
- package/templates/nextblock-template/lib/posts/readTime.ts +60 -60
- package/templates/nextblock-template/lib/privacy/consent-client.ts +57 -57
- package/templates/nextblock-template/lib/privacy/contact-emails.ts +64 -64
- package/templates/nextblock-template/lib/privacy/settings.ts +115 -115
- package/templates/nextblock-template/lib/privacy/types.ts +69 -69
- package/templates/nextblock-template/lib/promotions/server.test.ts +74 -74
- package/templates/nextblock-template/lib/promotions/server.ts +741 -741
- package/templates/nextblock-template/lib/resolve-block-relations.test.ts +142 -142
- package/templates/nextblock-template/lib/resolve-block-relations.ts +255 -255
- package/templates/nextblock-template/lib/search/types.ts +27 -27
- package/templates/nextblock-template/lib/setup/actions.ts +460 -460
- package/templates/nextblock-template/lib/setup/env-status.ts +125 -125
- package/templates/nextblock-template/lib/setup/env-write.ts +111 -111
- package/templates/nextblock-template/lib/setup/migrations-bundle.ts +15 -10
- package/templates/nextblock-template/lib/setup/provisioning.ts +59 -59
- package/templates/nextblock-template/lib/setup/schema-apply.ts +408 -408
- package/templates/nextblock-template/lib/setup/system-config.ts +105 -105
- package/templates/nextblock-template/lib/setup/types.ts +18 -18
- package/templates/nextblock-template/lib/site-url.ts +48 -48
- package/templates/nextblock-template/lib/storage/provider.ts +66 -66
- package/templates/nextblock-template/lib/storage/supabase-storage.ts +103 -103
- package/templates/nextblock-template/lib/themes/buildThemeCss.test.ts +163 -0
- package/templates/nextblock-template/lib/themes/buildThemeCss.ts +124 -0
- package/templates/nextblock-template/lib/themes/tokenColor.ts +31 -0
- package/templates/nextblock-template/lib/themes/tokens.ts +143 -0
- package/templates/nextblock-template/lib/updates/check-upstream.ts +441 -441
- package/templates/nextblock-template/lib/updates/github-device.ts +206 -206
- package/templates/nextblock-template/lib/updates/repo-identity.ts +56 -56
- package/templates/nextblock-template/next-env.d.ts +2 -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/docker-setup.mjs +310 -310
- package/templates/nextblock-template/scripts/restore.js +385 -385
- package/templates/nextblock-template/scripts/verify-cortex-ai-build-widget.tsx +98 -98
- package/templates/nextblock-template/scripts/verify-cortex-ai-generate-blocks.ts +62 -62
- package/templates/nextblock-template/scripts/verify-cortex-ai-global-tools.ts +537 -537
- package/templates/nextblock-template/scripts/verify-cortex-ai-routing.ts +58 -58
- package/templates/nextblock-template/scripts/verify-custom-block-definitions.ts +188 -188
- package/templates/nextblock-template/scripts/verify-dynamic-custom-block-extensions.ts +123 -123
- package/templates/nextblock-template/scripts/verify-dynamic-layout-engine.tsx +133 -133
- package/templates/nextblock-template/scripts/verify-milestone-2-custom-blocks.ts +65 -65
- package/templates/nextblock-template/scripts/verify-site-themes.ts +63 -0
- package/templates/nextblock-template/tailwind.config.js +25 -25
- package/templates/nextblock-template/tools/build-migrate.mjs +209 -209
- package/templates/nextblock-template/tools/configure-supabase-auth.js +282 -282
- package/templates/nextblock-template/tsconfig.tsbuildinfo +1 -1
- package/templates/nextblock-template/types/jsdom.d.ts +6 -6
- package/tsconfig.base.json +3 -3
|
@@ -2,31 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
import { DropdownMenuItem } from "@nextblock-cms/ui";
|
|
4
4
|
import { Trash2 } from "lucide-react";
|
|
5
|
-
import { deleteLogo } from "../actions";
|
|
6
|
-
import { useTransition, useState } from 'react';
|
|
7
|
-
import { ConfirmationModal } from '../../../components/ConfirmationModal';
|
|
8
|
-
import { toast } from 'react-hot-toast';
|
|
9
|
-
import { useRouter } from 'next/navigation';
|
|
5
|
+
import { deleteLogo } from "../actions";
|
|
6
|
+
import { useTransition, useState } from 'react';
|
|
7
|
+
import { ConfirmationModal } from '../../../components/ConfirmationModal';
|
|
8
|
+
import { toast } from 'react-hot-toast';
|
|
9
|
+
import { useRouter } from 'next/navigation';
|
|
10
10
|
|
|
11
11
|
interface DeleteLogoButtonProps {
|
|
12
12
|
logoId: string;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export default function DeleteLogoButton({ logoId }: DeleteLogoButtonProps) {
|
|
16
|
-
const router = useRouter();
|
|
17
|
-
const [isPending, startTransition] = useTransition();
|
|
18
|
-
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
15
|
+
export default function DeleteLogoButton({ logoId }: DeleteLogoButtonProps) {
|
|
16
|
+
const router = useRouter();
|
|
17
|
+
const [isPending, startTransition] = useTransition();
|
|
18
|
+
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
19
19
|
|
|
20
20
|
const handleDeleteConfirm = () => {
|
|
21
21
|
startTransition(async () => {
|
|
22
22
|
const result = await deleteLogo(logoId);
|
|
23
23
|
if (result?.error) {
|
|
24
24
|
toast.error(`Error: ${result.error}`);
|
|
25
|
-
} else {
|
|
26
|
-
toast.success("Logo deleted successfully");
|
|
27
|
-
router.refresh();
|
|
28
|
-
}
|
|
29
|
-
setIsModalOpen(false);
|
|
25
|
+
} else {
|
|
26
|
+
toast.success("Logo deleted successfully");
|
|
27
|
+
router.refresh();
|
|
28
|
+
}
|
|
29
|
+
setIsModalOpen(false);
|
|
30
30
|
});
|
|
31
31
|
};
|
|
32
32
|
|
|
@@ -41,13 +41,13 @@ export default function DeleteLogoButton({ logoId }: DeleteLogoButtonProps) {
|
|
|
41
41
|
<Trash2 className="mr-2 h-4 w-4" />
|
|
42
42
|
{isPending ? "Deleting..." : "Delete"}
|
|
43
43
|
</DropdownMenuItem>
|
|
44
|
-
<ConfirmationModal
|
|
45
|
-
isOpen={isModalOpen}
|
|
46
|
-
onClose={() => setIsModalOpen(false)}
|
|
47
|
-
onConfirm={handleDeleteConfirm}
|
|
48
|
-
title="Delete Brand Logo?"
|
|
49
|
-
description="This will permanently delete the logo. This action cannot be undone."
|
|
50
|
-
/>
|
|
44
|
+
<ConfirmationModal
|
|
45
|
+
isOpen={isModalOpen}
|
|
46
|
+
onClose={() => setIsModalOpen(false)}
|
|
47
|
+
onConfirm={handleDeleteConfirm}
|
|
48
|
+
title="Delete Brand Logo?"
|
|
49
|
+
description="This will permanently delete the logo. This action cannot be undone."
|
|
50
|
+
/>
|
|
51
51
|
</>
|
|
52
52
|
);
|
|
53
53
|
}
|
|
@@ -8,15 +8,15 @@ import { Label } from '@nextblock-cms/ui'
|
|
|
8
8
|
import { Button } from '@nextblock-cms/ui'
|
|
9
9
|
import { Alert, AlertDescription, Spinner } from '@nextblock-cms/ui'
|
|
10
10
|
import type { Database } from '@nextblock-cms/db'
|
|
11
|
-
import { ImageIcon, X as XIcon } from 'lucide-react'
|
|
12
|
-
import MediaPickerDialog from '../../../media/components/MediaPickerDialog'
|
|
13
|
-
import { useHotkeys } from '../../../../../hooks/use-hotkeys';
|
|
14
|
-
import { resolveMediaUrl } from '../../../../../lib/media/resolveMediaUrl';
|
|
15
|
-
type Media = Database['public']['Tables']['media']['Row'];
|
|
16
|
-
|
|
17
|
-
function resolveLogoSrc(objectKey?: string | null) {
|
|
18
|
-
return resolveMediaUrl(objectKey)
|
|
19
|
-
}
|
|
11
|
+
import { ImageIcon, X as XIcon } from 'lucide-react'
|
|
12
|
+
import MediaPickerDialog from '../../../media/components/MediaPickerDialog'
|
|
13
|
+
import { useHotkeys } from '../../../../../hooks/use-hotkeys';
|
|
14
|
+
import { resolveMediaUrl } from '../../../../../lib/media/resolveMediaUrl';
|
|
15
|
+
type Media = Database['public']['Tables']['media']['Row'];
|
|
16
|
+
|
|
17
|
+
function resolveLogoSrc(objectKey?: string | null) {
|
|
18
|
+
return resolveMediaUrl(objectKey)
|
|
19
|
+
}
|
|
20
20
|
|
|
21
21
|
interface LogoDetails {
|
|
22
22
|
id?: string
|
|
@@ -106,8 +106,8 @@ export default function LogoForm({ logo, action }: LogoFormProps) {
|
|
|
106
106
|
|
|
107
107
|
return (
|
|
108
108
|
<div className="space-y-6">
|
|
109
|
-
<div>
|
|
110
|
-
<Label htmlFor="name">Logo Name</Label>
|
|
109
|
+
<div>
|
|
110
|
+
<Label htmlFor="name">Logo Name</Label>
|
|
111
111
|
<Input
|
|
112
112
|
id="name"
|
|
113
113
|
name="name"
|
|
@@ -130,13 +130,15 @@ export default function LogoForm({ logo, action }: LogoFormProps) {
|
|
|
130
130
|
className="relative group inline-block"
|
|
131
131
|
style={{ maxWidth: logoDetails.width, maxHeight: 200 }}
|
|
132
132
|
>
|
|
133
|
-
<Image
|
|
134
|
-
src={resolveLogoSrc(logoDetails.object_key) || ''}
|
|
135
|
-
alt={logoDetails.name || 'Selected logo'}
|
|
136
|
-
width={logoDetails.width}
|
|
137
|
-
height={logoDetails.height}
|
|
133
|
+
<Image
|
|
134
|
+
src={resolveLogoSrc(logoDetails.object_key) || ''}
|
|
135
|
+
alt={logoDetails.name || 'Selected logo'}
|
|
136
|
+
width={logoDetails.width}
|
|
137
|
+
height={logoDetails.height}
|
|
138
138
|
className="rounded-md object-contain"
|
|
139
|
-
|
|
139
|
+
// width/height auto so the CSS max-height scales both axes and
|
|
140
|
+
// keeps the intrinsic aspect ratio (next/image warns otherwise)
|
|
141
|
+
style={{ width: 'auto', height: 'auto', maxWidth: '100%', maxHeight: '200px' }}
|
|
140
142
|
placeholder={logoDetails.blur_data_url ? 'blur' : 'empty'}
|
|
141
143
|
blurDataURL={logoDetails.blur_data_url || undefined}
|
|
142
144
|
/>
|
|
@@ -174,10 +176,10 @@ export default function LogoForm({ logo, action }: LogoFormProps) {
|
|
|
174
176
|
<>
|
|
175
177
|
<Spinner className="mr-2 h-4 w-4" /> Saving...
|
|
176
178
|
</>
|
|
177
|
-
) : (
|
|
178
|
-
`${logo ? 'Update' : 'Create'} Logo`
|
|
179
|
-
)}
|
|
180
|
-
</Button>
|
|
179
|
+
) : (
|
|
180
|
+
`${logo ? 'Update' : 'Create'} Logo`
|
|
181
|
+
)}
|
|
182
|
+
</Button>
|
|
181
183
|
{formError && (
|
|
182
184
|
<Alert variant="destructive" className="py-2 px-4 w-auto inline-flex items-center">
|
|
183
185
|
<AlertDescription>{formError}</AlertDescription>
|
package/templates/nextblock-template/app/cms/settings/logos/components/SetActiveLogoButton.tsx
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { DropdownMenuItem } from "@nextblock-cms/ui";
|
|
4
|
-
import { CheckCircle2 } from "lucide-react";
|
|
5
|
-
import { setActiveLogo } from "../actions";
|
|
6
|
-
import { useTransition } from "react";
|
|
7
|
-
import { toast } from "react-hot-toast";
|
|
8
|
-
import { useRouter } from "next/navigation";
|
|
9
|
-
|
|
10
|
-
interface SetActiveLogoButtonProps {
|
|
11
|
-
logoId: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export default function SetActiveLogoButton({ logoId }: SetActiveLogoButtonProps) {
|
|
15
|
-
const router = useRouter();
|
|
16
|
-
const [isPending, startTransition] = useTransition();
|
|
17
|
-
|
|
18
|
-
const handleSetActive = () => {
|
|
19
|
-
startTransition(async () => {
|
|
20
|
-
const result = await setActiveLogo(logoId);
|
|
21
|
-
if (result?.error) {
|
|
22
|
-
toast.error(`Error: ${result.error}`);
|
|
23
|
-
} else {
|
|
24
|
-
toast.success("Active logo updated");
|
|
25
|
-
router.refresh();
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
return (
|
|
31
|
-
<DropdownMenuItem
|
|
32
|
-
className="cursor-pointer"
|
|
33
|
-
// Keep the menu from closing before the transition starts.
|
|
34
|
-
onSelect={(e) => e.preventDefault()}
|
|
35
|
-
onClick={() => !isPending && handleSetActive()}
|
|
36
|
-
disabled={isPending}
|
|
37
|
-
>
|
|
38
|
-
<CheckCircle2 className="mr-2 h-4 w-4" />
|
|
39
|
-
{isPending ? "Setting active..." : "Set as active"}
|
|
40
|
-
</DropdownMenuItem>
|
|
41
|
-
);
|
|
42
|
-
}
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { DropdownMenuItem } from "@nextblock-cms/ui";
|
|
4
|
+
import { CheckCircle2 } from "lucide-react";
|
|
5
|
+
import { setActiveLogo } from "../actions";
|
|
6
|
+
import { useTransition } from "react";
|
|
7
|
+
import { toast } from "react-hot-toast";
|
|
8
|
+
import { useRouter } from "next/navigation";
|
|
9
|
+
|
|
10
|
+
interface SetActiveLogoButtonProps {
|
|
11
|
+
logoId: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default function SetActiveLogoButton({ logoId }: SetActiveLogoButtonProps) {
|
|
15
|
+
const router = useRouter();
|
|
16
|
+
const [isPending, startTransition] = useTransition();
|
|
17
|
+
|
|
18
|
+
const handleSetActive = () => {
|
|
19
|
+
startTransition(async () => {
|
|
20
|
+
const result = await setActiveLogo(logoId);
|
|
21
|
+
if (result?.error) {
|
|
22
|
+
toast.error(`Error: ${result.error}`);
|
|
23
|
+
} else {
|
|
24
|
+
toast.success("Active logo updated");
|
|
25
|
+
router.refresh();
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<DropdownMenuItem
|
|
32
|
+
className="cursor-pointer"
|
|
33
|
+
// Keep the menu from closing before the transition starts.
|
|
34
|
+
onSelect={(e) => e.preventDefault()}
|
|
35
|
+
onClick={() => !isPending && handleSetActive()}
|
|
36
|
+
disabled={isPending}
|
|
37
|
+
>
|
|
38
|
+
<CheckCircle2 className="mr-2 h-4 w-4" />
|
|
39
|
+
{isPending ? "Setting active..." : "Set as active"}
|
|
40
|
+
</DropdownMenuItem>
|
|
41
|
+
);
|
|
42
|
+
}
|
package/templates/nextblock-template/app/cms/settings/logos/components/SiteSeoSettingsForm.tsx
CHANGED
|
@@ -1,133 +1,133 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import { useState, useTransition } from 'react'
|
|
4
|
-
import { Button, Input, Label, Textarea } from '@nextblock-cms/ui'
|
|
5
|
-
|
|
6
|
-
import { saveSiteSeoSettings, type SiteSeoSettings } from '../actions'
|
|
7
|
-
|
|
8
|
-
interface SiteSeoSettingsFormProps {
|
|
9
|
-
initialSettings: SiteSeoSettings
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const TITLE_RECOMMENDED_MAX = 60
|
|
13
|
-
const DESCRIPTION_RECOMMENDED_MAX = 160
|
|
14
|
-
|
|
15
|
-
export default function SiteSeoSettingsForm({ initialSettings }: SiteSeoSettingsFormProps) {
|
|
16
|
-
const [isPending, startTransition] = useTransition()
|
|
17
|
-
const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null)
|
|
18
|
-
const [settings, setSettings] = useState<SiteSeoSettings>(() => ({
|
|
19
|
-
siteTitle: initialSettings.siteTitle ?? '',
|
|
20
|
-
siteDescription: initialSettings.siteDescription ?? '',
|
|
21
|
-
siteKeywords: initialSettings.siteKeywords ?? '',
|
|
22
|
-
}))
|
|
23
|
-
|
|
24
|
-
const handleSave = () => {
|
|
25
|
-
setMessage(null)
|
|
26
|
-
startTransition(async () => {
|
|
27
|
-
const result = await saveSiteSeoSettings(settings)
|
|
28
|
-
|
|
29
|
-
if (result?.error) {
|
|
30
|
-
setMessage({ type: 'error', text: result.error })
|
|
31
|
-
return
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
setMessage({ type: 'success', text: 'Site SEO settings updated successfully.' })
|
|
35
|
-
})
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<div className="space-y-6 rounded-xl border bg-background p-5">
|
|
40
|
-
<div className="space-y-1">
|
|
41
|
-
<h2 className="text-xl font-semibold">Site identity & SEO</h2>
|
|
42
|
-
<p className="text-sm text-muted-foreground">
|
|
43
|
-
Used for the browser tab, search results, and social link previews (Open Graph / Twitter).
|
|
44
|
-
The site title is also appended to every page title and shown next to the logo.
|
|
45
|
-
</p>
|
|
46
|
-
</div>
|
|
47
|
-
|
|
48
|
-
<div className="space-y-2">
|
|
49
|
-
<div className="flex items-center justify-between">
|
|
50
|
-
<Label htmlFor="seo-site-title">Site title</Label>
|
|
51
|
-
<span
|
|
52
|
-
className={`text-xs ${
|
|
53
|
-
settings.siteTitle.length > TITLE_RECOMMENDED_MAX
|
|
54
|
-
? 'text-amber-600'
|
|
55
|
-
: 'text-muted-foreground'
|
|
56
|
-
}`}
|
|
57
|
-
>
|
|
58
|
-
{settings.siteTitle.length}/{TITLE_RECOMMENDED_MAX}
|
|
59
|
-
</span>
|
|
60
|
-
</div>
|
|
61
|
-
<Input
|
|
62
|
-
id="seo-site-title"
|
|
63
|
-
placeholder="NextBlock™ CMS"
|
|
64
|
-
value={settings.siteTitle}
|
|
65
|
-
onChange={(event) =>
|
|
66
|
-
setSettings((current) => ({ ...current, siteTitle: event.target.value }))
|
|
67
|
-
}
|
|
68
|
-
/>
|
|
69
|
-
<p className="text-xs text-muted-foreground">
|
|
70
|
-
Example result: <span className="font-medium">Home | {settings.siteTitle || 'NextBlock™ CMS'}</span>
|
|
71
|
-
</p>
|
|
72
|
-
</div>
|
|
73
|
-
|
|
74
|
-
<div className="space-y-2">
|
|
75
|
-
<div className="flex items-center justify-between">
|
|
76
|
-
<Label htmlFor="seo-site-description">Default meta description</Label>
|
|
77
|
-
<span
|
|
78
|
-
className={`text-xs ${
|
|
79
|
-
settings.siteDescription.length > DESCRIPTION_RECOMMENDED_MAX
|
|
80
|
-
? 'text-amber-600'
|
|
81
|
-
: 'text-muted-foreground'
|
|
82
|
-
}`}
|
|
83
|
-
>
|
|
84
|
-
{settings.siteDescription.length}/{DESCRIPTION_RECOMMENDED_MAX}
|
|
85
|
-
</span>
|
|
86
|
-
</div>
|
|
87
|
-
<Textarea
|
|
88
|
-
id="seo-site-description"
|
|
89
|
-
rows={3}
|
|
90
|
-
placeholder="A short, compelling summary of your site for search engines and social cards."
|
|
91
|
-
value={settings.siteDescription}
|
|
92
|
-
onChange={(event) =>
|
|
93
|
-
setSettings((current) => ({ ...current, siteDescription: event.target.value }))
|
|
94
|
-
}
|
|
95
|
-
/>
|
|
96
|
-
<p className="text-xs text-muted-foreground">
|
|
97
|
-
Shown when a page has no description of its own. Aim for ~150–160 characters.
|
|
98
|
-
</p>
|
|
99
|
-
</div>
|
|
100
|
-
|
|
101
|
-
<div className="space-y-2">
|
|
102
|
-
<Label htmlFor="seo-site-keywords">Default keywords</Label>
|
|
103
|
-
<Input
|
|
104
|
-
id="seo-site-keywords"
|
|
105
|
-
placeholder="NextBlock, CMS, Next.js, Supabase"
|
|
106
|
-
value={settings.siteKeywords}
|
|
107
|
-
onChange={(event) =>
|
|
108
|
-
setSettings((current) => ({ ...current, siteKeywords: event.target.value }))
|
|
109
|
-
}
|
|
110
|
-
/>
|
|
111
|
-
<p className="text-xs text-muted-foreground">Comma-separated. Used as the default meta keywords.</p>
|
|
112
|
-
</div>
|
|
113
|
-
|
|
114
|
-
{message ? (
|
|
115
|
-
<div
|
|
116
|
-
className={`rounded-lg border px-4 py-3 text-sm ${
|
|
117
|
-
message.type === 'success'
|
|
118
|
-
? 'border-emerald-200 bg-emerald-50 text-emerald-700'
|
|
119
|
-
: 'border-red-200 bg-red-50 text-red-700'
|
|
120
|
-
}`}
|
|
121
|
-
>
|
|
122
|
-
{message.text}
|
|
123
|
-
</div>
|
|
124
|
-
) : null}
|
|
125
|
-
|
|
126
|
-
<div className="flex justify-end">
|
|
127
|
-
<Button type="button" onClick={handleSave} disabled={isPending}>
|
|
128
|
-
{isPending ? 'Saving...' : 'Save SEO Settings'}
|
|
129
|
-
</Button>
|
|
130
|
-
</div>
|
|
131
|
-
</div>
|
|
132
|
-
)
|
|
133
|
-
}
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useState, useTransition } from 'react'
|
|
4
|
+
import { Button, Input, Label, Textarea } from '@nextblock-cms/ui'
|
|
5
|
+
|
|
6
|
+
import { saveSiteSeoSettings, type SiteSeoSettings } from '../actions'
|
|
7
|
+
|
|
8
|
+
interface SiteSeoSettingsFormProps {
|
|
9
|
+
initialSettings: SiteSeoSettings
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const TITLE_RECOMMENDED_MAX = 60
|
|
13
|
+
const DESCRIPTION_RECOMMENDED_MAX = 160
|
|
14
|
+
|
|
15
|
+
export default function SiteSeoSettingsForm({ initialSettings }: SiteSeoSettingsFormProps) {
|
|
16
|
+
const [isPending, startTransition] = useTransition()
|
|
17
|
+
const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null)
|
|
18
|
+
const [settings, setSettings] = useState<SiteSeoSettings>(() => ({
|
|
19
|
+
siteTitle: initialSettings.siteTitle ?? '',
|
|
20
|
+
siteDescription: initialSettings.siteDescription ?? '',
|
|
21
|
+
siteKeywords: initialSettings.siteKeywords ?? '',
|
|
22
|
+
}))
|
|
23
|
+
|
|
24
|
+
const handleSave = () => {
|
|
25
|
+
setMessage(null)
|
|
26
|
+
startTransition(async () => {
|
|
27
|
+
const result = await saveSiteSeoSettings(settings)
|
|
28
|
+
|
|
29
|
+
if (result?.error) {
|
|
30
|
+
setMessage({ type: 'error', text: result.error })
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
setMessage({ type: 'success', text: 'Site SEO settings updated successfully.' })
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div className="space-y-6 rounded-xl border bg-background p-5">
|
|
40
|
+
<div className="space-y-1">
|
|
41
|
+
<h2 className="text-xl font-semibold">Site identity & SEO</h2>
|
|
42
|
+
<p className="text-sm text-muted-foreground">
|
|
43
|
+
Used for the browser tab, search results, and social link previews (Open Graph / Twitter).
|
|
44
|
+
The site title is also appended to every page title and shown next to the logo.
|
|
45
|
+
</p>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<div className="space-y-2">
|
|
49
|
+
<div className="flex items-center justify-between">
|
|
50
|
+
<Label htmlFor="seo-site-title">Site title</Label>
|
|
51
|
+
<span
|
|
52
|
+
className={`text-xs ${
|
|
53
|
+
settings.siteTitle.length > TITLE_RECOMMENDED_MAX
|
|
54
|
+
? 'text-amber-600'
|
|
55
|
+
: 'text-muted-foreground'
|
|
56
|
+
}`}
|
|
57
|
+
>
|
|
58
|
+
{settings.siteTitle.length}/{TITLE_RECOMMENDED_MAX}
|
|
59
|
+
</span>
|
|
60
|
+
</div>
|
|
61
|
+
<Input
|
|
62
|
+
id="seo-site-title"
|
|
63
|
+
placeholder="NextBlock™ CMS"
|
|
64
|
+
value={settings.siteTitle}
|
|
65
|
+
onChange={(event) =>
|
|
66
|
+
setSettings((current) => ({ ...current, siteTitle: event.target.value }))
|
|
67
|
+
}
|
|
68
|
+
/>
|
|
69
|
+
<p className="text-xs text-muted-foreground">
|
|
70
|
+
Example result: <span className="font-medium">Home | {settings.siteTitle || 'NextBlock™ CMS'}</span>
|
|
71
|
+
</p>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<div className="space-y-2">
|
|
75
|
+
<div className="flex items-center justify-between">
|
|
76
|
+
<Label htmlFor="seo-site-description">Default meta description</Label>
|
|
77
|
+
<span
|
|
78
|
+
className={`text-xs ${
|
|
79
|
+
settings.siteDescription.length > DESCRIPTION_RECOMMENDED_MAX
|
|
80
|
+
? 'text-amber-600'
|
|
81
|
+
: 'text-muted-foreground'
|
|
82
|
+
}`}
|
|
83
|
+
>
|
|
84
|
+
{settings.siteDescription.length}/{DESCRIPTION_RECOMMENDED_MAX}
|
|
85
|
+
</span>
|
|
86
|
+
</div>
|
|
87
|
+
<Textarea
|
|
88
|
+
id="seo-site-description"
|
|
89
|
+
rows={3}
|
|
90
|
+
placeholder="A short, compelling summary of your site for search engines and social cards."
|
|
91
|
+
value={settings.siteDescription}
|
|
92
|
+
onChange={(event) =>
|
|
93
|
+
setSettings((current) => ({ ...current, siteDescription: event.target.value }))
|
|
94
|
+
}
|
|
95
|
+
/>
|
|
96
|
+
<p className="text-xs text-muted-foreground">
|
|
97
|
+
Shown when a page has no description of its own. Aim for ~150–160 characters.
|
|
98
|
+
</p>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
<div className="space-y-2">
|
|
102
|
+
<Label htmlFor="seo-site-keywords">Default keywords</Label>
|
|
103
|
+
<Input
|
|
104
|
+
id="seo-site-keywords"
|
|
105
|
+
placeholder="NextBlock, CMS, Next.js, Supabase"
|
|
106
|
+
value={settings.siteKeywords}
|
|
107
|
+
onChange={(event) =>
|
|
108
|
+
setSettings((current) => ({ ...current, siteKeywords: event.target.value }))
|
|
109
|
+
}
|
|
110
|
+
/>
|
|
111
|
+
<p className="text-xs text-muted-foreground">Comma-separated. Used as the default meta keywords.</p>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
{message ? (
|
|
115
|
+
<div
|
|
116
|
+
className={`rounded-lg border px-4 py-3 text-sm ${
|
|
117
|
+
message.type === 'success'
|
|
118
|
+
? 'border-emerald-200 bg-emerald-50 text-emerald-700'
|
|
119
|
+
: 'border-red-200 bg-red-50 text-red-700'
|
|
120
|
+
}`}
|
|
121
|
+
>
|
|
122
|
+
{message.text}
|
|
123
|
+
</div>
|
|
124
|
+
) : null}
|
|
125
|
+
|
|
126
|
+
<div className="flex justify-end">
|
|
127
|
+
<Button type="button" onClick={handleSave} disabled={isPending}>
|
|
128
|
+
{isPending ? 'Saving...' : 'Save SEO Settings'}
|
|
129
|
+
</Button>
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
)
|
|
133
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import LogoForm from '../components/LogoForm'
|
|
2
2
|
import { createLogo } from '../actions'
|
|
3
3
|
|
|
4
|
-
export default function NewLogoPage() {
|
|
5
|
-
return (
|
|
6
|
-
<div>
|
|
7
|
-
<h1 className="text-2xl font-semibold mb-6">Add Brand Logo</h1>
|
|
8
|
-
<LogoForm action={createLogo} />
|
|
9
|
-
</div>
|
|
10
|
-
)
|
|
11
|
-
}
|
|
4
|
+
export default function NewLogoPage() {
|
|
5
|
+
return (
|
|
6
|
+
<div>
|
|
7
|
+
<h1 className="text-2xl font-semibold mb-6">Add Brand Logo</h1>
|
|
8
|
+
<LogoForm action={createLogo} />
|
|
9
|
+
</div>
|
|
10
|
+
)
|
|
11
|
+
}
|