feat: activer « Obtenir Base » (écrans verrouillés, carte Mises à jour, page d'erreur) + note Premium + texte de la carte Compte #346
Labels
No labels
autopilot:pending-human
source:analyste
source:defenseur
source:human
source:medic
status:approved
status:blocked
status:in-progress
status:needs-clarification
status:needs-fix
status:ready
status:review
status:triage
type:bug
type:feature
type:infra
type:refactor
type:schema
type:security
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: maximus/Simpl-Resultat#346
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
En édition gratuite, les écrans verrouillés montrent « Obtenir {tier} » désactivé, avec la note « Achat en ligne bientôt disponible ». C'était la décision de l'ADR 0017 en attendant #270, mergée le 2026-09-27 (PR #359).
Avec le helper
purchaseUrllivré par #270 :Analyse du 2026-09-27 (
/analyze) : prémisse revérifiée surmainde274ec, deux oublis corrigés (le bouton Annuler deProfileFormModal, leonNavigatedu modal), deux décisions ajoutées (A1, A2).Contexte vérifié (2026-09-27,
mainde274ec)src/shared/purchaseUrl.ts(#270) :purchaseUrl(language)→https://lacompagniemaximus.com/{fr|en}/produits/simpl-resultat. Le chemin est un contrat avec le site.…_x64-setup.exe,…_amd64.deb, v0.15.0 au 2026-09-27, vérifié en prod en FR et en EN), et/simpl-resultaty redirige.src/components/shared/UpsellGate.tsx:useNavigateest appelé sans condition ;disableden dur, avec la noteupsell.ctaGetSoon(l.61) ;navigate("/settings/users")puisonNavigate?.().RequireFeature.tsx:39(routes Budget, Ajustements, rapports avancés, Bilan) etProfileSwitcher.tsx:154-158(modal multi-profils,onNavigate={() => setShowUpsell(false)}).src/components/profile/ProfileFormModal.tsx, l.178-213 : panneau upsell compact (modeupsell). Il contient un bouton « Obtenir » désactivé, la noteupsell.ctaGetSoon(l.205) et un bouton Annuler qui revient à la liste des profils (setMode("list"), l.207-212). Le titre du modal resteprofile.createen modeupsell. Le modal a deux hôtes :ProfileSelectionPage.tsx:108, rendue horsBrowserRouter(App.tsx:97, alors que le routeur est monté en l.109) ;ProfileSwitcher.tsx:139, dans le routeur (onClose={() => setShowManage(false)}).src/shared/entitlements.ts:22-26) : Base et plus =budget,adjustments,reports-advanced,multi-profile; Premium seul =balance(Bilan).requiredTierFor(feature)donne le tier.src/components/settings/UpdateCard.tsx:75-80, monté dansSystemsSettingsPagedonc dans le routeur : l'étatnotEntitledn'affiche que le textesettings.updates.notEntitled.src/components/shared/ErrorPage.tsx:100-104: même état, avec la cléerror.updateNotEntitled.ErrorPageest rendue hors du routeur (App.tsx:93,ErrorBoundary.tsx:29). L'état n'apparaît qu'après un clic sur « Vérifier les mises à jour » (l.18-40).check()(useUpdater.ts:79-86,ErrorPage.tsx:22-28) : l'utilisateur n'apprend jamais qu'une version corrige une faille.src/components/settings/AccountCard.tsx:58afficheaccount.description, faux depuis v0.15.0. Le compte sert réellement à deux choses : joindre le courriel à la rétroaction (FeedbackDialog.tsx:26-35), et la page/comptedu site, qui liste les licences.LicenseCard.tsx) a son propre bouton « Acheter Simpl'Résultat », qui passe parpurchaseUrldepuis #270 : il ne change pas (décision A2).src/services/entitlements.test.ts: l'interfaceUpsellMessagestypeupsell.ctaGetSoon(l.116), attendue en l.145.> **Amendement du AAAA-MM-JJ (#N)** — …(ADR 0018, l.8) ;docs/architecture.md:299(ligneUpsellGate) et l.301 (ligne « Gate multi-profils », qui cite le « mode upsell compact ») ;docs/guide-utilisateur.md§12 (l.519), puce l.545 ;docs.editions.steps[3]FR/EN (« l'achat en ligne arrive bientôt… »).useInRouterContextest exporté parreact-router(installé, 7.x).Tâches
src/shared/upsellCta.ts:upsellCtaFor(tier: "base" | "premium")→{ purchasable: boolean; noteKey: string | null }. Base donne{ purchasable: true, noteKey: null }, Premium donne{ purchasable: false, noteKey: "upsell.premiumNotForSale" }. Test danssrc/shared/upsellCta.test.ts(décision A1).src/components/shared/PurchaseButton.tsx, sans routeur : un bouton « Obtenir Base » (upsell.ctaGet, avectier=license.editions.base) qui appelleopenUrl(purchaseUrl(i18n.language)). Il sert àUpsellGate, à la carte Mises à jour et à la page d'erreur.UpsellGate.tsx:upsellCtaFor(requiredTier): si le palier est achetable,PurchaseButtonactif, sans note ; sinon, bouton désactivé avec la notenoteKey;onNavigate, pour que le modal hôte reste ouvert ;useNavigate, rendu seulement siuseInRouterContext()est vrai.ProfileFormModal.tsx, modeupsell:UpsellGate(feature="multi-profile",requiredTier={requiredTierFor("multi-profile")},onNavigate={onClose}) ;UpsellGatele bouton Annuler qui revient à la liste des profils ;ProfileSwitcher(dans le routeur), « J'ai déjà une clé » apparaît et ferme le modal après la navigation ; ouvert depuisProfileSelectionPage(hors routeur), il n'apparaît pas, comme aujourd'hui.UpdateCard.tsx, étatnotEntitled: le textesettings.updates.notEntitled, puisPurchaseButton, puis « J'ai déjà une clé » (navigate("/settings/users"), cléupsell.ctaHaveKey), puis un lien « Télécharger la dernière version » verspurchaseUrl(i18n.language)(clésettings.updates.downloadLatest).ErrorPage.tsx, étatnotEntitled:PurchaseButtonet le lien « Télécharger la dernière version » (même clé), sans « J'ai déjà une clé » puisque la page est hors routeur.account.description:upsell.premiumNotForSale: FR « Premium n'est pas encore offert en ligne. » / EN « Premium isn't sold online yet. »settings.updates.notEntitled: FR « Les mises à jour automatiques sont incluses dans l'édition Base. » / EN « Automatic updates are included in the Base edition. »settings.updates.downloadLatest: FR « Télécharger la dernière version » / EN « Download the latest version ».error.updateNotEntitled: inchangé.upsell.ctaGetSoondes deux langues, ainsi que de l'interfaceUpsellMessageset des attentes deentitlements.test.ts.docs.editions.steps[3]FR/EN : retirer la mention « l'achat en ligne arrive bientôt ».docs.editions.tipsFR/EN : un conseil de plus, qui reprend celui du guide : en édition gratuite, la carte Mises à jour propose de télécharger la dernière version depuis la page produit.entitlements.test.tscouvre en FR et en ENupsell.premiumNotForSale,settings.updates.downloadLatestetaccount.descriptionà la place dectaGetSoon.> **Amendement du <date du commit> (#346)** — …en tête. Il indique que le CTA Base est actif viapurchaseUrl, que Premium reste désactivé avec la note « pas encore offert en ligne » tant qu'aucune offre Premium n'est vendable, et que la Gratuite a un lien « Télécharger la dernière version ». Ajouter le renvoi « (voir l'amendement en tête) » en l.66 et en l.111 ; en l.129, remplacer « #270 (câblage du CTA d'achat, à venir) » par « #270 (URL d'achat localisée) ; #346 (CTA d'achat actif, voir l'amendement en tête) ».docs/architecture.md: mettre à jour la ligneUpsellGate(l.299), ajouter une lignePurchaseButtonet une ligneupsellCtaFor, et remplacer « mode upsell compact » par « mode upsell, qui réutiliseUpsellGate» dans la ligne « Gate multi-profils » (l.301).docs/guide-utilisateur.md§12 : puce l.545, et mention du lien de téléchargement de la carte Mises à jour.CHANGELOG.mdetCHANGELOG.fr.md, sous[Unreleased]/[Non publié], dans l'ordre Added / Changed avant les sections Fixed et Security existantes : Added / Ajouté pour l'achat Base depuis les écrans verrouillés et le lien de téléchargement en Gratuite ; Changed / Modifié pour le texte de la carte Compte et la note Premium.Fichiers concernés
src/shared/upsellCta.ts(nouveau)src/shared/upsellCta.test.ts(nouveau)src/components/shared/PurchaseButton.tsx(nouveau)src/components/shared/UpsellGate.tsxsrc/components/profile/ProfileFormModal.tsxsrc/components/settings/UpdateCard.tsxsrc/components/shared/ErrorPage.tsxsrc/i18n/locales/fr.jsonsrc/i18n/locales/en.jsonsrc/services/entitlements.test.tsdocs/adr/0017-feature-gating-par-tier.mddocs/architecture.mddocs/guide-utilisateur.mdCHANGELOG.mdCHANGELOG.fr.mdDepends on
Critères d'acceptation
upsellCtaForest testée : Base achetable sans note, Premium non achetable avecupsell.premiumNotForSale.ProfileSwitchercomme viaProfileFormModal.ProfileFormModaln'a plus de panneau upsell propre, garde son bouton Annuler, et se ferme après « J'ai déjà une clé ».UpsellGaten'appelleuseNavigateque dans un sous-composant rendu soususeInRouterContext().upsell.ctaGetSoonn'existe plus dans aucune langue ni dansentitlements.test.ts.npm testetnpm run buildverts ; CHANGELOG FR/EN.Review caveats
PurchaseButtonpartagé (tâche 2), le CTA serait recopié sur trois surfaces. Le panneau compact deProfileFormModaln'existait qu'à cause duuseNavigateinconditionnel d'UpsellGate(tâches 3 et 4).check()en Gratuite : aucun appel réseau de plus, décision de Max./{fr|en}/produits/simpl-resultatest un contrat avec le site (voir le commentaire desrc/shared/purchaseUrl.ts).architecture.mdet les fichiers i18n. Ces conflits textuels se règlent au merge ; #355 ne touche pasdocs.editions.Décisions prises en planification
upsell.ctaGetSoonest retirée.notEntitled: lien « Télécharger la dernière version » vers la page produit, sans appel réseau (pas decheck()en Gratuite).onNavigate.ErrorPagen'a pas de « J'ai déjà une clé », puisqu'elle est hors routeur.upsellCtaFor, comme les sélecteurs de #270.purchaseUrl).Hors périmètre
/compte.Spec source
spec-plan-paiements.md(séance/plan-rundu 2026-09-24), complété par l'analyse du 2026-09-27. C'est un fichier de travail ignoré par git : ce corps se suffit à lui-même.feat: activer le bouton « Obtenir Base » des UpsellGate + lien d'achat carte Mises à jour + texte carte Compte Maximusto feat: activer « Obtenir Base » (écrans verrouillés, carte Mises à jour, page d'erreur) + note Premium + texte de la carte Comptemaximus referenced this issue2026-09-30 23:53:53 +00:00