mirror of
https://github.com/penpot/penpot.git
synced 2026-04-25 11:18:36 +00:00
✨ Subscribe with an activation code WIP
This commit is contained in:
parent
6c4ab8940d
commit
75e5c3dca1
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 88 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 63 KiB |
BIN
frontend/resources/images/nitrate-success.png
Normal file
BIN
frontend/resources/images/nitrate-success.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
@ -369,6 +369,9 @@ async function generateSvgSprite(files, prefix) {
|
||||
mode: {
|
||||
symbol: { inline: true },
|
||||
},
|
||||
shape: {
|
||||
transform: [],
|
||||
},
|
||||
});
|
||||
|
||||
for (let path of files) {
|
||||
|
||||
@ -40,7 +40,9 @@
|
||||
[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.icons :as deprecated-icon]
|
||||
[app.main.ui.nitrate.nitrate-code-activation-modal]
|
||||
[app.main.ui.nitrate.nitrate-form]
|
||||
[app.main.ui.nitrate.nitrate-activation-success-modal]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.dom.dnd :as dnd]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
|
||||
@ -21,6 +21,8 @@
|
||||
(def ^:svg-id logo-subscription "logo-subscription")
|
||||
(def ^:svg-id logo-subscription-light "logo-subscription-light")
|
||||
(def ^:svg-id nitrate-welcome "nitrate-welcome")
|
||||
(def ^:svg-id nitrate-success-dark "nitrate-success-dark")
|
||||
(def ^:svg-id nitrate-success-light "nitrate-success-light")
|
||||
(def ^:svg-id marketing-arrows "marketing-arrows")
|
||||
(def ^:svg-id marketing-exchange "marketing-exchange")
|
||||
(def ^:svg-id marketing-file "marketing-file")
|
||||
@ -39,3 +41,4 @@
|
||||
(assert (contains? raw-svg-list id) "invalid raw svg id")
|
||||
[:> "svg" props
|
||||
[:use {:href (dm/str "#asset-" id)}]])
|
||||
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.nitrate.nitrate-activation-success-modal
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.time :as ct]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.nitrate :as dnt]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.ds.buttons.button :refer [button*]]
|
||||
[app.main.ui.ds.foundations.assets.icon :as i :refer [icon*]]
|
||||
[app.main.ui.ds.foundations.assets.raw-svg :refer [raw-svg*]]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[app.util.theme :as theme]
|
||||
[beicon.v2.core :as rx]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc nitrate-activation-success-modal*
|
||||
{::mf/register modal/components
|
||||
::mf/register-as :nitrate-activation-success
|
||||
::mf/wrap-props true}
|
||||
[connectivity]
|
||||
|
||||
(let [profile (mf/deref refs/profile)
|
||||
profile-theme (get profile :theme theme/default)
|
||||
system-theme* (mf/use-state theme/get-system-theme)
|
||||
|
||||
light?
|
||||
(mf/with-memo [profile-theme (deref system-theme*)]
|
||||
(let [resolved (cond
|
||||
(= profile-theme "light") "light"
|
||||
(= profile-theme "system") (deref system-theme*)
|
||||
:else "dark")]
|
||||
(= resolved "light")))
|
||||
|
||||
svg-id (if light? "nitrate-success-light" "nitrate-success-dark")
|
||||
|
||||
cancel-at (dm/get-in connectivity [:subscription :cancel-at])
|
||||
date-str (when cancel-at
|
||||
(ct/format-inst cancel-at "d MMMM, yyyy"))
|
||||
|
||||
on-create-org
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(modal/hide!)
|
||||
(dnt/go-to-nitrate-cc-create-org)))]
|
||||
|
||||
(mf/with-effect []
|
||||
(let [s (->> (rx/from-event (.. js/window (matchMedia "(prefers-color-scheme: dark)")) "change")
|
||||
(rx/map #(if (.-matches %) "dark" "light"))
|
||||
(rx/subs! #(reset! system-theme* %)))]
|
||||
(fn [] (rx/dispose! s))))
|
||||
|
||||
[:div {:class (stl/css :modal-overlay)}
|
||||
[:div {:class (stl/css :modal-dialog)}
|
||||
[:button {:class (stl/css :close-btn) :on-click modal/hide!}
|
||||
[:> icon* {:icon-id "close"
|
||||
:size "m"}]]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:div {:class (stl/css :modal-start)}
|
||||
[:> raw-svg* {:id svg-id}]]
|
||||
|
||||
[:div {:class (stl/css :modal-end)}
|
||||
[:div {:class (stl/css :modal-title)}
|
||||
"You are Business Nitrate!"]
|
||||
|
||||
[:p {:class (stl/css :modal-text-primary)}
|
||||
(dm/str "Your plan is active until " (or date-str "—") ".")]
|
||||
|
||||
[:p {:class (stl/css :modal-text)}
|
||||
"You can manage your subscription anytime from the Subscription page in your account settings."]
|
||||
|
||||
[:p {:class (stl/css :modal-text)}
|
||||
"Enjoy your plan!"]
|
||||
|
||||
[:> button* {:variant "primary"
|
||||
:on-click on-create-org
|
||||
:class (stl/css :modal-button)}
|
||||
"Create organization"]]]]]))
|
||||
@ -0,0 +1,79 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@use "refactor/common-refactor.scss" as deprecated;
|
||||
@use "ds/typography.scss" as t;
|
||||
@use "ds/_borders.scss" as *;
|
||||
@use "ds/spacing.scss" as *;
|
||||
@use "ds/_sizes.scss" as *;
|
||||
@use "ds/_utils.scss" as *;
|
||||
|
||||
.modal-overlay {
|
||||
@extend %modal-overlay-base;
|
||||
|
||||
z-index: var(--z-index-notifications);
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
@extend %modal-container-base;
|
||||
|
||||
max-block-size: initial;
|
||||
min-inline-size: px2rem(608);
|
||||
max-inline-size: px2rem(608);
|
||||
padding: var(--sp-xxxl);
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
@extend %modal-close-btn-base;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
display: flex;
|
||||
gap: $sz-40;
|
||||
}
|
||||
|
||||
.modal-start {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
min-inline-size: $sz-224;
|
||||
|
||||
svg {
|
||||
inline-size: 100%;
|
||||
block-size: auto;
|
||||
}
|
||||
|
||||
@media (width <= 640px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-end {
|
||||
color: var(--color-foreground-secondary);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--sp-m);
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
@include t.use-typography("title-large");
|
||||
|
||||
color: var(--modal-title-foreground-color);
|
||||
}
|
||||
|
||||
.modal-text-primary {
|
||||
@include t.use-typography("body-large");
|
||||
|
||||
color: var(--color-foreground-primary);
|
||||
}
|
||||
|
||||
.modal-text {
|
||||
@include t.use-typography("body-large");
|
||||
}
|
||||
|
||||
.modal-button {
|
||||
margin-block-start: var(--sp-s);
|
||||
align-self: flex-start;
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.nitrate.nitrate-code-activation-modal
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.forms :as fm]
|
||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||
[app.main.ui.ds.foundations.assets.icon :as i]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def ^:private schema:activate-form
|
||||
[:map {:title "ActivateForm"}
|
||||
[:activation-code [:string {:min 1}]]])
|
||||
|
||||
(mf/defc nitrate-code-activation-modal*
|
||||
{::mf/register modal/components
|
||||
::mf/register-as :nitrate-code-activation}
|
||||
[_props]
|
||||
(let [initial (mf/with-memo []
|
||||
{:activation-code ""})
|
||||
form (fm/use-form :schema schema:activate-form
|
||||
:initial initial)
|
||||
|
||||
on-accept
|
||||
(mf/use-fn
|
||||
(mf/deps form)
|
||||
(fn [_]
|
||||
;; TODO: dispatch activation action with (-> @form :clean-data :activation-code)
|
||||
(modal/hide!)
|
||||
;; TODO: remove, only for flow testing
|
||||
(st/emit! (modal/show {:type :nitrate-activation-success}))))]
|
||||
|
||||
[:div {:class (stl/css :modal-overlay)}
|
||||
[:div {:class (stl/css :modal-dialog)}
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:class (stl/css :close-btn)
|
||||
:aria-label (tr "labels.close")
|
||||
:on-click modal/hide!
|
||||
:icon i/close}]
|
||||
|
||||
[:div {:class (stl/css :modal-header)}
|
||||
[:h2 {:class (stl/css :modal-title)} "Activate Nitrate"]]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:& fm/form {:form form :on-submit on-accept}
|
||||
[:& fm/input {:name :activation-code
|
||||
:auto-focus? true
|
||||
:label "Enter your activation code"
|
||||
:type "text"
|
||||
:placeholder "XXXX-XXXXX-XXXXX-XXXXX"}]]
|
||||
[:input
|
||||
{:type "button"
|
||||
:class (stl/css-case :accept-btn true
|
||||
:global/disabled (not (:valid @form)))
|
||||
:disabled (not (:valid @form))
|
||||
:value "Activate"
|
||||
:on-click on-accept}]
|
||||
[:div {:class (stl/css :footer-text)}
|
||||
"Need a code? Contact us: "
|
||||
[:a {:class (stl/css :link)
|
||||
:href "mailto:sales@nitrate.com"}
|
||||
"sales@nitrate.com"]]]]]))
|
||||
@ -0,0 +1,65 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@use "refactor/common-refactor.scss" as deprecated;
|
||||
@use "ds/typography.scss" as t;
|
||||
@use "ds/spacing.scss" as *;
|
||||
@use "ds/_sizes.scss" as *;
|
||||
|
||||
.close-btn {
|
||||
@extend %modal-close-btn-base;
|
||||
}
|
||||
|
||||
.modal-overlay {
|
||||
@extend %modal-overlay-base;
|
||||
|
||||
z-index: var(--z-index-notifications);
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
@extend %modal-container-base;
|
||||
|
||||
min-inline-size: px2rem(480);
|
||||
padding: var(--sp-xxxl);
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
@include t.use-typography("title-large");
|
||||
|
||||
color: var(--modal-title-foreground-color);
|
||||
margin-block-end: var(--sp-xxxl);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--sp-m);
|
||||
color: var(--color-foreground-secondary);
|
||||
}
|
||||
|
||||
.modal-description {
|
||||
@include t.use-typography("body-large");
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
@extend %modal-action-btns;
|
||||
}
|
||||
|
||||
.accept-btn {
|
||||
@extend %modal-accept-btn;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.footer-text {
|
||||
@include t.use-typography("body-medium");
|
||||
|
||||
color: var(--color-foreground-secondary);
|
||||
margin-block-start: var(--sp-xxxl);
|
||||
}
|
||||
|
||||
.link {
|
||||
color: var(--color-accent-primary);
|
||||
}
|
||||
@ -11,6 +11,7 @@
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.nitrate :as dnt]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.forms :as fm]
|
||||
[app.main.ui.ds.buttons.button :refer [button*]]
|
||||
[app.main.ui.ds.foundations.assets.icon :as i :refer [icon*]]
|
||||
@ -37,7 +38,12 @@
|
||||
(mf/use-fn
|
||||
(mf/deps form)
|
||||
(fn []
|
||||
(dnt/go-to-buy-nitrate-license (-> @form :clean-data :subscription name))))]
|
||||
(dnt/go-to-buy-nitrate-license (-> @form :clean-data :subscription name))))
|
||||
|
||||
on-activate-click
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(st/emit! (modal/show {:type :nitrate-code-activation}))))]
|
||||
|
||||
[:div {:class (stl/css :modal-overlay)}
|
||||
[:div {:class (stl/css :modal-dialog :subscription-success)}
|
||||
@ -80,6 +86,10 @@
|
||||
[:div {:class (stl/css :modal-text-small :modal-info)}
|
||||
"Cancel anytime before your next billing cycle."]]]
|
||||
|
||||
[:p {:class (stl/css :modal-text-medium)}
|
||||
"Have an activation code? " [:a {:class (stl/css :link)
|
||||
:on-click on-activate-click}
|
||||
"Enter activation code"]]
|
||||
|
||||
[:p {:class (stl/css :modal-text-medium)}
|
||||
[:a {:class (stl/css :link) :href dnt/go-to-subscription-url}
|
||||
@ -92,6 +102,13 @@
|
||||
"Contact us to try Nitrate for 14 days:")]
|
||||
[:p {:class (stl/css :modal-text-large)}
|
||||
[:a {:class (stl/css :link) :href "mailto:sales@penpot.app"}
|
||||
"sales@penpot.app"]]])]]]]))
|
||||
"sales@penpot.app"]]
|
||||
[:div {:class (stl/css :activation-code)}
|
||||
[:p {:class (stl/css :modal-text-large)}
|
||||
"Have an activation code?"]
|
||||
[:p {:class (stl/css :modal-text-large)}
|
||||
[:a {:class (stl/css :link)
|
||||
:on-click on-activate-click}
|
||||
"Enter activation code"]]]])]]]]))
|
||||
|
||||
|
||||
|
||||
@ -107,6 +107,10 @@
|
||||
color: var(--color-foreground-primary);
|
||||
}
|
||||
|
||||
.activation-code {
|
||||
margin-block-start: var(--sp-xxxl);
|
||||
}
|
||||
|
||||
.link {
|
||||
color: var(--color-accent-primary);
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
[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.nitrate.nitrate-activation-success-modal]
|
||||
[app.main.ui.notifications.badge :refer [badge-notification]]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr c]]
|
||||
@ -37,6 +38,7 @@
|
||||
cta-link-trial
|
||||
cta-text-with-icon
|
||||
cta-link-with-icon
|
||||
show-activation-by-code
|
||||
editors
|
||||
recommended
|
||||
show-button-cta]}]
|
||||
@ -66,6 +68,14 @@
|
||||
[:ul {:class (stl/css :benefits-list)}
|
||||
(for [benefit benefits]
|
||||
[:li {:key (dm/str benefit) :class (stl/css :benefit)} "- " benefit])]
|
||||
(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])
|
||||
(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
|
||||
@ -75,14 +85,10 @@
|
||||
[: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])])
|
||||
(when show-activation-by-code
|
||||
[:button {:class (stl/css :cta-button :activate-by-code)
|
||||
:on-click #(st/emit! (modal/show {:type :nitrate-code-activation}))}
|
||||
"Enter activation code"])])
|
||||
|
||||
(defn- make-management-form-schema [min-editors]
|
||||
[:map {:title "SeatsForm"}
|
||||
@ -360,36 +366,6 @@
|
||||
: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]}]
|
||||
@ -498,7 +474,7 @@
|
||||
^boolean show-subscription-success-modal?
|
||||
(st/emit!
|
||||
(if (= params-subscription "subscribed-to-penpot-nitrate")
|
||||
(modal/show :nitrate-success {})
|
||||
(modal/show :nitrate-activation-success {})
|
||||
(modal/show :subscription-success
|
||||
{:subscription-name (if (= params-subscription "subscribed-to-penpot-unlimited")
|
||||
(if (= success-modal-is-trial? "true")
|
||||
@ -658,6 +634,7 @@
|
||||
: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-activation-by-code true
|
||||
:show-button-cta (not nitrate-license)}])]]]))
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user