Skip to content

Commit

Permalink
feat: add donating card (#680)
Browse files Browse the repository at this point in the history
  • Loading branch information
RealKai42 authored Oct 18, 2023
1 parent b736417 commit 8db4c58
Show file tree
Hide file tree
Showing 20 changed files with 172 additions and 22 deletions.
Binary file added src/assets/qrCord/a12.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/qrCord/a36.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/qrCord/a50.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/qrCord/a6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/qrCord/a66.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/qrCord/w12.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/qrCord/w36.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/qrCord/w50.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/qrCord/w6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/qrCord/w66.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/sticker.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/sticker2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 27 additions & 14 deletions src/components/DonateCard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { AmountType } from '../DonatingCard'
import { DonatingCard } from '../DonatingCard'
import { StickerButton } from '../DonatingCard/components/StickerButton'
import { useChapterNumber, useDayFromFirstWordRecord, useSumWrongCount, useWordNumber } from './hooks/useWordStats'
import alipay from '@/assets/alipay.jpg'
import weChat from '@/assets/weChat.jpg'
import { DONATE_DATE } from '@/constants'
import { reportDonateCard } from '@/utils'
import noop from '@/utils/noop'
Expand All @@ -12,6 +13,7 @@ import IconParty from '~icons/logos/partytown-icon'

export const DonateCard = () => {
const [show, setShow] = useState(false)
const [amount, setAmount] = useState<AmountType | undefined>(undefined)

const chapterNumber = useChapterNumber()
const wordNumber = useWordNumber()
Expand All @@ -35,6 +37,7 @@ export const DonateCard = () => {
sumWrongCount,
dayFromFirstWord,
dayFromQwerty,
amount: amount ?? 0,
})

setShow(false)
Expand All @@ -50,11 +53,16 @@ export const DonateCard = () => {
sumWrongCount,
dayFromFirstWord,
dayFromQwerty,
amount: amount ?? 0,
})

setShow(false)
}

const onAmountChange = (amount: AmountType) => {
setAmount(amount)
}

useLayoutEffect(() => {
if (chapterNumber && chapterNumber !== 0 && chapterNumber % 10 === 0) {
const storedDate = window.localStorage.getItem(DONATE_DATE)
Expand Down Expand Up @@ -99,8 +107,8 @@ export const DonateCard = () => {
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="relative my-8 w-[36rem] transform select-text overflow-hidden rounded-lg bg-white text-left shadow-xl transition-all">
<div className="flex w-full flex-col justify-center gap-4 bg-white px-2 pb-4 pt-5 dark:bg-gray-800">
<Dialog.Panel className="relative my-8 w-[37rem] transform select-text overflow-hidden rounded-lg bg-white text-left shadow-xl transition-all">
<div className="flex w-full flex-col justify-center gap-4 bg-white px-2 pb-4 pt-5 dark:bg-gray-800 dark:text-gray-300">
<h1 className="gradient-text w-full pt-3 text-center text-[2.4rem] font-bold">{`${chapterNumber} Chapters Achievement !`}</h1>
<div className="flex w-full flex-col gap-4 px-4">
<p className="mx-auto px-4 indent-4">
Expand All @@ -116,20 +124,25 @@ export const DonateCard = () => {
<p className="mx-auto px-4 indent-4">
Qwerty Learner 已经坚持 <span className="font-medium ">开放源码、无广告、无商业化</span> 运营
<HighlightedText className="text-indigo-500"> {dayFromQwerty} </HighlightedText> 天,
我们的目标是为所有学习者提供一个高效、便捷、无干扰的学习环境。
我们的目标是为所有学习者提供一个高效、便捷、无干扰的学习环境。我们诚挚地邀请您考虑进行捐赠,捐赠将直接用于维持 Qwerty
的日常运营以及未来发展,让 Qwerty 与您一起成长。
</p>
<p className="mx-auto px-4 indent-4">
如果您喜欢 Qwerty,那么我们诚挚地邀请您考虑进行捐赠,您的捐赠将直接用于维持 Qwerty 的日常运营以及未来的发展,让 Qwerty
与您一起成长。
<p className="mx-auto px-4 indent-4 ">
为了感谢您的慷慨,单次 50 rmb 及以上的捐赠, 我们将回赠 Qwerty 的定制贴纸 5 枚
<span className="text-xs">(仅限大陆地区)</span>,希望您可以跟朋友分享您的快乐
</p>
<div className="flex items-center justify-center">
<StickerButton />
</div>
</div>

<div className="mt-3 flex h-44 w-full justify-between px-11">
<img src={alipay} alt="alipay" className=" h-full" />
<img src={weChat} alt="weChat" className=" h-full" />
</div>
<div className="flex w-full justify-between px-14 pb-3 pt-6">
<button type="button" className="my-btn-primary w-36 bg-amber-500 font-medium" onClick={onClickHasDonated}>
<DonatingCard className="mt-2" onAmountChange={onAmountChange} />
<div className="flex w-full justify-between px-14 pb-3 pt-0">
<button
type="button"
className={`my-btn-primary ${!amount && 'invisible'} w-36 bg-amber-500 font-medium transition-all`}
onClick={onClickHasDonated}
>
我已捐赠
</button>
<button type="button" className="my-btn-primary w-36 font-medium" onClick={onClickRemindMeLater}>
Expand Down
21 changes: 21 additions & 0 deletions src/components/DonatingCard/AmountQrMap.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import alipay from '@/assets/alipay.jpg'
import a6 from '@/assets/qrCord/a6.png'
import a12 from '@/assets/qrCord/a12.png'
import a36 from '@/assets/qrCord/a36.png'
import a50 from '@/assets/qrCord/a50.png'
import a66 from '@/assets/qrCord/a66.png'
import w6 from '@/assets/qrCord/w6.png'
import w12 from '@/assets/qrCord/w12.png'
import w36 from '@/assets/qrCord/w36.png'
import w50 from '@/assets/qrCord/w50.png'
import w66 from '@/assets/qrCord/w66.png'
import weChat from '@/assets/weChat.jpg'

export const AmountImageMap = {
'-1': [alipay, weChat],
6: [a6, w6],
12: [a12, w12],
36: [a36, w36],
50: [a50, w50],
66: [a66, w66],
}
23 changes: 23 additions & 0 deletions src/components/DonatingCard/components/Amount.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { AmountType } from '..'

export const Amount = ({
amount,
onClick,
active = true,
}: {
amount: AmountType
onClick?: (amount: AmountType) => void
active: boolean
}) => {
return (
<button
className={` focus: h-10 rounded border-gray-100 font-bold text-gray-700 shadow-md shadow-gray-300
outline-none hover:bg-gray-100 dark:bg-gray-700 dark:text-gray-300 dark:text-opacity-80 dark:opacity-80
dark:shadow-gray-700 hover:dark:bg-gray-600
${amount === -1 ? 'w-18' : 'w-10'} ${active ? 'bg-stone-100 dark:bg-gray-500' : ''}`}
onClick={() => onClick && onClick(amount)}
>
{amount === -1 ? '自定义' : amount}
</button>
)
}
37 changes: 37 additions & 0 deletions src/components/DonatingCard/components/StickerButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import sticker2 from '@/assets/sticker2.jpg'
import sticker1 from '@/assets/sticker.jpg'
import { Tooltip } from 'react-tooltip'
import 'react-tooltip/dist/react-tooltip.css'
import IconInfo from '~icons/ic/outline-info'
import SolarStickerSmileSquareOutline from '~icons/solar/sticker-smile-square-outline'

export const StickerButton = ({ className }: { className?: string }) => {
return (
<>
<div
data-tooltip-id="sticker-btn"
className={`w-max cursor-pointer rounded border-2 border-dashed border-gray-300 p-1.5 indent-0 text-sm font-bold text-gray-500 transition-all hover:border-indigo-500 hover:text-indigo-500
dark:text-gray-300
${className}`}
>
<SolarStickerSmileSquareOutline className="mb-[2px] mr-2 inline-block text-sm " />
查看贴纸
</div>
<Tooltip
id="sticker-btn"
opacity={1}
className="flex flex-col items-center justify-center gap-2 rounded-lg !bg-gray-100 !p-4 shadow-lg shadow-gray-300
dark:!bg-gray-800 dark:text-gray-300 dark:shadow-lg dark:shadow-gray-700"
>
<div className="flex gap-2">
<img src={sticker1} alt="alipay" className=" h-44 rounded shadow-lg shadow-gray-300 dark:shadow-gray-700" />
<img src={sticker2} alt="alipay" className=" h-44 rounded shadow-lg shadow-gray-300 dark:shadow-gray-700" />
</div>
<span className="mt-3 text-xs font-bold text-gray-500">
<IconInfo className="mb-[3px] mr-1 inline-block" />
此贴纸非商品,仅用于感谢您的捐赠,不可用于任何商业用途
</span>
</Tooltip>
</>
)
}
50 changes: 50 additions & 0 deletions src/components/DonatingCard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { AmountImageMap } from './AmountQrMap'
import { Amount } from './components/Amount'
import { useEffect, useState } from 'react'

export type AmountType = -1 | 6 | 12 | 36 | 50 | 66
const displayAmount: AmountType[] = [6, 12, 36, 50, 66, -1]

export const DonatingCard = ({ className, onAmountChange }: { className?: string; onAmountChange?: (amount: AmountType) => void }) => {
const [amount, setAmount] = useState<AmountType | undefined>(undefined)

const onClickAmount = (amount: AmountType) => {
setAmount(amount)
}

useEffect(() => {
onAmountChange && amount && onAmountChange(amount as AmountType)
}, [amount, onAmountChange])

return (
<div className={`flex w-full flex-col items-center justify-center gap-3 ${className && className}`}>
<h2 className="self-start pl-10 font-bold text-gray-800 dark:text-gray-300">选择您的捐赠金额:</h2>
<div className="mt-2 flex gap-3">
{displayAmount.map((a) => {
return <Amount active={a === amount} key={a} amount={a} onClick={onClickAmount} />
})}
</div>

<div className={`mt-3 flex w-full flex-col overflow-hidden px-11 transition-[height] duration-500 ${amount ? 'h-44' : 'h-0'}`}>
{amount && (
<div className="flex w-full justify-between">
<img src={AmountImageMap[amount][0]} alt="alipay" className=" h-44" />
<img src={AmountImageMap[amount][1]} alt="weChat" className=" h-44" />
</div>
)}
</div>
{amount && (amount >= 50 || amount === -1) && (
<span>
<a
className="text-sm font-bold text-gray-500 underline-offset-4 hover:underline dark:text-gray-400"
href="https://wj.qq.com/s2/13329666/380d/"
target="_blank"
rel="noreferrer"
>
贴纸寄送地址问卷
</a>
</span>
)}
</div>
)
}
19 changes: 12 additions & 7 deletions src/components/Footer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import alipay from '@/assets/alipay.jpg'
import { DonatingCard } from '../DonatingCard'
import { StickerButton } from '../DonatingCard/components/StickerButton'
import redBookCode from '@/assets/redBook-code.jpg'
import weChat from '@/assets/weChat.jpg'
import InfoPanel from '@/components/InfoPanel'
import Tooltip from '@/components/Tooltip'
import { infoPanelStateAtom } from '@/store'
Expand Down Expand Up @@ -49,21 +49,26 @@ const Footer: React.FC = () => {
iconClassName="text-amber-500 bg-amber-100 dark:text-amber-300 dark:bg-amber-500"
onClose={() => handleCloseInfoPanel('donate')}
>
<p className="text-sm text-gray-500 dark:text-gray-300">
<p className="indent-4 text-sm text-gray-500 dark:text-gray-300">
非常感谢大家使用 Qwerty Learner,目前该网站使用业余时间在维护,为了保证网站能够持续地提供给大家高质量的服务,我们需要您的帮助!
<br />
您的捐款将有助于我们支付网站的运营成本,改进网站的功能和设计,并提高用户体验。
<br />
</p>
<br />
<p className="text-sm text-gray-700 dark:text-gray-200">
<p className="indent-4 text-sm text-gray-700 dark:text-gray-200">
我们相信,共同的努力可以让 Qwerty Learner 成为更好的学习平台,也相信您的支持将给予我们持续前进的动力。 感谢您的支持!
</p>
<br />
<div className="flex w-full justify-start">
<img src={alipay} alt="alipay" className="mx-4 w-1/3" />
<img src={weChat} alt="weChat" className="mx-4 w-1/3" />
<p className="indent-4 text-sm text-gray-700 dark:text-gray-200">
为了感谢您的慷慨,单次 50 rmb 及以上的捐赠, 我们将回赠 Qwerty 的定制贴纸 5 枚<span className="text-xs">(仅限大陆地区)</span>
,希望您可以跟朋友分享您的快乐
</p>
<div className="flex items-center justify-center py-2">
<StickerButton className="" />
</div>

<DonatingCard />
</InfoPanel>

<InfoPanel
Expand Down
2 changes: 1 addition & 1 deletion src/components/InfoPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const InfoPanel: React.FC<InfoPanelProps> = ({ openState, title, onClose, icon:
</div>
</div>
<div className="bg-gray-50 px-4 py-3 dark:bg-gray-700 sm:flex sm:flex-row-reverse sm:px-6">
<button type="button" className={classNames(buttonClassName, 'btn-info-panel')} onClick={() => onClose()}>
<button type="button" className={classNames(buttonClassName, 'my-btn-info-panel ')} onClick={() => onClose()}>
关闭
</button>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/utils/mixpanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export type donateCardInfo = {
sumWrongCount: number
dayFromFirstWord: number
dayFromQwerty: number
amount: number
}

export function reportDonateCard(info: donateCardInfo) {
Expand Down

1 comment on commit 8db4c58

@vercel
Copy link

@vercel vercel bot commented on 8db4c58 Oct 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.