mirror of
https://github.com/StanGirard/quivr.git
synced 2024-12-25 04:12:44 +03:00
feat: manage plan (#1488)
# Description - add crown on premium user - link to manage plan in page `/user` ## ⚠️ Before merging Setup env variable: ```env NEXT_PUBLIC_STRIPE_MANAGE_PLAN_URL=<ignore-me-or-change-me> ``` ## Screenshots (if appropriate): <img width="290" alt="image" src="https://github.com/StanGirard/quivr/assets/67386567/a87b0f7e-b07c-4f4e-b9d2-515ac25ebf05"> <img width="318" alt="image" src="https://github.com/StanGirard/quivr/assets/67386567/6a4f4f72-8c75-45da-9468-cae1a8d28935">
This commit is contained in:
parent
41563767ad
commit
d311a53b6f
@ -18,3 +18,4 @@ NEXT_PUBLIC_CMS_URL=https://cms.quivr.app
|
||||
|
||||
NEXT_PUBLIC_STRIPE_PRICING_TABLE_ID=<ignore-me-or-change-me>
|
||||
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=<ignore-me-or-change-me>
|
||||
NEXT_PUBLIC_STRIPE_MANAGE_PLAN_URL=<ignore-me-or-change-me>
|
||||
|
29
frontend/app/user/components/StripePricingOrManageButton.tsx
Normal file
29
frontend/app/user/components/StripePricingOrManageButton.tsx
Normal file
@ -0,0 +1,29 @@
|
||||
import { useFeatureIsOn } from "@growthbook/growthbook-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { StripePricingModal } from "@/lib/components/Stripe";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import { useUserData } from "@/lib/hooks/useUserData";
|
||||
|
||||
const MANAGE_PLAN_URL = process.env.NEXT_PUBLIC_STRIPE_MANAGE_PLAN_URL;
|
||||
|
||||
export const StripePricingOrManageButton = (): JSX.Element => {
|
||||
const { t } = useTranslation("monetization");
|
||||
const { userData } = useUserData();
|
||||
const monetizationIsOn = useFeatureIsOn("monetization");
|
||||
|
||||
if (!monetizationIsOn) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const is_premium = userData?.is_premium ?? false;
|
||||
if (is_premium) {
|
||||
return (
|
||||
<a href={MANAGE_PLAN_URL} target="_blank" rel="noopener">
|
||||
<Button className="w-full">{t("manage_plan")}</Button>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
return <StripePricingModal Trigger={<Button>{t("upgrade")}</Button>} />;
|
||||
};
|
@ -1 +1,2 @@
|
||||
export { UserStatistics } from "./UserStatistics";
|
||||
export { StripePricingOrManageButton } from "./StripePricingOrManageButton";
|
||||
|
@ -1,36 +1,26 @@
|
||||
/* eslint-disable max-lines */
|
||||
"use client";
|
||||
import Link from "next/link";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { StripePricingModal } from "@/lib/components/Stripe";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import Card, { CardBody, CardHeader } from "@/lib/components/ui/Card";
|
||||
import { useSupabase } from "@/lib/context/SupabaseProvider";
|
||||
import { useUserData } from "@/lib/hooks/useUserData";
|
||||
import { redirectToLogin } from "@/lib/router/redirectToLogin";
|
||||
|
||||
import { UserStatistics } from "./components";
|
||||
import { StripePricingOrManageButton, UserStatistics } from "./components";
|
||||
import { ApiKeyConfig } from "./components/ApiKeyConfig";
|
||||
import LanguageSelect from "./components/LanguageDropDown/LanguageSelect";
|
||||
import ThemeSelect from "./components/ThemeSelect/ThemeSelect";
|
||||
|
||||
const UserPage = (): JSX.Element => {
|
||||
const { session } = useSupabase();
|
||||
const { userData } = useUserData();
|
||||
const is_premium = userData?.is_premium;
|
||||
|
||||
if (!session) {
|
||||
redirectToLogin();
|
||||
}
|
||||
|
||||
const { user } = session;
|
||||
const { t } = useTranslation([
|
||||
"translation",
|
||||
"user",
|
||||
"config",
|
||||
"monetization",
|
||||
]);
|
||||
const { t } = useTranslation(["translation", "user", "config"]);
|
||||
|
||||
return (
|
||||
<main className="container lg:w-2/3 mx-auto py-10 px-5">
|
||||
@ -52,11 +42,7 @@ const UserPage = (): JSX.Element => {
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
{is_premium === true ? null : (
|
||||
<StripePricingModal
|
||||
Trigger={<Button>{t("monetization:upgrade")}</Button>}
|
||||
/>
|
||||
)}
|
||||
<StripePricingOrManageButton />
|
||||
</CardBody>
|
||||
</Card>
|
||||
|
||||
|
@ -27,8 +27,10 @@ export const SidebarFooterButton = ({
|
||||
className="w-full rounded-lg px-5 py-2 text-base flex justify-start items-center gap-4 hover:bg-gray-200 dark:hover:bg-gray-800 hover:text-primary focus:outline-none"
|
||||
onClick={onClick}
|
||||
>
|
||||
{icon}
|
||||
<span className="text-ellipsis overflow-hidden">{label}</span>
|
||||
<span className="w-8 shrink-0">{icon}</span>
|
||||
<span className="w-full text-ellipsis overflow-hidden text-start">
|
||||
{label}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
@ -23,12 +23,12 @@ export const UpgradeToPlus = (): JSX.Element => {
|
||||
<SidebarFooterButton
|
||||
icon={<FiUser className="w-8 h-8" />}
|
||||
label={
|
||||
<>
|
||||
{t("upgrade")}{" "}
|
||||
<span className="rounded bg-primary/50 py-1 px-3 text-xs">
|
||||
<div className="flex justify-between items-center w-full">
|
||||
{t("upgrade")}
|
||||
<span className="rounded bg-primary/30 py-1 px-3 text-xs">
|
||||
{t("new")}
|
||||
</span>
|
||||
</>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
import { FaCrown } from "react-icons/fa";
|
||||
|
||||
import { Avatar } from "@/lib/components/ui/Avatar";
|
||||
import { useSupabase } from "@/lib/context/SupabaseProvider";
|
||||
import { useUserData } from "@/lib/hooks/useUserData";
|
||||
|
||||
import { SidebarFooterButton } from "./SidebarFooterButton";
|
||||
import { useGravatar } from "../../../../../hooks/useGravatar";
|
||||
@ -7,12 +10,21 @@ import { useGravatar } from "../../../../../hooks/useGravatar";
|
||||
export const UserButton = (): JSX.Element => {
|
||||
const { session } = useSupabase();
|
||||
const { gravatarUrl } = useGravatar();
|
||||
const { userData } = useUserData();
|
||||
const is_premium = userData?.is_premium ?? false;
|
||||
const email = session?.user.email ?? "";
|
||||
const label = (
|
||||
<span className="flex justify-between items-center flex-nowrap gap-1 w-full">
|
||||
<span className="text-ellipsis overflow-hidden">{email}</span>
|
||||
{is_premium && <FaCrown className="w-5 h-5 shrink-0" />}
|
||||
</span>
|
||||
);
|
||||
|
||||
return (
|
||||
<SidebarFooterButton
|
||||
href={"/user"}
|
||||
icon={<Avatar url={gravatarUrl} />}
|
||||
label={session?.user.email ?? ""}
|
||||
label={label}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"upgrade": "Upgrade to plus",
|
||||
"new": "New"
|
||||
"new": "New",
|
||||
"manage_plan": "Manage my plan"
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"upgrade": "Actualizar a plus",
|
||||
"new": "Nuevo"
|
||||
"new": "Nuevo",
|
||||
"manage_plan": "Gestionar mi plan"
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"upgrade": "Passer à la version plus",
|
||||
"new": "Nouveau"
|
||||
"new": "Nouveau",
|
||||
"manage_plan": "Gérer mon plan"
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"upgrade": "Atualizar para o plus",
|
||||
"new": "Novo"
|
||||
"new": "Novo",
|
||||
"manage_plan": "Gerenciar meu plano"
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"upgrade": "Обновить до плюса",
|
||||
"new": "Новый"
|
||||
"new": "Новый",
|
||||
"manage_plan": "Управлять моим планом"
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"upgrade": "升级至高级版",
|
||||
"new": "新"
|
||||
"new": "新",
|
||||
"manage_plan": "管理我的计划"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user