Implement UpgradeTip in App install flow (#8968)
parent
b36043b637
commit
bfa30aa504
|
@ -36,6 +36,7 @@ const Component = ({
|
|||
tos,
|
||||
privacy,
|
||||
isProOnly,
|
||||
teamsPlanRequired,
|
||||
descriptionItems,
|
||||
isTemplate,
|
||||
dependencies,
|
||||
|
@ -152,6 +153,7 @@ const Component = ({
|
|||
type={type}
|
||||
isProOnly={isProOnly}
|
||||
disableInstall={disableInstall}
|
||||
teamsPlanRequired={teamsPlanRequired}
|
||||
render={({ useDefaultComponent, ...props }) => {
|
||||
if (useDefaultComponent) {
|
||||
props = {
|
||||
|
@ -192,6 +194,7 @@ const Component = ({
|
|||
type={type}
|
||||
isProOnly={isProOnly}
|
||||
disableInstall={disableInstall}
|
||||
teamsPlanRequired={teamsPlanRequired}
|
||||
render={({ useDefaultComponent, ...props }) => {
|
||||
if (useDefaultComponent) {
|
||||
props = {
|
||||
|
@ -241,7 +244,9 @@ const Component = ({
|
|||
</div>
|
||||
<h4 className="text-emphasis mt-8 font-semibold ">{t("pricing")}</h4>
|
||||
<span className="text-default">
|
||||
{price === 0 ? (
|
||||
{teamsPlanRequired ? (
|
||||
t("teams_plan_required")
|
||||
) : price === 0 ? (
|
||||
t("free_to_use_apps")
|
||||
) : (
|
||||
<>
|
||||
|
@ -358,6 +363,7 @@ export default function App(props: {
|
|||
privacy?: string;
|
||||
licenseRequired: AppType["licenseRequired"];
|
||||
isProOnly: AppType["isProOnly"];
|
||||
teamsPlanRequired: AppType["teamsPlanRequired"];
|
||||
descriptionItems?: Array<string | { iframe: IframeHTMLAttributes<HTMLIFrameElement> }>;
|
||||
isTemplate?: boolean;
|
||||
disableInstall?: boolean;
|
||||
|
|
|
@ -72,6 +72,7 @@ function SingleAppPage(props: inferSSRProps<typeof getStaticProps>) {
|
|||
website={data.url}
|
||||
email={data.email}
|
||||
licenseRequired={data.licenseRequired}
|
||||
teamsPlanRequired={data.teamsPlanRequired}
|
||||
isProOnly={data.isProOnly}
|
||||
descriptionItems={source.data?.items as string[] | undefined}
|
||||
isTemplate={data.isTemplate}
|
||||
|
|
|
@ -47,6 +47,7 @@ export default function OmniInstallAppButton({
|
|||
<InstallAppButton
|
||||
type={app.type}
|
||||
isProOnly={app.isProOnly}
|
||||
teamsPlanRequired={app.teamsPlanRequired}
|
||||
wrapperClassName={classNames("[@media(max-width:260px)]:w-full", className)}
|
||||
render={({ useDefaultComponent, ...props }) => {
|
||||
if (useDefaultComponent) {
|
||||
|
|
|
@ -7,6 +7,7 @@ import classNames from "@calcom/lib/classNames";
|
|||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { CAL_URL } from "@calcom/lib/constants";
|
||||
import { deriveAppDictKeyFromType } from "@calcom/lib/deriveAppDictKeyFromType";
|
||||
import { useHasTeamPlan } from "@calcom/lib/hooks/useHasPaidPlan";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import type { RouterOutputs } from "@calcom/trpc/react";
|
||||
|
@ -49,14 +50,17 @@ export const InstallAppButtonWithoutPlanCheck = (
|
|||
export const InstallAppButton = (
|
||||
props: {
|
||||
isProOnly?: App["isProOnly"];
|
||||
teamsPlanRequired?: App["teamsPlanRequired"];
|
||||
type: App["type"];
|
||||
wrapperClassName?: string;
|
||||
disableInstall?: boolean;
|
||||
} & InstallAppButtonProps
|
||||
) => {
|
||||
const { isLoading, data: user } = trpc.viewer.me.useQuery();
|
||||
const { isLoading: isUserLoading, data: user } = trpc.viewer.me.useQuery();
|
||||
const router = useRouter();
|
||||
const proProtectionElementRef = useRef<HTMLDivElement | null>(null);
|
||||
const { isLoading: isTeamPlanStatusLoading, hasTeamPlan } = useHasTeamPlan();
|
||||
|
||||
useEffect(() => {
|
||||
const el = proProtectionElementRef.current;
|
||||
if (!el) {
|
||||
|
@ -72,12 +76,19 @@ export const InstallAppButton = (
|
|||
e.stopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (props.teamsPlanRequired && !hasTeamPlan) {
|
||||
// TODO: I think we should show the UpgradeTip in a Dialog here. This would solve the problem of no way to go back to the App page from the UpgradeTip page(except browser's back button)
|
||||
router.push(props.teamsPlanRequired.upgradeUrl);
|
||||
e.stopPropagation();
|
||||
return;
|
||||
}
|
||||
},
|
||||
true
|
||||
);
|
||||
}, [isLoading, user, router, props.isProOnly]);
|
||||
}, [isUserLoading, user, router, props.isProOnly, hasTeamPlan, props.teamsPlanRequired]);
|
||||
|
||||
if (isLoading) {
|
||||
if (isUserLoading || isTeamPlanStatusLoading) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
"publisher": "Cal.com",
|
||||
"email": "help@cal.com",
|
||||
"licenseRequired": true,
|
||||
"teamsPlanRequired": {
|
||||
"upgradeUrl": "/apps/routing-forms/forms"
|
||||
},
|
||||
"description": "It would allow a booker to connect with the right person or choose the right event, faster. It would work by taking inputs from the booker and using that data to route to the correct booker/event as configured by Cal user",
|
||||
"__createdUsingCli": true
|
||||
}
|
||||
|
|
|
@ -126,6 +126,9 @@ export interface App {
|
|||
/** only required for "usage-based" billing. % of commission for paid bookings */
|
||||
commission?: number;
|
||||
licenseRequired?: boolean;
|
||||
teamsPlanRequired?: {
|
||||
upgradeUrl: string;
|
||||
};
|
||||
isProOnly?: boolean;
|
||||
appData?: AppData;
|
||||
/**
|
||||
|
|
|
@ -97,6 +97,7 @@ export function AppCard({ app, credentials, searchText }: AppCardProps) {
|
|||
<InstallAppButton
|
||||
type={app.type}
|
||||
isProOnly={app.isProOnly}
|
||||
teamsPlanRequired={app.teamsPlanRequired}
|
||||
disableInstall={!!app.dependencies && !app.dependencyData?.some((data) => !data.installed)}
|
||||
wrapperClassName="[@media(max-width:260px)]:w-full"
|
||||
render={({ useDefaultComponent, ...props }) => {
|
||||
|
@ -127,6 +128,7 @@ export function AppCard({ app, credentials, searchText }: AppCardProps) {
|
|||
isProOnly={app.isProOnly}
|
||||
wrapperClassName="[@media(max-width:260px)]:w-full"
|
||||
disableInstall={!!app.dependencies && app.dependencyData?.some((data) => !data.installed)}
|
||||
teamsPlanRequired={app.teamsPlanRequired}
|
||||
render={({ useDefaultComponent, ...props }) => {
|
||||
if (useDefaultComponent) {
|
||||
props = {
|
||||
|
|
Loading…
Reference in New Issue