create-snapify-app 0.0.0-stage → 1.1.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/LICENSE.md +24 -0
- package/README.md +55 -2
- package/bin/create-snapify-app.mjs +174 -0
- package/lib/args.mjs +59 -0
- package/lib/copy.mjs +44 -0
- package/lib/env.mjs +84 -0
- package/lib/prompt.mjs +63 -0
- package/package.json +33 -4
- package/template/.env.example +79 -0
- package/template/.github/workflows/ci.yml +23 -0
- package/template/.github/workflows/deploy.yml +26 -0
- package/template/.github/workflows/ping.yml +8 -0
- package/template/.github/workflows/release.yml +67 -0
- package/template/.snapify-install.json +5 -0
- package/template/CHANGELOG.md +28 -0
- package/template/LICENSE +14 -0
- package/template/README.md +287 -0
- package/template/administrator.html +23 -0
- package/template/apps/client/src/App.tsx +765 -0
- package/template/apps/client/src/auth.css +400 -0
- package/template/apps/client/src/lib/api.ts +22 -0
- package/template/apps/client/src/main.tsx +20 -0
- package/template/apps/community/src/App.tsx +592 -0
- package/template/apps/community/src/main.tsx +20 -0
- package/template/apps/community/src/styles.css +24 -0
- package/template/apps/developers/src/App.tsx +643 -0
- package/template/apps/developers/src/main.tsx +17 -0
- package/template/apps/developers/src/pages.tsx +1587 -0
- package/template/apps/developers/src/styles.css +98 -0
- package/template/apps/developers/src/ui.tsx +179 -0
- package/template/apps/landing/src/App.tsx +598 -0
- package/template/apps/landing/src/LegalPages.tsx +158 -0
- package/template/apps/landing/src/OrderPage.tsx +381 -0
- package/template/apps/landing/src/SeoPages.tsx +923 -0
- package/template/apps/landing/src/copy.ts +195 -0
- package/template/apps/landing/src/main.tsx +20 -0
- package/template/apps/landing/src/styles.css +803 -0
- package/template/apps/landing/src/types.ts +19 -0
- package/template/apps/marketplace/src/App.tsx +1229 -0
- package/template/apps/marketplace/src/developer/DeveloperApp.tsx +1266 -0
- package/template/apps/marketplace/src/main.tsx +20 -0
- package/template/apps/marketplace/src/styles.css +1001 -0
- package/template/apps/shared/AuthContext.tsx +65 -0
- package/template/apps/shared/Logo.tsx +33 -0
- package/template/apps/shared/api.ts +47 -0
- package/template/apps/shared/ui.tsx +128 -0
- package/template/apps/superadmin/src/App.tsx +1264 -0
- package/template/apps/superadmin/src/lib/api.ts +20 -0
- package/template/apps/superadmin/src/lib/hooks.ts +20 -0
- package/template/apps/superadmin/src/main.tsx +16 -0
- package/template/apps/superadmin/src/pages/ClientsPage.tsx +185 -0
- package/template/apps/superadmin/src/pages/InvoicesPage.tsx +157 -0
- package/template/apps/superadmin/src/pages/NewsletterPage.tsx +212 -0
- package/template/apps/superadmin/src/pages/OrdersPage.tsx +195 -0
- package/template/apps/superadmin/src/pages/PaymentsPage.tsx +150 -0
- package/template/apps/superadmin/src/pages/PayoutsPage.tsx +133 -0
- package/template/apps/superadmin/src/pages/PublishersPage.tsx +151 -0
- package/template/apps/superadmin/src/pages/SeoControlPage.tsx +692 -0
- package/template/apps/superadmin/src/pages/SettingsPage.tsx +199 -0
- package/template/apps/superadmin/src/pages/SystemPage.tsx +109 -0
- package/template/apps/superadmin/src/pages/TicketsPage.tsx +201 -0
- package/template/apps/superadmin/src/pages/UsersPage.tsx +167 -0
- package/template/client.html +21 -0
- package/template/community/hamdiayari/akhbar/README.md +23 -0
- package/template/community/hamdiayari/akhbar/screenshot.jpg +0 -0
- package/template/community/hamdiayari/akhbar/snapify.theme.json +76 -0
- package/template/community/hamdiayari/akhbar/src/Brand.tsx +26 -0
- package/template/community/hamdiayari/akhbar/src/Footer.tsx +182 -0
- package/template/community/hamdiayari/akhbar/src/Header.tsx +191 -0
- package/template/community/hamdiayari/akhbar/src/Layout.tsx +49 -0
- package/template/community/hamdiayari/akhbar/src/Social.tsx +33 -0
- package/template/community/hamdiayari/akhbar/src/Ticker.tsx +86 -0
- package/template/community/hamdiayari/akhbar/src/Views.tsx +285 -0
- package/template/community/hamdiayari/akhbar/src/blocks/CollectionBlocks.tsx +672 -0
- package/template/community/hamdiayari/akhbar/src/blocks/ContentBlocks.tsx +305 -0
- package/template/community/hamdiayari/akhbar/src/blocks/ConversionBlocks.tsx +569 -0
- package/template/community/hamdiayari/akhbar/src/blocks/HeaderBlocks.tsx +287 -0
- package/template/community/hamdiayari/akhbar/src/index.tsx +51 -0
- package/template/community/hamdiayari/akhbar/src/kit.tsx +357 -0
- package/template/community/hamdiayari/akhbar/src/site.ts +96 -0
- package/template/community/hamdiayari/akhbar/src/styles.css +566 -0
- package/template/community/hamdiayari/akhbar-actualites/README.md +28 -0
- package/template/community/hamdiayari/akhbar-actualites/screenshot.jpg +0 -0
- package/template/community/hamdiayari/akhbar-actualites/snapify.module.json +107 -0
- package/template/community/hamdiayari/akhbar-actualites/src/admin/AudiencePage.tsx +185 -0
- package/template/community/hamdiayari/akhbar-actualites/src/admin/index.tsx +11 -0
- package/template/community/hamdiayari/akhbar-actualites/src/public/Archive.tsx +142 -0
- package/template/community/hamdiayari/akhbar-actualites/src/public/cards.tsx +152 -0
- package/template/community/hamdiayari/akhbar-actualites/src/public/index.tsx +71 -0
- package/template/community/hamdiayari/akhbar-actualites/src/public/posts.ts +103 -0
- package/template/community/hamdiayari/akhbar-actualites/src/public/styles.css +568 -0
- package/template/community/hamdiayari/akhbar-actualites/src/public/widgets.tsx +226 -0
- package/template/community/hamdiayari/akhbar-actualites/src/server.ts +119 -0
- package/template/community/hamdiayari/akhbar-actualites/src/types.ts +25 -0
- package/template/community/hamdiayari/akhbar-urgent/README.md +36 -0
- package/template/community/hamdiayari/akhbar-urgent/screenshot.jpg +0 -0
- package/template/community/hamdiayari/akhbar-urgent/snapify.module.json +64 -0
- package/template/community/hamdiayari/akhbar-urgent/src/admin/FlashesPage.tsx +229 -0
- package/template/community/hamdiayari/akhbar-urgent/src/admin/index.tsx +11 -0
- package/template/community/hamdiayari/akhbar-urgent/src/public/Ticker.tsx +81 -0
- package/template/community/hamdiayari/akhbar-urgent/src/public/index.tsx +63 -0
- package/template/community/hamdiayari/akhbar-urgent/src/public/styles.css +142 -0
- package/template/community/hamdiayari/akhbar-urgent/src/server.ts +101 -0
- package/template/community/hamdiayari/akhbar-urgent/src/types.ts +35 -0
- package/template/community.html +21 -0
- package/template/developers.html +24 -0
- package/template/docker-compose.db.yml +24 -0
- package/template/docs/BACKOFFICE_SNAPIFY.md +130 -0
- package/template/docs/CI_CD.md +66 -0
- package/template/docs/MODULES.md +346 -0
- package/template/docs/PLATFORM_DEPLOY.md +54 -0
- package/template/docs/logo.svg +10 -0
- package/template/drizzle/0000_init.sql +147 -0
- package/template/drizzle/0001_page_project.sql +5 -0
- package/template/drizzle/0002_modules.sql +23 -0
- package/template/drizzle/0003_themes.sql +4 -0
- package/template/drizzle/0004_security.sql +82 -0
- package/template/drizzle/0005_module_records.sql +16 -0
- package/template/drizzle/0006_avatars.sql +4 -0
- package/template/drizzle/0007_platform.sql +264 -0
- package/template/drizzle/0008_mp_validation.sql +3 -0
- package/template/drizzle/0009_saas_ops.sql +77 -0
- package/template/drizzle/0010_cms_chrome.sql +13 -0
- package/template/drizzle/0011_client_portal.sql +26 -0
- package/template/drizzle/meta/0000_snapshot.json +998 -0
- package/template/drizzle/meta/0001_snapshot.json +1004 -0
- package/template/drizzle/meta/_journal.json +90 -0
- package/template/drizzle.config.ts +16 -0
- package/template/ecosystem.snapify.cjs +24 -0
- package/template/for.html +1 -0
- package/template/index.html +29 -0
- package/template/landing.html +37 -0
- package/template/marketplace/catalog.json +373 -0
- package/template/marketplace/gallery/hamdiayari.preveris/01-home.jpg +0 -0
- package/template/marketplace/gallery/hamdiayari.recaptcha/01-reglages.jpg +0 -0
- package/template/marketplace/gallery/hamdiayari.recaptcha/02-logo.jpg +0 -0
- package/template/marketplace/gallery/novalabs.ai-articles/01-generer.jpg +0 -0
- package/template/marketplace/gallery/novalabs.ai-articles/02-fournisseur-ia.jpg +0 -0
- package/template/marketplace/gallery/novalabs.calendar/01-agenda-site.jpg +0 -0
- package/template/marketplace/gallery/novalabs.calendar/02-evenements-admin.jpg +0 -0
- package/template/marketplace/gallery/novalabs.calendar/03-reglages.jpg +0 -0
- package/template/marketplace/screenshots/hamdiayari.preveris-1.0.6.jpg +0 -0
- package/template/marketplace/screenshots/hamdiayari.recaptcha-1.0.0.jpg +0 -0
- package/template/marketplace/screenshots/hamdiayari.wp-seo-migrator-1.1.1.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.ai-articles-1.0.1.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.ai-chat-1.0.1.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.calendar-1.0.1.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.cart-1.0.0.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.checkout-1.0.0.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.customers-1.1.0.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.dogga-1.0.0.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.mahdia-1.0.0.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.shop-1.0.0.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.sidibou-1.0.0.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.whatsapp-1.0.1.jpg +0 -0
- package/template/marketplace.html +21 -0
- package/template/metadata.json +7 -0
- package/template/modules/ai-articles/screenshot.jpg +0 -0
- package/template/modules/ai-articles/snapify.module.json +74 -0
- package/template/modules/ai-articles/src/admin/ArticlesPage.tsx +162 -0
- package/template/modules/ai-articles/src/admin/GeneratePage.tsx +118 -0
- package/template/modules/ai-articles/src/admin/index.tsx +12 -0
- package/template/modules/ai-articles/src/public/index.tsx +119 -0
- package/template/modules/ai-articles/src/server.ts +287 -0
- package/template/modules/ai-articles/src/types.ts +30 -0
- package/template/modules/ai-chat/screenshot.jpg +0 -0
- package/template/modules/ai-chat/snapify.module.json +217 -0
- package/template/modules/ai-chat/src/public.tsx +198 -0
- package/template/modules/ai-chat/src/server.ts +142 -0
- package/template/modules/ai-theme-studio/README.md +15 -0
- package/template/modules/ai-theme-studio/screenshot.jpg +0 -0
- package/template/modules/ai-theme-studio/snapify.module.json +175 -0
- package/template/modules/ai-theme-studio/src/admin/HistoryPage.tsx +91 -0
- package/template/modules/ai-theme-studio/src/admin/StudioPage.tsx +414 -0
- package/template/modules/ai-theme-studio/src/admin/index.tsx +11 -0
- package/template/modules/ai-theme-studio/src/lib/images.ts +240 -0
- package/template/modules/ai-theme-studio/src/lib/llm.ts +123 -0
- package/template/modules/ai-theme-studio/src/lib/normalize.ts +714 -0
- package/template/modules/ai-theme-studio/src/lib/prompts.ts +198 -0
- package/template/modules/ai-theme-studio/src/server.ts +137 -0
- package/template/modules/ai-theme-studio/src/types.ts +112 -0
- package/template/modules/calendar/screenshot.jpg +0 -0
- package/template/modules/calendar/snapify.module.json +45 -0
- package/template/modules/calendar/src/admin/EventsPage.tsx +217 -0
- package/template/modules/calendar/src/admin/index.tsx +11 -0
- package/template/modules/calendar/src/public/index.tsx +231 -0
- package/template/modules/calendar/src/server.ts +143 -0
- package/template/modules/calendar/src/types.ts +25 -0
- package/template/modules/cart/screenshot.jpg +0 -0
- package/template/modules/cart/snapify.module.json +90 -0
- package/template/modules/cart/src/admin/index.tsx +265 -0
- package/template/modules/cart/src/public/CartPage.tsx +198 -0
- package/template/modules/cart/src/public/index.tsx +261 -0
- package/template/modules/cart/src/public/useQuote.ts +67 -0
- package/template/modules/cart/src/server.ts +148 -0
- package/template/modules/cart/src/types.ts +31 -0
- package/template/modules/checkout/screenshot.jpg +0 -0
- package/template/modules/checkout/snapify.module.json +264 -0
- package/template/modules/checkout/src/admin/OrderDetailPage.tsx +304 -0
- package/template/modules/checkout/src/admin/badges.tsx +28 -0
- package/template/modules/checkout/src/admin/index.tsx +236 -0
- package/template/modules/checkout/src/public/CheckoutPage.tsx +461 -0
- package/template/modules/checkout/src/public/OrderPages.tsx +153 -0
- package/template/modules/checkout/src/public/index.tsx +23 -0
- package/template/modules/checkout/src/server.ts +383 -0
- package/template/modules/checkout/src/types.ts +70 -0
- package/template/modules/customers/screenshot.jpg +0 -0
- package/template/modules/customers/snapify.module.json +115 -0
- package/template/modules/customers/src/admin/CustomerDetailPage.tsx +274 -0
- package/template/modules/customers/src/admin/index.tsx +194 -0
- package/template/modules/customers/src/public/AccountPages.tsx +470 -0
- package/template/modules/customers/src/public/AddressForm.tsx +115 -0
- package/template/modules/customers/src/public/AuthPages.tsx +349 -0
- package/template/modules/customers/src/public/Avatar.tsx +29 -0
- package/template/modules/customers/src/public/ProfileSection.tsx +291 -0
- package/template/modules/customers/src/public/index.tsx +137 -0
- package/template/modules/customers/src/public/session.ts +51 -0
- package/template/modules/customers/src/server.ts +421 -0
- package/template/modules/customers/src/types.ts +53 -0
- package/template/modules/recaptcha/logo.jpg +0 -0
- package/template/modules/recaptcha/screenshot.jpg +0 -0
- package/template/modules/recaptcha/snapify.module.json +99 -0
- package/template/modules/recaptcha/src/public/index.tsx +94 -0
- package/template/modules/recaptcha/src/server.ts +65 -0
- package/template/modules/recaptcha/src/types.ts +18 -0
- package/template/modules/shop/screenshot.jpg +0 -0
- package/template/modules/shop/snapify.module.json +340 -0
- package/template/modules/shop/src/admin/CategoriesPage.tsx +224 -0
- package/template/modules/shop/src/admin/ProductEditor.tsx +313 -0
- package/template/modules/shop/src/admin/ProductsPage.tsx +307 -0
- package/template/modules/shop/src/admin/index.tsx +14 -0
- package/template/modules/shop/src/public/Catalog.tsx +244 -0
- package/template/modules/shop/src/public/NotFound.tsx +22 -0
- package/template/modules/shop/src/public/ProductPage.tsx +195 -0
- package/template/modules/shop/src/public/index.tsx +134 -0
- package/template/modules/shop/src/public/useFetch.ts +26 -0
- package/template/modules/shop/src/server.ts +493 -0
- package/template/modules/shop/src/shared.ts +41 -0
- package/template/modules/shop/src/types.ts +60 -0
- package/template/modules/whatsapp/screenshot.jpg +0 -0
- package/template/modules/whatsapp/snapify.module.json +121 -0
- package/template/modules/whatsapp/src/public.tsx +119 -0
- package/template/modules/wp-seo-migrator/ARCHITECTURE.md +113 -0
- package/template/modules/wp-seo-migrator/README.md +21 -0
- package/template/modules/wp-seo-migrator/fixtures/aioseo-sample.csv +3 -0
- package/template/modules/wp-seo-migrator/fixtures/sample-exporter.json +39 -0
- package/template/modules/wp-seo-migrator/fixtures/sample-page.html +12 -0
- package/template/modules/wp-seo-migrator/fixtures/sample.htaccess +3 -0
- package/template/modules/wp-seo-migrator/screenshot.jpg +0 -0
- package/template/modules/wp-seo-migrator/snapify.module.json +87 -0
- package/template/modules/wp-seo-migrator/src/admin/HistoryPage.tsx +64 -0
- package/template/modules/wp-seo-migrator/src/admin/WizardPage.tsx +788 -0
- package/template/modules/wp-seo-migrator/src/admin/i18n.ts +156 -0
- package/template/modules/wp-seo-migrator/src/admin/index.tsx +11 -0
- package/template/modules/wp-seo-migrator/src/connectors/CUSTOM_CONNECTOR.md +31 -0
- package/template/modules/wp-seo-migrator/src/connectors/csvSeoFactory.ts +106 -0
- package/template/modules/wp-seo-migrator/src/connectors/exporter.ts +96 -0
- package/template/modules/wp-seo-migrator/src/connectors/gscCsv.ts +53 -0
- package/template/modules/wp-seo-migrator/src/connectors/htaccess.ts +65 -0
- package/template/modules/wp-seo-migrator/src/connectors/htmlCrawler.ts +90 -0
- package/template/modules/wp-seo-migrator/src/connectors/index.ts +113 -0
- package/template/modules/wp-seo-migrator/src/connectors/pluginCsv.ts +77 -0
- package/template/modules/wp-seo-migrator/src/connectors/rankMathCsv.ts +77 -0
- package/template/modules/wp-seo-migrator/src/connectors/redirection.ts +62 -0
- package/template/modules/wp-seo-migrator/src/connectors/sitemap.ts +44 -0
- package/template/modules/wp-seo-migrator/src/connectors/utils.ts +111 -0
- package/template/modules/wp-seo-migrator/src/connectors/wxr.ts +103 -0
- package/template/modules/wp-seo-migrator/src/connectors/yoastCsv.ts +56 -0
- package/template/modules/wp-seo-migrator/src/pipeline/analyze.ts +158 -0
- package/template/modules/wp-seo-migrator/src/pipeline/htmlParse.ts +58 -0
- package/template/modules/wp-seo-migrator/src/pipeline/remoteAuto.ts +328 -0
- package/template/modules/wp-seo-migrator/src/server.ts +492 -0
- package/template/modules/wp-seo-migrator/src/types.ts +151 -0
- package/template/modules/wp-seo-migrator/tests/connectors-extra.test.ts +39 -0
- package/template/modules/wp-seo-migrator/tests/merge.test.ts +25 -0
- package/template/package-lock.json +6016 -0
- package/template/package.json +74 -0
- package/template/public/images/photos/caravane-chameaux-desert.webp +0 -0
- package/template/public/images/photos/hammamet-medina-plage.jpg +0 -0
- package/template/public/images/photos/maison-campagne-collines.webp +0 -0
- package/template/public/images/photos/maisons-troglodytes-desert.jpg +0 -0
- package/template/public/images/photos/panorama-ville.jpg +0 -0
- package/template/public/images/photos/preveris-accessibilite-erp.jpg +0 -0
- package/template/public/images/photos/preveris-collectivites.jpg +0 -0
- package/template/public/images/photos/preveris-etudes-plans.jpg +0 -0
- package/template/public/images/photos/preveris-hero-erp.jpg +0 -0
- package/template/public/images/photos/preveris-ssi-incendie.jpg +0 -0
- package/template/public/images/photos/preveris-suivi-hotel.jpg +0 -0
- package/template/public/images/photos/ruelle-bleue-medina.jpg +0 -0
- package/template/public/images/photos/sidi-bou-said-port.webp +0 -0
- package/template/public/images/photos/terrasse-blanche-mer-voilier.jpg +0 -0
- package/template/public/landing/hero-ai-cms.jpg +0 -0
- package/template/public/landing/shot-dogga.jpg +0 -0
- package/template/public/landing/shot-mahdia.jpg +0 -0
- package/template/public/landing/shot-sidibou.jpg +0 -0
- package/template/public/llms.txt +35 -0
- package/template/public/logo.svg +10 -0
- package/template/scripts/app-pack.ts +155 -0
- package/template/scripts/app-publish.ts +100 -0
- package/template/scripts/apply-ecommerce-home.ts +196 -0
- package/template/scripts/auto-deploy-poll.sh +13 -0
- package/template/scripts/db-backup.sh +16 -0
- package/template/scripts/db-restore.sh +11 -0
- package/template/scripts/deploy.sh +34 -0
- package/template/scripts/github-webhook-deploy.sh +7 -0
- package/template/scripts/install-new-modules.ts +96 -0
- package/template/scripts/refresh-demo-baseline.ts +9 -0
- package/template/scripts/reinstall-marketplace-packs.ts +51 -0
- package/template/scripts/restore-classic-home.ts +13 -0
- package/template/scripts/sdk-pack.ts +289 -0
- package/template/scripts/sdk-publish.ts +75 -0
- package/template/scripts/seed-demo-products.ts +120 -0
- package/template/scripts/seed-theme-content-packs.ts +42 -0
- package/template/scripts/snapify-module.ts +207 -0
- package/template/scripts/test-theme-switch.ts +24 -0
- package/template/sdk/admin.css +18 -0
- package/template/sdk/admin.ts +95 -0
- package/template/sdk/build.ts +249 -0
- package/template/sdk/commerce.ts +512 -0
- package/template/sdk/content.ts +76 -0
- package/template/sdk/icons.ts +101 -0
- package/template/sdk/image.ts +60 -0
- package/template/sdk/index.ts +500 -0
- package/template/sdk/package.ts +298 -0
- package/template/sdk/recaptcha.tsx +122 -0
- package/template/sdk/settings.ts +84 -0
- package/template/sdk/theme.css +29 -0
- package/template/sdk/theme.ts +100 -0
- package/template/sdk/ui/commerce.tsx +385 -0
- package/template/sdk/ui/orders.tsx +136 -0
- package/template/sdk-kit/CHANGELOG.md +17 -0
- package/template/sdk-kit/LICENSE.md +47 -0
- package/template/sdk-kit/README.md +81 -0
- package/template/sdk-kit/cli.ts +339 -0
- package/template/sdk-kit/create-snapify/README.md +28 -0
- package/template/sdk-kit/create-snapify/create-snapify.mjs +11 -0
- package/template/sdk-kit/create-snapify/package.template.json +16 -0
- package/template/sdk-kit/package.template.json +95 -0
- package/template/sdk-kit/templates/common/README.md.tpl +27 -0
- package/template/sdk-kit/templates/common/_gitignore +3 -0
- package/template/sdk-kit/templates/common/package.json.tpl +19 -0
- package/template/sdk-kit/templates/common/src/snapify-env.d.ts +2 -0
- package/template/sdk-kit/templates/common/tsconfig.json +15 -0
- package/template/sdk-kit/templates/module/snapify.module.json.tpl +33 -0
- package/template/sdk-kit/templates/module/src/admin.tsx +53 -0
- package/template/sdk-kit/templates/module/src/public.tsx +49 -0
- package/template/sdk-kit/templates/module/src/server.ts +30 -0
- package/template/sdk-kit/templates/module/src/types.ts +19 -0
- package/template/sdk-kit/templates/theme/snapify.theme.json.tpl +22 -0
- package/template/sdk-kit/templates/theme/src/Footer.tsx +40 -0
- package/template/sdk-kit/templates/theme/src/Header.tsx +47 -0
- package/template/sdk-kit/templates/theme/src/Views.tsx +36 -0
- package/template/sdk-kit/templates/theme/src/blocks.tsx +93 -0
- package/template/sdk-kit/templates/theme/src/index.tsx +30 -0
- package/template/sdk-kit/templates/theme/src/site.tsx +59 -0
- package/template/sdk-kit/templates/theme/src/styles.css +71 -0
- package/template/server/client/routes.ts +252 -0
- package/template/server/cms/analyticsStore.ts +180 -0
- package/template/server/cms/auth.ts +155 -0
- package/template/server/cms/blockCatalog.ts +342 -0
- package/template/server/cms/blocks.ts +521 -0
- package/template/server/cms/contentMigration.ts +1119 -0
- package/template/server/cms/defaults.ts +303 -0
- package/template/server/cms/permissions.ts +154 -0
- package/template/server/cms/restoreClassicHome.ts +183 -0
- package/template/server/cms/revisions.ts +99 -0
- package/template/server/cms/scheduler.ts +78 -0
- package/template/server/cms/seed.ts +72 -0
- package/template/server/cms/seoAnalyzer.ts +213 -0
- package/template/server/cms/store.ts +122 -0
- package/template/server/cms/themeContent.ts +1386 -0
- package/template/server/cms/themePacks/sidibou-branding.json +1 -0
- package/template/server/cms/themePacks/sidibou-home.json +1 -0
- package/template/server/cms/themePacks/sidibou-menus.json +1 -0
- package/template/server/cms/types.ts +432 -0
- package/template/server/community/routes.ts +410 -0
- package/template/server/db/client.ts +43 -0
- package/template/server/db/repository.ts +389 -0
- package/template/server/db/schema.ts +726 -0
- package/template/server/demo/cmsReset.ts +196 -0
- package/template/server/developers/sdk.ts +85 -0
- package/template/server/geoip.ts +15 -0
- package/template/server/http.ts +53 -0
- package/template/server/mail.ts +216 -0
- package/template/server/marketplace/catalog.ts +74 -0
- package/template/server/marketplace/packageValidate.ts +475 -0
- package/template/server/marketplace/payments.ts +193 -0
- package/template/server/marketplace/routes.ts +850 -0
- package/template/server/marketplace/signing.ts +116 -0
- package/template/server/marketplace/syncOfficial.ts +282 -0
- package/template/server/media/images.ts +63 -0
- package/template/server/middleware/adminAuth.ts +134 -0
- package/template/server/modules/legacy.ts +44 -0
- package/template/server/modules/manager.ts +1122 -0
- package/template/server/modules/marketplace.ts +178 -0
- package/template/server/modules/outbound.ts +178 -0
- package/template/server/modules/purchases.ts +149 -0
- package/template/server/modules/records.ts +168 -0
- package/template/server/modules/themeHtml.ts +32 -0
- package/template/server/modules/trust.ts +16 -0
- package/template/server/modules/types.ts +147 -0
- package/template/server/platform/auth.ts +223 -0
- package/template/server/platform/clientWelcome.ts +168 -0
- package/template/server/platform/clients.ts +139 -0
- package/template/server/platform/dailyImprove.ts +356 -0
- package/template/server/platform/flouci.ts +126 -0
- package/template/server/platform/host.ts +69 -0
- package/template/server/platform/hostingProviders.ts +143 -0
- package/template/server/platform/licenseOrders.ts +291 -0
- package/template/server/platform/money.ts +42 -0
- package/template/server/platform/passwords.ts +41 -0
- package/template/server/platform/region.ts +86 -0
- package/template/server/platform/routes.ts +225 -0
- package/template/server/platform/seed.ts +82 -0
- package/template/server/platform/settings.ts +72 -0
- package/template/server/routes/adminAccount.ts +403 -0
- package/template/server/routes/adminCms.ts +808 -0
- package/template/server/routes/adminSystem.ts +243 -0
- package/template/server/routes/adminUsers.ts +449 -0
- package/template/server/routes/googleOAuth.ts +327 -0
- package/template/server/routes/modules.ts +323 -0
- package/template/server/routes/publicCms.ts +313 -0
- package/template/server/routes/seoPublic.ts +158 -0
- package/template/server/security/accounts.ts +121 -0
- package/template/server/security/audit.ts +143 -0
- package/template/server/security/authTokens.ts +74 -0
- package/template/server/security/ip.ts +68 -0
- package/template/server/security/rateLimit.ts +85 -0
- package/template/server/security/retention.ts +46 -0
- package/template/server/security/secrets.ts +44 -0
- package/template/server/security/sessions.ts +140 -0
- package/template/server/security/totp.ts +101 -0
- package/template/server/superadmin/analytics.ts +109 -0
- package/template/server/superadmin/auth.ts +92 -0
- package/template/server/superadmin/backlinksCatalog.ts +210 -0
- package/template/server/superadmin/frSeoContent.ts +165 -0
- package/template/server/superadmin/landingSeo.ts +675 -0
- package/template/server/superadmin/ops.ts +238 -0
- package/template/server/superadmin/routes.ts +1095 -0
- package/template/server/superadmin/tnSeoContent.ts +130 -0
- package/template/server.ts +522 -0
- package/template/src/App.tsx +263 -0
- package/template/src/admin/AdminApp.tsx +162 -0
- package/template/src/admin/account/AuthLayout.tsx +57 -0
- package/template/src/admin/account/SecurityForms.tsx +276 -0
- package/template/src/admin/admin.css +127 -0
- package/template/src/admin/context/AuthContext.tsx +147 -0
- package/template/src/admin/context/SiteContext.tsx +50 -0
- package/template/src/admin/editor/BlockLibrary.tsx +173 -0
- package/template/src/admin/editor/BlocksPanel.tsx +396 -0
- package/template/src/admin/editor/EditorBits.tsx +106 -0
- package/template/src/admin/editor/PreviewFrame.tsx +145 -0
- package/template/src/admin/editor/RichTextEditor.tsx +276 -0
- package/template/src/admin/editor/SeoPanel.tsx +349 -0
- package/template/src/admin/editor/StyleEditor.tsx +114 -0
- package/template/src/admin/editor/blockSchemas.ts +699 -0
- package/template/src/admin/editor/fields.tsx +486 -0
- package/template/src/admin/layout/AdminShell.tsx +418 -0
- package/template/src/admin/layout/nav.ts +95 -0
- package/template/src/admin/lib/api.ts +408 -0
- package/template/src/admin/lib/audit.ts +141 -0
- package/template/src/admin/lib/format.ts +84 -0
- package/template/src/admin/lib/hooks.ts +125 -0
- package/template/src/admin/main.tsx +16 -0
- package/template/src/admin/modules/InstallDialog.tsx +160 -0
- package/template/src/admin/modules/SettingsForm.tsx +145 -0
- package/template/src/admin/modules/kit.tsx +127 -0
- package/template/src/admin/modules/labels.tsx +226 -0
- package/template/src/admin/pages/AccountSetupPage.tsx +62 -0
- package/template/src/admin/pages/AnalyticsPage.tsx +206 -0
- package/template/src/admin/pages/BrandingPage.tsx +154 -0
- package/template/src/admin/pages/DashboardPage.tsx +239 -0
- package/template/src/admin/pages/EngagementPage.tsx +168 -0
- package/template/src/admin/pages/FormsPage.tsx +435 -0
- package/template/src/admin/pages/GeneralPage.tsx +120 -0
- package/template/src/admin/pages/LoginPage.tsx +249 -0
- package/template/src/admin/pages/MaintenancePage.tsx +125 -0
- package/template/src/admin/pages/MarketplacePage.tsx +426 -0
- package/template/src/admin/pages/MediaPage.tsx +251 -0
- package/template/src/admin/pages/MenusPage.tsx +446 -0
- package/template/src/admin/pages/ModuleAdminPage.tsx +113 -0
- package/template/src/admin/pages/ModuleDetailPage.tsx +293 -0
- package/template/src/admin/pages/ModulesPage.tsx +135 -0
- package/template/src/admin/pages/NewsletterPage.tsx +193 -0
- package/template/src/admin/pages/PageEditorPage.tsx +322 -0
- package/template/src/admin/pages/PagesListPage.tsx +277 -0
- package/template/src/admin/pages/PostEditorPage.tsx +292 -0
- package/template/src/admin/pages/PostsListPage.tsx +187 -0
- package/template/src/admin/pages/ProfilePage.tsx +489 -0
- package/template/src/admin/pages/ResetPasswordPage.tsx +110 -0
- package/template/src/admin/pages/SeoPage.tsx +670 -0
- package/template/src/admin/pages/SettingsPage.tsx +189 -0
- package/template/src/admin/pages/ThemeCustomizePage.tsx +170 -0
- package/template/src/admin/pages/ThemesPage.tsx +292 -0
- package/template/src/admin/pages/UsersPage.tsx +57 -0
- package/template/src/admin/pages/WidgetsPage.tsx +200 -0
- package/template/src/admin/seo/GoogleSetup.tsx +529 -0
- package/template/src/admin/settings/EmailTab.tsx +293 -0
- package/template/src/admin/settings/OtherTabs.tsx +270 -0
- package/template/src/admin/settings/SecurityTab.tsx +172 -0
- package/template/src/admin/settings/controls.tsx +133 -0
- package/template/src/admin/ui/Pagination.tsx +170 -0
- package/template/src/admin/ui/SaveBar.tsx +77 -0
- package/template/src/admin/ui/TagInput.tsx +54 -0
- package/template/src/admin/ui/charts.tsx +108 -0
- package/template/src/admin/ui/media.tsx +265 -0
- package/template/src/admin/ui/overlays.tsx +239 -0
- package/template/src/admin/ui/primitives.tsx +544 -0
- package/template/src/admin/users/AuditTab.tsx +104 -0
- package/template/src/admin/users/RolesTab.tsx +368 -0
- package/template/src/admin/users/UsersTab.tsx +723 -0
- package/template/src/admin/users/shared.tsx +278 -0
- package/template/src/cms/icons.ts +7 -0
- package/template/src/components/CookieBanner.tsx +166 -0
- package/template/src/components/MaintenanceGate.tsx +66 -0
- package/template/src/components/SiteAnalytics.tsx +64 -0
- package/template/src/components/SnapifyLogo.tsx +44 -0
- package/template/src/components/cms/BlockRenderer.tsx +154 -0
- package/template/src/components/cms/WidgetArea.tsx +193 -0
- package/template/src/context/SiteConfigContext.tsx +130 -0
- package/template/src/demoBase.ts +23 -0
- package/template/src/index.css +90 -0
- package/template/src/main.tsx +16 -0
- package/template/src/modules/ModuleHost.tsx +197 -0
- package/template/src/preview.ts +63 -0
- package/template/src/runtime.ts +38 -0
- package/template/src/themes/ThemeHost.tsx +168 -0
- package/template/src/themes/fallback.tsx +71 -0
- package/template/src/types.ts +94 -0
- package/template/src/views/BlogPostView.tsx +68 -0
- package/template/src/views/CmsPageView.tsx +34 -0
- package/template/start-pm2.sh +3 -0
- package/template/superadmin.html +20 -0
- package/template/themes/ai-canvas/screenshot.jpg +0 -0
- package/template/themes/ai-canvas/snapify.theme.json +96 -0
- package/template/themes/ai-canvas/src/CeeSimulator.tsx +247 -0
- package/template/themes/ai-canvas/src/Footer.tsx +190 -0
- package/template/themes/ai-canvas/src/Header.tsx +324 -0
- package/template/themes/ai-canvas/src/Layout.tsx +56 -0
- package/template/themes/ai-canvas/src/NotFound.tsx +58 -0
- package/template/themes/ai-canvas/src/Post.tsx +26 -0
- package/template/themes/ai-canvas/src/SnapifyLogo.tsx +44 -0
- package/template/themes/ai-canvas/src/blocks/CollectionBlocks.tsx +711 -0
- package/template/themes/ai-canvas/src/blocks/ContentBlocks.tsx +318 -0
- package/template/themes/ai-canvas/src/blocks/ConversionBlocks.tsx +559 -0
- package/template/themes/ai-canvas/src/blocks/HeaderBlocks.tsx +341 -0
- package/template/themes/ai-canvas/src/index.tsx +54 -0
- package/template/themes/ai-canvas/src/kit.tsx +398 -0
- package/template/themes/ai-canvas/src/site.ts +29 -0
- package/template/themes/ai-canvas/src/styles.css +317 -0
- package/template/themes/dogga/screenshot.jpg +0 -0
- package/template/themes/dogga/snapify.theme.json +55 -0
- package/template/themes/dogga/src/Brand.tsx +41 -0
- package/template/themes/dogga/src/Footer.tsx +202 -0
- package/template/themes/dogga/src/Header.tsx +239 -0
- package/template/themes/dogga/src/Layout.tsx +43 -0
- package/template/themes/dogga/src/Views.tsx +71 -0
- package/template/themes/dogga/src/blocks/CollectionBlocks.tsx +674 -0
- package/template/themes/dogga/src/blocks/ContentBlocks.tsx +307 -0
- package/template/themes/dogga/src/blocks/ConversionBlocks.tsx +571 -0
- package/template/themes/dogga/src/blocks/HeaderBlocks.tsx +289 -0
- package/template/themes/dogga/src/index.tsx +53 -0
- package/template/themes/dogga/src/kit.tsx +362 -0
- package/template/themes/dogga/src/site.ts +56 -0
- package/template/themes/dogga/src/styles.css +396 -0
- package/template/themes/mahdia/screenshot.jpg +0 -0
- package/template/themes/mahdia/snapify.theme.json +65 -0
- package/template/themes/mahdia/src/Brand.tsx +39 -0
- package/template/themes/mahdia/src/Footer.tsx +210 -0
- package/template/themes/mahdia/src/Header.tsx +291 -0
- package/template/themes/mahdia/src/Layout.tsx +44 -0
- package/template/themes/mahdia/src/Views.tsx +79 -0
- package/template/themes/mahdia/src/blocks/CollectionBlocks.tsx +674 -0
- package/template/themes/mahdia/src/blocks/ContentBlocks.tsx +307 -0
- package/template/themes/mahdia/src/blocks/ConversionBlocks.tsx +571 -0
- package/template/themes/mahdia/src/blocks/HeaderBlocks.tsx +289 -0
- package/template/themes/mahdia/src/index.tsx +53 -0
- package/template/themes/mahdia/src/kit.tsx +362 -0
- package/template/themes/mahdia/src/site.ts +75 -0
- package/template/themes/mahdia/src/styles.css +446 -0
- package/template/themes/preveris/screenshot.jpg +0 -0
- package/template/themes/preveris/snapify.theme.json +126 -0
- package/template/themes/preveris/src/Brand.tsx +44 -0
- package/template/themes/preveris/src/Footer.tsx +202 -0
- package/template/themes/preveris/src/Header.tsx +239 -0
- package/template/themes/preveris/src/Layout.tsx +42 -0
- package/template/themes/preveris/src/Views.tsx +71 -0
- package/template/themes/preveris/src/blocks/CollectionBlocks.tsx +678 -0
- package/template/themes/preveris/src/blocks/ContentBlocks.tsx +307 -0
- package/template/themes/preveris/src/blocks/ConversionBlocks.tsx +571 -0
- package/template/themes/preveris/src/blocks/HeaderBlocks.tsx +299 -0
- package/template/themes/preveris/src/index.tsx +53 -0
- package/template/themes/preveris/src/kit.tsx +365 -0
- package/template/themes/preveris/src/site.ts +79 -0
- package/template/themes/preveris/src/styles.css +446 -0
- package/template/themes/sidibou/screenshot.jpg +0 -0
- package/template/themes/sidibou/snapify.theme.json +21 -0
- package/template/themes/sidibou/src/CeeSimulator.tsx +247 -0
- package/template/themes/sidibou/src/Footer.tsx +203 -0
- package/template/themes/sidibou/src/Header.tsx +324 -0
- package/template/themes/sidibou/src/Layout.tsx +53 -0
- package/template/themes/sidibou/src/NotFound.tsx +58 -0
- package/template/themes/sidibou/src/Post.tsx +26 -0
- package/template/themes/sidibou/src/SnapifyLogo.tsx +44 -0
- package/template/themes/sidibou/src/blocks/CollectionBlocks.tsx +711 -0
- package/template/themes/sidibou/src/blocks/ContentBlocks.tsx +318 -0
- package/template/themes/sidibou/src/blocks/ConversionBlocks.tsx +559 -0
- package/template/themes/sidibou/src/blocks/HeaderBlocks.tsx +341 -0
- package/template/themes/sidibou/src/index.tsx +54 -0
- package/template/themes/sidibou/src/kit.tsx +398 -0
- package/template/themes/sidibou/src/site.ts +28 -0
- package/template/themes/sidibou/src/styles.css +317 -0
- package/template/tsconfig.json +33 -0
- package/template/vite.config.ts +42 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snapify — Conditions d’utilisation (Tunisie & France)
|
|
3
|
+
* © 2026 NOVALABS WEB DESIGN
|
|
4
|
+
*/
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { Link } from 'react-router-dom';
|
|
7
|
+
|
|
8
|
+
function LegalShell({ title, children }: { title: string; children: React.ReactNode }) {
|
|
9
|
+
return (
|
|
10
|
+
<div className="lp-wrap" style={{ padding: '48px 0 80px', maxWidth: 820 }}>
|
|
11
|
+
<p style={{ fontSize: 13, color: 'var(--color-muted)', marginBottom: 8 }}>
|
|
12
|
+
<Link to="/" style={{ color: 'var(--color-teal-dark)' }}>
|
|
13
|
+
← Accueil
|
|
14
|
+
</Link>
|
|
15
|
+
</p>
|
|
16
|
+
<h1 style={{ fontSize: '1.75rem', fontWeight: 800, marginBottom: 8 }}>{title}</h1>
|
|
17
|
+
<p style={{ color: 'var(--color-muted)', fontSize: 14, marginBottom: 32 }}>Dernière mise à jour : 24 octobre 2026</p>
|
|
18
|
+
<div className="lp-legal" style={{ lineHeight: 1.7, fontSize: 15 }}>
|
|
19
|
+
{children}
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function Block({ title, children }: { title: string; children: React.ReactNode }) {
|
|
26
|
+
return (
|
|
27
|
+
<section style={{ marginBottom: 28 }}>
|
|
28
|
+
<h2 style={{ fontSize: '1.1rem', fontWeight: 700, marginBottom: 8 }}>{title}</h2>
|
|
29
|
+
<div style={{ color: '#334155' }}>{children}</div>
|
|
30
|
+
</section>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** CGU marché Tunisie (TND, droit tunisien). */
|
|
35
|
+
export function ConditionsTunisiePage() {
|
|
36
|
+
return (
|
|
37
|
+
<LegalShell title="Conditions d’utilisation — Tunisie">
|
|
38
|
+
<Block title="1. Éditeur">
|
|
39
|
+
<p>
|
|
40
|
+
Le service Snapify est édité par <strong>NOVALABS WEB DESIGN</strong>, Tunisie — contact :{' '}
|
|
41
|
+
<a href="mailto:contact@novalabs.tn">contact@novalabs.tn</a> · +216 24 734 647.
|
|
42
|
+
</p>
|
|
43
|
+
</Block>
|
|
44
|
+
<Block title="2. Objet">
|
|
45
|
+
<p>
|
|
46
|
+
Les présentes conditions régissent l’utilisation du site snapify.tn, de la marketplace, de l’espace client et la
|
|
47
|
+
souscription à la licence annuelle Snapify (CMS) pour le marché tunisien. Les montants sont exprimés en dinars
|
|
48
|
+
tunisiens (DT / TND).
|
|
49
|
+
</p>
|
|
50
|
+
</Block>
|
|
51
|
+
<Block title="3. Licence Snapify">
|
|
52
|
+
<p>
|
|
53
|
+
La licence est <strong>annuelle</strong> et personnelle au titulaire. Elle couvre le droit d’utiliser le CMS
|
|
54
|
+
Snapify sur le domaine indiqué lors de la commande. L’hébergement, le nom de domaine et les frais tiers restent à
|
|
55
|
+
la charge du client. L’installation est réalisée après paiement effectif et réception des accès nécessaires.
|
|
56
|
+
</p>
|
|
57
|
+
</Block>
|
|
58
|
+
<Block title="4. Paiement">
|
|
59
|
+
<p>
|
|
60
|
+
Les paiements en ligne sont traités via Flouci (ou virement selon accord). Une facture peut être émise via
|
|
61
|
+
l’espace client. Tout défaut de paiement peut entraîner la suspension du service.
|
|
62
|
+
</p>
|
|
63
|
+
</Block>
|
|
64
|
+
<Block title="5. Espace client">
|
|
65
|
+
<p>
|
|
66
|
+
Le client dispose d’un espace (/espace-client sur snapify.tn ou snapify.fr) pour suivre ses demandes, tickets support,
|
|
67
|
+
paiements et factures. Il s’engage à protéger ses identifiants et à signaler toute utilisation abusive.
|
|
68
|
+
</p>
|
|
69
|
+
</Block>
|
|
70
|
+
<Block title="6. Support & tickets">
|
|
71
|
+
<p>
|
|
72
|
+
Le support est fourni via tickets. Les délais de réponse sont indicatifs et dépendent de la charge. Les signalements
|
|
73
|
+
de bugs doivent être précis (URL, étapes, captures si possible).
|
|
74
|
+
</p>
|
|
75
|
+
</Block>
|
|
76
|
+
<Block title="7. Données personnelles">
|
|
77
|
+
<p>
|
|
78
|
+
Les données collectées (identité, contact, projet) servent à l’exécution du contrat et au suivi commercial. Pour
|
|
79
|
+
toute demande d’accès ou de suppression : contact@novalabs.tn.
|
|
80
|
+
</p>
|
|
81
|
+
</Block>
|
|
82
|
+
<Block title="8. Responsabilité">
|
|
83
|
+
<p>
|
|
84
|
+
Snapify est fourni « en l’état ». NOVALABS n’est pas responsable des panne d’hébergeur tiers, pertes de données
|
|
85
|
+
hors de son contrôle, ou contenus publiés par le client. Le client reste responsable de la légalité de ses contenus.
|
|
86
|
+
</p>
|
|
87
|
+
</Block>
|
|
88
|
+
<Block title="9. Droit applicable">
|
|
89
|
+
<p>Les présentes sont soumises au droit tunisien. En cas de litige, compétence des tribunaux de Tunis, sauf disposition contraire d’ordre public.</p>
|
|
90
|
+
</Block>
|
|
91
|
+
<p style={{ marginTop: 32, fontSize: 14 }}>
|
|
92
|
+
Voir aussi :{' '}
|
|
93
|
+
<Link to="/conditions-utilisation-france" style={{ color: 'var(--color-teal-dark)', fontWeight: 600 }}>
|
|
94
|
+
Conditions France
|
|
95
|
+
</Link>
|
|
96
|
+
</p>
|
|
97
|
+
</LegalShell>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** CGU marché France (EUR, droit français / RGPD). */
|
|
102
|
+
export function ConditionsFrancePage() {
|
|
103
|
+
return (
|
|
104
|
+
<LegalShell title="Conditions d’utilisation — France">
|
|
105
|
+
<Block title="1. Éditeur">
|
|
106
|
+
<p>
|
|
107
|
+
Le service Snapify (offre France) est opéré par <strong>NOVALABS WEB DESIGN</strong> — contact :{' '}
|
|
108
|
+
<a href="mailto:contact@novalabs.tn">contact@novalabs.tn</a>. Site : snapify.fr.
|
|
109
|
+
</p>
|
|
110
|
+
</Block>
|
|
111
|
+
<Block title="2. Objet">
|
|
112
|
+
<p>
|
|
113
|
+
Les présentes conditions s’appliquent aux utilisateurs situés hors Tunisie / marché France : souscription licence
|
|
114
|
+
Snapify, marketplace et espace client. Les prix affichés sont en euros (€), conversion indicative depuis la grille
|
|
115
|
+
TND.
|
|
116
|
+
</p>
|
|
117
|
+
</Block>
|
|
118
|
+
<Block title="3. Licence & prestation">
|
|
119
|
+
<p>
|
|
120
|
+
Licence annuelle pour un domaine. Installation après paiement. L’hébergement et le domaine restent à la charge du
|
|
121
|
+
client. Toute évolution majeure du CMS peut faire l’objet d’une communication préalable.
|
|
122
|
+
</p>
|
|
123
|
+
</Block>
|
|
124
|
+
<Block title="4. Paiement & facturation">
|
|
125
|
+
<p>
|
|
126
|
+
Paiement sécurisé (Flouci ou modalité convenue). Factures téléchargeables depuis l’espace client. En cas de
|
|
127
|
+
rejet ou litige bancaire, l’accès peut être suspendu jusqu’à régularisation.
|
|
128
|
+
</p>
|
|
129
|
+
</Block>
|
|
130
|
+
<Block title="5. Données personnelles (RGPD)">
|
|
131
|
+
<p>
|
|
132
|
+
Responsable de traitement : NOVALABS WEB DESIGN. Finalités : contrat, support, facturation. Base légale :
|
|
133
|
+
exécution du contrat et intérêt légitime. Droits d’accès, rectification, effacement, limitation, portabilité :
|
|
134
|
+
contact@novalabs.tn. Vous pouvez introduire une réclamation auprès de la CNIL (France) ou de l’autorité locale
|
|
135
|
+
compétente.
|
|
136
|
+
</p>
|
|
137
|
+
</Block>
|
|
138
|
+
<Block title="6. Support">
|
|
139
|
+
<p>Tickets support et signalement de bugs via l’espace client. Pas de garantie de disponibilité 24/7 sauf SLA écrit.</p>
|
|
140
|
+
</Block>
|
|
141
|
+
<Block title="7. Limitation de responsabilité">
|
|
142
|
+
<p>
|
|
143
|
+
Dans les limites autorisées par le droit français, la responsabilité de NOVALABS est limitée au montant annuel de
|
|
144
|
+
la licence payée. Exclusion des dommages indirects (perte d’exploitation, image, etc.).
|
|
145
|
+
</p>
|
|
146
|
+
</Block>
|
|
147
|
+
<Block title="8. Droit applicable">
|
|
148
|
+
<p>Droit français. Litiges : tribunaux compétents de Paris, sous réserve des règles protectrices du consommateur.</p>
|
|
149
|
+
</Block>
|
|
150
|
+
<p style={{ marginTop: 32, fontSize: 14 }}>
|
|
151
|
+
Voir aussi :{' '}
|
|
152
|
+
<Link to="/conditions-utilisation" style={{ color: 'var(--color-teal-dark)', fontWeight: 600 }}>
|
|
153
|
+
Conditions Tunisie
|
|
154
|
+
</Link>
|
|
155
|
+
</p>
|
|
156
|
+
</LegalShell>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snapify Landing — formulaire de commande licence (699 DT / an)
|
|
3
|
+
* © 2026 NOVALABS WEB DESIGN — Tunisie
|
|
4
|
+
*/
|
|
5
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
6
|
+
import { Link } from 'react-router-dom';
|
|
7
|
+
import { Check, Globe2, Lock, Server, ShieldCheck, User } from 'lucide-react';
|
|
8
|
+
import { INTL_PRICE, type Copy } from './copy';
|
|
9
|
+
import type { DemoInfo, OrderOptions } from './types';
|
|
10
|
+
|
|
11
|
+
const THEMES = [
|
|
12
|
+
{ id: 'mahdia', label: 'Mahdia', img: '/landing/shot-mahdia.jpg' },
|
|
13
|
+
{ id: 'sidibou', label: 'SidiBou', img: '/landing/shot-sidibou.jpg' },
|
|
14
|
+
{ id: 'dogga', label: 'Dogga', img: '/landing/shot-dogga.jpg' },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
type Form = {
|
|
18
|
+
name: string;
|
|
19
|
+
company: string;
|
|
20
|
+
email: string;
|
|
21
|
+
phone: string;
|
|
22
|
+
gouvernorat: string;
|
|
23
|
+
city: string;
|
|
24
|
+
siteType: string;
|
|
25
|
+
domain: string;
|
|
26
|
+
domainStatus: 'owned' | 'to-register';
|
|
27
|
+
theme: string;
|
|
28
|
+
providerId: string;
|
|
29
|
+
providerOther: string;
|
|
30
|
+
hostingType: string;
|
|
31
|
+
accessType: string;
|
|
32
|
+
serverIp: string;
|
|
33
|
+
message: string;
|
|
34
|
+
acceptTerms: boolean;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const EMPTY: Form = {
|
|
38
|
+
name: '',
|
|
39
|
+
company: '',
|
|
40
|
+
email: '',
|
|
41
|
+
phone: '',
|
|
42
|
+
gouvernorat: '',
|
|
43
|
+
city: '',
|
|
44
|
+
siteType: 'vitrine',
|
|
45
|
+
domain: '',
|
|
46
|
+
domainStatus: 'owned',
|
|
47
|
+
theme: 'mahdia',
|
|
48
|
+
providerId: '',
|
|
49
|
+
providerOther: '',
|
|
50
|
+
hostingType: 'unknown',
|
|
51
|
+
accessType: 'unknown',
|
|
52
|
+
serverIp: '',
|
|
53
|
+
message: '',
|
|
54
|
+
acceptTerms: false,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
function Step({ n, icon, title, sub, children }: { n: number; icon: React.ReactNode; title: string; sub: string; children: React.ReactNode }) {
|
|
58
|
+
return (
|
|
59
|
+
<section className="lp-card">
|
|
60
|
+
<header className="lp-step">
|
|
61
|
+
<span className="lp-step-n">{n}</span>
|
|
62
|
+
<div>
|
|
63
|
+
<h3>
|
|
64
|
+
{icon} {title}
|
|
65
|
+
</h3>
|
|
66
|
+
<p>{sub}</p>
|
|
67
|
+
</div>
|
|
68
|
+
</header>
|
|
69
|
+
{children}
|
|
70
|
+
</section>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function Field({ label, hint, optional, children, wide }: { label: string; hint?: string; optional?: boolean; children: React.ReactNode; wide?: boolean }) {
|
|
75
|
+
return (
|
|
76
|
+
<label className={`lp-field${wide ? ' lp-field-wide' : ''}`}>
|
|
77
|
+
<span>
|
|
78
|
+
{label}
|
|
79
|
+
{optional ? <em> (facultatif)</em> : <b aria-hidden> *</b>}
|
|
80
|
+
</span>
|
|
81
|
+
{children}
|
|
82
|
+
{hint && <small>{hint}</small>}
|
|
83
|
+
</label>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function Chips({ value, options, onChange }: { value: string; options: { id: string; label: string }[]; onChange: (id: string) => void }) {
|
|
88
|
+
return (
|
|
89
|
+
<div className="lp-chips" role="radiogroup">
|
|
90
|
+
{options.map((o) => (
|
|
91
|
+
<button
|
|
92
|
+
key={o.id}
|
|
93
|
+
type="button"
|
|
94
|
+
role="radio"
|
|
95
|
+
aria-checked={value === o.id}
|
|
96
|
+
className={`lp-chip${value === o.id ? ' is-on' : ''}`}
|
|
97
|
+
onClick={() => onChange(o.id)}
|
|
98
|
+
>
|
|
99
|
+
{o.label}
|
|
100
|
+
</button>
|
|
101
|
+
))}
|
|
102
|
+
</div>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function OrderPage({ demo, copy, intl }: { demo: DemoInfo | null; copy: Copy; intl: boolean }) {
|
|
107
|
+
const [opts, setOpts] = useState<OrderOptions | null>(null);
|
|
108
|
+
const [f, setF] = useState<Form>(EMPTY);
|
|
109
|
+
const [busy, setBusy] = useState(false);
|
|
110
|
+
const [err, setErr] = useState('');
|
|
111
|
+
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
fetch(`/api/platform/order-options?market=${intl ? 'fr' : 'tn'}`)
|
|
114
|
+
.then((r) => r.json())
|
|
115
|
+
.then((data: OrderOptions) => {
|
|
116
|
+
setOpts(data);
|
|
117
|
+
setF((prev) => ({ ...prev, gouvernorat: '' }));
|
|
118
|
+
})
|
|
119
|
+
.catch(() => setErr('Impossible de charger la liste des hébergeurs. Rechargez la page.'));
|
|
120
|
+
}, [intl]);
|
|
121
|
+
|
|
122
|
+
const set = <K extends keyof Form>(k: K, v: Form[K]) => setF((prev) => ({ ...prev, [k]: v }));
|
|
123
|
+
|
|
124
|
+
const groups = useMemo(() => {
|
|
125
|
+
const p = opts?.providers || [];
|
|
126
|
+
const tn = p.filter((x) => x.group === 'tn');
|
|
127
|
+
const intlHosts = p.filter((x) => x.group === 'intl');
|
|
128
|
+
const other = p.filter((x) => x.group === 'other');
|
|
129
|
+
if (intl) {
|
|
130
|
+
return [
|
|
131
|
+
{ label: `Hébergeurs France / internationaux (${intlHosts.length})`, items: intlHosts },
|
|
132
|
+
{ label: 'Autre', items: other },
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
return [
|
|
136
|
+
{ label: `Hébergeurs en Tunisie (${tn.length})`, items: tn },
|
|
137
|
+
{ label: 'Hébergeurs internationaux', items: intlHosts },
|
|
138
|
+
{ label: 'Autre', items: other },
|
|
139
|
+
];
|
|
140
|
+
}, [opts, intl]);
|
|
141
|
+
|
|
142
|
+
const provider = opts?.providers.find((p) => p.id === f.providerId);
|
|
143
|
+
const noHosting = f.providerId === 'none';
|
|
144
|
+
const price = intl ? INTL_PRICE : demo?.priceLabel || '699 DT';
|
|
145
|
+
const siteTypeLabel = opts?.siteTypes.find((s) => s.id === f.siteType)?.label;
|
|
146
|
+
|
|
147
|
+
const submit = async (e: React.FormEvent) => {
|
|
148
|
+
e.preventDefault();
|
|
149
|
+
setErr('');
|
|
150
|
+
if (!f.acceptTerms) {
|
|
151
|
+
setErr('Veuillez accepter les conditions pour continuer.');
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
setBusy(true);
|
|
155
|
+
try {
|
|
156
|
+
const res = await fetch('/api/platform/license/checkout', {
|
|
157
|
+
method: 'POST',
|
|
158
|
+
headers: { 'Content-Type': 'application/json' },
|
|
159
|
+
body: JSON.stringify(noHosting ? { ...f, hostingType: 'unknown', accessType: 'unknown', serverIp: '' } : f),
|
|
160
|
+
});
|
|
161
|
+
const data = (await res.json()) as { link?: string; error?: string };
|
|
162
|
+
if (!res.ok || !data.link) throw new Error(data.error || 'Erreur lors de la création du paiement');
|
|
163
|
+
window.location.href = data.link;
|
|
164
|
+
} catch (ex) {
|
|
165
|
+
setErr(ex instanceof Error ? ex.message : 'Erreur');
|
|
166
|
+
setBusy(false);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<div className="lp-section lp-order">
|
|
172
|
+
<div className="lp-wrap">
|
|
173
|
+
<div className="lp-order-head">
|
|
174
|
+
<span className="lp-badge">
|
|
175
|
+
<ShieldCheck className="h-3.5 w-3.5" /> Paiement sécurisé Flouci · Installation sous 48 h
|
|
176
|
+
</span>
|
|
177
|
+
<h2>{copy.order.title}</h2>
|
|
178
|
+
<p className="sub">{copy.order.sub}</p>
|
|
179
|
+
</div>
|
|
180
|
+
|
|
181
|
+
<form className="lp-order-grid" onSubmit={submit}>
|
|
182
|
+
<div className="lp-order-main">
|
|
183
|
+
<Step n={1} icon={<User className="h-4 w-4" />} title="Vos coordonnées" sub="Pour vous contacter et établir la facture.">
|
|
184
|
+
<div className="lp-grid-2">
|
|
185
|
+
<Field label="Nom complet">
|
|
186
|
+
<input required autoComplete="name" value={f.name} onChange={(e) => set('name', e.target.value)} placeholder="Prénom Nom" />
|
|
187
|
+
</Field>
|
|
188
|
+
<Field label="Société / enseigne" optional>
|
|
189
|
+
<input autoComplete="organization" value={f.company} onChange={(e) => set('company', e.target.value)} placeholder="Ma société SARL" />
|
|
190
|
+
</Field>
|
|
191
|
+
<Field label="E-mail">
|
|
192
|
+
<input
|
|
193
|
+
required
|
|
194
|
+
type="email"
|
|
195
|
+
autoComplete="email"
|
|
196
|
+
value={f.email}
|
|
197
|
+
onChange={(e) => set('email', e.target.value)}
|
|
198
|
+
placeholder={intl ? 'vous@exemple.fr' : 'vous@exemple.tn'}
|
|
199
|
+
/>
|
|
200
|
+
</Field>
|
|
201
|
+
<Field label="Téléphone / WhatsApp">
|
|
202
|
+
<input
|
|
203
|
+
required
|
|
204
|
+
type="tel"
|
|
205
|
+
autoComplete="tel"
|
|
206
|
+
value={f.phone}
|
|
207
|
+
onChange={(e) => set('phone', e.target.value)}
|
|
208
|
+
placeholder={intl ? '+33 6 XX XX XX XX' : '+216 XX XXX XXX'}
|
|
209
|
+
/>
|
|
210
|
+
</Field>
|
|
211
|
+
<Field label={opts?.regionLabel || (intl ? 'Région' : 'Gouvernorat')}>
|
|
212
|
+
<select required value={f.gouvernorat} onChange={(e) => set('gouvernorat', e.target.value)}>
|
|
213
|
+
<option value="">Sélectionner…</option>
|
|
214
|
+
{opts?.gouvernorats.map((g) => (
|
|
215
|
+
<option key={g} value={g}>
|
|
216
|
+
{g}
|
|
217
|
+
</option>
|
|
218
|
+
))}
|
|
219
|
+
</select>
|
|
220
|
+
</Field>
|
|
221
|
+
<Field label="Ville" optional>
|
|
222
|
+
<input
|
|
223
|
+
autoComplete="address-level2"
|
|
224
|
+
value={f.city}
|
|
225
|
+
onChange={(e) => set('city', e.target.value)}
|
|
226
|
+
placeholder={intl ? 'Lyon, Paris…' : 'La Marsa'}
|
|
227
|
+
/>
|
|
228
|
+
</Field>
|
|
229
|
+
</div>
|
|
230
|
+
</Step>
|
|
231
|
+
|
|
232
|
+
<Step n={2} icon={<Globe2 className="h-4 w-4" />} title="Votre projet" sub="Le type de site et l’adresse sur laquelle installer Snapify.">
|
|
233
|
+
<Field label="Type de site" wide>
|
|
234
|
+
<Chips value={f.siteType} options={opts?.siteTypes || []} onChange={(v) => set('siteType', v)} />
|
|
235
|
+
</Field>
|
|
236
|
+
<div className="lp-grid-2">
|
|
237
|
+
<Field label="Nom de domaine" hint={intl ? 'Sans http:// — ex. maboutique.fr' : 'Sans http:// — ex. maboutique.tn'}>
|
|
238
|
+
<input
|
|
239
|
+
required
|
|
240
|
+
value={f.domain}
|
|
241
|
+
onChange={(e) => set('domain', e.target.value)}
|
|
242
|
+
placeholder={intl ? 'maboutique.fr' : 'maboutique.tn'}
|
|
243
|
+
inputMode="url"
|
|
244
|
+
/>
|
|
245
|
+
</Field>
|
|
246
|
+
<Field label="Ce domaine…">
|
|
247
|
+
<select value={f.domainStatus} onChange={(e) => set('domainStatus', e.target.value as Form['domainStatus'])}>
|
|
248
|
+
<option value="owned">m’appartient déjà</option>
|
|
249
|
+
<option value="to-register">reste à enregistrer</option>
|
|
250
|
+
</select>
|
|
251
|
+
</Field>
|
|
252
|
+
</div>
|
|
253
|
+
<Field label="Thème de départ" optional wide>
|
|
254
|
+
<div className="lp-themes" role="radiogroup">
|
|
255
|
+
{THEMES.map((th) => (
|
|
256
|
+
<button
|
|
257
|
+
key={th.id}
|
|
258
|
+
type="button"
|
|
259
|
+
role="radio"
|
|
260
|
+
aria-checked={f.theme === th.id}
|
|
261
|
+
className={`lp-theme${f.theme === th.id ? ' is-on' : ''}`}
|
|
262
|
+
onClick={() => set('theme', th.id)}
|
|
263
|
+
>
|
|
264
|
+
<img src={th.img} alt="" loading="lazy" />
|
|
265
|
+
<span>
|
|
266
|
+
{f.theme === th.id && <Check className="h-3.5 w-3.5" />} {th.label}
|
|
267
|
+
</span>
|
|
268
|
+
</button>
|
|
269
|
+
))}
|
|
270
|
+
</div>
|
|
271
|
+
</Field>
|
|
272
|
+
</Step>
|
|
273
|
+
|
|
274
|
+
<Step n={3} icon={<Server className="h-4 w-4" />} title="Votre hébergement" sub="Snapify s’installe chez l’hébergeur de votre choix (VPS ou mutualisé compatible).">
|
|
275
|
+
<Field
|
|
276
|
+
label="Hébergeur"
|
|
277
|
+
wide
|
|
278
|
+
hint={
|
|
279
|
+
opts
|
|
280
|
+
? intl
|
|
281
|
+
? `${opts.providers.filter((p) => p.group === 'intl').length} hébergeurs France / internationaux`
|
|
282
|
+
: `${opts.providers.filter((p) => p.group === 'tn').length} hébergeurs et bureaux d’enregistrement tunisiens (liste ATI) + internationaux`
|
|
283
|
+
: 'Chargement de la liste…'
|
|
284
|
+
}
|
|
285
|
+
>
|
|
286
|
+
<select required value={f.providerId} onChange={(e) => set('providerId', e.target.value)} disabled={!opts}>
|
|
287
|
+
<option value="">{opts ? 'Choisir votre hébergeur…' : 'Chargement…'}</option>
|
|
288
|
+
{groups.map((g) => (
|
|
289
|
+
<optgroup key={g.label} label={g.label}>
|
|
290
|
+
{g.items.map((p) => (
|
|
291
|
+
<option key={p.id} value={p.id}>
|
|
292
|
+
{intl ? p.name.replace(/\bTunisie\b/gi, '').replace(/\s{2,}/g, ' ').trim() : p.name}
|
|
293
|
+
{p.website ? ` — ${p.website}` : ''}
|
|
294
|
+
</option>
|
|
295
|
+
))}
|
|
296
|
+
</optgroup>
|
|
297
|
+
))}
|
|
298
|
+
</select>
|
|
299
|
+
</Field>
|
|
300
|
+
{f.providerId === 'other' && (
|
|
301
|
+
<Field label="Nom de votre hébergeur" wide>
|
|
302
|
+
<input required value={f.providerOther} onChange={(e) => set('providerOther', e.target.value)} placeholder="Nom et site web" />
|
|
303
|
+
</Field>
|
|
304
|
+
)}
|
|
305
|
+
{noHosting ? (
|
|
306
|
+
<p className="lp-note">
|
|
307
|
+
Pas de souci : après le paiement, nous vous recommandons un hébergement adapté à votre projet{intl ? '' : ' (Tunisie ou international)'} et nous nous occupons de la mise en place.
|
|
308
|
+
</p>
|
|
309
|
+
) : (
|
|
310
|
+
<>
|
|
311
|
+
<Field label="Type d’hébergement" wide>
|
|
312
|
+
<Chips value={f.hostingType} options={opts?.hostingTypes || []} onChange={(v) => set('hostingType', v)} />
|
|
313
|
+
</Field>
|
|
314
|
+
<Field label="Accès dont vous disposez" wide>
|
|
315
|
+
<Chips value={f.accessType} options={opts?.accessTypes || []} onChange={(v) => set('accessType', v)} />
|
|
316
|
+
</Field>
|
|
317
|
+
<Field label="Adresse IP du serveur" optional hint="Visible dans l’espace client de votre hébergeur." wide>
|
|
318
|
+
<input value={f.serverIp} onChange={(e) => set('serverIp', e.target.value)} placeholder="ex. 197.14.xx.xx" inputMode="decimal" />
|
|
319
|
+
</Field>
|
|
320
|
+
</>
|
|
321
|
+
)}
|
|
322
|
+
<p className="lp-note lp-note-lock">
|
|
323
|
+
<Lock className="h-4 w-4" /> N’indiquez jamais de mot de passe ici : nous vous demanderons les accès de façon sécurisée après le paiement.
|
|
324
|
+
</p>
|
|
325
|
+
</Step>
|
|
326
|
+
|
|
327
|
+
<section className="lp-card">
|
|
328
|
+
<Field label="Précisions sur votre projet" optional wide>
|
|
329
|
+
<textarea rows={4} value={f.message} onChange={(e) => set('message', e.target.value)} placeholder="Délais, nombre de produits, langues, intégrations souhaitées…" />
|
|
330
|
+
</Field>
|
|
331
|
+
<label className="lp-check">
|
|
332
|
+
<input type="checkbox" checked={f.acceptTerms} onChange={(e) => set('acceptTerms', e.target.checked)} />
|
|
333
|
+
<span>
|
|
334
|
+
J’accepte les{' '}
|
|
335
|
+
<Link to={intl ? '/conditions-utilisation' : '/conditions-utilisation'} style={{ color: 'var(--color-teal-dark)', fontWeight: 600 }}>
|
|
336
|
+
conditions d’utilisation ({intl ? 'France' : 'Tunisie'})
|
|
337
|
+
</Link>
|
|
338
|
+
, que NOVALABS installe Snapify sur l’hébergement indiqué et me contacte au sujet de cette commande. La licence est annuelle ; l’hébergement reste à ma charge. Un espace client sera créé pour suivre ma demande.
|
|
339
|
+
</span>
|
|
340
|
+
</label>
|
|
341
|
+
</section>
|
|
342
|
+
</div>
|
|
343
|
+
|
|
344
|
+
<aside className="lp-order-side">
|
|
345
|
+
<div className="lp-summary">
|
|
346
|
+
<div className="lp-summary-k">Licence Snapify</div>
|
|
347
|
+
<div className="lp-price-num">
|
|
348
|
+
{price} <small>/ an</small>
|
|
349
|
+
</div>
|
|
350
|
+
<ul>
|
|
351
|
+
{copy.pricing.includes.map((line) => (
|
|
352
|
+
<li key={line}>
|
|
353
|
+
<Check className="h-4 w-4" /> {line}
|
|
354
|
+
</li>
|
|
355
|
+
))}
|
|
356
|
+
</ul>
|
|
357
|
+
<dl>
|
|
358
|
+
<dt>Projet</dt>
|
|
359
|
+
<dd>{siteTypeLabel || '—'}</dd>
|
|
360
|
+
<dt>Domaine</dt>
|
|
361
|
+
<dd>{f.domain || '—'}</dd>
|
|
362
|
+
<dt>Hébergeur</dt>
|
|
363
|
+
<dd>{f.providerId === 'other' ? f.providerOther || 'Autre' : provider?.name || '—'}</dd>
|
|
364
|
+
</dl>
|
|
365
|
+
{err && <p className="lp-error">{err}</p>}
|
|
366
|
+
<button type="submit" className="lp-btn" disabled={busy || !opts}>
|
|
367
|
+
{busy ? 'Redirection vers Flouci…' : `${copy.order.submit} · ${price}`}
|
|
368
|
+
</button>
|
|
369
|
+
<p className="lp-summary-foot">
|
|
370
|
+
<ShieldCheck className="h-4 w-4" /> Paiement sécurisé via Flouci. {copy.pricing.note}.
|
|
371
|
+
</p>
|
|
372
|
+
<Link to="/" className="lp-back">
|
|
373
|
+
← Retour à l’accueil
|
|
374
|
+
</Link>
|
|
375
|
+
</div>
|
|
376
|
+
</aside>
|
|
377
|
+
</form>
|
|
378
|
+
</div>
|
|
379
|
+
</div>
|
|
380
|
+
);
|
|
381
|
+
}
|