fix: All roles need insight into consumption (#4242)

Co-authored-by: Piyush Gupta <piyushguptaa2z123@gmail.com>
This commit is contained in:
Dhruwang Jariwala
2024-11-12 11:42:38 +05:30
committed by GitHub
parent ade5c3d80e
commit da6f54eede
6 changed files with 51 additions and 51 deletions
@@ -59,15 +59,13 @@ export const EnvironmentLayout = async ({ environmentId, session, children }: En
const currentUserMembership = await getMembershipByUserIdOrganizationId(session?.user.id, organization.id);
const membershipRole = currentUserMembership?.role;
const { isOwner, isManager } = getAccessFlags(membershipRole);
const isOwnerOrManager = isOwner || isManager;
const { isMember } = getAccessFlags(membershipRole);
const { features, lastChecked, isPendingDowngrade, active } = await getEnterpriseLicense();
const productPermission = await getProductPermissionByUserId(session.user.id, environment.productId);
if (!isOwnerOrManager && !productPermission) {
if (isMember && !productPermission) {
throw new Error(t("common.product_permission_not_found"));
}
@@ -222,7 +222,7 @@ export const MainNavigation = ({
{
label: t("common.billing"),
href: `/environments/${environment.id}/settings/billing`,
hidden: !isFormbricksCloud || isPricingDisabled,
hidden: !isFormbricksCloud,
icon: CreditCardIcon,
},
{
@@ -40,7 +40,7 @@ export const OrganizationSettingsNavbar = ({
id: "billing",
label: t("common.billing"),
href: `/environments/${environmentId}/settings/billing`,
hidden: !isFormbricksCloud || isPricingDisabled || loading,
hidden: !isFormbricksCloud || loading,
current: pathname?.includes("/billing"),
},
{
@@ -35,6 +35,7 @@ interface PricingTableProps {
SCALE: string;
ENTERPRISE: string;
};
hasBillingRights: boolean;
}
export const PricingTable = ({
@@ -44,6 +45,7 @@ export const PricingTable = ({
productFeatureKeys,
responseCount,
stripePriceLookupKeys,
hasBillingRights,
}: PricingTableProps) => {
const t = useTranslations();
const [planPeriod, setPlanPeriod] = useState<TOrganizationBillingPeriod>(
@@ -220,48 +222,50 @@ export const PricingTable = ({
</div>
</div>
<div className="mx-auto mb-12">
<div className="flex gap-x-2">
<div className="mb-4 flex w-fit cursor-pointer overflow-hidden rounded-lg border border-slate-200 p-1 lg:mb-0">
<div
className={`flex-1 rounded-md px-4 py-0.5 text-center ${
planPeriod === "monthly" ? "bg-slate-200 font-semibold" : "bg-transparent"
}`}
onClick={() => handleMonthlyToggle("monthly")}>
{t("environments.settings.billing.monthly")}
{hasBillingRights && (
<div className="mx-auto mb-12">
<div className="gap-x-2">
<div className="mb-4 flex w-fit cursor-pointer overflow-hidden rounded-lg border border-slate-200 p-1 lg:mb-0">
<div
className={`flex-1 rounded-md px-4 py-0.5 text-center ${
planPeriod === "monthly" ? "bg-slate-200 font-semibold" : "bg-transparent"
}`}
onClick={() => handleMonthlyToggle("monthly")}>
{t("environments.settings.billing.monthly")}
</div>
<div
className={`flex-1 items-center whitespace-nowrap rounded-md py-0.5 pl-4 pr-2 text-center ${
planPeriod === "yearly" ? "bg-slate-200 font-semibold" : "bg-transparent"
}`}
onClick={() => handleMonthlyToggle("yearly")}>
{t("environments.settings.billing.annually")}
<span className="ml-2 inline-flex items-center rounded-full border border-green-200 bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800">
{t("environments.settings.billing.get_2_months_free")} 🔥
</span>
</div>
</div>
<div
className={`flex-1 items-center whitespace-nowrap rounded-md py-0.5 pl-4 pr-2 text-center ${
planPeriod === "yearly" ? "bg-slate-200 font-semibold" : "bg-transparent"
}`}
onClick={() => handleMonthlyToggle("yearly")}>
{t("environments.settings.billing.annually")}
<span className="ml-2 inline-flex items-center rounded-full border border-green-200 bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800">
{t("environments.settings.billing.get_2_months_free")} 🔥
</span>
<div className="relative mx-auto grid max-w-md grid-cols-1 gap-y-8 lg:mx-0 lg:-mb-14 lg:max-w-none lg:grid-cols-4">
<div
className="hidden lg:absolute lg:inset-x-px lg:bottom-0 lg:top-4 lg:block lg:rounded-xl lg:rounded-t-2xl lg:border lg:border-slate-200 lg:bg-slate-100 lg:pb-8 lg:ring-1 lg:ring-white/10"
aria-hidden="true"
/>
{CLOUD_PRICING_DATA.plans.map((plan) => (
<PricingCard
planPeriod={planPeriod}
key={plan.id}
plan={plan}
onUpgrade={async () => {
await onUpgrade(plan.id);
}}
organization={organization}
productFeatureKeys={productFeatureKeys}
onManageSubscription={openCustomerPortal}
/>
))}
</div>
</div>
</div>
<div className="relative mx-auto grid max-w-md grid-cols-1 gap-y-8 lg:mx-0 lg:-mb-14 lg:max-w-none lg:grid-cols-4">
<div
className="hidden lg:absolute lg:inset-x-px lg:bottom-0 lg:top-4 lg:block lg:rounded-xl lg:rounded-t-2xl lg:border lg:border-slate-200 lg:bg-slate-100 lg:pb-8 lg:ring-1 lg:ring-white/10"
aria-hidden="true"
/>
{CLOUD_PRICING_DATA.plans.map((plan) => (
<PricingCard
planPeriod={planPeriod}
key={plan.id}
plan={plan}
onUpgrade={async () => {
await onUpgrade(plan.id);
}}
organization={organization}
productFeatureKeys={productFeatureKeys}
onManageSubscription={openCustomerPortal}
/>
))}
</div>
</div>
)}
</div>
</main>
);
@@ -4,10 +4,7 @@ import { getTranslations } from "next-intl/server";
import { notFound } from "next/navigation";
import { authOptions } from "@formbricks/lib/authOptions";
import { IS_FORMBRICKS_CLOUD } from "@formbricks/lib/constants";
import { getMembershipByUserIdOrganizationId } from "@formbricks/lib/membership/service";
import { getAccessFlags } from "@formbricks/lib/membership/utils";
import { getOrganizationByEnvironmentId } from "@formbricks/lib/organization/service";
import { ErrorComponent } from "@formbricks/ui/components/ErrorComponent";
export const metadata: Metadata = {
title: "Billing",
@@ -29,10 +26,7 @@ const BillingLayout = async ({ children, params }) => {
throw new Error(t("common.organization_not_found"));
}
const currentUserMembership = await getMembershipByUserIdOrganizationId(session?.user.id, organization.id);
const { isMember } = getAccessFlags(currentUserMembership?.role);
return <>{!isMember ? <>{children}</> : <ErrorComponent />}</>;
return <>{children}</>;
};
export default BillingLayout;
@@ -6,6 +6,7 @@ import { authOptions } from "@formbricks/lib/authOptions";
import { IS_FORMBRICKS_CLOUD } from "@formbricks/lib/constants";
import { PRODUCT_FEATURE_KEYS, STRIPE_PRICE_LOOKUP_KEYS } from "@formbricks/lib/constants";
import { getMembershipByUserIdOrganizationId } from "@formbricks/lib/membership/service";
import { getAccessFlags } from "@formbricks/lib/membership/utils";
import {
getMonthlyActiveOrganizationPeopleCount,
getMonthlyOrganizationResponseCount,
@@ -33,6 +34,8 @@ const Page = async ({ params }) => {
]);
const currentUserMembership = await getMembershipByUserIdOrganizationId(session?.user.id, organization.id);
const { isMember } = getAccessFlags(currentUserMembership?.role);
const hasBillingRights = !isMember;
const canDoRoleManagement = await getRoleManagementPermission(organization);
@@ -55,6 +58,7 @@ const Page = async ({ params }) => {
responseCount={responseCount}
stripePriceLookupKeys={STRIPE_PRICE_LOOKUP_KEYS}
productFeatureKeys={PRODUCT_FEATURE_KEYS}
hasBillingRights={hasBillingRights}
/>
</PageContentWrapper>
);