'use client' import type { EducationStatusResponse } from '@dify/contracts/api/console/account/types.gen' import type { FC } from 'react' import { Button, buttonVariants } from '@langgenius/dify-ui/button' import { RiBook2Line, RiFileEditLine, RiGroupLine } from '@remixicon/react' import { useQuery, useSuspenseQuery } from '@tanstack/react-query' import { useAtomValue } from 'jotai' import * as React from 'react' import { useTranslation } from 'react-i18next' import { ApiAggregate, TriggerAll } from '@/app/components/base/icons/src/vender/workflow' import UsageInfo from '@/app/components/billing/usage-info' import { useProviderContext } from '@/context/provider-context' import { isCurrentWorkspaceManagerAtom } from '@/context/workspace-state' import { systemFeaturesQueryOptions } from '@/features/system-features/client' import Link from '@/next/link' import { consoleQuery } from '@/service/client' import { getDaysUntilEndOfMonth } from '@/utils/time' import Loading from '../../base/icons/src/public/thought/Loading' import { NUM_INFINITE } from '../config' import { useEducationDiscount } from '../hooks/use-education-discount' import UpgradeBtn from '../upgrade-btn' import AppsInfo from '../usage-info/apps-info' import VectorSpaceInfo from '../usage-info/vector-space-info' import { Professional, Sandbox, Team } from './assets' type Props = Readonly<{ loc: string }> const selectEducationPlanStatus = ({ allow_refresh, is_student }: EducationStatusResponse) => ({ isAboutToExpire: allow_refresh ?? false, isEducationAccount: is_student ?? false, }) const PlanComp: FC = ({ loc }) => { const { t } = useTranslation() const { data: deploymentEdition } = useSuspenseQuery({ ...systemFeaturesQueryOptions(), select: ({ deployment_edition }) => deployment_edition, }) const isCloudEdition = deploymentEdition === 'CLOUD' const isCurrentWorkspaceManager = useAtomValue(isCurrentWorkspaceManagerAtom) const { plan, enableEducationPlan } = useProviderContext() const { data: educationStatus } = useQuery( consoleQuery.account.education.get.queryOptions({ enabled: enableEducationPlan, select: selectEducationPlanStatus, }), ) const { isAboutToExpire = false, isEducationAccount = false } = educationStatus ?? {} const { type } = plan const { usage, total, reset } = plan const triggerEventsResetInDays = type === 'professional' && total.triggerEvents !== NUM_INFINITE ? (reset.triggerEvents ?? undefined) : undefined const apiRateLimitResetInDays = (() => { if (total.apiRateLimit === NUM_INFINITE) return undefined if (typeof reset.apiRateLimit === 'number') return reset.apiRateLimit if (type === 'sandbox') return getDaysUntilEndOfMonth() return undefined })() const { handleEducationDiscount, isEducationDiscountLoading } = useEducationDiscount() return (
{plan.type === 'sandbox' && } {plan.type === 'professional' && } {plan.type === 'team' && }
{t(($) => $[`plans.${type}.name`], { ns: 'billing' })}
{t(($) => $[`plans.${type}.for`], { ns: 'billing' })}
{isCloudEdition && enableEducationPlan && (!isEducationAccount || isAboutToExpire) && (
{/* Plan detail */}
$['usagePage.teamMembers'], { ns: 'billing' })} usage={usage.teamMembers} total={total.teamMembers} /> $['usagePage.documentsUploadQuota'], { ns: 'billing' })} usage={usage.documentsUploadQuota} total={total.documentsUploadQuota} /> $['usagePage.annotationQuota'], { ns: 'billing' })} usage={usage.annotatedResponse} total={total.annotatedResponse} /> $['usagePage.triggerEvents'], { ns: 'billing' })} usage={usage.triggerEvents} total={total.triggerEvents} tooltip={t(($) => $['plansCommon.triggerEvents.tooltip'], { ns: 'billing' }) as string} resetInDays={triggerEventsResetInDays} /> $['plansCommon.apiRateLimit'], { ns: 'billing' })} usage={usage.apiRateLimit} total={total.apiRateLimit} tooltip={ total.apiRateLimit === NUM_INFINITE ? undefined : (t(($) => $['plansCommon.apiRateLimitTooltip'], { ns: 'billing' }) as string) } resetInDays={apiRateLimitResetInDays} />
) } export default React.memo(PlanComp)