diff --git a/example/index.html b/example/index.html index 6aaaa9a..f8ae584 100644 --- a/example/index.html +++ b/example/index.html @@ -100,6 +100,11 @@

Notification

NFT Purchase Notification +
  • + + NFT Batch Purchase Notification + +
  • diff --git a/example/index.ts b/example/index.ts index 53682f9..bf288b8 100644 --- a/example/index.ts +++ b/example/index.ts @@ -17,6 +17,7 @@ import { getCreatorFollowPublishNewTemplate, getNFTNotificationTransferTemplate, getNFTNotificationPurchaseTemplate, + getNFTNotificationPurchaseMultipleTemplate, } from '../dist'; import { @@ -32,6 +33,7 @@ import { import { CreatorFollowConfirmationSampleData, CreatorFollowPublishNewSampleData, + NFTNotificationPurchaseMultipleSampleData, NFTNotificationPurchaseSampleData, NFTNotificationTransferSampleData, } from './data/nft'; @@ -168,6 +170,15 @@ handleRequest('/nft/notification/purchase', (req, res) => { res.send(subject.concat(body)); }); +handleRequest('/nft/notification/purchase-multiple', (req, res) => { + const { subject, body } = getNFTNotificationPurchaseMultipleTemplate({ + ...NFTNotificationPurchaseMultipleSampleData, + ...req.query, + ...req.body, + }); + res.send(subject.concat(body)); +}); + app.get('/', (_, res) => { res.sendFile(path.join(__dirname, 'index.html')); }); diff --git a/package.json b/package.json index 4eec0de..eec4579 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "7.1.0", + "version": "8.0.0-beta.4", "license": "GPL-3.0-or-later", "main": "dist/index.js", "typings": "dist/index.d.ts", diff --git a/src/assets/banners/cta-turn-story-into-collectible.jpg b/src/assets/banners/cta-turn-story-into-collectible.jpg new file mode 100644 index 0000000..96992cb Binary files /dev/null and b/src/assets/banners/cta-turn-story-into-collectible.jpg differ diff --git a/src/assets/icons/coin-insert.png b/src/assets/icons/coin-insert.png new file mode 100644 index 0000000..5594252 Binary files /dev/null and b/src/assets/icons/coin-insert.png differ diff --git a/src/components/cta-writing-nft.tsx b/src/components/cta-writing-nft.tsx index 7c4ae60..36acd14 100644 --- a/src/components/cta-writing-nft.tsx +++ b/src/components/cta-writing-nft.tsx @@ -1,15 +1,50 @@ import * as React from 'react'; +import { MjmlButton, MjmlColumn, MjmlImage, MjmlText } from 'mjml-react'; +import { FormattedMessage, useIntl } from 'react-intl'; -import { MjmlColumn, MjmlImage, MjmlText } from 'mjml-react'; +import { LIKER_LAND_ROOT } from '../constants'; +import * as Colors from '../constants/colors'; import { getAssetPath, wrapUtm } from '../utils/url'; import { BasicSection, BasicSectionProps } from './sections/basic'; -import { FormattedMessage, useIntl } from 'react-intl'; -export const WritingNFTCTASection = (props: BasicSectionProps) => { +export interface WritingNFTCTASectionProps extends BasicSectionProps { + isButton?: boolean; + likerID?: string; +} + +export const WritingNFTCTASection = ({ + isButton = false, + likerID, + ...props +}: WritingNFTCTASectionProps) => { const intl = useIntl(); - const bannerSrc = getAssetPath(`/banners/cta-writing-nft.jpg`); + const url = wrapUtm( + likerID ? `${LIKER_LAND_ROOT}/${likerID}` : `${LIKER_LAND_ROOT}/writing-nft` + ); + if (isButton) { + return ( + + + + + + + + ); + } + + const bannerSrc = getAssetPath( + `/banners/cta-turn-story-into-collectible.jpg` + ); return ( @@ -23,7 +58,7 @@ export const WritingNFTCTASection = (props: BasicSectionProps) => { { +export const NFTWidget = ({ + title, + coverImageSrc, + url, + priceLabel, + style, +}: NFTWidgetProps) => { return ( { width: '100%', borderRadius: 14, backgroundColor: '#ffffff', - border: `2px solid ${Colors.GreyD8}`, + border: `2px solid ${Colors.GreyEB}`, display: 'block', fontSize: 16, lineHeight: 1.5, + ...style, }} > @@ -69,6 +80,32 @@ export const NFTWidget = ({ title, coverImageSrc, url }: NFTWidgetProps) => { + {!!priceLabel && ( + + + + )}
    + + {priceLabel} +
    diff --git a/src/constants/colors.ts b/src/constants/colors.ts index 190dd1b..28e1172 100644 --- a/src/constants/colors.ts +++ b/src/constants/colors.ts @@ -6,6 +6,7 @@ export const PaleCyan = '#D7ECEC'; export const Grey4A = '#4a4a4a'; export const Grey9B = '#9b9b9b'; export const GreyD8 = '#d8d8d8'; +export const GreyEB = '#ebebeb'; export const GreyF7 = '#f7f7f7'; export const Green = '#36de00'; diff --git a/src/i18n/translations/cn.json b/src/i18n/translations/cn.json index b445c31..238a3ab 100644 --- a/src/i18n/translations/cn.json +++ b/src/i18n/translations/cn.json @@ -2,13 +2,16 @@ "cta.likecoin-button": "在文章中点击 LikeCoin button,可分配创作基金,额外奖励作者。", "cta.sponsor-link.banner.alt": "复制及分享你的赞助链结", "cta.sponsor-link.hint": "用这条链结建立你的粉丝团。详情", - "cta.writing-nft.title": "立即收集 Wrting NFT", + "cta.writing-nft.title": "立即收藏以表支持", "download": "下载:", "greeting": "你好 {name}:", "header.manage-delegation": "管理委託", "help.center.text": "帮助中心", "help.center.url": "https://docs.like.co/v/zh", "nft_notification_purchase_content": "BUYERLikeCoin 购入了你的作品 NFT_TITLE。", + "nft_notification_purchase_multiple_content": "恭喜!BUYERLIKE 购入了以下的作品:", + "nft_notification_purchase_multiple_subject": "你以 {price} LIKE 卖出了 {count} 份作品", + "nft_notification_purchase_multiple_title": "你以 {price} LIKE 卖出了 {count} 份作品", "nft_notification_purchase_subject": "你以 {price} LikeCoin 卖出了 {nftTitle}", "nft_notification_purchase_title": "你以 {price} LikeCoin 卖出了 {nftTitle}", "nft_notification_transfer_content": "SENDER 已赠你一份作品 NFT_TITLE。", diff --git a/src/i18n/translations/en.json b/src/i18n/translations/en.json index 3b7360f..b3e6683 100644 --- a/src/i18n/translations/en.json +++ b/src/i18n/translations/en.json @@ -2,13 +2,16 @@ "cta.likecoin-button": "Click the LikeCoin button in any articles, distribute Creators Fund to reward the creators.", "cta.sponsor-link.banner.alt": "Copy and share your sponsor link", "cta.sponsor-link.hint": "Build your fans group by this link. Learn more", - "cta.writing-nft.title": "Collect Writing NFT Now", + "cta.writing-nft.title": "Collect to support now", "download": "Download:", "greeting": "Dear {name}", "header.manage-delegation": "Manage delegation", "help.center.text": "Help Center", "help.center.url": "https://docs.like.co", "nft_notification_purchase_content": "BUYER has bought NFT_TITLE for LikeCoin.", + "nft_notification_purchase_multiple_content": "Congratulation! BUYER has collected your following works for LIKE:", + "nft_notification_purchase_multiple_subject": "You have sold {count} items for {price} LIKE", + "nft_notification_purchase_multiple_title": "You have sold {count} items for {price} LIKE", "nft_notification_purchase_subject": "You have sold {nftTitle} for {price} LikeCoin", "nft_notification_purchase_title": "You have sold {nftTitle} for {price} LikeCoin", "nft_notification_transfer_content": "SENDER has sent you a piece of creative work NFT_TITLE.", diff --git a/src/i18n/translations/zh.json b/src/i18n/translations/zh.json index b1b44b1..3a73b81 100644 --- a/src/i18n/translations/zh.json +++ b/src/i18n/translations/zh.json @@ -2,13 +2,16 @@ "cta.likecoin-button": "在文章中點擊 LikeCoin button,可分配創作基金,額外奬勵作者。", "cta.sponsor-link.banner.alt": "複製及分享你的贊助鏈結", "cta.sponsor-link.hint": "用這條鏈結建立你的粉絲團。詳情", - "cta.writing-nft.title": "立即收集 Wrting NFT", + "cta.writing-nft.title": "立即收藏以表支持", "download": "下載:", "greeting": "你好 {name}:", "header.manage-delegation": "管理委託", "help.center.text": "幫助中心", "help.center.url": "https://docs.like.co/v/zh", "nft_notification_purchase_content": "BUYERLikeCoin 購入了你的作品 NFT_TITLE。", + "nft_notification_purchase_multiple_content": "恭喜!BUYERLIKE 購入了以下的作品:", + "nft_notification_purchase_multiple_subject": "你以 {price} LIKE 賣出了 {count} 份作品", + "nft_notification_purchase_multiple_title": "你以 {price} LIKE 賣出了 {count} 份作品", "nft_notification_purchase_subject": "你以 {price} LikeCoin 賣出了 {nftTitle}", "nft_notification_purchase_title": "你以 {price} LikeCoin 賣出了 {nftTitle}", "nft_notification_transfer_content": "SENDER 已贈你一份作品 NFT_TITLE。", diff --git a/src/index.tsx b/src/index.tsx index aaed43a..398d618 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -56,6 +56,10 @@ import { NFTNotificationPurchaseTemplate, NFTNotificationPurchaseTemplateProps, } from './templates/nft/notification/purchase'; +import { + NFTNotificationPurchaseMultipleTemplate, + NFTNotificationPurchaseMultipleTemplateProps, +} from './templates/nft/notification/purchase-multiple'; export const getBasicTemplate = ( props: BasicTemplateProps, @@ -312,3 +316,27 @@ export const getNFTNotificationPurchaseTemplate = ( ); return { subject, body }; }; + +export const getNFTNotificationPurchaseMultipleTemplate = ( + props: NFTNotificationPurchaseMultipleTemplateProps, + options?: Mjml2HtmlOptions +) => { + const intl = initIntl(); + const { + subject = intl.formatMessage( + { id: 'nft_notification_purchase_multiple_subject' }, + { + price: formatNumber(props.totalPriceInLIKE), + count: props.purchasedItems.length, + } + ), + } = props; + const { html: body } = render( + , + { + minify: false, + ...options, + } + ); + return { subject, body }; +}; diff --git a/src/templates/nft/creator-follow/confirmation.tsx b/src/templates/nft/creator-follow/confirmation.tsx index 71c9e73..612df50 100644 --- a/src/templates/nft/creator-follow/confirmation.tsx +++ b/src/templates/nft/creator-follow/confirmation.tsx @@ -87,7 +87,11 @@ export const CreatorFollowConfirmationTemplate = ({
    - + ); diff --git a/src/templates/nft/default.tsx b/src/templates/nft/default.tsx index 5ae336a..806abe6 100644 --- a/src/templates/nft/default.tsx +++ b/src/templates/nft/default.tsx @@ -52,8 +52,8 @@ export const NFTDefaultTemplate = ({ {!message && ( )} - + - + ); diff --git a/src/templates/nft/notification/purchase-multiple.tsx b/src/templates/nft/notification/purchase-multiple.tsx new file mode 100644 index 0000000..c2edc85 --- /dev/null +++ b/src/templates/nft/notification/purchase-multiple.tsx @@ -0,0 +1,232 @@ +import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; +import { MjmlColumn, MjmlTable, MjmlText } from 'mjml-react'; + +import * as Colors from '../../../constants/colors'; +import { LIKER_LAND_ROOT } from '../../../constants'; + +import { Avatar } from '../../../components/avatar'; +import { WritingNFTCTASection } from '../../../components/cta-writing-nft'; +import { FooterSection } from '../../../components/footer'; +import { HeaderSection } from '../../../components/header'; +import { Link } from '../../../components/link'; +import { TemplateBase } from '../../../components/template-base'; +import { BasicSection } from '../../../components/sections/basic'; +import { NFTWidget } from '../../../components/nft-widget'; +import { TableRow } from '../../../components/table-row'; + +import { formatNumber } from '../../../utils/number'; +import { getAssetPath } from '../../../utils/url'; + +export interface NFTPurchaseItem { + title?: string; + coverImageSrc?: string; + url?: string; + priceInLIKE?: number; +} + +export interface NFTNotificationPurchaseMultipleTemplateProps { + subject?: string; + language?: string; + unsubscribeLink?: string; + + sellerLikerID?: string; + sellerDisplayName?: string; + sellerAvatarSrc?: string; + sellerIsCivicLiker?: boolean; + + buyerLikerID?: string; + buyerDisplayName?: string; + buyerAvatarSrc?: string; + buyerIsCivicLiker?: boolean; + buyerMessage?: string; + + purchasedItems: NFTPurchaseItem[]; + + totalPriceInLIKE?: number; +} + +const NUM_LARGE_DISPLAY_ITEMS = 3; + +export const NFTNotificationPurchaseMultipleTemplate = ({ + subject, + language, + unsubscribeLink, + + sellerDisplayName, + + buyerLikerID, + buyerDisplayName, + buyerAvatarSrc, + buyerIsCivicLiker, + buyerMessage, + + purchasedItems = [], + + totalPriceInLIKE, +}: NFTNotificationPurchaseMultipleTemplateProps) => { + const formattedTotalPrice = formatNumber(totalPriceInLIKE); + const largeDisplayItems = purchasedItems.slice(0, NUM_LARGE_DISPLAY_ITEMS); + const smallDisplayItems = purchasedItems.slice(NUM_LARGE_DISPLAY_ITEMS); + return ( + + + + + + + + + + + + + + + + ( + + {buyerDisplayName} + + ), + price: (unit: string) => ( + + {formattedTotalPrice} {unit} + + ), + }} + /> + + + + {!!buyerMessage && ( + + + + + {buyerMessage} + + + + )} + + + {largeDisplayItems.map((item, index) => { + const { title, coverImageSrc, url, priceInLIKE } = item; + return ( + 0 ? 24 : 0 }} + /> + ); + })} + + + {!!smallDisplayItems.length && ( + + + + {smallDisplayItems.map((item, i) => ( + + + + {item.title} + + + + + {item.title} + + + + + {item.priceInLIKE} + + + ))} + + + + )} + + + + ); +}; diff --git a/test/stub/nft.ts b/test/stub/nft.ts index f5dece1..348ab66 100644 --- a/test/stub/nft.ts +++ b/test/stub/nft.ts @@ -1,5 +1,6 @@ import { NFTNotificationTransferTemplateProps } from '../../dist/templates/nft/notification/transfer'; import { NFTNotificationPurchaseTemplateProps } from '../../dist/templates/nft/notification/purchase'; +import { NFTNotificationPurchaseMultipleTemplateProps } from '../../dist/templates/nft/notification/purchase-multiple'; import { CreatorFollowConfirmationTemplateProps } from '../../dist/templates/nft/creator-follow/confirmation'; import { CreatorFollowPublishNewTemplateProps } from '../../dist/templates/nft/creator-follow/publish-new'; @@ -12,6 +13,7 @@ import { SAMPLE_TEXT, SAMPLE_LIKEE_ID, SAMPLE_LIKEE_DISPLAY_NAME, + SAMPLE_NFT_IMAGE_URL, } from './samples'; export const CreatorFollowConfirmationSampleData: CreatorFollowConfirmationTemplateProps = { @@ -27,7 +29,7 @@ export const CreatorFollowConfirmationSampleData: CreatorFollowConfirmationTempl export const CreatorFollowPublishNewSampleData: CreatorFollowPublishNewTemplateProps = { ...CreatorFollowConfirmationSampleData, nftTitle: SAMPLE_TEXT, - nftCoverImageSrc: SAMPLE_IMAGE_URL, + nftCoverImageSrc: SAMPLE_NFT_IMAGE_URL, nftURL: SAMPLE_URL, }; @@ -38,7 +40,7 @@ export const NFTNotificationTransferSampleData: NFTNotificationTransferTemplateP senderAvatarSrc: SAMPLE_IMAGE_URL, senderIsCivicLiker: true, nftTitle: SAMPLE_TEXT, - nftCoverImageSrc: SAMPLE_IMAGE_URL, + nftCoverImageSrc: SAMPLE_NFT_IMAGE_URL, nftURL: SAMPLE_URL, message: SAMPLE_TEXT, }; @@ -51,7 +53,56 @@ export const NFTNotificationPurchaseSampleData: NFTNotificationPurchaseTemplateP buyerIsCivicLiker: true, priceInLIKE: 200000, nftTitle: SAMPLE_TEXT, - nftCoverImageSrc: SAMPLE_IMAGE_URL, + nftCoverImageSrc: SAMPLE_NFT_IMAGE_URL, nftURL: SAMPLE_URL, message: SAMPLE_TEXT, }; + +export const NFTNotificationPurchaseMultipleSampleData: NFTNotificationPurchaseMultipleTemplateProps = { + unsubscribeLink: SAMPLE_URL, + sellerDisplayName: SAMPLE_LIKER_DISPLAY_NAME, + buyerLikerID: SAMPLE_LIKEE_ID, + buyerDisplayName: SAMPLE_LIKEE_DISPLAY_NAME, + buyerAvatarSrc: SAMPLE_IMAGE_URL, + buyerIsCivicLiker: true, + buyerMessage: SAMPLE_TEXT, + purchasedItems: [ + { + title: SAMPLE_TEXT, + coverImageSrc: SAMPLE_NFT_IMAGE_URL, + url: SAMPLE_URL, + priceInLIKE: 2048, + }, + { + title: SAMPLE_TEXT, + coverImageSrc: SAMPLE_NFT_IMAGE_URL, + url: SAMPLE_URL, + priceInLIKE: 1024, + }, + { + title: SAMPLE_TEXT, + coverImageSrc: SAMPLE_NFT_IMAGE_URL, + url: SAMPLE_URL, + priceInLIKE: 64, + }, + { + title: SAMPLE_TEXT, + coverImageSrc: SAMPLE_NFT_IMAGE_URL, + url: SAMPLE_URL, + priceInLIKE: 32, + }, + { + title: SAMPLE_TEXT, + coverImageSrc: SAMPLE_NFT_IMAGE_URL, + url: SAMPLE_URL, + priceInLIKE: 16, + }, + { + title: SAMPLE_TEXT, + coverImageSrc: SAMPLE_NFT_IMAGE_URL, + url: SAMPLE_URL, + priceInLIKE: 8, + }, + ], + totalPriceInLIKE: 3192, +}; diff --git a/test/stub/samples.ts b/test/stub/samples.ts index 95c947b..c97e474 100644 --- a/test/stub/samples.ts +++ b/test/stub/samples.ts @@ -10,3 +10,4 @@ export const SAMPLE_TEXT = 'Lorem Ipsum'; export const SAMPLE_TIMESTAMP = 1609459860000; export const SAMPLE_URL = 'https://example.com'; export const SAMPLE_REMARK = 'likecoin remark'; +export const SAMPLE_NFT_IMAGE_URL = 'https://static.like.co/primitive-nft.jpg';