Merge branch 'feat/edu-version' into deploy/dev
This commit is contained in:
commit
de2f86fe5f
@ -3,7 +3,6 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import {
|
||||
useRouter,
|
||||
useSearchParams,
|
||||
} from 'next/navigation'
|
||||
import useSWRInfinite from 'swr/infinite'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -30,6 +29,7 @@ import TagManagementModal from '@/app/components/base/tag-management'
|
||||
import TagFilter from '@/app/components/base/tag-management/filter'
|
||||
import CheckboxWithLabel from '@/app/components/datasets/create/website/base/checkbox-with-label'
|
||||
import { useModalContextSelector } from '@/context/modal-context'
|
||||
import { EDUCATION_VERIFYING_LOCALSTORAGE_ITEM } from '@/app/education-apply/components/constants'
|
||||
|
||||
const getKey = (
|
||||
pageIndex: number,
|
||||
@ -136,14 +136,13 @@ const Apps = () => {
|
||||
setQuery(prev => ({ ...prev, isCreatedByMe: newValue }))
|
||||
}, [isCreatedByMe, setQuery])
|
||||
|
||||
const searchParams = useSearchParams()
|
||||
const action = searchParams.get('action')
|
||||
const setShowAccountSettingModal = useModalContextSelector(s => s.setShowAccountSettingModal)
|
||||
const educationVerifying = localStorage.getItem(EDUCATION_VERIFYING_LOCALSTORAGE_ITEM)
|
||||
|
||||
useEffect(() => {
|
||||
if (action === 'getEducationVerify')
|
||||
if (educationVerifying === 'yes')
|
||||
setShowAccountSettingModal({ payload: 'billing' })
|
||||
}, [action, setShowAccountSettingModal])
|
||||
}, [setShowAccountSettingModal, educationVerifying])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -1,15 +1,28 @@
|
||||
'use client'
|
||||
import { useEffect } from 'react'
|
||||
import { useContextSelector } from 'use-context-selector'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiDiscordFill, RiGithubFill } from '@remixicon/react'
|
||||
import Link from 'next/link'
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
import style from '../list.module.css'
|
||||
import Apps from './Apps'
|
||||
import AppContext from '@/context/app-context'
|
||||
import { LicenseStatus } from '@/types/feature'
|
||||
import {
|
||||
EDUCATION_VERIFYING_LOCALSTORAGE_ITEM,
|
||||
EDUCATION_VERIFY_URL_SEARCHPARAMS_ACTION,
|
||||
} from '@/app/education-apply/components/constants'
|
||||
|
||||
const AppList = () => {
|
||||
const { t } = useTranslation()
|
||||
const searchParams = useSearchParams()
|
||||
const educationVerifyAction = searchParams.get('action')
|
||||
|
||||
useEffect(() => {
|
||||
if (educationVerifyAction === EDUCATION_VERIFY_URL_SEARCHPARAMS_ACTION)
|
||||
localStorage.setItem(EDUCATION_VERIFYING_LOCALSTORAGE_ITEM, 'yes')
|
||||
}, [educationVerifyAction])
|
||||
const systemFeatures = useContextSelector(AppContext, v => v.systemFeatures)
|
||||
|
||||
return (
|
||||
|
@ -21,6 +21,7 @@ import { useAppContext } from '@/context/app-context'
|
||||
import Button from '@/app/components/base/button'
|
||||
import UsageInfo from '@/app/components/billing/usage-info'
|
||||
import VerifyStateModal from '@/app/education-apply/components/verify-state-modal'
|
||||
import { EDUCATION_VERIFYING_LOCALSTORAGE_ITEM } from '@/app/education-apply/components/constants'
|
||||
|
||||
type Props = {
|
||||
loc: string
|
||||
@ -44,10 +45,13 @@ const PlanComp: FC<Props> = ({
|
||||
|
||||
const [showModal, setShowModal] = React.useState(false)
|
||||
const handleVerify = () => {
|
||||
if (userProfile.email.endsWith('.edu'))
|
||||
if (userProfile.email.endsWith('.edu')) {
|
||||
localStorage.removeItem(EDUCATION_VERIFYING_LOCALSTORAGE_ITEM)
|
||||
router.push('/education-apply')
|
||||
else
|
||||
}
|
||||
else {
|
||||
setShowModal(true)
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div className='bg-background-section-burn rounded-2xl border-[0.5px] border-effects-highlight-lightmode-off'>
|
||||
@ -119,7 +123,7 @@ const PlanComp: FC<Props> = ({
|
||||
email={userProfile.email}
|
||||
isShow={showModal}
|
||||
title={t('education.rejectTitle')}
|
||||
content={t('education.rejectContent2')}
|
||||
content={t('education.rejectContent')}
|
||||
onConfirm={() => setShowModal(false)}
|
||||
onCancel={() => setShowModal(false)}
|
||||
/>
|
||||
|
2
web/app/education-apply/components/constants.ts
Normal file
2
web/app/education-apply/components/constants.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export const EDUCATION_VERIFY_URL_SEARCHPARAMS_ACTION = 'getEducationVerifyA'
|
||||
export const EDUCATION_VERIFYING_LOCALSTORAGE_ITEM = 'educationVerifying'
|
@ -4,6 +4,7 @@ import {
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import UserInfo from './user-info'
|
||||
import SearchInput from './search-input'
|
||||
import RoleSelector from './role-selector'
|
||||
@ -16,6 +17,8 @@ import {
|
||||
useInvalidateEducationStatus,
|
||||
} from '@/service/use-education'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { useToastContext } from '@/app/components/base/toast'
|
||||
import { EDUCATION_VERIFYING_LOCALSTORAGE_ITEM } from '@/app/education-apply/components/constants'
|
||||
|
||||
const EducationApplyAge = () => {
|
||||
const { t } = useTranslation()
|
||||
@ -31,11 +34,15 @@ const EducationApplyAge = () => {
|
||||
const { data } = useEducationVerify()
|
||||
const { onPlanInfoChanged } = useProviderContext()
|
||||
const updateEducationStatus = useInvalidateEducationStatus()
|
||||
const { notify } = useToastContext()
|
||||
const router = useRouter()
|
||||
|
||||
const handleModalConfirm = () => {
|
||||
setShowModal(undefined)
|
||||
onPlanInfoChanged()
|
||||
updateEducationStatus()
|
||||
localStorage.removeItem(EDUCATION_VERIFYING_LOCALSTORAGE_ITEM)
|
||||
router.replace('/')
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
@ -52,9 +59,9 @@ const EducationApplyAge = () => {
|
||||
})
|
||||
}
|
||||
else {
|
||||
setShowModal({
|
||||
title: t('education.rejectTitle'),
|
||||
desc: t('education.rejectContent'),
|
||||
notify({
|
||||
type: 'error',
|
||||
message: t('education.submitError'),
|
||||
})
|
||||
}
|
||||
})
|
||||
@ -113,9 +120,9 @@ const EducationApplyAge = () => {
|
||||
</div>
|
||||
<div className='mb-1 system-md-regular text-text-tertiary'>
|
||||
{t('education.form.terms.desc.front')}
|
||||
<a href='' className='text-text-secondary hover:underline'>{t('education.form.terms.desc.termsOfService')}</a>
|
||||
<a href='https://dify.ai/terms' target='_blank' className='text-text-secondary hover:underline'>{t('education.form.terms.desc.termsOfService')}</a>
|
||||
{t('education.form.terms.desc.and')}
|
||||
<a href='' className='text-text-secondary hover:underline'>{t('education.form.terms.desc.privacyPolicy')}</a>
|
||||
<a href='https://dify.ai/privacy' target='_blank' className='text-text-secondary hover:underline'>{t('education.form.terms.desc.privacyPolicy')}</a>
|
||||
{t('education.form.terms.desc.end')}
|
||||
</div>
|
||||
<div className='py-2 system-md-regular text-text-primary'>
|
||||
@ -151,7 +158,7 @@ const EducationApplyAge = () => {
|
||||
title={modalShow?.title || ''}
|
||||
content={modalShow?.desc}
|
||||
onConfirm={modalShow?.onConfirm || (() => {})}
|
||||
onCancel={() => setShowModal(undefined)}
|
||||
onCancel={modalShow?.onConfirm || (() => {})}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
@ -17,6 +17,9 @@ import type {
|
||||
ModelLoadBalancingConfigEntry,
|
||||
ModelProvider,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import {
|
||||
EDUCATION_VERIFYING_LOCALSTORAGE_ITEM,
|
||||
} from '@/app/education-apply/components/constants'
|
||||
|
||||
import Pricing from '@/app/components/billing/pricing'
|
||||
import type { ModerationConfig, PromptVariable } from '@/models/debug'
|
||||
@ -121,10 +124,10 @@ export const ModalContextProvider = ({
|
||||
const [showPricingModal, setShowPricingModal] = useState(searchParams.get('show-pricing') === '1')
|
||||
const [showAnnotationFullModal, setShowAnnotationFullModal] = useState(false)
|
||||
const handleCancelAccountSettingModal = () => {
|
||||
const action = searchParams.get('action')
|
||||
const educationVerifying = localStorage.getItem(EDUCATION_VERIFYING_LOCALSTORAGE_ITEM)
|
||||
|
||||
if (action === 'getEducationVerify')
|
||||
router.push(location.pathname, { forceOptimisticNavigation: true } as any)
|
||||
if (educationVerifying === 'yes')
|
||||
localStorage.removeItem(EDUCATION_VERIFYING_LOCALSTORAGE_ITEM)
|
||||
setShowAccountSettingModal(null)
|
||||
if (showAccountSettingModal?.onCancelCallback)
|
||||
showAccountSettingModal?.onCancelCallback()
|
||||
|
@ -35,12 +35,12 @@ const translation = {
|
||||
},
|
||||
},
|
||||
submit: 'Submit',
|
||||
submitError: 'Form submission failed. Please try again later.',
|
||||
learn: 'Learn how to get education verified',
|
||||
successTitle: 'You Have Got Dify Education Verified',
|
||||
successContent: 'We have issued a 50% discount coupon for the Dify Professional plan to your account. The coupon is valid for one year, please use it within the validity period.',
|
||||
rejectTitle: 'Your Dify Education Verified Has Been Rejected',
|
||||
rejectContent: 'We’re sorry, but You are now eligible for Education Verified status because you disagreed with our Terms & Agreements. Please review the terms of these clauses and reapply if eligible.',
|
||||
rejectContent2: 'Unfortunately you are not eligible for a Education Verified status and receive an exclusive 50% coupon for the Dify Professional Plan if you use this email address.',
|
||||
rejectContent: 'Unfortunately, you are not eligible for Education Verified status and therefore cannot receive the exclusive 50% coupon for the Dify Professional Plan if you use this email address.',
|
||||
emailLabel: 'Your current email',
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,13 @@ const translation = {
|
||||
},
|
||||
},
|
||||
submit: '送信',
|
||||
submitError: 'フォームの送信に失敗しました。しばらくしてから再度ご提出ください。',
|
||||
learn: '教育認証の取得方法はこちら',
|
||||
successTitle: 'Dify教育認証を取得しました!',
|
||||
successContent: 'お客様のアカウントに Difyプロフェッショナルプランの50%割引クーポン を発行しました。有効期間は 1年間 ですので、期限内にご利用ください。',
|
||||
rejectTitle: 'Dify教育認証が拒否されました',
|
||||
rejectContent: '申し訳ございませんが、このメールアドレスでは 教育認証 の資格を取得できず、Difyプロフェッショナルプランの50%割引クーポン を受け取ることはできません。',
|
||||
emailLabel: '現在のメールアドレス',
|
||||
}
|
||||
|
||||
export default translation
|
||||
|
@ -35,12 +35,12 @@ const translation = {
|
||||
},
|
||||
},
|
||||
submit: '提交',
|
||||
submitError: '提交表单失败,请稍后重新提交问卷。',
|
||||
learn: '了解如何获取教育版认证',
|
||||
successTitle: '您已获得 Dify 教育版认证',
|
||||
successContent: '我们已向您的账户发放了 Dify Professional 计划的 50% 折扣券。该券有效期为一年,请在有效期内使用。',
|
||||
successTitle: '您已成功获得 Dify 教育版认证!',
|
||||
successContent: '我们已向您的账户发放 Dify Professional 版 50% 折扣优惠券。该优惠券有效期为一年,请在有效期内使用。',
|
||||
rejectTitle: '您的 Dify 教育版认证已被拒绝',
|
||||
rejectContent: '很抱歉,由于您不同意我们的条款与协议,您现在不符合教育版认证的资格。请查看这些条款的内容,如果符合资格,请重新申请。',
|
||||
rejectContent2: '很抱歉,由于您的邮箱地址不符合教育版认证的资格,也无法获得 Dify Professional 计划的 50% 独家优惠券。',
|
||||
rejectContent: '非常遗憾,您无法使用此电子邮件以获得教育版认证资格,也无法领取 Dify Professional 版的 50% 独家优惠券。',
|
||||
emailLabel: '您当前的邮箱',
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user