mirror of
https://github.com/penpot/penpot.git
synced 2026-05-10 02:28:16 +00:00
* 🐛 Fix U and E icon displayed in project lis * 🐛 Fix U and E icon displayed in project list
249 lines
10 KiB
Clojure
249 lines
10 KiB
Clojure
;; Copyright (c) KALEIDOS INC
|
|
|
|
(ns app.main.ui.dashboard.subscription
|
|
(:require-macros [app.main.style :as stl])
|
|
(:require
|
|
[app.common.data.macros :as dm]
|
|
[app.config :as cf]
|
|
[app.main.data.event :as ev]
|
|
[app.main.router :as rt]
|
|
[app.main.store :as st]
|
|
[app.main.ui.components.dropdown-menu :refer [dropdown-menu-item*]]
|
|
[app.main.ui.ds.buttons.button :refer [button*]]
|
|
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
|
|
[app.main.ui.ds.product.cta :refer [cta*]]
|
|
[app.util.dom :as dom]
|
|
[app.util.i18n :as i18n :refer [tr]]
|
|
[app.util.keyboard :as kbd]
|
|
[lambdaisland.uri :as u]
|
|
[potok.v2.core :as ptk]
|
|
[rumext.v2 :as mf]))
|
|
|
|
(defn get-subscription-type
|
|
[{:keys [type status] :as subscription}]
|
|
(if (and subscription (:type subscription) (not (contains? #{"unpaid" "canceled"} status)))
|
|
type
|
|
"professional"))
|
|
|
|
(mf/defc cta-power-up*
|
|
[{:keys [top-title top-description bottom-description bottom-button bottom-button-href has-dropdown is-highlighted]}]
|
|
(let [show-data* (mf/use-state false)
|
|
show-data (deref show-data*)
|
|
handle-click
|
|
(mf/use-fn
|
|
(fn [event]
|
|
(dom/stop-propagation event)
|
|
(swap! show-data* not)))
|
|
handle-navigation
|
|
(mf/use-fn
|
|
(fn [event]
|
|
(dom/stop-propagation event)
|
|
(st/emit! (rt/nav-raw :href bottom-button-href))))]
|
|
|
|
[:div {:class (stl/css-case :cta-power-up true
|
|
:highlighted is-highlighted)
|
|
:on-click handle-click}
|
|
[:button {:class (stl/css-case :cta-top-section true
|
|
:cta-without-dropdown (not has-dropdown))}
|
|
[:div {:class (stl/css :content)}
|
|
[:span {:class (stl/css :cta-title)} top-title]
|
|
[:span {:class (stl/css :cta-text) :data-testid "subscription-name"} top-description]]
|
|
(when has-dropdown
|
|
[:> icon* {:icon-id (if (and has-dropdown show-data) i/arrow-up i/arrow-down)
|
|
:class (stl/css :icon-dropdown)
|
|
:size "s"}])]
|
|
|
|
(when (and has-dropdown show-data)
|
|
[:div {:class (stl/css :cta-bottom-section)}
|
|
[:> i18n/tr-html* {:content bottom-description
|
|
:class (stl/css :content)
|
|
:tag-name "span"}]])
|
|
|
|
(when (and bottom-description bottom-button)
|
|
[:div {:class (stl/css :cta-bottom-section)}
|
|
[:span {:class (stl/css :content)}
|
|
bottom-description]
|
|
[:> button* {:variant "primary"
|
|
:type "button"
|
|
:class (stl/css :cta-bottom-button)
|
|
:on-click handle-navigation} bottom-button]])]))
|
|
|
|
(mf/defc subscription-sidebar*
|
|
[{:keys [profile]}]
|
|
(let [subscription (:subscription (:props profile))
|
|
subscription-type (get-subscription-type subscription)
|
|
subscription-is-trial (= (:status subscription) "trialing")
|
|
subscription-href (dm/str (u/join cf/public-uri "#/settings/subscriptions"))]
|
|
|
|
(case subscription-type
|
|
"professional"
|
|
[:> cta-power-up*
|
|
{:top-title (tr "subscription.dashboard.power-up.your-subscription")
|
|
:top-description (tr "subscription.dashboard.power-up.professional.top-title")
|
|
:bottom-description (tr "subscription.dashboard.power-up.professional.bottom-description")
|
|
:bottom-button (tr "subscription.dashboard.power-up.professional.bottom-button")
|
|
:bottom-button-href subscription-href
|
|
:has-dropdown false
|
|
:is-highlighted true}]
|
|
|
|
"unlimited"
|
|
(if subscription-is-trial
|
|
[:> cta-power-up*
|
|
{:top-title (tr "subscription.dashboard.power-up.your-subscription")
|
|
:top-description (tr "subscription.dashboard.power-up.trial.top-title")
|
|
:bottom-description (tr "subscription.dashboard.power-up.trial.bottom-description" subscription-href)
|
|
:has-dropdown true
|
|
:is-highlighted false}]
|
|
|
|
[:> cta-power-up*
|
|
{:top-title (tr "subscription.dashboard.power-up.your-subscription")
|
|
:top-description (tr "subscription.dashboard.power-up.unlimited-plan")
|
|
:bottom-description (tr "subscription.dashboard.power-up.unlimited.bottom-text" subscription-href)
|
|
:has-dropdown true
|
|
:is-highlighted false}])
|
|
|
|
"enterprise"
|
|
(if subscription-is-trial
|
|
[:> cta-power-up*
|
|
{:top-title (tr "subscription.dashboard.power-up.your-subscription")
|
|
:top-description (tr "subscription.dashboard.power-up.enterprise-trial.top-title")
|
|
:has-dropdown false
|
|
:is-highlighted false}]
|
|
[:> cta-power-up*
|
|
{:top-title (tr "subscription.dashboard.power-up.your-subscription")
|
|
:top-description (tr "subscription.dashboard.power-up.enterprise-plan")
|
|
:has-dropdown false
|
|
:is-highlighted false}]))))
|
|
|
|
(mf/defc team*
|
|
[{:keys [is-owner team]}]
|
|
(let [subscription (:subscription team)
|
|
subscription-type (get-subscription-type subscription)
|
|
subscription-is-trial (= "trialing" (:status subscription))
|
|
|
|
go-to-manage-subscription
|
|
(mf/use-fn
|
|
(fn []
|
|
(st/emit! (ptk/event ::ev/event {::ev/name "open-subscription-management"
|
|
::ev/origin "dashboard"
|
|
:section "team-settings"}))
|
|
(let [href (-> (rt/get-current-href)
|
|
(rt/encode-url))
|
|
href (str "payments/subscriptions/show?returnUrl=" href)]
|
|
(st/emit! (rt/nav-raw :href href)))))]
|
|
|
|
[:div {:class (stl/css :team)}
|
|
[:div {:class (stl/css :team-label)}
|
|
(tr "subscription.dashboard.team-plan")]
|
|
[:span {:class (stl/css :team-text)}
|
|
(case subscription-type
|
|
"professional" (tr "subscription.settings.professional")
|
|
"unlimited" (if subscription-is-trial
|
|
(tr "subscription.settings.unlimited-trial")
|
|
(tr "subscription.settings.unlimited"))
|
|
|
|
"enterprise" (tr "subscription.settings.enterprise"))]
|
|
(when (and is-owner (not= subscription-type "professional"))
|
|
[:button {:class (stl/css :manage-subscription-link)
|
|
:on-click go-to-manage-subscription
|
|
:data-testid "manage-subscription-link"}
|
|
(tr "subscription.settings.manage-your-subscription")])]))
|
|
|
|
(mf/defc menu-team-icon*
|
|
[{:keys [subscription-type]}]
|
|
[:span {:class (stl/css :subscription-icon-wrapper)}
|
|
[:> icon* {:icon-id (case subscription-type
|
|
"unlimited" i/character-u
|
|
"enterprise" i/character-e)
|
|
:class (stl/css :subscription-icon)
|
|
:size "s"
|
|
:title (if (= subscription-type "unlimited")
|
|
(tr "subscription.dashboard.power-up.unlimited-plan")
|
|
(tr "subscription.dashboard.power-up.enterprise-plan"))
|
|
:data-testid "subscription-icon"}]])
|
|
|
|
(mf/defc main-menu-power-up*
|
|
[{:keys [close-sub-menu]}]
|
|
(let [go-to-subscription (mf/use-fn #(st/emit! (rt/nav :settings-subscription)))]
|
|
[:> dropdown-menu-item* {:class (stl/css-case :menu-item true)
|
|
:on-click go-to-subscription
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(go-to-subscription)))
|
|
:on-pointer-enter close-sub-menu
|
|
:id "file-menu-power-up"}
|
|
[:span {:class (stl/css :item-name)} (tr "subscription.workspace.header.menu.option.power-up")]]))
|
|
|
|
(mf/defc members-cta*
|
|
[]
|
|
[:> cta* {:class (stl/css :members-cta)
|
|
:title (tr "subscription.dashboard.unlimited-members-extra-editors-cta-title")}
|
|
[:> i18n/tr-html*
|
|
{:tag-name "span"
|
|
:class (stl/css :cta-message)
|
|
:content (tr "subscription.dashboard.unlimited-members-extra-editors-cta-text")}]])
|
|
|
|
(mf/defc dashboard-cta*
|
|
[{:keys [profile]}]
|
|
(let [subscription (-> profile :props :subscription)
|
|
subscription-type (get-subscription-type subscription)
|
|
go-to-subscription (dm/str (u/join cf/public-uri "#/settings/subscriptions"))
|
|
seats (:quantity subscription)
|
|
editors (count (:editors subscription))
|
|
cta-title
|
|
(cond
|
|
(= "professional" subscription-type)
|
|
(tr "subscription.dashboard.professional-dashboard-cta-title" editors)
|
|
|
|
(= "unlimited" subscription-type)
|
|
(tr "subscription.dashboard.unlimited-dashboard-cta-title" seats editors))
|
|
|
|
cta-message
|
|
(cond
|
|
(= "professional" subscription-type)
|
|
(tr "subscription.dashboard.professional-dashboard-cta-upgrade-owner" go-to-subscription)
|
|
|
|
(= "unlimited" subscription-type)
|
|
(tr "subscription.dashboard.unlimited-dashboard-cta-upgrade-owner" go-to-subscription))]
|
|
|
|
[:> cta* {:class (stl/css :dashboard-cta) :title cta-title}
|
|
[:> i18n/tr-html*
|
|
{:tag-name "span"
|
|
:class (stl/css :cta-message)
|
|
:content cta-message}]]))
|
|
|
|
(defn show-subscription-dashboard-banner?
|
|
[profile]
|
|
(let [subscription (-> profile :props :subscription)
|
|
subscription-type (get-subscription-type subscription)
|
|
seats (:quantity subscription)
|
|
editors (count (:editors subscription))]
|
|
|
|
(or
|
|
(and (= subscription-type "professional")
|
|
(> editors 8))
|
|
(and
|
|
(= subscription-type "unlimited")
|
|
(or
|
|
;; common: seats < 25 and diff >= 4
|
|
(and (< seats 25)
|
|
(>= (- editors seats) 4))
|
|
;; special: reached 25+ editors, seats < 25 and there is overuse
|
|
(and (< seats 25)
|
|
(>= editors 25)
|
|
(> editors seats)))))))
|
|
|
|
(defn show-subscription-members-banner?
|
|
[team profile]
|
|
(let [subscription (:subscription team)
|
|
subscription-type (get-subscription-type subscription)
|
|
seats (:seats subscription)
|
|
editors (count (-> profile :props :subscription :editors))
|
|
is-owner (-> team :permissions :is-owner)]
|
|
(and
|
|
is-owner
|
|
(= subscription-type "unlimited")
|
|
;; common: seats < 25 and diff >= 4 between editors/seats and there is overuse
|
|
(and (< seats 25)
|
|
(>= (- editors seats) 4)))))
|