diff --git a/.gitignore b/.gitignore index 8f322f0d8..af98c2bc3 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,6 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# page +page_bak.tsx \ No newline at end of file diff --git a/api/folder.api.ts b/api/folder.api.ts new file mode 100644 index 000000000..2ea092869 --- /dev/null +++ b/api/folder.api.ts @@ -0,0 +1,39 @@ +import { instance } from '@/lib/axios'; + +const FOLDERS = '/users/1/folders'; +const LINKS = '/users/1/links'; + +// folder name +export async function getFolderProps() { + try { + const res = await instance.get(FOLDERS); + const { data } = res.data; + return data; + } catch (error) { + console.log('ERROR IN SERVER FETCHING DATA: ', error); + return; + } +} +export async function getFolderDetailProps(id: string) { + try { + const res = await instance.get(`${FOLDERS}/${id}`); + const { data } = res.data; + return data; + } catch (error) { + console.log('ERROR IN SERVER FETCHING DATA: ', error); + return; + } +} + +// folder content list +export async function getLinkProps(id?: string) { + try { + let endPoint = id ? `${LINKS}?folderId=${id}` : LINKS; + const res = await instance.get(endPoint); + const { data } = res.data; + return data; + } catch (error) { + console.log('ERROR IN SERVER FETCHING DATA: ', error); + return; + } +} diff --git a/app/(auth)/layout.tsx b/app/(auth)/layout.tsx new file mode 100644 index 000000000..16c26af93 --- /dev/null +++ b/app/(auth)/layout.tsx @@ -0,0 +1,39 @@ +'use client'; +import Loading from '@/components/loading/Loading'; +import { ACCESS_TOKEN_KEY } from '@/lib/axios'; +import { JoinBody, JoinWrap } from '@/styles/loginStyle'; +import { useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; + +function getCookie(name: string) { + const cookieString = document.cookie; + const cookies = cookieString.split('; '); + for (const cookie of cookies) { + const [cookieName] = cookie.split('='); + if (cookieName === name) { + return true; + } + } + return false; +} + +export default function Template({ children }: { children: React.ReactNode }) { + const router = useRouter(); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + if (getCookie(ACCESS_TOKEN_KEY)) { + router.push('/folder'); + return; + } + setIsLoading(false); + }, [isLoading]); + + if (isLoading) return ; + + return ( + + {children} + + ); +} diff --git a/app/(auth)/signin/page.tsx b/app/(auth)/signin/page.tsx new file mode 100644 index 000000000..38f83c4aa --- /dev/null +++ b/app/(auth)/signin/page.tsx @@ -0,0 +1,122 @@ +'use client'; +import AuthLink from '@/components/Auth/AuthLink'; +import AuthLogo from '@/components/Auth/AuthLogo'; +import AuthRegister from '@/components/Auth/AuthRegister'; +import Button from '@/components/common/atoms/Button'; +import { ErrorText, FormRowBox, FormWrap } from '@/components/join/formStyle'; +import { loginForm } from '@/components/join/interface'; +import { AuthContext } from '@/lib/auto.provider'; +import { instance } from '@/lib/axios'; +import { Relative } from '@/styles/commonStyle'; +import Image from 'next/image'; +import { useRouter } from 'next/navigation'; +import { useContext, useState } from 'react'; +import { useForm } from 'react-hook-form'; + +export default function SignIn() { + const router = useRouter(); + const { handleLogin } = useContext(AuthContext); + const [IsVisibility, setIsVisibility] = useState(false); + + const { + register, + handleSubmit, + formState: { errors }, + setError, + } = useForm({ mode: 'onBlur' }); + + const handleLoginCheck = async (email: loginForm['email'], password: loginForm['password']) => { + try { + const res = await instance.post('/sign-in', { email, password }); + const { data } = res; + if (data) { + handleLogin(data.data.accessToken); + router.push('/folder'); + } + } catch { + setError('email', { message: '이메일을 확인해 주세요.' }); + setError('password', { message: '비밀번호를 확인해 주세요.' }); + return; + } + }; + + const handleValid = (data: loginForm) => { + const { email, password } = data; + handleLoginCheck(email, password); + }; + + return ( + <> + + + +
+ + + + {errors.email?.message} + + + + + + + + {errors.password?.message} + + +
+
+ + + ); +} diff --git a/app/(auth)/signup/page.tsx b/app/(auth)/signup/page.tsx new file mode 100644 index 000000000..673d4c644 --- /dev/null +++ b/app/(auth)/signup/page.tsx @@ -0,0 +1,194 @@ +'use client'; +import Button from '@/components/common/atoms/Button'; +import LinkButton from '@/components/common/atoms/LinkButton'; +import { ErrorText, FormRowBox, FormWrap } from '@/components/join/formStyle'; +import { IJoinForm } from '@/components/join/interface'; +import { instance } from '@/lib/axios'; +import { LINKBRARY_LOGO } from '@/src/constant/image.constant'; +import { FontSM, Relative } from '@/styles/commonStyle'; +import Image from 'next/image'; +import { useRouter } from 'next/navigation'; +import { useState } from 'react'; +import { useForm } from 'react-hook-form'; +import { JoinAccessControlBox, JoinSocial, JoinTitle } from '../../../styles/loginStyle'; + +export default function SignUp() { + const router = useRouter(); + const [pwVisibility, setPwVisibility] = useState(false); + const [pwConfirmVisibility, setPwConfirmVisibility] = useState(false); + const { + register, + handleSubmit, + formState: { errors }, + setError, + } = useForm({ mode: 'onBlur' }); + + const handleEmailCheck = async (email: IJoinForm['email']) => { + try { + const res = await instance.post('/users/1/check-email', { email }); + if (res) { + return true; + } + } catch { + setError('email', { message: '사용중인 이메일 입니다.' }, { shouldFocus: true }); + return; + } + }; + + const handlePassWordCheck = (password: IJoinForm['password'], passwordConfirm: IJoinForm['passwordConfirm']) => { + if (password !== passwordConfirm) { + setError('passwordConfirm', { message: '비밀번호가 다릅니다.' }, { shouldFocus: true }); + return; + } + }; + + const handleValid = (data: IJoinForm) => { + const { password, passwordConfirm } = data; + // 비밀번호 같은지 확인 + handlePassWordCheck(password, passwordConfirm); + router.push('/folder'); + }; + + return ( + <> + + + linkbrary + + + + 이미 회원이신가요? + 로그인 하기 + + +
+ {/* 이메일 */} + + + handleEmailCheck(e.target.value), + })} + type='email' + id='input__id-element' + placeholder='이메일을 입력해 주세요.' + className={errors.email ? 'error' : ''} + /> + {/* onBlur: (e) => handleEmailCheck(e.target.value) == undefined || '있는 아이디', */} + {errors.email?.message} + + {/* 비밀번호 */} + + + + + + + {errors.password?.message} + + {/* 비밀번호 확인*/} + + + + + + + {errors.passwordConfirm?.message} + + +
+
+ + 다른 방식으로 가입하기 +
+ + 구글로고 + + + 카카오로고 + +
+
+ + ); +} diff --git a/pages/folder/index.tsx b/app/(private)/folder/[[...id]]/FolderClient.tsx similarity index 54% rename from pages/folder/index.tsx rename to app/(private)/folder/[[...id]]/FolderClient.tsx index 945a1d25e..1f303f176 100644 --- a/pages/folder/index.tsx +++ b/app/(private)/folder/[[...id]]/FolderClient.tsx @@ -1,80 +1,52 @@ -import { useEffect, useState } from 'react'; -import { useRouter } from 'next/router'; -import { GetServerSidePropsContext } from 'next'; -import { ContainBody, Container } from '@/styles/commonStyle'; -import LinkAddHeader from '@/components/folder/LinkAddHeader'; -import SearchInputBox from '@/components/folder/SearchInputBox'; -import FolderButtonList from '@/components/folder/FolderButtonList'; +'use client'; import Button from '@/components/common/atoms/Button'; -import FolderContentControll from '@/components/folder/FolderContentControll'; +import FolderButtonList from '@/components/folder/FolderButtonList'; +import FolderContentControl from '@/components/folder/FolderContentControl'; +import LinkAddHeader from '@/components/folder/LinkAddHeader'; import PostCardList from '@/components/folder/PostCardList'; -import Modal from '@/components/modal/Modal'; +import SearchInputBox from '@/components/folder/SearchInputBox'; +import { IFolderContent, IFolderMenuButton } from '@/components/folder/interface'; import Loading from '@/components/loading/Loading'; -import { BodyInner, BookmarkBox, EmptyBox, FolderContainHead } from '../../styles/folderStyle'; -import { IFolderContentApi, IFolderMenuButtonApi } from '../../components/folder/interface'; -import { instance } from '@/lib/axios'; +import Modal from '@/components/modal/Modal'; +import { ContainBody, Container } from '@/styles/commonStyle'; +import { BodyInner, BookmarkBox, FolderContainHead } from '@/styles/folderStyle'; +import { useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; const ADD_IMAGE = '/assets/icon/icon_primary_add.svg'; const SEARCH_IMAGE = '/assets/icon/icon_search.svg'; const LINK_IMAGE = '/assets/icon/icon_primaty_link.svg'; -export async function getServerSideProps(contaxt: GetServerSidePropsContext) { - const { query } = contaxt; - try { - let resContent; - const resMenu = await instance.get(`/folders`); - if (query.id) { - resContent = await instance.get(`/links?folderId=${query.id}`); - } else { - resContent = await instance.get(`/links`); - } - - const $menu = resMenu.data; - const $content = resContent.data; - return { - props: { - $menu, - $content, - }, - }; - } catch (error) { - console.log('ERROR IN SERVER FETCHING DATA: ', error); - return { - notFound: true, - }; - } +export interface IFolderClientProps { + menuData: IFolderMenuButton[]; + contentData: IFolderContent[]; + pageId?: string; } - -export default function Folder({ $menu, $content }: { $menu: IFolderMenuButtonApi; $content: IFolderContentApi }) { +export default function FolderClient({ menuData, contentData, pageId }: IFolderClientProps) { + const [menu, setMenu] = useState(menuData); + const [content, setContent] = useState(contentData); const router = useRouter(); - const [tabTitle, setTabTitle] = useState('전체'); - const [activeBtn, setActiveBtn] = useState(-1); + const [tabTitle, setTabTitle] = useState('전체'); + const [activeBtn, setActiveBtn] = useState('전체'); const [isModalShow, setIsModalShow] = useState(false); const [modalType, setModalType] = useState(''); const [searchContatn, setSearchContent] = useState(); - const [isStylesLoaded, setIsStylesLoaded] = useState(false); + const [isLoading, setIsLoading] = useState(false); // 폴더리스트버튼 - const handleClick = (id: number) => { + const handleClick = (id: string) => { if (!id) return; + let title = menu.find((data) => { + return `${data.id}` === `${id}` && data; + }); + const result = title ? title.name : '전체'; - if (id === -1) { - router.push(``); - setTabTitle('전체'); - } else { - router.push(`?id=${id}`); - let title = $menu.data.filter((data) => `${data.id}` === `${id}`); - setTabTitle(`${title[0].name}`); - } + setTabTitle(result); setActiveBtn(id); }; - // modal open const handleModalOpen = (type: string) => { setIsModalShow(true); - if (type === 'folderDelete') { - let aaa = tabTitle; - } setModalType(type); }; @@ -83,32 +55,29 @@ export default function Folder({ $menu, $content }: { $menu: IFolderMenuButtonAp setIsModalShow(false); }; - // Search + // // Search const handelSearch = (value: string) => { let filter; if (value) { - filter = $content?.data.filter((con) => { + filter = content?.filter((con) => { if (!con) return; return con.description?.includes(value) || con.title?.includes(value) || con.url?.includes(value); }); setSearchContent(filter); return; } - setSearchContent($content?.data); + setSearchContent(content); }; - // search - const contentSearch = searchContatn ?? $content?.data; + // // search + const contentSearch = searchContatn ?? content; useEffect(() => { let idExists; - - if (router.query.id) { - // folder가 있을때 - idExists = $menu.data.some((item: any) => `${item.id}` === `${router.query.id}`); - } else if (router.query.id === '-1') { - // 전체 일때 + if (!pageId) { router.push(`/folder`); + } else { + idExists = menu.some((item: any) => `${item.id}` === `${pageId}`); } if (idExists === false) { @@ -117,10 +86,10 @@ export default function Folder({ $menu, $content }: { $menu: IFolderMenuButtonAp router.push(`/folder`); } - setIsStylesLoaded(true); - }, [$menu, router]); + setIsLoading(true); + }, [menu, router, pageId]); - if (!isStylesLoaded) return ; + if (!isLoading) return ; return ( @@ -138,20 +107,20 @@ export default function Folder({ $menu, $content }: { $menu: IFolderMenuButtonAp {/* 폴더 리스트 버튼 */} {/* 탭 타이틀, 설정 버튼 */} - @@ -163,7 +132,7 @@ export default function Folder({ $menu, $content }: { $menu: IFolderMenuButtonAp diff --git a/app/(private)/folder/[[...id]]/page.tsx b/app/(private)/folder/[[...id]]/page.tsx new file mode 100644 index 000000000..b682cc90a --- /dev/null +++ b/app/(private)/folder/[[...id]]/page.tsx @@ -0,0 +1,31 @@ +import { getFolderProps, getLinkProps } from '@/api/folder.api'; +import { IFolderContent, IFolderMenuButton } from '@/components/folder/interface'; +import FolderClient from './FolderClient'; +import Loading from '@/components/loading/Loading'; + +export interface IFolderClientProps { + menuData: IFolderMenuButton[]; + contentData: IFolderContent[]; +} + +export async function getFolderProp(id: string): Promise { + try { + const [menuData, contentData] = await Promise.all([getFolderProps(), getLinkProps(id)]); + return { menuData, contentData }; + } catch (error) { + console.log('ERROR IN SERVER FETCHING DATA: ', error); + return { + menuData: [], + contentData: [], + }; + } +} + +export default async function Folder({ params }: { params: { id: string } }) { + const { menuData, contentData } = await getFolderProp(params.id); + const { id: pageId } = params; + const props = { menuData, contentData, pageId }; + // if (!menuData || !contentData) return ; + + return ; +} diff --git a/pages/shared/[id].tsx b/app/(private)/shared/[id]/SharedClient.tsx similarity index 52% rename from pages/shared/[id].tsx rename to app/(private)/shared/[id]/SharedClient.tsx index fedc4c171..8b4660623 100644 --- a/pages/shared/[id].tsx +++ b/app/(private)/shared/[id]/SharedClient.tsx @@ -1,70 +1,40 @@ -import { ContainBody, ContainHead, Container, TitleMs } from '@/styles/commonStyle'; -import { BodyInner, ShareHeadInner } from '../../styles/folderStyle'; -import { IFolderContentApi, IFolderMenuButton } from '../../components/folder/interface'; +'use client'; import PostCardList from '@/components/folder/PostCardList'; -import { instance } from '@/lib/axios'; -import { useRouter } from 'next/router'; -import { GetServerSidePropsContext } from 'next'; import SearchInputBox from '@/components/folder/SearchInputBox'; -import { useState } from 'react'; +import { IFolderContent, IFolderMenuButton } from '@/components/folder/interface'; +import { ContainBody, ContainHead, Container, TitleMs } from '@/styles/commonStyle'; +import { BodyInner, ShareHeadInner } from '@/styles/folderStyle'; import Image from 'next/image'; +import { useRouter } from 'next/navigation'; +import { useState } from 'react'; const LOGO_IMAGE = '/assets/logo/logo_codeit.svg'; const SEARCH_IMAGE = '/assets/icon/icon_search.svg'; -export async function getServerSideProps(contaxt: GetServerSidePropsContext) { - const { query } = contaxt; - try { - const [resTitle, resContent] = await Promise.all([instance.get(`/folders/${query.id}`), instance.get(`/links?folderId=${query.id}`)]); - const $title = resTitle.data; - const $content = resContent.data; - - if (!$title.data[0]) { - return { - notFound: true, - }; - } - - return { - props: { - $title, - $content, - }, - }; - } catch (error) { - console.log('ERROR IN SERVER FETCHING DATA: ', error); - return { - notFound: true, - }; - } -} - export interface IShareTitle { data: Omit; } -export default function Shared({ $title, $content }: { $title: IShareTitle; $content: IFolderContentApi }) { +export default function SharedClient({ menuData, contentData, pageId }: { menuData: IFolderMenuButton[]; contentData: IFolderContent[]; pageId: string }) { const router = useRouter(); const [searchContatn, setSearchContent] = useState(); - + console.log('menuData', menuData); // Search const handelSearch = (value: string) => { let filter; if (value) { - filter = $content?.data.filter((con) => { + filter = contentData.filter((con: IFolderContent) => { if (!con) return; return con.description?.includes(value) || con.title?.includes(value) || con.url?.includes(value); }); setSearchContent(filter); return; } - setSearchContent($content?.data); + setSearchContent(contentData); }; // search - const contentSearch = searchContatn ?? $content?.data; - - if (!$title.data[0]) router.push('/notfound'); + const contentSearch = searchContatn ?? contentData; return ( @@ -77,7 +47,7 @@ export default function Shared({ $title, $content }: { $title: IShareTitle; $con height={60} />

@코드잇

- {$title?.data[0]?.name && {$title?.data[0]?.name}} + {menuData[0]?.name && {menuData[0]?.name}} diff --git a/app/(private)/shared/[id]/page.tsx b/app/(private)/shared/[id]/page.tsx new file mode 100644 index 000000000..bc476ab9f --- /dev/null +++ b/app/(private)/shared/[id]/page.tsx @@ -0,0 +1,22 @@ +import { getFolderDetailProps, getLinkProps } from '@/api/folder.api'; +import { revalidatePath } from 'next/cache'; +import { redirect } from 'next/navigation'; +import SharedClient from './SharedClient'; + +export async function getSharedProp(id: string) { + try { + const [menuData, contentData] = await Promise.all([getFolderDetailProps(id), getLinkProps(id)]); + return { menuData, contentData }; + } catch (error) { + console.log('ERROR IN SERVER FETCHING DATA: ', error); + } + revalidatePath('/folder'); + redirect('/folder'); +} + +export default async function Shared({ params: { id } }: { params: { id: string } }) { + const pageId = id; + const { menuData, contentData } = await getSharedProp(pageId); + const props = { menuData, contentData, pageId }; + return ; +} diff --git a/pages/faq/index.tsx b/app/(public)/faq/page.tsx similarity index 65% rename from pages/faq/index.tsx rename to app/(public)/faq/page.tsx index e851de0c0..3bd2672fd 100644 --- a/pages/faq/index.tsx +++ b/app/(public)/faq/page.tsx @@ -1,4 +1,10 @@ +'use client'; import { Container, InnerLarge } from '@/styles/commonStyle'; +import { Metadata } from 'next'; + +const metadata: Metadata = { + title: 'Faq', +}; export default function Faq() { return ( diff --git a/pages/policy/index.tsx b/app/(public)/privacy/page.tsx similarity index 66% rename from pages/policy/index.tsx rename to app/(public)/privacy/page.tsx index e78590e67..e7c65b609 100644 --- a/pages/policy/index.tsx +++ b/app/(public)/privacy/page.tsx @@ -1,4 +1,10 @@ +'use client'; import { Container, InnerLarge } from '@/styles/commonStyle'; +import { Metadata } from 'next'; + +const metadata: Metadata = { + title: 'Policy', +}; export default function Policy() { return ( diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 000000000..5a6bc0fa3 --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,20 @@ +import ThemeProvider from '@/lib/theme.provider'; +import '@/styles/globals.css'; +import { Metadata } from 'next'; + +export const metadata: Metadata = { + title: { + template: '%s | Linkbrary', + default: 'Linkbrary', + }, +}; + +export default function RootLayout({ children }: { children: React.ReactNode }) { + return ( + + + {children} + + + ); +} diff --git a/pages/404.tsx b/app/not-found.tsx similarity index 96% rename from pages/404.tsx rename to app/not-found.tsx index 619ff392d..31e9a2cd9 100644 --- a/pages/404.tsx +++ b/app/not-found.tsx @@ -1,6 +1,7 @@ +'use client'; +import { TitleMs } from '@/styles/commonStyle'; import Link from 'next/link'; import { NotFoundWrap } from '../styles/errorStyle'; -import { TitleMs } from '@/styles/commonStyle'; export default function NotFound() { return ( diff --git a/pages/index.tsx b/app/page.tsx similarity index 93% rename from pages/index.tsx rename to app/page.tsx index 509dfcbd2..34653218d 100644 --- a/pages/index.tsx +++ b/app/page.tsx @@ -1,17 +1,18 @@ -import { Container, TitleLs, TitleMs } from '@/styles/commonStyle'; -import { Section } from '../styles/mainStyle'; +'use client'; import LinkButton from '@/components/common/atoms/LinkButton'; -import { useEffect, useState } from 'react'; import Loading from '@/components/loading/Loading'; +import { Container, TitleLs, TitleMs } from '@/styles/commonStyle'; +import { useEffect, useState } from 'react'; +import { Section } from '../styles/mainStyle'; export default function Home() { - const [isStylesLoaded, setIsStylesLoaded] = useState(false); + const [isLoading, setIsLoading] = useState(false); useEffect(() => { - setIsStylesLoaded(true); + setIsLoading(true); }, []); - if (!isStylesLoaded) return ; + if (!isLoading) return ; return ( @@ -22,8 +23,8 @@ export default function Home() { 관리해 보세요 + href='/folder' + linkClass='link--gradient large btn__link-add'> 링크 추가하기 diff --git a/components/Auth/AuthLink.tsx b/components/Auth/AuthLink.tsx new file mode 100644 index 000000000..514145f55 --- /dev/null +++ b/components/Auth/AuthLink.tsx @@ -0,0 +1,17 @@ +import { JoinAccessControlBox } from '@/styles/loginStyle'; +import LinkButton from '../common/atoms/LinkButton'; + +interface IAuthLink { + desc: string; + href: string; + btnText: string; +} + +export default function AuthLink({ desc, href, btnText }: IAuthLink) { + return ( + + {desc} + {btnText} + + ); +} diff --git a/components/Auth/AuthLogo.tsx b/components/Auth/AuthLogo.tsx new file mode 100644 index 000000000..713c54b10 --- /dev/null +++ b/components/Auth/AuthLogo.tsx @@ -0,0 +1,19 @@ +import { JoinTitle } from '@/styles/loginStyle'; +import LinkButton from '../common/atoms/LinkButton'; +import Image from 'next/image'; +import { LINKBRARY_LOGO } from '@/src/constant/image.constant'; + +export default function AuthLogo() { + return ( + + + linkbrary + + + ); +} diff --git a/components/Auth/AuthRegister.tsx b/components/Auth/AuthRegister.tsx new file mode 100644 index 000000000..1d502c143 --- /dev/null +++ b/components/Auth/AuthRegister.tsx @@ -0,0 +1,30 @@ +import { GOOGLE, KAKAO } from '@/src/constant/image.constant'; +import Image from 'next/image'; +import LinkButton from '../common/atoms/LinkButton'; +import { FontSM } from '@/styles/commonStyle'; +import { JoinSocial } from '@/styles/loginStyle'; + +const snsRegister = [GOOGLE, KAKAO]; + +export default function AuthRegister({ title }: { title: string }) { + return ( + + {title} +
+ {snsRegister.map((sns) => ( + + {sns.NAME} + + ))} +
+
+ ); +} diff --git a/components/common/Footer.tsx b/components/common/Footer.tsx index 5b3935674..aa5a990f2 100644 --- a/components/common/Footer.tsx +++ b/components/common/Footer.tsx @@ -1,9 +1,10 @@ +'use client'; +import Image from 'next/image'; +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; import { useEffect, useState } from 'react'; -import { FootInner, FootNav, FootSign, FootSocial, FootWrap } from './footerStyle'; import LinkButton from './atoms/LinkButton'; -import Link from 'next/link'; -import Image from 'next/image'; -import { useRouter } from 'next/router'; +import { FootInner, FootNav, FootSign, FootSocial, FootWrap } from './footerStyle'; export const snsIconSrc = [ { @@ -31,12 +32,12 @@ export const snsIconSrc = [ const hidePages = ['/signin', '/signup']; function Footer() { - const { pathname } = useRouter(); + const pathName = usePathname(); const [isHideFooter, setIsHideFooter] = useState(true); useEffect(() => { - setIsHideFooter(hidePages.includes(pathname)); - }, [pathname]); + setIsHideFooter(hidePages.includes(pathName)); + }, [pathName]); if (isHideFooter) return null; @@ -60,8 +61,8 @@ function Footer() { {snsIconSrc.map((sns) => ( + href={sns.link} + linkClass={`link--social-emoji`}> {sns.id}(); + // const [userInfo, setUserInfo] = useState(); - const handleUserInfo = async () => { - const res = await joinInstance.get(`/sample/user`); - setUserInfo(JSON.parse(JSON.stringify(res.data))); - }; + // const handleUserInfo = async () => { + // const res = await instance.get(`/users/1/sample/user`); + // setUserInfo(JSON.parse(JSON.stringify(res.data))); + // }; useEffect(() => { - handleUserInfo(); - setIsHideHeader(hidePages.includes(pathname)); - setIsFixed(noHeaderFixed.includes(pathname)); - }, [pathname]); + // handleUserInfo(); + setIsHideHeader(hidePages.includes(pathName)); + setIsFixed(noHeaderFixed.includes(pathName)); + }, [pathName]); if (isHideHeader) return null; @@ -50,9 +50,11 @@ function Header() { $position={isfixed}> - + linkbrary - {userInfo?.email} + {/* {userInfo?.email} */} ) : ( + href={'/login'} + linkClass={'link--gradient link--login large'}> 로그인 )} diff --git a/components/common/atoms/Button.tsx b/components/common/atoms/Button.tsx index c6bd59f58..e1aab2d88 100644 --- a/components/common/atoms/Button.tsx +++ b/components/common/atoms/Button.tsx @@ -1,22 +1,23 @@ +'use client'; import { ButtonHTMLAttributes } from 'react'; import { ButtonModule } from './buttonStyle'; interface IButtonModule { children: React.ReactNode; - $btnClass?: string; - $BeforButtonIcon?: string; - $id?: string; - $afterButtonIcon?: string; - $type?: ButtonHTMLAttributes['type']; + btnClass?: string; + $beforeIcon?: string; + id?: string; + $afterIcon?: string; + type?: ButtonHTMLAttributes['type']; onclick?: () => void; } -export default function Button({ children, $btnClass, $type = 'button', $BeforButtonIcon = '', $afterButtonIcon = '', onclick }: IButtonModule) { +export default function Button({ children, btnClass, type = 'button', $beforeIcon, $afterIcon, onclick }: IButtonModule) { return ( {children} diff --git a/components/common/atoms/CheckBox.tsx b/components/common/atoms/CheckBox.tsx index 3b9f0123e..e52a770f4 100644 --- a/components/common/atoms/CheckBox.tsx +++ b/components/common/atoms/CheckBox.tsx @@ -1,11 +1,11 @@ -import { IModal } from '@/src/constant/modal'; +import { IModal } from '@/src/constant/modal.constant'; import { CheckBoxWrap } from './checkBoxStyle'; -function CheckBox({ $data }: IModal['modalData']) { +function CheckBox({ data }: IModal['modalData']) { return ( - {$data && - $data?.map((list: any) => ( + {data && + data?.map((list: any) => (
diff --git a/components/common/atoms/Input.tsx b/components/common/atoms/Input.tsx index 1451722f0..9d7e0fa7b 100644 --- a/components/common/atoms/Input.tsx +++ b/components/common/atoms/Input.tsx @@ -1,23 +1,23 @@ -import { ChangeEvent, ReactNode, useEffect, useRef, useState } from 'react'; -import { InputModule } from './inputStyle'; -import Button from './Button'; import { Relative } from '@/styles/commonStyle'; +import { ChangeEvent, ReactNode, useRef, useState } from 'react'; +import Button from './Button'; +import { InputModule } from './inputStyle'; interface IButtonModule { - $id?: string; - $type?: string; - $inputClass?: string; - $btnShow?: boolean; - $placeholder?: string; - $beforeBgIcon?: string; - $btnClass?: string; - $clickEvent?: string | undefined; + id?: string; + type?: string; + inputClass?: string; + btnShow?: boolean; + placeholder?: string; + $beforeIcon?: string; + btnClass?: string; + clickEventType?: string | undefined; children?: ReactNode; onclick?: () => void; onchange?: (value: string) => void; } -function Input({ $id, $btnShow = false, $type = 'text', $inputClass, $placeholder, $beforeBgIcon = '', $btnClass = '', $clickEvent, children, onchange }: IButtonModule) { +function Input({ id, btnShow = false, type = 'text', inputClass, placeholder, $beforeIcon = '', btnClass = '', clickEventType, children, onchange }: IButtonModule) { const [value, setValue] = useState(''); const refInput = useRef(null); @@ -44,19 +44,19 @@ function Input({ $id, $btnShow = false, $type = 'text', $inputClass, $placeholde <> - {$btnShow && $clickEvent && ( + {btnShow && clickEventType && ( )} diff --git a/components/common/atoms/LinkButton.tsx b/components/common/atoms/LinkButton.tsx index 9e30554a8..84c4c45d9 100644 --- a/components/common/atoms/LinkButton.tsx +++ b/components/common/atoms/LinkButton.tsx @@ -1,17 +1,18 @@ import { LinkModule } from './LinkButtonStyle'; interface IButtonModule { children: React.ReactNode; - $link: string; - $linkClass?: string; - $target?: string; + href: string; + linkClass?: string; + target?: string; } -export default function LinkButton({ children, $link, $linkClass, $target = '_self' }: IButtonModule) { +export default function LinkButton({ children, href, linkClass, target = '_self' }: IButtonModule) { return ( + href={href} + className={linkClass} + target={target} + scroll={false}> {children} ); diff --git a/components/common/atoms/LinkButtonStyle.ts b/components/common/atoms/LinkButtonStyle.ts index 23e730851..1b9496f89 100644 --- a/components/common/atoms/LinkButtonStyle.ts +++ b/components/common/atoms/LinkButtonStyle.ts @@ -1,7 +1,7 @@ -import styled from 'styled-components'; +import { font24 } from '@/styles/commonStyle'; import { theme } from '@/styles/theme'; import Link from 'next/link'; -import { font24 } from '@/styles/commonStyle'; +import styled from 'styled-components'; export const LinkModule = styled(Link)` position: relative; @@ -40,7 +40,7 @@ export const LinkModule = styled(Link)` line-height: 37px; } } - &.mideum { + &.medium { width: 80px; font-size: 14px; line-height: 37px; diff --git a/components/common/atoms/buttonStyle.ts b/components/common/atoms/buttonStyle.ts index e68b69124..b71bd69ae 100644 --- a/components/common/atoms/buttonStyle.ts +++ b/components/common/atoms/buttonStyle.ts @@ -2,8 +2,8 @@ import { theme } from '@/styles/theme'; import styled from 'styled-components'; export const ButtonModule = styled.button<{ - $afterButtonIcon: string; - $BeforButtonIcon: string; + $afterIcon?: string; + $beforeIcon?: string; }>` &.button { &--outlined { @@ -28,13 +28,13 @@ export const ButtonModule = styled.button<{ &--icon-before { display: inline-block; padding-left: 22px; - background: url(${({ $BeforButtonIcon }) => $BeforButtonIcon || ''}) no-repeat left center; + background: url(${({ $beforeIcon }) => $beforeIcon || ''}) no-repeat left center; background-size: 18px 18px; } &--icon-after { display: inline-block; padding-right: 20px; - background: url(${({ $afterButtonIcon }) => $afterButtonIcon || ''}) no-repeat right center; + background: url(${({ $afterIcon }) => $afterIcon || ''}) no-repeat right center; background-size: 18px 18px; } &--gradient { @@ -87,7 +87,7 @@ export const ButtonModule = styled.button<{ line-height: 37px; } } - &.mideum { + &.medium { font-size: 14px; line-height: 37px; font-weight: 600; diff --git a/components/common/atoms/inputStyle.ts b/components/common/atoms/inputStyle.ts index 8168f5c97..d0e075be0 100644 --- a/components/common/atoms/inputStyle.ts +++ b/components/common/atoms/inputStyle.ts @@ -1,7 +1,7 @@ import { theme } from '@/styles/theme'; import styled from 'styled-components'; -export const InputModule = styled.input<{ $beforeBgIcon: string }>` +export const InputModule = styled.input<{ $beforeIcon: string }>` padding: 0 15px; width: 100%; line-height: 58px; @@ -26,7 +26,7 @@ export const InputModule = styled.input<{ $beforeBgIcon: string }>` line-height: 54px; color: ${theme.color.gray6}; border-radius: 0.625rem; - background: #f5f5f5 url(${({ $beforeBgIcon }) => $beforeBgIcon || ''}) no-repeat left 1rem center; + background: #f5f5f5 url(${({ $beforeIcon }) => $beforeIcon || ''}) no-repeat left 1rem center; background-size: 1rem 1rem; box-sizing: border-box; @media screen and (max-width: ${theme.screenSize.moLarge}) { @@ -38,7 +38,7 @@ export const InputModule = styled.input<{ $beforeBgIcon: string }>` width: 100%; padding: 0 120px 0 52px; line-height: 67px; - background: #fff url(${({ $beforeBgIcon }) => $beforeBgIcon || ''}) no-repeat left 20px center; + background: #fff url(${({ $beforeIcon }) => $beforeIcon || ''}) no-repeat left 20px center; border-radius: 15px; @media screen and (max-width: ${theme.screenSize.moLarge}) { padding: 0 100px 0 34px; diff --git a/components/common/headerStyle.ts b/components/common/headerStyle.ts index 6755c2fa7..4a147da66 100644 --- a/components/common/headerStyle.ts +++ b/components/common/headerStyle.ts @@ -1,7 +1,6 @@ -import { DFlaxAlignCenter, DFlaxAlignCenterBtw, dflexCenter } from '@/styles/commonStyle'; +import { DFlaxAlignCenterBtw, dflexCenter } from '@/styles/commonStyle'; import { theme } from '@/styles/theme'; import styled from 'styled-components'; -import Button from './atoms/Button'; export const HeaderWrap = styled.header<{ $position: boolean | undefined }>` position: ${({ $position }) => ($position ? 'absolute' : 'fixed')}; diff --git a/components/folder/FolderButtonList.tsx b/components/folder/FolderButtonList.tsx index 29503d0be..4fbc53c80 100644 --- a/components/folder/FolderButtonList.tsx +++ b/components/folder/FolderButtonList.tsx @@ -1,30 +1,30 @@ import { BookMarkBtnList } from '@/styles/folderStyle'; import { memo } from 'react'; import Button from '../common/atoms/Button'; -import { IFolderMenuButtonApi } from './interface'; +import { IFolderMenuButton } from './interface'; interface IButtonList { - $menu: IFolderMenuButtonApi | null; - $activeBtnId: number; - onClick: (id: number) => void; + $menu?: IFolderMenuButton[]; + $activeBtnId: string; + onClick: (id: string) => void; } function FolderButtonList({ $menu, $activeBtnId, onClick }: IButtonList) { return ( {$menu && - $menu.data?.map((item) => ( + $menu.map((item) => ( ))} diff --git a/components/folder/FolderContentControll.tsx b/components/folder/FolderContentControl.tsx similarity index 75% rename from components/folder/FolderContentControll.tsx rename to components/folder/FolderContentControl.tsx index bcf145e10..de4e59fd4 100644 --- a/components/folder/FolderContentControll.tsx +++ b/components/folder/FolderContentControl.tsx @@ -1,9 +1,9 @@ -import { memo } from 'react'; import { FontLS } from '@/styles/commonStyle'; -import { ShareBox } from '../share/shareStyle'; import { ShareListBtn } from '@/styles/folderStyle'; +import { memo } from 'react'; import Button from '../common/atoms/Button'; import LinkButton from '../common/atoms/LinkButton'; +import { ShareBox } from '../share/shareStyle'; const folderControlBtn = [ { @@ -26,20 +26,20 @@ const folderControlBtn = [ }, ]; -interface iControll { - $title: string; +interface iControl { + $title?: string; onclick: (type: string) => void; - $id?: number; + id?: string; } -function FolderContentControll({ $title, onclick, $id }: iControll) { +function FolderContentControl({ $title, onclick, id }: iControl) { const handleModalOpen = (type: string) => { onclick(type); }; return ( - {$id && $id === -1 ? ( + {id && id === `전체` ? ( @@ -47,9 +47,9 @@ function FolderContentControll({ $title, onclick, $id }: iControll) { ) : ( + href={`/shared/${id}`} + linkClass='link--title-text tab-title' + target='_blank'> {$title} )} @@ -58,9 +58,9 @@ function FolderContentControll({ $title, onclick, $id }: iControll) { {folderControlBtn.map((btn) => ( @@ -71,4 +71,4 @@ function FolderContentControll({ $title, onclick, $id }: iControll) { ); } -export default memo(FolderContentControll); +export default memo(FolderContentControl); diff --git a/components/folder/LinkAddHeader.tsx b/components/folder/LinkAddHeader.tsx index 76585df63..11f833873 100644 --- a/components/folder/LinkAddHeader.tsx +++ b/components/folder/LinkAddHeader.tsx @@ -1,17 +1,17 @@ import { LinkAddHeadInner } from '@/styles/folderStyle'; -import Input from '../common/atoms/Input'; import { memo } from 'react'; +import Input from '../common/atoms/Input'; function LinkAddHeader({ $inputIconImg }: { $inputIconImg: string }) { return (
+ inputClass={'input__link--add'} + placeholder={'링크를 추가해 보세요'} + $beforeIcon={$inputIconImg} + btnShow={true} + btnClass={'button--gradient medium'}> 추가하기
diff --git a/components/folder/PostCard.tsx b/components/folder/PostCard.tsx index 96fd1e99f..97596d1b0 100644 --- a/components/folder/PostCard.tsx +++ b/components/folder/PostCard.tsx @@ -1,17 +1,16 @@ -import { useEffect, useMemo, useState } from 'react'; -import Link from 'next/link'; +import { instance } from '@/lib/axios'; +import { IModal } from '@/src/constant/modal.constant'; +import { calculateTimeAgo } from '@/src/utils/calcTilmAgo'; +import { DFlaxAlignCenterBtw, EllipsisLine } from '@/styles/commonStyle'; import Image from 'next/image'; +import Link from 'next/link'; +import { useEffect, useState } from 'react'; import Modal, { IModalInfo } from '../modal/Modal'; import { BookMarkBtn, CardMenu, CardWrap } from './PostCardStyle'; -import { DFlaxAlignCenterBtw, EllipsisLine } from '@/styles/commonStyle'; -import { calculateTimeAgo } from '@/src/utils/calcTilmAgo'; -import { IModal } from '@/src/constant/modal'; -import { instance } from '@/lib/axios'; import { IFolderContent } from './interface'; +import { LINKBRARY_LOGO } from '@/src/constant/image.constant'; -const EMPTY_IMAGE = '/assets/logo/logo.svg'; - -type SelectedModalInfo = { $type: string } & Partial>; +type SelectedModalInfo = { type: string } & Partial>; export default function PostCard({ id, folder_id, image_source, description, created_at, url }: IFolderContent) { const [isBookMark, setIsBookMark] = useState(false); @@ -19,17 +18,17 @@ export default function PostCard({ id, folder_id, image_source, description, cre const [isModalShow, setIsModalShow] = useState(false); const [modalType, setModalType] = useState({ $card_Id: '', - $type: '', + type: '', }); const [modalData, setModalData] = useState>(); - const handelerBookMarkActive = () => setIsBookMark((prev) => !prev); - const handelerCardDropdown = () => setIsCardMenu((prev) => !prev); + const handlerBookMarkActive = () => setIsBookMark((prev) => !prev); + const handlerCardDropdown = () => setIsCardMenu((prev) => !prev); const handleModalOpen = (type: string) => { // 미트볼메뉴-삭제하기 if (type === 'linkDelete') { setModalType({ - $type: type, + type: type, $card_Id: `${id}`, $descText: url, }); @@ -37,7 +36,7 @@ export default function PostCard({ id, folder_id, image_source, description, cre // 미트볼메뉴-폴더에추가 if (type === 'folderInAdd') { setModalType({ - $type: type, + type: type, }); } setIsModalShow(true); @@ -47,13 +46,9 @@ export default function PostCard({ id, folder_id, image_source, description, cre setIsModalShow(false); }; - const date = useMemo(() => { - return new Date(`${created_at}`); - }, []); - const handleModalProps = async () => { // 클릭한 link의 폴더명 - const resMenu = await instance.get(`/folders`); + const resMenu = await instance.get(`/users/1/folders`); const folderName = resMenu.data.data; if (folderName) setModalData(folderName); }; @@ -67,7 +62,7 @@ export default function PostCard({ id, folder_id, image_source, description, cre + onClick={handlerBookMarkActive}> 북마크버튼 {description} -

{date.toLocaleString()}

+

{new Date(`${created_at}`).toLocaleString()}

@@ -65,7 +65,7 @@ function Modal({ onOpen, onClose, $type, $card_Id, $folder_Id, $descText, $modal )} -
- {errors.password?.message} - - - - - - 소셜 로그인 -
- - 구글로고 - - - 카카오로고 - -
-
- - - ); -} diff --git a/pages/signup/index.tsx b/pages/signup/index.tsx deleted file mode 100644 index d5dc0b456..000000000 --- a/pages/signup/index.tsx +++ /dev/null @@ -1,250 +0,0 @@ -import { FontSM, Relative } from '@/styles/commonStyle'; -import LinkButton from '@/components/common/atoms/LinkButton'; -import Button from '@/components/common/atoms/Button'; -import { ErrorText, FormRowBox, FormWrap } from '@/components/join/formStyle'; -import { JoinAccessControlBox, JoinBody, JoinTitle, JoinWrap, JoinSocial } from '../../styles/loginStyle'; -import { useEffect, useState } from 'react'; -import { useForm } from 'react-hook-form'; -import { joinInstance } from '@/lib/axios'; -import { useRouter } from 'next/router'; -import { IJoinForm } from '@/components/join/interfase'; -import { GetServerSidePropsContext } from 'next'; -import Image from 'next/image'; -import Loading from '@/components/loading/Loading'; - -const BASE_PAGE_URL = '/'; -const SIGNUP_PAGE_URL = '/signup'; - -export async function getServerSideProps(contaxt: GetServerSidePropsContext) { - const { req, resolvedUrl } = contaxt; - const isSignupPage = resolvedUrl === SIGNUP_PAGE_URL; - - if (req.headers.referer) { - // 내부 접속 - if (req.headers.cookie) { - return { - redirect: { - destination: req.headers.referer, - permanent: false, - }, - }; - } - } - - if (!req.headers.referer) { - //외부 접속 - if (req.headers.cookie) { - return { - redirect: { - destination: BASE_PAGE_URL, - permanent: false, - }, - }; - } - } - - if (!req.headers.cookie && !isSignupPage) { - return { - redirect: { - destination: SIGNUP_PAGE_URL, - permanent: false, - }, - }; - } - - return { props: {} }; -} - -export default function SignUp() { - const router = useRouter(); - const [pwVisibility, setPwVisibility] = useState(false); - const [pwConfirmVisibility, setPwConfirmVisibility] = useState(false); - const { - register, - handleSubmit, - formState: { errors }, - setError, - setValue, - } = useForm({ mode: 'onBlur' }); - const [isStylesLoaded, setIsStylesLoaded] = useState(false); - - const handleEmailCheck = async (email: IJoinForm['email']) => { - try { - const res = await joinInstance.post('/check-email', { email }); - if (res) { - return true; - } - } catch { - setError('email', { message: '사용중인 이메일 입니다.' }, { shouldFocus: true }); - return; - } - }; - - const handlePassWordCheck = (password: IJoinForm['password'], passwordConfirm: IJoinForm['passwordConfirm']) => { - if (password !== passwordConfirm) { - setError('passwordConfirm', { message: '비밀번호가 다릅니다.' }, { shouldFocus: true }); - } - }; - - const handleValid = (data: IJoinForm) => { - const { password, passwordConfirm } = data; - // 비밀번호 같은지 확인 - handlePassWordCheck(password, passwordConfirm); - router.push('/folder'); - }; - - useEffect(() => { - if (localStorage.getItem('linkbrary')) { - alert('로그인한 상태입니다.'); - router.push('/folder'); - } - setIsStylesLoaded(true); - }, [router]); - - if (!isStylesLoaded) return ; - - return ( - - - - - linkbrary - - - - 이미 회원이신가요? - 로그인 하기 - - -
- {/* 이메일 */} - - - handleEmailCheck(e.target.value), - })} - type='email' - id='input__id-element' - placeholder='이메일을 입력해 주세요.' - className={errors.email ? 'error' : ''} - /> - {/* onBlur: (e) => handleEmailCheck(e.target.value) == undefined || '있는 아이디', */} - {errors.email?.message} - - {/* 비밀번호 */} - - - - - - - {errors.password?.message} - - {/* 비밀번호 확인*/} - - - - - - - {errors.passwordConfirm?.message} - - -
-
- - 다른 방식으로 가입하기 -
- - 구글로고 - - - 카카오로고 - -
-
-
-
- ); -} diff --git a/public/assets/icon/icon_dotte.svg b/public/assets/icon/icon_dotted.svg similarity index 100% rename from public/assets/icon/icon_dotte.svg rename to public/assets/icon/icon_dotted.svg diff --git a/src/constant/api.ts b/src/constant/api.ts deleted file mode 100644 index 58667237d..000000000 --- a/src/constant/api.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const BASE_URL = 'https://bootcamp-api.codeit.kr/api/users/1'; - -export const FOLDER_MENU_LIST_API = `${BASE_URL}/folders`; -export const FOLDER_CONTENT_LIST_API = `${BASE_URL}/links`; diff --git a/src/constant/image.constant.ts b/src/constant/image.constant.ts new file mode 100644 index 000000000..ac4121b18 --- /dev/null +++ b/src/constant/image.constant.ts @@ -0,0 +1,15 @@ +// logo +export const LINKBRARY_LOGO = '/assets/logo/logo.svg'; + +// sns +export const GOOGLE = { + NAME: '구글로고', + LINK: 'https://www.google.co.kr/?hl=ko', + CIRCLE_LOG: '/assets/icon/icon_google.png', +}; + +export const KAKAO = { + NAME: 'KAKAO로고', + LINK: 'https://www.kakaocorp.com/page/', + CIRCLE_LOG: '/assets/icon/icon_kakao.png', +}; diff --git a/src/constant/layoutConfig.ts b/src/constant/layoutConfig.ts deleted file mode 100644 index cb059d0a9..000000000 --- a/src/constant/layoutConfig.ts +++ /dev/null @@ -1,38 +0,0 @@ -interface IPageLayoutConfig { - [key: string]: { - [key: string]: boolean; - }; -} - -export type urlName = keyof IPageLayoutConfig; - -export const pageLayoutConfig: IPageLayoutConfig = { - main: { - header: true, - footer: true, - }, - folder: { - header: true, - footer: true, - }, - faq: { - header: true, - footer: true, - }, - signin: { - header: false, - footer: false, - }, - signup: { - header: false, - footer: false, - }, - policy: { - header: true, - footer: true, - }, - notfound: { - header: true, - footer: true, - }, -}; diff --git a/src/constant/modal.ts b/src/constant/modal.constant.ts similarity index 95% rename from src/constant/modal.ts rename to src/constant/modal.constant.ts index b8cf94747..99e47ba13 100644 --- a/src/constant/modal.ts +++ b/src/constant/modal.constant.ts @@ -16,7 +16,7 @@ interface IModalItem { // 폴더에 추가의 폴더메뉴 리스트 export async function fetchFolderInAddData() { try { - const resMenu = await instance.get(`/folders`); + const resMenu = await instance.get(`/users/1/folders`); return resMenu.data; } catch (error) { console.error('Error fetching folder data:', error); diff --git a/src/constant/share.ts b/src/constant/share.constant.ts similarity index 100% rename from src/constant/share.ts rename to src/constant/share.constant.ts diff --git a/src/utils/localStorage.ts b/src/utils/localStorage.ts new file mode 100644 index 000000000..54da1fb9e --- /dev/null +++ b/src/utils/localStorage.ts @@ -0,0 +1,18 @@ +type LocalStorageKey = string; +type AuthToken = string; + +// set +export function setLocalStorage(key: LocalStorageKey, token: AuthToken) { + localStorage.setItem(key, token); +} + +// get +export function getLocalStorage(key: LocalStorageKey): string | null { + const accessToken = localStorage.getItem(key); + return accessToken; +} + +// remove +export function removeLocalStorage(key: LocalStorageKey) { + localStorage.removeItem(key); +} diff --git a/styles/commonStyle.ts b/styles/commonStyle.ts index 7581d7f1c..9ce3892a6 100644 --- a/styles/commonStyle.ts +++ b/styles/commonStyle.ts @@ -70,7 +70,7 @@ export const TitleMs = styled.h3` line-height: 1.79rem; } `; -export const ModlaTitle = styled.h2` +export const ModalTitle = styled.h2` font-size: ${theme.font.l}; font-weight: 700; text-align: center; diff --git a/styles/folderStyle.ts b/styles/folderStyle.ts index b82915ea3..f994d4449 100644 --- a/styles/folderStyle.ts +++ b/styles/folderStyle.ts @@ -43,7 +43,7 @@ export const LinkAddHeadInner = styled.div` z-index: 100; } - .button--gradient.mideum { + .button--gradient.medium { position: absolute; right: 20px; top: 50%; @@ -54,7 +54,7 @@ export const LinkAddHeadInner = styled.div` @media screen and (max-width: ${theme.screenSize.moLarge}) { padding: 16px 32px; - .button--gradient.mideum { + .button--gradient.medium { right: 12px; } } @@ -66,7 +66,7 @@ export const BodyInner = styled(ContainBodyInner)` export const PostCardWrap = styled.div` display: grid; - grid-template-columns: repeat(3, minmax(33.3333%, 1fr)); + grid-template-columns: repeat(3, 1fr); gap: 1.5625rem 1.25rem; @media screen and (max-width: 1124px) { diff --git a/tsconfig.json b/tsconfig.json index 0b4d0e593..098117327 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,15 +21,21 @@ "@/*": [ "./*" ] - } + }, + "plugins": [ + { + "name": "next" + } + ] }, "include": [ "next-env.d.ts", "**/*.ts", "**/*.tsx", - "next.config.js" + "next.config.js", + ".next/types/**/*.ts" ], "exclude": [ "node_modules" ] -} \ No newline at end of file +}