Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
93ee9ce
Document: yml파일 수정
mungyun1 Nov 5, 2024
4932dff
Feat: /api auth.ts 파일 추가
junjeeong Nov 6, 2024
541b278
Feat: images 및 icons 폴더 생성
mungyun1 Nov 6, 2024
b0fd85b
Feat: 프리티어 설정
mungyun1 Nov 6, 2024
5362bda
Fix: lint 오류 수정
mungyun1 Nov 6, 2024
e118a60
Feat: 공통 Button 컴포넌트 구현
mungyun1 Nov 6, 2024
b2e9a39
Design : 모달 UI 기본 구성
hongggyelim Nov 6, 2024
f16e087
Design: Layout 분리 및 즐겨찾기 페이지 UI 구현
99minji Nov 6, 2024
0e91bf4
Merge branch 'develop' into 정준영/api함수-세팅
junjeeong Nov 6, 2024
f5b5f11
Delete: 작업내역 삭제
hongggyelim Nov 6, 2024
82a1a66
Merge branch 'develop' of https://github.com/codeit9-temporary/linkbr…
99minji Nov 6, 2024
0c1ecba
Comments: favorite 주석 추가
99minji Nov 6, 2024
edaea46
Fix: 버튼 코드 리뷰 반영 수정
mungyun1 Nov 6, 2024
66dd303
Fix: 버튼 hover 추가
mungyun1 Nov 6, 2024
a8e56a5
Feat: 공통 Button 컴포넌트 구현
mungyun Nov 6, 2024
cfe2046
Merge branch 'develop' of https://github.com/codeit9-temporary/linkbr…
99minji Nov 6, 2024
9d55550
Feat: /lib_/api 함수 세팅
junjeeong Nov 6, 2024
04cb936
Merge branch '정준영/api함수-세팅' into feature/api함수-세팅
junjeeong Nov 6, 2024
36968af
Feat:헤더 구현 & 버튼 수정
venise5224 Nov 6, 2024
0a6f8d6
Refactor: onClick 코드 수정
venise5224 Nov 6, 2024
b8f4cd4
Merge pull request #17 from codeit9-temporary/feature/api함수-세팅
junjeeong Nov 6, 2024
1529256
Refactor: onClick 코드 수정
venise5224 Nov 6, 2024
899a7b9
Merge branch 'develop' of https://github.com/codeit9-temporary/linkbr…
venise5224 Nov 6, 2024
292a07e
Merge pull request #15 from codeit9-temporary/feature/favorite
99minji Nov 6, 2024
7aad49c
Merge branch 'develop' of https://github.com/codeit9-temporary/linkbr…
venise5224 Nov 6, 2024
ea95d74
Fix: 오류 수정
venise5224 Nov 6, 2024
9d57a97
Merge pull request #20 from codeit9-temporary/feature/Header
venise5224 Nov 6, 2024
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
8 changes: 7 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
{
"extends": ["next/core-web-vitals", "next/typescript"]
"extends": [
"next/core-web-vitals",
"plugin:prettier/recommended" // Prettier와 충돌 방지
],
"rules": {
"prettier/prettier": ["error"] // Prettier의 규칙을 ESLint가 오류로 처리
}
}
7 changes: 4 additions & 3 deletions .github/workflows/linkbrary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ name: Linkbrary CI
on:
push:
branches:
- main # main 브랜치에 푸시될 때 실행
- main # main 브랜치에 푸시될 때 실행
- develop
pull_request:
branches:
- develop # main 브랜치로의 PR이 생성될 때 실행
- develop # main 브랜치로의 PR이 생성될 때 실행

jobs:
lint-and-build:
Expand All @@ -19,7 +20,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '20.15.1' # 현재 사용 중인 Node.js 버전
node-version: "20.15.1" # 현재 사용 중인 Node.js 버전

- name: Install dependencies
run: npm install
Expand Down
9 changes: 9 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"semi": true,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 80,
"arrowParens": "always",
"endOfLine": "auto"
}
40 changes: 40 additions & 0 deletions components/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { ReactNode, ButtonHTMLAttributes } from "react";

interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
children: ReactNode;
width?: string;
height?: string;
radius?: string;
color?: "positive" | "negative";
size?: string;
}

const Button = ({
children,
width = "auto",
height = "53px",
radius = "8px",
color = "positive",
size = "18px",
...props
}: ButtonProps) => {
const backgroundStyle =
color === "positive"
? "linear-gradient(90.99deg, #6D6AFE 0.12%, #6AE3FE 101.84%)"
: "#FF5B56";

return (
<button
style={{
borderRadius: radius,
background: backgroundStyle,
}}
className={`flex justify-center ${width} ${height} ${size} items-center text-white font-[600] whitespace-nowrap hover:opacity-90`}
{...props}
>
{children}
</button>
);
};

export default Button;
52 changes: 52 additions & 0 deletions components/HeaderMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import Image from "next/image";
import Profile from "@/public/icons/profile.png";
import Star from "@/public/icons/star.png";
import Link from "next/link";
import Button from "./Button";
import { useRouter } from "next/router";

const HeaderMenu = () => {
const isLoggedIn = false;
const router = useRouter();

return (
<>
{!isLoggedIn ? (
<Button
onClick={() => {
router.push("/login");
}}
width="w-[80px] md:w-[128px]"
height="h-[37px] md:h-[53px]"
size="text-[14px] md:text-[18px]"
type="button"
>
로그인
</Button>
) : (
<div className="flex items-center gap-[24px]">
<Link
href={"/favorite"}
className="flex items-center gap-[6px] bg-gray200 border border-purple100 rounded-[4px] py-[10px] px-[12px] text-[12px] leading-[14.32px] md:text-[14px] md:leading-[16.71px] font-normal"
>
<Image
src={Star}
width={14}
height={17}
alt=""
className="align-top"
/>
즐겨찾기
</Link>
<div className="flex items-center gap-[6px] text-[14px] leading-[16.71px] font-normal">
<Image src={Profile} width={28} height={28} alt="프로필" />
{/* 임시 유저 네임 */}
<span className="hidden md:block">전상민</span>
</div>
</div>
)}
</>
);
};

export default HeaderMenu;
15 changes: 15 additions & 0 deletions components/Layout/CardsLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react";

interface CardsLayoutProps {
children: React.ReactNode;
}

const CardsLayout = ({ children }: CardsLayoutProps) => {
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5 md:gap-6 lg:gap-[10px] w-full">
{children}
</div>
);
};

export default CardsLayout;
15 changes: 15 additions & 0 deletions components/Layout/ContentLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react";

interface ContentLayoutProps {
children: React.ReactNode;
}

const ContentLayout = ({ children }: ContentLayoutProps) => {
return (
<div className="w-full max-w-[1125px] mx-auto p-[10px] md:p-10 px-[32.5px]">
{children}
</div>
);
};

export default ContentLayout;
24 changes: 24 additions & 0 deletions components/Layout/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Logo from "@/public/icons/logo.svg";
import Image from "next/image";
import Link from "next/link";
import HeaderMenu from "../HeaderMenu";

const Header = () => {
return (
<div>
<div className="bg-gray100 py-[13px] px-[32px] md:py-[33px] md:px-[200px]">
<div className="flex justify-between items-center max-w-[1520px]">
<Link
href={"/"}
className="w-[88.67px] h-[16px] md:w-[133px] md:h-[24px]"
>
<Image src={Logo} width={133} height={24} alt="로고" />
</Link>
<HeaderMenu />
</div>
</div>
</div>
);
};

export default Header;
65 changes: 65 additions & 0 deletions lib/api/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import axiosInstance from "./axiosInstanceApi";

interface signInProps {
email: string;
password: string;
}

interface signUpProps extends signInProps {
name: string;
}

interface easySignInProps {
token: string;
redirectUri: string;
}

interface easySignUpProps extends easySignInProps {
name: string;
}

// 회원가입
export const postSignUp = async (body: signUpProps) => {
try {
const res = await axiosInstance.post("/auth/sign-up", body);
if (res.status >= 200 && res.status < 300) return res.data;
} catch (err) {
console.error("에러 메시지: ", err instanceof Error ? err.message : err);
}
};

// 로그인
export const postSignIn = async (body: signInProps) => {
try {
const res = await axiosInstance.post("/auth/sign-in", body);
if (res.status >= 200 && res.status < 300) return res.data;
} catch (err) {
console.error("에러 메시지: ", err instanceof Error ? err.message : err);
}
};

// 간편 회원가입
export const postEasySignUp = async (
provider: "google" | "kakao",
body: easySignUpProps
) => {
try {
const res = await axiosInstance.post(`/auth/sign-up/${provider}`, body);
if (res.status >= 200 && res.status < 300) return res.data;
} catch (err) {
console.error("에러 메시지: ", err instanceof Error ? err.message : err);
}
};

// 간편 로그인
export const postEasySignIn = async (
provider: "google" | "kakao",
body: easySignInProps
) => {
try {
const res = await axiosInstance.post(`/auth/sign-in/${provider}`, body);
if (res.status >= 200 && res.status < 300) return res.data;
} catch (err) {
console.error("에러 메시지: ", err instanceof Error ? err.message : err);
}
};
6 changes: 6 additions & 0 deletions lib/api/axiosInstanceApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,10 @@ const axiosInstance = axios.create({
timeout: 5000,
});

export const proxy = axios.create({
// 배포 이후에는 배포된 URL로 변경해야 함.
baseURL: "http://localhost:3000",
timeout: 5000,
});

export default axiosInstance;
55 changes: 55 additions & 0 deletions lib/api/folder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import axiosInstance, { proxy } from "./axiosInstanceApi";

interface folderApiProps {
name: string;
}

// 유저의 모든 폴더 조회(auth)
export const getFolders = async () => {
try {
const res = await proxy.get("/api/folders");
if (res.status >= 200 && res.status < 300) return res.data;
} catch (err) {
console.error("에러 메시지: ", err instanceof Error ? err.message : err);
}
};

// 유저의 폴더 생성(auth)
export const postFolders = async (body: folderApiProps) => {
try {
const res = await proxy.post("/api/folders", body);
if (res.status >= 200 && res.status < 300) return res.data;
} catch (err) {
console.error("에러 메시지: ", err instanceof Error ? err.message : err);
}
};

// 폴더 조회
export const getFolder = async (forderId: number) => {
try {
const res = await axiosInstance.get(`/folders/${forderId}`);
if (res.status >= 200 && res.status < 300) return res.data;
} catch (err) {
console.error("에러 메시지: ", err instanceof Error ? err.message : err);
}
};

// 폴더 삭제(auth)
export const deleteFolder = async (forderId: number) => {
try {
const res = await proxy.delete(`/api/folders/${forderId}`);
if (res.status >= 200 && res.status < 300) return res.data;
} catch (err) {
console.error("에러 메시지: ", err instanceof Error ? err.message : err);
}
};

// 폴더 이름 수정(auth)
export const putFolder = async (forderId: number, body: folderApiProps) => {
try {
const res = await proxy.put(`/api/folders/${forderId}`, body);
if (res.status >= 200 && res.status < 300) return res.data;
} catch (err) {
console.error("에러 메시지: ", err instanceof Error ? err.message : err);
}
};
Loading
Loading