()
| 113 | } |
| 114 | |
| 115 | function BannerSubscription() { |
| 116 | const { t } = useTranslation(); |
| 117 | const { currentPlan, daysBeforeExpire, expireAt, isExpired, isTrialing } = |
| 118 | useSubscriptionState(); |
| 119 | |
| 120 | const content = useMemo(() => { |
| 121 | if (currentPlan === PlanType.FREE) return ""; |
| 122 | |
| 123 | const plan = t(planTitleKey(currentPlan)); |
| 124 | if (isTrialing) { |
| 125 | return t("banner.trial-expires", { |
| 126 | days: daysBeforeExpire, |
| 127 | expireAt, |
| 128 | plan, |
| 129 | }); |
| 130 | } |
| 131 | if (isExpired) { |
| 132 | return t("banner.license-expired", { expireAt, plan }); |
| 133 | } |
| 134 | if (daysBeforeExpire <= LICENSE_EXPIRATION_THRESHOLD) { |
| 135 | return t("banner.license-expires", { |
| 136 | days: daysBeforeExpire, |
| 137 | expireAt, |
| 138 | plan, |
| 139 | }); |
| 140 | } |
| 141 | return ""; |
| 142 | }, [currentPlan, daysBeforeExpire, expireAt, isExpired, isTrialing, t]); |
| 143 | |
| 144 | if (!content) return null; |
| 145 | |
| 146 | return ( |
| 147 | <div className="bg-info"> |
| 148 | <div className="mx-auto px-3 py-1"> |
| 149 | <div className="flex flex-wrap items-center justify-center gap-x-2"> |
| 150 | <p className="ml-3 truncate text-base font-medium text-white"> |
| 151 | {content} |
| 152 | </p> |
| 153 | <RouterLink |
| 154 | to={{ name: SETTING_ROUTE_WORKSPACE_SUBSCRIPTION }} |
| 155 | className="flex cursor-pointer items-center justify-center py-1 text-base font-medium text-white underline hover:opacity-80" |
| 156 | > |
| 157 | {t( |
| 158 | isTrialing |
| 159 | ? "subscription.purchase.subscribe" |
| 160 | : "subscription.purchase.update" |
| 161 | )} |
| 162 | <ShoppingCart className="ml-1 size-5 text-white" /> |
| 163 | </RouterLink> |
| 164 | </div> |
| 165 | </div> |
| 166 | </div> |
| 167 | ); |
| 168 | } |
| 169 | |
| 170 | function BannerAnnouncement() { |
| 171 | const workspaceProfile = useWorkspaceProfile(); |
nothing calls this directly
no test coverage detected