@salifbiaye/create-boutique 0.6.0 → 0.7.1
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/cli/dist/code.js +110 -0
- package/cli/dist/commands.js +145 -11
- package/cli/dist/create.js +54 -7
- package/cli/dist/generate.js +65 -4
- package/cli/dist/guide.js +10 -2
- package/cli/dist/index.js +20 -7
- package/cli/dist/payments.js +150 -0
- package/docs/fiche-client.en.html +2 -2
- package/docs/fiche-client.html +2 -2
- package/docs/guide-complet.fr.html +681 -256
- package/docs/guide-images/categories.jpg +0 -0
- package/docs/guide-images/clients.jpg +0 -0
- package/docs/guide-images/collections.jpg +0 -0
- package/docs/guide-images/commande-detail.jpg +0 -0
- package/docs/guide-images/commande-expedier.jpg +0 -0
- package/docs/guide-images/commande-menu.jpg +0 -0
- package/docs/guide-images/commande-paiement.jpg +0 -0
- package/docs/guide-images/commandes-liste.jpg +0 -0
- package/docs/guide-images/connexion.jpg +0 -0
- package/docs/guide-images/groupes-clients.jpg +0 -0
- package/docs/guide-images/inventaire.jpg +0 -0
- package/docs/guide-images/listes-prix.jpg +0 -0
- package/docs/guide-images/menu.jpg +0 -0
- package/docs/guide-images/mes-boutiques-fermer.jpg +0 -0
- package/docs/guide-images/mes-boutiques-panneau.jpg +0 -0
- package/docs/guide-images/mes-boutiques.jpg +0 -0
- package/docs/guide-images/parametres-boutique.jpg +0 -0
- package/docs/guide-images/parametres-canaux.jpg +0 -0
- package/docs/guide-images/parametres-emplacements.jpg +0 -0
- package/docs/guide-images/parametres-profil.jpg +0 -0
- package/docs/guide-images/parametres-regions.jpg +0 -0
- package/docs/guide-images/parametres-utilisateurs.jpg +0 -0
- package/docs/guide-images/produit-creer-details.jpg +0 -0
- package/docs/guide-images/produit-detail.jpg +0 -0
- package/docs/guide-images/produit-variantes-menu.jpg +0 -0
- package/docs/guide-images/produit-variantes.jpg +0 -0
- package/docs/guide-images/produits-liste.jpg +0 -0
- package/docs/guide-images/promotion-details.jpg +0 -0
- package/docs/guide-images/promotion-type.jpg +0 -0
- package/docs/guide-images/promotions-liste.jpg +0 -0
- package/docs/guide-images/site-boutique.jpg +0 -0
- package/docs/guide-images/site-fermee.png +0 -0
- package/docs/guide-images/vue-ensemble.jpg +0 -0
- package/package.json +3 -2
- package/templates/backend/medusa-config.ts +31 -25
- package/templates/backend/package-lock.json +21 -0
- package/templates/backend/package.json +2 -0
- package/templates/backend/src/admin/i18n/json/en.json +51 -3
- package/templates/backend/src/admin/i18n/json/fr.json +51 -3
- package/templates/backend/src/admin/routes/boutique-campaigns/campaign-drawer.tsx +2 -0
- package/templates/backend/src/admin/routes/boutique-campaigns/page.tsx +36 -1
- package/templates/backend/src/admin/routes/reviews/page.tsx +259 -0
- package/templates/backend/src/api/admin/boutique-campaigns/route.ts +3 -1
- package/templates/backend/src/api/admin/boutique-online/[salesChannelId]/route.ts +22 -0
- package/templates/backend/src/api/admin/reviews/[id]/route.ts +15 -0
- package/templates/backend/src/api/admin/reviews/route.ts +47 -0
- package/templates/backend/src/api/middlewares.ts +7 -0
- package/templates/backend/src/api/store/campaign/route.ts +5 -1
- package/templates/backend/src/api/store/reviews/latest/route.ts +39 -0
- package/templates/backend/src/api/store/reviews/order/route.ts +36 -0
- package/templates/backend/src/api/store/reviews/route.ts +43 -0
- package/templates/backend/src/api/store/reviews/summary/route.ts +28 -0
- package/templates/backend/src/emails/en.json +3 -1
- package/templates/backend/src/emails/fr.json +3 -1
- package/templates/backend/src/lib/email-config.ts +14 -0
- package/templates/backend/src/lib/emails.ts +9 -0
- package/templates/backend/src/lib/notify.ts +14 -8
- package/templates/backend/src/lib/payment-config.ts +66 -0
- package/templates/backend/src/lib/project.ts +12 -0
- package/templates/backend/src/lib/redirect-payment.ts +264 -0
- package/templates/backend/src/lib/review-token.ts +40 -0
- package/templates/backend/src/lib/reviews.ts +25 -0
- package/templates/backend/src/modules/naboopay/index.ts +6 -0
- package/templates/backend/src/modules/naboopay/service.ts +92 -0
- package/templates/backend/src/modules/paydunya/index.ts +6 -0
- package/templates/backend/src/modules/paydunya/service.ts +89 -0
- package/templates/backend/src/modules/paytech/index.ts +6 -0
- package/templates/backend/src/modules/paytech/service.ts +114 -0
- package/templates/backend/src/modules/product-review/index.ts +8 -0
- package/templates/backend/src/modules/product-review/migrations/Migration20261001090000.ts +18 -0
- package/templates/backend/src/modules/product-review/models/review.ts +25 -0
- package/templates/backend/src/modules/product-review/service.ts +6 -0
- package/templates/backend/src/modules/product-review/validators.ts +27 -0
- package/templates/backend/src/modules/smtp/index.ts +6 -0
- package/templates/backend/src/modules/smtp/service.ts +73 -0
- package/templates/backend/src/scripts/seed.ts +52 -36
- package/templates/backend/src/subscribers/fulfillment-emails.ts +1 -1
- package/templates/backend/src/workflows/reviews.ts +21 -0
- package/templates/backend/src/workflows/steps/create-review.ts +52 -0
- package/templates/backend/src/workflows/steps/update-review.ts +36 -0
- package/templates/storefront/PERSONNALISER.md +134 -0
- package/templates/storefront/locales/en.json +198 -11
- package/templates/storefront/locales/fr.json +198 -11
- package/templates/storefront/public/custom/LISEZMOI.txt +2 -0
- package/templates/storefront/src/app/(checkout)/layout.tsx +1 -1
- package/templates/storefront/src/app/(main)/layout.tsx +8 -1
- package/templates/storefront/src/app/(main)/legal/[page]/page.tsx +42 -7
- package/templates/storefront/src/app/(main)/page.tsx +149 -4
- package/templates/storefront/src/app/(main)/review/page.tsx +60 -0
- package/templates/storefront/src/app/(main)/store/page.tsx +3 -1
- package/templates/storefront/src/app/(main)/template.tsx +17 -2
- package/templates/storefront/src/app/layout.tsx +13 -1
- package/templates/storefront/src/lib/boutique/campaign.ts +5 -1
- package/templates/storefront/src/lib/boutique/page-name.ts +25 -0
- package/templates/storefront/src/lib/boutique/schema.ts +3 -1
- package/templates/storefront/src/lib/constants.tsx +17 -0
- package/templates/storefront/src/lib/data/review-actions.ts +28 -0
- package/templates/storefront/src/lib/data/reviews.ts +64 -0
- package/templates/storefront/src/modules/checkout/components/payment/index.tsx +26 -4
- package/templates/storefront/src/modules/checkout/components/payment-button/index.tsx +85 -2
- package/templates/storefront/src/modules/products/templates/index.tsx +5 -0
- package/templates/storefront/src/modules/store/components/shop-search.tsx +85 -0
- package/templates/storefront/src/modules/store/templates/index.tsx +16 -8
- package/templates/storefront/src/modules/store/templates/paginated-products.tsx +15 -3
- package/templates/storefront/src/modules/ub/album.tsx +2 -0
- package/templates/storefront/src/modules/ub/arena.tsx +182 -0
- package/templates/storefront/src/modules/ub/campaign-blocks.tsx +3 -2
- package/templates/storefront/src/modules/ub/campaign-ended.tsx +27 -13
- package/templates/storefront/src/modules/ub/cinema.tsx +2 -0
- package/templates/storefront/src/modules/ub/cookie-banner.tsx +62 -0
- package/templates/storefront/src/modules/ub/gala.tsx +2 -0
- package/templates/storefront/src/modules/ub/grimoire.tsx +35 -8
- package/templates/storefront/src/modules/ub/harvest.tsx +2 -1
- package/templates/storefront/src/modules/ub/hero-image.tsx +14 -0
- package/templates/storefront/src/modules/ub/home-kit.ts +45 -0
- package/templates/storefront/src/modules/ub/lantern.tsx +244 -0
- package/templates/storefront/src/modules/ub/locker.tsx +180 -0
- package/templates/storefront/src/modules/ub/mosaic.tsx +189 -0
- package/templates/storefront/src/modules/ub/nav.tsx +8 -5
- package/templates/storefront/src/modules/ub/review-form.tsx +62 -0
- package/templates/storefront/src/modules/ub/reviews.tsx +131 -0
- package/templates/storefront/src/modules/ub/riviera.tsx +175 -0
- package/templates/storefront/src/modules/ub/souk.tsx +214 -0
- package/templates/storefront/src/modules/ub/sunset-checklist.tsx +95 -0
- package/templates/storefront/src/modules/ub/sunset.tsx +164 -0
- package/templates/storefront/src/modules/ub/tech.tsx +2 -2
- package/templates/storefront/src/modules/ub/training.tsx +196 -0
- package/templates/storefront/src/proxy.ts +2 -0
- package/templates/storefront/src/styles/custom.css +26 -0
- package/templates/storefront/src/styles/ub/album.css +1 -1
- package/templates/storefront/src/styles/ub/arena.css +120 -0
- package/templates/storefront/src/styles/ub/cinema.css +1 -1
- package/templates/storefront/src/styles/ub/gala.css +1 -1
- package/templates/storefront/src/styles/ub/grimoire.css +23 -7
- package/templates/storefront/src/styles/ub/harvest.css +7 -6
- package/templates/storefront/src/styles/ub/lantern.css +157 -0
- package/templates/storefront/src/styles/ub/locker.css +115 -0
- package/templates/storefront/src/styles/ub/media.css +10 -0
- package/templates/storefront/src/styles/ub/mosaic.css +118 -0
- package/templates/storefront/src/styles/ub/motion.css +0 -3
- package/templates/storefront/src/styles/ub/overrides.css +10 -0
- package/templates/storefront/src/styles/ub/pages.css +176 -0
- package/templates/storefront/src/styles/ub/reviews.css +85 -0
- package/templates/storefront/src/styles/ub/riviera.css +103 -0
- package/templates/storefront/src/styles/ub/souk.css +144 -0
- package/templates/storefront/src/styles/ub/sunset.css +123 -0
- package/templates/storefront/src/styles/ub/tech.css +2 -5
- package/templates/storefront/src/styles/ub/training.css +120 -0
- package/templates/storefront/themes/jeux/campaign.en.json +31 -0
- package/templates/storefront/themes/jeux/campaign.fr.json +31 -0
- package/templates/storefront/themes/jeux/theme.json +11 -0
- package/templates/storefront/themes/jeux-2/campaign.en.json +31 -0
- package/templates/storefront/themes/jeux-2/campaign.fr.json +31 -0
- package/templates/storefront/themes/jeux-2/theme.json +11 -0
- package/templates/storefront/themes/mubarak/campaign.en.json +31 -0
- package/templates/storefront/themes/mubarak/campaign.fr.json +31 -0
- package/templates/storefront/themes/mubarak/theme.json +11 -0
- package/templates/storefront/themes/mubarak-2/campaign.en.json +31 -0
- package/templates/storefront/themes/mubarak-2/campaign.fr.json +31 -0
- package/templates/storefront/themes/mubarak-2/theme.json +11 -0
- package/templates/storefront/themes/sport/campaign.en.json +31 -0
- package/templates/storefront/themes/sport/campaign.fr.json +31 -0
- package/templates/storefront/themes/sport/theme.json +11 -0
- package/templates/storefront/themes/sport-2/campaign.en.json +31 -0
- package/templates/storefront/themes/sport-2/campaign.fr.json +31 -0
- package/templates/storefront/themes/sport-2/theme.json +11 -0
- package/templates/storefront/themes/summer/campaign.en.json +31 -0
- package/templates/storefront/themes/summer/campaign.fr.json +31 -0
- package/templates/storefront/themes/summer/theme.json +11 -0
- package/templates/storefront/themes/summer-2/campaign.en.json +31 -0
- package/templates/storefront/themes/summer-2/campaign.fr.json +31 -0
- package/templates/storefront/themes/summer-2/theme.json +11 -0
package/cli/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import fs from "node:fs";
|
|
|
3
3
|
import { parseArgs } from "node:util";
|
|
4
4
|
import pc from "picocolors";
|
|
5
5
|
import { z } from "zod";
|
|
6
|
-
import { add, admin, apply, urls, backup, campaignExport, campaignImport, check, guide, remove, set, stripeWebhook, themes, update } from "./commands.js";
|
|
6
|
+
import { add, admin, apply, urls, backup, restore, campaignExport, campaignImport, check, guide, remove, set, stripeWebhook, themes, update } from "./commands.js";
|
|
7
7
|
import { answersSchema, create } from "./create.js";
|
|
8
8
|
import { ProjectError } from "./project.js";
|
|
9
9
|
const HELP = `create-boutique — Usine à Boutiques
|
|
@@ -18,7 +18,9 @@ const HELP = `create-boutique — Usine à Boutiques
|
|
|
18
18
|
--site-url <domaine> mode single : domaine du site
|
|
19
19
|
--mode multi|single multi (défaut) : un site par boutique ; single : un seul site, boutique active choisie dans l'admin
|
|
20
20
|
--stripe-pk / --stripe-sk / --stripe-whsec clés Stripe (optionnelles)
|
|
21
|
-
--resend-key / --email-from e-mails (optionnels)
|
|
21
|
+
--resend-key / --email-from e-mails par Resend (optionnels)
|
|
22
|
+
--smtp-host smtp.gmail.com --smtp-user <adresse> e-mails par SMTP (mot de passe : SMTP_PASS dans .env)
|
|
23
|
+
--mobile paytech,paydunya,naboopay paiement Wave / Orange Money (clés dans .env ; détails : create-boutique sans --yes)
|
|
22
24
|
--products <csv> --images <dossier> catalogue (optionnel)
|
|
23
25
|
--store-port 8001 --api-port 9000 --storage-port 9100 premiers ports essayés
|
|
24
26
|
--config <fichier.json> toutes les options dans un fichier (mêmes clés, en camelCase)
|
|
@@ -32,16 +34,18 @@ const HELP = `create-boutique — Usine à Boutiques
|
|
|
32
34
|
create-boutique set <dossier> [--mode multi|single] change de mode (un site par boutique ↔ un seul site)
|
|
33
35
|
create-boutique set <dossier> [--boutique <slug>] [--name …] [--theme …] [--currency …] [--country …] [--language …]
|
|
34
36
|
create-boutique themes liste les thèmes
|
|
35
|
-
create-boutique update <dossier> [--no-up]
|
|
37
|
+
create-boutique update <dossier> [--no-up] [--yes] met à jour le code (config, .env, données, custom.css conservés ;
|
|
38
|
+
code modifié à la main : listé, copié dans backups/, confirmation)
|
|
36
39
|
create-boutique check <dossier> commande test dans chaque boutique
|
|
37
|
-
create-boutique backup <dossier>
|
|
40
|
+
create-boutique backup <dossier> [--keep 7] base + images dans backups/<date>/ (--keep : garde les N plus récentes)
|
|
41
|
+
create-boutique restore <dossier> [--from <nom>] [--yes] remet une sauvegarde (la plus récente par défaut)
|
|
38
42
|
create-boutique admin <dossier> adresse, e-mail et mot de passe de l'admin
|
|
39
43
|
create-boutique guide <dossier> régénère GUIDE-CLIENT.pdf et GUIDE-COMPLET.pdf
|
|
40
44
|
create-boutique stripe-webhook <dossier> --url https://api.marque.com crée le webhook Stripe, écrit STRIPE_WEBHOOK_SECRET
|
|
41
45
|
create-boutique campaign export <dossier> campagnes en base → config/campaigns/*.json
|
|
42
46
|
create-boutique campaign import <dossier> [--boutique <slug>] [--yes] JSON → base (écrase)
|
|
43
47
|
`;
|
|
44
|
-
const COMMANDS = new Set(["urls", "apply", "add", "remove", "set", "themes", "update", "check", "backup", "campaign", "admin", "guide", "stripe-webhook", "help"]);
|
|
48
|
+
const COMMANDS = new Set(["restore", "urls", "apply", "add", "remove", "set", "themes", "update", "check", "backup", "campaign", "admin", "guide", "stripe-webhook", "help"]);
|
|
45
49
|
async function main() {
|
|
46
50
|
const { values, positionals } = parseArgs({
|
|
47
51
|
allowPositionals: true,
|
|
@@ -59,11 +63,15 @@ async function main() {
|
|
|
59
63
|
"files-url": { type: "string" },
|
|
60
64
|
"site-url": { type: "string" },
|
|
61
65
|
from: { type: "string" },
|
|
66
|
+
keep: { type: "string" },
|
|
62
67
|
"stripe-pk": { type: "string" },
|
|
63
68
|
"stripe-sk": { type: "string" },
|
|
64
69
|
"stripe-whsec": { type: "string" },
|
|
65
70
|
"resend-key": { type: "string" },
|
|
66
71
|
"email-from": { type: "string" },
|
|
72
|
+
"smtp-host": { type: "string" },
|
|
73
|
+
"smtp-user": { type: "string" },
|
|
74
|
+
mobile: { type: "string" },
|
|
67
75
|
products: { type: "string" },
|
|
68
76
|
images: { type: "string" },
|
|
69
77
|
"store-port": { type: "string" },
|
|
@@ -108,6 +116,9 @@ async function main() {
|
|
|
108
116
|
stripeWhsec: values["stripe-whsec"],
|
|
109
117
|
resendKey: values["resend-key"],
|
|
110
118
|
emailFrom: values["email-from"],
|
|
119
|
+
smtpHost: values["smtp-host"],
|
|
120
|
+
smtpUser: values["smtp-user"],
|
|
121
|
+
mobile: values.mobile ? values.mobile.split(",").map((m) => m.trim()).filter(Boolean) : undefined,
|
|
111
122
|
products: values.products,
|
|
112
123
|
images: values.images,
|
|
113
124
|
storePort: port(values["store-port"]),
|
|
@@ -140,11 +151,13 @@ async function main() {
|
|
|
140
151
|
case "themes":
|
|
141
152
|
return themes();
|
|
142
153
|
case "update":
|
|
143
|
-
return update(dirArg(), up);
|
|
154
|
+
return update(dirArg(), { ...up, yes: !!values.yes });
|
|
144
155
|
case "check":
|
|
145
156
|
return check(dirArg());
|
|
146
157
|
case "backup":
|
|
147
|
-
return backup(dirArg());
|
|
158
|
+
return void backup(dirArg(), { keep: values.keep ? Number(values.keep) : undefined });
|
|
159
|
+
case "restore":
|
|
160
|
+
return restore(dirArg(), { from: values.from, yes: !!values.yes });
|
|
148
161
|
case "admin":
|
|
149
162
|
return admin(dirArg());
|
|
150
163
|
case "guide":
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import pc from "picocolors";
|
|
3
|
+
export const MOBILE = {
|
|
4
|
+
paytech: {
|
|
5
|
+
name: "PayTech",
|
|
6
|
+
methods: "Wave, Orange Money, Free Money, Wizall, carte bancaire (Visa, Mastercard)",
|
|
7
|
+
currencies: ["xof", "eur", "usd", "cad", "gbp", "mad"],
|
|
8
|
+
test: "pas de simulation : chaque paiement test débite vraiment 100 à 150 FCFA (quel que soit le panier) sur le Wave / Orange Money du testeur ; l'argent arrive sur le solde PayTech de la boutique (moins les frais)",
|
|
9
|
+
needs: "compte PayTech + 2 clés (API_KEY, API_SECRET) ; mode prod après activation du compte",
|
|
10
|
+
refund: "bouton Remboursement de l'admin : l'argent repart vers le client (remboursement total uniquement)",
|
|
11
|
+
site: "paytech.sn",
|
|
12
|
+
},
|
|
13
|
+
paydunya: {
|
|
14
|
+
name: "PayDunya",
|
|
15
|
+
methods: "Wave, Orange Money, Free Money, carte bancaire…",
|
|
16
|
+
currencies: ["xof"],
|
|
17
|
+
test: "sandbox gratuite (aucun vrai paiement), clés de test séparées",
|
|
18
|
+
needs: "compte PayDunya + application + 3 clés (master key, private key, token)",
|
|
19
|
+
refund: "dans le tableau de bord PayDunya (pas d'API), puis enregistré dans l'admin",
|
|
20
|
+
site: "paydunya.com",
|
|
21
|
+
},
|
|
22
|
+
naboopay: {
|
|
23
|
+
name: "NabooPay",
|
|
24
|
+
methods: "Wave, Orange Money (carte annoncée)",
|
|
25
|
+
currencies: ["xof"],
|
|
26
|
+
test: "pas de mode test documenté : tester avec de petits montants réels",
|
|
27
|
+
needs: "compte NabooPay + 1 clé API + secret du webhook (tableau de bord → Paramètres → Intégration)",
|
|
28
|
+
refund: "bouton Remboursement de l'admin : l'argent repart vers le client (total uniquement, Wave et Orange Money)",
|
|
29
|
+
site: "naboopay.com",
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
const stop = (v) => {
|
|
33
|
+
if (p.isCancel(v)) {
|
|
34
|
+
p.cancel("Création annulée.");
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
return v;
|
|
38
|
+
};
|
|
39
|
+
/** Devises des boutiques pour lesquelles l'agrégateur ne s'affichera pas */
|
|
40
|
+
const unsupported = (id, currencies) => currencies.filter((c) => !MOBILE[id].currencies.includes(c));
|
|
41
|
+
/** Explication affichée avant le choix : critères de chaque agrégateur */
|
|
42
|
+
export function mobileNote(currencies) {
|
|
43
|
+
const lines = Object.keys(MOBILE).flatMap((id) => {
|
|
44
|
+
const m = MOBILE[id];
|
|
45
|
+
const off = unsupported(id, currencies);
|
|
46
|
+
return [
|
|
47
|
+
pc.bold(`${m.name}`) + pc.dim(` (${m.site})`),
|
|
48
|
+
` Moyens : ${m.methods}`,
|
|
49
|
+
` Devises : ${m.currencies.map((c) => c.toUpperCase()).join(", ")}` + (off.length ? pc.yellow(` → pas pour vos boutiques en ${off.join(", ").toUpperCase()}`) : ""),
|
|
50
|
+
` Test : ${m.test}`,
|
|
51
|
+
` Il faut : ${m.needs}`,
|
|
52
|
+
` Rembourser : ${m.refund}`,
|
|
53
|
+
"",
|
|
54
|
+
];
|
|
55
|
+
});
|
|
56
|
+
return [
|
|
57
|
+
"Le client choisit « Wave, Orange Money… », paie sur la page sécurisée de l'agrégateur,",
|
|
58
|
+
"puis revient sur la boutique ; le montant est toujours calculé par le backend.",
|
|
59
|
+
"Confirmation automatique (même si le client ferme la page) : backend en ligne en HTTPS.",
|
|
60
|
+
"",
|
|
61
|
+
...lines,
|
|
62
|
+
"Plusieurs possibles (le client voit un choix par agrégateur). Clés : maintenant (saisie masquée)",
|
|
63
|
+
"ou plus tard dans .env, puis « docker compose restart backend ».",
|
|
64
|
+
].join("\n");
|
|
65
|
+
}
|
|
66
|
+
/** Questions : agrégateurs, clés (facultatives maintenant), mode test / prod */
|
|
67
|
+
export async function askMobile(a, currencies) {
|
|
68
|
+
if (a.mobile)
|
|
69
|
+
return a;
|
|
70
|
+
p.note(mobileNote(currencies), "Paiement mobile : Wave, Orange Money, carte (Afrique de l'Ouest)");
|
|
71
|
+
const mobile = stop(await p.multiselect({
|
|
72
|
+
message: "Agrégateurs de paiement mobile (espace = cocher, Entrée sans rien = aucun)",
|
|
73
|
+
options: Object.keys(MOBILE).map((id) => {
|
|
74
|
+
const off = unsupported(id, currencies);
|
|
75
|
+
return {
|
|
76
|
+
value: id,
|
|
77
|
+
label: MOBILE[id].name,
|
|
78
|
+
hint: `${MOBILE[id].currencies.length > 1 ? "XOF, EUR, USD…" : "XOF uniquement"}${off.length ? ` · inactif en ${off.join(", ").toUpperCase()}` : ""}`,
|
|
79
|
+
};
|
|
80
|
+
}),
|
|
81
|
+
required: false,
|
|
82
|
+
}));
|
|
83
|
+
for (const id of mobile) {
|
|
84
|
+
const off = unsupported(id, currencies);
|
|
85
|
+
if (off.length === currencies.length) {
|
|
86
|
+
p.log.warn(`${MOBILE[id].name} n'acceptera aucune de vos boutiques (${currencies.join(", ").toUpperCase()}) : il faut une boutique en XOF.`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const out = { mobile };
|
|
90
|
+
const secret = async (message) => stop(await p.password({ message: `${message} (vide = plus tard dans .env)` })) || undefined;
|
|
91
|
+
const env = async (name, test) => stop(await p.select({
|
|
92
|
+
message: `${name} : mode`,
|
|
93
|
+
options: [
|
|
94
|
+
{ value: "test", label: "test", hint: test },
|
|
95
|
+
{ value: "prod", label: "production", hint: "vrais paiements, compte activé" },
|
|
96
|
+
],
|
|
97
|
+
initialValue: "test",
|
|
98
|
+
}));
|
|
99
|
+
if (mobile.includes("paytech")) {
|
|
100
|
+
out.paytechKey = await secret("PayTech : API_KEY");
|
|
101
|
+
out.paytechSecret = out.paytechKey ? await secret("PayTech : API_SECRET") : undefined;
|
|
102
|
+
out.paytechEnv = await env("PayTech", "vrais débits de 100 à 150 FCFA par paiement test, reçus sur le solde PayTech");
|
|
103
|
+
}
|
|
104
|
+
if (mobile.includes("paydunya")) {
|
|
105
|
+
out.paydunyaMaster = await secret("PayDunya : clé principale (master key)");
|
|
106
|
+
out.paydunyaPrivate = out.paydunyaMaster ? await secret("PayDunya : clé privée") : undefined;
|
|
107
|
+
out.paydunyaToken = out.paydunyaMaster ? await secret("PayDunya : token") : undefined;
|
|
108
|
+
out.paydunyaEnv = await env("PayDunya", "sandbox, aucun vrai paiement");
|
|
109
|
+
}
|
|
110
|
+
if (mobile.includes("naboopay")) {
|
|
111
|
+
out.naboopayKey = await secret("NabooPay : clé API");
|
|
112
|
+
p.log.info("NabooPay : le secret du webhook se crée après la mise en ligne (tableau de bord → Paramètres → Intégration) ; à mettre dans NABOOPAY_WEBHOOK_SECRET.");
|
|
113
|
+
}
|
|
114
|
+
return out;
|
|
115
|
+
}
|
|
116
|
+
/** Ligne du récapitulatif */
|
|
117
|
+
export function mobileSummary(a) {
|
|
118
|
+
if (!a.mobile?.length)
|
|
119
|
+
return "Wave / Orange Money : non (possible plus tard : clés dans .env, voir README)";
|
|
120
|
+
const one = (id) => {
|
|
121
|
+
const keys = id === "paytech" ? a.paytechKey && a.paytechSecret : id === "paydunya" ? a.paydunyaMaster && a.paydunyaPrivate && a.paydunyaToken : a.naboopayKey;
|
|
122
|
+
const mode = id === "paytech" ? a.paytechEnv : id === "paydunya" ? a.paydunyaEnv : undefined;
|
|
123
|
+
return `${MOBILE[id].name}${mode ? ` (${mode})` : ""}${keys ? "" : " — clés à mettre dans .env"}`;
|
|
124
|
+
};
|
|
125
|
+
return `Wave / Orange Money : ${a.mobile.map(one).join(", ")}`;
|
|
126
|
+
}
|
|
127
|
+
/** E-mails : Resend, SMTP (Gmail…) ou aucun */
|
|
128
|
+
export async function askMail() {
|
|
129
|
+
const kind = stop(await p.select({
|
|
130
|
+
message: "E-mails aux clients (confirmation, expédition, mot de passe oublié…)",
|
|
131
|
+
options: [
|
|
132
|
+
{ value: "smtp", label: "SMTP (Gmail, OVH, Brevo…)", hint: "Gmail : mot de passe d'application, ~500 e-mails/jour" },
|
|
133
|
+
{ value: "resend", label: "Resend", hint: "clé re_…, domaine vérifié ; 3 000 e-mails/mois gratuits" },
|
|
134
|
+
{ value: "none", label: "Aucun pour l'instant", hint: "la boutique marche, sans e-mails" },
|
|
135
|
+
],
|
|
136
|
+
initialValue: "smtp",
|
|
137
|
+
}));
|
|
138
|
+
if (kind !== "smtp")
|
|
139
|
+
return { kind };
|
|
140
|
+
p.note([
|
|
141
|
+
"Gmail : Compte Google → Sécurité → Validation en deux étapes (activée)",
|
|
142
|
+
"→ Mots de passe des applications → créer (16 caractères). Jamais le mot de passe du compte.",
|
|
143
|
+
"Les e-mails partent de l'adresse Gmail, avec le nom de la boutique ; les réponses vont au marchand.",
|
|
144
|
+
].join("\n"), "SMTP");
|
|
145
|
+
const host = stop(await p.text({ message: "Serveur SMTP", initialValue: "smtp.gmail.com" }));
|
|
146
|
+
const port = Number(stop(await p.text({ message: "Port (465 = SSL, 587 = STARTTLS)", initialValue: "465", validate: (v) => (/^\d+$/.test(v ?? "") ? undefined : "un nombre") })));
|
|
147
|
+
const user = stop(await p.text({ message: "Identifiant (adresse e-mail du compte)", placeholder: "boutique@gmail.com" }));
|
|
148
|
+
const pass = stop(await p.password({ message: "Mot de passe d'application (vide = plus tard dans .env)" })) || undefined;
|
|
149
|
+
return { kind, smtp: { smtpHost: host.trim(), smtpPort: port, smtpUser: user.trim() || undefined, smtpPass: pass } };
|
|
150
|
+
}
|
|
@@ -98,8 +98,8 @@
|
|
|
98
98
|
<div class="screen">
|
|
99
99
|
<div class="num">3</div>
|
|
100
100
|
<div>
|
|
101
|
-
<h2>
|
|
102
|
-
<div class="where">Menu:
|
|
101
|
+
<h2>My stores <small>texts and images of each store</small></h2>
|
|
102
|
+
<div class="where">Menu: My stores</div>
|
|
103
103
|
<ol>
|
|
104
104
|
<li>Pick the store (Halloween, Black Friday, Christmas…) and click <b>Edit</b>.</li>
|
|
105
105
|
<li>Change the title, text, button, hero image, logo and the offer dates.</li>
|
package/docs/fiche-client.html
CHANGED
|
@@ -98,8 +98,8 @@
|
|
|
98
98
|
<div class="screen">
|
|
99
99
|
<div class="num">3</div>
|
|
100
100
|
<div>
|
|
101
|
-
<h2>
|
|
102
|
-
<div class="where">Menu :
|
|
101
|
+
<h2>Mes boutiques <small>site en ligne ou fermé, textes et images</small></h2>
|
|
102
|
+
<div class="where">Menu : Mes boutiques</div>
|
|
103
103
|
<ol>
|
|
104
104
|
<li>Choisissez la boutique (Halloween, Black Friday, Noël…) et cliquez sur <b>Modifier</b>.</li>
|
|
105
105
|
<li>Changez le titre, le texte, le bouton, l'image principale, le logo et les dates de l'offre.</li>
|