feat: token usage

feat/ai-courses
Arik Chakma 2 months ago
parent 2e391c0ff0
commit 09f76d0c25
  1. 106
      src/components/GenerateCourse/AICourseLimit.tsx
  2. 4
      src/queries/ai-course.ts

@ -13,10 +13,9 @@ import { queryClient } from '../../stores/query-client';
import { useOutsideClick } from '../../hooks/use-outside-click'; import { useOutsideClick } from '../../hooks/use-outside-click';
import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal'; import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';
import { billingDetailsOptions } from '../../queries/billing'; import { billingDetailsOptions } from '../../queries/billing';
import { getPercentage } from '../../helper/number';
export function AICourseLimit() { export function AICourseLimit() {
const containerRef = useRef<HTMLDivElement>(null);
const [isOpen, setIsOpen] = useState(false);
const [showUpgradeModal, setShowUpgradeModal] = useState(false); const [showUpgradeModal, setShowUpgradeModal] = useState(false);
const { data: limits, isLoading } = useQuery( const { data: limits, isLoading } = useQuery(
@ -27,105 +26,28 @@ export function AICourseLimit() {
const { data: userBillingDetails, isLoading: isBillingDetailsLoading } = const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =
useQuery(billingDetailsOptions(), queryClient); useQuery(billingDetailsOptions(), queryClient);
useOutsideClick(containerRef, () => {
setIsOpen(false);
});
if (isLoading || !limits || isBillingDetailsLoading || !userBillingDetails) { if (isLoading || !limits || isBillingDetailsLoading || !userBillingDetails) {
return ( return (
<div className="h-[34px] w-[243px] animate-pulse rounded-lg border border-gray-200 bg-gray-200"></div> <div className="h-[38px] w-[208.09px] animate-pulse rounded-lg border border-gray-200 bg-gray-200"></div>
); );
} }
const { const { used, limit } = limits;
used: courseUsed,
limit: courseLimit,
lessonUsed,
lessonLimit,
followUpUsed,
followUpLimit,
} = limits;
const coursePercentage = Math.round((courseUsed / courseLimit) * 100); const totalPercentage = getPercentage(used, limit);
const lessonPercentage = Math.round((lessonUsed / lessonLimit) * 100);
const followUpPercentage = Math.round((followUpUsed / followUpLimit) * 100);
return ( return (
<> <>
<div className="relative z-10" ref={containerRef}> <div className="relative flex h-full min-h-[38px] cursor-pointer items-center overflow-hidden rounded-lg border border-gray-200 px-3 py-1.5 text-sm hover:bg-gray-50">
<button <span className="relative z-10">
className="flex h-full cursor-pointer items-center rounded-lg border border-gray-200 px-2 py-1.5 text-sm hover:bg-gray-50" {totalPercentage}% of the daily limit used
onClick={() => setIsOpen(!isOpen)} </span>
> <div
<div className="mr-3 flex items-center gap-1.5"> className="absolute inset-0 h-full bg-gray-50"
<BookIcon className="h-4 w-4" /> style={{
{coursePercentage}% width: `${totalPercentage}%`,
</div> }}
<div className="mr-3 flex items-center gap-1.5"> ></div>
<BookOpenIcon className="h-4 w-4" />
{lessonPercentage}%
</div>
<div className="mr-3 flex items-center gap-1.5">
<BotIcon className="h-4 w-4" />
{followUpPercentage}%
</div>
<span className="mr-1">of daily limits</span>
<ChevronDownIcon className="h-4 w-4" />
</button>
{isOpen && (
<div className="absolute right-0 top-full w-full translate-y-1 overflow-hidden rounded-lg border border-gray-200 bg-white p-2 pt-0 text-sm shadow-lg">
<div className="-mx-2">
<div className="relative overflow-hidden">
<div className="relative z-10 flex items-center gap-2 border-b border-b-gray-200 px-2 py-1">
<BookIcon className="size-3.5" />
{courseUsed} of {courseLimit} courses used
</div>
<div
className="absolute inset-0 bg-gray-100"
style={{
width: `${coursePercentage}%`,
}}
/>
</div>
<div className="relative overflow-hidden">
<div className="relative z-10 flex items-center gap-2 border-b border-b-gray-200 px-2 py-1">
<BookOpenIcon className="size-3.5" />
{lessonUsed} of {lessonLimit} lessons used
</div>
<div
className="absolute inset-0 bg-gray-100"
style={{
width: `${lessonPercentage}%`,
}}
/>
</div>
<div className="relative overflow-hidden">
<div className="relative z-10 flex items-center gap-2 border-b border-b-gray-200 px-2 py-1">
<BotIcon className="size-3.5" />
{followUpUsed} of {followUpLimit} follow-ups used
</div>
<div
className="absolute inset-0 bg-gray-100"
style={{
width: `${followUpPercentage}%`,
}}
/>
</div>
</div>
<div className="mt-2 flex items-center justify-center gap-2 text-gray-500">
<ClockIcon className="size-3.5" />
Limit resets every 24 hours
</div>
</div>
)}
</div> </div>
{userBillingDetails.status === 'none' && ( {userBillingDetails.status === 'none' && (

@ -72,10 +72,6 @@ type GetAICourseLimitParams = {};
type GetAICourseLimitResponse = { type GetAICourseLimitResponse = {
used: number; used: number;
limit: number; limit: number;
lessonUsed: number;
lessonLimit: number;
followUpUsed: number;
followUpLimit: number;
}; };
export function getAiCourseLimitOptions() { export function getAiCourseLimitOptions() {

Loading…
Cancel
Save