'use client' import type { EducationStatusResponse } from '@dify/contracts/api/console/account/types.gen' import type { GetFeaturesResponse } from '@dify/contracts/api/console/features/types.gen' import type { ReactNode } from 'react' import { Button, buttonVariants } from '@langgenius/dify-ui/button' import { useMutation, useQuery, useSuspenseQuery } from '@tanstack/react-query' import { useCallback, useEffect, useRef } from 'react' import { useTranslation } from 'react-i18next' import Loading from '@/app/components/base/loading' import { useDocLink } from '@/context/i18n' import { userProfileQueryOptions } from '@/features/account-profile/client' import Link from '@/next/link' import { redirect, useRouter } from '@/next/navigation' import { consoleClient, consoleQuery } from '@/service/client' import { EducationStatusCard } from '../status-card' import UserInfo from '../user-info' class EducationVerificationRejectedError extends Error {} type EducationVerificationRequest = () => Promise<{ token?: string | null }> const selectEducationStatus = ({ allow_refresh, is_student }: EducationStatusResponse) => ({ allowRefresh: allow_refresh ?? false, isEducationAccount: is_student ?? false, }) const selectEducationPlanEnabled = ({ education }: GetFeaturesResponse) => education.enabled const requestEducationVerification: EducationVerificationRequest = () => consoleClient.account.education.verify.get({}, { context: { silent: true } }) async function requestEducationVerificationToken( requestVerification: EducationVerificationRequest, ) { const response = await requestVerification() if (!response.token) throw new EducationVerificationRejectedError() return response.token } export default function EducationVerifyPage() { return } export function EducationVerifyFlow({ requestVerification = requestEducationVerification, }: { requestVerification?: EducationVerificationRequest }) { const { t } = useTranslation() const router = useRouter() const { data: userEmail } = useSuspenseQuery({ ...userProfileQueryOptions(), select: (data) => data.profile.email, }) const docLink = useDocLink() const verificationStartedRef = useRef(false) const featuresQuery = useQuery( consoleQuery.features.get.queryOptions({ select: selectEducationPlanEnabled }), ) const enableEducationPlan = featuresQuery.data === true const educationStatusQuery = useQuery( consoleQuery.account.education.get.queryOptions({ enabled: featuresQuery.isSuccess && enableEducationPlan, select: selectEducationStatus, }), ) const { error: verificationError, isError: isVerificationError, mutate: verifyEducation, reset: resetVerification, } = useMutation({ mutationKey: ['education', 'verification-token'], mutationFn: () => requestEducationVerificationToken(requestVerification), }) const startVerification = useCallback(() => { if (verificationStartedRef.current) return verificationStartedRef.current = true verifyEducation(undefined, { onSuccess: (token) => { router.replace(`/education/apply?token=${encodeURIComponent(token)}`) }, }) }, [router, verifyEducation]) const educationStatus = educationStatusQuery.data const isAlreadyVerified = educationStatus?.isEducationAccount === true && !educationStatus.allowRefresh const canVerify = educationStatusQuery.isSuccess && educationStatus !== undefined && (!educationStatus.isEducationAccount || educationStatus.allowRefresh) useEffect(() => { if (canVerify) startVerification() }, [canVerify, startVerification]) if (featuresQuery.isPending) return if (!enableEducationPlan) return redirect('/') if (educationStatusQuery.isPending) return if (educationStatusQuery.isError) return ( { void educationStatusQuery.refetch() }} /> ) if (isAlreadyVerified) return if (verificationError instanceof EducationVerificationRejectedError) { return ( ) } if (isVerificationError) return ( { verificationStartedRef.current = false resetVerification() startVerification() }} /> ) return } function EducationVerifyContent({ children }: { children: ReactNode }) { return ( <>
{children} ) } function EducationVerifyLoading() { return ( } title={} > ) } function EducationVerifiedContent() { const { t } = useTranslation() return ( ) } function EducationVerifyError({ onRetry }: { onRetry: () => void }) { const { t } = useTranslation() return ( ) }