diff --git a/package-lock.json b/package-lock.json
index d4903c29..31b71d05 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -23207,7 +23207,8 @@
},
"node_modules/react-hot-toast": {
"version": "2.4.1",
- "license": "MIT",
+ "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.1.tgz",
+ "integrity": "sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==",
"dependencies": {
"goober": "^2.1.10"
},
@@ -28384,6 +28385,7 @@
"react": "^18",
"react-dom": "^18",
"react-hook-form": "^7.52.1",
+ "react-hot-toast": "^2.4.1",
"react-secure-storage": "^1.3.2",
"react-slick": "^0.30.2",
"slick-carousel": "^1.8.1"
diff --git a/packages/client/app/(withLayout)/question/[id]/page.tsx b/packages/client/app/(withLayout)/question/[id]/page.tsx
index 0b264351..d679068f 100644
--- a/packages/client/app/(withLayout)/question/[id]/page.tsx
+++ b/packages/client/app/(withLayout)/question/[id]/page.tsx
@@ -1,5 +1,20 @@
+import { fetchMemberInformation, ssrConfig } from '@shared/api'
+import { QueryClient } from '@tanstack/react-query'
+import { cookies } from 'next/headers'
import { ClientQuestionDetailPage } from 'src/clientPages/questionDetail'
-export default function QuestionDetailPage() {
+export default async function QuestionDetailPage(d) {
+ const queryClient = new QueryClient()
+ const config = ssrConfig()
+
+ try {
+ const user = await queryClient.fetchQuery({
+ queryKey: [`/members/information`],
+ queryFn: () => fetchMemberInformation(config),
+ })
+ } catch (e) {
+ console.log(e)
+ }
+ // TODO: give userData by props to ClientQuestionDetailPage
return
}
diff --git a/packages/client/app/layout.tsx b/packages/client/app/layout.tsx
index 4a66563b..cd9c9d68 100644
--- a/packages/client/app/layout.tsx
+++ b/packages/client/app/layout.tsx
@@ -4,6 +4,7 @@ import './globals.css'
import localFont from 'next/font/local'
import './design-system-globals.css'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
+import { ToastPrepare } from '@gds/component'
import ReactQueryClientProviders from '../src/apps/provider/reactQueryProviders'
export const metadata: Metadata = {
@@ -53,6 +54,7 @@ export default function RootLayout({
+
{children}
{process.env.NODE_ENV !== 'production' && (
diff --git a/packages/client/next.config.mjs b/packages/client/next.config.mjs
index 22efc9ba..37eaec12 100644
--- a/packages/client/next.config.mjs
+++ b/packages/client/next.config.mjs
@@ -7,10 +7,12 @@ const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const withVanillaExtract = createVanillaExtractPlugin()
+const API_BASE_URL = process.env.API_BASE_URL
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
+ trailingSlash: true,
images: {
remotePatterns: [
{
@@ -19,6 +21,14 @@ const nextConfig = {
},
],
},
+ async rewrites() {
+ return [
+ {
+ source: '/api/:path*/',
+ destination: `${API_BASE_URL}/:path*/`,
+ },
+ ]
+ },
}
export default withVanillaExtract(nextConfig)
diff --git a/packages/client/package.json b/packages/client/package.json
index 374da341..73414e9d 100644
--- a/packages/client/package.json
+++ b/packages/client/package.json
@@ -21,7 +21,7 @@
"react": "^18",
"react-dom": "^18",
"react-hook-form": "^7.52.1",
- "react-secure-storage": "^1.3.2",
+ "react-hot-toast": "^2.4.1",
"react-slick": "^0.30.2",
"slick-carousel": "^1.8.1"
},
diff --git a/packages/client/src/clientPages/questionCreate/ui/ClientQuestionCreatePage.tsx b/packages/client/src/clientPages/questionCreate/ui/ClientQuestionCreatePage.tsx
index 7253f894..a61547d3 100644
--- a/packages/client/src/clientPages/questionCreate/ui/ClientQuestionCreatePage.tsx
+++ b/packages/client/src/clientPages/questionCreate/ui/ClientQuestionCreatePage.tsx
@@ -8,6 +8,7 @@ import { QuestionCreateInputs } from '@widgets/QuestionCreateInputs'
import { MainLoader } from '@shared/ui'
import { useState } from 'react'
import { useRouter } from 'next/navigation'
+import { Toast } from '@gds/component'
import { usePostQuestion } from '../api/auth'
export function ClientQuestionCreatePage() {
@@ -37,6 +38,16 @@ export function ClientQuestionCreatePage() {
form.reset()
setImageUrls([])
router.push('/home')
+ Toast.success({
+ title: '질문이 등록되었습니다.',
+ })
+ },
+ onError: (e) => {
+ Toast.error({
+ title:
+ e.response?.data?.message ||
+ '서버 오류가 발생했습니다. 다시 시도해주세요.',
+ })
},
},
)
diff --git a/packages/client/src/clientPages/questionDetail/ui/ClientQuestionDetailPage.tsx b/packages/client/src/clientPages/questionDetail/ui/ClientQuestionDetailPage.tsx
index 980ea1e2..28346fae 100644
--- a/packages/client/src/clientPages/questionDetail/ui/ClientQuestionDetailPage.tsx
+++ b/packages/client/src/clientPages/questionDetail/ui/ClientQuestionDetailPage.tsx
@@ -9,7 +9,7 @@ import {
import { useFetchMemberInformation } from '@shared/api'
import { useParams, useRouter } from 'next/navigation'
import { MainLoader } from '@shared/ui'
-import { useState } from 'react'
+import { Toast } from '@gds/component'
import { pageWrapper } from './style.css'
import {
useFetchQuestionPost,
@@ -22,10 +22,21 @@ export function ClientQuestionDetailPage() {
const params = useParams()
const router = useRouter()
- const { data: userData } = useFetchMemberInformation()
- const { data: questionData } = useFetchQuestionPost({
- questionPostId: Number(params.id),
- })
+ const {
+ data: userData,
+ isError: userDataIsError,
+ error: userDataError,
+ } = useFetchMemberInformation()
+ const {
+ data: questionData,
+ isError: questionDataIsError,
+ error: questionDataError,
+ } = useFetchQuestionPost(
+ {
+ questionPostId: Number(params.id),
+ },
+ { enabled: !!params.id },
+ )
const { mutate: createQuestionMeta } = usePostCreateQuestionMeta()
const { mutate: cancelQuestionMeta } = usePostCancelQuestionMeta()
const { mutate: createAnswer } = usePostAnswer()
@@ -36,6 +47,17 @@ export function ClientQuestionDetailPage() {
if (params.id === undefined) {
router.push('/home')
+ Toast.error({ title: '잘못된 접근 입니다.' })
+ } else if (userDataIsError) {
+ router.push('/home')
+ Toast.error({
+ title: userDataError?.message || '서버 오류가 발생했습니다.',
+ })
+ } else if (questionDataIsError) {
+ router.push('/home')
+ Toast.error({
+ title: questionDataError?.message || '서버 오류가 발생했습니다.',
+ })
}
return (
@@ -70,8 +92,9 @@ export function ClientQuestionDetailPage() {
registerAnswerRequest: { content: answer },
},
{
- onSuccess: () => {
- refetch()
+ onSuccess: async () => {
+ await refetch()
+ Toast.success({ title: '답변이 등록되었습니다.' })
},
},
)
diff --git a/packages/client/src/clientPages/signup/api/mail.ts b/packages/client/src/clientPages/signup/api/mail.ts
index b9cbfb27..2d810ab2 100644
--- a/packages/client/src/clientPages/signup/api/mail.ts
+++ b/packages/client/src/clientPages/signup/api/mail.ts
@@ -1,7 +1,7 @@
import { useMutation } from '@tanstack/react-query'
import { AuthCodeRequest, MailAPIApi, SendMailRequest } from '@server-api/api'
-import { getTmpAuthorizedConfig, config } from '@shared/api/config'
+import { config } from '@shared/api/config'
export const useSendVerificationCodeByEmail = () => {
return useMutation({
diff --git a/packages/client/src/clientPages/signup/ui/ClientSignupPage.tsx b/packages/client/src/clientPages/signup/ui/ClientSignupPage.tsx
index 3060d2d3..182ce5a0 100644
--- a/packages/client/src/clientPages/signup/ui/ClientSignupPage.tsx
+++ b/packages/client/src/clientPages/signup/ui/ClientSignupPage.tsx
@@ -8,6 +8,8 @@ import { SignupInputSection } from '@widgets/SignupInputs'
import { usePostMember } from '@shared/api'
import { useRouter } from 'next/navigation'
import { PageURL } from '@shared/model'
+import { useState } from 'react'
+import { color, Typo } from '@gds/token'
import * as styles from './style.css'
export function ClientSignupPage() {
@@ -22,6 +24,7 @@ export function ClientSignupPage() {
} = form.watch()
const { mutate: createMember, status } = usePostMember()
const router = useRouter()
+ const [submitError, setSubmitError] = useState(null)
return (
<>
@@ -30,6 +33,14 @@ export function ClientSignupPage() {
+
+ {submitError}
+