mirror of
https://github.com/lukevella/rallly.git
synced 2025-04-28 17:56:37 +02:00
♻️ Use user tier to determine subscription status (#1686)
This commit is contained in:
parent
5c61057a84
commit
cd38e9105d
5 changed files with 9 additions and 71 deletions
|
@ -17,7 +17,8 @@ import { Trans } from "react-i18next";
|
||||||
|
|
||||||
import { PayWallDialog } from "@/components/pay-wall-dialog";
|
import { PayWallDialog } from "@/components/pay-wall-dialog";
|
||||||
import { ProBadge } from "@/components/pro-badge";
|
import { ProBadge } from "@/components/pro-badge";
|
||||||
import { usePlan } from "@/contexts/plan";
|
|
||||||
|
import { useUser } from "../user-provider";
|
||||||
|
|
||||||
export type PollSettingsFormData = {
|
export type PollSettingsFormData = {
|
||||||
requireParticipantEmail: boolean;
|
requireParticipantEmail: boolean;
|
||||||
|
@ -66,9 +67,9 @@ export const PollSettingsForm = ({ children }: React.PropsWithChildren) => {
|
||||||
const form = useFormContext<PollSettingsFormData>();
|
const form = useFormContext<PollSettingsFormData>();
|
||||||
const posthog = usePostHog();
|
const posthog = usePostHog();
|
||||||
const paywallDialog = useDialog();
|
const paywallDialog = useDialog();
|
||||||
const plan = usePlan();
|
const { user } = useUser();
|
||||||
|
|
||||||
const isFree = plan === "free";
|
const isFree = user.tier !== "pro";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -32,10 +32,10 @@ import { PayWallDialog } from "@/components/pay-wall-dialog";
|
||||||
import { FinalizePollDialog } from "@/components/poll/manage-poll/finalize-poll-dialog";
|
import { FinalizePollDialog } from "@/components/poll/manage-poll/finalize-poll-dialog";
|
||||||
import { ProBadge } from "@/components/pro-badge";
|
import { ProBadge } from "@/components/pro-badge";
|
||||||
import { Trans } from "@/components/trans";
|
import { Trans } from "@/components/trans";
|
||||||
import { usePlan } from "@/contexts/plan";
|
|
||||||
import { usePoll } from "@/contexts/poll";
|
import { usePoll } from "@/contexts/poll";
|
||||||
import { trpc } from "@/trpc/client";
|
import { trpc } from "@/trpc/client";
|
||||||
|
|
||||||
|
import { useUser } from "../user-provider";
|
||||||
import { DeletePollDialog } from "./manage-poll/delete-poll-dialog";
|
import { DeletePollDialog } from "./manage-poll/delete-poll-dialog";
|
||||||
import { useCsvExporter } from "./manage-poll/use-csv-exporter";
|
import { useCsvExporter } from "./manage-poll/use-csv-exporter";
|
||||||
|
|
||||||
|
@ -125,6 +125,7 @@ const ManagePoll: React.FunctionComponent<{
|
||||||
}> = ({ disabled }) => {
|
}> = ({ disabled }) => {
|
||||||
const poll = usePoll();
|
const poll = usePoll();
|
||||||
const queryClient = trpc.useUtils();
|
const queryClient = trpc.useUtils();
|
||||||
|
const { user } = useUser();
|
||||||
const reopen = trpc.polls.reopen.useMutation({
|
const reopen = trpc.polls.reopen.useMutation({
|
||||||
onMutate: () => {
|
onMutate: () => {
|
||||||
queryClient.polls.get.setData({ urlId: poll.id }, (oldPoll) => {
|
queryClient.polls.get.setData({ urlId: poll.id }, (oldPoll) => {
|
||||||
|
@ -143,7 +144,6 @@ const ManagePoll: React.FunctionComponent<{
|
||||||
const duplicateDialog = useDialog();
|
const duplicateDialog = useDialog();
|
||||||
const finalizeDialog = useDialog();
|
const finalizeDialog = useDialog();
|
||||||
const paywallDialog = useDialog();
|
const paywallDialog = useDialog();
|
||||||
const plan = usePlan();
|
|
||||||
const posthog = usePostHog();
|
const posthog = usePostHog();
|
||||||
const { exportToCsv } = useCsvExporter();
|
const { exportToCsv } = useCsvExporter();
|
||||||
|
|
||||||
|
@ -203,7 +203,7 @@ const ManagePoll: React.FunctionComponent<{
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
disabled={!!poll.event}
|
disabled={!!poll.event}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (plan === "free") {
|
if (user.tier !== "pro") {
|
||||||
paywallDialog.trigger();
|
paywallDialog.trigger();
|
||||||
posthog?.capture("trigger paywall", {
|
posthog?.capture("trigger paywall", {
|
||||||
poll_id: poll.id,
|
poll_id: poll.id,
|
||||||
|
@ -233,7 +233,7 @@ const ManagePoll: React.FunctionComponent<{
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (plan === "free") {
|
if (user.tier !== "pro") {
|
||||||
paywallDialog.trigger();
|
paywallDialog.trigger();
|
||||||
posthog?.capture("trigger paywall", {
|
posthog?.capture("trigger paywall", {
|
||||||
poll_id: poll.id,
|
poll_id: poll.id,
|
||||||
|
|
|
@ -31,14 +31,12 @@ import { OptimizedAvatarImage } from "@/components/optimized-avatar-image";
|
||||||
import { RegisterLink } from "@/components/register-link";
|
import { RegisterLink } from "@/components/register-link";
|
||||||
import { Trans } from "@/components/trans";
|
import { Trans } from "@/components/trans";
|
||||||
import { IfCloudHosted, IfSelfHosted } from "@/contexts/environment";
|
import { IfCloudHosted, IfSelfHosted } from "@/contexts/environment";
|
||||||
import { Plan, usePlan } from "@/contexts/plan";
|
|
||||||
import { isFeedbackEnabled } from "@/utils/constants";
|
import { isFeedbackEnabled } from "@/utils/constants";
|
||||||
|
|
||||||
import { IfAuthenticated, IfGuest, useUser } from "./user-provider";
|
import { IfAuthenticated, IfGuest, useUser } from "./user-provider";
|
||||||
|
|
||||||
export const UserDropdown = ({ className }: { className?: string }) => {
|
export const UserDropdown = ({ className }: { className?: string }) => {
|
||||||
const { user, logout } = useUser();
|
const { user, logout } = useUser();
|
||||||
usePlan(); // prefetch plan data
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu modal={false}>
|
<DropdownMenu modal={false}>
|
||||||
<DropdownMenuTrigger
|
<DropdownMenuTrigger
|
||||||
|
@ -68,9 +66,6 @@ export const UserDropdown = ({ className }: { className?: string }) => {
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-4">
|
|
||||||
<Plan />
|
|
||||||
</div>
|
|
||||||
</DropdownMenuLabel>
|
</DropdownMenuLabel>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItem asChild={true}>
|
<DropdownMenuItem asChild={true}>
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { useRouter } from "next/navigation";
|
||||||
import { signIn, signOut } from "next-auth/react";
|
import { signIn, signOut } from "next-auth/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { useSubscription } from "@/contexts/plan";
|
|
||||||
import { useTranslation } from "@/i18n/client";
|
import { useTranslation } from "@/i18n/client";
|
||||||
import { isOwner } from "@/utils/permissions";
|
import { isOwner } from "@/utils/permissions";
|
||||||
|
|
||||||
|
@ -77,13 +76,12 @@ export const UserProvider = ({
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
user?: RegisteredUser | GuestUser;
|
user?: RegisteredUser | GuestUser;
|
||||||
}) => {
|
}) => {
|
||||||
const subscription = useSubscription();
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const posthog = usePostHog();
|
const posthog = usePostHog();
|
||||||
|
|
||||||
const isGuest = !user || user.tier === "guest";
|
const isGuest = !user || user.tier === "guest";
|
||||||
const tier = isGuest ? "guest" : subscription?.active ? "pro" : "hobby";
|
const tier = isGuest ? "guest" : user.tier;
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (user) {
|
if (user) {
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
"use client";
|
|
||||||
import { Badge } from "@rallly/ui/badge";
|
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
import { ProBadge } from "@/components/pro-badge";
|
|
||||||
import { Trans } from "@/components/trans";
|
|
||||||
import { trpc } from "@/trpc/client";
|
|
||||||
import { isSelfHosted } from "@/utils/constants";
|
|
||||||
|
|
||||||
export const useSubscription = () => {
|
|
||||||
const { data } = trpc.user.subscription.useQuery(undefined, {
|
|
||||||
enabled: !isSelfHosted,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isSelfHosted) {
|
|
||||||
return {
|
|
||||||
active: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const usePlan = () => {
|
|
||||||
const data = useSubscription();
|
|
||||||
|
|
||||||
const isPaid = data?.active === true;
|
|
||||||
|
|
||||||
return isPaid ? "paid" : "free";
|
|
||||||
};
|
|
||||||
|
|
||||||
export const IfSubscribed = ({ children }: React.PropsWithChildren) => {
|
|
||||||
const plan = usePlan();
|
|
||||||
|
|
||||||
return plan === "paid" ? <>{children}</> : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const IfFreeUser = ({ children }: React.PropsWithChildren) => {
|
|
||||||
const subscription = useSubscription();
|
|
||||||
|
|
||||||
return subscription?.active === false ? <>{children}</> : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Plan = () => {
|
|
||||||
const plan = usePlan();
|
|
||||||
|
|
||||||
if (plan === "paid") {
|
|
||||||
return <ProBadge />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Badge>
|
|
||||||
<Trans i18nKey="planFree" defaults="Free" />
|
|
||||||
</Badge>
|
|
||||||
);
|
|
||||||
};
|
|
Loading…
Add table
Reference in a new issue