From 8489ea85fe0861f99b9820dd29b36e6046039778 Mon Sep 17 00:00:00 2001 From: jinhojang6 Date: Wed, 30 Oct 2024 00:50:01 +0900 Subject: [PATCH] feat: implement Collapse-related components --- apis/general/useGetEpochs.ts | 7 +- apis/general/useGetUserXP.ts | 7 +- public/icons/chevron-right-dark-purple.svg | 3 + .../Dashboard/OperatorPanel/OperatorPanel.tsx | 17 ++- .../Dashboard/ProgressBar/ProgressBar.tsx | 9 +- src/components/common/Collapse/Collapse.tsx | 37 +------ src/components/common/Collapse/CopyCode.tsx | 43 ++++++++ .../common/Collapse/EnterXPCode.tsx | 102 ++++++++++++++++++ .../Dashboard/DashboardContainer.tsx | 7 ++ 9 files changed, 190 insertions(+), 42 deletions(-) create mode 100644 public/icons/chevron-right-dark-purple.svg create mode 100644 src/components/common/Collapse/CopyCode.tsx create mode 100644 src/components/common/Collapse/EnterXPCode.tsx diff --git a/apis/general/useGetEpochs.ts b/apis/general/useGetEpochs.ts index d741c7ee5e..f4e1790e3b 100644 --- a/apis/general/useGetEpochs.ts +++ b/apis/general/useGetEpochs.ts @@ -11,7 +11,11 @@ export const fetchData = async () => { return await api.get('/epochs').then((res) => res.data) } -const useGetEpochs = () => { +interface Props { + enabled: boolean +} + +const useGetEpochs = ({ enabled }: Props) => { const queryKey = ['getEpochs'] const queryClient = useQueryClient() @@ -22,6 +26,7 @@ const useGetEpochs = () => { const response = useQuery({ queryKey: queryKey, queryFn: fetchData, + enabled, ...useQueryOptions, }) diff --git a/apis/general/useGetUserXP.ts b/apis/general/useGetUserXP.ts index 6e2a065723..4c7f5ec298 100644 --- a/apis/general/useGetUserXP.ts +++ b/apis/general/useGetUserXP.ts @@ -7,11 +7,15 @@ const useQueryOptions = { retry: 1, } +interface Props { + enabled: boolean +} + export const fetchData = async () => { return await api.get('/user/xp').then((res) => res.data) } -const useGetUserXP = () => { +const useGetUserXP = ({ enabled }: Props) => { const queryKey = ['getUserXP'] const queryClient = useQueryClient() @@ -22,6 +26,7 @@ const useGetUserXP = () => { const response = useQuery({ queryKey: queryKey, queryFn: fetchData, + enabled, ...useQueryOptions, }) diff --git a/public/icons/chevron-right-dark-purple.svg b/public/icons/chevron-right-dark-purple.svg new file mode 100644 index 0000000000..570de5a55e --- /dev/null +++ b/public/icons/chevron-right-dark-purple.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/Dashboard/OperatorPanel/OperatorPanel.tsx b/src/components/Dashboard/OperatorPanel/OperatorPanel.tsx index 264772c92b..c082be1ff2 100644 --- a/src/components/Dashboard/OperatorPanel/OperatorPanel.tsx +++ b/src/components/Dashboard/OperatorPanel/OperatorPanel.tsx @@ -1,3 +1,5 @@ +import CopyCode from '@/components/common/Collapse/CopyCode' +import EnterXPCode from '@/components/common/Collapse/EnterXPCode' import { breakpoints } from '@/configs/ui.configs' import { truncateString } from '@/utils/general.utils' import styled from '@emotion/styled' @@ -136,10 +138,10 @@ const OperatorPanel: React.FC = () => { */} - {/* */} + + + + ) } @@ -160,6 +162,13 @@ const Profile = styled.div` } ` +const CollapseContainer = styled.div` + display: flex; + flex-direction: column; + gap: 2px; + margin-top: 24px; +` + const OperatorImage = styled.img` width: 100%; aspect-ratio: 1; diff --git a/src/components/Dashboard/ProgressBar/ProgressBar.tsx b/src/components/Dashboard/ProgressBar/ProgressBar.tsx index ae146c4429..c206034457 100644 --- a/src/components/Dashboard/ProgressBar/ProgressBar.tsx +++ b/src/components/Dashboard/ProgressBar/ProgressBar.tsx @@ -4,7 +4,6 @@ import styled from '@emotion/styled' import { useAtomValue } from 'jotai' import React from 'react' import useGetEpochs from '../../../../apis/general/useGetEpochs' -import useGetUserXP from '../../../../apis/general/useGetUserXP' import { userInfoAtom } from '../../../../atoms/userInfo' interface ProgressBarProps { @@ -16,10 +15,12 @@ const ProgressBar: React.FC = ({ progress = 0, claimPosition = 76, }) => { - const { data: epochs } = useGetEpochs() - const { data: userXP } = useGetUserXP() - console.log('userXP', userXP) const user = useAtomValue(userInfoAtom) + + const { data: epochs } = useGetEpochs({ + enabled: user?.address?.length > 0, + }) + // const { data: currentBlock } = useGetCurrentBTCBlock() // const { data: pillars } = useGetPillars() diff --git a/src/components/common/Collapse/Collapse.tsx b/src/components/common/Collapse/Collapse.tsx index 9613ea1faf..234a38c2ac 100644 --- a/src/components/common/Collapse/Collapse.tsx +++ b/src/components/common/Collapse/Collapse.tsx @@ -3,26 +3,16 @@ import React, { useState } from 'react' interface CollapsibleProps { header: string - content: string - enableCopy?: boolean + children: React.ReactNode } -const Collapse: React.FC = ({ - header, - content, - enableCopy = true, -}) => { +const Collapse: React.FC = ({ header, children }) => { const [isOpen, setIsOpen] = useState(false) const toggleOpen = () => { setIsOpen(!isOpen) } - const copyToClipboard = () => { - navigator.clipboard.writeText(content) - alert('Copied to clipboard!') - } - return (
@@ -35,14 +25,7 @@ const Collapse: React.FC = ({ )}
- - {content} - {enableCopy && ( - - file copy - - )} - + {children}
) } @@ -50,7 +33,6 @@ const Collapse: React.FC = ({ const Container = styled.div` background-color: #320430; border-radius: 8px; - margin: 10px 0; color: #f29ae9; cursor: pointer; ` @@ -70,23 +52,14 @@ const Body = styled.div<{ isOpen: boolean }>` max-height: ${({ isOpen }) => (isOpen ? '100px' : '0')}; overflow: hidden; transition: max-height 0.3s ease; - background-color: #320430; - padding: 20px 16px 20px 8px; + background-color: #260324; + padding: 16px 8px; font-size: 14px; line-height: 20px; color: #f29ae9; letter-spacing: 0.14px; ` -const CopyButton = styled.button` - background: none; - border: none; - color: #f29ae9; - cursor: pointer; - font-size: 14px; - margin-left: 10px; -` - const Chevron = styled.span<{ isExpanded: boolean }>` display: inline-flex; transition: transform 0.3s ease; diff --git a/src/components/common/Collapse/CopyCode.tsx b/src/components/common/Collapse/CopyCode.tsx new file mode 100644 index 0000000000..4983de49c3 --- /dev/null +++ b/src/components/common/Collapse/CopyCode.tsx @@ -0,0 +1,43 @@ +import styled from '@emotion/styled' +import React from 'react' +import Collapse from './Collapse' + +const CopyCode: React.FC = () => { + const content = '445f5..4645sdf54' + + const copyToClipboard = () => { + navigator.clipboard.writeText(content) + alert('Copied to clipboard!') + } + + return ( + + +
{content}
+ + file copy + +
+
+ ) +} + +const CopyButton = styled.button` + background: none; + border: none; + color: #f29ae9; + cursor: pointer; + font-size: 14px; + margin-left: 10px; +` + +const Wrapper = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + width: 100%; + height: 28px; +` + +export default CopyCode diff --git a/src/components/common/Collapse/EnterXPCode.tsx b/src/components/common/Collapse/EnterXPCode.tsx new file mode 100644 index 0000000000..6fc79f3e95 --- /dev/null +++ b/src/components/common/Collapse/EnterXPCode.tsx @@ -0,0 +1,102 @@ +import styled from '@emotion/styled' +import React, { useState } from 'react' +import { api } from '../../../../common/api' +import Collapse from './Collapse' + +const EnterXPCode: React.FC = () => { + const [code, setCode] = useState('') + const [message, setMessage] = useState(null) + const [isSuccess, setIsSuccess] = useState(true) + + const handleChange = (e: React.ChangeEvent) => { + setCode(e.target.value) + } + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault() + + api + .post('/user/exit-code', { exit_code: code }) + .then((res) => { + setMessage(res.data.message) + setIsSuccess(true) + }) + .catch((err) => { + console.log(err) + setMessage(err.message || 'Something went wrong') + setIsSuccess(false) + }) + } + + return ( + + +
+ + +
+ {message && {message}} +
+
+ ) +} + +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 16px; + + width: 100%; +` + +const Form = styled.form` + display: flex; + width: 100%; + + button { + display: flex; + width: 40px; + height: 40px; + padding: 13px; + justify-content: center; + align-items: center; + border: none; + background: #f29ae9; + box-sizing: border-box; + cursor: pointer; + } +` + +const Input = styled.input` + color: #f29ae9; + width: 100%; + font-size: 14px; + line-height: 20px; + letter-spacing: 0.14px; + height: 40px; + padding: 10px 14px; + background: transparent; + border: none; + border-bottom: 1px solid #f29ae9; + + &::placeholder { + color: #f29ae9; + opacity: 0.5; + } + + &:focus { + outline: none; + } +` + +const Message = styled.span<{ isSuccess: boolean }>` + color: ${({ isSuccess }) => (isSuccess ? '#8FFFB6' : '#F26969')}; + font-size: 12px; + line-height: 16px; + letter-spacing: 0.12px; + opacity: 0.6; +` + +export default EnterXPCode diff --git a/src/containers/Dashboard/DashboardContainer.tsx b/src/containers/Dashboard/DashboardContainer.tsx index c6f8f24bda..477cdf0d32 100644 --- a/src/containers/Dashboard/DashboardContainer.tsx +++ b/src/containers/Dashboard/DashboardContainer.tsx @@ -5,6 +5,7 @@ import { breakpoints } from '@/configs/ui.configs' import styled from '@emotion/styled' import { useAtom, useSetAtom } from 'jotai' import React, { useEffect } from 'react' +import useGetUserXP from '../../../apis/general/useGetUserXP' import useGetUserInfo from '../../../apis/operators/useGetUserInfo' import { userInfoAtom } from '../../../atoms/userInfo' import { walletAddressAtom } from '../../../atoms/wallet' @@ -43,6 +44,12 @@ const DashboardContainer: React.FC = ({ const processedOperators = processMyOperators(userInfoData?.operators) + const { data: userXP } = useGetUserXP({ + enabled: !!walletAddress && walletAddress.length > 0, + }) + + // console.log('userXP', userXP) + return (