Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Review์šฉ PR #1

Open
wants to merge 53 commits into
base: empty
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
438bbae
Initial commit from Create Next App
Yeonseo-Jo Mar 31, 2024
9bcce41
init: vanilla extract ์„ค์น˜ ๋ฐ ์„ค์ •
Yeonseo-Jo Apr 7, 2024
5f81e01
init: axios, tanstack query ์„ค์น˜
Yeonseo-Jo Apr 7, 2024
afd7520
init: ์•ˆ์“ฐ๋Š” ํŒŒ์ผ ์ œ๊ฑฐ
Yeonseo-Jo Apr 7, 2024
e9b46fd
init: global, reset css ์ถ”๊ฐ€
Yeonseo-Jo Apr 7, 2024
08f435c
init: ๋ฉ”ํƒ€ ๋ฐ์ดํ„ฐ ์ˆ˜์ •
Yeonseo-Jo Apr 7, 2024
752bd48
feat: React Query Provider ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ ๋ฐ ์ตœ์ƒ์œ„ layout์— ์ ์šฉ
Yeonseo-Jo Apr 8, 2024
b096771
feat: axios ๊ณตํ†ต instance ์ƒ์„ฑ
Yeonseo-Jo Apr 8, 2024
51905be
feat: ๋ผ์šฐํŒ… ํ•  ํŽ˜์ด์ง€ ๊ตฌ์„ฑ
Yeonseo-Jo Apr 8, 2024
01de1c7
feat: ๊นƒํ—ˆ๋ธŒ ๋กœ๊ณ  ์ด๋ฏธ์ง€ ์ถ”๊ฐ€
Yeonseo-Jo Apr 8, 2024
c348690
fix: ์„ค์ • ๊ด€๋ จ style ํŒŒ์ผ๋“ค ํด๋” ๊ตฌ์กฐ ์ด๋™, ๋„ค์ด๋ฐ ๋ณ€๊ฒฝ
Yeonseo-Jo Apr 8, 2024
5445c08
feat: ๊ณตํ†ต ํ—ค๋” ๊ตฌํ˜„
Yeonseo-Jo Apr 8, 2024
2f7f3ae
feat: Layout ์ƒ์„ฑ ๋ฐ Layout์— ํ—ค๋” ์ถ”๊ฐ€
Yeonseo-Jo Apr 8, 2024
486e231
feat: ํ™ˆ ํ™”๋ฉด ui ๊ตฌํ˜„
Yeonseo-Jo Apr 8, 2024
ab9c17c
fix: token ์ž…๋ ฅ ๋ฐ ์ œ์ถœํ•˜๋Š” ๋ถ€๋ถ„ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌ
Yeonseo-Jo Apr 9, 2024
6c31713
fix : axios instance ์ˆ˜์ • ๋ฐ instance defaults๋ฅผ ํ†ตํ•ด ํ† ํฐ ์ €์žฅ ํ•จ์ˆ˜ ์ƒ์„ฑ
Yeonseo-Jo Apr 9, 2024
71f0703
feat: ํ† ํฐ ์ž…๋ ฅ ๋ฐ›๋Š” ๋กœ์ง ๊ตฌํ˜„
Yeonseo-Jo Apr 9, 2024
3000bd8
fix: ํŽ˜์ด์ง€ ์ด๋™ ๋ฒ„ํŠผ Link ํƒœ๊ทธ๋กœ ๊ฐ์‹ธ๊ธฐ
Yeonseo-Jo Apr 10, 2024
a81c704
feat: User data type ์ง€์ •
Yeonseo-Jo Apr 10, 2024
b1209ba
feat: user profile ์ •๋ณด getํ•˜๋Š” ๋ฐ์ดํ„ฐ ํŒจ์นญ ํ•จ์ˆ˜ ์ž‘์„ฑ
Yeonseo-Jo Apr 10, 2024
dc8c0b9
feat: user follow ์ •๋ณด get ํ•˜๋Š” ๋ฐ์ดํ„ฐ ํŒจ์นญ ํ•จ์ˆ˜ ์ž‘์„ฑ
Yeonseo-Jo Apr 10, 2024
9a85ca7
feat: user ์ •๋ณด ๊ฐ€์ ธ์˜ค๋Š” react-query ํŒจ์นญ hook ์ž‘์„ฑ ๋ฐ ํ…Œ์ŠคํŠธ
Yeonseo-Jo Apr 10, 2024
232393e
feat: ์œ ์ € ํ”„๋กœํ•„ ์ปดํฌ๋„ŒํŠธ ui ๊ตฌํ˜„
Yeonseo-Jo Apr 10, 2024
4666379
feat: next/image ๊ด€๋ จ ์„ค์ •(๋„๋ฉ”์ธ ํ—ˆ์šฉ)
Yeonseo-Jo Apr 10, 2024
87f6979
fix: useGetCombinedUserInfo data ํƒ€์ž… ์„ธ๋ถ€ ์ง€์ •
Yeonseo-Jo Apr 10, 2024
b36c384
feat : user ํ”„๋กœํ•„ ๋ถ€๋ถ„ ๋ฐ์ดํ„ฐ ์—ฐ๊ฒฐ
Yeonseo-Jo Apr 10, 2024
5acad80
feat: followListPage css ์ถ”๊ฐ€
Yeonseo-Jo Apr 10, 2024
7b878be
feat : followList ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ ๋ฐ ์Šคํƒ€์ผ๋ง
Yeonseo-Jo Apr 10, 2024
2df5c94
fix: ์Šคํƒ€์ผ๋ง ์ˆ˜์ •
Yeonseo-Jo Apr 10, 2024
54c6d64
feat: follow ์‚ญ์ œ ํ•˜๋Š” ๋ฐ์ดํ„ฐ ํŒจ์นญ ํ•จ์ˆ˜ ์ •์˜
Yeonseo-Jo Apr 10, 2024
4b5d05f
feat: ํŒ”๋กœ์šฐ ํ•˜๋Š” ๋ฐ์ดํ„ฐ ํŒจ์นญ ํ•จ์ˆ˜ ์ •์˜
Yeonseo-Jo Apr 10, 2024
884356a
feat: ํŒ”๋กœ์šฐ ํ›„ mutateํ•œ ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ปค์Šคํ…€ ํ›… ์ž‘์„ฑ
Yeonseo-Jo Apr 10, 2024
1162224
feat: ์–ธํŒ”๋กœ์šฐ ํ›„ mutate ๋œ ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ปค์Šคํ…€ ํ›… ์ž‘์„ฑ
Yeonseo-Jo Apr 10, 2024
1b08f75
feat: ํŒ”๋กœ์šฐ, ์–ธํŒ”๋กœ์šฐ ๋ฒ„ํŠผ ํ•ธ๋“ค๋Ÿฌ ๋ถ™์ด๊ธฐ
Yeonseo-Jo Apr 10, 2024
eb45bf1
fix: ๋ธŒ๋ผ์šฐ์ € ์บ์‹ฑ ๊ด€๋ จ ํ—ค๋” ์„ค์ • ์ถ”๊ฐ€
Yeonseo-Jo Apr 10, 2024
e3b1c20
fix: follow ์ˆซ์ž ๋ณ€๋™ ํ”„๋กœํ•„์— ๋ฐ”๋กœ ๋ฐ˜์˜ํ•˜๊ธฐ ์œ„ํ•ด ๋กœ์ง ๋ณ€๊ฒฝ
Yeonseo-Jo Apr 10, 2024
ca52a21
feat: mutation ๊ณตํ†ต ์ปค์Šคํ…€ ํ•จ์ˆ˜ ์ƒ์„ฑ
Yeonseo-Jo Apr 10, 2024
60d37d3
fix: mutation ๊ณตํ†ต ํ•จ์ˆ˜ ์‚ฌ์šฉ
Yeonseo-Jo Apr 10, 2024
f6714f1
fix: followList ๋ถ€๋ถ„ ๊ณตํ†ต ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ
Yeonseo-Jo Apr 10, 2024
59a7188
fix: query key ์ƒ์ˆ˜ ๊ด€๋ฆฌ
Yeonseo-Jo Apr 10, 2024
5aefd92
feat: sessionStorage ์‚ฌ์šฉํ•˜๋Š” ์œ ํ‹ธ ํ•จ์ˆ˜ ์ •์˜
Yeonseo-Jo Apr 11, 2024
d094f85
fix: ์ƒˆ๋กœ ๊ณ ์นจ ์‹œ์—๋„ ํ† ํฐ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์„ธ์…˜ ์Šคํ† ๋ฆฌ์ง€ ์‚ฌ์šฉ
Yeonseo-Jo Apr 11, 2024
1570df4
fix : ํ† ํฐ ์ž…๋ ฅ ๊ฐ’์— ๋”ฐ๋ผ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” ๋น„ํ™œ์„ฑํ™” ์Šคํƒ€์ผ ๊ตฌ๋ถ„
Yeonseo-Jo Apr 11, 2024
94cf01a
feat: ๋กœ๋”ฉ ์ค‘ ์Šค์ผˆ๋ ˆํ†ค UI ๊ตฌํ˜„
Yeonseo-Jo Apr 11, 2024
549a047
feat : ์—๋Ÿฌ ํŽ˜์ด์ง€ ๊ตฌํ˜„
Yeonseo-Jo Apr 11, 2024
efa686c
fix: sessionStorage is not defined ์ด์Šˆ ํ•ด๊ฒฐ
Yeonseo-Jo Apr 11, 2024
bc637f4
fix: token ๋งŒ๋“ค๋Ÿฌ ๊ฐ€๊ธฐ hoverStyle ๋ณ€๊ฒฝ
Yeonseo-Jo Apr 11, 2024
562235d
Merge branch 'empty' into review
Yeonseo-Jo Apr 11, 2024
be0d995
fix: image/domain deprecated ์ด์Šˆ ํ•ด๊ฒฐ
Yeonseo-Jo Apr 17, 2024
95132be
fix: boolean type ์ถ”๋ก  ๋˜๋Š” ์‚ผํ•ญ ์—ฐ์‚ฐ์ž -> && ์—ฐ์‚ฐ์œผ๋กœ ๋กœ์ง ๋ณ€๊ฒฝ (isHasToken)
Yeonseo-Jo Apr 17, 2024
168c587
fix: button type ์ถ”๊ฐ€
Yeonseo-Jo Apr 17, 2024
33aa0c3
fix: token ์ž…๋ ฅ ๋ฒ„ํŠผ disabled๋กœ ๋กœ์ง ์ˆ˜์ •
Yeonseo-Jo Apr 17, 2024
5916a35
fix: ์—๋Ÿฌ์‹œ ํ† ํฐ ์‚ญ์ œ ๋กœ์ง ์ถ”๊ฐ€
Yeonseo-Jo Apr 17, 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
3 changes: 3 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
36 changes: 36 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
7 changes: 7 additions & 0 deletions apis/follow/deleteFollower.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { instance } from "..";

export const deleteFollower = async (username: string) => {
const response = await instance.delete(`/user/following/${username}`);

return response;
};
7 changes: 7 additions & 0 deletions apis/follow/putFollower.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { instance } from "..";

export const putFollower = async (username: string) => {
const response = await instance.put(`/user/following/${username}`);

return response;
};
15 changes: 15 additions & 0 deletions apis/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import axios, { AxiosInstance } from "axios";

export const instance: AxiosInstance = axios.create({
baseURL: process.env.NEXT_PUBLIC_BASE_URL,
headers: {
Accept: "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28",
"If-None-Match": "",
},
});

// token ์ž…๋ ฅ ํ›„ ํ—ค๋”์— ์ €์žฅํ•˜๋Š” ํ•จ์ˆ˜
export const setInstanceToken = (token: string) => {
instance.defaults.headers.common["Authorization"] = `Bearer ${token}`;

Choose a reason for hiding this comment

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

P5: ๋ฐ˜๋“œ์‹œ ํ† ํฐ์„ ๋„ฃ์–ด์ค˜์•ผ ํ•˜๋‹ˆ๊นŒ ์š”์ฒญ์ด ๊ฐ€๊ธฐ ์ „์— ์ด๊ฑธ ๋บ์–ด์™€์„œ ํ† ํฐ ๊ฐ’์„ ๋„ฃ์–ด์ค˜์•ผ๊ฒ ๋‹ค! ๋ผ๊ณ  ์ƒ๊ฐํ•ด์„œ, interceptor๋ฅผ ํ™œ์šฉํ•ด์„œ ๊ตฌํ˜„ํ–ˆ๋Š”๋ฐ์š”..!
๋‹ค์‹œ axios๋ž‘ AxiosInstance์— ๋Œ€ํ•ด ์ฐฌ์ฐฌํžˆ ์ฐพ์•„๋ณด๋‹ˆ, ์–ด์ฐจํ”ผ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ† ํฐ์ด ์žˆ์–ด์•ผ ๋™์ž‘ํ•˜๋Š” ๋ถ€๋ถ„์ด๋ผ์„œ interceptor์™€ ๊ฐ™์€ ์˜ˆ์™ธ์ ์ธ ์„ค์ •์„ ํ•ด์ค„ ํ•„์š”์—†์ด ๊ธฐ๋ณธ๊ฐ’(defaults)์œผ๋กœ ๋„ฃ์–ด์ฃผ๋Š”๊ฒŒ ๋” ๋งž๋Š” ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹น. . !

๋ช…ํ™•ํ•œ ๊ธฐ์ค€์ด ์žˆ๋‹ค๊ธฐ ๋ณด๋‹จ ๊ทธ๋•Œ ๊ทธ๋•Œ ์ƒํ™ฉ์„ ์ž˜ ํŒ๋‹จํ•˜๊ณ  ์ž˜ ์„ ํƒํ•˜๋Š”๊ฒŒ ์ค‘์š”ํ•œ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ๊ฑธ ๋‹ค์‹œ ํ•œ ๋ฒˆ ๋Š๋ผ๊ณ  ๊ฐ‘๋‹ˆ๋‹ค ..~

};
16 changes: 16 additions & 0 deletions apis/user/getUserFollowInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { UserTypes } from "@/types/user/UserTypes";
import { instance } from "..";

const PER_PAGE = 100;

export const getUserFollowInfo = async () => {
const { data: followingData } = await instance.get<Array<UserTypes>>(
`/user/following?per_page=${PER_PAGE}`
);

const { data: followersData } = await instance.get<Array<UserTypes>>(
`user/followers?per_page=${PER_PAGE}`
);

return { followingData, followersData };
};
7 changes: 7 additions & 0 deletions apis/user/getUserProfileInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { UserProfileInfoTypes } from "@/types/user/UserTypes";
import { instance } from "..";

export const getUserProfileInfo = async () => {
const { data } = await instance.get<UserProfileInfoTypes>("/user");
return data;
};
27 changes: 27 additions & 0 deletions app/(home)/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import TokenInputContainer from "@/components/home/TokenInputContainer.tsx";
import Link from "next/link";
import * as styles from "../../styles/home/HomeContainerStyle.css.ts";

const HomePage = () => {
return (
<section className={styles.HomeWrapper}>
<article className={styles.TokenBoxContainer}>
<div className={styles.TokenLinkBox}>
<Link
href={"https://github.com/settings/tokens"}
className={styles.TokenLinkBtn}
target="_blank"
>
Github Token ๋งŒ๋“ค๋Ÿฌ ๊ฐ€๊ธฐ
</Link>
<p className={styles.TokenInfoText}>
๏น’ ํ† ํฐ ๋ฐœ๊ธ‰ ์‹œ ๊ถŒํ•œ user(Update ALL user data)๋ฅผ ์ฒดํฌํ•ด์ฃผ์„ธ์š”!
</p>
</div>
<TokenInputContainer />
</article>
</section>
);
};

export default HomePage;
Binary file added app/favicon.ico
Binary file not shown.
47 changes: 47 additions & 0 deletions app/follow-list/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"use client";

import { setInstanceToken } from "@/apis";
import Error from "@/components/common/Error";
import FollowList from "@/components/follow-list/FollowList";
import UserProfile from "@/components/follow-list/UserProfile";
import FollowListSkeleton from "@/components/follow-list/skeletonUi/FollowListSkeleton";
import { useGetCombinedUserInfo } from "@/hooks/user/useGetCombinedUserInfo";
import { getSessionStorageHandler } from "@/utils/getSessionStorageHandler";
import * as styles from "../../styles/follow-list/FollowListPageContainerStyle.css";

const FollowListPage = () => {
const token: string | null =
typeof window !== "undefined"
? getSessionStorageHandler().getItem("token")
: null;
const isHasToken =
typeof window !== "undefined" &&
getSessionStorageHandler().hasItem("token");

const { isLoading, error, data } = useGetCombinedUserInfo();

if (!isHasToken || !token) return <Error />;
setInstanceToken(token);

const userProfileData = data[0];
const followData = data[1];

return (
<section className={styles.FollowListPageWrapper}>
{isLoading && <FollowListSkeleton />}
{error && <Error />}
{!isLoading && !error && (
<UserProfile
userProfile={userProfileData}
followCnt={{
following: followData.followingData.length,
followers: followData.followersData.length,
}}
/>
)}
{!isLoading && !error && <FollowList followData={followData} />}
</section>
);
};

export default FollowListPage;
21 changes: 21 additions & 0 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { Metadata } from "next";

import Layout from "@/components/Layout";
import "../styles/globalStyle.css";

export const metadata: Metadata = {
title: "github ๋งžํŒ” ํƒ์ง€๊ธฐ",
description: "github ํŒ”๋กœ์šฐ ์ƒํƒœ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๋งžํŒ” ํƒ์ง€๊ธฐ์ž…๋‹ˆ๋‹ค.",
};

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="ko">
<Layout>{children}</Layout>
</html>
);
}
20 changes: 20 additions & 0 deletions components/Layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Inter } from "next/font/google";
import React from "react";
import * as styles from "../styles/common/LayoutStyle.css";
import ReactQueryProvider from "./ReactQueryProvider";
import Header from "./common/Header";

const inter = Inter({ subsets: ["latin"] });

const Layout = ({ children }: React.PropsWithChildren) => {
return (
<body className={inter.className}>
<ReactQueryProvider>
<Header />
<main className={styles.LayoutMainStyle}>{children}</main>
</ReactQueryProvider>
</body>
);
};

export default Layout;
13 changes: 13 additions & 0 deletions components/ReactQueryProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"use client";

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import React, { useState } from "react";

const ReactQueryProvider = ({ children }: React.PropsWithChildren) => {
const [queryClient] = useState(new QueryClient());

Choose a reason for hiding this comment

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

ASK: ์•„๋ž˜์™€ ๊ฐ™์€ ํ˜•ํƒœ๊ฐ€ ์•„๋‹ˆ๋ผ ์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ ์ •์˜ํ•˜์‹  ์ด์œ ๊ฐ€ ๋”ฐ๋กœ ์žˆ์„๊นŒ์šฉ!?

Suggested change
const [queryClient] = useState(new QueryClient());
const queryClient = new QueryClient();

Copy link
Owner Author

Choose a reason for hiding this comment

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

๋ฃจ๋ฐ์ด ๋ฆฌ๋ทฐ์— ๋‚จ๊ฒผ๋“ฏ์ด Next.js์—์„œ๋Š” queryprovider์—์„œ queryclient ์ •์˜ ์‹œ ์ฐธ์กฐ๋™์ผ์„ฑ ์œ ์ง€๋ฅผ ์œ„ํ•ด useState๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๊ตฌ ํ•ฉ๋‹ˆ๋‹น!!

return (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
);
};

export default ReactQueryProvider;
38 changes: 38 additions & 0 deletions components/common/Error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"use client";

import * as styles from "@/styles/common/ErrorStyle.css";
import { getSessionStorageHandler } from "@/utils/getSessionStorageHandler";
import { useRouter } from "next/navigation";
import { useEffect } from "react";

const Error = () => {
const router = useRouter();

useEffect(() => {
// ์—๋Ÿฌ ์‹œ sessionStorage์— ์žˆ๋Š” token ์ •๋ณด ์‚ญ์ œ
if (typeof window === undefined) return;
if (!getSessionStorageHandler().hasItem) return;

getSessionStorageHandler().removeItem("token");
}, []);

return (
<section className={styles.ErrorWrapper}>
<div className={styles.ErrorTxtContainer}>
<h2 className={styles.ErrorTitleTxt}>๐Ÿฅบ Error ๐Ÿฅบ</h2>

Choose a reason for hiding this comment

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

ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ ์ž… ์‚์ฃฝ ํ–„ ใ…‹ ใ„ฑใ…‡ใ…‡ ๐Ÿน

<p className={styles.ErrorDescribTxt}>
๏น’์˜ฌ๋ฐ”๋ฅธ token ๊ฐ’์ธ์ง€ ํ™•์ธํ•ด์ฃผ์„ธ์š”
</p>
</div>
<button
className={styles.ErrorBackBtn}
type="button"
onClick={() => router.back()}
>
์ด์ „์œผ๋กœ
</button>
</section>
);
};

export default Error;
22 changes: 22 additions & 0 deletions components/common/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import img_github_logo_white from "@/public/images/img_github_logo_white.png";
import Image from "next/image";
import Link from "next/link";
import * as styles from "../../styles/common/HeaderStyle.css";

const Header = () => {
return (
<header className={styles.HeaderWrapper}>
<Link href="/">

Choose a reason for hiding this comment

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

์˜ค ์ด ๋ถ€๋ถ„ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ์ธก๋ฉด์—์„œ ์ข‹์„ ๊ฒƒ ๊ฐ™๋„ค์š”! !! ์ƒ๊ฐ ๋ชปํ•œ ๋ถ€๋ถ„์ธ๋ฐ ์‡ฝ์ƒฅ ๊ฐ€์ ธ๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹น ~

<Image
src={img_github_logo_white}
alt="๊นƒํ—ˆ๋ธŒ-๋กœ๊ณ "
width={30}
height={30}
/>
</Link>
<h1 className={styles.HeaderTitle}>๊นƒํ—ˆ๋ธŒ ํŒ”๋กœ์šฐ ํƒ์ง€๊ธฐ</h1>
</header>
);
};

export default Header;
50 changes: 50 additions & 0 deletions components/follow-list/FollowList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { LIST_TYPE } from "@/constants/follow-list/LIST_TYPE";
import { UserFollowInfoDataTypes } from "@/types/user/UserTypes";
import { useMemo } from "react";
import * as styles from "../../styles/follow-list/FollowListStyle.css";
import FollowListDetailWrapper from "./FollowListDetailWrapper";

const FollowList = ({
followData,
}: {
followData: UserFollowInfoDataTypes;
}) => {
const { followingData, followersData } = followData;

const getIsMatchInfo = useMemo(() => {
// ๋งžํŒ” ์ค‘์ธ ์‚ฌ๋žŒ๋“ค ๋ฆฌ์ŠคํŠธ
const matchedList = followersData.filter((follower) => {
return followingData.some(
(following) => following.login === follower.login
);
});

// ๋‚˜๋ฅผ ํŒ”๋กœ์šฐ ํ•œ ์‚ฌ๋žŒ๋“ค ์ค‘ ๋‚ด๊ฐ€ ํŒ”๋กœ์šฐ ํ•˜์ง€ ์•Š์€ ์‚ฌ๋žŒ๋“ค ๋ฆฌ์ŠคํŠธ
const unMatchedList = followersData.filter((follower) => {
return !matchedList.includes(follower);
});

return [
{ type: LIST_TYPE.unMatched, list: unMatchedList },
{ type: LIST_TYPE.matched, list: matchedList },
];
Comment on lines +27 to +30

Choose a reason for hiding this comment

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

!!! ๋„ˆ๋ฌด ๊น”๋”ํ•˜๊ณ  ์ข‹๋„ค์š” ๐Ÿ‘๐Ÿ‘

}, [followersData, followingData]);

const matchListData = getIsMatchInfo;

return (
<article className={styles.FollowListWrapper}>
{matchListData.map(({ type, list }) => {
return (
<FollowListDetailWrapper
key={type}
listType={type}
targetMatchList={list}
/>
);
})}
</article>
);
};

export default FollowList;
Loading