(ns app.main.ui.settings.subscription (:require-macros [app.main.style :as stl]) (:require [app.common.data.macros :as dm] [app.common.schema :as sm] [app.common.time :as ct] [app.common.uri :as u] [app.config :as cf] [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] [app.main.ui.components.forms :as fm] [app.main.ui.dashboard.subscription :refer [get-subscription-type]] [app.main.ui.ds.buttons.button :refer [button*]] [app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i] [app.main.ui.ds.foundations.assets.raw-svg :refer [raw-svg*]] [app.main.ui.notifications.badge :refer [badge-notification]] [app.util.dom :as dom] [app.util.i18n :as i18n :refer [tr c]] [potok.v2.core :as ptk] [rumext.v2 :as mf])) (mf/defc plan-card* {::mf/props :obj} [{:keys [card-title card-title-icon price-value price-period cancel-at benefits-title benefits cta-text cta-link cta-text-trial cta-link-trial cta-text-with-icon cta-link-with-icon editors recommended show-button-cta]}] [:div {:class (stl/css-case :plan-card true :plan-card-highlight recommended)} [:div {:class (stl/css :plan-card-header)} [:div {:class (stl/css :plan-card-title-container)} (when card-title-icon [:> icon* {:icon-id card-title-icon :class (stl/css :plan-title-icon) :size "s"}]) [:h4 {:class (stl/css :plan-card-title)} card-title] (when recommended [:& badge-notification {:content (tr "subscription.settings.recommended") :size :small :is-focus true}]) (when editors [:span {:class (stl/css :plan-editors)} (tr "subscription.settings.editors" editors)])] (when (and price-value price-period) [:div {:class (stl/css :plan-price)} [:span {:class (stl/css :plan-price-value)} price-value] [:span {:class (stl/css :plan-price-period)} " / " price-period]]) (when cancel-at [:div {:class (stl/css :plan-cancel)} [:span {:class (stl/css :plan-cancel-date)} cancel-at]])] (when benefits-title [:h5 {:class (stl/css :benefits-title)} benefits-title]) [:ul {:class (stl/css :benefits-list)} (for [benefit benefits] [:li {:key (dm/str benefit) :class (stl/css :benefit)} "- " benefit])] (when (and cta-link-with-icon cta-text-with-icon) [:button {:class (stl/css :cta-button :more-info) :on-click cta-link-with-icon} cta-text-with-icon [:> icon* {:icon-id "open-link" :size "s"}]]) (when (and cta-link cta-text (not show-button-cta)) [:button {:class (stl/css-case :cta-button true :bottom-link (not (and cta-link-trial cta-text-trial))) :on-click cta-link} cta-text]) (when (and cta-link cta-text show-button-cta) [:> button* {:variant "primary" :type "button" :class (stl/css-case :bottom-button (not (and cta-link-trial cta-text-trial))) :on-click cta-link} cta-text]) (when (and cta-link-trial cta-text-trial) [:button {:class (stl/css :cta-button :bottom-link) :on-click cta-link-trial} cta-text-trial])]) (defn- make-management-form-schema [min-editors] [:map {:title "SeatsForm"} [:min-members [::sm/number {:min min-editors :max 9999}]] [:redirect-to-payment-details :boolean]]) (mf/defc subscribe-management-dialog {::mf/register modal/components ::mf/register-as :management-dialog} [{:keys [subscription-type current-subscription editors subscribe-to-trial]}] (let [unlimited-modal-step* (mf/use-state 1) unlimited-modal-step (deref unlimited-modal-step*) subscription-name (if subscribe-to-trial (if (= subscription-type "unlimited") (tr "subscription.settings.unlimited-trial") (tr "subscription.settings.enterprise-trial")) (case subscription-type "professional" (tr "subscription.settings.professional") "unlimited" (tr "subscription.settings.unlimited") "enterprise" (tr "subscription.settings.enterprise"))) min-editors (if (seq editors) (count editors) 1) initial (mf/with-memo [min-editors] {:min-members min-editors :redirect-to-payment-details false}) schema (mf/with-memo [min-editors] (make-management-form-schema min-editors)) form (fm/use-form :schema schema :initial initial) submit-in-progress (mf/use-ref false) subscribe-to-unlimited (mf/use-fn (fn [min-members add-payment-details?] (when-not (mf/ref-val submit-in-progress) (mf/set-ref-val! submit-in-progress true) (let [return-url (-> (rt/get-current-href) (rt/encode-url)) href (dm/str "payments/subscriptions/create?type=unlimited&show=" add-payment-details? "&quantity=" min-members "&returnUrl=" return-url)] (reset! form nil) (st/emit! (ptk/event ::ev/event {::ev/name "create-trial-subscription" :type "unlimited" :quantity min-members}) (rt/nav-raw :href href)))))) subscribe-to-enterprise (mf/use-fn (fn [] (st/emit! (ptk/event ::ev/event {::ev/name "create-trial-subscription" :type "enterprise"})) (let [return-url (-> (rt/get-current-href) (rt/encode-url)) href (dm/str "payments/subscriptions/create?type=enterprise&returnUrl=" return-url)] (st/emit! (rt/nav-raw :href href))))) handle-accept-dialog (mf/use-fn (fn [] (st/emit! (ev/event {::ev/name "open-subscription-management" ::ev/origin "settings" :section "subscription-management-modal"})) (let [current-href (rt/get-current-href) returnUrl (js/encodeURIComponent current-href) href (dm/str "payments/subscriptions/show?returnUrl=" returnUrl)] (st/emit! (rt/nav-raw :href href))) (modal/hide!))) handle-close-dialog (mf/use-fn (fn [] (st/emit! (ptk/event ::ev/event {::ev/name "close-subscription-modal"})) (modal/hide!))) show-editors-list* (mf/use-state false) show-editors-list (deref show-editors-list*) handle-click (mf/use-fn (fn [event] (dom/stop-propagation event) (swap! show-editors-list* not))) on-submit (mf/use-fn (mf/deps current-subscription unlimited-modal-step*) (fn [form] (let [clean-data (get @form :clean-data) min-members (get clean-data :min-members) redirect? (get clean-data :redirect-to-payment-details)] (if (or (contains? #{"unpaid" "canceled"} (:status current-subscription)) (= @unlimited-modal-step* 2)) (subscribe-to-unlimited min-members redirect?) (swap! unlimited-modal-step* inc))))) on-add-payments-click (mf/use-fn (fn [] (swap! form update :data assoc :redirect-to-payment-details true)))] [: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)} (if (= unlimited-modal-step 2) (tr "subscription.settings.management-dialog.step-2-title") (tr "subscription.settings.management.dialog.title" subscription-name))] [:div {:class (stl/css :modal-content)} (when (and (seq editors) (not= unlimited-modal-step 2)) [:* [:p {:class (stl/css :editors-text)} (tr "subscription.settings.management.dialog.currently-editors-title" (c (count editors)))] [:button {:class (stl/css :cta-button :show-editors-button) :on-click handle-click} (tr "subscription.settings.management.dialog.editors") [:> icon* {:icon-id (if show-editors-list i/arrow-up i/arrow-down) :class (stl/css :icon-dropdown) :size "s"}]] (when show-editors-list [:* [:p {:class (stl/css :editors-text :editors-list-warning)} (tr "subscription.settings.management.dialog.editors-explanation")] [:ul {:class (stl/css :editors-list)} (for [editor editors] [:li {:key (dm/str (:id editor)) :class (stl/css :team-name)} "- " (:name editor)])]])]) (when (and (or (and (= subscription-type "professional") (contains? #{"unlimited" "enterprise"} (:type current-subscription))) (and (= subscription-type "unlimited") (= (:type current-subscription) "enterprise"))) (not (contains? #{"unpaid" "canceled"} (:status current-subscription))) (not subscribe-to-trial)) [:div {:class (stl/css :modal-text)} (tr "subscription.settings.management.dialog.downgrade")]) (if (and (= subscription-type "unlimited") (or subscribe-to-trial (contains? #{"unpaid" "canceled"} (:status current-subscription)))) [:& fm/form {:on-submit on-submit :class (stl/css :seats-form) :form form} (when (= unlimited-modal-step 1) [:* [:div {:class (stl/css :editors-wrapper)} [:div {:class (stl/css :fields-row)} [:& fm/input {:type "number" :name :min-members :show-error false :label "" :class (stl/css :input-field)}]] [:div {:class (stl/css :editors-cost)} [:span {:class (stl/css :modal-text-medium)} (when (> (get-in @form [:clean-data :min-members]) 25) [:> i18n/tr-html* {:class (stl/css :modal-text-cap) :tag-name "span" :content (tr "subscription.settings.management.dialog.price-month" "175")}]) [:> i18n/tr-html* {:class (stl/css-case :text-strikethrough (> (get-in @form [:clean-data :min-members]) 25)) :tag-name "span" :content (tr "subscription.settings.management.dialog.price-month" (* 7 (or (get-in @form [:clean-data :min-members]) 0)))}]] [:span {:class (stl/css :modal-text-medium)} (tr "subscription.settings.management.dialog.payment-explanation")]]] (when (get-in @form [:errors :min-members]) [:div {:class (stl/css :error-message)} (tr "subscription.settings.management.dialog.input-error")]) [:div {:class (stl/css :unlimited-capped-warning)} (tr "subscription.settings.management.dialog.unlimited-capped-warning")] [: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 (if (contains? #{"unpaid" "canceled"} (:status current-subscription)) (tr "subscription.settings.subscribe") (tr "labels.continue")) :class (stl/css :primary-button)}]]]]) (when (= unlimited-modal-step 2) [:* [:p {:class (stl/css :modal-text-medium)} (tr "subscription.settings.management-dialog.step-2-description")] [:div {:class (stl/css :modal-footer)} [:div {:class (stl/css :action-buttons)} [:input {:class (stl/css :cancel-button) :type "submit" :value (tr "subscription.settings.management-dialog.step-2-skip-button")}] [:input {:class (stl/css :primary-button) :type "submit" :value (tr "subscription.settings.management-dialog.step-2-add-payment-button") :on-click on-add-payments-click}]]]])] [: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}] [:input {:class (stl/css :primary-button) :type "button" :value (if subscribe-to-trial (tr "subscription.settings.start-trial") (tr "labels.continue")) :on-click (if (or subscribe-to-trial (contains? #{"unpaid" "canceled"} (:status current-subscription))) subscribe-to-enterprise handle-accept-dialog)}]]])]]])) (mf/defc subscription-success-dialog {::mf/register modal/components ::mf/register-as :subscription-success} [{:keys [subscription-name]}] (let [profile (mf/deref refs/profile) handle-close-dialog (mf/use-fn (fn [] (st/emit! (ptk/event ::ev/event {::ev/name "subscription-success"})) (modal/hide!)))] [:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-dialog :subscription-success)} [:button {:class (stl/css :close-btn) :on-click handle-close-dialog} [:> icon* {:icon-id "close" :size "m"}]] [:div {:class (stl/css :modal-success-content)} [:div {:class (stl/css :modal-start)} [:> raw-svg* {:id (if (= "light" (:theme profile)) "logo-subscription-light" "logo-subscription")}]] [:div {:class (stl/css :modal-end)} [:div {:class (stl/css :modal-title)} (tr "subscription.settings.sucess.dialog.title" subscription-name)] (when (not= subscription-name "professional") [:p {:class (stl/css :modal-text-large)} (tr "subscription.settings.success.dialog.thanks" subscription-name)]) [:p {:class (stl/css :modal-text-large)} (tr "subscription.settings.success.dialog.description")] [:p {:class (stl/css :modal-text-large)} (tr "subscription.settings.sucess.dialog.footer")] [:div {:class (stl/css :success-action-buttons)} [:input {:class (stl/css :primary-button) :type "button" :value (tr "labels.close") :on-click handle-close-dialog}]]]]]])) (mf/defc nitrate-success-dialog {::mf/register modal/components ::mf/register-as :nitrate-success} [] ;; TODO add translations for this texts when we have the definitive ones (let [profile (mf/deref refs/profile)] [:div {:class (stl/css :modal-overlay)} [:div {:class (stl/css :modal-dialog :subscription-success)} [:button {:class (stl/css :close-btn) :on-click modal/hide!} [:> icon* {:icon-id "close" :size "m"}]] [:div {:class (stl/css :modal-success-content)} [:div {:class (stl/css :modal-start)} [:> raw-svg* {:id (if (= "light" (:theme profile)) "logo-subscription-light" "logo-subscription")}]] [:div {:class (stl/css :modal-end)} [:div {:class (stl/css :modal-title)} "You are Business Nitrate!"] [:p {:class (stl/css :modal-text-large)} (tr "subscription.settings.success.dialog.description")] [:p {:class (stl/css :modal-text-large)} (tr "subscription.settings.sucess.dialog.footer")] [:div {:class (stl/css :success-action-buttons)} [:input {:class (stl/css :primary-button) :type "button" :value "CREATE ORGANIZATION" :on-click dnt/go-to-nitrate-cc-create-org}]]]]]])) (mf/defc subscription-page* [{:keys [profile]}] (let [route (mf/deref refs/route) authenticated? (da/is-authenticated? profile) nitrate-license (:subscription profile) nitrate? (dnt/is-valid-license? profile) params-subscription (-> route :params :query :subscription) show-trial-subscription-modal? (or (= params-subscription "subscription-to-penpot-unlimited") (= params-subscription "subscription-to-penpot-enterprise")) show-subscription-success-modal? (or (= params-subscription "subscribed-to-penpot-unlimited") (= params-subscription "subscribed-to-penpot-enterprise") (= params-subscription "subscribed-to-penpot-nitrate")) success-modal-is-trial? (-> route :params :query :trial) subscription-editors (-> profile :props :subscription :editors) subscription (-> profile :props :subscription) subscription-type (if (and (contains? cf/flags :nitrate) nitrate?) (:type nitrate-license) (get-subscription-type subscription)) subscription-is-trial? (= (:status subscription) "trialing") member-since (ct/format-inst (:created-at profile) "d MMMM, yyyy") subscribed-since (if nitrate? (ct/format-inst (:created-at nitrate-license) "d MMMM, yyyy") (ct/format-inst (:start-date subscription) "d MMMM, yyyy")) go-to-pricing-page (mf/use-fn (fn [] (st/emit! (ev/event {::ev/name "explore-pricing-click" ::ev/origin "settings" :section "subscription"})) (dom/open-new-window "https://penpot.app/pricing"))) go-to-payments (mf/use-fn (fn [] (st/emit! (ev/event {::ev/name "open-subscription-management" ::ev/origin "settings" :section "subscription"})) (let [current-href (rt/get-current-href) returnUrl (js/encodeURIComponent current-href) href (dm/str "payments/subscriptions/show?returnUrl=" returnUrl)] (st/emit! (rt/nav-raw :href href))))) open-subscription-modal (mf/use-fn (mf/deps subscription-editors nitrate-license) (fn [subscription-type current-subscription] (st/emit! (ev/event {::ev/name "open-subscription-modal" ::ev/origin "settings:in-app"})) (if (= subscription-type "nitrate") (st/emit! (dnt/show-nitrate-popup :nitrate-dialog {:nitrate-license nitrate-license})) (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"))) (mf/with-effect [authenticated? show-subscription-success-modal? show-trial-subscription-modal? success-modal-is-trial? subscription] (when ^boolean authenticated? (cond ^boolean show-trial-subscription-modal? (st/emit! (ptk/event ::ev/event {::ev/name "open-subscription-modal" ::ev/origin "settings:from-pricing-page"}) (modal/show :management-dialog {:subscription-type (if (= params-subscription "subscription-to-penpot-unlimited") "unlimited" "enterprise") :current-subscription subscription :editors subscription-editors :subscribe-to-trial (not (:type subscription))}) (rt/nav :settings-subscription {} {::rt/replace true})) ^boolean show-subscription-success-modal? (st/emit! (if (= params-subscription "subscribed-to-penpot-nitrate") (modal/show :nitrate-success {}) (modal/show :subscription-success {:subscription-name (if (= params-subscription "subscribed-to-penpot-unlimited") (if (= success-modal-is-trial? "true") (tr "subscription.settings.unlimited-trial") (tr "subscription.settings.unlimited")) (if (= success-modal-is-trial? "true") (tr "subscription.settings.enterprise-trial") (tr "subscription.settings.enterprise")))})) (rt/nav :settings-subscription {} {::rt/replace true}))))) [:section {:class (stl/css :dashboard-section)} [:div {:class (stl/css :dashboard-content)} [:h2 {:class (stl/css :title-section)} (tr "subscription.labels")] [:div {:class (stl/css :your-subscription)} [:h3 {:class (stl/css :plan-section-title)} (tr "subscription.settings.section-plan")] (if nitrate? ;; TODO add translations for this texts when we have the definitive ones [:> plan-card* {:card-title "Business Nitrate" :card-title-icon i/character-b :cancel-at (when (:cancel-at nitrate-license) (dm/str "Active until " (ct/format-inst (:cancel-at nitrate-license) "d MMMM, yyyy"))) :benefits-title "Loren ipsum", :benefits ["Loren ipsum", "Loren ipsum", "Loren ipsum"] :cta-text-with-icon "Control Center" :cta-link-with-icon dnt/go-to-nitrate-cc :cta-text (tr "subscription.settings.manage-your-subscription") :cta-link dnt/go-to-nitrate-billing}] (case subscription-type "professional" [:> plan-card* {:card-title (tr "subscription.settings.professional") :benefits [(tr "subscription.settings.professional.storage-benefit"), (tr "subscription.settings.professional.autosave-benefit"), (tr "subscription.settings.professional.teams-editors-benefit")]}] "unlimited" (if subscription-is-trial? [:> plan-card* {:card-title (tr "subscription.settings.unlimited-trial") :card-title-icon i/character-u :benefits-title (tr "subscription.settings.benefits.all-professional-benefits"), :benefits [(tr "subscription.settings.unlimited.storage-benefit") (tr "subscription.settings.unlimited.autosave-benefit"), (tr "subscription.settings.unlimited.bill")] :cta-text (tr "subscription.settings.manage-your-subscription") :cta-link go-to-payments :cta-text-trial (tr "subscription.settings.add-payment-to-continue") :cta-link-trial go-to-payments :editors (-> profile :props :subscription :quantity)}] [:> plan-card* {:card-title (tr "subscription.settings.unlimited") :card-title-icon i/character-u :benefits-title (tr "subscription.settings.benefits.all-unlimited-benefits") :benefits [(tr "subscription.settings.unlimited.storage-benefit"), (tr "subscription.settings.unlimited.autosave-benefit"), (tr "subscription.settings.unlimited.bill")] :cta-text (tr "subscription.settings.manage-your-subscription") :cta-link go-to-payments :editors (-> profile :props :subscription :quantity)}]) "enterprise" (if subscription-is-trial? [:> plan-card* {:card-title (tr "subscription.settings.enterprise-trial") :card-title-icon i/character-e :benefits-title (tr "subscription.settings.benefits.all-unlimited-benefits"), :benefits [(tr "subscription.settings.enterprise.unlimited-storage-benefit"), (tr "subscription.settings.enterprise.autosave"), (tr "subscription.settings.enterprise.capped-bill")] :cta-text (tr "subscription.settings.manage-your-subscription") :cta-link go-to-payments :cta-text-trial (tr "subscription.settings.add-payment-to-continue") :cta-link-trial go-to-payments}] [:> plan-card* {:card-title (tr "subscription.settings.enterprise") :card-title-icon i/character-e :benefits-title (tr "subscription.settings.benefits.all-unlimited-benefits"), :benefits [(tr "subscription.settings.enterprise.unlimited-storage-benefit"), (tr "subscription.settings.enterprise.autosave"), (tr "subscription.settings.enterprise.capped-bill")] :cta-text (tr "subscription.settings.manage-your-subscription") :cta-link go-to-payments}]))) [:div {:class (stl/css :membership-container)} (when (or nitrate? (and subscribed-since (not= subscription-type "professional"))) [:div {:class (stl/css :membership)} [:> icon* {:class (stl/css :subscription-member) :icon-id "crown" :size "m"}] [:span {:class (stl/css :membership-date)} (tr "subscription.settings.support-us-since" subscribed-since)]]) [:div {:class (stl/css :membership)} [:> icon* {:class (stl/css :penpot-member) :icon-id "user" :size "m"}] [:span {:class (stl/css :membership-date)} (tr "subscription.settings.member-since" member-since)]]]] [:div {:class (stl/css :other-subscriptions)} [:h3 {:class (stl/css :plan-section-title)} (tr "subscription.settings.other-plans")] (when (not= subscription-type "professional") [:> plan-card* {:card-title (tr "subscription.settings.professional") :price-value "$0" :price-period (tr "subscription.settings.price-editor-month") :benefits [(tr "subscription.settings.professional.storage-benefit"), (tr "subscription.settings.professional.autosave-benefit"), (tr "subscription.settings.professional.teams-editors-benefit")] :cta-text (tr "subscription.settings.subscribe") :cta-link #(open-subscription-modal "professional") :cta-text-with-icon (tr "subscription.settings.more-information") :cta-link-with-icon go-to-pricing-page}]) (when (not= subscription-type "unlimited") [:> plan-card* {:card-title (tr "subscription.settings.unlimited") :card-title-icon i/character-u :price-value "$7" :price-period (tr "subscription.settings.price-editor-month") :benefits-title (tr "subscription.settings.benefits.all-professional-benefits") :benefits [(tr "subscription.settings.unlimited.storage-benefit"), (tr "subscription.settings.unlimited.autosave-benefit"), (tr "subscription.settings.unlimited.bill")] :cta-text (if (:type subscription) (tr "subscription.settings.subscribe") (tr "subscription.settings.try-it-free")) :cta-link #(open-subscription-modal "unlimited" subscription) :cta-text-with-icon (tr "subscription.settings.more-information") :cta-link-with-icon go-to-pricing-page :recommended (= subscription-type "professional") :show-button-cta (= subscription-type "professional")}]) (when (and (not= subscription-type "enterprise") (not (contains? cf/flags :nitrate))) [:> plan-card* {:card-title (tr "subscription.settings.enterprise") :card-title-icon i/character-e :price-value "$950" :price-period (tr "subscription.settings.price-organization-month") :benefits-title (tr "subscription.settings.benefits.all-unlimited-benefits") :benefits [(tr "subscription.settings.enterprise.unlimited-storage-benefit"), (tr "subscription.settings.enterprise.autosave"), (tr "subscription.settings.enterprise.capped-bill")] :cta-text (if (:type subscription) (tr "subscription.settings.subscribe") (tr "subscription.settings.try-it-free")) :cta-link #(open-subscription-modal "enterprise" subscription) :cta-text-with-icon (tr "subscription.settings.more-information") :cta-link-with-icon go-to-pricing-page :show-button-cta (= subscription-type "professional")}]) ;; TODO add translations for this texts when we have the definitive ones (when (and (contains? cf/flags :nitrate) (not nitrate?)) [:> plan-card* {:card-title "Business Nitrate" :card-title-icon i/character-n :price-value "$25" :price-period "org member" :benefits-title (tr "subscription.settings.benefits.all-unlimited-benefits") :benefits ["Crea organizaciones y añade personas, que usarán Penpot con las reglas que configures." "Acceso exclusivo al Control Center" "Lorem ipsum"] :cta-text (if nitrate-license (tr "subscription.settings.subscribe") "Try 14 days for free") :cta-link #(open-subscription-modal "nitrate" subscription) :cta-text-with-icon (tr "subscription.settings.more-information") :cta-link-with-icon go-to-pricing-page :show-button-cta (not nitrate-license)}])]]])) (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} [{:keys [nitrate-license] :as 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 [subscription (-> @form :clean-data :subscription name) return-url (dm/str (rt/get-current-href) "?" (u/map->query-string {:subscription "subscribed-to-penpot-nitrate"}))] (dnt/go-to-buy-nitrate-license subscription return-url))))] [: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 (if nitrate-license (tr "subscription.settings.subscribe") "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)} (if nitrate-license "Contact us to upgrade to Nitrate:" "Contact us to try Nitrate for 14 days:")] [:div {:class (stl/css :modal-text)} [:a {:class (stl/css :cta-button) :href "mailto:sales@penpot.app"} "sales@penpot.app"]]])]]))