Skip to content

Commit

Permalink
Merge branch 'feature/#32-front-layout' of https://github.com/Kumoh-t…
Browse files Browse the repository at this point in the history
…alk/kumoh-talk-Frontend into feature/#34-profile-image
  • Loading branch information
Jinoko01 committed Feb 10, 2025
2 parents 6b6820f + 454cd57 commit b32b8a8
Show file tree
Hide file tree
Showing 28 changed files with 813 additions and 350 deletions.
276 changes: 276 additions & 0 deletions src/app/api/[domain]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
import { NextRequest, NextResponse } from 'next/server';
import { getCookie, parseJwt } from '@/app/lib/apis/auth';
import { refreshToken } from '@/app/lib/apis/user';

const baseUrl = `${process.env.NEXT_PUBLIC_API_URL}/api/v1`;

const convertCookieToHeaders = (cookies: string | null): HeadersInit =>
cookies
? {
'Content-Type': 'application/json',
Authorization: `Bearer ${getCookie(cookies, 'accessToken')}`,
}
: {
'Content-Type': 'application/json',
};

const _fetch = async (
url: string,
options: RequestInit,
body?: string | any,
) => {
if (body && typeof body !== 'string') {
options.body = JSON.stringify(body);
}
return await fetch(url, options);
};

const refreshAndRetry = async (
request: NextRequest,
func: (request: NextRequest, params: any) => Promise<NextResponse>,
params: any,
accessToken?: string,
_refreshToken?: string,
) => {
if (!accessToken || !_refreshToken) {
return NextResponse.json({ status: 403 });
}

const newTokenRes = await refreshToken(accessToken, _refreshToken!);

if (newTokenRes.status === 200) {
const body = await newTokenRes.json();
const tokenBody: {
accessToken: string;
refreshToken: string;
} = body.data;

const res2 = await func(request, params);

res2.cookies.set('accessToken', tokenBody.accessToken, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
path: '/',
});
res2.cookies.set('refreshToken', tokenBody.refreshToken, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
path: '/',
});
return res2;
} else {
return NextResponse.json({ status: 403 });
}
};

export async function GET(
request: NextRequest,
{ params }: { params: { domain: string } },
): Promise<NextResponse> {
const cookies = request.headers.get('cookie');
const headers = convertCookieToHeaders(cookies);

const searchParams = request.nextUrl.searchParams;

if (cookies && getCookie(cookies, 'accessToken')) {
const accessToken = getCookie(cookies, 'accessToken')!;
const { USER_ID: userId } = parseJwt(accessToken);
searchParams.append('userId', '' + userId);
}
console.log(`${baseUrl}/${params.domain}?${searchParams.toString()}`)

const res = await _fetch(
`${baseUrl}/${params.domain}?${searchParams.toString()}`,
{
method: 'GET',
headers,
},
);
const body = await res.json();

// 토큰 만료
if (res.status === 401) {
console.log('Token expired, refreshing token');
return refreshAndRetry(
request,
GET,
{ params },
getCookie(cookies!, 'accessToken')!,
getCookie(cookies!, 'refreshToken')!,
);
}

return NextResponse.json(body, { status: res.status });
}

export async function POST(
request: NextRequest,
{ params }: { params: { domain: string } },
): Promise<NextResponse> {
const cookies = request.headers.get('cookie');
const headers = convertCookieToHeaders(cookies);

const searchParams = request.nextUrl.searchParams;

if (cookies && getCookie(cookies, 'accessToken')) {
const accessToken = getCookie(cookies, 'accessToken')!;
const { USER_ID: userId } = parseJwt(accessToken);
searchParams.append('userId', '' + userId);
}

const res = await _fetch(
`${baseUrl}/${params.domain}?${searchParams.toString()}`,
{
method: 'POST',
headers,
},
await request.json(),
);

// 토큰 만료
if (res.status === 401) {
console.log('Token expired, refreshing token');
return refreshAndRetry(
request,
POST,
{ params },
getCookie(cookies!, 'accessToken')!,
getCookie(cookies!, 'refreshToken')!,
);
}

return NextResponse.json(await res.json(), { status: res.status });
}

export async function PUT(
request: NextRequest,
{ params }: { params: { domain: string } },
): Promise<NextResponse> {
const cookies = request.headers.get('cookie');
const headers = convertCookieToHeaders(cookies);

const searchParams = request.nextUrl.searchParams;

if (cookies && getCookie(cookies, 'accessToken')) {
const accessToken = getCookie(cookies, 'accessToken')!;
const { USER_ID: userId } = parseJwt(accessToken);
searchParams.append('userId', '' + userId);
}

const res = await _fetch(
`${baseUrl}/${params.domain}?${searchParams.toString()}`,
{
method: 'PUT',
headers,
},
await request.json(),
);

// 토큰 만료
if (res.status === 401) {
console.log('Token expired, refreshing token');
return refreshAndRetry(
request,
PUT,
{ params },
getCookie(cookies!, 'accessToken')!,
getCookie(cookies!, 'refreshToken')!,
);
}

return NextResponse.json(await res.json(), { status: res.status });
}

export async function PATCH(
request: NextRequest,
{ params }: { params: { domain: string } },
): Promise<NextResponse> {
const cookies = request.headers.get('cookie');
const headers = convertCookieToHeaders(cookies);

const searchParams = request.nextUrl.searchParams;

if (cookies && getCookie(cookies, 'accessToken')) {
const accessToken = getCookie(cookies, 'accessToken')!;
const { USER_ID: userId } = parseJwt(accessToken);
searchParams.append('userId', '' + userId);
}

const res = await _fetch(
`${baseUrl}/${params.domain}?${searchParams.toString()}`,
{
method: 'PATCH',
headers,
},
await request.json(),
);

const resBody = await res.json();
console.log(res.status, resBody);

// 토큰 만료
if (res.status === 401) {
console.log('Token expired, refreshing token');
return refreshAndRetry(
request,
PATCH,
{ params },
getCookie(cookies!, 'accessToken')!,
getCookie(cookies!, 'refreshToken')!,
);
}

const response = NextResponse.json(resBody, { status: res.status });
if (resBody.data?.accessToken) {
response.cookies.set('accessToken', resBody.data.accessToken, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
path: '/',
});
response.cookies.set('refreshToken', resBody.data.refreshToken, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
path: '/',
});
}

return response;
}

export async function DELETE(
request: NextRequest,
{ params }: { params: { domain: string } },
): Promise<NextResponse> {
const cookies = request.headers.get('cookie');
const headers = convertCookieToHeaders(cookies);

const searchParams = request.nextUrl.searchParams;

if (cookies && getCookie(cookies, 'accessToken')) {
const accessToken = getCookie(cookies, 'accessToken')!;
const { USER_ID: userId } = parseJwt(accessToken);
searchParams.append('userId', '' + userId);
}

const res = await _fetch(
`${baseUrl}/${params.domain}?${searchParams.toString()}`,
{
method: 'DELETE',
headers,
},
);

// 토큰 만료
if (res.status === 401) {
console.log('Token expired, refreshing token');
return refreshAndRetry(
request,
DELETE,
{ params },
getCookie(cookies!, 'accessToken')!,
getCookie(cookies!, 'refreshToken')!,
);
}

return NextResponse.json(await res.json(), { status: res.status });
}
28 changes: 28 additions & 0 deletions src/app/assets/svg/SeminarCommentSvg.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export default function SeminarCommentSvg() {
return (
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M2.28334 15.6929H2.25478C2.02929 15.6921 1.81333 15.6018 1.65438 15.4418C1.49543 15.2819 1.40649 15.0654 1.40711 14.8399V14.7984C1.41275 14.7258 1.42576 14.6539 1.44595 14.5839L2.08179 12.2836C2.06532 12.236 2.04419 12.1902 2.01871 12.1468C2.00308 12.1208 1.98613 12.0956 1.96791 12.0714L1.94965 12.0455C1.17708 10.875 0.766001 9.5031 0.767614 8.10065C0.761637 6.18914 1.5097 4.3819 2.87435 3.01227C4.28515 1.59715 6.17607 0.817872 8.19914 0.817872C9.91504 0.817236 11.58 1.40088 12.92 2.47272C14.2302 3.52725 15.1406 4.99615 15.4829 6.61281C15.5884 7.10333 15.6419 7.60358 15.6426 8.10529C15.6426 10.0623 14.8909 11.9001 13.5259 13.281C12.1483 14.6739 10.2992 15.4412 8.31834 15.4412C7.61775 15.4412 6.72758 15.2632 6.30025 15.1424C5.77431 14.9949 5.26431 14.799 5.24306 14.7907C5.18597 14.7687 5.12529 14.7575 5.0641 14.7575C4.99773 14.7571 4.93197 14.7702 4.87086 14.7961L4.84396 14.8067L2.60408 15.6162C2.51066 15.6548 2.41212 15.6796 2.31156 15.6899L2.28334 15.6929ZM2.83019 11.4485C2.86771 11.4997 2.90324 11.5534 2.93578 11.6079L2.94009 11.6155C3.13201 11.9512 3.1931 12.2534 3.12205 12.512L2.5732 14.4976L4.47109 13.8126C4.84007 13.6617 5.25271 13.6571 5.6249 13.8C5.64515 13.8079 6.109 13.9866 6.58779 14.12C7.03504 14.2452 7.79406 14.3784 8.31967 14.3784C11.7728 14.3784 14.5814 11.5644 14.5814 8.10529C14.581 7.67806 14.5357 7.25205 14.4463 6.83428C13.836 3.9632 11.2097 1.88037 8.19914 1.88037C6.46062 1.88037 4.83666 2.54875 3.62707 3.76233C2.46297 4.93008 1.8248 6.47004 1.83011 8.09899C1.82878 9.28927 2.17648 10.4538 2.83019 11.4485Z"
fill="white"
/>
<path
d="M5.0176 9.31788C5.6044 9.31788 6.0801 8.84218 6.0801 8.25538C6.0801 7.66857 5.6044 7.19288 5.0176 7.19288C4.4308 7.19288 3.9551 7.66857 3.9551 8.25538C3.9551 8.84218 4.4308 9.31788 5.0176 9.31788Z"
fill="white"
/>
<path
d="M8.2051 9.31788C8.7919 9.31788 9.2676 8.84218 9.2676 8.25538C9.2676 7.66857 8.7919 7.19288 8.2051 7.19288C7.6183 7.19288 7.1426 7.66857 7.1426 8.25538C7.1426 8.84218 7.6183 9.31788 8.2051 9.31788Z"
fill="white"
/>
<path
d="M11.3926 9.31788C11.9794 9.31788 12.4551 8.84218 12.4551 8.25538C12.4551 7.66857 11.9794 7.19288 11.3926 7.19288C10.8058 7.19288 10.3301 7.66857 10.3301 8.25538C10.3301 8.84218 10.8058 9.31788 11.3926 9.31788Z"
fill="white"
/>
</svg>
);
}
Loading

0 comments on commit b32b8a8

Please sign in to comment.