From 28c7286550ddc28ee8a2b285d5a24fff156f4bed Mon Sep 17 00:00:00 2001 From: lw Date: Fri, 24 May 2024 19:47:56 +0700 Subject: [PATCH] [UI] Update style for mission screen --- .../src/Popup/Home/Mission/TaskItem.tsx | 305 ++++++++++-------- .../src/Popup/Home/Mission/TaskList.tsx | 144 ++++----- .../src/Popup/Home/Mission/index.tsx | 168 +++++----- .../src/Popup/Home/index.tsx | 2 +- .../src/components/Games/GamePoint.tsx | 41 +++ .../src/components/Games/Logo.tsx | 58 ---- .../src/components/Games/index.ts | 1 + .../src/connector/booka/types.ts | 3 +- .../src/contexts/ThemeContext.tsx | 14 + packages/webapp/public/assets/reset.css | 38 +++ 10 files changed, 421 insertions(+), 353 deletions(-) create mode 100644 packages/extension-koni-ui/src/components/Games/GamePoint.tsx delete mode 100644 packages/extension-koni-ui/src/components/Games/Logo.tsx diff --git a/packages/extension-koni-ui/src/Popup/Home/Mission/TaskItem.tsx b/packages/extension-koni-ui/src/Popup/Home/Mission/TaskItem.tsx index e9e2432f30..cede784395 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Mission/TaskItem.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Mission/TaskItem.tsx @@ -2,16 +2,15 @@ // SPDX-License-Identifier: Apache-2.0 import { SWTransactionResponse } from '@subwallet/extension-base/services/transaction-service/types'; -import CountDown from '@subwallet/extension-koni-ui/components/Common/CountDown'; -import { GamePoint } from '@subwallet/extension-koni-ui/components/Games/Logo'; +import { GamePoint } from '@subwallet/extension-koni-ui/components'; import { BookaSdk } from '@subwallet/extension-koni-ui/connector/booka/sdk'; import { Task, TaskHistoryStatus } from '@subwallet/extension-koni-ui/connector/booka/types'; import { TelegramConnector } from '@subwallet/extension-koni-ui/connector/telegram'; import { useNotification, useSetCurrentPage, useTranslation } from '@subwallet/extension-koni-ui/hooks'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; -import { formatInteger } from '@subwallet/extension-koni-ui/utils'; +import { customFormatDate, formatInteger } from '@subwallet/extension-koni-ui/utils'; import { actionTaskOnChain } from '@subwallet/extension-koni-ui/utils/game/task'; -import { Button, Icon, Image, Typography } from '@subwallet/react-ui'; +import { Button, Icon, Image } from '@subwallet/react-ui'; import CN from 'classnames'; import { CheckCircle } from 'phosphor-react'; import React, { useCallback, useEffect, useState } from 'react'; @@ -24,7 +23,8 @@ type Props = { const apiSDK = BookaSdk.instance; const telegramConnector = TelegramConnector.instance; -const _TaskItem = ({ className, task, actionReloadPoint }: Props): React.ReactElement => { + +const _TaskItem = ({ actionReloadPoint, className, task }: Props): React.ReactElement => { useSetCurrentPage('/home/mission'); const notify = useNotification(); const [account, setAccount] = useState(apiSDK.account); @@ -53,7 +53,7 @@ const _TaskItem = ({ className, task, actionReloadPoint }: Props): React.ReactEl } return () => clearInterval(taskItemUpdaterInterval); - }, [checking]); + }, [actionReloadPoint, checking, task.taskHistoryId]); useEffect(() => { const accountSub = apiSDK.subscribeAccount().subscribe((data) => { @@ -65,71 +65,75 @@ const _TaskItem = ({ className, task, actionReloadPoint }: Props): React.ReactEl }; }, []); - const finishTask = useCallback(async () => { - const taskId = task.id; - const onChainType = task.onChainType; - const { address } = account?.info || {}; + const finishTask = useCallback(() => { + (async () => { + const taskId = task.id; + const onChainType = task.onChainType; + const { address } = account?.info || {}; - if (!address) { - return; - } + if (!address) { + return; + } - setTaskLoading(true); - let res: SWTransactionResponse | null = null; - const networkKey = 'alephTest'; + setTaskLoading(true); + let res: SWTransactionResponse | null = null; + const networkKey = 'alephTest'; - if (onChainType) { - const now = new Date(); - const date = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`; - const data = JSON.stringify({ address, type: onChainType, date }); + if (onChainType) { + const now = new Date(); + const date = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`; + const data = JSON.stringify({ address, type: onChainType, date }); - res = await actionTaskOnChain(onChainType, 'alephTest', address, data); + res = await actionTaskOnChain(onChainType, 'alephTest', address, data); - if ((res && res.errors.length > 0) || !res) { - setTaskLoading(false); - let message = t(`Network ${networkKey} not enable`); - if (res && res.errors.length > 0) { - const error = res?.errors[0] || {}; - // @ts-ignore - message = error?.message || ''; - } + if ((res && res.errors.length > 0) || !res) { + setTaskLoading(false); + let message = t(`Network ${networkKey} not enable`); - notify({ - message: message, - type: 'error' - }); + if (res && res.errors.length > 0) { + const error = res?.errors[0] || {}; - return; - } - } + // @ts-ignore + message = error?.message || ''; + } - let extrinsicHash = ''; + notify({ + message: message, + type: 'error' + }); - if (res) { - extrinsicHash = res.extrinsicHash || ''; - } + return; + } + } - apiSDK.finishTask(taskId, extrinsicHash, networkKey) - .finally(() => { - setTaskLoading(false); + let extrinsicHash = ''; - if (onChainType) { - setChecking(true); - } else { - setCompleted(true); - actionReloadPoint(); - } - }) - .catch(console.error); + if (res) { + extrinsicHash = res.extrinsicHash || ''; + } - setTimeout(() => { - task.url && telegramConnector.openLink(task.url); - }, 100); - }, [task.id, task.url]); + apiSDK.finishTask(taskId, extrinsicHash, networkKey) + .finally(() => { + setTaskLoading(false); + + if (onChainType) { + setChecking(true); + } else { + setCompleted(true); + actionReloadPoint(); + } + }) + .catch(console.error); + + setTimeout(() => { + task.url && telegramConnector.openLink(task.url); + }, 100); + })().catch(console.error); + }, [account?.info, actionReloadPoint, notify, t, task.id, task.onChainType, task.url]); const { endTime, isDisabled, - isEnd, isInTimeRange, + isInTimeRange, isNotStarted, startTime } = (() => { const now = Date.now(); @@ -145,118 +149,143 @@ const _TaskItem = ({ className, task, actionReloadPoint }: Props): React.ReactEl endTime, isNotStarted, isInTimeRange, + // @ts-ignore isEnd, isDisabled: isNotStarted || isEnd }; })(); - return
- -
- {task.name} - - + const renderTaskDate = () => { + const now = Date.now(); + + let content: string | undefined; + + if (isNotStarted && !!startTime && startTime < now) { + content = `${t('Begins at')} ${customFormatDate(startTime, '#hhhh#:#mm# - #DD#/#MM#/#YYYY#')}`; + } else if (isInTimeRange && !!endTime && endTime > now) { + content = `${t('Ends at')} ${customFormatDate(endTime, '#hhhh#:#mm# - #DD#/#MM#/#YYYY#')}`; + } + + if (content) { + return ( +
+ content +
+ ); + } + + return null; + }; + + return ( +
+
+ +
+ +
+
+
+ {task.name} +
+
+
+ + + {renderTaskDate()} +
+
+ +
+ {!completed && ( + + )} { - isNotStarted && !!startTime && ( - - ) - } - { - isInTimeRange && !!endTime && ( - ) } - { - isEnd && ({t('Ended')}) - } - +
- {!completed && !checking && } - {completed && !checking &&
; + ); }; const TaskItem = styled(_TaskItem)(({ theme: { extendToken, token } }: ThemeProps) => { - return { alignItems: 'center', + return { + alignItems: 'center', display: 'flex', - marginBottom: token.marginXS, padding: token.paddingSM, borderRadius: token.borderRadius, - backgroundColor: token.colorBgSecondary, '&.disabled': { opacity: 0.6 }, - '.task-banner': { - marginRight: token.marginSM + '.__mid-part': { + flex: 1 }, - '.task-title': { - flex: 1, + '.__task-banner': { + marginRight: token.marginXS + }, - '.__title': { - marginBottom: 0 - }, + '.__min-part-line-1': { - '.__sub-title': { - color: token.colorTextDark4 - } }, - '.play-button, .checked-button': { - marginLeft: token.marginSM + '.__min-part-line-2': { + display: 'flex', + alignItems: 'center' }, - '.checked-button': { - color: token.colorSuccess - } }; + '.__task-name': { + color: token.colorTextDark2, + fontWeight: token.headingFontWeight, + fontSize: token.fontSize, + lineHeight: token.lineHeight + }, + + '.__task-date': { + display: 'flex', + fontSize: 10, + lineHeight: '16px', + fontWeight: token.headingFontWeight, + color: token.colorTextDark3, + paddingLeft: token.paddingXS, + alignItems: 'center', + + '&:before': { + content: '""', + marginRight: token.marginXS, + backgroundColor: token.colorTextDark4, + height: 12, + width: 1 + } + } + }; }); export default TaskItem; diff --git a/packages/extension-koni-ui/src/Popup/Home/Mission/TaskList.tsx b/packages/extension-koni-ui/src/Popup/Home/Mission/TaskList.tsx index cfeec490cb..b922c33838 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Mission/TaskList.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Mission/TaskList.tsx @@ -5,107 +5,93 @@ import { TaskCategory, TaskCategoryInfo } from '@subwallet/extension-koni-ui/con import { useTranslation } from '@subwallet/extension-koni-ui/hooks'; import TaskItem from '@subwallet/extension-koni-ui/Popup/Home/Mission/TaskItem'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; -import { Button, Icon, Typography } from '@subwallet/react-ui'; -import { CaretLeft } from 'phosphor-react'; -import React, { useMemo } from 'react'; +import React from 'react'; import styled from 'styled-components'; type Props = ThemeProps & { - currentTaskCategory?: number; + taskCategoryMap: Record; taskCategoryInfoMap: Record; - onBackToCategoryList: VoidFunction; actionReloadPoint: VoidFunction; - taskCategory: TaskCategory | undefined; }; -const Component = ({ actionReloadPoint, className, currentTaskCategory, onBackToCategoryList, taskCategory, taskCategoryInfoMap }: Props): React.ReactElement => { +const Component = ({ actionReloadPoint, className, taskCategoryInfoMap, taskCategoryMap }: Props): React.ReactElement => { const { t } = useTranslation(); - const sortedTaskList = useMemo(() => { - const now = Date.now(); - - const taskList = currentTaskCategory ? taskCategoryInfoMap[currentTaskCategory]?.tasks || [] : []; - - return taskList.filter((task) => { - // Filter out the task that ended more than 1 day ago - if (!task.completedAt && task.endTime && new Date(task.endTime).getTime() < now) { - return false; - } else { - return true; - } - }) - .sort((a, b) => { - const aDisabled = ((a.startTime && new Date(a.startTime).getTime() > now) || (a.endTime && new Date(a.endTime).getTime() < now)); - const bDisabled = ((b.startTime && new Date(b.startTime).getTime() > now) || (b.endTime && new Date(b.endTime).getTime() < now)); - - if (aDisabled && !bDisabled) { - return 1; - } - - if (!aDisabled && bDisabled) { - return -1; - } - - if (a.status === 0 && b.status !== 0) { - return -1; - } - - if (a.status !== 0 && b.status === 0) { - return 1; - } - - return a.status - b.status; - }); - }, [currentTaskCategory, taskCategoryInfoMap]); - return (
-
-
- - {sortedTaskList.map((task) => ( - - ))} + { + Object.values(taskCategoryInfoMap).map((tci) => ( +
+
+
+ {taskCategoryMap[tci.id]?.name} +
+ +
+ {`${tci.completeCount}/${tci.tasks.length}`} {t('mission')} +
+
+
+ { + tci.tasks.map((t) => ( + + )) + } +
+
+ )) + }
); }; export const TaskList = styled(Component)(({ theme: { extendToken, token } }: ThemeProps) => { return { - '.__list-header': { + '.__task-category-item': { + marginBottom: token.marginXS + }, + + '.__tasks-container': { + backgroundColor: token.colorWhite, + borderRadius: 20, + paddingTop: token.paddingXXS, + paddingBottom: token.paddingXXS + }, + + '.__task-category-info': { + color: token.colorTextDark1, display: 'flex', - alignItems: 'center', - marginBottom: token.marginXS, + gap: token.sizeXS, + overflow: 'hidden', + paddingLeft: token.paddingSM, + paddingRight: token.paddingSM, + marginBottom: token.marginXS + }, - '.ant-typography': { - marginBottom: 0 - } + '.__task-category-name': { + fontSize: token.fontSizeLG, + flex: 1, + textOverflow: 'ellipsis', + overflow: 'hidden', + 'white-space': 'nowrap', + fontWeight: token.headingFontWeight }, - '.task-list': { - padding: token.padding, + '.__complete-missions': { + fontSize: token.fontSize, + lineHeight: token.lineHeight + }, - '.account-info': { - marginBottom: token.marginSM - } + '.__task-item + .__task-item': { + marginTop: token.marginXXS } }; }); diff --git a/packages/extension-koni-ui/src/Popup/Home/Mission/index.tsx b/packages/extension-koni-ui/src/Popup/Home/Mission/index.tsx index c5b018fc90..9c8cd51f99 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Mission/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Mission/index.tsx @@ -1,24 +1,28 @@ // Copyright 2019-2022 @subwallet/extension-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 -import GameAccount from '@subwallet/extension-koni-ui/components/Games/GameAccount'; +import { GameAccountBlock } from '@subwallet/extension-koni-ui/components'; import { BookaSdk } from '@subwallet/extension-koni-ui/connector/booka/sdk'; -import { Task, TaskCategory, TaskCategoryInfo } from '@subwallet/extension-koni-ui/connector/booka/types'; +import { EnergyConfig, Task, TaskCategory, TaskCategoryInfo, TaskHistoryStatus } from '@subwallet/extension-koni-ui/connector/booka/types'; +import { HomeContext } from '@subwallet/extension-koni-ui/contexts/screen/HomeContext'; import { useSetCurrentPage } from '@subwallet/extension-koni-ui/hooks'; import { TaskList } from '@subwallet/extension-koni-ui/Popup/Home/Mission/TaskList'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useContext, useEffect, useState } from 'react'; import styled from 'styled-components'; -import { TaskCategoryList } from './TaskCategoryList'; - type Props = ThemeProps; const apiSDK = BookaSdk.instance; -enum ViewMode { - CATEGORY_LIST = 'category_list', - TASK_LIST = 'task_list', +function getTaskCategoryMap (taskCategories: TaskCategory[]): Record { + const result: Record = {}; + + taskCategories.forEach((tc) => { + result[tc.id] = tc; + }); + + return result; } function getTaskCategoryInfoMap (tasks: Task[]): Record { @@ -33,26 +37,45 @@ function getTaskCategoryInfoMap (tasks: Task[]): Record { + tci.tasks.sort((a, b) => { + const aDisabled = ((a.startTime && new Date(a.startTime).getTime() > now) || (a.endTime && new Date(a.endTime).getTime() < now)); + const bDisabled = ((b.startTime && new Date(b.startTime).getTime() > now) || (b.endTime && new Date(b.endTime).getTime() < now)); - if (t.completedAt || t.status > 0) { - return; + if (aDisabled && !bDisabled) { + return 1; } - if (t.startTime && (now < new Date(t.startTime).getTime())) { - return; + if (!aDisabled && bDisabled) { + return -1; } - if (t.endTime && (now >= new Date(t.endTime).getTime())) { - return; + if (a.status === TaskHistoryStatus.COMPLETED && b.status !== TaskHistoryStatus.COMPLETED) { + return 1; } - result[t.categoryId].minPoint += (t.pointReward || 0); - } + if (a.status !== TaskHistoryStatus.COMPLETED && b.status === TaskHistoryStatus.COMPLETED) { + return -1; + } + + return 0; + }); }); return result; @@ -60,14 +83,12 @@ function getTaskCategoryInfoMap (tasks: Task[]): Record { useSetCurrentPage('/home/mission'); - const [taskCategoryList, setTaskCategoryList] = useState(apiSDK.taskCategoryList); - const [taskCategoryInfoMap, setTaskCategoryInfoMap] = useState>(getTaskCategoryInfoMap(apiSDK.taskList)); + const [taskCategoryMap, setTaskCategoryMap] = useState>({}); + const [taskCategoryInfoMap, setTaskCategoryInfoMap] = useState>({}); const [account, setAccount] = useState(apiSDK.account); - const [currentViewMode, setCurrentViewMode] = useState(ViewMode.CATEGORY_LIST); - const [currentTaskCategory, setCurrentTaskCategory] = useState(); - const [taskCategory, setTaskCategory] = useState(); + const [energyConfig, setEnergyConfig] = useState(apiSDK.energyConfig); const [reloadAccount, setReloadAccount] = useState(0); - const [point, setPoint] = useState(account?.attributes.point || 0); + const { setContainerClass } = useContext(HomeContext); const actionReloadPoint = useCallback(() => { setReloadAccount(reloadAccount + 1); @@ -76,17 +97,24 @@ const Component = ({ className }: Props): React.ReactElement => { useEffect(() => { const accountSub = apiSDK.subscribeAccount().subscribe((data) => { setAccount(data); - setPoint(data?.attributes.point || 0); + }); + + const energyConfigSub = apiSDK.subscribeEnergyConfig().subscribe((data) => { + setEnergyConfig(data); }); return () => { accountSub.unsubscribe(); + energyConfigSub.unsubscribe(); }; }, [reloadAccount]); useEffect(() => { + setTaskCategoryMap(getTaskCategoryMap(apiSDK.taskCategoryList)); + setTaskCategoryInfoMap(getTaskCategoryInfoMap(apiSDK.taskList)); + const taskCategoryListSub = apiSDK.subscribeTaskCategoryList().subscribe((data) => { - setTaskCategoryList(data); + setTaskCategoryMap(getTaskCategoryMap(data)); }); let taskListUpdaterInterval: NodeJS.Timer; @@ -108,61 +136,51 @@ const Component = ({ className }: Props): React.ReactElement => { }; }, []); - const onClickCategoryItem = useCallback((categoryId: number) => { - setCurrentViewMode(ViewMode.TASK_LIST); - setCurrentTaskCategory(categoryId); - setTaskCategory(taskCategoryList.find((tc) => tc.id === categoryId)); - }, []); - - const onBackToCategoryList = useCallback(() => { - setCurrentViewMode(ViewMode.CATEGORY_LIST); - setCurrentTaskCategory(undefined); - }, []); + useEffect(() => { + setContainerClass('mission-screen-wrapper'); - return
-
- {account && ( - { + setContainerClass(undefined); + }; + }, [setContainerClass]); + + return ( +
+
+ - )} - - { - currentViewMode === ViewMode.CATEGORY_LIST && ( - - ) - } +
- { - currentViewMode === ViewMode.TASK_LIST && ( - - ) - } +
+ +
-
; + ); }; const Mission = styled(Component)(({ theme: { extendToken, token } }: ThemeProps) => { return { - '.task-list': { - padding: token.padding, - - '.account-info': { - marginBottom: token.marginSM - } + overflow: 'hidden', + display: 'flex', + flexDirection: 'column', + + '.game-account-block-wrapper': { + paddingLeft: token.paddingXS, + paddingRight: token.paddingXS, + paddingBottom: token.paddingSM + }, + + '.task-list-container': { + paddingLeft: token.paddingXS, + paddingRight: token.paddingXS, + overflow: 'auto', + paddingBottom: 34 } }; }); diff --git a/packages/extension-koni-ui/src/Popup/Home/index.tsx b/packages/extension-koni-ui/src/Popup/Home/index.tsx index f2f8573563..4f1294d32d 100644 --- a/packages/extension-koni-ui/src/Popup/Home/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/index.tsx @@ -108,7 +108,7 @@ const Home = styled(Component)(({ theme: { token } }: Props) => { } }, - '&.game-screen-wrapper, &.invitation-screen-wrapper': { + '&.game-screen-wrapper, &.invitation-screen-wrapper, &.mission-screen-wrapper': { '.ant-sw-screen-layout-body': { paddingBottom: 56, diff --git a/packages/extension-koni-ui/src/components/Games/GamePoint.tsx b/packages/extension-koni-ui/src/components/Games/GamePoint.tsx new file mode 100644 index 0000000000..2778b8b085 --- /dev/null +++ b/packages/extension-koni-ui/src/components/Games/GamePoint.tsx @@ -0,0 +1,41 @@ +// Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import DefaultLogosMap from '@subwallet/extension-koni-ui/assets/logo'; +import { ThemeProps } from '@subwallet/extension-koni-ui/types'; +import React from 'react'; +import styled from 'styled-components'; + +type GamePointProps = ThemeProps & { + point: string; + size?: number; +}; + +function Component ({ className, point, size = 16 }: GamePointProps) { + return ( +
+ {point} + + {'token'} +
+ ); +} + +const GamePoint = styled(Component)(({ theme: { token } }: GamePointProps) => { + return ({ + display: 'flex', + gap: token.sizeXXS, + alignItems: 'center', + color: token.colorTextDark3, + fontSize: token.fontSize, + lineHeight: token.lineHeight + }); +}); + +export default GamePoint; diff --git a/packages/extension-koni-ui/src/components/Games/Logo.tsx b/packages/extension-koni-ui/src/components/Games/Logo.tsx deleted file mode 100644 index 9099e919d4..0000000000 --- a/packages/extension-koni-ui/src/components/Games/Logo.tsx +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors -// SPDX-License-Identifier: Apache-2.0 - -import { ThemeProps } from '@subwallet/extension-koni-ui/types'; -import { Image } from '@subwallet/react-ui'; -import React from 'react'; -import styled from 'styled-components'; - -type GameLogoProps = { - className?: string; - size?: number; -} - -type GamePointProps = ThemeProps & { - className?: string; - preText?: string; - text: string; - size?: number; -}; - -export function GameLogo ({ className, size = 24 }: GameLogoProps) { - return (); -} - -function _GamePoint ({ className, preText, size = 16, text }: GamePointProps) { - return
- {preText && {preText}} - - {text} -
; -} - -export const GamePoint = styled(_GamePoint)(({ theme: { token } }: GamePointProps) => { - return ({ - display: 'flex', - alignItems: 'center', - fontSize: '14px', - color: token.colorTextDark4, - - '.pre-text': { - marginRight: '3px' - }, - - '.game-point': { - marginRight: '3px' - } - }); -}); diff --git a/packages/extension-koni-ui/src/components/Games/index.ts b/packages/extension-koni-ui/src/components/Games/index.ts index c75decb26f..443196e68d 100644 --- a/packages/extension-koni-ui/src/components/Games/index.ts +++ b/packages/extension-koni-ui/src/components/Games/index.ts @@ -5,3 +5,4 @@ export { default as GameAccountAvatar } from './GameAccountAvatar'; export { default as GameAccountBlock } from './GameAccountBlock'; export { default as GameCardItem } from './GameCardItem'; export { default as GameEnergyBar } from './GameEnergyBar'; +export { default as GamePoint } from './GamePoint'; diff --git a/packages/extension-koni-ui/src/connector/booka/types.ts b/packages/extension-koni-ui/src/connector/booka/types.ts index 26ee744028..1a349ecefe 100644 --- a/packages/extension-koni-ui/src/connector/booka/types.ts +++ b/packages/extension-koni-ui/src/connector/booka/types.ts @@ -101,12 +101,11 @@ export interface TaskCategory { description?: string | null; icon?: string | null; active: boolean; - minPoint?: number; } export type TaskCategoryInfo = { id: number; - minPoint: number; + completeCount: number; tasks: Task[]; } diff --git a/packages/extension-koni-ui/src/contexts/ThemeContext.tsx b/packages/extension-koni-ui/src/contexts/ThemeContext.tsx index b8dc32c7c0..6ca6c6030f 100644 --- a/packages/extension-koni-ui/src/contexts/ThemeContext.tsx +++ b/packages/extension-koni-ui/src/contexts/ThemeContext.tsx @@ -419,6 +419,20 @@ const GlobalStyle = createGlobalStyle(({ theme }) => { '.ant-progress.ant-progress .ant-progress-bg': { backgroundColor: extendToken.colorBgSecondary2 + }, + + // background icon + + '.background-icon': { + '&.-primary-1': { + color: token.colorPrimary, + backgroundColor: extendToken.colorBgSecondary2 + }, + + '&.-primary-2': { + color: token.colorTextDark1, + backgroundColor: token.colorPrimary + } } }); }); diff --git a/packages/webapp/public/assets/reset.css b/packages/webapp/public/assets/reset.css index f7834f8750..6989d9b2b1 100644 --- a/packages/webapp/public/assets/reset.css +++ b/packages/webapp/public/assets/reset.css @@ -808,3 +808,41 @@ div.ant-notification-notice { .ant-btn.ant-btn > span + .anticon { margin-inline-start: 4px } + +/* icon */ +.background-icon { + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 100%; +} + +.background-icon.-size-1 { + font-size: 8px; + min-width: 12px; + height: 12px; +} + +.background-icon.-size-2 { + font-size: 10px; + min-width: 16px; + height: 16px; +} + +.background-icon.-size-3 { + font-size: 16px; + min-width: 24px; + height: 24px; +} + +.background-icon.-size-4 { + font-size: 20px; + min-width: 32px; + height: 32px; +} + +.background-icon.-size-5 { + font-size: 24px; + min-width: 40px; + height: 40px; +}