Skip to content

Commit

Permalink
Merge branch 'feat/#124' into feat/#71
Browse files Browse the repository at this point in the history
  • Loading branch information
lsy20140 committed Oct 9, 2024
2 parents ba874e6 + c4993b3 commit 7ade7f0
Show file tree
Hide file tree
Showing 21 changed files with 293 additions and 101 deletions.
9 changes: 9 additions & 0 deletions public/images/ability_chart.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions src/api/auth/skill/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { get } from '@/lib/axios'

// 유저 상위 퍼센트 조회
export async function getUserPrecedence() {
const res = await get<number>('/skill/precedence')
return res
}

export async function getUserAbility() {
const res = await get('/skill/ability')
return res
}
6 changes: 6 additions & 0 deletions src/api/quiz/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { get } from '@/lib/axios'

export async function getTodayParticipants() {
const res = await get<number>('/learnings/today/participants')
return res
}
6 changes: 6 additions & 0 deletions src/api/words/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ export async function getRecentWords() {
const res = await get<SuccessResponse<SimpleWordType[]>>('/words/recent')
return res.words
}

// 오늘의 용어 3개 조회
export async function getTodayWords() {
const res = await get<SuccessResponse<SimpleWordType[]>>('/words/todays')
return res.words
}
15 changes: 14 additions & 1 deletion src/app/google/callback/loading/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@ const LoginCallback = () => {
const router = useRouter()
const searchParams = useSearchParams()
const setAccessToken = useAuthStore((state) => state.setAccessToken)
const setUserId = useAuthStore((state) => state.setUserId)
const [role, setRole] = useState(searchParams.get('role'))

const accessToken = searchParams.get('accessToken')
const isSignUp = searchParams.get('isSignUp')
const userId = searchParams.get('id')

useEffect(() => {
if (role && accessToken) {
setAccessToken(accessToken)
setRole(role)
setUserId(Number(userId))
}

if (accessToken) {
Expand All @@ -29,7 +33,16 @@ const LoginCallback = () => {
router.push('/home/dictionary')
}
}
}, [role, accessToken, isSignUp, router, setAccessToken, setRole])
}, [
role,
accessToken,
isSignUp,
router,
setAccessToken,
setRole,
setUserId,
userId,
])

return <></>
}
Expand Down
36 changes: 31 additions & 5 deletions src/app/home/learning/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,40 @@
import { WordsList } from '@/components/domain/home/dictionary/RecentlyAddedWords/data'
import { getUserPrecedence } from '@/api/auth/skill'
import { getTodayParticipants } from '@/api/quiz'
import { getTodayWords } from '@/api/words'
import CommunicationStats from '@/components/domain/home/learning/CommunicationStats'
import TodayQuiz from '@/components/domain/home/learning/TodayQuiz'
import TodayWords from '@/components/domain/home/learning/TodayWords'
import {
HydrationBoundary,
QueryClient,
dehydrate,
} from '@tanstack/react-query'

export default async function LearningTab() {
const queryClient = new QueryClient()

await Promise.all([
queryClient.prefetchQuery({
queryKey: ['today', 'participants'],
queryFn: getTodayParticipants,
}),
queryClient.prefetchQuery({
queryKey: ['words', 'today'],
queryFn: getTodayWords,
}),
queryClient.prefetchQuery({
queryKey: ['skill', 'precedence'],
queryFn: getUserPrecedence,
}),
])

export default function LearningTab() {
return (
<div className="w-full my-12 flex flex-col items-center gap-[60px]">
<TodayQuiz todaySolvedCnt={50} />
<TodayWords wordsList={WordsList} />
<CommunicationStats />
<HydrationBoundary state={dehydrate(queryClient)}>
<TodayQuiz />
<TodayWords />
<CommunicationStats />
</HydrationBoundary>
</div>
)
}
4 changes: 2 additions & 2 deletions src/components/common/BottomSheet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ export default function BottomSheet({ children }: BottomSheetType) {
return (
<>
<div
className="w-full max-w-[430px] h-dvh fixed top-0 bg-background bg-opacity-50"
className="w-full max-w-[430px] h-dvh fixed top-0 bg-background bg-opacity-50 z-40"
onClick={closeBottomSheet}
/>
<div className="w-full max-w-[430px] fixed bottom-0 rounded-t-2xl py-7 px-6 bg-gray-700 text-onSurface-300">
<div className="w-full max-w-[430px] fixed bottom-0 rounded-t-2xl py-7 px-6 bg-gray-700 text-onSurface-300 z-50">
{children}
</div>
</>
Expand Down
10 changes: 8 additions & 2 deletions src/components/domain/home/Header/LoginButton.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { useRouter } from 'next/navigation'

export default function LoginButton() {
const router = useRouter()
return (
<>
<div className="px-2 py-1 font-medium text-sm bg-[#47D3AD] text-[#0E121B] rounded-[4px]">
<button
className="px-2 py-1 font-medium text-sm bg-[#47D3AD] text-[#0E121B] rounded-[4px]"
onClick={() => router.push('/')}
>
로그인
</div>
</button>
</>
)
}
13 changes: 7 additions & 6 deletions src/components/domain/home/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
'use client'
import Image from 'next/image'
import Link from 'next/link'
import LoginButton from './LoginButton'
import { useAuthStore } from '@/store/useAuthStore'

export default function Header() {
const isLoginUser = true
const { userId } = useAuthStore()

return (
<div className="flex justify-between items-center h-14 px-4 py-5">
Expand All @@ -12,18 +14,17 @@ export default function Header() {
<Link href={'/search'} className="text-white">
<Image width={24} height={24} src={'/icons/search.svg'} alt="검색" />
</Link>
{isLoginUser ? (
{userId ? (
<Link
href={'/mypage'}
className="relative w-[42px] h-[42px] rounded-full overflow-hidden"
>
{/* <Image
<Image
className="object-cover"
fill
src={'/images/logo.svg'}
src={'/images/logo.svg'} // user profile image로 변경필요
alt="마이페이지"
/> */}
<div className="w-[42px] h-[42px] rounded-full bg-gray-600" />
/>
</Link>
) : (
<LoginButton />
Expand Down
24 changes: 0 additions & 24 deletions src/components/domain/home/dictionary/RecentlyAddedWords/data.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ChartProgressBar from './ChartProgressBar'

type TotalChartProps = {
topPercent: number
topPercent: number | '??'
percent: number
}

Expand Down
21 changes: 14 additions & 7 deletions src/components/domain/home/learning/CommunicationStats/index.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,42 @@
'use client'
import { useGetPrecedence } from '@/hooks/auth/useGetSkill'
import CategoryChartItem from './CategoryChartItem'
import TotalChart from './TotalChart'
import { StatsInfo } from './data'
import { useAuthStore } from '@/store/useAuthStore'

export type Category = 'develop' | 'design' | 'business'
const categories: Category[] = ['develop', 'design', 'business']

export default function CommunicationStats() {
const { userId } = useAuthStore()
const { precedence } = useGetPrecedence()

return (
<>
<div className="w-full flex flex-col items-center text-onSurface-300 px-4">
<div className="w-full flex justify-between items-end mb-6">
<div>
<p className="text-h2 mb-3">나의 업무 소통 능력치 📊</p>
<p className="text-onSurface-200">
용어 퀴즈로 단어를 학습하고 <br />
소통 능력치를 높일 수 있어요.
{userId
? '용어 퀴즈로 단어를 학습하고 소통 능력치를 높일 수 있어요.'
: '로그인을 하고 나의 업무 소통\n능력치를 확인해보세요!'}
</p>
</div>
<TotalChart
topPercent={StatsInfo.topPercent}
percent={StatsInfo.totalPercent}
topPercent={userId ? ((precedence as number) ?? 100) : '??'}
percent={userId ? StatsInfo.totalPercent : 0}
/>
</div>
<div className="w-full flex justify-between gap-4 max-xs:flex-col">
{categories.map((category: Category, idx: number) => (
<CategoryChartItem
key={idx}
category={category}
percent={StatsInfo[category].percent}
cnt={StatsInfo[category].cnt}
totalCnt={StatsInfo[category].totalCnt}
percent={userId ? StatsInfo[category].percent : 0}
cnt={userId ? StatsInfo[category].cnt : 0}
totalCnt={userId ? StatsInfo[category].totalCnt : 0}
/>
))}
</div>
Expand Down
104 changes: 68 additions & 36 deletions src/components/domain/home/learning/TodayQuiz/index.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,80 @@
'use client'
import Button from '@/components/common/Button'
import LoginBottomSheet from '@/components/shared/LoginBottomSheet'
import { useGetTodayParticipants } from '@/hooks/quiz/useGetTodayParticipants'
import { useAuthStore } from '@/store/useAuthStore'
import useUIStore from '@/store/useUIStore'
import { getTodayDate } from '@/utils/date'
import Image from 'next/image'
import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { useEffect, useState } from 'react'

type TodayQuizProps = {
todaySolvedCnt: number
}
export default function TodayQuiz() {
const { participants } = useGetTodayParticipants()
const { userId } = useAuthStore()
const { bottomSheetType, openBottomSheet } = useUIStore()
const router = useRouter()
const [skipLogin, setSkipLogin] = useState<string | null>(null)
const [loginSheetType, setLoginSheetType] = useState<
'loginBtn' | 'learningTab'
>('loginBtn')

useEffect(() => {
if (typeof window === undefined) return
setSkipLogin(localStorage.getItem('skipLogin'))
if (!userId && skipLogin === 'false') {
openBottomSheet('login')
setLoginSheetType('learningTab')
}
}, [skipLogin, openBottomSheet, userId])

export default function TodayQuiz({ todaySolvedCnt }: TodayQuizProps) {
const handleClick = () => {
if (!userId) {
openBottomSheet('login')
setLoginSheetType('loginBtn')
return
}
router.push('/') // quiz url로 변경
}
return (
<div className="w-full px-4 text-onSurface-300 ">
<p className="text-h2 text-onSurface-300 mb-3">
<span className="text-primary-400">{getTodayDate() + ' '}</span>
용어 퀴즈💫
</p>
<div
className="w-full flex justify-between p-5 rounded-2xl"
style={{
backgroundImage:
'linear-gradient(120deg, #0FB -25.6%, #3D7DF3 31.25%, #6E32E6 86.98%)',
}}
>
<div className="flex flex-col justify-between text-onSurface-300">
<p className="text-h1 mb-2">용어 퀴즈</p>
<p className="mb-5">
오늘&nbsp;
<span className="text-primary-100 text-h3">{todaySolvedCnt}</span>
명이 퀴즈에
<br />
참여했어요.
</p>
<Link href={'#'}>
<Button type="black" width={36 * 4}>
<>
<div className="w-full px-4 text-onSurface-300 ">
<p className="text-h2 text-onSurface-300 mb-3">
<span className="text-primary-400">{getTodayDate() + ' '}</span>
용어 퀴즈💫
</p>
<div
className="w-full flex justify-between p-5 rounded-2xl"
style={{
backgroundImage:
'linear-gradient(120deg, #0FB -25.6%, #3D7DF3 31.25%, #6E32E6 86.98%)',
}}
>
<div className="flex flex-col justify-between text-onSurface-300">
<p className="text-h1 mb-2">용어 퀴즈</p>
<p className="mb-5">
오늘&nbsp;
<span className="text-primary-100 text-h3">{participants}</span>
명이 퀴즈에
<br />
참여했어요.
</p>
<Button type="black" width={36 * 4} onClick={handleClick}>
퀴즈 풀러 가기
</Button>
</Link>
</div>
<Image
alt="quiz_img"
src={'/images/home_quiz.svg'}
width={179}
height={166}
/>
</div>
<Image
alt="quiz_img"
src={'/images/home_quiz.svg'}
width={179}
height={166}
/>
</div>
</div>
<LoginBottomSheet
isOpen={bottomSheetType === 'login'}
type={loginSheetType}
/>
</>
)
}
Loading

0 comments on commit 7ade7f0

Please sign in to comment.