From e4b69426e95ae8ff1ed1aeb6175aba8db1f0bec3 Mon Sep 17 00:00:00 2001 From: Pablo Alba Date: Tue, 24 Feb 2026 13:06:10 +0100 Subject: [PATCH] :sparkles: Add subscribe to nitrate dialog --- frontend/src/app/main/data/nitrate.cljs | 6 +- .../src/app/main/ui/dashboard/sidebar.cljs | 4 +- .../app/main/ui/dashboard/subscription.cljs | 4 +- .../app/main/ui/dashboard/subscription.scss | 4 + .../src/app/main/ui/nitrate/nitrate_form.cljs | 4 +- .../app/main/ui/settings/subscription.cljs | 100 ++++++++++++++++-- .../app/main/ui/settings/subscription.scss | 19 ++++ 7 files changed, 126 insertions(+), 15 deletions(-) diff --git a/frontend/src/app/main/data/nitrate.cljs b/frontend/src/app/main/data/nitrate.cljs index 14c32a5021..1f9a916e56 100644 --- a/frontend/src/app/main/data/nitrate.cljs +++ b/frontend/src/app/main/data/nitrate.cljs @@ -6,10 +6,12 @@ [potok.v2.core :as ptk])) (defn show-nitrate-popup - [] + [popup-type] (ptk/reify ::show-nitrate-popup ptk/WatchEvent (watch [_ _ _] (->> (rp/cmd! ::get-nitrate-connectivity {}) (rx/map (fn [connectivity] - (modal/show :nitrate-form (or connectivity {})))))))) + (modal/show popup-type (or connectivity {})))))))) + + diff --git a/frontend/src/app/main/ui/dashboard/sidebar.cljs b/frontend/src/app/main/ui/dashboard/sidebar.cljs index a293f11bfe..d1bccb550d 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/app/main/ui/dashboard/sidebar.cljs @@ -305,7 +305,7 @@ (if (:nitrate-licence profile) ;; TODO update when org creation route is ready (dom/open-new-window "/control-center/org/create") - (st/emit! (dnt/show-nitrate-popup)))))] + (st/emit! (dnt/show-nitrate-popup :nitrate-form)))))] [:> dropdown-menu* props @@ -551,7 +551,7 @@ (if (:nitrate-licence profile) ;; TODO update when org creation route is ready (dom/open-new-window "/control-center/org/create") - (st/emit! (dnt/show-nitrate-popup)))))] + (st/emit! (dnt/show-nitrate-popup :nitrate-form)))))] (if empty? [:div {:class (stl/css :nitrate-orgs-empty)} [:span {:class (stl/css :nitrate-penpot-icon)} diff --git a/frontend/src/app/main/ui/dashboard/subscription.cljs b/frontend/src/app/main/ui/dashboard/subscription.cljs index be502bb46f..84630e1bbd 100644 --- a/frontend/src/app/main/ui/dashboard/subscription.cljs +++ b/frontend/src/app/main/ui/dashboard/subscription.cljs @@ -121,7 +121,7 @@ (let [handle-click (mf/use-fn (fn [] - (st/emit! (dnt/show-nitrate-popup))))] + (st/emit! (dnt/show-nitrate-popup :nitrate-form))))] ;; TODO add translations for this texts when we have the definitive ones [:div {:class (stl/css :nitrate-banner :highlighted)} @@ -133,7 +133,7 @@ [:span {:class (stl/css :nitrate-info)} "Some further information and explanation."] [:> button* {:variant "primary" :type "button" - :class (stl/css :cta-bottom-button) + :class (stl/css :cta-bottom-button :nitrate-bottom-button) :on-click handle-click} "UPGRADE TO NITRATE"]]])) (mf/defc team* diff --git a/frontend/src/app/main/ui/dashboard/subscription.scss b/frontend/src/app/main/ui/dashboard/subscription.scss index ded491e67b..b27fb7a610 100644 --- a/frontend/src/app/main/ui/dashboard/subscription.scss +++ b/frontend/src/app/main/ui/dashboard/subscription.scss @@ -230,3 +230,7 @@ display: flex; flex-direction: column; } + +.nitrate-bottom-button { + width: fit-content; +} diff --git a/frontend/src/app/main/ui/nitrate/nitrate_form.cljs b/frontend/src/app/main/ui/nitrate/nitrate_form.cljs index 6870a70e3b..4e02d72dc2 100644 --- a/frontend/src/app/main/ui/nitrate/nitrate_form.cljs +++ b/frontend/src/app/main/ui/nitrate/nitrate_form.cljs @@ -26,7 +26,7 @@ ::mf/wrap-props true} [connectivity] - (let [show-buttons (:licenses connectivity) + (let [online? (:licenses connectivity) initial (mf/with-memo [] {:subscription "yearly"}) form (fm/use-form :schema schema:nitrate-form @@ -58,7 +58,7 @@ "Sail ho shrouds spirits boom mizzenmast yardarm. Pinnace holystone mizzenmast quarter crow's nest nipperkin grog yardarm hempen halter furl."] [:p {:class (stl/css :modal-text-large)} "Deadlights jack lad schooner scallywag dance the hempen jig carouser broadside cable strike colors."] - (if show-buttons + (if online? [:& fm/form {:form form} [:p {:class (stl/css :modal-text-large)} diff --git a/frontend/src/app/main/ui/settings/subscription.cljs b/frontend/src/app/main/ui/settings/subscription.cljs index a69e6f9a58..f3cabc939e 100644 --- a/frontend/src/app/main/ui/settings/subscription.cljs +++ b/frontend/src/app/main/ui/settings/subscription.cljs @@ -8,6 +8,7 @@ [app.main.data.auth :as da] [app.main.data.event :as ev] [app.main.data.modal :as modal] + [app.main.data.nitrate :as dnt] [app.main.refs :as refs] [app.main.router :as rt] [app.main.store :as st] @@ -416,11 +417,13 @@ (fn [subscription-type current-subscription] (st/emit! (ev/event {::ev/name "open-subscription-modal" ::ev/origin "settings:in-app"})) - (st/emit! - (modal/show :management-dialog - {:subscription-type subscription-type - :current-subscription current-subscription - :editors subscription-editors :subscribe-to-trial (not (:type subscription))}))))] + (if (= subscription-type "nitrate") + (st/emit! (dnt/show-nitrate-popup :nitrate-dialog)) + (st/emit! + (modal/show :management-dialog + {:subscription-type subscription-type + :current-subscription current-subscription + :editors subscription-editors :subscribe-to-trial (not (:type subscription))})))))] (mf/with-effect [] (dom/set-html-title (tr "subscription.labels"))) @@ -589,8 +592,91 @@ "Acceso exclusivo al Control Center" "Lorem ipsum"] :cta-text (tr "subscription.settings.subscribe") - ;; TODO add link to open nitrate modal - :cta-link #(dom/open-new-window "https://penpot.app/nitrate") + :cta-link #(open-subscription-modal "nitrate" subscription) :cta-text-with-icon (tr "subscription.settings.more-information") :cta-link-with-icon go-to-pricing-page}])]]])) + +(def ^:private schema:nitrate-form + [:map {:title "NitrateForm"} + [:subscription [::sm/one-of #{:monthly :yearly}]]]) + +(mf/defc subscribe-nitrate-dialog + {::mf/register modal/components + ::mf/register-as :nitrate-dialog} + [connectivity] + ;; TODO add translations for this texts when we have the definitive ones + (let [online? (:licenses connectivity) + initial (mf/with-memo [] + {:subscription "yearly"}) + form (fm/use-form :schema schema:nitrate-form + :initial initial) + + handle-close-dialog + (mf/use-fn + (fn [] + (modal/hide!))) + + on-submit + (mf/use-fn + (mf/deps form) + (fn [] + (let [params (:clean-data @form)] + (dom/open-new-window (str "/control-center/licenses/start?subscription=" (name (:subscription params)))))))] + + [:div {:class (stl/css :modal-overlay)} + [:div {:class (stl/css :modal-dialog)} + [:button {:class (stl/css :close-btn) :on-click handle-close-dialog} + [:> icon* {:icon-id "close" + :size "m"}]] + [:div {:class (stl/css :modal-title :subscription-title)} + "Subcribe to the Business Nitrate plan"] + + (if online? + [:div {:class (stl/css :modal-content)} + + + + [:div {:class (stl/css :modal-text)} + "Lorem ipsum lorem ipsum:"] + + + [:& fm/form {:on-submit on-submit + :class (stl/css :seats-form) + :form form} + + [:* + [:div {:class (stl/css :editors-wrapper)} + [:div {:class (stl/css :fields-row)} + [:& fm/radio-buttons + {:options [{:label "Price Tag Yearly (Discount)" :value "yearly"} + {:label "Price Tag Montly" :value "monthly"}] + :name :subscription + :class (stl/css :radio-btns)}]]] + [:div {:class (stl/css :modal-text)} + "You won’t be charged right now. Payment will be processed at the end of the trial. Cancel anytime."] + + + + [:div {:class (stl/css :modal-footer)} + [:div {:class (stl/css :action-buttons)} + [:input + {:class (stl/css :cancel-button) + :type "button" + :value (tr "ds.confirm-cancel") + :on-click handle-close-dialog}] + + [:> fm/submit-button* + {:label "TRY 14 DAYS FOR FREE" + :class (stl/css :primary-button)}]]]]]] + [:div {:class (stl/css :modal-content :modal-contact-content)} + [:div {:class (stl/css :modal-text)} + "Lorem ipsum lorem ipsum Lorem ipsum lorem ipsum Lorem ipsum lorem ipsum"] + [:div {:class (stl/css :modal-text)} + "Contact us to upgrade to Nitrate:"] + [:div {:class (stl/css :modal-text)} + [:a {:class (stl/css :link) :href "mailto:sales@penpot.app"} + "sales@penpot.app"]]])]])) + + + diff --git a/frontend/src/app/main/ui/settings/subscription.scss b/frontend/src/app/main/ui/settings/subscription.scss index e86d54cd16..f98c1caef3 100644 --- a/frontend/src/app/main/ui/settings/subscription.scss +++ b/frontend/src/app/main/ui/settings/subscription.scss @@ -329,3 +329,22 @@ .show-editors-button { padding-inline: 0; } + +.radio-btns { + label { + @include t.use-typography("body-large"); + padding: 0; + display: flex; + align-items: center; + color: var(--color-foreground-secondary); + } + + display: flex; + flex-direction: column; + padding: 0 0 var(--sp-xl) 0; + gap: var(--sp-s); +} + +.modal-contact-content { + gap: var(--sp-xl); +}