Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/icons/ver3/logo_ver3.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/app/_api/adminTopics/editAdminTopic.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import axiosInstance from '@/lib/axios/axiosInstance';
import axiosInstanceForAdmin from '@/lib/axios/axiosInstanceForAdmin';

import { editAdminTopicType } from '@/lib/types/requestedTopicType';

const editAdminTopic = async ({ topicId, isExposed, categoryCode, title }: editAdminTopicType) => {
await axiosInstance.put(`/admin/topics/${topicId}`, {
await axiosInstanceForAdmin.put(`/admin/topics/${topicId}`, {
isExposed,
categoryCode,
title,
Expand Down
4 changes: 2 additions & 2 deletions src/app/_api/adminTopics/getAdminTopics.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import axiosInstance from '@/lib/axios/axiosInstance';
import axiosInstanceForAdmin from '@/lib/axios/axiosInstanceForAdmin';

interface GetTopicsType {
cursorId?: number | null;
Expand All @@ -13,7 +13,7 @@ const getAdminTopics = async ({ cursorId }: GetTopicsType) => {
params.append('cursorId', cursorId.toString());
}

const response = await axiosInstance.get(`/admin/topics?${params.toString()}`);
const response = await axiosInstanceForAdmin.get(`/admin/topics?${params.toString()}`);

return response.data;
};
Expand Down
4 changes: 2 additions & 2 deletions src/app/_api/notice/createNotice.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import axiosInstance from '@/lib/axios/axiosInstance';
import axiosInstanceForAdmin from '@/lib/axios/axiosInstanceForAdmin';
import { NoticeCreateType } from '@/lib/types/noticeType';

interface ResponseType {
id: number;
}

const createNotice = async (data: NoticeCreateType) => {
const response = await axiosInstance.post<ResponseType>('/admin/notices', data);
const response = await axiosInstanceForAdmin.post<ResponseType>('/admin/notices', data);

return response.data;
};
Expand Down
4 changes: 2 additions & 2 deletions src/app/_api/notice/deleteNotice.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import axiosInstance from '@/lib/axios/axiosInstance';
import axiosInstanceForAdmin from '@/lib/axios/axiosInstanceForAdmin';

const deleteNotice = async (noticeId: number) => {
await axiosInstance.delete(`/admin/notices/${noticeId}`);
await axiosInstanceForAdmin.delete(`/admin/notices/${noticeId}`);
};

export default deleteNotice;
4 changes: 2 additions & 2 deletions src/app/_api/notice/getAdminNotices.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import axiosInstance from '@/lib/axios/axiosInstance';
import axiosInstanceForAdmin from '@/lib/axios/axiosInstanceForAdmin';
import { AdminNoticeType } from '@/lib/types/noticeType';

const getAdminNotices = async () => {
const result = await axiosInstance.get<AdminNoticeType[]>('/admin/notices');
const result = await axiosInstanceForAdmin.get<AdminNoticeType[]>('/admin/notices');

return result.data;
};
Expand Down
4 changes: 2 additions & 2 deletions src/app/_api/notice/sendNoticeAlarm.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import axiosInstance from '@/lib/axios/axiosInstance';
import axiosInstanceForAdmin from '@/lib/axios/axiosInstanceForAdmin';

const sendNoticeAlarm = async (noticeId: number) => {
await axiosInstance.post(`/admin/notices/${noticeId}/alarm`);
await axiosInstanceForAdmin.post(`/admin/notices/${noticeId}/alarm`);
};

export default sendNoticeAlarm;
4 changes: 2 additions & 2 deletions src/app/_api/notice/updateNotice.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import axiosInstance from '@/lib/axios/axiosInstance';
import axiosInstanceForAdmin from '@/lib/axios/axiosInstanceForAdmin';
import { NoticeCreateType } from '@/lib/types/noticeType';

interface UpdateNoticeRequestType {
Expand All @@ -7,7 +7,7 @@ interface UpdateNoticeRequestType {
}

const updateNotice = async ({ noticeData, noticeId }: UpdateNoticeRequestType) => {
await axiosInstance.put<ResponseType>(`/admin/notices/${noticeId}`, noticeData);
await axiosInstanceForAdmin.put<ResponseType>(`/admin/notices/${noticeId}`, noticeData);
};

export default updateNotice;
4 changes: 2 additions & 2 deletions src/app/_api/notice/updateNoticePublic.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import axiosInstance from '@/lib/axios/axiosInstance';
import axiosInstanceForAdmin from '@/lib/axios/axiosInstanceForAdmin';

const updateNoticePublic = async (noticeId: number) => {
await axiosInstance.patch(`/admin/notices/${noticeId}`);
await axiosInstanceForAdmin.patch(`/admin/notices/${noticeId}`);
};

export default updateNoticePublic;
6 changes: 3 additions & 3 deletions src/app/_api/notice/uploadNoticeImages.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import axios from 'axios';
import axiosInstance from '@/lib/axios/axiosInstance';
import axiosInstanceForAdmin from '@/lib/axios/axiosInstanceForAdmin';

interface UploadImageType {
order: number;
Expand All @@ -19,7 +19,7 @@ interface PresignedResponseType {

const uploadNoticeImages = async ({ noticeId, imageFileData, imageExtensionData }: UploadNoticeImagesProps) => {
// 1. Presigned url 발급 요청
const presignedResponse = await axiosInstance.post<PresignedResponseType[]>(
const presignedResponse = await axiosInstanceForAdmin.post<PresignedResponseType[]>(
`/admin/notices/${noticeId}/presigned-url`,
imageExtensionData
);
Expand All @@ -34,7 +34,7 @@ const uploadNoticeImages = async ({ noticeId, imageFileData, imageExtensionData
});

// 3. 이미지 업로드 완료 서버에 알림
await axiosInstance.post(`/admin/notices/${noticeId}/upload-complete`, imageExtensionData);
await axiosInstanceForAdmin.post(`/admin/notices/${noticeId}/upload-complete`, imageExtensionData);
};

export default uploadNoticeImages;
23 changes: 22 additions & 1 deletion src/app/admin/layout.css.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { style } from '@vanilla-extract/css';
import { Header } from '@/styles/font.css';
import { Header, Body } from '@/styles/font.css';
import { vars } from '@/styles/theme.css';

export const container = style({
Expand Down Expand Up @@ -28,3 +28,24 @@ export const title = style([
export const main = style({
flexGrow: 1,
});

export const page = style({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
minHeight: '100vh',
});

export const logout = style([
Body,
{
padding: '1rem 2rem',
backgroundColor: vars.color.bluegray6,
borderRadius: '0.8rem',
opacity: 0.6,

':hover': {
opacity: 1,
},
},
]);
53 changes: 38 additions & 15 deletions src/app/admin/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,53 @@
'use client';

import { usePathname } from 'next/navigation';
import { ReactNode } from 'react';

import * as styles from './layout.css';

import NavLinks from './_components/NavLinks';
import { removeCookie } from '@/lib/utils/cookie';

interface AdminNoticeLayoutProps {
children: ReactNode;
}

const HIDE_PATH = ['/admin', '/admin/login'];

export default function AdminNoticeLayout({ children }: AdminNoticeLayoutProps) {
const path = usePathname();
const isHideNav = path && HIDE_PATH.includes(path);

const handleClickLogout = () => {
removeCookie('admin-accessToken');
removeCookie('admin-refreshToken');

location.href = '/admin';
};

return (
<section className={styles.container}>
<div className={styles.nav}>
<h1 className={styles.title}>🤍 리스티웨이브 관리</h1>
<NavLinks
links={[
{
label: '요청 주제',
path: '/admin/topics',
},
{
label: '게시물',
path: '/admin/notice',
},
]}
/>
</div>
{!isHideNav && (
<div className={styles.nav}>
<h1 className={styles.title}>🤍 리스티웨이브 관리</h1>
<NavLinks
links={[
{
label: '요청 주제',
path: '/admin/topics',
},
{
label: '게시물',
path: '/admin/notice',
},
]}
/>
<button onClick={handleClickLogout} className={styles.logout}>
로그아웃
</button>
</div>
)}

<main className={styles.main}>{children}</main>
</section>
);
Expand Down
62 changes: 62 additions & 0 deletions src/app/admin/login/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
'use client';

import { useRouter } from 'next/navigation';
import { useForm } from 'react-hook-form';

import * as styles from './pgae.css';

import axiosInstance from '@/lib/axios/axiosInstance';
import { setCookie } from '@/lib/utils/cookie';

interface FormValuesType {
account: string;
password: string;
}

export default function AdminLogin() {
const router = useRouter();
const { register, handleSubmit } = useForm<FormValuesType>({
defaultValues: {
account: '',
password: '',
},
});

const onSubmit = async (values: FormValuesType) => {
try {
const { data } = await axiosInstance.post('/admin/login', values);

const adminAccessToken = data.accessToken;
const adminRefreshToken = data.refreshToken;

setCookie('admin-accessToken', adminAccessToken, 'AT');
setCookie('admin-refreshToken', adminRefreshToken, 'ADMIN');

router.push('/admin/topics');
} catch (error) {
console.log(error);
}
};
Comment on lines +25 to +39
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이제는 로그인의 달인이 되신 소현님...!!


return (
<div className={styles.page}>
<form onSubmit={handleSubmit(onSubmit)} className={styles.form}>
<div className={styles.field}>
<label htmlFor="account" className={styles.label}>
🐳 아이디
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐳🤍

</label>
<input id="account" required {...register('account')} className={styles.input} />
</div>
<div className={styles.field}>
<label htmlFor="password" className={styles.label}>
🍀 비밀번호
</label>
<input type="password" id="password" required {...register('password')} className={styles.input} />
</div>
<button type="submit" className={styles.button}>
로그인
</button>
</form>
</div>
);
}
67 changes: 67 additions & 0 deletions src/app/admin/login/pgae.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { style } from '@vanilla-extract/css';

import { vars } from '@/styles/theme.css';
import { BodyRegular } from '@/styles/font.css';

export const page = style({
width: '100%',
minHeight: '100vh',

display: 'flex',
justifyContent: 'center',
alignItems: 'center',
});

export const form = style({
padding: '2rem',

width: '100%',
maxWidth: '640px',

display: 'flex',
gap: '2.5rem',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
});

export const field = style({
width: '100%',

display: 'flex',
gap: '1rem',
flexDirection: 'column',
});

export const label = style({
fontSize: '2rem',
fontWeight: 500,
});

export const input = style([
BodyRegular,
{
padding: '1.2rem 2.4rem',
borderRadius: '0.8rem',
border: `1px solid ${vars.color.lightblue}`,

selectors: {
'&:focus': {
border: `1px solid ${vars.color.blue}`,
},
},
},
]);

export const button = style({
width: '100%',
padding: '1.5rem',
marginTop: '3rem',

fontSize: '2rem',
fontWeight: 500,

borderRadius: '0.8rem',
backgroundColor: vars.color.blue,
color: vars.color.white,
});
14 changes: 14 additions & 0 deletions src/app/admin/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Link from 'next/link';

import * as styles from './layout.css';
import Image from 'next/image';

export default function AdminPage() {
return (
<div className={styles.page}>
<Link href={`${process.env.NEXT_PUBLIC_SERVER_DOMAIN}/admin`}>
<Image alt="관리자페이지 로고" src="/icons/ver3/logo_ver3.0.png" width={200} height={170} />
</Link>
</div>
);
}
Loading
Loading