Skip to content

Commit

Permalink
Merge pull request #403 from Bamdoliro/develop
Browse files Browse the repository at this point in the history
Release - user v1.0.6
  • Loading branch information
SEOKKAMONI authored Sep 18, 2023
2 parents 8093024 + ca02cf5 commit 52dbcf1
Show file tree
Hide file tree
Showing 116 changed files with 1,804 additions and 442 deletions.
4 changes: 3 additions & 1 deletion apps/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@
"axios": "^1.4.0",
"next": "13.4.6",
"react": "18.2.0",
"react-dom": "18.2.0"
"react-dom": "18.2.0",
"react-toastify": "^9.1.3",
"recoil": "^0.7.7"
},
"msw": {
"workerDirectory": "public"
Expand Down
1 change: 1 addition & 0 deletions apps/admin/public/svg/logo_black.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions apps/admin/src/apis/storage/storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
type LocalStorageKey = 'access-token' | 'refresh-token';
export class Storage {
static getItem(key: LocalStorageKey) {
return typeof window !== 'undefined' ? localStorage.getItem(key) : null;
}

static setItem(key: LocalStorageKey, value: string) {
if (typeof window === 'undefined') return;
localStorage.setItem(key, value);
}
}
2 changes: 2 additions & 0 deletions apps/admin/src/apis/token/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as refreshToken } from './refresh';
export { default as authorization } from './token';
20 changes: 20 additions & 0 deletions apps/admin/src/apis/token/refresh.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ROUTES, TOKEN } from '@/constants/common/constant';
import { maru } from '../instance/instance';
import { Storage } from '../storage/storage';

const refreshToken = async () => {
try {
const { data } = await maru.patch('/auth', null, {
headers: {
'Refresh-Token': `${Storage.getItem(TOKEN.REFRESH)}`,
},
});
Storage.setItem(TOKEN.ACCESS, data.data.accessToken);
} catch {
window.location.href = ROUTES.LOGIN;
alert('다시 로그인 해주세요');
localStorage.clear();
}
};

export default refreshToken;
22 changes: 22 additions & 0 deletions apps/admin/src/apis/token/token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { TOKEN } from '@/constants/common/constant';

import { Storage } from '../storage/storage';

const authorization = () => {
return {
headers: {
Authorization: `Bearer ${Storage.getItem(TOKEN.ACCESS)}`,
},
};
};

authorization.FormData = () => {
return {
headers: {
Authorization: `Bearer ${Storage.getItem(TOKEN.ACCESS)}`,
'Content-Type': 'multipart/form-data',
},
};
};

export default authorization;
51 changes: 51 additions & 0 deletions apps/admin/src/app/faq/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use client';

import FaqDetailContent from '@/components/faq/FaqDetailContent/FaqDetailContent';
import { ROUTES } from '@/constants/common/constant';
import AppLayout from '@/layouts/AppLayout';
import { IconArrowLeft } from '@maru/icon';
import { color, font } from '@maru/theme';
import { Loader } from '@maru/ui';
import { flex } from '@maru/utils';
import Link from 'next/link';
import { Suspense } from 'react';
import { styled } from 'styled-components';

interface Props {
params: { id: number };
}

const FaqDetailPage = ({ params: { id } }: Props) => {
// TODO :: 수정, 삭제 기능 추가하기
return (
<AppLayout>
<StyledNoticeDetail>
<DirectLink href={ROUTES.FAQ}>
<IconArrowLeft width={18} height={18} />
돌아가기
</DirectLink>
<Suspense fallback={<Loader />}>
<FaqDetailContent id={id} />
</Suspense>
</StyledNoticeDetail>
</AppLayout>
);
};

export default FaqDetailPage;

const StyledNoticeDetail = styled.div`
position: relative;
${flex({ flexDirection: 'column' })}
gap: 24px;
width: 100%;
min-height: 100vh;
padding: 64px 75px;
`;

const DirectLink = styled(Link)`
${flex({ alignItems: 'center' })}
gap: 2px;
${font.p3}
color: ${color.gray600};
`;
12 changes: 12 additions & 0 deletions apps/admin/src/app/faq/faq.hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ROUTES } from '@/constants/common/constant';
import { useRouter } from 'next/navigation';

const useCTAButton = () => {
const router = useRouter();
const handleGoFaqPostPageButtonClick = () => {
router.push(ROUTES.FAQ_POST);
};
return { handleGoFaqPostPageButtonClick };
};

export default useCTAButton;
19 changes: 11 additions & 8 deletions apps/admin/src/app/faq/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@ import AppLayout from '@/layouts/AppLayout';
import { Button, Column, Dropdown, Row, SearchInput, Text } from '@maru/ui';
import { flex } from '@maru/utils';
import { styled } from 'styled-components';
import useCTAButton from './faq.hooks';

const FaqPage = () => {
const { handleGoFaqPostPageButtonClick } = useCTAButton();

return (
<AppLayout>
<StyledFaqPage>
<Text fontType="H1">자주 묻는 질문</Text>
<Column gap={36}>
<Row justifyContent="space-between">
<Button size="SMALL" icon="ADD_ICON">
자주 묻는 질문 작성
</Button>
<Row gap={16}>
<SearchInput placeholder="검색어를 입력하세요." />
<Dropdown
data={[]}
size="SMALL"
Expand All @@ -25,11 +26,13 @@ const FaqPage = () => {
onChange={() => console.log('이잉')}
name="category"
/>
<Row gap={8}>
<SearchInput placeholder="검색어를 입력하세요." />
<Button size="SMALL">검색</Button>
</Row>
</Row>
<Button
size="SMALL"
icon="ADD_ICON"
onClick={handleGoFaqPostPageButtonClick}>
자주 묻는 질문 작성
</Button>
</Row>
</Column>
<FaqTable />
Expand All @@ -44,6 +47,6 @@ const StyledFaqPage = styled.div`
${flex({ flexDirection: 'column' })}
gap: 40px;
width: 100%;
height: 100%;
min-height: 100vh;
padding: 64px 75px;
`;
46 changes: 46 additions & 0 deletions apps/admin/src/app/faq/post/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use client';

import FaqPost from '@/components/faq/FaqPost/FaqPost';
import { ROUTES } from '@/constants/common/constant';
import AppLayout from '@/layouts/AppLayout';
import { IconArrowLeft } from '@maru/icon';
import { color, font } from '@maru/theme';
import { Loader } from '@maru/ui';
import { flex } from '@maru/utils';
import Link from 'next/link';
import { Suspense } from 'react';
import styled from 'styled-components';

const FaqPostPage = () => {
return (
<AppLayout>
<StyledFaqDetail>
<DirectLink href={ROUTES.FAQ}>
<IconArrowLeft width={18} height={18} />
돌아가기
</DirectLink>
<Suspense fallback={<Loader />}>
<FaqPost />
</Suspense>
</StyledFaqDetail>
</AppLayout>
);
};

export default FaqPostPage;

const StyledFaqDetail = styled.div`
position: relative;
${flex({ flexDirection: 'column' })}
gap: 24px;
width: 100%;
min-height: 100vh;
padding: 64px 75px;
`;

const DirectLink = styled(Link)`
${flex({ alignItems: 'center' })}
gap: 2px;
${font.p3}
color: ${color.gray600};
`;
41 changes: 41 additions & 0 deletions apps/admin/src/app/login/login.hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { ROUTES } from '@/constants/common/constant';
import { useLoginAdminMutation } from '@/services/auth/mutations';
import { PostLoginAuthReq } from '@/types/auth/remote';
import { useRouter } from 'next/navigation';
import { ChangeEventHandler, useState } from 'react';

export const useLoginAction = (loginAdminData: PostLoginAuthReq) => {
const { loginAdminMutate: loginAdminMutate } = useLoginAdminMutation(loginAdminData);

const handleLoginButtonClick = () => {
loginAdminMutate();
};

return { handleLoginButtonClick };
};

export const useInput = () => {
const [loginAdminData, setLoginAdminData] = useState<PostLoginAuthReq>({
phoneNumber: '',
password: '',
});

const handleLoginAdminDataChange: ChangeEventHandler<HTMLInputElement> = (e) => {
const { name, value } = e.target;
setLoginAdminData({ ...loginAdminData, [name]: value });
};

return {
loginAdminData,
handleLoginAdminDataChange,
};
};

export const useCTAButton = () => {
const router = useRouter();

const handleGoMainPageButtonClick = () => {
router.push(ROUTES.MAIN);
};
return { handleGoMainPageButtonClick };
};
68 changes: 68 additions & 0 deletions apps/admin/src/app/login/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
'use client';

import { color } from '@maru/theme';
import { Button, Column, Input, PreviewInput } from '@maru/ui';
import { flex } from '@maru/utils';
import Image from 'next/image';
import { styled } from 'styled-components';
import { useCTAButton, useInput, useLoginAction } from './login.hooks';

const LoginPage = () => {
const { handleGoMainPageButtonClick } = useCTAButton();
const { loginAdminData, handleLoginAdminDataChange } = useInput();
const { handleLoginButtonClick } = useLoginAction(loginAdminData);

return (
<StyledLoginPage>
<LoginBox>
<Column gap={56} alignItems="center" width={446}>
<Image
src="/svg/logo_black.svg"
onClick={handleGoMainPageButtonClick}
style={{ cursor: 'pointer' }}
width={232}
height={70}
alt="logo"
/>
<Column gap="36px" width="100%">
<Column gap="24px">
<Input
label="전화번호"
width="100%"
name="phoneNumber"
onChange={handleLoginAdminDataChange}
/>
<PreviewInput
label="비밀번호"
width="100%"
name="password"
onChange={handleLoginAdminDataChange}
/>
</Column>
<Column gap="16px" alignItems="flex-end">
<Button width="100%" onClick={handleLoginButtonClick}>
로그인
</Button>
</Column>
</Column>
</Column>
</LoginBox>
</StyledLoginPage>
);
};

export default LoginPage;

const StyledLoginPage = styled.div`
${flex({ justifyContent: 'center' })}
width: 100%;
height: 100vh;
`;

const LoginBox = styled.div`
${flex({ flexDirection: 'column', alignItems: 'center' })}
justify-content: center;
width: 818px;
height: 100%;
background-color: ${color.white};
`;
50 changes: 50 additions & 0 deletions apps/admin/src/app/notice/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use client';

import NoticeDetailContent from '@/components/notice/NoticeDetailContent/NoticeDetailContent';
import AppLayout from '@/layouts/AppLayout';
import { IconArrowLeft } from '@maru/icon';
import { color, font } from '@maru/theme';
import { Loader } from '@maru/ui';
import { flex } from '@maru/utils';
import Link from 'next/link';
import { Suspense } from 'react';
import { styled } from 'styled-components';

interface Props {
params: { id: number };
}

const NoticeDetailPage = ({ params: { id } }: Props) => {
// TODO :: 수정, 삭제 기능 추가하기
return (
<AppLayout>
<StyledNoticeDetail>
<DirectLink href="/notice">
<IconArrowLeft width={18} height={18} />
돌아가기
</DirectLink>
<Suspense fallback={<Loader />}>
<NoticeDetailContent id={id} />
</Suspense>
</StyledNoticeDetail>
</AppLayout>
);
};

export default NoticeDetailPage;

const StyledNoticeDetail = styled.div`
position: relative;
${flex({ flexDirection: 'column' })}
gap: 24px;
width: 100%;
min-height: 100vh;
padding: 64px 75px;
`;

const DirectLink = styled(Link)`
${flex({ alignItems: 'center' })}
gap: 2px;
${font.p3}
color: ${color.gray600};
`;
Loading

1 comment on commit 52dbcf1

@vercel
Copy link

@vercel vercel bot commented on 52dbcf1 Sep 18, 2023

Choose a reason for hiding this comment

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

Please sign in to comment.