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

5주차 미션-제이 #12

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions 제이-김규리/5주차/mission/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
VITE_TMDB_TOKEN=eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIzYjEzNWM0ZTcxOGE0ZGZkNzY5ZDQyNmU4NzgyYzdkZSIsIm5iZiI6MTcyODQ2MDc5OS4xODg5NDIsInN1YiI6IjY3MDBlYWQ5YzlhMTBkNDZlYTdjZmVlNiIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.R3Ahq2PqWhv0O3uaxzQZcsvWRjFVHXJom63Q1qlhufk
VITE_MOVIE_API_URL=https://api.themoviedb.org/3
24 changes: 24 additions & 0 deletions 제이-김규리/5주차/mission/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
8 changes: 8 additions & 0 deletions 제이-김규리/5주차/mission/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# React + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
38 changes: 38 additions & 0 deletions 제이-김규리/5주차/mission/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import js from '@eslint/js'
import globals from 'globals'
import react from 'eslint-plugin-react'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'

export default [
{ ignores: ['dist'] },
{
files: ['**/*.{js,jsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
},
settings: { react: { version: '18.3' } },
plugins: {
react,
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...js.configs.recommended.rules,
...react.configs.recommended.rules,
...react.configs['jsx-runtime'].rules,
...reactHooks.configs.recommended.rules,
'react/jsx-no-target-blank': 'off',
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
},
]
13 changes: 13 additions & 0 deletions 제이-김규리/5주차/mission/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Movie</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
35 changes: 35 additions & 0 deletions 제이-김규리/5주차/mission/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "practice1",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"@hookform/resolvers": "^3.9.0",
"axios": "^1.7.7",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.53.1",
"react-icons": "^5.3.0",
"react-router-dom": "^6.26.2",
"styled-components": "^6.1.13",
"yup": "^1.4.0"
},
"devDependencies": {
"@eslint/js": "^9.11.1",
"@types/react": "^18.3.10",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react-swc": "^3.5.0",
"eslint": "^9.11.1",
"eslint-plugin-react": "^7.37.0",
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.12",
"globals": "^15.9.0",
"vite": "^5.4.8"
}
}
1 change: 1 addition & 0 deletions 제이-김규리/5주차/mission/public/vite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
87 changes: 87 additions & 0 deletions 제이-김규리/5주차/mission/src/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import HomePage from "./pages/home.jsx";
import NotFound from "./pages/not-found.jsx";
import LoginPage from "./pages/login.jsx";
import SignUpPage from "./pages/sign-up.jsx";
import Search from "./pages/search.jsx";
import Movies from "./pages/movies-page/movies.jsx";
import RootLayout from "./layout/root-layout.jsx";
import styled, {createGlobalStyle} from "styled-components";
import UpComingPage from "./pages/movies-page/movies-category/up-coming.jsx";
import NowPlayingPage from "./pages/movies-page/movies-category/now-playing.jsx";
import PopularPage from "./pages/movies-page/movies-category/popular.jsx";
import TopRatedPage from "./pages/movies-page/movies-category/top-rated.jsx";
import DetailPage from "./pages/movies-page/detail.jsx";


const router = createBrowserRouter([
{
path: '/',
element: <RootLayout/>,
errorElement: <NotFound/>,
// Outlet에 들어가는 요소들 ??
children: [
{
index: true,
element: <HomePage/>,
},
{
path: 'login',
element: <LoginPage/>
},
{
path: 'sign-up',
element: <SignUpPage/>
},
{
// 경로가 path면 element요소를 보여줌
path: 'search',
element: <Search/>
},
{
path: 'movies',
element: <Movies/>,
},
{
path: 'movies/up-coming',
element: <UpComingPage/>
},
{
path: 'movies/now-playing',
element: <NowPlayingPage/>
},
{
path: 'movies/popular',
element: <PopularPage/>
},
{
path: 'movies/top-rated',
element: <TopRatedPage/>
},
{
// :movieId는 동적으로 변경될 수 있는 경로 변수
path: 'movies/:movieId',
element: <DetailPage/>
},
]
}
])


const GlobalStyle = createGlobalStyle`
body{
background-color: black;
}
`;


function App(){
return (
<>
<GlobalStyle/>
<RouterProvider router={router}/>
</>
);
}

export default App;
10 changes: 10 additions & 0 deletions 제이-김규리/5주차/mission/src/apis/axios-instance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import axios from 'axios';

const axiosInstance = axios.create({
headers: {
Authorization: `Bearer ${import.meta.env.VITE_TMDB_TOKEN}`,
},
baseURL: import.meta.env.VITE_MOVIE_API_URL,
})

export default axiosInstance;
1 change: 1 addition & 0 deletions 제이-김규리/5주차/mission/src/assets/react.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions 제이-김규리/5주차/mission/src/components/custom-Link.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {Link} from "react-router-dom";
import styled from "styled-components";

const StyledLink = styled(Link)`
color: white;
text-decoration: none;
font-size: 12px;
font-weight: ${props => props.fontWeight || 'normal'};
`;

export default StyledLink;


Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import styled from "styled-components";

const StyledNavbarButton = styled.button`
background-color: ${props => props.backgroundColor || 'black'};
border-radius: 8px;
height: 32px;
width: 70px;
border: none;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;

transition: opacity 0.2s ease;

&:hover{
opacity: 0.8;
}
`;

export default StyledNavbarButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import styled from "styled-components";

const StyledSidebarButton = styled.button`
background-color: ${props => props.backgroundColor || 'black'};
border-radius: 8px;
height: 32px;
width: 60px;
border: none;
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
margin-left: 5px;
`;

export default StyledSidebarButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import styled from "styled-components";

const StyledTxt = styled.h1`
color: white;
`;

export default StyledTxt;
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import styled from "styled-components";
import {Link} from "react-router-dom";

const StyledCardLink = styled(Link)`
width: 126px;
border-radius: 8px;
overflow: hidden;
transition: transform 0.2s ease;
margin: 20px 10px;
&:hover {
transform: scale(1.05); /* 마우스 호버 시 카드 확대 */
}
`;

const MovieDate = styled.div`
font-size: 12px;
color: white;
margin: 0 5px;
`;

const MovieImage = styled.img`
width: 100%;
height: 75%;
`;

const MovieTitle = styled.div`
font-size: 15px;
color: white;
font-weight: bold;
margin: 0 5px;
margin-top: 3px;
`;

// 구조분해 할당
const MovieCard = ({movie}) => {
return(
<StyledCardLink to={`/movies/${movie.id}`}>
<MovieImage src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
alt={movie.title} />
<MovieTitle>{movie.title}</MovieTitle>
<MovieDate>{movie.release_date}</MovieDate>
</StyledCardLink>
);
}


export default MovieCard;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import styled from "styled-components";

const MovieContainer = styled.div`
display: flex;
flex-wrap: wrap;
`;

export default MovieContainer;
36 changes: 36 additions & 0 deletions 제이-김규리/5주차/mission/src/components/navbar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import StyledLink from "./custom-Link";
import StyledNavbarButton from "./custom-NavbarButton";
import styled from "styled-components";
import {Link} from "react-router-dom";

const StyledNav = styled.nav`
display: grid;
grid-template-columns: auto 90px 90px;
height: 40px;
align-items: center;
margin-bottom: 15px;
`;
const StyledYongchaLink = styled(Link)`
width: 95px;
color: #e50914;
font-size: 1.2em;
text-decoration: none;
margin-left: 10px;
font-weight: 500;
`;

const Navbar = () => {
return(
<StyledNav>
<StyledYongchaLink to={'/'}>YONGCHA</StyledYongchaLink>
<StyledNavbarButton>
<StyledLink to={'/login'}>로그인</StyledLink>
</StyledNavbarButton>
<StyledNavbarButton backgroundColor={'#e7545b'}>
<StyledLink to={'/sign-up'}>회원가입</StyledLink>
</StyledNavbarButton>
</StyledNav>
);
}

export default Navbar;
Loading