Show number of credits left
This commit is contained in:
parent
a46ff8692c
commit
5256d428e0
@ -11,20 +11,60 @@ import {
|
|||||||
import { useStore } from "../../store/store";
|
import { useStore } from "../../store/store";
|
||||||
import { capitalize } from "./utils";
|
import { capitalize } from "./utils";
|
||||||
import StripeCustomerPortalLink from "./StripeCustomerPortalLink";
|
import StripeCustomerPortalLink from "./StripeCustomerPortalLink";
|
||||||
|
import { Progress } from "../ui/progress";
|
||||||
|
import { useAuthenticatedFetch } from "./useAuthenticatedFetch";
|
||||||
|
import { SAAS_BACKEND_URL } from "../../config";
|
||||||
|
import { CreditsUsage } from "./types";
|
||||||
|
import { useState } from "react";
|
||||||
|
import toast from "react-hot-toast";
|
||||||
|
|
||||||
export default function AvatarDropdown() {
|
export default function AvatarDropdown() {
|
||||||
const { user, isLoaded, isSignedIn } = useUser();
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const { signOut } = useClerk();
|
const [isLoadingUsage, setIsLoadingUsage] = useState(false);
|
||||||
|
const [usedCredits, setUsedCredits] = useState(0);
|
||||||
|
const [totalCredits, setTotalCredits] = useState(0);
|
||||||
|
|
||||||
const subscriberTier = useStore((state) => state.subscriberTier);
|
const subscriberTier = useStore((state) => state.subscriberTier);
|
||||||
const setPricingDialogOpen = useStore((state) => state.setPricingDialogOpen);
|
const setPricingDialogOpen = useStore((state) => state.setPricingDialogOpen);
|
||||||
const isFreeUser = subscriberTier === "free";
|
const isFreeUser = subscriberTier === "free";
|
||||||
|
|
||||||
|
const { user, isLoaded, isSignedIn } = useUser();
|
||||||
|
const { signOut } = useClerk();
|
||||||
|
const authenticatedFetch = useAuthenticatedFetch();
|
||||||
|
|
||||||
|
async function open(isOpen: boolean) {
|
||||||
|
setIsOpen(isOpen);
|
||||||
|
|
||||||
|
// Do not fetch usage if the user is a free user
|
||||||
|
// or that information hasn't loaded yet
|
||||||
|
// or the dropdown is closed
|
||||||
|
if (isFreeUser || !subscriberTier || !isOpen) return;
|
||||||
|
|
||||||
|
setIsLoadingUsage(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res: CreditsUsage = await authenticatedFetch(
|
||||||
|
SAAS_BACKEND_URL + "/credits/usage",
|
||||||
|
"POST"
|
||||||
|
);
|
||||||
|
|
||||||
|
setUsedCredits(res.used_monthly_credits);
|
||||||
|
setTotalCredits(res.total_monthly_credits);
|
||||||
|
} catch (e) {
|
||||||
|
toast.error(
|
||||||
|
"Failed to fetch credit usage. Please contact support to get this issue fixed."
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
setIsLoadingUsage(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If Clerk is still loading or user is logged out, don't show anything
|
// If Clerk is still loading or user is logged out, don't show anything
|
||||||
if (!isLoaded || !isSignedIn) return null;
|
if (!isLoaded || !isSignedIn) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DropdownMenu>
|
<DropdownMenu open={isOpen} onOpenChange={open}>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Avatar className="w-8 h-8 cursor-pointer">
|
<Avatar className="w-8 h-8 cursor-pointer">
|
||||||
<AvatarImage src={user?.imageUrl} alt="Profile image" />
|
<AvatarImage src={user?.imageUrl} alt="Profile image" />
|
||||||
@ -44,6 +84,28 @@ export default function AvatarDropdown() {
|
|||||||
<DropdownMenuLabel>
|
<DropdownMenuLabel>
|
||||||
{capitalize(subscriberTier) + " Subscriber"}
|
{capitalize(subscriberTier) + " Subscriber"}
|
||||||
</DropdownMenuLabel>
|
</DropdownMenuLabel>
|
||||||
|
|
||||||
|
{/* Loading credit usage */}
|
||||||
|
{isLoadingUsage && (
|
||||||
|
<DropdownMenuItem className="text-xs text-gray-700">
|
||||||
|
Loading credit usage...
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Credits usage */}
|
||||||
|
{!isLoadingUsage && (
|
||||||
|
<>
|
||||||
|
<DropdownMenuItem>
|
||||||
|
<Progress value={(usedCredits / totalCredits) * 100} />
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem className="text-xs text-gray-700">
|
||||||
|
{usedCredits} out of {totalCredits} credits used.
|
||||||
|
{subscriberTier !== "pro" && (
|
||||||
|
<> Upgrade to Pro to get more credits.</>
|
||||||
|
)}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItem asChild={true}>
|
<DropdownMenuItem asChild={true}>
|
||||||
<a href="mailto:support@picoapps.xyz" target="_blank">
|
<a href="mailto:support@picoapps.xyz" target="_blank">
|
||||||
|
|||||||
@ -10,3 +10,8 @@ export interface UserResponse {
|
|||||||
export interface PortalSessionResponse {
|
export interface PortalSessionResponse {
|
||||||
url: string;
|
url: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CreditsUsage {
|
||||||
|
total_monthly_credits: number;
|
||||||
|
used_monthly_credits: number;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user