@xiwebdesign/xicms-core 7.31.0 → 8.16.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/XiCMSProvider.js +23 -7
- package/dist/XiCMSProvider.js.map +1 -1
- package/dist/admin/AdminApp.js +175 -93
- package/dist/admin/AdminApp.js.map +1 -1
- package/dist/admin/AdminHelp.d.ts +1 -1
- package/dist/admin/AdminHelp.js +44 -36
- package/dist/admin/AdminHelp.js.map +1 -1
- package/dist/admin/CoreVersion.d.ts +6 -3
- package/dist/admin/CoreVersion.js +60 -24
- package/dist/admin/CoreVersion.js.map +1 -1
- package/dist/admin/NewsEditor.d.ts +7 -0
- package/dist/admin/NewsEditor.js +117 -75
- package/dist/admin/NewsEditor.js.map +1 -1
- package/dist/admin/SuperadminPanel.js +1 -1
- package/dist/admin/SuperadminPanel.js.map +1 -1
- package/dist/admin/ZoekPalet.d.ts +15 -0
- package/dist/admin/ZoekPalet.js +123 -0
- package/dist/admin/ZoekPalet.js.map +1 -0
- package/dist/admin/blockEditors/GenericEditor.js +36 -18
- package/dist/admin/blockEditors/GenericEditor.js.map +1 -1
- package/dist/admin/blockEditors/StyleEditor.js +37 -3
- package/dist/admin/blockEditors/StyleEditor.js.map +1 -1
- package/dist/admin/blockEditors/SymbolRefEditor.js +44 -2
- package/dist/admin/blockEditors/SymbolRefEditor.js.map +1 -1
- package/dist/admin/blockEditors/index.js +154 -73
- package/dist/admin/blockEditors/index.js.map +1 -1
- package/dist/admin/customBlocks/CustomBlocksPanel.js +18 -7
- package/dist/admin/customBlocks/CustomBlocksPanel.js.map +1 -1
- package/dist/admin/dashboard/DashboardPanel.js +26 -16
- package/dist/admin/dashboard/DashboardPanel.js.map +1 -1
- package/dist/admin/editors/RichTextEditor.d.ts +4 -3
- package/dist/admin/editors/RichTextEditor.js +19 -60
- package/dist/admin/editors/RichTextEditor.js.map +1 -1
- package/dist/admin/editors/fontSizeExtension.js +7 -1
- package/dist/admin/editors/fontSizeExtension.js.map +1 -1
- package/dist/admin/editors/slashMenu.d.ts +18 -0
- package/dist/admin/editors/slashMenu.js +34 -0
- package/dist/admin/editors/slashMenu.js.map +1 -0
- package/dist/admin/editors/useRijkeTekst.d.ts +48 -0
- package/dist/admin/editors/useRijkeTekst.js +310 -0
- package/dist/admin/editors/useRijkeTekst.js.map +1 -0
- package/dist/admin/forms/FormsPanel.d.ts +11 -2
- package/dist/admin/forms/FormsPanel.js +218 -65
- package/dist/admin/forms/FormsPanel.js.map +1 -1
- package/dist/admin/lib/blokInfo.d.ts +17 -0
- package/dist/admin/lib/blokInfo.js +80 -0
- package/dist/admin/lib/blokInfo.js.map +1 -0
- package/dist/admin/lib/foutNaarMens.d.ts +1 -0
- package/dist/admin/lib/foutNaarMens.js +22 -0
- package/dist/admin/lib/foutNaarMens.js.map +1 -0
- package/dist/admin/lib/gewisteVelden.d.ts +13 -0
- package/dist/admin/lib/gewisteVelden.js +31 -0
- package/dist/admin/lib/gewisteVelden.js.map +1 -0
- package/dist/admin/lib/heroHulp.d.ts +11 -0
- package/dist/admin/lib/heroHulp.js +18 -0
- package/dist/admin/lib/heroHulp.js.map +1 -0
- package/dist/admin/lib/kleur.js +2 -3
- package/dist/admin/lib/kleur.js.map +1 -1
- package/dist/admin/lib/leesbaarheid.d.ts +34 -0
- package/dist/admin/lib/leesbaarheid.js +82 -0
- package/dist/admin/lib/leesbaarheid.js.map +1 -0
- package/dist/admin/lib/lengteAdvies.d.ts +1 -0
- package/dist/admin/lib/lengteAdvies.js +16 -0
- package/dist/admin/lib/lengteAdvies.js.map +1 -0
- package/dist/admin/lib/mediaLijst.d.ts +26 -0
- package/dist/admin/lib/mediaLijst.js +42 -0
- package/dist/admin/lib/mediaLijst.js.map +1 -0
- package/dist/admin/lib/mediaUsage.d.ts +12 -1
- package/dist/admin/lib/mediaUsage.js +43 -33
- package/dist/admin/lib/mediaUsage.js.map +1 -1
- package/dist/admin/lib/menuHulp.d.ts +16 -0
- package/dist/admin/lib/menuHulp.js +41 -0
- package/dist/admin/lib/menuHulp.js.map +1 -0
- package/dist/admin/lib/onopgeslagen.d.ts +10 -0
- package/dist/admin/lib/onopgeslagen.js +35 -0
- package/dist/admin/lib/onopgeslagen.js.map +1 -0
- package/dist/admin/lib/pagesClient.d.ts +55 -2
- package/dist/admin/lib/pagesClient.js +126 -28
- package/dist/admin/lib/pagesClient.js.map +1 -1
- package/dist/admin/lib/paginaGebruik.d.ts +56 -0
- package/dist/admin/lib/paginaGebruik.js +109 -0
- package/dist/admin/lib/paginaGebruik.js.map +1 -0
- package/dist/admin/lib/publicatieCheck.d.ts +25 -0
- package/dist/admin/lib/publicatieCheck.js +114 -0
- package/dist/admin/lib/publicatieCheck.js.map +1 -0
- package/dist/admin/lib/scrollNaarDetail.d.ts +6 -0
- package/dist/admin/lib/scrollNaarDetail.js +20 -0
- package/dist/admin/lib/scrollNaarDetail.js.map +1 -0
- package/dist/admin/lib/symbolsClient.d.ts +10 -0
- package/dist/admin/lib/symbolsClient.js +14 -1
- package/dist/admin/lib/symbolsClient.js.map +1 -1
- package/dist/admin/lib/tekstVeld.d.ts +8 -0
- package/dist/admin/lib/tekstVeld.js +10 -0
- package/dist/admin/lib/tekstVeld.js.map +1 -0
- package/dist/admin/lib/useIsSuperadmin.d.ts +2 -0
- package/dist/admin/lib/useIsSuperadmin.js +13 -0
- package/dist/admin/lib/useIsSuperadmin.js.map +1 -0
- package/dist/admin/lib/veldTaal.d.ts +14 -0
- package/dist/admin/lib/veldTaal.js +248 -0
- package/dist/admin/lib/veldTaal.js.map +1 -0
- package/dist/admin/lib/versieVergelijk.d.ts +17 -0
- package/dist/admin/lib/versieVergelijk.js +24 -0
- package/dist/admin/lib/versieVergelijk.js.map +1 -0
- package/dist/admin/lib/zodFields.js +22 -4
- package/dist/admin/lib/zodFields.js.map +1 -1
- package/dist/admin/lib/zodFout.d.ts +9 -0
- package/dist/admin/lib/zodFout.js +63 -0
- package/dist/admin/lib/zodFout.js.map +1 -0
- package/dist/admin/media/MediaManager.js +162 -32
- package/dist/admin/media/MediaManager.js.map +1 -1
- package/dist/admin/media/MediaPicker.d.ts +3 -0
- package/dist/admin/media/MediaPicker.js +84 -31
- package/dist/admin/media/MediaPicker.js.map +1 -1
- package/dist/admin/menu/MenuPanel.js +144 -83
- package/dist/admin/menu/MenuPanel.js.map +1 -1
- package/dist/admin/navContext.d.ts +3 -0
- package/dist/admin/navContext.js +13 -1
- package/dist/admin/navContext.js.map +1 -1
- package/dist/admin/pages/PageEditor.js +146 -30
- package/dist/admin/pages/PageEditor.js.map +1 -1
- package/dist/admin/pages/PagesPanel.js +215 -61
- package/dist/admin/pages/PagesPanel.js.map +1 -1
- package/dist/admin/pages/StarterKiezer.d.ts +12 -0
- package/dist/admin/pages/StarterKiezer.js +113 -0
- package/dist/admin/pages/StarterKiezer.js.map +1 -0
- package/dist/admin/panelRegistry.d.ts +1 -1
- package/dist/admin/panelRegistry.js +2 -1
- package/dist/admin/panelRegistry.js.map +1 -1
- package/dist/admin/patterns/PatternInserter.js +1 -1
- package/dist/admin/patterns/PatternInserter.js.map +1 -1
- package/dist/admin/settings/BedrijfInstellingen.d.ts +20 -0
- package/dist/admin/settings/BedrijfInstellingen.js +159 -0
- package/dist/admin/settings/BedrijfInstellingen.js.map +1 -0
- package/dist/admin/settings/MailTemplates.js +5 -4
- package/dist/admin/settings/MailTemplates.js.map +1 -1
- package/dist/admin/settings/SettingsPanel.js +120 -78
- package/dist/admin/settings/SettingsPanel.js.map +1 -1
- package/dist/admin/settings/SnapshotsCard.js +4 -4
- package/dist/admin/settings/SnapshotsCard.js.map +1 -1
- package/dist/admin/settings/VorigeTerugzetten.d.ts +15 -0
- package/dist/admin/settings/VorigeTerugzetten.js +89 -0
- package/dist/admin/settings/VorigeTerugzetten.js.map +1 -0
- package/dist/admin/shop/CategoriesTab.js +6 -4
- package/dist/admin/shop/CategoriesTab.js.map +1 -1
- package/dist/admin/shop/DiscountsTab.js +4 -2
- package/dist/admin/shop/DiscountsTab.js.map +1 -1
- package/dist/admin/shop/OrdersTab.js +57 -19
- package/dist/admin/shop/OrdersTab.js.map +1 -1
- package/dist/admin/shop/ProductPaneel.js +2 -1
- package/dist/admin/shop/ProductPaneel.js.map +1 -1
- package/dist/admin/shop/ProductsTab.js +40 -19
- package/dist/admin/shop/ProductsTab.js.map +1 -1
- package/dist/admin/shop/ShopPanel.js +13 -1
- package/dist/admin/shop/ShopPanel.js.map +1 -1
- package/dist/admin/shop/ShopSettingsTab.js +56 -17
- package/dist/admin/shop/ShopSettingsTab.js.map +1 -1
- package/dist/admin/shop/productClient.js +7 -3
- package/dist/admin/shop/productClient.js.map +1 -1
- package/dist/admin/stats/NietGevonden.d.ts +10 -0
- package/dist/admin/stats/NietGevonden.js +78 -0
- package/dist/admin/stats/NietGevonden.js.map +1 -0
- package/dist/admin/stats/StatsPanel.js +6 -1
- package/dist/admin/stats/StatsPanel.js.map +1 -1
- package/dist/admin/stats/lib.d.ts +2 -0
- package/dist/admin/stats/lib.js.map +1 -1
- package/dist/admin/ui/ConfirmDialog.js +10 -1
- package/dist/admin/ui/ConfirmDialog.js.map +1 -1
- package/dist/admin/ui/Icon.d.ts +34 -0
- package/dist/admin/ui/Icon.js +44 -0
- package/dist/admin/ui/Icon.js.map +1 -0
- package/dist/admin/ui/ImageField.d.ts +15 -0
- package/dist/admin/ui/ImageField.js +67 -0
- package/dist/admin/ui/ImageField.js.map +1 -0
- package/dist/admin/ui/KleurVeld.d.ts +25 -0
- package/dist/admin/ui/KleurVeld.js +76 -0
- package/dist/admin/ui/KleurVeld.js.map +1 -0
- package/dist/admin/ui/LaadStaat.d.ts +21 -0
- package/dist/admin/ui/LaadStaat.js +43 -0
- package/dist/admin/ui/LaadStaat.js.map +1 -0
- package/dist/admin/ui/LeesbaarheidPaneel.d.ts +10 -0
- package/dist/admin/ui/LeesbaarheidPaneel.js +68 -0
- package/dist/admin/ui/LeesbaarheidPaneel.js.map +1 -0
- package/dist/admin/ui/LinkDialog.d.ts +22 -0
- package/dist/admin/ui/LinkDialog.js +131 -0
- package/dist/admin/ui/LinkDialog.js.map +1 -0
- package/dist/admin/ui/LinkVeld.d.ts +14 -0
- package/dist/admin/ui/LinkVeld.js +49 -0
- package/dist/admin/ui/LinkVeld.js.map +1 -0
- package/dist/admin/ui/PreviewLinkResultaat.d.ts +14 -0
- package/dist/admin/ui/PreviewLinkResultaat.js +52 -0
- package/dist/admin/ui/PreviewLinkResultaat.js.map +1 -0
- package/dist/admin/ui/charts.js +5 -5
- package/dist/admin/ui/charts.js.map +1 -1
- package/dist/admin/ui/primitives.d.ts +16 -6
- package/dist/admin/ui/primitives.js +98 -26
- package/dist/admin/ui/primitives.js.map +1 -1
- package/dist/admin/ui/select.js +5 -2
- package/dist/admin/ui/select.js.map +1 -1
- package/dist/admin/ui/switch.d.ts +3 -1
- package/dist/admin/ui/switch.js +6 -3
- package/dist/admin/ui/switch.js.map +1 -1
- package/dist/admin/ui/toast.d.ts +2 -1
- package/dist/admin/ui/toast.js +17 -11
- package/dist/admin/ui/toast.js.map +1 -1
- package/dist/admin/visual/BlokKiezer.d.ts +34 -0
- package/dist/admin/visual/BlokKiezer.js +225 -0
- package/dist/admin/visual/BlokKiezer.js.map +1 -0
- package/dist/admin/visual/InlineGereedschap.d.ts +52 -0
- package/dist/admin/visual/InlineGereedschap.js +356 -0
- package/dist/admin/visual/InlineGereedschap.js.map +1 -0
- package/dist/admin/visual/InlineRijkeTekst.d.ts +23 -0
- package/dist/admin/visual/InlineRijkeTekst.js +152 -0
- package/dist/admin/visual/InlineRijkeTekst.js.map +1 -0
- package/dist/admin/visual/VisualEditor.js +273 -125
- package/dist/admin/visual/VisualEditor.js.map +1 -1
- package/dist/admin.css +1 -1
- package/dist/auth/AuthProvider.js +1 -0
- package/dist/auth/AuthProvider.js.map +1 -1
- package/dist/bedrijf/bedrijf.d.ts +44 -0
- package/dist/bedrijf/bedrijf.js +125 -0
- package/dist/bedrijf/bedrijf.js.map +1 -0
- package/dist/blocks/BlockRenderer.js +11 -1
- package/dist/blocks/BlockRenderer.js.map +1 -1
- package/dist/blocks/blockStyle.d.ts +7 -0
- package/dist/blocks/blockStyle.js +16 -3
- package/dist/blocks/blockStyle.js.map +1 -1
- package/dist/blocks/builtinSchemas.js +6 -0
- package/dist/blocks/builtinSchemas.js.map +1 -1
- package/dist/blocks/builtins/AgendaRender.d.ts +22 -0
- package/dist/blocks/builtins/AgendaRender.js +69 -9
- package/dist/blocks/builtins/AgendaRender.js.map +1 -1
- package/dist/blocks/builtins/Availability.d.ts +1 -0
- package/dist/blocks/builtins/Availability.js +23 -0
- package/dist/blocks/builtins/Availability.js.map +1 -0
- package/dist/blocks/builtins/AvailabilityRender.d.ts +12 -0
- package/dist/blocks/builtins/AvailabilityRender.js +105 -0
- package/dist/blocks/builtins/AvailabilityRender.js.map +1 -0
- package/dist/blocks/builtins/BeforeAfterRender.js +4 -3
- package/dist/blocks/builtins/BeforeAfterRender.js.map +1 -1
- package/dist/blocks/builtins/Booking.js +1 -1
- package/dist/blocks/builtins/Booking.js.map +1 -1
- package/dist/blocks/builtins/BreadcrumbsRender.d.ts +4 -3
- package/dist/blocks/builtins/BreadcrumbsRender.js +14 -8
- package/dist/blocks/builtins/BreadcrumbsRender.js.map +1 -1
- package/dist/blocks/builtins/ColumnsRender.d.ts +1 -1
- package/dist/blocks/builtins/ColumnsRender.js +3 -1
- package/dist/blocks/builtins/ColumnsRender.js.map +1 -1
- package/dist/blocks/builtins/Contact.js +1 -1
- package/dist/blocks/builtins/Contact.js.map +1 -1
- package/dist/blocks/builtins/ContactRender.d.ts +1 -1
- package/dist/blocks/builtins/ContactRender.js +37 -8
- package/dist/blocks/builtins/ContactRender.js.map +1 -1
- package/dist/blocks/builtins/Cta.js +1 -1
- package/dist/blocks/builtins/Cta.js.map +1 -1
- package/dist/blocks/builtins/CtaRender.d.ts +1 -1
- package/dist/blocks/builtins/CtaRender.js +5 -4
- package/dist/blocks/builtins/CtaRender.js.map +1 -1
- package/dist/blocks/builtins/Embed.js +1 -1
- package/dist/blocks/builtins/Embed.js.map +1 -1
- package/dist/blocks/builtins/FormBlock.js +1 -0
- package/dist/blocks/builtins/FormBlock.js.map +1 -1
- package/dist/blocks/builtins/FormBlockRender.d.ts +6 -0
- package/dist/blocks/builtins/FormBlockRender.js +88 -16
- package/dist/blocks/builtins/FormBlockRender.js.map +1 -1
- package/dist/blocks/builtins/GalleryRender.js +3 -2
- package/dist/blocks/builtins/GalleryRender.js.map +1 -1
- package/dist/blocks/builtins/Hero.js +1 -1
- package/dist/blocks/builtins/Hero.js.map +1 -1
- package/dist/blocks/builtins/HeroRender.js +7 -3
- package/dist/blocks/builtins/HeroRender.js.map +1 -1
- package/dist/blocks/builtins/OpenNowBadge.d.ts +4 -2
- package/dist/blocks/builtins/OpenNowBadge.js +6 -6
- package/dist/blocks/builtins/OpenNowBadge.js.map +1 -1
- package/dist/blocks/builtins/OpeningHoursRender.d.ts +8 -2
- package/dist/blocks/builtins/OpeningHoursRender.js +27 -6
- package/dist/blocks/builtins/OpeningHoursRender.js.map +1 -1
- package/dist/blocks/builtins/PriceList.d.ts +1 -0
- package/dist/blocks/builtins/PriceList.js +25 -0
- package/dist/blocks/builtins/PriceList.js.map +1 -0
- package/dist/blocks/builtins/PriceListRender.d.ts +17 -0
- package/dist/blocks/builtins/PriceListRender.js +87 -0
- package/dist/blocks/builtins/PriceListRender.js.map +1 -0
- package/dist/blocks/builtins/RichTextBlockRender.js +6 -1
- package/dist/blocks/builtins/RichTextBlockRender.js.map +1 -1
- package/dist/blocks/builtins/SectionHeading.d.ts +1 -0
- package/dist/blocks/builtins/SectionHeading.js +14 -0
- package/dist/blocks/builtins/SectionHeading.js.map +1 -0
- package/dist/blocks/builtins/SectionHeadingRender.d.ts +7 -0
- package/dist/blocks/builtins/SectionHeadingRender.js +14 -0
- package/dist/blocks/builtins/SectionHeadingRender.js.map +1 -0
- package/dist/blocks/builtins/SliderRender.js +3 -2
- package/dist/blocks/builtins/SliderRender.js.map +1 -1
- package/dist/blocks/builtins/SymbolRef.js +1 -1
- package/dist/blocks/builtins/SymbolRef.js.map +1 -1
- package/dist/blocks/builtins/TeamRender.js +6 -1
- package/dist/blocks/builtins/TeamRender.js.map +1 -1
- package/dist/blocks/builtins/Testimonials.js +3 -1
- package/dist/blocks/builtins/Testimonials.js.map +1 -1
- package/dist/blocks/builtins/TestimonialsRender.js +4 -0
- package/dist/blocks/builtins/TestimonialsRender.js.map +1 -1
- package/dist/blocks/builtins/WhatsappChatRender.d.ts +1 -1
- package/dist/blocks/builtins/WhatsappChatRender.js +3 -1
- package/dist/blocks/builtins/WhatsappChatRender.js.map +1 -1
- package/dist/blocks/builtins/Widgets.js +2 -2
- package/dist/blocks/builtins/Widgets.js.map +1 -1
- package/dist/blocks/builtins/WidgetsRender.js +3 -1
- package/dist/blocks/builtins/WidgetsRender.js.map +1 -1
- package/dist/blocks/builtins/consentEmbed.js +26 -9
- package/dist/blocks/builtins/consentEmbed.js.map +1 -1
- package/dist/blocks/builtins/index.d.ts +3 -0
- package/dist/blocks/builtins/index.js +6 -0
- package/dist/blocks/builtins/index.js.map +1 -1
- package/dist/blocks/builtins/lib/autoComplete.d.ts +7 -0
- package/dist/blocks/builtins/lib/autoComplete.js +20 -0
- package/dist/blocks/builtins/lib/autoComplete.js.map +1 -0
- package/dist/blocks/builtins/lib/bookingUrl.d.ts +2 -2
- package/dist/blocks/builtins/lib/bookingUrl.js +1 -1
- package/dist/blocks/builtins/lib/bookingUrl.js.map +1 -1
- package/dist/blocks/builtins/lib/ical.d.ts +24 -0
- package/dist/blocks/builtins/lib/ical.js +82 -0
- package/dist/blocks/builtins/lib/ical.js.map +1 -0
- package/dist/blocks/builtins/lib/vandaag.d.ts +8 -0
- package/dist/blocks/builtins/lib/vandaag.js +22 -0
- package/dist/blocks/builtins/lib/vandaag.js.map +1 -0
- package/dist/blocks/registry.d.ts +6 -0
- package/dist/blocks/registry.js.map +1 -1
- package/dist/blocks/ui/index.js +1 -0
- package/dist/blocks/ui/index.js.map +1 -1
- package/dist/components/EditBar.js +2 -4
- package/dist/components/EditBar.js.map +1 -1
- package/dist/components/News.js +26 -18
- package/dist/components/News.js.map +1 -1
- package/dist/components/PageView.d.ts +7 -1
- package/dist/components/PageView.js +17 -0
- package/dist/components/PageView.js.map +1 -1
- package/dist/components/ResponsiveImage.js +18 -20
- package/dist/components/ResponsiveImage.js.map +1 -1
- package/dist/components/onderOffset.d.ts +13 -0
- package/dist/components/onderOffset.js +74 -0
- package/dist/components/onderOffset.js.map +1 -0
- package/dist/components/site/Bedrijfsnummers.d.ts +9 -0
- package/dist/components/site/Bedrijfsnummers.js +12 -0
- package/dist/components/site/Bedrijfsnummers.js.map +1 -0
- package/dist/components/site/SiteFooter.d.ts +6 -1
- package/dist/components/site/SiteFooter.js +62 -9
- package/dist/components/site/SiteFooter.js.map +1 -1
- package/dist/components/site/SiteHeader.d.ts +15 -0
- package/dist/components/site/SiteHeader.js +70 -0
- package/dist/components/site/SiteHeader.js.map +1 -0
- package/dist/components/site/SiteNav.d.ts +2 -0
- package/dist/components/site/SiteNav.js +29 -5
- package/dist/components/site/SiteNav.js.map +1 -1
- package/dist/demo/DemoStudio.js +2 -2
- package/dist/demo/DemoStudio.js.map +1 -1
- package/dist/demo/demoStore.d.ts +13 -0
- package/dist/demo/demoStore.js +36 -0
- package/dist/demo/demoStore.js.map +1 -1
- package/dist/editor/EditorProvider.js +15 -4
- package/dist/editor/EditorProvider.js.map +1 -1
- package/dist/firebase/functionsClient.js +5 -1
- package/dist/firebase/functionsClient.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +20 -1
- package/dist/index.js.map +1 -1
- package/dist/media/ImageContext.d.ts +17 -0
- package/dist/media/ImageContext.js +65 -20
- package/dist/media/ImageContext.js.map +1 -1
- package/dist/media/altInHtml.d.ts +9 -0
- package/dist/media/altInHtml.js +17 -0
- package/dist/media/altInHtml.js.map +1 -0
- package/dist/media/srcset.d.ts +12 -0
- package/dist/media/srcset.js +13 -0
- package/dist/media/srcset.js.map +1 -0
- package/dist/modules/builtins.d.ts +1 -0
- package/dist/modules/builtins.js +22 -9
- package/dist/modules/builtins.js.map +1 -1
- package/dist/modules/consent/ConsentBanner.d.ts +5 -0
- package/dist/modules/consent/ConsentBanner.js +8 -7
- package/dist/modules/consent/ConsentBanner.js.map +1 -1
- package/dist/modules/consent/standaard.d.ts +12 -0
- package/dist/modules/consent/standaard.js +10 -0
- package/dist/modules/consent/standaard.js.map +1 -0
- package/dist/modules/consent/useConsent.d.ts +4 -0
- package/dist/modules/consent/useConsent.js +30 -1
- package/dist/modules/consent/useConsent.js.map +1 -1
- package/dist/modules/shop/blocks/Cart.js +5 -3
- package/dist/modules/shop/blocks/Cart.js.map +1 -1
- package/dist/modules/shop/blocks/Checkout.js +56 -35
- package/dist/modules/shop/blocks/Checkout.js.map +1 -1
- package/dist/modules/shop/blocks/Donation.js +4 -4
- package/dist/modules/shop/blocks/Donation.js.map +1 -1
- package/dist/modules/shop/blocks/ProductDetail.js +19 -3
- package/dist/modules/shop/blocks/ProductDetail.js.map +1 -1
- package/dist/modules/shop/blocks/ProductGrid.d.ts +3 -1
- package/dist/modules/shop/blocks/ProductGrid.js +8 -4
- package/dist/modules/shop/blocks/ProductGrid.js.map +1 -1
- package/dist/modules/shop/blocks/ShopCategories.js +4 -3
- package/dist/modules/shop/blocks/ShopCategories.js.map +1 -1
- package/dist/modules/shop/lib.d.ts +4 -0
- package/dist/modules/shop/lib.js +14 -0
- package/dist/modules/shop/lib.js.map +1 -1
- package/dist/modules/shop/settings.d.ts +3 -0
- package/dist/modules/shop/settings.js +14 -0
- package/dist/modules/shop/settings.js.map +1 -1
- package/dist/modules/shop/strings.d.ts +4 -0
- package/dist/modules/shop/strings.js +8 -0
- package/dist/modules/shop/strings.js.map +1 -1
- package/dist/next/envCheck.d.ts +42 -0
- package/dist/next/envCheck.js +106 -0
- package/dist/next/envCheck.js.map +1 -0
- package/dist/next/index.cjs +185 -2
- package/dist/next/index.d.ts +2 -0
- package/dist/next/index.js +8 -1
- package/dist/next/index.js.map +1 -1
- package/dist/next/securityHeaders.d.ts +36 -0
- package/dist/next/securityHeaders.js +74 -0
- package/dist/next/securityHeaders.js.map +1 -0
- package/dist/patterns/builtins.d.ts +7 -0
- package/dist/patterns/builtins.js +138 -3
- package/dist/patterns/builtins.js.map +1 -1
- package/dist/releaseNotes.js +148 -0
- package/dist/releaseNotes.js.map +1 -1
- package/dist/render/PublishedPage.d.ts +2 -1
- package/dist/render/PublishedPage.js +10 -4
- package/dist/render/PublishedPage.js.map +1 -1
- package/dist/schema/blocks.d.ts +473 -0
- package/dist/schema/blocks.js +105 -5
- package/dist/schema/blocks.js.map +1 -1
- package/dist/schema/business.d.ts +118 -0
- package/dist/schema/business.js +75 -0
- package/dist/schema/business.js.map +1 -0
- package/dist/schema/fields.d.ts +2 -1
- package/dist/schema/fields.js.map +1 -1
- package/dist/schema/forms.d.ts +18 -0
- package/dist/schema/forms.js +18 -3
- package/dist/schema/forms.js.map +1 -1
- package/dist/schema/mail.d.ts +10 -0
- package/dist/schema/mail.js +7 -0
- package/dist/schema/mail.js.map +1 -1
- package/dist/schema/settings.d.ts +103 -0
- package/dist/schema/settings.js +24 -3
- package/dist/schema/settings.js.map +1 -1
- package/dist/schema/shop.d.ts +2 -0
- package/dist/schema/shop.js +4 -0
- package/dist/schema/shop.js.map +1 -1
- package/dist/schema/shopGeld.d.ts +1 -0
- package/dist/schema/shopGeld.js +1 -0
- package/dist/schema/shopGeld.js.map +1 -1
- package/dist/schema/siteConfig.d.ts +69 -1
- package/dist/schema/siteConfig.js +7 -2
- package/dist/schema/siteConfig.js.map +1 -1
- package/dist/server/blockData.d.ts +1 -1
- package/dist/server/blockData.js +74 -18
- package/dist/server/blockData.js.map +1 -1
- package/dist/server/cspRapport.d.ts +20 -0
- package/dist/server/cspRapport.js +56 -0
- package/dist/server/cspRapport.js.map +1 -0
- package/dist/server/fonts.d.ts +3 -0
- package/dist/server/fonts.js +39 -0
- package/dist/server/fonts.js.map +1 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +8 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/sanitize.js +2 -0
- package/dist/server/sanitize.js.map +1 -1
- package/dist/settings/useSiteSettings.js +4 -1
- package/dist/settings/useSiteSettings.js.map +1 -1
- package/dist/starters/starters.d.ts +69 -0
- package/dist/starters/starters.js +171 -0
- package/dist/starters/starters.js.map +1 -0
- package/dist/styles.css +1181 -212
- package/dist/theme/color.d.ts +10 -0
- package/dist/theme/color.js +17 -1
- package/dist/theme/color.js.map +1 -1
- package/dist/theme/fontFallback.d.ts +23 -0
- package/dist/theme/fontFallback.js +58 -0
- package/dist/theme/fontFallback.js.map +1 -0
- package/dist/theme/fonts.d.ts +11 -0
- package/dist/theme/fonts.js +16 -0
- package/dist/theme/fonts.js.map +1 -0
- package/dist/version.js +1 -1
- package/package.json +5 -4
|
@@ -14,13 +14,25 @@ import {
|
|
|
14
14
|
trashPage,
|
|
15
15
|
subscribeVersions,
|
|
16
16
|
restoreVersion,
|
|
17
|
-
paginaToestand
|
|
17
|
+
paginaToestand,
|
|
18
|
+
planningDatum,
|
|
19
|
+
getVersieSnapshot,
|
|
20
|
+
publicatieContext,
|
|
21
|
+
zetPlanning
|
|
18
22
|
} from "../lib/pagesClient.js";
|
|
19
23
|
import { slugify } from "../lib/slugify.js";
|
|
24
|
+
import { controleerPagina } from "../lib/publicatieCheck.js";
|
|
25
|
+
import { LeesbaarheidPaneel } from "../ui/LeesbaarheidPaneel.js";
|
|
26
|
+
import { paginaTekst } from "../lib/leesbaarheid.js";
|
|
27
|
+
import { vergelijkVersie } from "../lib/versieVergelijk.js";
|
|
28
|
+
import { useRegistry } from "../../blocks/context.js";
|
|
20
29
|
import { titelMeter, omschrijvingMeter } from "../lib/seoHulp.js";
|
|
21
30
|
import { callable } from "../../firebase/functionsClient.js";
|
|
22
31
|
import { getFirebaseApp } from "../../firebase/client.js";
|
|
23
32
|
import { isDemoActive } from "../../demo/demoStore.js";
|
|
33
|
+
import { PreviewLinkResultaat } from "../ui/PreviewLinkResultaat.js";
|
|
34
|
+
import { bevatBlok, laadPaginaGebruik, verwijzingenZin } from "../lib/paginaGebruik.js";
|
|
35
|
+
import { useAdminNav } from "../navContext.js";
|
|
24
36
|
function formatVersionDate(createdAt) {
|
|
25
37
|
const d = createdAt && typeof createdAt.toDate === "function" ? createdAt.toDate() : typeof createdAt === "string" ? new Date(createdAt) : null;
|
|
26
38
|
if (!d || Number.isNaN(d.getTime())) return "";
|
|
@@ -40,18 +52,30 @@ function ToestandBadge({ p }) {
|
|
|
40
52
|
function PageEditor({ siteId, page, allPages }) {
|
|
41
53
|
const { toast } = useToast();
|
|
42
54
|
const confirm = useConfirm();
|
|
55
|
+
const registry = useRegistry();
|
|
43
56
|
const [draft, setDraft] = useState(page);
|
|
44
57
|
const [busy, setBusy] = useState(null);
|
|
45
58
|
const [saveState, setSaveState] = useState("idle");
|
|
46
59
|
const [versions, setVersions] = useState([]);
|
|
47
|
-
const [
|
|
60
|
+
const [previewLink, setPreviewLink] = useState(null);
|
|
48
61
|
const firstRender = useRef(true);
|
|
49
62
|
const slugTouched = useRef(Boolean(page.slug));
|
|
63
|
+
const nav = useAdminNav();
|
|
64
|
+
const isHome = page.path === "/";
|
|
65
|
+
function essentieelZin() {
|
|
66
|
+
const labels = /* @__PURE__ */ new Set();
|
|
67
|
+
bevatBlok(page.blocks ?? [], (b) => {
|
|
68
|
+
const def = registry.get(String(b._type));
|
|
69
|
+
if (def?.essentieel) labels.add(def.label);
|
|
70
|
+
return false;
|
|
71
|
+
});
|
|
72
|
+
return labels.size ? ` Op deze pagina staat ${[...labels].map((l) => `\u201C${l}\u201D`).join(" en ")} \u2014 daar werkt de site op.` : "";
|
|
73
|
+
}
|
|
50
74
|
useEffect(() => {
|
|
51
75
|
setDraft(page);
|
|
52
76
|
firstRender.current = true;
|
|
53
77
|
slugTouched.current = Boolean(page.slug);
|
|
54
|
-
|
|
78
|
+
setPreviewLink(null);
|
|
55
79
|
}, [page.id]);
|
|
56
80
|
useEffect(() => {
|
|
57
81
|
setDraft((d) => ({ ...d, published: page.published, updatedAt: page.updatedAt, lastPublishedAt: page.lastPublishedAt, trashed: page.trashed }));
|
|
@@ -104,9 +128,21 @@ function PageEditor({ siteId, page, allPages }) {
|
|
|
104
128
|
toast({ title: "Adres is al in gebruik", description: "Kies eerst een ander pad.", tone: "error" });
|
|
105
129
|
return;
|
|
106
130
|
}
|
|
131
|
+
const ctx = await publicatieContext(siteId);
|
|
132
|
+
const waarschuwingen = controleerPagina(draft, {
|
|
133
|
+
bekendePaden: allPages ? allPages.filter((p) => !p.trashed).map((p) => p.path) : ctx.bekendePaden,
|
|
134
|
+
livePaden: allPages ? allPages.filter((p) => !p.trashed && p.published).map((p) => p.path) : ctx.livePaden,
|
|
135
|
+
redirects: ctx.redirects
|
|
136
|
+
});
|
|
107
137
|
const ok = await confirm({
|
|
108
138
|
title: "Pagina publiceren?",
|
|
109
|
-
description:
|
|
139
|
+
description: /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
140
|
+
/* @__PURE__ */ jsx("p", { children: padGewijzigd ? `De live site wordt bijgewerkt (${draft.path}). Het oude adres (${page.path}) verwijst automatisch door.` : `De live site wordt bijgewerkt (${draft.path}).` }),
|
|
141
|
+
waarschuwingen.length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-lg bg-amber-50 px-3 py-2 text-amber-900", children: [
|
|
142
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium", children: "Even nakijken (je kunt ook gewoon publiceren):" }),
|
|
143
|
+
/* @__PURE__ */ jsx("ul", { className: "mt-1 list-disc pl-5", children: waarschuwingen.map((w, i) => /* @__PURE__ */ jsx("li", { children: w.tekst }, i)) })
|
|
144
|
+
] })
|
|
145
|
+
] }),
|
|
110
146
|
confirmLabel: "Publiceren"
|
|
111
147
|
});
|
|
112
148
|
if (!ok) return;
|
|
@@ -122,9 +158,11 @@ function PageEditor({ siteId, page, allPages }) {
|
|
|
122
158
|
}
|
|
123
159
|
}
|
|
124
160
|
async function onUnpublish() {
|
|
161
|
+
const gebruik = await laadPaginaGebruik(siteId, page.path, page.id);
|
|
162
|
+
const zin = gebruik ? verwijzingenZin(gebruik) : null;
|
|
125
163
|
const ok = await confirm({
|
|
126
164
|
title: "Pagina offline halen?",
|
|
127
|
-
description:
|
|
165
|
+
description: `Bezoekers zien de pagina niet meer (het adres geeft een foutpagina). De werkversie blijft bewaard; publiceren zet hem weer live.${zin ? ` ${zin}` : ""}${essentieelZin()}`,
|
|
128
166
|
confirmLabel: "Offline halen",
|
|
129
167
|
tone: "danger"
|
|
130
168
|
});
|
|
@@ -132,7 +170,7 @@ function PageEditor({ siteId, page, allPages }) {
|
|
|
132
170
|
setBusy("unpublish");
|
|
133
171
|
try {
|
|
134
172
|
await unpublishPage(siteId, draft.id);
|
|
135
|
-
toast({ title: "Offline gehaald", description: "
|
|
173
|
+
toast({ title: "Offline gehaald", description: "Binnen enkele minuten is de pagina niet meer te bezoeken. De werkversie blijft bewaard." });
|
|
136
174
|
} catch (e) {
|
|
137
175
|
toast({ title: "Offline halen mislukt", description: e.message, tone: "error" });
|
|
138
176
|
} finally {
|
|
@@ -142,7 +180,7 @@ function PageEditor({ siteId, page, allPages }) {
|
|
|
142
180
|
async function onDuplicate() {
|
|
143
181
|
setBusy("dup");
|
|
144
182
|
try {
|
|
145
|
-
await duplicatePage(siteId, draft);
|
|
183
|
+
await duplicatePage(siteId, draft, (allPages ?? []).map((p) => p.path));
|
|
146
184
|
toast({ title: "Pagina gedupliceerd", description: "De kopie staat als concept in de lijst.", tone: "success" });
|
|
147
185
|
} catch (e) {
|
|
148
186
|
toast({ title: "Dupliceren mislukt", description: e.message, tone: "error" });
|
|
@@ -151,9 +189,12 @@ function PageEditor({ siteId, page, allPages }) {
|
|
|
151
189
|
}
|
|
152
190
|
}
|
|
153
191
|
async function onTrash() {
|
|
192
|
+
const gebruik = await laadPaginaGebruik(siteId, page.path, page.id);
|
|
193
|
+
const zin = gebruik ? verwijzingenZin(gebruik) : null;
|
|
194
|
+
const basis = page.published ? "De pagina gaat offline en staat 30 dagen in de prullenbak; daarna wordt hij definitief verwijderd. Herstellen kan al die tijd." : "De pagina staat 30 dagen in de prullenbak; daarna wordt hij definitief verwijderd. Herstellen kan al die tijd.";
|
|
154
195
|
const ok = await confirm({
|
|
155
196
|
title: `"${draft.title}" naar de prullenbak?`,
|
|
156
|
-
description:
|
|
197
|
+
description: `${basis}${zin ? ` ${zin}` : ""}${essentieelZin()}`,
|
|
157
198
|
confirmLabel: "Naar prullenbak",
|
|
158
199
|
tone: "danger"
|
|
159
200
|
});
|
|
@@ -161,7 +202,11 @@ function PageEditor({ siteId, page, allPages }) {
|
|
|
161
202
|
setBusy("trash");
|
|
162
203
|
try {
|
|
163
204
|
await trashPage(siteId, draft);
|
|
164
|
-
toast({
|
|
205
|
+
toast({
|
|
206
|
+
title: "In de prullenbak",
|
|
207
|
+
description: gebruik?.menu.length ? "Onderaan de lijst te herstellen. Vergeet het menu-item niet." : "Onderaan de lijst te herstellen.",
|
|
208
|
+
action: gebruik?.menu.length ? { label: "Menu aanpassen", onClick: () => nav("menu") } : void 0
|
|
209
|
+
});
|
|
165
210
|
} catch (e) {
|
|
166
211
|
toast({ title: "Mislukt", description: e.message, tone: "error" });
|
|
167
212
|
} finally {
|
|
@@ -174,23 +219,28 @@ function PageEditor({ siteId, page, allPages }) {
|
|
|
174
219
|
setBusy("preview");
|
|
175
220
|
try {
|
|
176
221
|
const res = await callable(app, "createPreviewLink")({ siteId, path: draft.path });
|
|
177
|
-
|
|
222
|
+
setPreviewLink(res.data);
|
|
178
223
|
try {
|
|
179
224
|
await navigator.clipboard?.writeText(res.data.url);
|
|
180
|
-
toast({ title: "
|
|
225
|
+
toast({ title: "Voorbeeldlink gekopieerd", description: "Zeven dagen geldig. Wie hem opent ziet de nieuwste stand, ook wat nog niet gepubliceerd is.", tone: "success" });
|
|
181
226
|
} catch {
|
|
182
|
-
toast({ title: "
|
|
227
|
+
toast({ title: "Voorbeeldlink gemaakt", description: "Kopieer hem hieronder.", tone: "success" });
|
|
183
228
|
}
|
|
184
229
|
} catch (e) {
|
|
185
|
-
toast({ title: "
|
|
230
|
+
toast({ title: "Voorbeeldlink mislukt", description: e.message, tone: "error" });
|
|
186
231
|
} finally {
|
|
187
232
|
setBusy(null);
|
|
188
233
|
}
|
|
189
234
|
}
|
|
190
235
|
async function onRestore(versionId) {
|
|
236
|
+
const versie = await getVersieSnapshot(siteId, draft.id, versionId).catch(() => null);
|
|
237
|
+
const verschil = versie ? vergelijkVersie(draft, versie, (t) => registry.get(t)?.label ?? t) : [];
|
|
191
238
|
const ok = await confirm({
|
|
192
239
|
title: "Versie herstellen?",
|
|
193
|
-
description:
|
|
240
|
+
description: /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
241
|
+
verschil.length > 0 && /* @__PURE__ */ jsx("ul", { className: "list-disc pl-5", children: verschil.map((r, i) => /* @__PURE__ */ jsx("li", { children: r }, i)) }),
|
|
242
|
+
/* @__PURE__ */ jsx("p", { children: "De huidige werkversie wordt overschreven met deze versie (ongedaan te maken met een nieuwere versie). Publiceer daarna om het live te zetten." })
|
|
243
|
+
] }),
|
|
194
244
|
confirmLabel: "Herstellen"
|
|
195
245
|
});
|
|
196
246
|
if (!ok) return;
|
|
@@ -216,7 +266,7 @@ function PageEditor({ siteId, page, allPages }) {
|
|
|
216
266
|
saveState === "error" && /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "sm", onClick: () => void persist(draft), children: "Opnieuw opslaan" }),
|
|
217
267
|
!inPrullenbak && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
218
268
|
/* @__PURE__ */ jsx(Button, { variant: "secondary", size: "sm", onClick: openOpSite, title: "De tekst en blokken bewerk je op de pagina zelf", children: "\u270E Bewerken op de site" }),
|
|
219
|
-
/* @__PURE__ */ jsx(Button, { size: "sm", onClick: onPublish, disabled: busy !== null, children:
|
|
269
|
+
/* @__PURE__ */ jsx(Button, { loading: busy === "publish", size: "sm", onClick: onPublish, disabled: busy !== null, children: "Publiceren" })
|
|
220
270
|
] })
|
|
221
271
|
] })
|
|
222
272
|
] }),
|
|
@@ -228,10 +278,11 @@ function PageEditor({ siteId, page, allPages }) {
|
|
|
228
278
|
] }),
|
|
229
279
|
/* @__PURE__ */ jsxs("div", { className: "grid gap-3 md:grid-cols-2", children: [
|
|
230
280
|
/* @__PURE__ */ jsx(Field, { label: "Titel", children: /* @__PURE__ */ jsx(Input, { value: draft.title, onChange: (e) => setTitle(e.target.value) }) }),
|
|
231
|
-
/* @__PURE__ */ jsxs(Field, { label: "Adres (pad)", hint: "bv. /
|
|
281
|
+
/* @__PURE__ */ jsxs(Field, { label: "Adres (pad)", hint: isHome ? "De homepage heeft altijd het adres /." : "bv. /over-ons", children: [
|
|
232
282
|
/* @__PURE__ */ jsx(
|
|
233
283
|
Input,
|
|
234
284
|
{
|
|
285
|
+
readOnly: isHome,
|
|
235
286
|
value: draft.path,
|
|
236
287
|
onChange: (e) => update({ ...draft, path: e.target.value }),
|
|
237
288
|
onBlur: () => {
|
|
@@ -281,17 +332,19 @@ function PageEditor({ siteId, page, allPages }) {
|
|
|
281
332
|
!inPrullenbak && /* @__PURE__ */ jsxs(Card, { children: [
|
|
282
333
|
/* @__PURE__ */ jsx("h3", { className: "mb-1 text-base font-semibold", children: "Delen v\xF3\xF3r publiceren" }),
|
|
283
334
|
/* @__PURE__ */ jsx("p", { className: "mb-3 text-xs text-slate-500", children: "Laat iemand zonder inlog meekijken naar de werkversie. De link werkt zeven dagen en geeft geen toegang tot het beheer." }),
|
|
284
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
285
|
-
/* @__PURE__ */ jsx(Button, { variant: "secondary", size: "sm", disabled: busy !== null || isDemoActive(), onClick: () => void maakPreviewLink(), children:
|
|
286
|
-
|
|
335
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
336
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { loading: busy === "preview", variant: "secondary", size: "sm", disabled: busy !== null || isDemoActive(), onClick: () => void maakPreviewLink(), children: previewLink ? "Nieuwe link maken" : "Voorbeeldlink maken" }) }),
|
|
337
|
+
previewLink && /* @__PURE__ */ jsx(PreviewLinkResultaat, { link: previewLink, titel: draft.title })
|
|
287
338
|
] })
|
|
288
339
|
] }),
|
|
340
|
+
!inPrullenbak && /* @__PURE__ */ jsx(LeesbaarheidPaneel, { tekst: paginaTekst(draft.blocks), titel: "Leesbaarheid van deze pagina" }),
|
|
341
|
+
!inPrullenbak && !isDemoActive() && /* @__PURE__ */ jsx(PlanningKaart, { siteId, page }),
|
|
289
342
|
versions.length > 0 && /* @__PURE__ */ jsxs(Card, { children: [
|
|
290
343
|
/* @__PURE__ */ jsx("h4", { className: "mb-2 text-sm font-semibold", children: "Versiegeschiedenis" }),
|
|
291
344
|
/* @__PURE__ */ jsx("ul", { className: "grid gap-1 text-sm text-slate-600", children: versions.slice(0, 10).map((v) => /* @__PURE__ */ jsxs("li", { className: "flex items-center justify-between border-b border-slate-100 py-1 last:border-0", children: [
|
|
292
345
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
293
|
-
v.label ?? (v.kind === "publish" ? "Gepubliceerd" :
|
|
294
|
-
formatVersionDate(v.createdAt) && /* @__PURE__ */ jsxs("span", { className: "text-slate-
|
|
346
|
+
v.label ?? (v.kind === "publish" ? "Gepubliceerd" : "Opgeslagen versie"),
|
|
347
|
+
formatVersionDate(v.createdAt) && /* @__PURE__ */ jsxs("span", { className: "text-slate-500", children: [
|
|
295
348
|
" \xB7 ",
|
|
296
349
|
formatVersionDate(v.createdAt)
|
|
297
350
|
] })
|
|
@@ -300,16 +353,79 @@ function PageEditor({ siteId, page, allPages }) {
|
|
|
300
353
|
] }, v.id)) })
|
|
301
354
|
] }),
|
|
302
355
|
!inPrullenbak && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-end gap-3 border-t border-slate-200 pt-4", children: [
|
|
303
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", disabled: busy !== null, onClick: () => void onDuplicate(), children:
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
"
|
|
356
|
+
/* @__PURE__ */ jsx(Button, { loading: busy === "dup", variant: "ghost", size: "sm", disabled: busy !== null, onClick: () => void onDuplicate(), children: "Dupliceren" }),
|
|
357
|
+
isHome ? /* @__PURE__ */ jsx("span", { className: "text-xs text-slate-500", children: "De homepage kan niet offline of in de prullenbak." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
358
|
+
page.published && /* @__PURE__ */ jsx(Button, { loading: busy === "unpublish", variant: "ghost", size: "sm", disabled: busy !== null, onClick: () => void onUnpublish(), children: "Offline halen" }),
|
|
359
|
+
/* @__PURE__ */ jsx(Button, { variant: "dangerGhost", size: "sm", disabled: busy !== null, onClick: () => void onTrash(), children: "Naar prullenbak" })
|
|
360
|
+
] })
|
|
361
|
+
] })
|
|
362
|
+
] });
|
|
363
|
+
}
|
|
364
|
+
function naarInvoer(d) {
|
|
365
|
+
if (!d) return "";
|
|
366
|
+
const p = (n) => String(n).padStart(2, "0");
|
|
367
|
+
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}T${p(d.getHours())}:${p(d.getMinutes())}`;
|
|
368
|
+
}
|
|
369
|
+
function uitInvoer(v) {
|
|
370
|
+
if (!v) return null;
|
|
371
|
+
const d = new Date(v);
|
|
372
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
373
|
+
}
|
|
374
|
+
function PlanningKaart({ siteId, page }) {
|
|
375
|
+
const { toast } = useToast();
|
|
376
|
+
const [aan, setAan] = useState(() => naarInvoer(planningDatum(page.publishAt)));
|
|
377
|
+
const [uit, setUit] = useState(() => naarInvoer(planningDatum(page.unpublishAt)));
|
|
378
|
+
const [bezig, setBezig] = useState(false);
|
|
379
|
+
useEffect(() => {
|
|
380
|
+
setAan(naarInvoer(planningDatum(page.publishAt)));
|
|
381
|
+
setUit(naarInvoer(planningDatum(page.unpublishAt)));
|
|
382
|
+
}, [page.publishAt, page.unpublishAt]);
|
|
383
|
+
const aanDatum = uitInvoer(aan);
|
|
384
|
+
const uitDatum = uitInvoer(uit);
|
|
385
|
+
const fout = aanDatum && aanDatum.getTime() < Date.now() - 6e4 ? "Het publicatiemoment ligt in het verleden." : aanDatum && uitDatum && uitDatum <= aanDatum ? "Offline halen moet n\xE1 het publiceren liggen." : null;
|
|
386
|
+
async function opslaan() {
|
|
387
|
+
if (fout) return;
|
|
388
|
+
setBezig(true);
|
|
389
|
+
try {
|
|
390
|
+
await zetPlanning(siteId, page.id, { publishAt: aanDatum, unpublishAt: uitDatum });
|
|
391
|
+
toast({
|
|
392
|
+
title: aanDatum || uitDatum ? "Ingepland" : "Planning gewist",
|
|
393
|
+
description: aanDatum || uitDatum ? "Wordt uitgevoerd binnen 10 minuten na het gekozen moment." : void 0,
|
|
394
|
+
tone: "success"
|
|
395
|
+
});
|
|
396
|
+
} catch (e) {
|
|
397
|
+
toast({ title: "Inplannen mislukt", description: e.message, tone: "error" });
|
|
398
|
+
} finally {
|
|
399
|
+
setBezig(false);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
const lang = (d) => d.toLocaleString("nl-NL", { weekday: "long", day: "numeric", month: "long", hour: "2-digit", minute: "2-digit" });
|
|
403
|
+
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
404
|
+
/* @__PURE__ */ jsx("h4", { className: "mb-1 text-sm font-semibold", children: "Inplannen" }),
|
|
405
|
+
/* @__PURE__ */ jsx("p", { className: "mb-3 text-xs text-slate-500", children: "Laat de pagina op een gekozen moment vanzelf live gaan of verdwijnen \u2014 bijvoorbeeld een actie of een vacature. Gebeurt binnen 10 minuten na het gekozen moment; bij publiceren gaat de werkversie live zoals die dan is." }),
|
|
406
|
+
page.planningFout && /* @__PURE__ */ jsxs("p", { role: "alert", className: "mb-3 rounded-lg bg-red-50 px-3 py-2 text-sm text-red-800", children: [
|
|
407
|
+
"De vorige planning is niet gelukt: ",
|
|
408
|
+
page.planningFout
|
|
409
|
+
] }),
|
|
410
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-3 md:grid-cols-2", children: [
|
|
411
|
+
/* @__PURE__ */ jsx(Field, { label: "Automatisch publiceren op", hint: aanDatum ? lang(aanDatum) : "Leeg = niet ingepland", children: /* @__PURE__ */ jsx(Input, { type: "datetime-local", value: aan, onChange: (e) => setAan(e.target.value) }) }),
|
|
412
|
+
/* @__PURE__ */ jsx(Field, { label: "Automatisch offline halen op", hint: uitDatum ? lang(uitDatum) : "Leeg = blijft staan", children: /* @__PURE__ */ jsx(Input, { type: "datetime-local", value: uit, onChange: (e) => setUit(e.target.value) }) })
|
|
413
|
+
] }),
|
|
414
|
+
fout && /* @__PURE__ */ jsx("p", { role: "alert", className: "mt-2 text-sm text-red-700", children: fout }),
|
|
415
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-3 flex gap-2", children: [
|
|
416
|
+
/* @__PURE__ */ jsx(Button, { loading: bezig, size: "sm", variant: "secondary", disabled: bezig || Boolean(fout), onClick: () => void opslaan(), children: "Planning opslaan" }),
|
|
417
|
+
Boolean(page.publishAt || page.unpublishAt) && /* @__PURE__ */ jsx(
|
|
418
|
+
Button,
|
|
307
419
|
{
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
onClick: () =>
|
|
312
|
-
|
|
420
|
+
size: "sm",
|
|
421
|
+
variant: "ghost",
|
|
422
|
+
disabled: bezig,
|
|
423
|
+
onClick: () => {
|
|
424
|
+
setAan("");
|
|
425
|
+
setUit("");
|
|
426
|
+
void zetPlanning(siteId, page.id, { publishAt: null, unpublishAt: null }).then(() => toast({ title: "Planning gewist", tone: "success" })).catch((e) => toast({ title: "Wissen mislukt", description: e.message, tone: "error" }));
|
|
427
|
+
},
|
|
428
|
+
children: "Planning wissen"
|
|
313
429
|
}
|
|
314
430
|
)
|
|
315
431
|
] })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/admin/pages/PageEditor.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { Button, Card, Field, Input, Textarea, Badge } from \"../ui/primitives\";\nimport { Switch } from \"../ui/switch\";\nimport { useToast } from \"../ui/toast\";\nimport { useConfirm } from \"../ui/ConfirmDialog\";\nimport { MediaPickerButton } from \"../media/MediaPicker\";\nimport {\n saveDraft,\n publishPage,\n unpublishPage,\n duplicatePage,\n trashPage,\n subscribeVersions,\n restoreVersion,\n paginaToestand,\n type DraftPage,\n} from \"../lib/pagesClient\";\nimport { slugify } from \"../lib/slugify\";\nimport { titelMeter, omschrijvingMeter, type Meter } from \"../lib/seoHulp\";\nimport { callable } from \"../../firebase/functionsClient\";\nimport { getFirebaseApp } from \"../../firebase/client\";\nimport { isDemoActive } from \"../../demo/demoStore\";\n\ntype SaveState = \"idle\" | \"saving\" | \"saved\" | \"error\";\n\ninterface VersionRow {\n id: string;\n createdAt?: unknown;\n kind?: string;\n label?: string;\n}\n\nfunction formatVersionDate(createdAt: unknown): string {\n const d =\n createdAt && typeof (createdAt as { toDate?: () => Date }).toDate === \"function\"\n ? (createdAt as { toDate: () => Date }).toDate()\n : typeof createdAt === \"string\"\n ? new Date(createdAt)\n : null;\n if (!d || Number.isNaN(d.getTime())) return \"\";\n return d.toLocaleString(\"nl-NL\", { dateStyle: \"medium\", timeStyle: \"short\" });\n}\n\n/** Lengtemeter onder een SEO-veld: één regel, kleur zegt genoeg. */\nfunction MeterRegel({ m }: { m: Meter }) {\n const kleur = m.toon === \"goed\" ? \"text-emerald-700\" : m.toon === \"lang\" || m.toon === \"leeg\" ? \"text-amber-700\" : \"text-slate-500\";\n return <p className={`mt-1 text-xs ${kleur}`}>{m.tekst}</p>;\n}\n\n/** Badge voor de toestand van een pagina — gedeeld met de lijst. */\nexport function ToestandBadge({ p }: { p: DraftPage }) {\n const t = paginaToestand(p);\n if (t === \"gewijzigd\") return <Badge tone=\"amber\">gewijzigd, nog niet live</Badge>;\n if (t === \"live\") return <Badge tone=\"green\">live</Badge>;\n if (t === \"prullenbak\") return <Badge>prullenbak</Badge>;\n return <Badge tone=\"amber\">concept</Badge>;\n}\n\n/**\n * Pagina-instellingen (7.24) — wat je NIET op de pagina zelf ziet: titel, adres, SEO, versies,\n * en de levenscyclus (publiceren, offline halen, dupliceren, prullenbak).\n *\n * Tot 7.24 stond hier een complete tweede editor: elk blok als formulier, met eigen ↑↓🗑, een\n * eigen publiceerknop zónder de \"wat is er veranderd\"-diff en zonder undo. Het dashboard stuurde\n * de klant intussen naar de site zelf (\"bewerk op de pagina\") — twee manieren voor één ding, met\n * twee gedragingen. De blokken bewerk je nu uitsluitend op de site (knop hieronder); dit scherm\n * gaat over de pagina als geheel.\n */\nexport function PageEditor({ siteId, page, allPages }: { siteId: string; page: DraftPage; allPages?: DraftPage[] }) {\n const { toast } = useToast();\n const confirm = useConfirm();\n const [draft, setDraft] = useState<DraftPage>(page);\n const [busy, setBusy] = useState<string | null>(null);\n const [saveState, setSaveState] = useState<SaveState>(\"idle\");\n const [versions, setVersions] = useState<VersionRow[]>([]);\n const [previewUrl, setPreviewUrl] = useState<string | null>(null);\n const firstRender = useRef(true);\n const slugTouched = useRef(Boolean(page.slug));\n\n // Wissel van pagina → herlaad lokale state. Bewust NIET op elke remote-update: dan zou een\n // autosave-echo je typwerk overschrijven.\n useEffect(() => {\n setDraft(page);\n firstRender.current = true;\n slugTouched.current = Boolean(page.slug);\n setPreviewUrl(null);\n }, [page.id]); // eslint-disable-line react-hooks/exhaustive-deps\n // Toestand-velden volgen wél live (publiceren/offline halen gebeurt buiten dit formulier om).\n useEffect(() => {\n setDraft((d) => ({ ...d, published: page.published, updatedAt: page.updatedAt, lastPublishedAt: page.lastPublishedAt, trashed: page.trashed }));\n }, [page.published, page.updatedAt, page.lastPublishedAt, page.trashed]);\n\n useEffect(() => subscribeVersions(siteId, page.id, (v) => setVersions(v)), [siteId, page.id]);\n\n function persist(d: DraftPage) {\n setSaveState(\"saving\");\n // Alleen de metadata: de blokken zijn van de visuele editor. Zou dit `blocks` meesturen, dan\n // kon een verouderde kopie hier een net-gemaakte inline bewerking overschrijven.\n return saveDraft(siteId, d.id, { title: d.title, slug: d.slug, path: d.path, seo: d.seo })\n .then(() => setSaveState(\"saved\"))\n .catch(() => {\n setSaveState(\"error\");\n toast({ title: \"Opslaan mislukt\", description: \"Wijzigingen zijn nog niet opgeslagen.\", tone: \"error\" });\n });\n }\n\n useEffect(() => {\n if (firstRender.current) {\n firstRender.current = false;\n return;\n }\n const t = setTimeout(() => void persist(draft), 800);\n return () => clearTimeout(t);\n }, [draft.title, draft.slug, draft.path, draft.seo]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n const onBeforeUnload = (e: BeforeUnloadEvent) => {\n if (saveState === \"saving\" || saveState === \"error\") {\n e.preventDefault();\n e.returnValue = \"\";\n }\n };\n window.addEventListener(\"beforeunload\", onBeforeUnload);\n return () => window.removeEventListener(\"beforeunload\", onBeforeUnload);\n }, [saveState]);\n\n function update(next: DraftPage) {\n setDraft(next);\n }\n function setTitle(title: string) {\n const slug = slugTouched.current ? draft.slug : slugify(title);\n update({ ...draft, title, slug });\n }\n\n const seo = draft.seo ?? {};\n const padBotsing = allPages?.some((p) => p.id !== draft.id && !p.trashed && p.path === draft.path) ?? false;\n const padGewijzigd = Boolean(page.published && page.path !== draft.path);\n\n /** Naar de pagina op de site, met de bewerkmodus alvast aan (zelfde sleutel als EditorProvider). */\n function openOpSite() {\n try {\n sessionStorage.setItem(\"xicms-bewerkmodus\", \"bewerken\");\n } catch {\n /* geblokkeerde opslag: dan opent de pagina in kijkmodus en kies je \"Bewerken\" in de balk */\n }\n window.location.assign(draft.path || \"/\");\n }\n\n async function onPublish() {\n if (padBotsing) {\n toast({ title: \"Adres is al in gebruik\", description: \"Kies eerst een ander pad.\", tone: \"error\" });\n return;\n }\n const ok = await confirm({\n title: \"Pagina publiceren?\",\n description: padGewijzigd\n ? `De live site wordt bijgewerkt (${draft.path}). Het oude adres (${page.path}) verwijst automatisch door.`\n : `De live site wordt bijgewerkt (${draft.path}).`,\n confirmLabel: \"Publiceren\",\n });\n if (!ok) return;\n setBusy(\"publish\");\n try {\n await saveDraft(siteId, draft.id, { title: draft.title, slug: draft.slug, path: draft.path, seo: draft.seo });\n await publishPage(siteId, draft.id);\n toast({ title: \"Gepubliceerd\", description: draft.path, tone: \"success\" });\n } catch (e) {\n toast({ title: \"Publiceren mislukt\", description: (e as Error).message, tone: \"error\" });\n } finally {\n setBusy(null);\n }\n }\n\n async function onUnpublish() {\n const ok = await confirm({\n title: \"Pagina offline halen?\",\n description: \"Bezoekers zien de pagina niet meer (het adres geeft een 404). De werkversie blijft bewaard; publiceren zet hem weer live.\",\n confirmLabel: \"Offline halen\",\n tone: \"danger\",\n });\n if (!ok) return;\n setBusy(\"unpublish\");\n try {\n await unpublishPage(siteId, draft.id);\n toast({ title: \"Offline gehaald\", description: \"De live site laat de pagina los na de eerstvolgende rebuild (meestal enkele minuten).\" });\n } catch (e) {\n toast({ title: \"Offline halen mislukt\", description: (e as Error).message, tone: \"error\" });\n } finally {\n setBusy(null);\n }\n }\n\n async function onDuplicate() {\n setBusy(\"dup\");\n try {\n await duplicatePage(siteId, draft);\n toast({ title: \"Pagina gedupliceerd\", description: \"De kopie staat als concept in de lijst.\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Dupliceren mislukt\", description: (e as Error).message, tone: \"error\" });\n } finally {\n setBusy(null);\n }\n }\n\n async function onTrash() {\n const ok = await confirm({\n title: `\"${draft.title}\" naar de prullenbak?`,\n description: page.published\n ? \"De pagina gaat offline en staat 30 dagen in de prullenbak; daarna wordt hij definitief verwijderd. Herstellen kan al die tijd.\"\n : \"De pagina staat 30 dagen in de prullenbak; daarna wordt hij definitief verwijderd. Herstellen kan al die tijd.\",\n confirmLabel: \"Naar prullenbak\",\n tone: \"danger\",\n });\n if (!ok) return;\n setBusy(\"trash\");\n try {\n await trashPage(siteId, draft);\n toast({ title: \"In de prullenbak\", description: \"Onderaan de lijst te herstellen.\" });\n } catch (e) {\n toast({ title: \"Mislukt\", description: (e as Error).message, tone: \"error\" });\n } finally {\n setBusy(null);\n }\n }\n\n async function maakPreviewLink() {\n const app = getFirebaseApp();\n if (!app) return;\n setBusy(\"preview\");\n try {\n const res = await callable<{ siteId: string; path: string }, { url: string; expiresAt: number }>(app, \"createPreviewLink\")({ siteId, path: draft.path });\n setPreviewUrl(res.data.url);\n try {\n await navigator.clipboard?.writeText(res.data.url);\n toast({ title: \"Preview-link gekopieerd\", description: \"Zeven dagen geldig. Wie hem opent ziet de nieuwste stand, ook wat nog niet gepubliceerd is.\", tone: \"success\" });\n } catch {\n toast({ title: \"Preview-link gemaakt\", description: \"Kopieer hem hieronder.\", tone: \"success\" });\n }\n } catch (e) {\n toast({ title: \"Preview-link mislukt\", description: (e as Error).message, tone: \"error\" });\n } finally {\n setBusy(null);\n }\n }\n\n async function onRestore(versionId: string) {\n const ok = await confirm({\n title: \"Versie herstellen?\",\n description: \"De huidige werkversie wordt overschreven met deze versie. Publiceer daarna om het live te zetten.\",\n confirmLabel: \"Herstellen\",\n });\n if (!ok) return;\n try {\n const restored = await restoreVersion(siteId, draft.id, versionId);\n setDraft({ ...draft, ...restored });\n firstRender.current = true;\n toast({ title: \"Versie hersteld\", description: \"Controleer op de site en publiceer om live te zetten.\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Herstellen mislukt\", description: (e as Error).message, tone: \"error\" });\n }\n }\n\n const inPrullenbak = Boolean(draft.trashed);\n\n return (\n <div className=\"grid gap-4\">\n <Card>\n <div className=\"mb-3 flex flex-wrap items-center justify-between gap-2\">\n <div className=\"flex items-center gap-2\">\n <h3 className=\"text-base font-semibold\">Pagina</h3>\n <ToestandBadge p={draft} />\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-xs text-slate-500\" aria-live=\"polite\">\n {saveState === \"saving\" ? \"Opslaan…\" : saveState === \"saved\" ? \"✓ Opgeslagen\" : \"\"}\n </span>\n {saveState === \"error\" && (\n <Button variant=\"secondary\" size=\"sm\" onClick={() => void persist(draft)}>\n Opnieuw opslaan\n </Button>\n )}\n {!inPrullenbak && (\n <>\n <Button variant=\"secondary\" size=\"sm\" onClick={openOpSite} title=\"De tekst en blokken bewerk je op de pagina zelf\">\n ✎ Bewerken op de site\n </Button>\n <Button size=\"sm\" onClick={onPublish} disabled={busy !== null}>\n {busy === \"publish\" ? \"Bezig…\" : \"Publiceren\"}\n </Button>\n </>\n )}\n </div>\n </div>\n {saveState === \"error\" && (\n <div className=\"mb-3 rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700\">\n Niet alle wijzigingen zijn opgeslagen. Controleer je verbinding en klik “Opnieuw opslaan”.\n </div>\n )}\n <p className=\"mb-3 text-xs text-slate-500\">\n De inhoud (teksten, foto's, blokken) bewerk je op de pagina zelf via <em>Bewerken op de site</em>. Hier\n staan de dingen die je dáár niet ziet: de naam, het adres en hoe Google de pagina toont.\n </p>\n <div className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Titel\">\n <Input value={draft.title} onChange={(e) => setTitle(e.target.value)} />\n </Field>\n <Field label=\"Adres (pad)\" hint=\"bv. / of /over-ons\">\n <Input\n value={draft.path}\n onChange={(e) => update({ ...draft, path: e.target.value })}\n onBlur={() => {\n const parts = draft.path.split(\"/\").map((s) => slugify(s)).filter(Boolean);\n const normalized = \"/\" + parts.join(\"/\");\n if (normalized !== draft.path) update({ ...draft, path: normalized });\n }}\n />\n {padBotsing && (\n <p className=\"mt-1 text-xs text-red-600\" role=\"alert\">\n ⚠ Er bestaat al een pagina met dit adres — één van beide wordt dan onbereikbaar.\n </p>\n )}\n {padGewijzigd && !padBotsing && (\n <p className=\"mt-1 text-xs text-slate-500\">\n Na publiceren verwijst het oude adres ({page.path}) automatisch door naar het nieuwe.\n </p>\n )}\n </Field>\n </div>\n </Card>\n\n <Card>\n <h3 className=\"mb-1 text-base font-semibold\">In Google en bij het delen</h3>\n <p className=\"mb-3 text-xs text-slate-500\">Zo ziet de pagina eruit in zoekresultaten en als iemand de link deelt op social media of WhatsApp.</p>\n <div className=\"grid gap-3\">\n <Field label=\"Titel in zoekresultaten\" hint=\"Leeg = de paginatitel\">\n <Input value={seo.title ?? \"\"} onChange={(e) => update({ ...draft, seo: { ...seo, title: e.target.value } })} />\n <MeterRegel m={titelMeter(seo.title, draft.title)} />\n </Field>\n <Field label=\"Omschrijving\" hint=\"Eén of twee zinnen die uitnodigen om te klikken\">\n <Textarea rows={2} value={seo.description ?? \"\"} onChange={(e) => update({ ...draft, seo: { ...seo, description: e.target.value } })} />\n <MeterRegel m={omschrijvingMeter(seo.description)} />\n </Field>\n <Field label=\"Afbeelding bij het delen\" hint=\"Verschijnt als voorbeeld op social media en in WhatsApp. Leeg = de standaardafbeelding van de site.\">\n <div className=\"flex flex-wrap items-center gap-2\">\n {seo.ogImage && (\n // eslint-disable-next-line @next/next/no-img-element\n <img src={seo.ogImage} alt=\"\" className=\"h-14 w-24 rounded-md border border-slate-200 object-cover\" />\n )}\n <MediaPickerButton siteId={siteId} label={seo.ogImage ? \"Andere kiezen\" : \"Kies / upload\"} onSelect={(m) => update({ ...draft, seo: { ...seo, ogImage: m.url } })} />\n {seo.ogImage && (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => update({ ...draft, seo: { ...seo, ogImage: undefined } })}>\n Weghalen\n </Button>\n )}\n </div>\n </Field>\n <Switch\n checked={Boolean(seo.noindex)}\n onCheckedChange={(v) => update({ ...draft, seo: { ...seo, noindex: v || undefined } })}\n label=\"Niet opnemen in Google (bijvoorbeeld een bedankt- of actiepagina)\"\n />\n </div>\n </Card>\n\n {!inPrullenbak && (\n <Card>\n <h3 className=\"mb-1 text-base font-semibold\">Delen vóór publiceren</h3>\n <p className=\"mb-3 text-xs text-slate-500\">\n Laat iemand zonder inlog meekijken naar de werkversie. De link werkt zeven dagen en geeft geen toegang tot het beheer.\n </p>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button variant=\"secondary\" size=\"sm\" disabled={busy !== null || isDemoActive()} onClick={() => void maakPreviewLink()}>\n {busy === \"preview\" ? \"Bezig…\" : \"Preview-link maken\"}\n </Button>\n {previewUrl && <Input readOnly value={previewUrl} className=\"min-w-0 flex-1 text-xs\" onFocus={(e) => e.currentTarget.select()} />}\n </div>\n </Card>\n )}\n\n {versions.length > 0 && (\n <Card>\n <h4 className=\"mb-2 text-sm font-semibold\">Versiegeschiedenis</h4>\n <ul className=\"grid gap-1 text-sm text-slate-600\">\n {versions.slice(0, 10).map((v) => (\n <li key={v.id} className=\"flex items-center justify-between border-b border-slate-100 py-1 last:border-0\">\n <span>\n {v.label ?? (v.kind === \"publish\" ? \"Gepubliceerd\" : v.kind ?? \"snapshot\")}\n {formatVersionDate(v.createdAt) && <span className=\"text-slate-400\"> · {formatVersionDate(v.createdAt)}</span>}\n </span>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => void onRestore(v.id)}>\n Herstellen\n </Button>\n </li>\n ))}\n </ul>\n </Card>\n )}\n\n {!inPrullenbak && (\n <div className=\"flex flex-wrap items-center justify-end gap-3 border-t border-slate-200 pt-4\">\n <Button variant=\"ghost\" size=\"sm\" disabled={busy !== null} onClick={() => void onDuplicate()}>\n {busy === \"dup\" ? \"Bezig…\" : \"Dupliceren\"}\n </Button>\n {page.published && (\n <Button variant=\"ghost\" size=\"sm\" disabled={busy !== null} onClick={() => void onUnpublish()}>\n {busy === \"unpublish\" ? \"Bezig…\" : \"Offline halen\"}\n </Button>\n )}\n <button\n type=\"button\"\n disabled={busy !== null}\n className=\"rounded px-2 py-1 text-sm text-red-600 hover:underline focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:outline-none disabled:opacity-50\"\n onClick={() => void onTrash()}\n >\n Naar prullenbak\n </button>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/pages/PageEditor.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { Button, Card, Field, Input, Textarea, Badge } from \"../ui/primitives\";\nimport { Switch } from \"../ui/switch\";\nimport { useToast } from \"../ui/toast\";\nimport { useConfirm } from \"../ui/ConfirmDialog\";\nimport { MediaPickerButton } from \"../media/MediaPicker\";\nimport {\n saveDraft,\n publishPage,\n unpublishPage,\n duplicatePage,\n trashPage,\n subscribeVersions,\n restoreVersion,\n paginaToestand,\n planningDatum,\n getVersieSnapshot,\n publicatieContext,\n zetPlanning,\n type DraftPage,\n} from \"../lib/pagesClient\";\nimport { slugify } from \"../lib/slugify\";\nimport { controleerPagina } from \"../lib/publicatieCheck\";\nimport { LeesbaarheidPaneel } from \"../ui/LeesbaarheidPaneel\";\nimport { paginaTekst } from \"../lib/leesbaarheid\";\nimport { vergelijkVersie } from \"../lib/versieVergelijk\";\nimport { useRegistry } from \"../../blocks/context\";\nimport { titelMeter, omschrijvingMeter, type Meter } from \"../lib/seoHulp\";\nimport { callable } from \"../../firebase/functionsClient\";\nimport { getFirebaseApp } from \"../../firebase/client\";\nimport { isDemoActive } from \"../../demo/demoStore\";\nimport { PreviewLinkResultaat, type PreviewLink } from \"../ui/PreviewLinkResultaat\";\nimport { bevatBlok, laadPaginaGebruik, verwijzingenZin } from \"../lib/paginaGebruik\";\nimport { useAdminNav } from \"../navContext\";\n\ntype SaveState = \"idle\" | \"saving\" | \"saved\" | \"error\";\n\ninterface VersionRow {\n id: string;\n createdAt?: unknown;\n kind?: string;\n label?: string;\n}\n\nfunction formatVersionDate(createdAt: unknown): string {\n const d =\n createdAt && typeof (createdAt as { toDate?: () => Date }).toDate === \"function\"\n ? (createdAt as { toDate: () => Date }).toDate()\n : typeof createdAt === \"string\"\n ? new Date(createdAt)\n : null;\n if (!d || Number.isNaN(d.getTime())) return \"\";\n return d.toLocaleString(\"nl-NL\", { dateStyle: \"medium\", timeStyle: \"short\" });\n}\n\n/** Lengtemeter onder een SEO-veld: één regel, kleur zegt genoeg. */\nfunction MeterRegel({ m }: { m: Meter }) {\n const kleur = m.toon === \"goed\" ? \"text-emerald-700\" : m.toon === \"lang\" || m.toon === \"leeg\" ? \"text-amber-700\" : \"text-slate-500\";\n return <p className={`mt-1 text-xs ${kleur}`}>{m.tekst}</p>;\n}\n\n/** Badge voor de toestand van een pagina — gedeeld met de lijst. */\nexport function ToestandBadge({ p }: { p: DraftPage }) {\n const t = paginaToestand(p);\n if (t === \"gewijzigd\") return <Badge tone=\"amber\">gewijzigd, nog niet live</Badge>;\n if (t === \"live\") return <Badge tone=\"green\">live</Badge>;\n if (t === \"prullenbak\") return <Badge>prullenbak</Badge>;\n return <Badge tone=\"amber\">concept</Badge>;\n}\n\n/**\n * Pagina-instellingen (7.24) — wat je NIET op de pagina zelf ziet: titel, adres, SEO, versies,\n * en de levenscyclus (publiceren, offline halen, dupliceren, prullenbak).\n *\n * Tot 7.24 stond hier een complete tweede editor: elk blok als formulier, met eigen ↑↓🗑, een\n * eigen publiceerknop zónder de \"wat is er veranderd\"-diff en zonder undo. Het dashboard stuurde\n * de klant intussen naar de site zelf (\"bewerk op de pagina\") — twee manieren voor één ding, met\n * twee gedragingen. De blokken bewerk je nu uitsluitend op de site (knop hieronder); dit scherm\n * gaat over de pagina als geheel.\n */\nexport function PageEditor({ siteId, page, allPages }: { siteId: string; page: DraftPage; allPages?: DraftPage[] }) {\n const { toast } = useToast();\n const confirm = useConfirm();\n const registry = useRegistry();\n const [draft, setDraft] = useState<DraftPage>(page);\n const [busy, setBusy] = useState<string | null>(null);\n const [saveState, setSaveState] = useState<SaveState>(\"idle\");\n const [versions, setVersions] = useState<VersionRow[]>([]);\n const [previewLink, setPreviewLink] = useState<PreviewLink | null>(null);\n const firstRender = useRef(true);\n const slugTouched = useRef(Boolean(page.slug));\n const nav = useAdminNav();\n /**\n * 8.10: de homepage is geen gewone pagina. Offline halen of weggooien gaf het héle domein een\n * 404, en een ander adres maakte van \"/\" een doorverwijzing. Dat kan nu niet meer (ook de\n * server en de rules weigeren het); de titel en de SEO blijven gewoon bewerkbaar.\n */\n const isHome = page.path === \"/\";\n /** Staat er een blok op waar de werking van de site op leunt (afrekenen, formulier …)? */\n function essentieelZin(): string {\n const labels = new Set<string>();\n bevatBlok(page.blocks ?? [], (b) => {\n const def = registry.get(String(b._type));\n if (def?.essentieel) labels.add(def.label);\n return false;\n });\n return labels.size ? ` Op deze pagina staat ${[...labels].map((l) => `“${l}”`).join(\" en \")} — daar werkt de site op.` : \"\";\n }\n\n // Wissel van pagina → herlaad lokale state. Bewust NIET op elke remote-update: dan zou een\n // autosave-echo je typwerk overschrijven.\n useEffect(() => {\n setDraft(page);\n firstRender.current = true;\n slugTouched.current = Boolean(page.slug);\n setPreviewLink(null);\n }, [page.id]); // eslint-disable-line react-hooks/exhaustive-deps\n // Toestand-velden volgen wél live (publiceren/offline halen gebeurt buiten dit formulier om).\n useEffect(() => {\n setDraft((d) => ({ ...d, published: page.published, updatedAt: page.updatedAt, lastPublishedAt: page.lastPublishedAt, trashed: page.trashed }));\n }, [page.published, page.updatedAt, page.lastPublishedAt, page.trashed]);\n\n useEffect(() => subscribeVersions(siteId, page.id, (v) => setVersions(v)), [siteId, page.id]);\n\n function persist(d: DraftPage) {\n setSaveState(\"saving\");\n // Alleen de metadata: de blokken zijn van de visuele editor. Zou dit `blocks` meesturen, dan\n // kon een verouderde kopie hier een net-gemaakte inline bewerking overschrijven.\n return saveDraft(siteId, d.id, { title: d.title, slug: d.slug, path: d.path, seo: d.seo })\n .then(() => setSaveState(\"saved\"))\n .catch(() => {\n setSaveState(\"error\");\n toast({ title: \"Opslaan mislukt\", description: \"Wijzigingen zijn nog niet opgeslagen.\", tone: \"error\" });\n });\n }\n\n useEffect(() => {\n if (firstRender.current) {\n firstRender.current = false;\n return;\n }\n const t = setTimeout(() => void persist(draft), 800);\n return () => clearTimeout(t);\n }, [draft.title, draft.slug, draft.path, draft.seo]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n const onBeforeUnload = (e: BeforeUnloadEvent) => {\n if (saveState === \"saving\" || saveState === \"error\") {\n e.preventDefault();\n e.returnValue = \"\";\n }\n };\n window.addEventListener(\"beforeunload\", onBeforeUnload);\n return () => window.removeEventListener(\"beforeunload\", onBeforeUnload);\n }, [saveState]);\n\n function update(next: DraftPage) {\n setDraft(next);\n }\n function setTitle(title: string) {\n const slug = slugTouched.current ? draft.slug : slugify(title);\n update({ ...draft, title, slug });\n }\n\n const seo = draft.seo ?? {};\n const padBotsing = allPages?.some((p) => p.id !== draft.id && !p.trashed && p.path === draft.path) ?? false;\n const padGewijzigd = Boolean(page.published && page.path !== draft.path);\n\n /** Naar de pagina op de site, met de bewerkmodus alvast aan (zelfde sleutel als EditorProvider). */\n function openOpSite() {\n try {\n sessionStorage.setItem(\"xicms-bewerkmodus\", \"bewerken\");\n } catch {\n /* geblokkeerde opslag: dan opent de pagina in kijkmodus en kies je \"Bewerken\" in de balk */\n }\n window.location.assign(draft.path || \"/\");\n }\n\n async function onPublish() {\n if (padBotsing) {\n toast({ title: \"Adres is al in gebruik\", description: \"Kies eerst een ander pad.\", tone: \"error\" });\n return;\n }\n // 8.4: dezelfde controle als in de editor (alt-teksten, dode links, Google-omschrijving).\n const ctx = await publicatieContext(siteId);\n const waarschuwingen = controleerPagina(draft, {\n bekendePaden: allPages ? allPages.filter((p) => !p.trashed).map((p) => p.path) : ctx.bekendePaden,\n livePaden: allPages ? allPages.filter((p) => !p.trashed && p.published).map((p) => p.path) : ctx.livePaden,\n redirects: ctx.redirects,\n });\n const ok = await confirm({\n title: \"Pagina publiceren?\",\n description: (\n <div className=\"grid gap-2\">\n <p>\n {padGewijzigd\n ? `De live site wordt bijgewerkt (${draft.path}). Het oude adres (${page.path}) verwijst automatisch door.`\n : `De live site wordt bijgewerkt (${draft.path}).`}\n </p>\n {waarschuwingen.length > 0 && (\n <div className=\"rounded-lg bg-amber-50 px-3 py-2 text-amber-900\">\n <p className=\"font-medium\">Even nakijken (je kunt ook gewoon publiceren):</p>\n <ul className=\"mt-1 list-disc pl-5\">\n {waarschuwingen.map((w, i) => (\n <li key={i}>{w.tekst}</li>\n ))}\n </ul>\n </div>\n )}\n </div>\n ),\n confirmLabel: \"Publiceren\",\n });\n if (!ok) return;\n setBusy(\"publish\");\n try {\n await saveDraft(siteId, draft.id, { title: draft.title, slug: draft.slug, path: draft.path, seo: draft.seo });\n await publishPage(siteId, draft.id);\n toast({ title: \"Gepubliceerd\", description: draft.path, tone: \"success\" });\n } catch (e) {\n toast({ title: \"Publiceren mislukt\", description: (e as Error).message, tone: \"error\" });\n } finally {\n setBusy(null);\n }\n }\n\n async function onUnpublish() {\n const gebruik = await laadPaginaGebruik(siteId, page.path, page.id);\n const zin = gebruik ? verwijzingenZin(gebruik) : null;\n const ok = await confirm({\n title: \"Pagina offline halen?\",\n description: `Bezoekers zien de pagina niet meer (het adres geeft een foutpagina). De werkversie blijft bewaard; publiceren zet hem weer live.${zin ? ` ${zin}` : \"\"}${essentieelZin()}`,\n confirmLabel: \"Offline halen\",\n tone: \"danger\",\n });\n if (!ok) return;\n setBusy(\"unpublish\");\n try {\n await unpublishPage(siteId, draft.id);\n toast({ title: \"Offline gehaald\", description: \"Binnen enkele minuten is de pagina niet meer te bezoeken. De werkversie blijft bewaard.\" });\n } catch (e) {\n toast({ title: \"Offline halen mislukt\", description: (e as Error).message, tone: \"error\" });\n } finally {\n setBusy(null);\n }\n }\n\n async function onDuplicate() {\n setBusy(\"dup\");\n try {\n await duplicatePage(siteId, draft, (allPages ?? []).map((p) => p.path));\n toast({ title: \"Pagina gedupliceerd\", description: \"De kopie staat als concept in de lijst.\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Dupliceren mislukt\", description: (e as Error).message, tone: \"error\" });\n } finally {\n setBusy(null);\n }\n }\n\n async function onTrash() {\n const gebruik = await laadPaginaGebruik(siteId, page.path, page.id);\n const zin = gebruik ? verwijzingenZin(gebruik) : null;\n const basis = page.published\n ? \"De pagina gaat offline en staat 30 dagen in de prullenbak; daarna wordt hij definitief verwijderd. Herstellen kan al die tijd.\"\n : \"De pagina staat 30 dagen in de prullenbak; daarna wordt hij definitief verwijderd. Herstellen kan al die tijd.\";\n const ok = await confirm({\n title: `\"${draft.title}\" naar de prullenbak?`,\n description: `${basis}${zin ? ` ${zin}` : \"\"}${essentieelZin()}`,\n confirmLabel: \"Naar prullenbak\",\n tone: \"danger\",\n });\n if (!ok) return;\n setBusy(\"trash\");\n try {\n await trashPage(siteId, draft);\n toast({\n title: \"In de prullenbak\",\n description: gebruik?.menu.length ? \"Onderaan de lijst te herstellen. Vergeet het menu-item niet.\" : \"Onderaan de lijst te herstellen.\",\n action: gebruik?.menu.length ? { label: \"Menu aanpassen\", onClick: () => nav(\"menu\") } : undefined,\n });\n } catch (e) {\n toast({ title: \"Mislukt\", description: (e as Error).message, tone: \"error\" });\n } finally {\n setBusy(null);\n }\n }\n\n async function maakPreviewLink() {\n const app = getFirebaseApp();\n if (!app) return;\n setBusy(\"preview\");\n try {\n const res = await callable<{ siteId: string; path: string }, { url: string; expiresAt: number }>(app, \"createPreviewLink\")({ siteId, path: draft.path });\n setPreviewLink(res.data);\n try {\n await navigator.clipboard?.writeText(res.data.url);\n toast({ title: \"Voorbeeldlink gekopieerd\", description: \"Zeven dagen geldig. Wie hem opent ziet de nieuwste stand, ook wat nog niet gepubliceerd is.\", tone: \"success\" });\n } catch {\n toast({ title: \"Voorbeeldlink gemaakt\", description: \"Kopieer hem hieronder.\", tone: \"success\" });\n }\n } catch (e) {\n toast({ title: \"Voorbeeldlink mislukt\", description: (e as Error).message, tone: \"error\" });\n } finally {\n setBusy(null);\n }\n }\n\n async function onRestore(versionId: string) {\n // 8.4: eerst laten zien wat er verandert — herstellen was blind (alleen een datum).\n const versie = await getVersieSnapshot(siteId, draft.id, versionId).catch(() => null);\n const verschil = versie ? vergelijkVersie(draft, versie, (t) => registry.get(t)?.label ?? t) : [];\n const ok = await confirm({\n title: \"Versie herstellen?\",\n description: (\n <div className=\"grid gap-2\">\n {verschil.length > 0 && (\n <ul className=\"list-disc pl-5\">\n {verschil.map((r, i) => (\n <li key={i}>{r}</li>\n ))}\n </ul>\n )}\n <p>De huidige werkversie wordt overschreven met deze versie (ongedaan te maken met een nieuwere versie). Publiceer daarna om het live te zetten.</p>\n </div>\n ),\n confirmLabel: \"Herstellen\",\n });\n if (!ok) return;\n try {\n const restored = await restoreVersion(siteId, draft.id, versionId);\n setDraft({ ...draft, ...restored });\n firstRender.current = true;\n toast({ title: \"Versie hersteld\", description: \"Controleer op de site en publiceer om live te zetten.\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Herstellen mislukt\", description: (e as Error).message, tone: \"error\" });\n }\n }\n\n const inPrullenbak = Boolean(draft.trashed);\n\n return (\n <div className=\"grid gap-4\">\n <Card>\n <div className=\"mb-3 flex flex-wrap items-center justify-between gap-2\">\n <div className=\"flex items-center gap-2\">\n <h3 className=\"text-base font-semibold\">Pagina</h3>\n <ToestandBadge p={draft} />\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-xs text-slate-500\" aria-live=\"polite\">\n {saveState === \"saving\" ? \"Opslaan…\" : saveState === \"saved\" ? \"✓ Opgeslagen\" : \"\"}\n </span>\n {saveState === \"error\" && (\n <Button variant=\"secondary\" size=\"sm\" onClick={() => void persist(draft)}>\n Opnieuw opslaan\n </Button>\n )}\n {!inPrullenbak && (\n <>\n <Button variant=\"secondary\" size=\"sm\" onClick={openOpSite} title=\"De tekst en blokken bewerk je op de pagina zelf\">\n ✎ Bewerken op de site\n </Button>\n <Button loading={busy === \"publish\"} size=\"sm\" onClick={onPublish} disabled={busy !== null}>\n {\"Publiceren\"}\n </Button>\n </>\n )}\n </div>\n </div>\n {saveState === \"error\" && (\n <div className=\"mb-3 rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700\">\n Niet alle wijzigingen zijn opgeslagen. Controleer je verbinding en klik “Opnieuw opslaan”.\n </div>\n )}\n <p className=\"mb-3 text-xs text-slate-500\">\n De inhoud (teksten, foto's, blokken) bewerk je op de pagina zelf via <em>Bewerken op de site</em>. Hier\n staan de dingen die je dáár niet ziet: de naam, het adres en hoe Google de pagina toont.\n </p>\n <div className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Titel\">\n <Input value={draft.title} onChange={(e) => setTitle(e.target.value)} />\n </Field>\n <Field label=\"Adres (pad)\" hint={isHome ? \"De homepage heeft altijd het adres /.\" : \"bv. /over-ons\"}>\n <Input\n readOnly={isHome}\n value={draft.path}\n onChange={(e) => update({ ...draft, path: e.target.value })}\n onBlur={() => {\n const parts = draft.path.split(\"/\").map((s) => slugify(s)).filter(Boolean);\n const normalized = \"/\" + parts.join(\"/\");\n if (normalized !== draft.path) update({ ...draft, path: normalized });\n }}\n />\n {padBotsing && (\n <p className=\"mt-1 text-xs text-red-600\" role=\"alert\">\n ⚠ Er bestaat al een pagina met dit adres — één van beide wordt dan onbereikbaar.\n </p>\n )}\n {padGewijzigd && !padBotsing && (\n <p className=\"mt-1 text-xs text-slate-500\">\n Na publiceren verwijst het oude adres ({page.path}) automatisch door naar het nieuwe.\n </p>\n )}\n </Field>\n </div>\n </Card>\n\n <Card>\n <h3 className=\"mb-1 text-base font-semibold\">In Google en bij het delen</h3>\n <p className=\"mb-3 text-xs text-slate-500\">Zo ziet de pagina eruit in zoekresultaten en als iemand de link deelt op social media of WhatsApp.</p>\n <div className=\"grid gap-3\">\n <Field label=\"Titel in zoekresultaten\" hint=\"Leeg = de paginatitel\">\n <Input value={seo.title ?? \"\"} onChange={(e) => update({ ...draft, seo: { ...seo, title: e.target.value } })} />\n <MeterRegel m={titelMeter(seo.title, draft.title)} />\n </Field>\n <Field label=\"Omschrijving\" hint=\"Eén of twee zinnen die uitnodigen om te klikken\">\n <Textarea rows={2} value={seo.description ?? \"\"} onChange={(e) => update({ ...draft, seo: { ...seo, description: e.target.value } })} />\n <MeterRegel m={omschrijvingMeter(seo.description)} />\n </Field>\n <Field label=\"Afbeelding bij het delen\" hint=\"Verschijnt als voorbeeld op social media en in WhatsApp. Leeg = de standaardafbeelding van de site.\">\n <div className=\"flex flex-wrap items-center gap-2\">\n {seo.ogImage && (\n // eslint-disable-next-line @next/next/no-img-element\n <img src={seo.ogImage} alt=\"\" className=\"h-14 w-24 rounded-md border border-slate-200 object-cover\" />\n )}\n <MediaPickerButton siteId={siteId} label={seo.ogImage ? \"Andere kiezen\" : \"Kies / upload\"} onSelect={(m) => update({ ...draft, seo: { ...seo, ogImage: m.url } })} />\n {seo.ogImage && (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => update({ ...draft, seo: { ...seo, ogImage: undefined } })}>\n Weghalen\n </Button>\n )}\n </div>\n </Field>\n <Switch\n checked={Boolean(seo.noindex)}\n onCheckedChange={(v) => update({ ...draft, seo: { ...seo, noindex: v || undefined } })}\n label=\"Niet opnemen in Google (bijvoorbeeld een bedankt- of actiepagina)\"\n />\n </div>\n </Card>\n\n {!inPrullenbak && (\n <Card>\n <h3 className=\"mb-1 text-base font-semibold\">Delen vóór publiceren</h3>\n <p className=\"mb-3 text-xs text-slate-500\">\n Laat iemand zonder inlog meekijken naar de werkversie. De link werkt zeven dagen en geeft geen toegang tot het beheer.\n </p>\n <div className=\"grid gap-2\">\n <div>\n <Button loading={busy === \"preview\"} variant=\"secondary\" size=\"sm\" disabled={busy !== null || isDemoActive()} onClick={() => void maakPreviewLink()}>\n {previewLink ? \"Nieuwe link maken\" : \"Voorbeeldlink maken\"}\n </Button>\n </div>\n {previewLink && <PreviewLinkResultaat link={previewLink} titel={draft.title} />}\n </div>\n </Card>\n )}\n\n {!inPrullenbak && <LeesbaarheidPaneel tekst={paginaTekst(draft.blocks)} titel=\"Leesbaarheid van deze pagina\" />}\n\n {!inPrullenbak && !isDemoActive() && <PlanningKaart siteId={siteId} page={page} />}\n\n {versions.length > 0 && (\n <Card>\n <h4 className=\"mb-2 text-sm font-semibold\">Versiegeschiedenis</h4>\n <ul className=\"grid gap-1 text-sm text-slate-600\">\n {versions.slice(0, 10).map((v) => (\n <li key={v.id} className=\"flex items-center justify-between border-b border-slate-100 py-1 last:border-0\">\n <span>\n {v.label ?? (v.kind === \"publish\" ? \"Gepubliceerd\" : \"Opgeslagen versie\")}\n {formatVersionDate(v.createdAt) && <span className=\"text-slate-500\"> · {formatVersionDate(v.createdAt)}</span>}\n </span>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => void onRestore(v.id)}>\n Herstellen\n </Button>\n </li>\n ))}\n </ul>\n </Card>\n )}\n\n {!inPrullenbak && (\n <div className=\"flex flex-wrap items-center justify-end gap-3 border-t border-slate-200 pt-4\">\n <Button loading={busy === \"dup\"} variant=\"ghost\" size=\"sm\" disabled={busy !== null} onClick={() => void onDuplicate()}>\n {\"Dupliceren\"}\n </Button>\n {isHome ? (\n <span className=\"text-xs text-slate-500\">De homepage kan niet offline of in de prullenbak.</span>\n ) : (\n <>\n {page.published && (\n <Button loading={busy === \"unpublish\"} variant=\"ghost\" size=\"sm\" disabled={busy !== null} onClick={() => void onUnpublish()}>\n {\"Offline halen\"}\n </Button>\n )}\n <Button variant=\"dangerGhost\" size=\"sm\" disabled={busy !== null} onClick={() => void onTrash()}>\n Naar prullenbak\n </Button>\n </>\n )}\n </div>\n )}\n </div>\n );\n}\n\n/** \"2026-10-18T09:30\" (datetime-local) ↔ Date, in de tijdzone van de gebruiker. */\nfunction naarInvoer(d: Date | null): string {\n if (!d) return \"\";\n const p = (n: number) => String(n).padStart(2, \"0\");\n return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}T${p(d.getHours())}:${p(d.getMinutes())}`;\n}\nfunction uitInvoer(v: string): Date | null {\n if (!v) return null;\n const d = new Date(v);\n return Number.isNaN(d.getTime()) ? null : d;\n}\n\n/**\n * Inplannen (8.4): de pagina op een gekozen moment automatisch publiceren en/of offline halen —\n * een actie die om middernacht ingaat, een vacature die na de sluitingsdatum verdwijnt. De planner\n * in de functions loopt elke 10 minuten; dat staat er eerlijk bij.\n */\nfunction PlanningKaart({ siteId, page }: { siteId: string; page: DraftPage }) {\n const { toast } = useToast();\n const [aan, setAan] = useState(() => naarInvoer(planningDatum(page.publishAt)));\n const [uit, setUit] = useState(() => naarInvoer(planningDatum(page.unpublishAt)));\n const [bezig, setBezig] = useState(false);\n useEffect(() => {\n setAan(naarInvoer(planningDatum(page.publishAt)));\n setUit(naarInvoer(planningDatum(page.unpublishAt)));\n }, [page.publishAt, page.unpublishAt]);\n\n const aanDatum = uitInvoer(aan);\n const uitDatum = uitInvoer(uit);\n const fout =\n aanDatum && aanDatum.getTime() < Date.now() - 60_000\n ? \"Het publicatiemoment ligt in het verleden.\"\n : aanDatum && uitDatum && uitDatum <= aanDatum\n ? \"Offline halen moet ná het publiceren liggen.\"\n : null;\n\n async function opslaan() {\n if (fout) return;\n setBezig(true);\n try {\n await zetPlanning(siteId, page.id, { publishAt: aanDatum, unpublishAt: uitDatum });\n toast({\n title: aanDatum || uitDatum ? \"Ingepland\" : \"Planning gewist\",\n description: aanDatum || uitDatum ? \"Wordt uitgevoerd binnen 10 minuten na het gekozen moment.\" : undefined,\n tone: \"success\",\n });\n } catch (e) {\n toast({ title: \"Inplannen mislukt\", description: (e as Error).message, tone: \"error\" });\n } finally {\n setBezig(false);\n }\n }\n\n const lang = (d: Date) => d.toLocaleString(\"nl-NL\", { weekday: \"long\", day: \"numeric\", month: \"long\", hour: \"2-digit\", minute: \"2-digit\" });\n return (\n <Card>\n <h4 className=\"mb-1 text-sm font-semibold\">Inplannen</h4>\n <p className=\"mb-3 text-xs text-slate-500\">\n Laat de pagina op een gekozen moment vanzelf live gaan of verdwijnen — bijvoorbeeld een actie of een\n vacature. Gebeurt binnen 10 minuten na het gekozen moment; bij publiceren gaat de werkversie live\n zoals die dan is.\n </p>\n {page.planningFout && (\n <p role=\"alert\" className=\"mb-3 rounded-lg bg-red-50 px-3 py-2 text-sm text-red-800\">\n De vorige planning is niet gelukt: {page.planningFout}\n </p>\n )}\n <div className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Automatisch publiceren op\" hint={aanDatum ? lang(aanDatum) : \"Leeg = niet ingepland\"}>\n <Input type=\"datetime-local\" value={aan} onChange={(e) => setAan(e.target.value)} />\n </Field>\n <Field label=\"Automatisch offline halen op\" hint={uitDatum ? lang(uitDatum) : \"Leeg = blijft staan\"}>\n <Input type=\"datetime-local\" value={uit} onChange={(e) => setUit(e.target.value)} />\n </Field>\n </div>\n {fout && <p role=\"alert\" className=\"mt-2 text-sm text-red-700\">{fout}</p>}\n <div className=\"mt-3 flex gap-2\">\n <Button loading={bezig} size=\"sm\" variant=\"secondary\" disabled={bezig || Boolean(fout)} onClick={() => void opslaan()}>\n {\"Planning opslaan\"}\n </Button>\n {Boolean(page.publishAt || page.unpublishAt) && (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n disabled={bezig}\n onClick={() => {\n setAan(\"\");\n setUit(\"\");\n void zetPlanning(siteId, page.id, { publishAt: null, unpublishAt: null })\n .then(() => toast({ title: \"Planning gewist\", tone: \"success\" }))\n .catch((e: Error) => toast({ title: \"Wissen mislukt\", description: e.message, tone: \"error\" }));\n }}\n >\n Planning wissen\n </Button>\n )}\n </div>\n </Card>\n );\n}\n"],"mappings":"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","names":[]}
|