Skip to content

Commit 82a39a1

Browse files
authored
[25.05.20 / TASK-194] Hotfix - 프로덕션 환경 오류 수정 (#36)
1 parent f691edc commit 82a39a1

File tree

12 files changed

+154
-95
lines changed

12 files changed

+154
-95
lines changed

src/apis/instance.request.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,11 @@ export const instance = async <I, R>(
7575
return (data.body as unknown as SuccessType<R>).data;
7676
} catch (err: unknown) {
7777
const context = err as Response;
78-
if (location && !context.ok && context.status === 401) {
79-
window.location.replace('/');
78+
if (!context.ok && context.status === 401) {
79+
if (location) window.location.replace('/');
8080
return {} as never;
8181
}
82+
8283
setContext('Request', {
8384
path: context.url,
8485
status: context.status,

src/app/(auth-required)/components/QRCode.tsx

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,22 @@ export const QRCode = () => {
1313
const { data, isSuccess } = useQuery({ queryKey: [PATHS.QRLOGIN], queryFn: createQRToken });
1414

1515
return (
16-
<Layout title="QR 로그인" className="w-fit h-fit">
17-
{isSuccess ? (
18-
<QRCodeSVG
19-
value={`${env.BASE_URL}/api/qr-login?token=${data.token}`}
20-
width={width < SCREENS.MBI ? 140 : 181}
21-
height={width < SCREENS.MBI ? 140 : 181}
22-
enableBackground={0}
23-
bgColor={COLORS.BG.SUB}
24-
fgColor={COLORS.TEXT.MAIN}
25-
className="transition-all"
26-
/>
27-
) : (
28-
<div className="size-[180px] max-MBI:size-[140px] bg-BG-ALT" />
29-
)}
16+
<Layout title="QR 로그인">
17+
<div className="size-full flex items-center justify-center">
18+
{isSuccess ? (
19+
<QRCodeSVG
20+
value={`${env.BASE_URL}/api/qr-login?token=${data.token}`}
21+
width={width < SCREENS.MBI ? 140 : 181}
22+
height={width < SCREENS.MBI ? 140 : 181}
23+
enableBackground={0}
24+
bgColor={COLORS.BG.SUB}
25+
fgColor={COLORS.TEXT.MAIN}
26+
className="transition-all"
27+
/>
28+
) : (
29+
<div className="size-[180px] max-MBI:size-[140px] bg-BG-ALT" />
30+
)}
31+
</div>
3032
</Layout>
3133
);
3234
};

src/app/(auth-required)/components/header/Section.tsx

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { usePathname, useRouter } from 'next/navigation';
2-
import { startHolyLoader } from 'holy-loader';
1+
import { usePathname } from 'next/navigation';
2+
import Link from 'next/link';
33
import { Icon, NameType } from '@/components';
44
import { COLORS } from '@/constants';
55

@@ -38,17 +38,10 @@ export const Section = <T extends clickType>({
3838
icon,
3939
}: PropType<T>) => {
4040
const currentPath = usePathname();
41-
const { push } = useRouter();
4241

4342
if (clickType === 'link') {
4443
return (
45-
<div
46-
onClick={() => {
47-
startHolyLoader();
48-
push(action);
49-
}}
50-
className={`${defaultStyle} ${navigateStyle}`}
51-
>
44+
<Link href={action} className={`${defaultStyle} ${navigateStyle}`}>
5245
<Icon
5346
size={25}
5447
color={
@@ -61,7 +54,7 @@ export const Section = <T extends clickType>({
6154
>
6255
{children}
6356
</span>
64-
</div>
57+
</Link>
6558
);
6659
}
6760

src/app/(auth-required)/components/notice/Modal.tsx

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,29 @@ import { useQuery } from '@tanstack/react-query';
44
import { notiList } from '@/apis';
55
import { PATHS } from '@/constants';
66
import { Modal as Layout } from '@/components';
7+
import { convertDateToKST } from '@/utils/dateUtil';
78

89
export const Modal = () => {
910
const { data } = useQuery({ queryKey: [PATHS.NOTIS], queryFn: notiList });
1011

1112
return (
12-
<Layout title="공지사항" className="w-[800px] h-[500px] max-MBI:w-[450px] max-MBI:h-[200px]">
13-
{data?.posts?.map(({ content, created_at, id, title }) => (
14-
<div key={id} className="flex flex-col gap-2">
15-
<div className="flex items-center gap-3">
16-
<h3 className="text-TEXT-MAIN text-T4 max-MBI:text-T5">{title}</h3>
17-
<h4 className="text-TEXT-ALT text-T5 max-MBI:text-ST5">{created_at.split('T')[0]}</h4>
13+
<Layout title="공지사항" className="w-[800px] h-[500px]">
14+
<div className="flex flex-col w-full h-full overflow-auto gap-5">
15+
{data?.posts?.map(({ content, created_at, id, title }) => (
16+
<div key={id} className="flex flex-col gap-2">
17+
<div className="flex items-center gap-3">
18+
<h3 className="text-TEXT-MAIN text-T4 max-MBI:text-T5">{title}</h3>
19+
<h4 className="text-TEXT-ALT text-T5 max-MBI:text-ST5">
20+
{convertDateToKST(created_at)?.short}
21+
</h4>
22+
</div>
23+
<div
24+
className="text-TEXT-MAIN text-[14px] prose !max-w-full"
25+
dangerouslySetInnerHTML={{ __html: content }}
26+
/>
1827
</div>
19-
<div
20-
className="text-TEXT-MAIN text-I4 prose"
21-
dangerouslySetInnerHTML={{ __html: content }}
22-
/>
23-
</div>
24-
))}
28+
))}
29+
</div>
2530
</Layout>
2631
);
2732
};

src/app/(auth-required)/components/notice/index.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { useQuery } from '@tanstack/react-query';
55
import { notiList } from '@/apis';
66
import { PATHS } from '@/constants';
77
import { useModal } from '@/hooks/useModal';
8+
import { convertDateToKST } from '@/utils/dateUtil';
89
import { Modal } from './Modal';
910

1011
const DAY_IN_MS = 1000 * 60 * 60 * 24;
@@ -19,9 +20,11 @@ export const Notice = () => {
1920

2021
useEffect(() => {
2122
try {
22-
if (!data?.posts[0]) return;
23+
if (!data?.posts?.length) return;
2324

24-
const lastUpdated = new Date(data?.posts[0].created_at?.split('T')[0] as string).getTime();
25+
const lastUpdated = new Date(
26+
convertDateToKST(data?.posts[0].created_at)?.short as string,
27+
).getTime();
2528
const daysSinceUpdate = Math.ceil((new Date().getTime() - lastUpdated) / DAY_IN_MS);
2629

2730
if (daysSinceUpdate > RECENT_POST_THRESHOLD_DAYS) return;

src/app/(auth-required)/main/Content.tsx

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
'use client';
22

33
import { useInfiniteQuery, useQuery } from '@tanstack/react-query';
4-
import { useEffect } from 'react';
4+
import { useEffect, useMemo } from 'react';
55
import { useInView } from 'react-intersection-observer';
66
import { useSearchParam } from '@/hooks/useSearchParam';
77
import { Button, Dropdown, Check } from '@/components';
88
import { postList, postSummary } from '@/apis';
99
import { PATHS, SORT_TYPE } from '@/constants';
1010
import { SortKey, SortValue } from '@/types';
11-
import { convertDateToKST } from '@/utils';
11+
import { convertDateToKST } from '@/utils/dateUtil';
1212
import { Section, Summary } from './components';
1313

1414
const sorts: Array<[SortKey, SortValue]> = Object.entries(SORT_TYPE) as Array<[SortKey, SortValue]>;
@@ -22,7 +22,7 @@ export const Content = () => {
2222
const { ref, inView } = useInView();
2323

2424
const { data: posts, fetchNextPage } = useInfiniteQuery({
25-
queryKey: [PATHS.POSTS, [searchParams.asc, searchParams.sort]], // Query Key
25+
queryKey: [PATHS.POSTS, [searchParams.asc, searchParams.sort]],
2626
queryFn: async ({ pageParam = '' }) =>
2727
await postList(
2828
{ asc: searchParams.asc === 'true', sort: searchParams.sort || '' },
@@ -39,11 +39,17 @@ export const Content = () => {
3939
});
4040

4141
useEffect(() => {
42-
if (posts && posts.pages[posts.pages?.length - 1].nextCursor !== null && inView) {
43-
fetchNextPage();
44-
}
42+
const pages = posts?.pages;
43+
if (!pages?.length || !inView) return;
44+
45+
const hasNextCursor = pages[pages.length - 1].nextCursor !== null;
46+
if (!hasNextCursor) return;
47+
48+
fetchNextPage();
4549
}, [inView]);
4650

51+
const joinedPosts = useMemo(() => posts?.pages.flatMap((i) => i.posts), [posts]);
52+
4753
return (
4854
<div className="flex w-full h-full gap-[30px] max-MBI:flex-col max-TBL:gap-[20px] overflow-hidden">
4955
{summaries && <Summary {...summaries} />}
@@ -85,18 +91,9 @@ export const Content = () => {
8591
</div>
8692
</div>
8793
<div className="w-full h-full flex flex-col gap-[30px] relative max-TBL:gap-[20px] overflow-auto">
88-
{posts?.pages?.map((n) =>
89-
n.posts.map((i, j) =>
90-
j !== n?.posts.length - 1 ? (
91-
<Section key={i.id} {...i} />
92-
) : (
93-
<div className="relative" key={i.id}>
94-
<div ref={ref} className="absolute" />
95-
<Section {...i} />
96-
</div>
97-
),
98-
),
99-
)}
94+
{joinedPosts?.map((item, index, array) => (
95+
<Section key={item.id} ref={index === array.length - 1 ? ref : undefined} {...item} />
96+
))}
10097
</div>
10198
</div>
10299
</div>

src/app/(auth-required)/main/components/Section/Graph.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { Dropdown, Input } from '@/components';
1818
import { PostDetailValue } from '@/types';
1919
import { useResponsive } from '@/hooks';
2020
import { postDetail } from '@/apis';
21-
import { convertDateToKST } from '@/utils';
21+
import { convertDateToKST } from '@/utils/dateUtil';
2222

2323
ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend);
2424

src/app/(auth-required)/main/components/Section/index.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
'use client';
22

3-
import { useState } from 'react';
3+
import { ForwardedRef, forwardRef, useState } from 'react';
44
import { parseNumber } from '@/utils/numberUtil';
55
import { COLORS, env, PATHS } from '@/constants';
66
import { PostType, UserDto } from '@/types';
77
import { Icon } from '@/components';
88
import { getQueryClient } from '@/utils/queryUtil';
9-
import { convertDateToKST } from '@/utils';
9+
import { convertDateToKST } from '@/utils/dateUtil';
1010
import { Graph } from './Graph';
1111

12-
export const Section = (p: PostType) => {
12+
export const Section = forwardRef<HTMLElement, PostType>((p, ref) => {
1313
const [open, setOpen] = useState(false);
1414

1515
const username = (getQueryClient().getQueryData([PATHS.ME]) as Partial<UserDto>)?.username;
1616

1717
const url = `${env.VELOG_URL}/@${username}/${p.slug}`;
1818

1919
return (
20-
<section className="flex flex-col w-full h-fit relative">
20+
<section className="flex flex-col w-full h-fit relative" ref={ref}>
2121
<div
2222
className={`p-[25px] h-fit cursor-pointer bg-BG-SUB flex justify-between items-center gap-4 ${!open ? 'rounded-[4px] max-MBI:pb-[35px_!important]' : 'rounded-t-[4px]'} max-xl:flex-col max-MBI:flex-col max-MBI:p-[20px]`}
2323
onClick={() => setOpen((prev) => !prev)}
@@ -74,4 +74,4 @@ export const Section = (p: PostType) => {
7474
{open && <Graph id={p.id} releasedAt={p.releasedAt} />}
7575
</section>
7676
);
77-
};
77+
});
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { Line } from 'react-chartjs-2';
2+
import { Modal as Layout } from '@/components';
3+
import { COLORS } from '@/constants';
4+
5+
export const table = {
6+
totalViews: '전체 조회수 통계',
7+
totalLikes: '전체 좋아요 통계',
8+
totalPosts: '총 게시글 통계',
9+
};
10+
11+
const datasets = {
12+
backgroundColor: COLORS.TEXT.MAIN,
13+
borderColor: COLORS.PRIMARY.MAIN,
14+
};
15+
16+
const defaultData = {
17+
labels: [
18+
'2025-03-01',
19+
'2025-03-02',
20+
'2025-03-03',
21+
'2025-03-04',
22+
'2025-03-05',
23+
'2025-03-06',
24+
'2025-03-07',
25+
],
26+
datasets: [
27+
{
28+
label: 'Temp',
29+
data: [10, 11, 14, 23, 36, 50, 79],
30+
...datasets,
31+
},
32+
],
33+
};
34+
35+
export const Modal = ({ name }: { name: keyof typeof table }) => {
36+
return (
37+
<Layout title={table[name]} className="w-[1100px] h-fit max-TBL:w-[800px] transition-all">
38+
<Line
39+
data={defaultData}
40+
options={{
41+
responsive: true,
42+
maintainAspectRatio: false,
43+
animation: false,
44+
interaction: { mode: 'nearest', intersect: false },
45+
plugins: { legend: { display: false } },
46+
scales: {
47+
x: { axis: 'x', grid: { color: COLORS.BORDER.SUB }, ticks: { precision: 0 } },
48+
y: { axis: 'y', grid: { color: COLORS.BORDER.SUB }, ticks: { precision: 0 } },
49+
},
50+
}}
51+
className="w-full h-[auto_!important] max-h-[300px]"
52+
/>
53+
</Layout>
54+
);
55+
};
Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
1+
import { useModal } from '@/hooks';
12
import { parseNumber } from '@/utils/numberUtil';
3+
import { Modal, table } from './Modal';
24

35
interface IProp {
46
title: string;
57
content: number;
68
increasement?: number;
79
prefix?: string;
8-
id?: string;
10+
id: keyof typeof table;
911
}
1012

1113
const afterContent =
1214
'after:text-PRIMARY-SUB after:content-[attr(data-increasement)_"↑"] after:ml-2 after:text-ST3 max-TBL:after:text-ST4 transition-all';
1315

1416
export const SidebarContent = ({ title, content, increasement, prefix = '개', id }: IProp) => {
17+
const { open } = useModal();
18+
1519
return (
16-
<div className="flex flex-col items-center justify-center gap-[10px] bg-BG-SUB w-[375px] p-4 rounded-[4px] h-full max-TBL:w-[280px]">
20+
<div
21+
// onClick={() => open(<Modal name={id} />)}
22+
// className="flex flex-col items-center justify-center gap-[10px] bg-BG-SUB w-[375px] hover:bg-BG-ALT cursor-pointer transition-all duration-300 p-4 rounded-[4px] h-full max-TBL:w-[280px]"
23+
className="flex flex-col items-center justify-center gap-[10px] bg-BG-SUB w-[375px] duration-300 p-4 rounded-[4px] h-full max-TBL:w-[280px]"
24+
>
1725
<span className="text-TEXT-ALT text-T4 transition-all max-TBL:text-T5">{title}</span>
1826
<span
1927
className={`flex items-center text-TEXT-MAIN text-T1 transition-all max-TBL:text-T2 ${increasement && increasement !== 0 ? afterContent : ''}`}
@@ -22,6 +30,7 @@ export const SidebarContent = ({ title, content, increasement, prefix = '개', i
2230
>
2331
{parseNumber(content) + prefix}
2432
</span>
33+
{/* <span className="text-TEXT-ALT text-ST5">클릭해서 통계 그래프 보기</span> */}
2534
</div>
2635
);
2736
};

0 commit comments

Comments
 (0)