Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] QA 피드백 일부 반영 #42

Merged
merged 9 commits into from
Jul 25, 2024
95 changes: 57 additions & 38 deletions apps/extension/components/PopupBox/PopupBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,71 +2,80 @@
/* eslint-disable jsx-a11y/click-events-have-key-events */
import { Button, SymbolLogo, Text, TypoLogo } from '@vook-client/design-system'
import { useQuery, useQueryClient } from '@tanstack/react-query'
import { useLayoutEffect, useState } from 'react'
import { useEffect, useLayoutEffect, useState } from 'react'
import { baseFetcher, userOptions, vocabularyOptions } from '@vook-client/api'

import { getStorage, removeStorage, setStorage } from '../../utils/storage'
import { getStorage, removeStorage } from '../../utils/storage'

import { PopupBoxContainer } from './PopupBox.styles'

import { SearchBox } from 'components/SearchBox'

export const PopupBox = () => {
const [login, setLogin] = useState<boolean>(false)
const [tokenDone, setTokenDone] = useState<boolean>(false)
const [hasToken, setHasToken] = useState<boolean>(false)
const [initializing, setInitializing] = useState<boolean>(false)
const [hasResult, setHasResult] = useState<boolean>(false)

const client = useQueryClient()

const userInfo = useQuery({
const userInfoQuery = useQuery({
...userOptions.userInfo(client),
enabled: tokenDone,
enabled: hasToken,
})
const vocabularyQuery = useQuery({

useQuery({
...vocabularyOptions.vocabularyInfo(client),
enabled: tokenDone,
enabled: userInfoQuery.isSuccess,
})

useLayoutEffect(() => {
baseFetcher.setUnAuthorizedHandler(() => {
removeStorage('vook-access')
removeStorage('vook-refresh')
setTokenDone(false)
})
}, [])

useLayoutEffect(() => {
const setToken = async () => {
const access = await getStorage<string>('vook-access')
const refresh = await getStorage<string>('vook-refresh')
const vookLogin = await getStorage<string>('vook-login')

if (!access || !refresh) {
setTokenDone(false)
return
}

if (!vookLogin) {
setTokenDone(false)
setLogin(false)
setHasToken(false)
setInitializing(true)
return
}

client.setQueryData(['access'], access)
client.setQueryData(['refresh'], refresh)
setTokenDone(true)

setInitializing(true)
setHasToken(true)
}

setToken()
}, [client])

useLayoutEffect(() => {
if (userInfo.isSuccess && userInfo.data) {
setStorage('vook-user', userInfo.data)
setStorage('vook-vocabulary', vocabularyQuery.data)
setLogin(true)
}
}, [userInfo.data, userInfo.isSuccess, vocabularyQuery.data])
useEffect(() => {
window.addEventListener(
'message',
(event: {
data: {
from: string
access: string
refresh: string
}
}) => {
if (
event.data.from === 'vook-web' &&
event.data.access &&
event.data.refresh
) {
setHasToken(true)
}
},
)
}, [])

const onClickLogin = () => {
window.open(
Expand All @@ -76,28 +85,23 @@ export const PopupBox = () => {
)
}

if (!initializing) {
return null
}

const userInfo = userInfoQuery.data?.result || null

return (
<PopupBoxContainer
style={{
width: hasResult ? '800px' : '450px',
}}
>
<Button
size="small"
filled={false}
onClick={() => {
removeStorage('vook-access')
removeStorage('vook-refresh')
setLogin(false)
}}
>
로그아웃
</Button>
<div className="logo">
<SymbolLogo size={24} />
<TypoLogo size="small" />
</div>
{!login && (
{!hasToken && (
<>
<Text type="body-1" fontWeight="medium">
주제별로 용어집을 관리하고, 간편하게 용어를 검색하세요
Expand All @@ -121,7 +125,22 @@ export const PopupBox = () => {
</Text>
</>
)}
{login && <SearchBox hasResult={hasResult} setHasResult={setHasResult} />}
{userInfo && hasToken && (
<>
<Button
size="small"
filled={false}
onClick={() => {
removeStorage('vook-access')
removeStorage('vook-refresh')
setHasToken(false)
}}
>
로그아웃
</Button>
<SearchBox hasResult={hasResult} setHasResult={setHasResult} />
</>
)}
</PopupBoxContainer>
)
}
24 changes: 21 additions & 3 deletions apps/extension/components/SearchBox/SearchBox.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Icon, SymbolLogo } from '@vook-client/design-system'
import { Icon, SymbolLogo, Text } from '@vook-client/design-system'
import { useEffect, useState } from 'react'
import { useQuery, useQueryClient } from '@tanstack/react-query'
import { searchQueryOptions, vocabularyOptions } from '@vook-client/api'
Expand All @@ -23,7 +23,7 @@ export const SearchBox = ({ hasResult, setHasResult }: SearchBoxProps) => {
const query = useQuery({
...searchQueryOptions.search(
{
query: text,
queries: text.split(' '),
highlightPostTag: '</strong>',
highlightPreTag: '<strong>',
withFormat: true,
Expand All @@ -36,7 +36,9 @@ export const SearchBox = ({ hasResult, setHasResult }: SearchBoxProps) => {
})

const onSubmit = () => {
query.refetch()
if (text.trim().length > 0) {
query.refetch()
}
}

useEffect(() => {
Expand Down Expand Up @@ -71,6 +73,22 @@ export const SearchBox = ({ hasResult, setHasResult }: SearchBoxProps) => {
{query.isSuccess && (
<TermList records={query.data.result.records || []} />
)}
{query.data?.result.records.reduce((acc, cur) => {
return (acc += cur.hits.length)
}, 0) === 0 && (
<Text
type="body-1"
color="semantic-label-alternative"
fontWeight="medium"
>
검색 결과가 없습니다.
</Text>
)}
{query.isError && (
<Text type="body-1" color="status-error" fontWeight="medium">
검색 중 에러가 발생하였습니다.
</Text>
)}
</S.SearchBoxInputBox>
</S.SearchBoxContainer>
)
Expand Down
83 changes: 48 additions & 35 deletions apps/extension/components/SearchWindow/SearchWindow.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Text } from '@vook-client/design-system'
import { useQuery, useQueryClient } from '@tanstack/react-query'
import { searchQueryOptions, vocabularyOptions } from '@vook-client/api'

import { useSelectedText, useToggle } from '../../store/toggle'

import { SearchWindowHeader } from './SearchWindowHeader'
import * as S from './SearchWindow.styles'

import { useSearch } from 'hooks/useSearch'
import { TermList } from 'components/TermList'
import {
BlankTermList,
Expand Down Expand Up @@ -51,52 +52,72 @@ export const SearchWindow = () => {
const { selectedText } = useSelectedText()
const { position } = useToggle()

const { query, headerText, tailText } = useSearch({
selectedText,
const client = useQueryClient()

const vocabularyQuery = useQuery({
...vocabularyOptions.vocabularyInfo(client),
})

const searchQuery = useQuery({
...searchQueryOptions.search(
{
queries: selectedText,
highlightPostTag: '</strong>',
highlightPreTag: '<strong>',
withFormat: true,
vocabularyUids:
vocabularyQuery.data?.result.map((item) => item.uid) || [],
},
client,
),
enabled: vocabularyQuery.isSuccess && selectedText.length <= 10,
})

if (selectedText.length > 30) {
const External = () => {
return (
<a
href={process.env.PLASMO_PUBLIC_WEB_DOMAIN}
onClick={() => {
window.open(process.env.PLASMO_PUBLIC_WEB_DOMAIN, '_blank')
}}
style={{
cursor: 'pointer',
}}
>
Vook 바로가기
<LinkExternalIcon />
</a>
)
}

if (selectedText.length > 10) {
return (
<S.SearchWindowBox className="vook-search-window" position={position}>
<SearchWindowHeader />
<S.SearchOverMaxLength>
<Text color="label-alternative" type="body-2" fontWeight="medium">
용어 검색은 30자 이내로만 가능합니다.
용어 검색은 10단어 이내로만 가능합니다.
</Text>
</S.SearchOverMaxLength>
<S.SearchWindowLink>
<a
href={process.env.PLASMO_PUBLIC_WEB_DOMAIN}
target="_blank"
rel="noreferrer"
>
Vook 바로가기
<LinkExternalIcon />
</a>
<External />
</S.SearchWindowLink>
</S.SearchWindowBox>
)
}

if (query.isLoading) {
if (searchQuery.isLoading) {
return (
<S.SearchWindowBox className="vook-search-window" position={position}>
<SearchWindowHeader tailText="검색 중..." />
<S.SearchWindowLink>
<a
href={process.env.PLASMO_PUBLIC_WEB_DOMAIN}
target="_blank"
rel="noreferrer"
>
Vook 바로가기
<LinkExternalIcon />
</a>
<External />
</S.SearchWindowLink>
</S.SearchWindowBox>
)
}

if (query.isError) {
if (vocabularyQuery.isError || searchQuery.isError) {
return (
<S.SearchWindowBox className="vook-search-window" position={position}>
<SearchWindowHeader />
Expand All @@ -120,8 +141,7 @@ export const SearchWindow = () => {
}

if (
query.isSuccess &&
query.data.result.records.reduce(
searchQuery.data?.result.records.reduce(
(acc, record) => record.hits.length + acc,
0,
) === 0
Expand All @@ -143,28 +163,21 @@ export const SearchWindow = () => {
</SearchWindowBlankButton>
</BlankTermList>
<S.SearchWindowLink>
<a
href={process.env.PLASMO_PUBLIC_WEB_DOMAIN}
target="_blank"
rel="noreferrer"
>
Vook 바로가기
<LinkExternalIcon />
</a>
<External />
</S.SearchWindowLink>
</S.SearchWindowBox>
)
}

return (
<S.SearchWindowBox className="vook-search-window" position={position}>
<SearchWindowHeader headerText={headerText} tailText={tailText} />
<SearchWindowHeader />
<div
style={{
width: '800px',
}}
>
<TermList records={query.data?.result.records || []} />
<TermList records={searchQuery.data?.result.records || []} />
</div>
<S.SearchWindowLink>
<a
Expand Down
4 changes: 3 additions & 1 deletion apps/extension/content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const getStyle = () => {
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: 3,
retry: 0,
},
},
})
Expand Down Expand Up @@ -91,8 +91,10 @@ function VookContentScript() {
await setStorage('vook-access', event.data.access)
await setStorage('vook-refresh', event.data.refresh)
await setStorage('vook-login', true)

queryClient.setQueryData(['access'], event.data.access)
queryClient.setQueryData(['refresh'], event.data.refresh)

postSuccessMessage()
}
},
Expand Down
Loading
Loading