diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1cac559
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,25 @@
+# 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?
+.env
\ No newline at end of file
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..2dd7caa
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,7 @@
+{
+ "tabWidth": 2,
+ "singleQuote": false,
+ "semi": true,
+ "trailingComma": "all",
+ "printWidth": 80
+}
diff --git a/README.md b/README.md
index b737bcc..fc9bec0 100644
--- a/README.md
+++ b/README.md
@@ -1,77 +1,86 @@
-유튜브 앱 작성
+[![Netlify Status](https://api.netlify.com/api/v1/badges/170bfd9e-858c-41d4-bf11-1a47f894d3a8/deploy-status)](https://app.netlify.com/sites/bulsazotube/deploys)
-유튜브앱 설명자료:
-https://docs.google.com/document/d/1vHlO8lgIo1oXBYiecpE8TbG2tHnr3Hmv25UxK_7a5_g/edit#
+
-목표: 유튜브 앱을 만든다.
+# [프로젝트 소개](https://docs.google.com/document/d/1vHlO8lgIo1oXBYiecpE8TbG2tHnr3Hmv25UxK_7a5_g/edit#)
-수행 기간: 오늘 ~ 2023.01.20(금) 까지
-리뷰 기간:
-제출 방법:
-main 혹은 다른 사람의 브랜치로 절대 병합하지 않도록 주의하세요!
-혹시 문제가 발생한 경우, 바로 강사에게 알려주세요!
-현재 깃헙 저장소를 클론!
-확인 가능하도록 본명으로 브랜치 생성!
-과제 수행 후 원격 저장소로 푸시!
-현재 깃헙 저장소에서 main 브랜치로 Pull Request 생성하면 제출 완료!
-Pull Request 설명을 꼼꼼하게 작성!
+유튜브 API를 활용한 유튜브 클론
-요구사항
-다음 요구사항은 필수로 구현하고 그 외 기능은 마음대로 추가할 수 있다.
-유튜브 api를 사용해서 유튜브 데이터를 가져옵니다.
+## 배포 사이트
-- 유튜브 Api 사용 방법 (API KEY 생성하는 법)
-https://console.cloud.google.com/ Google cloud console로 이동하기
-Youtube Data API 활성화 시키기
-API KEY 생성하기
+[불사조 유튜브](https://bulsazotube.netlify.app/)
- - 유튜브 API 요청 방법
-baseURL : https://youtube.googleapis.com/youtube/v3
+# 팀원
-검색어로 인한 비디오 데이터:
-/search?part=snippet&maxResults=10&q={검색어}
+
-특정 비디오 데이터 :
-/videos?part=snippet&part=contentDetails&part=player&part=statistics&id={videoId}
+# 🔨기술 스택
-특정 채널 정보 데이터:
-/channels?part=snippet&part=statistics&part=contentDetails&id={channelId}
+
+
+
+
+
+
-댓글 데이터:
-/commentThreads?part=snippet&videoId={videoId}
+
+
-관련 비디오 데이터:
-/search?part=snippet&maxResults=10&relatedToVideoId=${videoId}&type=video
+# 📆 과제 기간 및 담당 업무
+과제 기간: 2023. 1. 16 ~ 2022. 1. 20
- - 요청 주의 사항
-
-a. 하루에 하나의 api_key에 할당된 요청 수가 있습니다.
-그 이상 넘어가면 더 이상 요청을 못하게 되기 때문에 데이터를 가져오면 localStorage에 넣어서 localStorage에 이미 데이터가 있으면 요청을 보내지 말고 그 데이터를 이용해서 앱을 개발해 줍니다.
+- 유지석 : <상세 페이지> 동영상 설명, 댓글
+- 소재헌 : <상세 페이지> 동영상 상세 정보
+- 윤준수 : <상세 페이지> 관련동영상
+- 우지수 : <메인 페이지, 사이드바> 메인 페이지 전체, 사이드바
+- 임예지 : <검색 페이지, 헤더> 검색 페이지 전체, 헤더
+
-b. 를 없애도 개발을 해주세요. (요청이 두 번씩 가서 더 많은 api 호출을 하게 됩니다.)
+# 🎈기능 구현
+- 메인 페이지에서는 10개의 고정된 동영상을 보여준다.
+- 검색 페이지에서는 검색어에 해당하는 10개의 동영상을 보여준다.(채널은 제외)
+- 동영상을 클릭하면 상세 페이지로 이동한다.
+- 상세 페이지에서는 해당 동영상의 영상, 정보, 설명, 댓글, 관련동영상을 보여준다.
+- 사용자의 컴퓨터 설정에 따른 다크, 라이트 모드를 적용시켰다.
+- 검색 페이지와 헤더를 제외한 나머지 부분은 반응형으로 만들었다.
+- api 할당량을 초과하면 고정된 더미 데이터를 보여준다.
+
-UI 구현 예시
-예시를 참고로 자유롭게 구현한다.
+# 🔔어려웠던 점
-- 메인 화면
-youtube api 를 이용해서 원하는 검색어에 맞는 비디오 데이터를 가져옵니다.
-가져온 데이터를 이용해서 아래와 같은 UI를 보여줍니다.
-Navigation bar (위쪽 부분) side bar (왼쪽 부분)의 UI를 조건에 따라 처리해줍니다.
+- 타입스크립트가 익숙하지 않아서 타입 오류를 해결하는 것이 많이 힘들었다.
+- 중복되는 함수들을 합치는 작업이 어려웠다.
+- api 호출 할당량이 적어서 실제로 되는지 안되는지 확인하는 것이 힘들었다.
+- 반응형 작업이 어려웠다.
+
+
+# 💡궁금한 점
+
+- api 호출시, 여러 이펙트안에서 분리해서 각각 호출하는 것이 좋은지
+- 하나의 이펙트안에서 호출하는 게 좋은지
+- 혹은 하나의 이펙트안에서 axios.all을 이용해 처리하는게 좋은지
+- 자녀 컴포넌트에서 각자 api 호출이 좋은지, 부모 컴포넌트에서 호출을 한 후 prop으로 내리는 게 좋을지
+- 더미데이터를 useState의 기본값에 할당을 해주어서 처음 렌더링 할때 더미데이터 값이 먼저 렌더링 되고 그 다음에 api에서 받아온 값이 렌더링 되는데 고칠 수 있는 방법이 있는지
-- 비디오 화면
-youtube api 를 이용해서 특정 비디오, 댓글, 관련 비디오 데이터를 가져옵니다.
-가져온 데이터를 이용해서 아래와 같은 UI를 보여줍니다.
-- 검색 화면
-youtube api 를 이용해서 원하는 검색어에 맞는 비디오 데이터를 가져옵니다.
-가져온 데이터를 이용해서 아래와 같은 UI를 보여줍니다.
-주의 사항
-컴포넌트를 올바르게 나누기
-반응형 스타일도 신경 쓰되 스타일보다는 기능 위주로 개발하기
-최대한 이해하기 쉬운 변수명, 파일명, 컴포넌트명 사용하기
-어떠한 부분(데이터)을 위해서 State 관리 라이브러리를 사용해야 할지 생각해 보기
-React-router-dom api의 중첩 라우팅을 이용해서 레이아웃을 만들어주기
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..5ba507b
--- /dev/null
+++ b/index.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ YouTube
+
+
+
+
+
+
+
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..bff8a11
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,2477 @@
+{
+ "name": "youtube",
+ "version": "0.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "youtube",
+ "version": "0.0.0",
+ "dependencies": {
+ "axios": "^1.2.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-icons": "^4.7.1",
+ "react-router-dom": "^6.6.2",
+ "styled-components": "^5.3.6",
+ "styled-reset": "^4.4.5"
+ },
+ "devDependencies": {
+ "@types/react": "^18.0.26",
+ "@types/react-dom": "^18.0.9",
+ "@types/styled-components": "^5.1.26",
+ "@vitejs/plugin-react-swc": "^3.0.0",
+ "typescript": "^4.9.3",
+ "vite": "^4.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
+ "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
+ "dependencies": {
+ "@babel/highlight": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.20.7",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz",
+ "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==",
+ "dependencies": {
+ "@babel/types": "^7.20.7",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "jsesc": "^2.5.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz",
+ "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==",
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
+ "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
+ "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
+ "dependencies": {
+ "@babel/template": "^7.18.10",
+ "@babel/types": "^7.19.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-hoist-variables": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
+ "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz",
+ "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==",
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-split-export-declaration": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
+ "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.19.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
+ "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.19.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
+ "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
+ "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.20.7",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz",
+ "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==",
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.20.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz",
+ "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==",
+ "dependencies": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.20.12",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.12.tgz",
+ "integrity": "sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==",
+ "dependencies": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.20.7",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.19.0",
+ "@babel/helper-hoist-variables": "^7.18.6",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.20.7",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz",
+ "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.19.4",
+ "@babel/helper-validator-identifier": "^7.19.1",
+ "to-fast-properties": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@emotion/is-prop-valid": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz",
+ "integrity": "sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==",
+ "dependencies": {
+ "@emotion/memoize": "^0.8.0"
+ }
+ },
+ "node_modules/@emotion/memoize": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz",
+ "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA=="
+ },
+ "node_modules/@emotion/stylis": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz",
+ "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ=="
+ },
+ "node_modules/@emotion/unitless": {
+ "version": "0.7.5",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
+ "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz",
+ "integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz",
+ "integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz",
+ "integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz",
+ "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz",
+ "integrity": "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz",
+ "integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz",
+ "integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz",
+ "integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz",
+ "integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz",
+ "integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz",
+ "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz",
+ "integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz",
+ "integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz",
+ "integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz",
+ "integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz",
+ "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz",
+ "integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz",
+ "integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz",
+ "integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz",
+ "integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz",
+ "integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz",
+ "integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+ "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.17",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
+ "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "3.1.0",
+ "@jridgewell/sourcemap-codec": "1.4.14"
+ }
+ },
+ "node_modules/@remix-run/router": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.2.1.tgz",
+ "integrity": "sha512-XiY0IsyHR+DXYS5vBxpoBe/8veTeoRpMHP+vDosLZxL5bnpetzI0igkxkLZS235ldLzyfkxF+2divEwWHP3vMQ==",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@swc/core": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.26.tgz",
+ "integrity": "sha512-U7vEsaLn3IGg0XCRLJX/GTkK9WIfFHUX5USdrp1L2QD29sWPe25HqNndXmUR9KytzKmpDMNoUuHyiuhpVrnNeQ==",
+ "dev": true,
+ "hasInstallScript": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/swc"
+ },
+ "optionalDependencies": {
+ "@swc/core-darwin-arm64": "1.3.26",
+ "@swc/core-darwin-x64": "1.3.26",
+ "@swc/core-linux-arm-gnueabihf": "1.3.26",
+ "@swc/core-linux-arm64-gnu": "1.3.26",
+ "@swc/core-linux-arm64-musl": "1.3.26",
+ "@swc/core-linux-x64-gnu": "1.3.26",
+ "@swc/core-linux-x64-musl": "1.3.26",
+ "@swc/core-win32-arm64-msvc": "1.3.26",
+ "@swc/core-win32-ia32-msvc": "1.3.26",
+ "@swc/core-win32-x64-msvc": "1.3.26"
+ }
+ },
+ "node_modules/@swc/core-darwin-arm64": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.26.tgz",
+ "integrity": "sha512-FWWflBfKRYrUJtko2xiedC5XCa31O75IZZqnTWuLpe9g3C5tnUuF3M8LSXZS/dn6wprome1MhtG9GMPkSYkhkg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-darwin-x64": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.26.tgz",
+ "integrity": "sha512-0uQeebAtsewqJ2b35aPZstGrylwd6oJjUyAJOfVJNbremFSJ5JzytB3NoDCIw7CT5UQrSRpvD3mU95gfdQjDGA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm-gnueabihf": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.26.tgz",
+ "integrity": "sha512-06T+LbVFlyciQtwrUB5/a16A1ju1jFoYvd/hq9TWhf7GrtL43U7oJIgqMOPHx2j0+Ps2R3S6R/UUN5YXu618zA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm64-gnu": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.26.tgz",
+ "integrity": "sha512-2NT/0xALPfK+U01qIlHxjkGdIj6F0txhu1U2v6B0YP2+k0whL2gCgYeg9QUvkYEXSD5r1Yx+vcb2R/vaSCSClg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm64-musl": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.26.tgz",
+ "integrity": "sha512-64KrTay9hC0mTvZ1AmEFmNEwV5QDjw9U7PJU5riotSc28I+Q/ZoM0qcSFW9JRRa6F2Tr+IfMtyv8+eB2//BQ5g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-x64-gnu": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.26.tgz",
+ "integrity": "sha512-Te8G13l3dcRM1Mf3J4JzGUngzNXLKnMYlUmBOYN/ORsx7e+VNelR3zsTLHC0+0jGqELDgqvMyzDfk+dux/C/bQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-x64-musl": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.26.tgz",
+ "integrity": "sha512-nqQWuSM6OTKepUiQ9+rXgERq/JiO72RBOpXKO2afYppsL96sngjIRewV74v5f6IAfyzw+k+AhC5pgRA4Xu/Jkg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-arm64-msvc": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.26.tgz",
+ "integrity": "sha512-xx34mx+9IBV1sun7sxoNFiqNom9wiOuvsQFJUyQptCnZHgYwOr9OI204LBF95dCcBCZsTm2hT1wBnySJOeimYw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-ia32-msvc": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.26.tgz",
+ "integrity": "sha512-48LZ/HKNuU9zl8c7qG6IQKb5rBCwmJgysGOmEGzTRBYxAf/x6Scmt0aqxCoV4J02HOs2WduCBDnhUKsSQ2kcXQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-x64-msvc": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.26.tgz",
+ "integrity": "sha512-UPe7S+MezD/S6cKBIc50TduGzmw6PBz1Ms5p+5wDLOKYNS/LSEM4iRmLwvePzP5X8mOyesXrsbwxLy8KHP65Yw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@types/hoist-non-react-statics": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
+ "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.5",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
+ "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
+ "dev": true
+ },
+ "node_modules/@types/react": {
+ "version": "18.0.26",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz",
+ "integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==",
+ "dev": true,
+ "dependencies": {
+ "@types/prop-types": "*",
+ "@types/scheduler": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.0.10",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.10.tgz",
+ "integrity": "sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/scheduler": {
+ "version": "0.16.2",
+ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
+ "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
+ "dev": true
+ },
+ "node_modules/@types/styled-components": {
+ "version": "5.1.26",
+ "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.26.tgz",
+ "integrity": "sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==",
+ "dev": true,
+ "dependencies": {
+ "@types/hoist-non-react-statics": "*",
+ "@types/react": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@vitejs/plugin-react-swc": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.0.1.tgz",
+ "integrity": "sha512-3GQ2oruZO9j8dSHcI0MUeOZQBhjYyDQsF/pKY4Px+CJxn0M16OhgFeEzUjeuwci4zhhjoNIDE9aFNaV5GMQ09g==",
+ "dev": true,
+ "dependencies": {
+ "@swc/core": "^1.3.22"
+ },
+ "peerDependencies": {
+ "vite": "^4"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
+ "node_modules/axios": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.2.tgz",
+ "integrity": "sha512-bz/J4gS2S3I7mpN/YZfGFTqhXTYzRho8Ay38w2otuuDR322KzFIWm/4W2K6gIwvWaws5n+mnb7D1lN9uD+QH6Q==",
+ "dependencies": {
+ "follow-redirects": "^1.15.0",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/babel-plugin-styled-components": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz",
+ "integrity": "sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.16.0",
+ "@babel/helper-module-imports": "^7.16.0",
+ "babel-plugin-syntax-jsx": "^6.18.0",
+ "lodash": "^4.17.11",
+ "picomatch": "^2.3.0"
+ },
+ "peerDependencies": {
+ "styled-components": ">= 2"
+ }
+ },
+ "node_modules/babel-plugin-syntax-jsx": {
+ "version": "6.18.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
+ "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw=="
+ },
+ "node_modules/camelize": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
+ "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/css-color-keywords": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
+ "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/css-to-react-native": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.1.0.tgz",
+ "integrity": "sha512-AryfkFA29b4I3vG7N4kxFboq15DxwSXzhXM37XNEjwJMgjYIc8BcqfiprpAqX0zadI5PMByEIwAMzXxk5Vcc4g==",
+ "dependencies": {
+ "camelize": "^1.0.0",
+ "css-color-keywords": "^1.0.0",
+ "postcss-value-parser": "^4.0.2"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
+ "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==",
+ "dev": true
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz",
+ "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.16.17",
+ "@esbuild/android-arm64": "0.16.17",
+ "@esbuild/android-x64": "0.16.17",
+ "@esbuild/darwin-arm64": "0.16.17",
+ "@esbuild/darwin-x64": "0.16.17",
+ "@esbuild/freebsd-arm64": "0.16.17",
+ "@esbuild/freebsd-x64": "0.16.17",
+ "@esbuild/linux-arm": "0.16.17",
+ "@esbuild/linux-arm64": "0.16.17",
+ "@esbuild/linux-ia32": "0.16.17",
+ "@esbuild/linux-loong64": "0.16.17",
+ "@esbuild/linux-mips64el": "0.16.17",
+ "@esbuild/linux-ppc64": "0.16.17",
+ "@esbuild/linux-riscv64": "0.16.17",
+ "@esbuild/linux-s390x": "0.16.17",
+ "@esbuild/linux-x64": "0.16.17",
+ "@esbuild/netbsd-x64": "0.16.17",
+ "@esbuild/openbsd-x64": "0.16.17",
+ "@esbuild/sunos-x64": "0.16.17",
+ "@esbuild/win32-arm64": "0.16.17",
+ "@esbuild/win32-ia32": "0.16.17",
+ "@esbuild/win32-x64": "0.16.17"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
+ "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "dependencies": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+ "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "node_modules/jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
+ "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+ "dev": true,
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.4.21",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz",
+ "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.4",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
+ "node_modules/react": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
+ "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
+ "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/react-icons": {
+ "version": "4.7.1",
+ "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.7.1.tgz",
+ "integrity": "sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw==",
+ "peerDependencies": {
+ "react": "*"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/react-router": {
+ "version": "6.6.2",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.6.2.tgz",
+ "integrity": "sha512-uJPG55Pek3orClbURDvfljhqFvMgJRo59Pktywkk8hUUkTY2aRfza8Yhl/vZQXs+TNQyr6tu+uqz/fLxPICOGQ==",
+ "dependencies": {
+ "@remix-run/router": "1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.6.2",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.6.2.tgz",
+ "integrity": "sha512-6SCDXxRQqW5af8ImOqKza7icmQ47/EMbz572uFjzvcArg3lZ+04PxSPp8qGs+p2Y+q+b+S/AjXv8m8dyLndIIA==",
+ "dependencies": {
+ "@remix-run/router": "1.2.1",
+ "react-router": "6.6.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.10.0.tgz",
+ "integrity": "sha512-JmRYz44NjC1MjVF2VKxc0M1a97vn+cDxeqWmnwyAF4FvpjK8YFdHpaqvQB+3IxCvX05vJxKZkoMDU8TShhmJVA==",
+ "dev": true,
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=14.18.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
+ "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/shallowequal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
+ "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
+ },
+ "node_modules/source-map-js": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/styled-components": {
+ "version": "5.3.6",
+ "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.6.tgz",
+ "integrity": "sha512-hGTZquGAaTqhGWldX7hhfzjnIYBZ0IXQXkCYdvF1Sq3DsUaLx6+NTHC5Jj1ooM2F68sBiVz3lvhfwQs/S3l6qg==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.0.0",
+ "@babel/traverse": "^7.4.5",
+ "@emotion/is-prop-valid": "^1.1.0",
+ "@emotion/stylis": "^0.8.4",
+ "@emotion/unitless": "^0.7.4",
+ "babel-plugin-styled-components": ">= 1.12.0",
+ "css-to-react-native": "^3.0.0",
+ "hoist-non-react-statics": "^3.0.0",
+ "shallowequal": "^1.1.0",
+ "supports-color": "^5.5.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/styled-components"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0",
+ "react-dom": ">= 16.8.0",
+ "react-is": ">= 16.8.0"
+ }
+ },
+ "node_modules/styled-reset": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/styled-reset/-/styled-reset-4.4.5.tgz",
+ "integrity": "sha512-uEQzbCqSBbx1ZT9VuquoGOJyVzs3kMIMCyjxmtSo4/JoTCrq92UFTJx91KcdMncDaymz6NE8sgSvstHHcJjExg==",
+ "engines": {
+ "node": ">=16.0.0"
+ },
+ "peerDependencies": {
+ "styled-components": ">=4.0.0 || >=5.0.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.9.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
+ "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-4.0.4.tgz",
+ "integrity": "sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==",
+ "dev": true,
+ "dependencies": {
+ "esbuild": "^0.16.3",
+ "postcss": "^8.4.20",
+ "resolve": "^1.22.1",
+ "rollup": "^3.7.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ },
+ "peerDependencies": {
+ "@types/node": ">= 14",
+ "less": "*",
+ "sass": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ }
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
+ "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
+ "requires": {
+ "@babel/highlight": "^7.18.6"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.20.7",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz",
+ "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==",
+ "requires": {
+ "@babel/types": "^7.20.7",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "jsesc": "^2.5.1"
+ }
+ },
+ "@babel/helper-annotate-as-pure": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz",
+ "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==",
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-environment-visitor": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
+ "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg=="
+ },
+ "@babel/helper-function-name": {
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
+ "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
+ "requires": {
+ "@babel/template": "^7.18.10",
+ "@babel/types": "^7.19.0"
+ }
+ },
+ "@babel/helper-hoist-variables": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
+ "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz",
+ "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==",
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
+ "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-string-parser": {
+ "version": "7.19.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
+ "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw=="
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.19.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
+ "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w=="
+ },
+ "@babel/highlight": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
+ "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.20.7",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz",
+ "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg=="
+ },
+ "@babel/template": {
+ "version": "7.20.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz",
+ "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==",
+ "requires": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.20.12",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.12.tgz",
+ "integrity": "sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==",
+ "requires": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.20.7",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.19.0",
+ "@babel/helper-hoist-variables": "^7.18.6",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ }
+ },
+ "@babel/types": {
+ "version": "7.20.7",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz",
+ "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.19.4",
+ "@babel/helper-validator-identifier": "^7.19.1",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "@emotion/is-prop-valid": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz",
+ "integrity": "sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==",
+ "requires": {
+ "@emotion/memoize": "^0.8.0"
+ }
+ },
+ "@emotion/memoize": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz",
+ "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA=="
+ },
+ "@emotion/stylis": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz",
+ "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ=="
+ },
+ "@emotion/unitless": {
+ "version": "0.7.5",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
+ "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
+ },
+ "@esbuild/android-arm": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz",
+ "integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/android-arm64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz",
+ "integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/android-x64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz",
+ "integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/darwin-arm64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz",
+ "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/darwin-x64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz",
+ "integrity": "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/freebsd-arm64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz",
+ "integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/freebsd-x64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz",
+ "integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-arm": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz",
+ "integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-arm64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz",
+ "integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-ia32": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz",
+ "integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-loong64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz",
+ "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-mips64el": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz",
+ "integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-ppc64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz",
+ "integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-riscv64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz",
+ "integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-s390x": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz",
+ "integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-x64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz",
+ "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/netbsd-x64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz",
+ "integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/openbsd-x64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz",
+ "integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/sunos-x64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz",
+ "integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/win32-arm64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz",
+ "integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/win32-ia32": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz",
+ "integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/win32-x64": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz",
+ "integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==",
+ "dev": true,
+ "optional": true
+ },
+ "@jridgewell/gen-mapping": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+ "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+ "requires": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ },
+ "@jridgewell/resolve-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w=="
+ },
+ "@jridgewell/set-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw=="
+ },
+ "@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
+ },
+ "@jridgewell/trace-mapping": {
+ "version": "0.3.17",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
+ "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
+ "requires": {
+ "@jridgewell/resolve-uri": "3.1.0",
+ "@jridgewell/sourcemap-codec": "1.4.14"
+ }
+ },
+ "@remix-run/router": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.2.1.tgz",
+ "integrity": "sha512-XiY0IsyHR+DXYS5vBxpoBe/8veTeoRpMHP+vDosLZxL5bnpetzI0igkxkLZS235ldLzyfkxF+2divEwWHP3vMQ=="
+ },
+ "@swc/core": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.26.tgz",
+ "integrity": "sha512-U7vEsaLn3IGg0XCRLJX/GTkK9WIfFHUX5USdrp1L2QD29sWPe25HqNndXmUR9KytzKmpDMNoUuHyiuhpVrnNeQ==",
+ "dev": true,
+ "requires": {
+ "@swc/core-darwin-arm64": "1.3.26",
+ "@swc/core-darwin-x64": "1.3.26",
+ "@swc/core-linux-arm-gnueabihf": "1.3.26",
+ "@swc/core-linux-arm64-gnu": "1.3.26",
+ "@swc/core-linux-arm64-musl": "1.3.26",
+ "@swc/core-linux-x64-gnu": "1.3.26",
+ "@swc/core-linux-x64-musl": "1.3.26",
+ "@swc/core-win32-arm64-msvc": "1.3.26",
+ "@swc/core-win32-ia32-msvc": "1.3.26",
+ "@swc/core-win32-x64-msvc": "1.3.26"
+ }
+ },
+ "@swc/core-darwin-arm64": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.26.tgz",
+ "integrity": "sha512-FWWflBfKRYrUJtko2xiedC5XCa31O75IZZqnTWuLpe9g3C5tnUuF3M8LSXZS/dn6wprome1MhtG9GMPkSYkhkg==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-darwin-x64": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.26.tgz",
+ "integrity": "sha512-0uQeebAtsewqJ2b35aPZstGrylwd6oJjUyAJOfVJNbremFSJ5JzytB3NoDCIw7CT5UQrSRpvD3mU95gfdQjDGA==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-linux-arm-gnueabihf": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.26.tgz",
+ "integrity": "sha512-06T+LbVFlyciQtwrUB5/a16A1ju1jFoYvd/hq9TWhf7GrtL43U7oJIgqMOPHx2j0+Ps2R3S6R/UUN5YXu618zA==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-linux-arm64-gnu": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.26.tgz",
+ "integrity": "sha512-2NT/0xALPfK+U01qIlHxjkGdIj6F0txhu1U2v6B0YP2+k0whL2gCgYeg9QUvkYEXSD5r1Yx+vcb2R/vaSCSClg==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-linux-arm64-musl": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.26.tgz",
+ "integrity": "sha512-64KrTay9hC0mTvZ1AmEFmNEwV5QDjw9U7PJU5riotSc28I+Q/ZoM0qcSFW9JRRa6F2Tr+IfMtyv8+eB2//BQ5g==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-linux-x64-gnu": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.26.tgz",
+ "integrity": "sha512-Te8G13l3dcRM1Mf3J4JzGUngzNXLKnMYlUmBOYN/ORsx7e+VNelR3zsTLHC0+0jGqELDgqvMyzDfk+dux/C/bQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-linux-x64-musl": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.26.tgz",
+ "integrity": "sha512-nqQWuSM6OTKepUiQ9+rXgERq/JiO72RBOpXKO2afYppsL96sngjIRewV74v5f6IAfyzw+k+AhC5pgRA4Xu/Jkg==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-win32-arm64-msvc": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.26.tgz",
+ "integrity": "sha512-xx34mx+9IBV1sun7sxoNFiqNom9wiOuvsQFJUyQptCnZHgYwOr9OI204LBF95dCcBCZsTm2hT1wBnySJOeimYw==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-win32-ia32-msvc": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.26.tgz",
+ "integrity": "sha512-48LZ/HKNuU9zl8c7qG6IQKb5rBCwmJgysGOmEGzTRBYxAf/x6Scmt0aqxCoV4J02HOs2WduCBDnhUKsSQ2kcXQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-win32-x64-msvc": {
+ "version": "1.3.26",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.26.tgz",
+ "integrity": "sha512-UPe7S+MezD/S6cKBIc50TduGzmw6PBz1Ms5p+5wDLOKYNS/LSEM4iRmLwvePzP5X8mOyesXrsbwxLy8KHP65Yw==",
+ "dev": true,
+ "optional": true
+ },
+ "@types/hoist-non-react-statics": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
+ "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
+ "dev": true,
+ "requires": {
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
+ "@types/prop-types": {
+ "version": "15.7.5",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
+ "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
+ "dev": true
+ },
+ "@types/react": {
+ "version": "18.0.26",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz",
+ "integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==",
+ "dev": true,
+ "requires": {
+ "@types/prop-types": "*",
+ "@types/scheduler": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "@types/react-dom": {
+ "version": "18.0.10",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.10.tgz",
+ "integrity": "sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==",
+ "dev": true,
+ "requires": {
+ "@types/react": "*"
+ }
+ },
+ "@types/scheduler": {
+ "version": "0.16.2",
+ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
+ "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
+ "dev": true
+ },
+ "@types/styled-components": {
+ "version": "5.1.26",
+ "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.26.tgz",
+ "integrity": "sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==",
+ "dev": true,
+ "requires": {
+ "@types/hoist-non-react-statics": "*",
+ "@types/react": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "@vitejs/plugin-react-swc": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.0.1.tgz",
+ "integrity": "sha512-3GQ2oruZO9j8dSHcI0MUeOZQBhjYyDQsF/pKY4Px+CJxn0M16OhgFeEzUjeuwci4zhhjoNIDE9aFNaV5GMQ09g==",
+ "dev": true,
+ "requires": {
+ "@swc/core": "^1.3.22"
+ }
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
+ "axios": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.2.tgz",
+ "integrity": "sha512-bz/J4gS2S3I7mpN/YZfGFTqhXTYzRho8Ay38w2otuuDR322KzFIWm/4W2K6gIwvWaws5n+mnb7D1lN9uD+QH6Q==",
+ "requires": {
+ "follow-redirects": "^1.15.0",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "babel-plugin-styled-components": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz",
+ "integrity": "sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.16.0",
+ "@babel/helper-module-imports": "^7.16.0",
+ "babel-plugin-syntax-jsx": "^6.18.0",
+ "lodash": "^4.17.11",
+ "picomatch": "^2.3.0"
+ }
+ },
+ "babel-plugin-syntax-jsx": {
+ "version": "6.18.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
+ "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw=="
+ },
+ "camelize": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
+ "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ=="
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ },
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "css-color-keywords": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
+ "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg=="
+ },
+ "css-to-react-native": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.1.0.tgz",
+ "integrity": "sha512-AryfkFA29b4I3vG7N4kxFboq15DxwSXzhXM37XNEjwJMgjYIc8BcqfiprpAqX0zadI5PMByEIwAMzXxk5Vcc4g==",
+ "requires": {
+ "camelize": "^1.0.0",
+ "css-color-keywords": "^1.0.0",
+ "postcss-value-parser": "^4.0.2"
+ }
+ },
+ "csstype": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
+ "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
+ },
+ "esbuild": {
+ "version": "0.16.17",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz",
+ "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==",
+ "dev": true,
+ "requires": {
+ "@esbuild/android-arm": "0.16.17",
+ "@esbuild/android-arm64": "0.16.17",
+ "@esbuild/android-x64": "0.16.17",
+ "@esbuild/darwin-arm64": "0.16.17",
+ "@esbuild/darwin-x64": "0.16.17",
+ "@esbuild/freebsd-arm64": "0.16.17",
+ "@esbuild/freebsd-x64": "0.16.17",
+ "@esbuild/linux-arm": "0.16.17",
+ "@esbuild/linux-arm64": "0.16.17",
+ "@esbuild/linux-ia32": "0.16.17",
+ "@esbuild/linux-loong64": "0.16.17",
+ "@esbuild/linux-mips64el": "0.16.17",
+ "@esbuild/linux-ppc64": "0.16.17",
+ "@esbuild/linux-riscv64": "0.16.17",
+ "@esbuild/linux-s390x": "0.16.17",
+ "@esbuild/linux-x64": "0.16.17",
+ "@esbuild/netbsd-x64": "0.16.17",
+ "@esbuild/openbsd-x64": "0.16.17",
+ "@esbuild/sunos-x64": "0.16.17",
+ "@esbuild/win32-arm64": "0.16.17",
+ "@esbuild/win32-ia32": "0.16.17",
+ "@esbuild/win32-x64": "0.16.17"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
+ },
+ "follow-redirects": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
+ "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
+ },
+ "form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "optional": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="
+ },
+ "hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "requires": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "is-core-module": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+ "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="
+ },
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
+ },
+ "mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "requires": {
+ "mime-db": "1.52.0"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "nanoid": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
+ "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
+ },
+ "postcss": {
+ "version": "8.4.21",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz",
+ "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==",
+ "dev": true,
+ "requires": {
+ "nanoid": "^3.3.4",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
+ },
+ "proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
+ "react": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
+ "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
+ "requires": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "react-dom": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
+ "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.0"
+ }
+ },
+ "react-icons": {
+ "version": "4.7.1",
+ "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.7.1.tgz",
+ "integrity": "sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw==",
+ "requires": {}
+ },
+ "react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "react-router": {
+ "version": "6.6.2",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.6.2.tgz",
+ "integrity": "sha512-uJPG55Pek3orClbURDvfljhqFvMgJRo59Pktywkk8hUUkTY2aRfza8Yhl/vZQXs+TNQyr6tu+uqz/fLxPICOGQ==",
+ "requires": {
+ "@remix-run/router": "1.2.1"
+ }
+ },
+ "react-router-dom": {
+ "version": "6.6.2",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.6.2.tgz",
+ "integrity": "sha512-6SCDXxRQqW5af8ImOqKza7icmQ47/EMbz572uFjzvcArg3lZ+04PxSPp8qGs+p2Y+q+b+S/AjXv8m8dyLndIIA==",
+ "requires": {
+ "@remix-run/router": "1.2.1",
+ "react-router": "6.6.2"
+ }
+ },
+ "resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dev": true,
+ "requires": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "rollup": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.10.0.tgz",
+ "integrity": "sha512-JmRYz44NjC1MjVF2VKxc0M1a97vn+cDxeqWmnwyAF4FvpjK8YFdHpaqvQB+3IxCvX05vJxKZkoMDU8TShhmJVA==",
+ "dev": true,
+ "requires": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "scheduler": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
+ "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
+ "requires": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "shallowequal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
+ "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
+ },
+ "source-map-js": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+ "dev": true
+ },
+ "styled-components": {
+ "version": "5.3.6",
+ "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.6.tgz",
+ "integrity": "sha512-hGTZquGAaTqhGWldX7hhfzjnIYBZ0IXQXkCYdvF1Sq3DsUaLx6+NTHC5Jj1ooM2F68sBiVz3lvhfwQs/S3l6qg==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.0.0",
+ "@babel/traverse": "^7.4.5",
+ "@emotion/is-prop-valid": "^1.1.0",
+ "@emotion/stylis": "^0.8.4",
+ "@emotion/unitless": "^0.7.4",
+ "babel-plugin-styled-components": ">= 1.12.0",
+ "css-to-react-native": "^3.0.0",
+ "hoist-non-react-statics": "^3.0.0",
+ "shallowequal": "^1.1.0",
+ "supports-color": "^5.5.0"
+ }
+ },
+ "styled-reset": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/styled-reset/-/styled-reset-4.4.5.tgz",
+ "integrity": "sha512-uEQzbCqSBbx1ZT9VuquoGOJyVzs3kMIMCyjxmtSo4/JoTCrq92UFTJx91KcdMncDaymz6NE8sgSvstHHcJjExg==",
+ "requires": {}
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true
+ },
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog=="
+ },
+ "typescript": {
+ "version": "4.9.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
+ "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
+ "dev": true
+ },
+ "vite": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-4.0.4.tgz",
+ "integrity": "sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==",
+ "dev": true,
+ "requires": {
+ "esbuild": "^0.16.3",
+ "fsevents": "~2.3.2",
+ "postcss": "^8.4.20",
+ "resolve": "^1.22.1",
+ "rollup": "^3.7.0"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..b69da6d
--- /dev/null
+++ b/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "youtube",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build && echo '/* /index.html 200' | cat > dist/_redirects",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "axios": "^1.2.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-icons": "^4.7.1",
+ "react-router-dom": "^6.6.2",
+ "styled-components": "^5.3.6",
+ "styled-reset": "^4.4.5"
+ },
+ "devDependencies": {
+ "@types/react": "^18.0.26",
+ "@types/react-dom": "^18.0.9",
+ "@types/styled-components": "^5.1.26",
+ "@vitejs/plugin-react-swc": "^3.0.0",
+ "typescript": "^4.9.3",
+ "vite": "^4.0.0"
+ }
+}
diff --git a/src/App.tsx b/src/App.tsx
new file mode 100644
index 0000000..3104cc8
--- /dev/null
+++ b/src/App.tsx
@@ -0,0 +1,43 @@
+import { BrowserRouter, Routes, Route } from "react-router-dom";
+import Layout from "./components/layout/Layout";
+import Home from "./pages/Home";
+import Search from "./pages/Search";
+import Watch from "./pages/Watch";
+import { useState, useEffect } from "react";
+import ScrollToTop from "./utils/ScrollToTop";
+
+const App = () => {
+ const [open, setOpen] = useState(false);
+
+ const handleClickOpen = () => {
+ setOpen((prev) => !prev);
+ };
+
+ useEffect(() => {
+ window.onbeforeunload = function pushRefresh() {
+ window.scrollTo(0, 0);
+ };
+ }, []);
+
+ return (
+
+
+
+
+ }
+ >
+ } />
+ } />
+ } />
+
+
+
+ );
+};
+export default App;
diff --git a/src/api/api.ts b/src/api/api.ts
new file mode 100644
index 0000000..319bd4b
--- /dev/null
+++ b/src/api/api.ts
@@ -0,0 +1,110 @@
+import { AxiosError } from "axios";
+import { instance } from ".";
+
+interface FetchFn {
+ (
+ id: string,
+ setState: React.Dispatch>,
+ setError: React.Dispatch>,
+ ): void;
+}
+
+export const getComments: FetchFn = async (id, setState, setError) => {
+ try {
+ const res = await instance.get(
+ `/commentThreads?part=snippet&videoId=${id}`,
+ );
+
+ if (res.status === 200) {
+ localStorage.setItem("comments", JSON.stringify(res.data.items));
+ setState(res.data.items);
+ }
+ } catch (error) {
+ if (error instanceof AxiosError) {
+ console.log(error.message);
+ setError(error.message);
+ } else {
+ throw error;
+ }
+ }
+};
+
+export const getDescription: FetchFn = async (id, setState, setError) => {
+ try {
+ const res = await instance(
+ `/channels?part=snippet&part=statistics&part=contentDetails&id=${id}`,
+ );
+
+ if (res.status === 200) {
+ localStorage.setItem("desc", JSON.stringify(res.data));
+ setState(res.data);
+ }
+ } catch (error) {
+ if (error instanceof AxiosError) {
+ console.log(error.message);
+ setError(error.message);
+ } else {
+ throw error;
+ }
+ }
+};
+
+export const getVideoDetail: FetchFn = async (id, setState, setError) => {
+ try {
+ const res = await instance.get(
+ `/videos?part=snippet&part=contentDetails&part=player&part=statistics&id=${id}`,
+ );
+ if (res.status === 200) {
+ localStorage.setItem("detail", JSON.stringify(res.data));
+ setState(res.data);
+ }
+ } catch (error) {
+ if (error instanceof AxiosError) {
+ console.log(error.message);
+ setError(error.message);
+ } else {
+ throw error;
+ }
+ }
+};
+
+export const getRelated: FetchFn = async (id, setRelatedData, setError) => {
+ try {
+ const res = await instance.get(
+ `/search?part=snippet&maxResults=10&relatedToVideoId=${id}&type=video`,
+ );
+ if (res.status === 200) {
+ setRelatedData(res.data.items);
+ }
+ } catch (error) {
+ if (error instanceof AxiosError) {
+ console.log(error.message);
+ setError(error.message);
+ } else {
+ throw error;
+ }
+ }
+};
+
+// 검색어로 인한 비디오 데이터
+export const getSearchData: FetchFn = async (
+ searchWord,
+ setState,
+ setError,
+) => {
+ try {
+ const res = await instance.get(
+ `/search?part=snippet&maxResults=10&q=${searchWord}`,
+ );
+ if (res.status === 200) {
+ setState(res.data.items);
+ }
+ } catch (error) {
+ if (error instanceof AxiosError) {
+ console.log(error.message);
+ setError(error.message);
+ } else {
+ throw error;
+ }
+ }
+};
diff --git a/src/api/index.ts b/src/api/index.ts
new file mode 100644
index 0000000..04ad57a
--- /dev/null
+++ b/src/api/index.ts
@@ -0,0 +1,8 @@
+import axios from "axios";
+
+export const instance = axios.create({
+ baseURL: "https://youtube.googleapis.com/youtube/v3",
+ params: {
+ key: import.meta.env.VITE_API_KEY_YOON,
+ },
+});
diff --git a/src/components/home/MainCard.tsx b/src/components/home/MainCard.tsx
new file mode 100644
index 0000000..ebdcac3
--- /dev/null
+++ b/src/components/home/MainCard.tsx
@@ -0,0 +1,159 @@
+import { useEffect, useState } from "react";
+import styled from "styled-components";
+import { instance } from "../../api";
+import { Link } from "react-router-dom";
+import { nFormatter } from "../../utils/nFormatter";
+import { videoTime } from "../../utils/videoTime";
+import { displayedAt } from "../../utils/displayedAt";
+import { VideoSearchData } from "../../types/videoSearchTypes";
+import { mainVideoDetailDummyData } from "../../data/data";
+import { getVideoDetail } from "../../api/api";
+
+const MainCard = ({ item, i }: { item: VideoSearchData; i: number }) => {
+ const videoId = item.id.videoId;
+ const [videoResult, setVideoResult] = useState(mainVideoDetailDummyData);
+ const [isError, setIsError] = useState("");
+
+ useEffect(() => {
+ getVideoDetail(videoId, setVideoResult, setIsError);
+ }, []);
+
+ // // dummy data 로컬에 저장
+ localStorage.setItem(
+ "mainVideoDetailDummyData",
+ JSON.stringify(mainVideoDetailDummyData),
+ );
+
+ // // dummy data 로컬에서 가져오기
+ const localDetailData = JSON.parse(
+ localStorage.getItem("mainVideoDetailDummyData") || "",
+ );
+
+ return (
+
+
+
+
+
+
+
+ {videoTime(localDetailData[i].items[0].contentDetails.duration)}
+
+
+
+
+
+
+
+
+
+ {item.snippet.title}
+
+ {item.snippet.channelTitle}
+
+
+ 조회수{" "}
+ {nFormatter(localDetailData[i].items[0].statistics.viewCount)}
+
+
+ · {displayedAt(item.snippet.publishTime)}{" "}
+
+
+
+
+
+ );
+};
+
+const Wrap = styled.div`
+ width: 100%;
+ height: auto;
+ display: flex;
+ flex-wrap: wrap;
+ align-content: flex-start;
+ margin-bottom: 20px;
+ padding: 10px;
+ box-sizing: border-box;
+`;
+const MainImage = styled.div`
+ width: 100%;
+ aspect-ratio: 16 / 9;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ overflow: hidden;
+ border-radius: 15px;
+ position: relative;
+ img {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ border-radius: 15px;
+ }
+`;
+const Duration = styled.div`
+ z-index: 9;
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ padding: 5px;
+ font-size: 11px;
+ font-weight: bold;
+ background-color: rgba(0, 0, 0, 0.8);
+ color: white;
+ border-radius: 5px;
+ margin: 5px;
+`;
+const Info = styled.div`
+ width: 100%;
+ height: 100px;
+ display: flex;
+ align-content: flex-start;
+`;
+const Text = styled.div`
+ width: 75%;
+ line-height: 1.2rem;
+ font-weight: 500;
+ margin-top: 12px;
+`;
+const Title = styled.p`
+ font-size: 1em;
+ font-weight: 500;
+ margin-bottom: 6px;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2;
+ text-overflow: ellipsis;
+ overflow: hidden;
+`;
+const ChannelTitle = styled.div`
+ font-size: 0.8em;
+ color: #606060;
+ height: auto;
+`;
+const Image = styled.div`
+ width: 36px;
+ height: 36px;
+ margin: 12px 12px 0 0;
+ border-radius: 100px;
+ overflow: hidden;
+ position: relative;
+ img {
+ height: 36px;
+ position: absolute;
+ left: -15px;
+ margin: auto;
+ }
+`;
+const Detail = styled.div`
+ display: flex;
+`;
+const ViewCount = styled(ChannelTitle)``;
+const Time = styled(ChannelTitle)``;
+
+export default MainCard;
diff --git a/src/components/layout/Aside.tsx b/src/components/layout/Aside.tsx
new file mode 100644
index 0000000..03380d0
--- /dev/null
+++ b/src/components/layout/Aside.tsx
@@ -0,0 +1,470 @@
+import { Link } from "react-router-dom";
+import styled from "styled-components";
+import { useLocation } from "react-router-dom";
+
+const Aside = ({
+ open,
+}: {
+ open: boolean;
+ setOpen: React.Dispatch>;
+}) => {
+ const { pathname } = useLocation();
+ if (open === true) {
+ return (
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
좋아요 표시한 동영상
+
+
+ -
+
탐색
+
+
+
+
+
+
+
+
+ -
+
YouTube 더보기
+
+
+
+
+
+
+
+
YouTube Premium
+
+
+
+
+
+
+
+
+
+
+
크리에이터 스튜디오
+
+
+
+
+
+
+
+
+
+
YouTube Music
+
+
+
+
+
+
+
+
+
+
+
YouTube Kids
+
+
+
+ -
+
+
+
+
+
+ 정보보도자료저작권문의하기크리에이터광고개발자
+
+ 약관개인정보처리방침정책 및 안전YouTube 작동의 원리새로운 기능
+ 테스트하기
+
+
+ © 2023 Google LLC, Sundar Pichai, 1600 Amphitheatre Parkway, Mountain
+ View CA 94043, USA, 0807-882-594 (무료),
+ yt-support-solutions-kr@google.com, 호스팅: Google LLC,
+ 사업자정보, 불법촬영물 신고
+ 크리에이터들이
+
+ 유튜브 상에 게시, 태그 또는 추천한 상품들은 판매자들의 약관에 따라
+ 판매됩니다. 유튜브는 이러한 제품들을 판매하지 않으며, 그에 대한 책임을
+ 지지 않습니다.
+
+
+ );
+ } else {
+ if (pathname.includes("watch")) return null;
+ else {
+ return (
+
+
+
+
+
+
+
+
+ );
+ }
+ }
+};
+
+const Open = styled.aside`
+ width: 240px;
+ height: 100vh;
+ position: fixed;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ top: 0;
+ left: 0;
+ display: flex;
+ flex-direction: column;
+ flex-wrap: nowrap;
+ padding-top: 54px;
+ box-sizing: border-box;
+ z-index: 9;
+ ::-webkit-scrollbar {
+ display: none;
+ }
+ :hover {
+ ::-webkit-scrollbar {
+ display: inline-block;
+ width: 8px;
+ height: 100%;
+ }
+ ::-webkit-scrollbar-thumb {
+ /* 스크롤 */
+ background-color: #d3d3d3;
+ background-clip: padding-box;
+ border-top: 54px solid transparent;
+ }
+ }
+ .info {
+ padding: 16px 24px 0;
+ font-size: 12px;
+ color: #606060;
+ line-height: 1.1;
+ }
+ .terms {
+ line-height: 1.3;
+ color: #909090;
+ padding-bottom: 20px;
+ }
+ .blue {
+ color: "#065fd4";
+ }
+`;
+
+const Item = styled.div`
+ width: 204px;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ padding: 12px;
+ border-bottom: 1px solid #e6e6e6;
+ h3 {
+ padding: 12px 0 12px 12px;
+ }
+
+ .wrap {
+ width: 204px;
+ height: 40px;
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ border-radius: 10px;
+ padding: 12px 0 12px 12px;
+ box-sizing: border-box;
+ .icon {
+ width: 24px;
+ height: 24px;
+ margin-right: 24px;
+ }
+ p {
+ font-size: 14px;
+ text-align: center;
+ text-overflow: ellipsis;
+ }
+ :hover {
+ border-radius: 10px;
+ background-color: #eee;
+ transition: 0.2s;
+ cursor: pointer;
+ p {
+ color: black;
+ }
+ .icon {
+ fill: black;
+ }
+ }
+ }
+`;
+
+const Close = styled.aside`
+ width: 72px;
+ height: 100vh;
+ position: fixed;
+ display: flex;
+ justify-content: flex-start;
+ margin-top: 56px;
+ padding: 0 4px;
+ box-sizing: border-box;
+ top: 0;
+ flex-direction: column;
+ cursor: pointer;
+ .wrap {
+ width: 100%;
+ height: 74px;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ align-items: flex-end;
+ padding: 16px 0 14px 0;
+ box-sizing: border-box;
+ &:hover {
+ border-radius: 10px;
+ background-color: #eee;
+ transition: 0.2s;
+ p {
+ color: black;
+ }
+ .icon {
+ fill: black;
+ }
+ }
+ .icon {
+ width: 24px;
+ height: 24px;
+ font-size: 23px;
+ cursor: pointer;
+ display: flex;
+ flex-wrap: nowrap;
+ align-content: center;
+ justify-content: center;
+ }
+ p {
+ width: 100%;
+ font-size: 10px;
+ text-align: center;
+ line-height: 0.8rem;
+ }
+ }
+`;
+
+export default Aside;
diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx
new file mode 100644
index 0000000..bbe1df3
--- /dev/null
+++ b/src/components/layout/Header.tsx
@@ -0,0 +1,233 @@
+import { useState } from "react";
+import styled from "styled-components";
+import { SlMenu, SlMagnifier } from "react-icons/sl";
+import { BsFillMicFill, BsBell } from "react-icons/bs";
+import { RiVideoAddLine } from "react-icons/ri";
+import { useNavigate, Link } from "react-router-dom";
+
+const Header = ({
+ open,
+ handleClickOpen,
+}: {
+ open: boolean;
+ handleClickOpen: () => void;
+}) => {
+ const navigate = useNavigate();
+ const [value, setValue] = useState("");
+
+ const handleSubmit = (e: React.FormEvent) => {
+ e.preventDefault();
+ navigate(`/search?q=${value}`);
+ (document.activeElement as HTMLElement).blur();
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+const Container = styled.header`
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ background-color: #fff;
+ padding-left: 15px;
+ position: fixed;
+ top: 0;
+ z-index: 10;
+ width: 100%;
+ @media (prefers-color-scheme: dark) {
+ background-color: #0f0f0f;
+ }
+`;
+const Start = styled.div`
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ .bar {
+ width: 18px;
+ height: 18px;
+ padding: 12px;
+ cursor: pointer;
+ }
+`;
+
+const Box = styled.div`
+ display: flex;
+ &:hover {
+ background-color: rgba(220, 220, 220, 0.5);
+ border-radius: 50%;
+ }
+`;
+
+const Logo = styled.div`
+ width: 90px;
+ height: 18px;
+ padding: 18px 20px;
+ cursor: pointer;
+`;
+
+const Center = styled(Start)`
+ width: 728px;
+`;
+
+const End = styled(Start)`
+ min-width: 225px;
+ gap: 10px;
+ .video,
+ .bell {
+ width: 22px;
+ height: 22px;
+ padding: 10px;
+ cursor: pointer;
+ }
+`;
+
+const Form = styled.form`
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+`;
+
+const Search = styled.input`
+ box-sizing: border-box;
+ border: none;
+ outline: none;
+ width: 520px;
+ height: 40px;
+ margin-left: 10px;
+ border-radius: 40px 0 0 40px;
+ padding: 0px 4px 0px 20px;
+ border: 1px solid rgb(211, 211, 211);
+ box-shadow: rgb(238, 238, 238) 0px 1px 2px 0px inset;
+ font-size: 15px;
+ &:focus {
+ border-width: 1.3px;
+ border-color: #3f51b5;
+ width: 530px;
+ box-shadow: rgb(238, 238, 238) 0px 1px 2px 0px inset;
+ }
+`;
+
+const Submit = styled.button`
+ width: 64px;
+ height: 40px;
+ border-radius: 0 40px 40px 0;
+ border: 1px solid rgb(211, 211, 211);
+ border-left: none;
+ padding: 1px 6px;
+ margin-right: 10px;
+ cursor: pointer;
+ &:hover {
+ background-color: rgba(220, 220, 220, 0.9);
+ }
+ svg {
+ font-size: 18px;
+ }
+`;
+
+const Profile = styled.button`
+ border-radius: 50%;
+ width: 40px;
+ height: 40px;
+ background-color: rgb(249, 249, 249);
+ border: none;
+ overflow: hidden;
+ position: relative;
+ cursor: pointer;
+ img {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 40px;
+ height: 40px;
+ }
+`;
+
+const Voice = styled(Profile)`
+ &:hover {
+ background-color: rgba(220, 220, 220, 0.9);
+ }
+ svg {
+ font-size: 16px;
+ }
+`;
+
+export default Header;
diff --git a/src/components/layout/Layout.tsx b/src/components/layout/Layout.tsx
new file mode 100644
index 0000000..05542fa
--- /dev/null
+++ b/src/components/layout/Layout.tsx
@@ -0,0 +1,39 @@
+import { Outlet, useLocation } from "react-router-dom";
+import Aside from "./Aside";
+import Header from "./Header";
+import styled from "styled-components";
+import { useEffect } from "react";
+
+const Layout = ({
+ open,
+ setOpen,
+ handleClickOpen,
+}: {
+ open: boolean;
+ setOpen: React.Dispatch>;
+ handleClickOpen: () => void;
+}) => {
+ const { pathname } = useLocation();
+
+ useEffect(() => {
+ if (pathname.includes("watch") && open === true) {
+ setOpen(false);
+ }
+ }, [pathname]);
+
+ return (
+
+
+
+
+
+
+
+ );
+};
+
+const Container = styled.div`
+ position: relative;
+`;
+
+export default Layout;
diff --git a/src/components/search/SearchCard.tsx b/src/components/search/SearchCard.tsx
new file mode 100644
index 0000000..b815608
--- /dev/null
+++ b/src/components/search/SearchCard.tsx
@@ -0,0 +1,204 @@
+import { useState, useEffect } from "react";
+import styled from "styled-components";
+import { VideoSearchData } from "../../types/videoSearchTypes";
+import { nFormatter } from "../../utils/nFormatter";
+import { videoTime } from "../../utils/videoTime";
+import { Link } from "react-router-dom";
+import { AiOutlineClockCircle } from "react-icons/ai";
+import { BiListCheck, BiDotsVerticalRounded } from "react-icons/bi";
+import { displayedAt } from "../../utils/displayedAt";
+import { getVideoDetail, getDescription } from "../../api/api";
+import {
+ searchVideoDetailDummyData,
+ searchVideoChannelDummyData,
+} from "../../data/data";
+import type { Video } from "../../types/relatedCardTypes";
+import type { IDescription } from "../../types/descriptionTypes";
+
+const SearchCard = ({ data }: { data: VideoSearchData }) => {
+ const [videoResult, setVideoResult] = useState(
+ searchVideoDetailDummyData,
+ );
+ const [channelResult, setChannelResult] = useState(
+ searchVideoChannelDummyData,
+ );
+ const [isHovering, setIsHovering] = useState(false);
+ const [isError, setIsError] = useState("");
+ useEffect(() => {
+ getVideoDetail(data.id.videoId, setVideoResult, setIsError);
+ getDescription(data.snippet.channelId, setChannelResult, setIsError);
+ }, [data]);
+
+ return (
+ <>
+ {videoResult && channelResult && videoResult.items.length > 0 ? (
+ setIsHovering(true)}
+ onMouseOut={() => setIsHovering(false)}
+ >
+
+
+
+
+
+
+
+ {videoTime(videoResult?.items[0]?.contentDetails?.duration)}
+
+
+ {isHovering ? (
+
+
+
+
+ ) : (
+ ""
+ )}
+
+
+
+
+
+ {data.snippet.title}
+
+ {isHovering ? (
+
+
+
+ ) : (
+ ""
+ )}
+
+
+
+ 조회수{" "}
+ {nFormatter(
+ Number(videoResult?.items[0]?.statistics?.viewCount),
+ )}
+
+ {" • "}
+ {displayedAt(data.snippet.publishTime)}
+
+
+
+ {data.snippet.channelTitle}
+
+ {data.snippet.description}
+
+
+ ) : null}
+ >
+ );
+};
+
+const Section = styled.section`
+ max-height: 200px;
+ padding: 1rem 8rem 0 2rem;
+ display: flex;
+`;
+
+const Card = styled.div`
+ width: 360px;
+ height: 200px;
+ color: #fff;
+ font-size: 15px;
+ letter-spacing: 0.2px;
+ position: relative;
+`;
+
+const Video = styled.div`
+ max-width: 100%;
+ height: 200px;
+ margin-right: 20px;
+ cursor: pointer;
+ img {
+ aspect-ratio: 16 / 9;
+ height: 100%;
+ border-radius: 10px;
+ }
+`;
+
+const Duration = styled.div`
+ padding: 3px 4px;
+ background-color: rgba(0, 0, 0, 0.8);
+ position: absolute;
+ bottom: 0;
+ right: 5px;
+ font-weight: 600;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border-radius: 5px;
+ font-size: 12px;
+ margin-bottom: 3px;
+`;
+
+const HoverBox = styled.div`
+ display: flex;
+ position: absolute;
+ flex-direction: column;
+ gap: 3px;
+ top: 5px;
+ right: 5px;
+ svg {
+ font-size: 22px;
+ background-color: #000000c0;
+ border-radius: 3px;
+ padding: 3px;
+ color: #fff;
+ cursor: pointer;
+ }
+`;
+
+const Info = styled.div`
+ display: flex;
+ flex-direction: column;
+ margin-left: 15px;
+`;
+
+const TitleBox = styled.div`
+ display: flex;
+ align-items: flex-start;
+ cursor: pointer;
+`;
+
+const Title = styled.h3`
+ margin-bottom: 0.5rem;
+ line-height: 150%;
+ font-size: 18px;
+`;
+
+const MoreInfoBtn = styled.div`
+ position: absolute;
+ right: 130px;
+ cursor: pointer;
+ svg {
+ font-size: 20px;
+ }
+`;
+
+const Views = styled.div`
+ font-size: 12px;
+ color: rgb(96, 96, 96);
+ cursor: pointer;
+`;
+
+const Name = styled(Views)`
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 12px 0;
+ img {
+ border: none;
+ border-radius: 50%;
+ width: 24px;
+ height: 24px;
+ cursor: pointer;
+ }
+`;
+
+const Descript = styled(Views)``;
+
+export default SearchCard;
diff --git a/src/components/watch/Comment.tsx b/src/components/watch/Comment.tsx
new file mode 100644
index 0000000..51b9bdb
--- /dev/null
+++ b/src/components/watch/Comment.tsx
@@ -0,0 +1,109 @@
+import { AiOutlineDislike, AiOutlineLike } from "react-icons/ai";
+import styled from "styled-components";
+import type { ISnippet } from "../../types/commentsTypes";
+import { displayedAt } from "../../utils/displayedAt";
+import { Profile } from "./Description";
+
+const Comment = ({ comment }: { comment: ISnippet }) => {
+ return (
+
+
+
+
+
+
+ {comment.authorDisplayName}
+
+ {displayedAt(comment.publishedAt)}
+
+
+
+ {comment.textOriginal || comment.textDisplay}
+
+
+
+ {comment.likeCount}
+
+
+
+
+ 답글
+
+
+
+ );
+};
+export default Comment;
+const CommentList = styled.li`
+ display: flex;
+ gap: 1.25rem;
+ margin-bottom: 1.25rem;
+`;
+
+const CommentWrapper = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+ font-size: 1rem;
+ font-weight: 300;
+`;
+
+const StyledComment = styled.div`
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ line-height: 1.4;
+ font-size: 14px;
+ font-weight: 400;
+
+ span {
+ word-break: break-all;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ -webkit-line-clamp: 3;
+ }
+
+ time {
+ font-weight: 400;
+ font-size: 12px;
+ }
+`;
+
+const Author = styled.span`
+ font-size: 13px;
+ font-weight: 500;
+`;
+
+const Reply = styled.span`
+ font-size: 12px;
+ font-weight: 500;
+`;
+
+const Btn = styled.button`
+ border: none;
+ background-color: transparent;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ gap: 0.25rem;
+ padding: 0.25rem;
+
+ span {
+ font-size: 12px;
+ color: #0f0f0f;
+
+ @media (prefers-color-scheme: dark) {
+ color: #f1f1f1;
+ }
+ }
+
+ svg {
+ @media (prefers-color-scheme: dark) {
+ color: #f1f1f1;
+ }
+ }
+`;
diff --git a/src/components/watch/Comments.tsx b/src/components/watch/Comments.tsx
new file mode 100644
index 0000000..48ef84b
--- /dev/null
+++ b/src/components/watch/Comments.tsx
@@ -0,0 +1,36 @@
+import { useEffect, useState } from "react";
+import styled from "styled-components";
+import { getComments } from "../../api/api";
+import { commentsDummyData } from "../../data/data";
+import type { CommentsProp, IComment } from "../../types/commentsTypes";
+import Comment from "./Comment";
+
+const Comments = ({ comments }: CommentsProp) => {
+ const commentsData = comments.map(
+ (comment) => comment.snippet.topLevelComment.snippet,
+ );
+
+ return (
+
+ 댓글 {commentsData.length}개
+ {
+
+ {commentsData.map((comment) => (
+
+ ))}
+
+ }
+
+ );
+};
+export default Comments;
+
+const CommentSection = styled.section`
+ padding: 1.5rem;
+`;
+
+const H4 = styled.h4`
+ font-size: 1.25rem;
+ font-weight: 600;
+ margin-bottom: 2rem;
+`;
diff --git a/src/components/watch/Description.tsx b/src/components/watch/Description.tsx
new file mode 100644
index 0000000..7af9a39
--- /dev/null
+++ b/src/components/watch/Description.tsx
@@ -0,0 +1,117 @@
+import { useEffect, useState } from "react";
+import styled from "styled-components";
+import { getDescription } from "../../api/api";
+import { descriptionDummyData } from "../../data/data";
+import type {
+ IDescription,
+ IDescriptionProps,
+} from "../../types/descriptionTypes";
+import { nFormatter } from "../../utils/nFormatter";
+
+const Description = ({ channelId }: IDescriptionProps) => {
+ const [isError, setIsError] = useState("");
+
+ const [description, setDescription] =
+ useState(descriptionDummyData);
+
+ useEffect(() => {
+ getDescription(channelId, setDescription, setIsError);
+ }, [channelId]);
+
+ const desc = description?.items[0];
+
+ return (
+
+
+
+
+
+
+
+
{desc?.snippet.title}
+
+ 구독자 {nFormatter(Number(desc?.statistics.subscriberCount))}
+
+
+
+
+ {desc?.snippet.description}
+
+
+
+ 구독하기
+
+
+ );
+};
+export default Description;
+
+const DescContainer = styled.section`
+ position: relative;
+ display: flex;
+ gap: 1rem;
+ border-bottom: 1px solid rgba(90, 90, 90, 0.55);
+ padding: 1.5rem;
+`;
+
+const ProfileWrapper = styled.div`
+ display: flex;
+ gap: 1rem;
+ margin-bottom: 2rem;
+`;
+
+export const Profile = styled.div`
+ border-radius: 50%;
+ width: 32px;
+ height: 32px;
+ overflow: hidden;
+ flex-shrink: 0;
+
+ img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ }
+`;
+
+const DescWrapper = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+
+ h4 {
+ font-weight: 600;
+ line-height: 1.4;
+ }
+`;
+
+const Follower = styled.p`
+ font-size: 0.875rem;
+ color: gray;
+ margin-top: 0.25rem;
+`;
+
+const Desc = styled.p`
+ overflow: hidden;
+ display: -webkit-box;
+ -webkit-line-clamp: 3;
+ -webkit-box-orient: vertical;
+ line-height: 1.4;
+`;
+
+const SubscribeWrapper = styled.div`
+ position: absolute;
+ top: 1.5rem;
+ right: 1.5rem;
+`;
+
+const Subscribe = styled.button`
+ padding: 10px 15px;
+ background-color: red;
+ color: #fff;
+ font-weight: 700;
+ border: none;
+ border-radius: 3px;
+ cursor: pointer;
+ font-size: 14px;
+`;
diff --git a/src/components/watch/MainVideo.tsx b/src/components/watch/MainVideo.tsx
new file mode 100644
index 0000000..c2000d2
--- /dev/null
+++ b/src/components/watch/MainVideo.tsx
@@ -0,0 +1,184 @@
+import styled from "styled-components";
+import { VideoDetailData } from "../../types/videoDetailTypes";
+import { displayedAt } from "../../utils/displayedAt";
+import { nFormatter } from "../../utils/nFormatter";
+
+interface MainVideoProps {
+ videoDetailData: VideoDetailData;
+}
+
+const MainVideo = ({ videoDetailData }: MainVideoProps) => {
+ const tags = videoDetailData?.items[0]?.snippet?.tags?.map((tag, index) => {
+ if (index < 4) return #{tag} ;
+ });
+
+ return (
+
+
+ VIDEO
+
+ {tags}
+ {videoDetailData?.items[0]?.snippet?.title}
+
+ {"조회수 "}
+ {nFormatter(Number(videoDetailData?.items[0]?.statistics?.viewCount))}
+ {"회 "}
+ {displayedAt(videoDetailData?.items[0]?.snippet?.publishedAt || "")}
+
+
+
+
+
+
+
+
+ {nFormatter(
+ Number(videoDetailData?.items[0].statistics.likeCount),
+ ) || ""}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 공유
+
+
+
+
+
+
+ 저장
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+const VideoContainer = styled.div`
+ border-bottom: 1px solid rgba(90, 90, 90, 0.55);
+`;
+
+const VideoPlayer = styled.div`
+ position: relative;
+ padding-top: 56.25%;
+`;
+
+const Iframe = styled.iframe`
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+`;
+
+const Tags = styled.div`
+ display: flex;
+ color: #09f;
+ margin-top: 20px;
+ font-size: 12px;
+`;
+
+const Tag = styled.div`
+ margin-right: 0.5rem;
+ cursor: pointer;
+`;
+
+const Title = styled.div`
+ word-break: break-word;
+ font-size: 20px;
+ font-weight: 600;
+ margin: 12px 0;
+`;
+
+const ViewDateInfo = styled.div`
+ color: #aaaaaa;
+ font-size: 14px;
+`;
+
+const ButtonWrapper = styled.div`
+ display: flex;
+ justify-content: flex-end;
+`;
+
+const Button = styled.div`
+ display: flex;
+ align-items: center;
+ padding: 1.2rem;
+ padding-top: 0;
+ cursor: pointer;
+ span {
+ font-weight: 600;
+ margin-left: 0.5rem;
+ }
+`;
+
+const LikeContainer = styled.div`
+ display: flex;
+ align-items: center;
+ border-bottom: 2px solid;
+`;
+
+export default MainVideo;
diff --git a/src/components/watch/RelatedCard.tsx b/src/components/watch/RelatedCard.tsx
new file mode 100644
index 0000000..ef96bdc
--- /dev/null
+++ b/src/components/watch/RelatedCard.tsx
@@ -0,0 +1,164 @@
+import React, { useState, useEffect } from "react";
+import { instance } from "../../api";
+import styled from "styled-components";
+import { Link } from "react-router-dom";
+import { displayedAt } from "../../utils/displayedAt";
+import { nFormatter } from "../../utils/nFormatter";
+import { videoTime } from "../../utils/videoTime";
+import { AiOutlineClockCircle } from "react-icons/ai";
+import { BiListCheck, BiDotsVerticalRounded } from "react-icons/bi";
+import { getVideoDetail } from "../../api/api";
+import { videoDetailDummyData } from "../../data/data";
+import type { RelatedItem } from "../../types/relatedItemType";
+import type { Video } from "../../types/relatedCardTypes";
+
+type Props = { item: RelatedItem };
+
+function RelatedCard({ item }: Props) {
+ localStorage.setItem("relatedCard", JSON.stringify(item));
+
+ const videoDate: number = new Date(item.snippet.publishTime).getTime();
+ const [videoResult, setVideoResult] = useState(videoDetailDummyData);
+ const [isHovering, setIsHovering] = useState(false);
+ const [isError, setIsError] = useState("");
+ // useEffect(() => {
+ // // getVideoDetail(item.id.videoId, setVideoResult, setIsError);
+ // }, [item]);
+ const watchLink = `/watch/${item.id.videoId}`;
+ return (
+
+ setIsHovering(true)}
+ onMouseOut={() => setIsHovering(false)}
+ >
+
+
+
+ {videoTime(videoResult?.items[0]?.contentDetails?.duration || "")}
+
+ {isHovering ? (
+
+
+
+
+ ) : null}
+
+
+ {item.snippet.title}
+ {isHovering ? (
+
+
+
+ ) : null}
+ {item.snippet.channelTitle}
+
+
+ 조회수{" "}
+ {nFormatter(Number(videoResult?.items[0]?.statistics?.viewCount))}
+
+ •
+ {displayedAt(item.snippet.publishTime)}
+
+
+
+
+ );
+}
+const PreviewBox = styled.div`
+ position: relative;
+ width: 160px;
+ height: 90px;
+ cursor: pointer;
+`;
+const VideoTime = styled.span`
+ position: absolute;
+ background-color: #000000c0;
+ padding: 4px;
+ right: 5px;
+ bottom: 5px;
+ font-size: 12px;
+ border-radius: 3px;
+ color: #fff;
+`;
+
+const Thumbnail = styled.img`
+ width: 100%;
+ border-radius: 5px;
+`;
+const VideoCard = styled.div`
+ max-width: 400px;
+ min-width: 300px;
+ display: flex;
+ height: 90px;
+ margin-bottom: 10px;
+ :hover h3 {
+ font-weight: 500;
+ }
+`;
+const RelatedTitle = styled.h3`
+ width: 90%;
+ font-size: 14px;
+ text-overflow: ellipsis;
+ font-weight: 400;
+ overflow: hidden;
+ word-break: break-word;
+ line-height: 1.1rem;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ cursor: pointer;
+`;
+const RelatedChannel = styled.p`
+ font-size: 12px;
+ font-weight: 300;
+ cursor: pointer;
+ :hover {
+ font-weight: 500;
+ }
+`;
+const DetailBox = styled.div`
+ display: flex;
+ position: relative;
+ flex-direction: column;
+ justify-content: space-around;
+ width: calc(100% - 160px);
+ padding-left: 12px;
+`;
+
+const InfoBox = styled.div`
+ display: flex;
+ font-size: 12px;
+ font-weight: 400;
+ cursor: pointer;
+`;
+const InfoDot = styled.span`
+ margin: 0 3px;
+`;
+
+const HoverBox = styled.div`
+ display: flex;
+ position: absolute;
+ flex-direction: column;
+ gap: 3px;
+ top: 5px;
+ right: 5px;
+ svg {
+ font-size: 16px;
+ background-color: #000000c0;
+ border-radius: 3px;
+ padding: 3px;
+ color: #fff;
+ cursor: pointer;
+ }
+`;
+const MoreInfoBtn = styled.div`
+ position: absolute;
+ right: 0px;
+ top: 5px;
+ cursor: pointer;
+ svg {
+ font-size: 20px;
+ }
+`;
+
+export default RelatedCard;
diff --git a/src/components/watch/RelatedVideo.tsx b/src/components/watch/RelatedVideo.tsx
new file mode 100644
index 0000000..e930016
--- /dev/null
+++ b/src/components/watch/RelatedVideo.tsx
@@ -0,0 +1,23 @@
+import { useEffect, useState } from "react";
+import RelatedCard from "./RelatedCard";
+import styled from "styled-components";
+import { relatedVideoDummyData } from "../../data/data";
+import type { RelatedType } from "../../types/relatedTypes"
+
+type Props = { relatedData: RelatedType };
+
+function RelatedVideo({ relatedData }: Props) {
+ return (
+
+ {relatedData?.map((item: any) => (
+
+ ))}
+
+ );
+}
+
+const RelatedList = styled.div`
+ max-width: 400px;
+`;
+
+export default RelatedVideo;
diff --git a/src/data/data.ts b/src/data/data.ts
new file mode 100644
index 0000000..917185a
--- /dev/null
+++ b/src/data/data.ts
@@ -0,0 +1,3633 @@
+export const videoDetailDummyData = {
+ kind: "youtube#videoListResponse",
+ etag: "UaVhWWfFRX6oOr9PuxvQGoIRITU",
+ items: [
+ {
+ kind: "youtube#video",
+ etag: "s43bWhmTNZVZVZZ0lWueAgD96s4",
+ id: "ZDHCU-j3y4Y",
+ snippet: {
+ publishedAt: "2023-01-15T19:00:11Z", // O
+ channelId: "UCwQLh1dMRrT4WRjNKYzGHcw",
+ title: "The History Of Reworks That FAILED In League Of Legends", // O
+ description:
+ "Throughout League's entire history, many champions were reworked or reimagined to have a more healthy, modernized, and engaging playstyle. For the most part, the majority of them have turned out for the better, but there were a few that turned out so bad that they actually had to get REVERTED (or in some cases reworked again). Today we'll be going through some of League's Failed Reworks!\n\nLeague of Legends Discussion Playlist: https://bit.ly/3dzJuUZ\n\nCheck out my Genshin Impact channel! https://bit.ly/3HQN9ud\nCheck out my Smash Bros channel! https://bit.ly/3rlFD3Z\n\nSupport me on Patreon! https://bit.ly/3iy5pvu\nDonate to the channel! https://bit.ly/36TpIQP\n\n~Editor (TofuGraphics)~\nTwitter: https://twitter.com/TofuGraphics\n\n~Contact Links~\nFacebook: https://bit.ly/3lGV9Vg\nTwitter: https://bit.ly/3kv7CZU\nDiscord: https://bit.ly/33M2iev\nTwitch: https://bit.ly/2XNes31\nCandle.gg: https://bit.ly/3ndfU9r\nEmail: varsverum@gmail.com (Business inquiries only)\n\nGraphics provided by: https://twitter.com/TofuGraphics\n\n#LoL #Fail #Reworks",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/ZDHCU-j3y4Y/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/ZDHCU-j3y4Y/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/ZDHCU-j3y4Y/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/ZDHCU-j3y4Y/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/ZDHCU-j3y4Y/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "Vars",
+ tags: [
+ "vars",
+ "varsverum",
+ "league of legends",
+ "lol",
+ "vars lol",
+ "league of legends gameplay",
+ "lol discussion",
+ "vars league of legends",
+ "why no one plays",
+ "lol why no one plays",
+ "lol rework",
+ "lol rengar rework",
+ "lol asol rework",
+ "lol aurelion sol rework",
+ "lol zac",
+ "lol zac ultimate",
+ "lol leblanc rework",
+ "lol leblanc revert",
+ "lol rengar revert",
+ "rework",
+ "lol new aurelion sol",
+ "lol aurelion sol abilities",
+ "reworks in league of legends",
+ "lol kog'maw 5.0 attack speed",
+ "lol ryze",
+ ],
+ categoryId: "20",
+ liveBroadcastContent: "none",
+ localized: {
+ title: "The History Of Reworks That FAILED In League Of Legends",
+ description:
+ "Throughout League's entire history, many champions were reworked or reimagined to have a more healthy, modernized, and engaging playstyle. For the most part, the majority of them have turned out for the better, but there were a few that turned out so bad that they actually had to get REVERTED (or in some cases reworked again). Today we'll be going through some of League's Failed Reworks!\n\nLeague of Legends Discussion Playlist: https://bit.ly/3dzJuUZ\n\nCheck out my Genshin Impact channel! https://bit.ly/3HQN9ud\nCheck out my Smash Bros channel! https://bit.ly/3rlFD3Z\n\nSupport me on Patreon! https://bit.ly/3iy5pvu\nDonate to the channel! https://bit.ly/36TpIQP\n\n~Editor (TofuGraphics)~\nTwitter: https://twitter.com/TofuGraphics\n\n~Contact Links~\nFacebook: https://bit.ly/3lGV9Vg\nTwitter: https://bit.ly/3kv7CZU\nDiscord: https://bit.ly/33M2iev\nTwitch: https://bit.ly/2XNes31\nCandle.gg: https://bit.ly/3ndfU9r\nEmail: varsverum@gmail.com (Business inquiries only)\n\nGraphics provided by: https://twitter.com/TofuGraphics\n\n#LoL #Fail #Reworks",
+ },
+ defaultAudioLanguage: "en",
+ },
+ contentDetails: {
+ duration: "PT15M1S",
+ dimension: "2d",
+ definition: "hd",
+ caption: "false",
+ licensedContent: true,
+ contentRating: {},
+ projection: "rectangular",
+ },
+ statistics: {
+ viewCount: "50299", // O
+ likeCount: "2700", // O
+ favoriteCount: "0",
+ commentCount: "289",
+ },
+ player: {
+ // O
+ embedHtml:
+ '',
+ },
+ },
+ ],
+ pageInfo: {
+ totalResults: 1,
+ resultsPerPage: 1,
+ },
+};
+
+export const commentsDummyData = [
+ {
+ kind: "youtube#commentThread",
+ etag: "ZGp5YeVjs4LcHrWGtbwiZNgq2tY",
+ id: "UgyKSucEINu_lC1i0Xl4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "fmG2fTsh6hgtCeMboP4Out87NYc",
+ id: "UgyKSucEINu_lC1i0Xl4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay: "정준하 욕심 겁나많아보인다",
+ textOriginal: "정준하 욕심 겁나많아보인다",
+ authorDisplayName: "젊은청년",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/ytc/AMLnZu8btLRG6NCYsNRue13AJDp-o9wtWoSgAm1fTg=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCBVpEXdBNFKQe8uiC6gPUaA",
+ authorChannelId: {
+ value: "UCBVpEXdBNFKQe8uiC6gPUaA",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 1,
+ publishedAt: "2023-01-13T06:54:00Z",
+ updatedAt: "2023-01-13T06:54:00Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "fhmC2Nq2s9rJwHP8GY1gL43Dpks",
+ id: "UgxzDnqWMfRL7WHF5Ot4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "W86U2npC_YOpFJ5qAW6DPeAPGBg",
+ id: "UgxzDnqWMfRL7WHF5Ot4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay:
+ "진짜...이광수 전에 노홍철이 있었다 진짜 광기다......",
+ textOriginal: "진짜...이광수 전에 노홍철이 있었다\n진짜 광기다......",
+ authorDisplayName: "윤재현",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/ytc/AMLnZu_D1oFvD2EDAxkxuKiUm1AP4QjHv7WW4wwfNpSd=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCMvxFyM0KogrC3B6LpBImTg",
+ authorChannelId: {
+ value: "UCMvxFyM0KogrC3B6LpBImTg",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 0,
+ publishedAt: "2023-01-10T12:38:50Z",
+ updatedAt: "2023-01-10T12:38:50Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "RUGId9pTGetUQFENjXVLdc0Sq90",
+ id: "Ugx8smEPSDT9zaqEqmR4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "r5wvQA-BZpP1zhV1v1xIeGUPfcA",
+ id: "Ugx8smEPSDT9zaqEqmR4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay:
+ '7:40 조력자라고 하지않고 신인 개그맨 이름 한번더 언급해주는 유재석',
+ textOriginal:
+ "7:40 조력자라고 하지않고 신인 개그맨 이름 한번더 언급해주는 유재석",
+ authorDisplayName: "코쿤",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/ytc/AMLnZu8HcCEOLh9E6_lL--632Na6xKWdi02USFC9oIVp=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCuc--dlCwj1GYamWqdZlJOA",
+ authorChannelId: {
+ value: "UCuc--dlCwj1GYamWqdZlJOA",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 1,
+ publishedAt: "2023-01-09T05:30:02Z",
+ updatedAt: "2023-01-09T05:30:02Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "qDX4i5D2ISR1ArcpmI1x7pjxXHE",
+ id: "UgyIhfzhY0Z1boPEyxB4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "t8hizTyaRp5oMYwnla8h0BVLDwg",
+ id: "UgyIhfzhY0Z1boPEyxB4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay:
+ "술래잡기가 완성도, 결과 면에서는 여드름 브레이크, 돈가방보다 좋았다고 생각한다. 특히나 후반부가 진짜 쫄깃하고 재밌었음",
+ textOriginal:
+ "술래잡기가 완성도, 결과 면에서는 여드름 브레이크, 돈가방보다 좋았다고 생각한다. 특히나 후반부가 진짜 쫄깃하고 재밌었음",
+ authorDisplayName: "J J",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/ytc/AMLnZu-Z0n2aGfI191mqgKgktUjrg6kqT1Hwt0B1Yw=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCco0kb3kOPcq5PQ2yrQwqlg",
+ authorChannelId: {
+ value: "UCco0kb3kOPcq5PQ2yrQwqlg",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 0,
+ publishedAt: "2023-01-08T09:25:23Z",
+ updatedAt: "2023-01-08T09:25:23Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "u6IpscIrVfsrb0CvA321-aXRP2A",
+ id: "UgzOBNj0B6-J3eZ3n714AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "zlalgNHvUkI7Gv9XCYDKdJDGx6k",
+ id: "UgzOBNj0B6-J3eZ3n714AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay: "형돈이는 어디간거징",
+ textOriginal: "형돈이는 어디간거징",
+ authorDisplayName: "잭과콩나물공장",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/Mtq_4v3eXh3ei-Dr60KKx0-scI50reN2wOR7a0mI4wbV83a-aQN0ld3g39ZZCyXlDyQ1Z9vMHg=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCJhrhTTYIVn-OKyXyilbebQ",
+ authorChannelId: {
+ value: "UCJhrhTTYIVn-OKyXyilbebQ",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 0,
+ publishedAt: "2023-01-05T04:39:21Z",
+ updatedAt: "2023-01-05T04:39:21Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "I2hytVoktWbJNwq8QMF0KTidpa8",
+ id: "UgziY2Ei7C2kHXc5iG14AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "VzqGUrZdjom_Yw3ODtPc93CKDK8",
+ id: "UgziY2Ei7C2kHXc5iG14AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay: "뾰요오옹",
+ textOriginal: "뾰요오옹",
+ authorDisplayName: "유빈이",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/ytc/AMLnZu92oTckcvmM4ukkAoMssmqAhiijpM-HPrDPvfyHfHwkrw=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCCcsCOLw0JQXgy4jgXuY3Rw",
+ authorChannelId: {
+ value: "UCCcsCOLw0JQXgy4jgXuY3Rw",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 0,
+ publishedAt: "2023-01-02T13:03:29Z",
+ updatedAt: "2023-01-02T13:03:29Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "9tjCHtYRbnMrR0NsavsaZMRqhD4",
+ id: "Ugypb_eRVJD1ugZPyqt4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "KmZJu185NqCurO26aWQnTdfmxbk",
+ id: "Ugypb_eRVJD1ugZPyqt4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay: "박명수 그래도 문 안 잠그고 방송 위해서 적당히 타협..",
+ textOriginal: "박명수 그래도 문 안 잠그고 방송 위해서 적당히 타협..",
+ authorDisplayName: "고영규",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/ytc/AMLnZu9pA0DL3LNZn_X5xmgj756v-eKSsSzehwLvbqBukg=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCAwuu16r-pGHBr9nMiwtWXg",
+ authorChannelId: {
+ value: "UCAwuu16r-pGHBr9nMiwtWXg",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 0,
+ publishedAt: "2023-01-01T11:03:47Z",
+ updatedAt: "2023-01-01T11:03:47Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "Eqt6nPSTJ-MzBZhx3Td5CN-tLs8",
+ id: "UgxOCRIm4z37brVvzdp4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "by5dlZUW5Vfq7J5uEcNF4tn5URw",
+ id: "UgxOCRIm4z37brVvzdp4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay: "무한도전만의 이런 추격전 다시 느끼고싶다..",
+ textOriginal: "무한도전만의 이런 추격전 다시 느끼고싶다..",
+ authorDisplayName: "이나 김",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/ytc/AMLnZu8nA8pULegKUS9ur9pmAlTeiFLytp3HbrOlzoB0D2KLGg=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCKoPWpRMvf5gr4sbA2OPkww",
+ authorChannelId: {
+ value: "UCKoPWpRMvf5gr4sbA2OPkww",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 0,
+ publishedAt: "2022-12-31T12:05:42Z",
+ updatedAt: "2022-12-31T12:05:42Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "_ZuUl3ATUPQoBI_Es3HToaKSo3o",
+ id: "UgzzYNiuu4qWZIOKOUZ4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "7gEMm5T1THQAC60zN9ME2SZqLc4",
+ id: "UgzzYNiuu4qWZIOKOUZ4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay: "진정한 광기ㅋㅋㅋ",
+ textOriginal: "진정한 광기ㅋㅋㅋ",
+ authorDisplayName: "노약자석터줏대감",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/sYJWrhnrU7i8W9wmeIv5zQJ8rlzTHtzUyxtta7la1-H3itmnZuj3SPdFr0GO71h6pQyEQlgUaw=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCdJdPvz-1m3_xQcbSnKIzKw",
+ authorChannelId: {
+ value: "UCdJdPvz-1m3_xQcbSnKIzKw",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 0,
+ publishedAt: "2022-12-31T02:57:53Z",
+ updatedAt: "2022-12-31T02:57:53Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "fYdh41L_2J3q_6eXJ6m1jEHS2Cg",
+ id: "UgzGWjUe9nNTf_9TOC94AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "nknZAiTQ3HBIhGi3bIjtgUCfwR4",
+ id: "UgzGWjUe9nNTf_9TOC94AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay:
+ '15:35 장손이 아니에요ㅋㅋㅋ 돌아잌ㅋㅋㅋ',
+ textOriginal: "15:35 장손이 아니에요ㅋㅋㅋ 돌아잌ㅋㅋㅋ",
+ authorDisplayName: "룬",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/ytc/AMLnZu9TLDEYaJ6gV8sv8XYKhGdjco3j2t38cCNRR9k4oA=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UC5e40lG8mBNvvB6Cj5dozig",
+ authorChannelId: {
+ value: "UC5e40lG8mBNvvB6Cj5dozig",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 0,
+ publishedAt: "2022-12-30T09:44:29Z",
+ updatedAt: "2022-12-30T09:44:29Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "eVNRoA2PyQrT_SImYmYvGF-Lgk8",
+ id: "UgxYG6u-4V54jbwgmnl4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "2yQEdEldlt1t_hEPlzFosuRb-iI",
+ id: "UgxYG6u-4V54jbwgmnl4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay:
+ '15:33 "저는 여한이 없어요 처자식도 없어요" "부모님이 계시잖아" "장손이 아니예요" ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ',
+ textOriginal:
+ '15:33 "저는 여한이 없어요 처자식도 없어요" \n"부모님이 계시잖아"\n"장손이 아니예요"\nㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ',
+ authorDisplayName: "김이름",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/ytc/AMLnZu8wFHh5gtqTtW-d6ugJX5892JmTCOLN_IRQkmVi=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCg3tKiygYu62uN7LPZgGOhA",
+ authorChannelId: {
+ value: "UCg3tKiygYu62uN7LPZgGOhA",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 0,
+ publishedAt: "2022-12-25T03:09:35Z",
+ updatedAt: "2022-12-25T03:09:35Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "4U2AGGcf8Zfg-DjPtOcNQA9t3_U",
+ id: "UgyGnngduQ5c1D4cYtN4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "_ct2wYyiq3QDbG-j31iw3NFWYnM",
+ id: "UgyGnngduQ5c1D4cYtN4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay:
+ "박명수 2분 남기고 하하핳 거리면서 오토바이 타는거 개귀엽ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬",
+ textOriginal:
+ "박명수 2분 남기고 하하핳 거리면서 오토바이 타는거 개귀엽ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬ㅋ⫬",
+ authorDisplayName: "알명수",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/j0py5aAO7UItcsI_LY5cf9nLeF6Y56eqRUOT3HaestiPZLHYHkd35nPnTfohTIlAhttPQaLs-Q=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCJzpcUYXpKE66DO0jYdsTTA",
+ authorChannelId: {
+ value: "UCJzpcUYXpKE66DO0jYdsTTA",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 0,
+ publishedAt: "2022-12-22T05:50:27Z",
+ updatedAt: "2022-12-22T05:50:27Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "JoUKKUWvLpBorx-YMNFvPPg-Fas",
+ id: "UgwCP1vI-CoieKeP1oB4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "YpRU6TeF3W7JP9T9af8cMtwKe-Y",
+ id: "UgwCP1vI-CoieKeP1oB4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay:
+ '15:40 어? 박명수씨네 제발 형한테 형이라고좀 해 유재석한테는 틈만 나면 너는 형한테 어쩌구저쩌구 말하면서 너는 왜 안하는데?? 쉼표편에서 나온것처럼 장점많은사람인거 아는데 단점하나가 진짜 조오오오오온나 큼',
+ textOriginal:
+ "15:40 어? 박명수씨네\n제발 형한테 형이라고좀 해\n유재석한테는 틈만 나면 너는 형한테 어쩌구저쩌구 말하면서 너는 왜 안하는데?? \n쉼표편에서 나온것처럼 장점많은사람인거 아는데 단점하나가 진짜 조오오오오온나 큼",
+ authorDisplayName: "ABCABC",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/DNyLdVU0Rn6wkeyBCi9NkDvC89HWonThBSGjbotgcBL9qke0MtyZdMzClfEIy4-nQiWWSqgAyg=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCghYiFI_PWYxAByNe95P_rg",
+ authorChannelId: {
+ value: "UCghYiFI_PWYxAByNe95P_rg",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 1,
+ publishedAt: "2022-12-21T13:03:00Z",
+ updatedAt: "2022-12-21T13:03:00Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 2,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "pIDFU7t-hFosX8C7rhHpI6ML9iw",
+ id: "Ugx6k_cR0oxntxX-X6p4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "XcyjKSh6oxBPJkPAL0W9TlyRe-o",
+ id: "Ugx6k_cR0oxntxX-X6p4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay:
+ "지금 생각해보니까 저 찬물 위에 17분 동안 있었단 거네 ㄷ ㄷ",
+ textOriginal:
+ "지금 생각해보니까 저 찬물 위에 17분 동안 있었단 거네 ㄷ ㄷ",
+ authorDisplayName: "Si -hun",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/ytc/AMLnZu8PNG5qvLDn1w-0hvR5qCfhkYNYqXvZ-uuGhRyolg=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCKYckvI8xQ8ylisj2S9wQPw",
+ authorChannelId: {
+ value: "UCKYckvI8xQ8ylisj2S9wQPw",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 22,
+ publishedAt: "2022-12-20T19:59:15Z",
+ updatedAt: "2022-12-20T19:59:15Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "YZbI8_RL7dnTv8kAINMtm00KKTQ",
+ id: "Ugx_2Yu0YVVw9w6jiud4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "T2P05MP4iQb_9qPTzuZ8lhiVUSE",
+ id: "Ugx_2Yu0YVVw9w6jiud4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay:
+ '7:48 진짜 광기 레전드 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ',
+ textOriginal:
+ "7:48 진짜 광기 레전드 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ",
+ authorDisplayName: "서울사는사람",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/z-02RdNMu1US4L4nbViZuFcuzYUBpTb8oZeCHQZWAk2CKMT7faNDKRANmRfutlmBu0vPSsXJ=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCqckkltVGybgk0hlVBU2BDg",
+ authorChannelId: {
+ value: "UCqckkltVGybgk0hlVBU2BDg",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 15,
+ publishedAt: "2022-12-16T16:53:38Z",
+ updatedAt: "2022-12-16T16:53:38Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "ZMY6YXkBNKyj5fk1COAiOFoaSps",
+ id: "Ugxq3XCpmwW9ew_birF4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "mwPAD0gxGy5-HFAkOG_o4Ce9NHQ",
+ id: "Ugxq3XCpmwW9ew_birF4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay: "정준하는 진짜 게임을 재미없게하는구나 그렇구나",
+ textOriginal: "정준하는 진짜 게임을 재미없게하는구나 그렇구나",
+ authorDisplayName: "손동준",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/ytc/AMLnZu--mcxnKJoI59uE8u8UdsA_gMX6njiDYq-Ev9NPu2Wf3g=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UC4hASrxu6oYpbkvjrcsQcZA",
+ authorChannelId: {
+ value: "UC4hASrxu6oYpbkvjrcsQcZA",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 0,
+ publishedAt: "2022-12-15T13:33:37Z",
+ updatedAt: "2022-12-15T13:33:37Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 1,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "48oWKoG1jf2-bfATc5IRvh-cyn4",
+ id: "UgzSAO2uOfK0ihxQTeN4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "QYwGvSanUTEZrv2tA8Ze2wX006I",
+ id: "UgzSAO2uOfK0ihxQTeN4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay:
+ "역시 유재석이다 물속에서 노홍철 잡을 수 있었는데 분량 재미 그런거 생각해서 일부러 바로 안잡았네",
+ textOriginal:
+ "역시 유재석이다\n물속에서 노홍철 잡을 수 있었는데 분량 재미 그런거 생각해서 일부러 바로 안잡았네",
+ authorDisplayName: "박상기",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/ytc/AMLnZu-x6tGyn6JYSqdZtPUpweiOzFqJm-KIqB238g=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCAXYo02l2KANRPW41ysVRfw",
+ authorChannelId: {
+ value: "UCAXYo02l2KANRPW41ysVRfw",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 40,
+ publishedAt: "2022-12-13T06:05:46Z",
+ updatedAt: "2022-12-13T06:05:46Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "Kc2f-c2CslI_sr4E71nXlljiOu4",
+ id: "Ugw3rvPT887A48FhzoV4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "jdg9qvskbN8HgqXWulHVbxWALd4",
+ id: "Ugw3rvPT887A48FhzoV4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay: "50cc는 면허 필요없음?",
+ textOriginal: "50cc는 면허 필요없음?",
+ authorDisplayName: "박태훈",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/ytc/AMLnZu_XTwLFAzvLNZiOxCx2Z677fk-fu75mwBNzzoY4Eu7EbA=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCiAaxZpT39uHlI4GrIe5R5Q",
+ authorChannelId: {
+ value: "UCiAaxZpT39uHlI4GrIe5R5Q",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 0,
+ publishedAt: "2022-12-07T18:54:52Z",
+ updatedAt: "2022-12-07T18:54:52Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "IiHb78HTCa-YJ_Ivd-gVB8Sw4jI",
+ id: "UgxYppMPrQO4DQ87cwN4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "Lh4ooUsCW27jKUKpyF1mCRDwOFY",
+ id: "UgxYppMPrQO4DQ87cwN4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay: "이런게 진짜 버라이어티지 ㅋㅋㅋㅋ",
+ textOriginal: "이런게 진짜 버라이어티지 ㅋㅋㅋㅋ",
+ authorDisplayName: "아뉘",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/ytc/AMLnZu9N4rsR_ExInUp2Vcs_-2GYnBlUd_l5hVcpBR9Lgw=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UC0EWH6wY6uu3pBxHIwSvS_A",
+ authorChannelId: {
+ value: "UC0EWH6wY6uu3pBxHIwSvS_A",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 3,
+ publishedAt: "2022-12-01T14:14:35Z",
+ updatedAt: "2022-12-01T14:14:35Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+ {
+ kind: "youtube#commentThread",
+ etag: "dSRFMNi4Ke8g8M53kr_YoatIJSE",
+ id: "UgydNL-Jg6X7CewnMMt4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ topLevelComment: {
+ kind: "youtube#comment",
+ etag: "MmLYg3D9QKpoidIhzngSb3U-WLE",
+ id: "UgydNL-Jg6X7CewnMMt4AaABAg",
+ snippet: {
+ videoId: "T95sMUMyb3o",
+ textDisplay: "아이고미치겠네 이거 죽겠네 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ",
+ textOriginal: "아이고미치겠네 이거 죽겠네 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ",
+ authorDisplayName: "윤재앙오세이돈",
+ authorProfileImageUrl:
+ "https://yt3.ggpht.com/ytc/AMLnZu_YUSUSZtx8sTDP-5TAJmW9lcA_QML1RH2UsOIHIA=s48-c-k-c0x00ffffff-no-rj",
+ authorChannelUrl:
+ "http://www.youtube.com/channel/UCxt-rA4QVTCUgchiFtgwV_w",
+ authorChannelId: {
+ value: "UCxt-rA4QVTCUgchiFtgwV_w",
+ },
+ canRate: true,
+ viewerRating: "none",
+ likeCount: 0,
+ publishedAt: "2022-11-21T07:28:11Z",
+ updatedAt: "2022-11-21T07:28:11Z",
+ },
+ },
+ canReply: true,
+ totalReplyCount: 0,
+ isPublic: true,
+ },
+ },
+];
+
+export const descriptionDummyData = {
+ kind: "youtube#channelListResponse",
+ etag: "ajF4r6clnUEyVb9aBeacaRfXn5w",
+ pageInfo: { totalResults: 1, resultsPerPage: 5 },
+ items: [
+ {
+ kind: "youtube#channel",
+ etag: "lahV7vkMgJ4f4Hw9t8XXIBGrzps",
+ id: "UCwQLh1dMRrT4WRjNKYzGHcw",
+ snippet: {
+ title: "Vars",
+ description:
+ '“You take 20 minutes to explain what should only take 2."\n\nWelcome to my main channel! Here you can find discussions, analysis and video essays on League of Legends. My second channel has the same but for Genshin Impact and my third channel features Super Smash Bros. Utlimate.\n\n(As of 04/13/2022) Currently making videos/content on:\n- League of Legends - This channel!\n- Genshin Impact - https://www.youtube.com/varsii\n- Super Smash Bros. Ultimate - https://www.youtube.com/varsiii\n',
+ customUrl: "@varsverum",
+ publishedAt: "2018-01-26T02:28:53Z",
+ thumbnails: {
+ default: {
+ url: "https://yt3.ggpht.com/HwXPP35OjkzHI6_BSUe0XvtrM7zg5mb__A1a_xl4oiehjIZyVTusYkyl9jWv8eByy7Yw7QbR=s88-c-k-c0x00ffffff-no-rj",
+ width: 88,
+ height: 88,
+ },
+ medium: {
+ url: "https://yt3.ggpht.com/HwXPP35OjkzHI6_BSUe0XvtrM7zg5mb__A1a_xl4oiehjIZyVTusYkyl9jWv8eByy7Yw7QbR=s240-c-k-c0x00ffffff-no-rj",
+ width: 240,
+ height: 240,
+ },
+ high: {
+ url: "https://yt3.ggpht.com/HwXPP35OjkzHI6_BSUe0XvtrM7zg5mb__A1a_xl4oiehjIZyVTusYkyl9jWv8eByy7Yw7QbR=s800-c-k-c0x00ffffff-no-rj",
+ width: 800,
+ height: 800,
+ },
+ },
+ localized: {
+ title: "Vars",
+ description:
+ '“You take 20 minutes to explain what should only take 2."\n\nWelcome to my main channel! Here you can find discussions, analysis and video essays on League of Legends. My second channel has the same but for Genshin Impact and my third channel features Super Smash Bros. Utlimate.\n\n(As of 04/13/2022) Currently making videos/content on:\n- League of Legends - This channel!\n- Genshin Impact - https://www.youtube.com/varsii\n- Super Smash Bros. Ultimate - https://www.youtube.com/varsiii\n',
+ },
+ country: "US",
+ },
+ contentDetails: {
+ relatedPlaylists: { likes: "", uploads: "UUwQLh1dMRrT4WRjNKYzGHcw" },
+ },
+ statistics: {
+ viewCount: "54584880",
+ subscriberCount: "176000",
+ hiddenSubscriberCount: false,
+ videoCount: "622",
+ },
+ },
+ ],
+};
+
+export const relatedVideoDummyData = [
+ {
+ kind: "youtube#searchResult",
+ etag: "GRuv7Grp6FaviVH8yWbbiCcig2w",
+ id: { kind: "youtube#video", videoId: "uLxPN-J8WqA" },
+ snippet: {
+ publishedAt: "2022-03-04T00:28:44Z",
+ channelId: "UCwQLh1dMRrT4WRjNKYzGHcw",
+ title: "Ionia: Why So Many Champions Are Overloaded | League of Legends",
+ description:
+ "AFTER TWO MONTHS WE FINALLY HAVE THE THIRD EPISODE OF MY LORE SERIES XD Sorry about that! I promise though this one's gonna be a banger! For today let's dive into the lore of Ionia and how its champions have a rather questionable definition of what \"balance\" is supposed to be.\n\nLeague of Legends Champion Lore/Factions Playlist: https://bit.ly/3FQpoBu\n\n~Check out my second channel!~ https://bit.ly/3HQN9ud\n\nSupport me on Patreon! https://bit.ly/3iy5pvu\nDonate to the channel! https://bit.ly/36TpIQP\n\n~Editor (Aphrow)~\nTwitter: https://twitter.com/aphrew\nTwitch: https://www.twitch.tv/afrew\nYouTube: https://www.youtube.com/channel/UCOEcYMd0oCwNtpyLvTyFXtQ\nWebsite: https://www.aphediting.net/videoediting\n\n~Contact Links~\nFacebook: https://bit.ly/3lGV9Vg\nTwitter: https://bit.ly/3kv7CZU\nDiscord: https://bit.ly/33M2iev\nTwitch: https://bit.ly/2XNes31\nCandle.gg: https://bit.ly/3ndfU9r\nEmail: varsverum@gmail.com (Business inquiries only)\n\nGraphics provided by: https://twitter.com/TofuGraphics\n\n#LoL #Ionia #Lore",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/uLxPN-J8WqA/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/uLxPN-J8WqA/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/uLxPN-J8WqA/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/uLxPN-J8WqA/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/uLxPN-J8WqA/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "Vars",
+ liveBroadcastContent: "none",
+ publishTime: "2022-03-04T00:28:44Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "p4erUavdn-Ec8pzcMRJodAyoKFQ",
+ id: { kind: "youtube#video", videoId: "0Rqlq5p9QLs" },
+ snippet: {
+ publishedAt: "2023-01-16T16:05:04Z",
+ channelId: "UCvzoHz_9Vym9HUJ3lNRfCcw",
+ title: "Do You Remember The Champ So Bad You Got BANNED For Playing Her",
+ description:
+ "🕹Download for FREE: https://operagx.gg/Exil4 Join the millions of gamers optimizing their setup with the Opera GX browser. Sponsored by Opera GX!\n\n\nToday, let's talk about old league of legends, and talking about a champion that was so bad you risked getting your account banned just for playing her. The old Evelynn had such a low win rate and was so underpowered, she was a complete troll pick... This video was written, produced, edited, and voiced by Kellen (Exil)\n\n►Subscribe to the channel!! http://bit.ly/2NlXg0q\n\n»» Business inquiries\nlolelderwood@gmail.com \n\nIf you enjoy the content and want to support me and see Video Editing tutorials, please check out my Patreon! https://www.patreon.com/exil22\n\nMusic in this video comes from Epidemic Sound and the Runescape 3 Soundtrack\n\n#league #proguides #leagueoflegends",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/0Rqlq5p9QLs/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/0Rqlq5p9QLs/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/0Rqlq5p9QLs/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/0Rqlq5p9QLs/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/0Rqlq5p9QLs/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "Exil",
+ liveBroadcastContent: "none",
+ publishTime: "2023-01-16T16:05:04Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "oz4qtadkUwF892YRo2dlbo9CD3M",
+ id: { kind: "youtube#video", videoId: "ISZFYY1kP4Q" },
+ snippet: {
+ publishedAt: "2022-10-25T04:21:23Z",
+ channelId: "UCwQLh1dMRrT4WRjNKYzGHcw",
+ title:
+ 'Sion\'s Rework: Why He Was "Deleted" From The Game | League of Legends',
+ description:
+ "Sion's original design could very well be in the 5 WORST designed champions of all time. An identity split between equal parts physical damage auto attacker and magic damage AP bruiser(?) with neither being compatible with the other. As a result, Riot saw fit to discard virtually everything about old Sion and start fresh. In today's Rework Retrospective we're gonna look at their most ambitious Visual Gameplay Update done so far by that point.\n\nLeague of Legends Rework Retrospective Playlist: https://bit.ly/3yWdMsZ\n\nCheck out my Genshin Impact channel! https://bit.ly/3HQN9ud\nCheck out my Smash Bros channel! https://bit.ly/3rlFD3Z\n\nSupport me on Patreon! https://bit.ly/3iy5pvu\nDonate to the channel! https://bit.ly/36TpIQP\n\n~Editor (Wik)~\nTwitter: https://twitter.com/Wikthe3rd\nYoutube: https://www.youtube.com/channel/UCNmB6swLTafxeO2PHs6XVSg\n\n~Contact Links~\nFacebook: https://bit.ly/3lGV9Vg\nTwitter: https://bit.ly/3kv7CZU\nDiscord: https://bit.ly/33M2iev\nTwitch: https://bit.ly/2XNes31\nCandle.gg: https://bit.ly/3ndfU9r\nEmail: varsverum@gmail.com (Business inquiries only)\n\nGraphics provided by: https://twitter.com/TofuGraphics\n\n#LoL #Sion #Rework",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/ISZFYY1kP4Q/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/ISZFYY1kP4Q/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/ISZFYY1kP4Q/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/ISZFYY1kP4Q/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/ISZFYY1kP4Q/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "Vars",
+ liveBroadcastContent: "none",
+ publishTime: "2022-10-25T04:21:23Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "_d1d-7Nso2OWvxTFtDEPPisxX-A",
+ id: { kind: "youtube#video", videoId: "P_EuoNfA_yA" },
+ snippet: {
+ publishedAt: "2023-01-09T02:02:23Z",
+ channelId: "UCwQLh1dMRrT4WRjNKYzGHcw",
+ title: "Warwick Rework: A Perfect Masterpiece | League of Legends",
+ description:
+ "Warwick's visual gameplay update rework has to be arguably one of if not the best rework ever performed, a process of turning otherwise extremely simple abilities into very interactive and satisfying abilities. Let's dive into Warwick's Rework: A Retrospective!\n\nLeague of Legends Rework Retrospective Playlist: https://bit.ly/3yWdMsZ\n\nCheck out my Genshin Impact channel! https://bit.ly/3HQN9ud\nCheck out my Smash Bros channel! https://bit.ly/3rlFD3Z\n\nSupport me on Patreon! https://bit.ly/3iy5pvu\nDonate to the channel! https://bit.ly/36TpIQP\n\n~Editor (MeadowEdits)~\nTwitter: https://twitter.com/MeadowEdits\n\n~Contact Links~\nFacebook: https://bit.ly/3lGV9Vg\nTwitter: https://bit.ly/3kv7CZU\nDiscord: https://bit.ly/33M2iev\nTwitch: https://bit.ly/2XNes31\nCandle.gg: https://bit.ly/3ndfU9r\nEmail: varsverum@gmail.com (Business inquiries only)\n\nGraphics provided by: https://twitter.com/TofuGraphics\n\n#LoL #Warwick #Rework",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/P_EuoNfA_yA/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/P_EuoNfA_yA/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/P_EuoNfA_yA/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/P_EuoNfA_yA/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/P_EuoNfA_yA/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "Vars",
+ liveBroadcastContent: "none",
+ publishTime: "2023-01-09T02:02:23Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "IqC_ayy2a8mkfxg5Lu-j4RUCJdk",
+ id: { kind: "youtube#video", videoId: "nFyaJqFIsuw" },
+ snippet: {
+ publishedAt: "2023-01-13T00:02:40Z",
+ channelId: "UC5Yo88QF-chdugJbAnB2tUw",
+ title: "The Science Behind the Unproblematic Nature of the Capybara",
+ description:
+ "1st video of 2023! Appreciate y'all being patient, as you can imagine, these videos aren’t exactly quick to make (but hopefully worth it).\n\nMusic from:\nLakey Inspired: A Walk on the Moon & Watching the Clouds\nRuneScape: Medieval\nSuper Smash Bros: Delfino Plaza & Molgera Battle\nHollow Knight: Greenpath\n\nTikTok: https://vm.tiktok.com/ZM8TDoghj/\nInstagram: https://www.instagram.com/mndiaye97/?...\n\nIf you’d like to support the channel and earn access to exclusive content, check out my Patreon below \nhttps://www.patreon.com/HoodNature\n\nSubscribe, turn on ALL post notifications and make sure to drink water and hug your mother",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/nFyaJqFIsuw/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/nFyaJqFIsuw/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/nFyaJqFIsuw/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/nFyaJqFIsuw/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/nFyaJqFIsuw/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "Casual Geographic",
+ liveBroadcastContent: "none",
+ publishTime: "2023-01-13T00:02:40Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "2zvRAGcHs04dtXFP9bKVErtESfo",
+ id: { kind: "youtube#video", videoId: "kiKSqg0cfMA" },
+ snippet: {
+ publishedAt: "2022-11-18T10:04:55Z",
+ channelId: "UCFl1mGlf5j0Qno1Kxnyv6FA",
+ title: "15 INSANE MECHANICS You NEED to KNOW in League of Legends!",
+ description:
+ "►SPECIAL: https://www.skill-capped.com/lol/browse3/course/lkzr43492d/t4nk71qm79#mechanics\n►𝐒𝐔𝐁𝐒𝐂𝐑𝐈𝐁𝐄: http://goo.gl/kGvFCu\n►𝐃𝐈𝐒𝐂𝐎𝐑𝐃: https://discord.gg/CBsV72B\n\nWhat is Skill Capped?\nSkill Capped has one goal in mind: help YOU become a BETTER player FAST! We create guides that ACTUALLY WORK by the TOP PROS and COACHES. We're so confident we can help you IMPROVE that we back it up with a RANK IMPROVEMENT GUARANTEE not found anywhere else!\n\nChapters:\n00:00 Intro\n1:48 Zone Mechanics\n14:38 Movement Mechanics\n20:05 Farming Mechanics\n25:35 Hidden Mechanics\n\n\nFollow Skill Capped at:\n►TikTok: https://www.tiktok.com/@skillcappedlol\n►FACEBOOK: https://www.facebook.com/skillcapped \n►TWITTER: https://twitter.com/skillcapped \n\n#lolguides #leagueoflegends #skillcapped #season12",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/kiKSqg0cfMA/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/kiKSqg0cfMA/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/kiKSqg0cfMA/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/kiKSqg0cfMA/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/kiKSqg0cfMA/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "Skill Capped Challenger LoL Guides",
+ liveBroadcastContent: "none",
+ publishTime: "2022-11-18T10:04:55Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "Wl6prnic8I31QozrfQAGK-LCt2A",
+ id: { kind: "youtube#video", videoId: "vU2fEDRmyng" },
+ snippet: {
+ publishedAt: "2022-12-05T15:21:57Z",
+ channelId: "UCwQLh1dMRrT4WRjNKYzGHcw",
+ title: "The History Of The Most TOXIC Metas In League of Legends",
+ description:
+ "~SPONSOR~ Check out my new line of gaming PC's that were made with the help of Apex! By using my code VARS you can get up to 250$ off your first purchase! https://apexpartner.app/redirect/vars \n\nIt's been almost 13 years since League of Legends was officially released. To commemorate this, I decided to look back through the game's history and reminisce over some of the worst, most toxic metas we've had to go through and see how they shaped the game's future!\n\nLeague of Legends Discussion Playlist: https://bit.ly/3dzJuUZ\n\nCheck out my Genshin Impact channel! https://bit.ly/3HQN9ud\nCheck out my Smash Bros channel! https://bit.ly/3rlFD3Z\n\nSupport me on Patreon! https://bit.ly/3iy5pvu\nDonate to the channel! https://bit.ly/36TpIQP\n\n~Editor (MeadowEdits)~\nTwitter: https://twitter.com/MeadowEdits\n\n~Contact Links~\nFacebook: https://bit.ly/3lGV9Vg\nTwitter: https://bit.ly/3kv7CZU\nDiscord: https://bit.ly/33M2iev\nTwitch: https://bit.ly/2XNes31\nCandle.gg: https://bit.ly/3ndfU9r\nEmail: varsverum@gmail.com (Business inquiries only)\n\nGraphics provided by: https://twitter.com/TofuGraphics\n\n#LoL #Meta #History",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/vU2fEDRmyng/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/vU2fEDRmyng/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/vU2fEDRmyng/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/vU2fEDRmyng/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/vU2fEDRmyng/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "Vars",
+ liveBroadcastContent: "none",
+ publishTime: "2022-12-05T15:21:57Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "vjV8rWJXSPIKmcPzj5_0hhvTV30",
+ id: { kind: "youtube#video", videoId: "fQlUt2ciHS0" },
+ snippet: {
+ publishedAt: "2021-03-05T04:21:56Z",
+ channelId: "UCwQLh1dMRrT4WRjNKYzGHcw",
+ title:
+ "Should Untargetability Be Removed From The Game? | League of Legends",
+ description:
+ "Another discussion video! This time talking about my thoughts on Untargetability in League of Legends. Is it balanced? Is it fair? Is it overpowered? Is it bad for the game? Should it stay? Should it be removed?\n\n~Timestamps~\n(0:00) - Introduction\n(3:38) - Part One: Untargetability is Good?\n(8:09) - Part Two: Untargetability is Bad?\n\nLeague of Legends Discussion Playlist: https://bit.ly/3dzJuUZ\n\nSupport me on Patreon! https://bit.ly/3iy5pvu\nDonate to the channel! https://bit.ly/36TpIQP\n\n~Contact Links~\nDiscord: https://bit.ly/33M2iev\nTwitter: https://bit.ly/3kv7CZU\nTwitch: https://bit.ly/2XNes31\nCandle.gg: https://bit.ly/3ndfU9r\nEmail: varsverum@gmail.com (Business inquiries only)\n\nGraphics provided by: https://tofugraphics.carbonmade.com/\n\n#LoL #Untargetability #Discussion",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/fQlUt2ciHS0/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/fQlUt2ciHS0/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/fQlUt2ciHS0/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/fQlUt2ciHS0/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/fQlUt2ciHS0/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "Vars",
+ liveBroadcastContent: "none",
+ publishTime: "2021-03-05T04:21:56Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "kULfvK1R8mmr14ZrA571OPNIAPU",
+ id: { kind: "youtube#video", videoId: "YPq5aQxskcs" },
+ snippet: {
+ publishedAt: "2022-04-22T03:07:17Z",
+ channelId: "UCwQLh1dMRrT4WRjNKYzGHcw",
+ title: "Yorick's Rework: Was It A Failure? | League of Legends",
+ description:
+ "Welcome back to another episode of the Rework Retrospective series! Today we're gonna be discussing Yorick: The Sheppard of Souls. Arguably the LEAST played champion of all time in his previous iteration and... kind of still the same with his current one too. Was it a failed rework?\n\nLeague of Legends Rework Retrospective Playlist: https://bit.ly/3yWdMsZ\n\nCheck out my Genshin Impact channel! https://bit.ly/3HQN9ud\nCheck out my Smash Bros channel! https://bit.ly/3rlFD3Z\n\nSupport me on Patreon! https://bit.ly/3iy5pvu\nDonate to the channel! https://bit.ly/36TpIQP\n\n~Editor (MeadowEdits)~\nTwitter: https://twitter.com/MeadowEdits\n\n~Contact Links~\nFacebook: https://bit.ly/3lGV9Vg\nTwitter: https://bit.ly/3kv7CZU\nDiscord: https://bit.ly/33M2iev\nTwitch: https://bit.ly/2XNes31\nCandle.gg: https://bit.ly/3ndfU9r\nEmail: varsverum@gmail.com (Business inquiries only)\n\nGraphics provided by: https://twitter.com/TofuGraphics\n\n#LoL #Yorick #Rework",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/YPq5aQxskcs/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/YPq5aQxskcs/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/YPq5aQxskcs/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/YPq5aQxskcs/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/YPq5aQxskcs/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "Vars",
+ liveBroadcastContent: "none",
+ publishTime: "2022-04-22T03:07:17Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "hPqwg5vYuS9g49Ex74_p45BpSko",
+ id: { kind: "youtube#video", videoId: "POVEOmjcZwI" },
+ snippet: {
+ publishedAt: "2022-03-12T16:26:55Z",
+ channelId: "UCQHX6ViZmPsWiYSFAyS0a3Q",
+ title: "700 Elo Chess - 19 BLUNDERS!!",
+ description:
+ "➡️ Get My Chess Courses: https://www.chessly.com/\nTwo 700s created this masterpiece. \n\n➡️ Start Playing Chess FOR FREE: http://bit.ly/3Xa3EsB\n\n➡️ Enjoy my videos? Donate Here : https://www.paypal.me/gothamchess\n\nCheck out my new Cookies and Cream Cold Brew from Madrinas! Don’t forget to use code “GOTHAM” at checkout to save 20% off your order: https://madrinas.coffee/gothamchess\n\n⭐️ Follow Me If You Are Amazing:\n➡️ TWITCH: https://www.twitch.tv/gothamchess\n➡️ TIKTOK: https://www.tiktok.com/@levyrozman\n➡️ CAMEO: https://www.cameo.com/gothamchess\n➡️ TWITTER: https://twitter.com/gothamchess\n➡️ INSTAGRAM: https://www.instagram.com/gothamchess/\n➡️ GOTHAM DISCORD: https://discord.gg/f2ETqcWKdt\n\n➡️ THUMBNAILS BY: http://instagram.com/jojochessnoob",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/POVEOmjcZwI/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/POVEOmjcZwI/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/POVEOmjcZwI/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/POVEOmjcZwI/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/POVEOmjcZwI/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "GothamChess",
+ liveBroadcastContent: "none",
+ publishTime: "2022-03-12T16:26:55Z",
+ },
+ },
+];
+
+export const mainVideoDummyData = {
+ kind: "youtube#searchListResponse",
+ etag: "1vazrGuAkgvVhNTMfwBwL6L5G5s",
+ nextPageToken: "CAoQAA",
+ regionCode: "KR",
+ pageInfo: { totalResults: 1000000, resultsPerPage: 10 },
+ items: [
+ {
+ kind: "youtube#searchResult",
+ etag: "aaYFVnMFqN59SqbWTkiDt0b3_Z8",
+ id: { kind: "youtube#video", videoId: "z5qPOGI0tic" },
+ snippet: {
+ publishedAt: "2023-01-17T08:30:24Z",
+ channelId: "UC9idb-NIhZrI6wkPesc3MUg",
+ title:
+ "[#무한도전] 덕담... 이거 맞아? 차갑지만 따뜻해요 | 무한도전⏱오분순삭 MBC080209방송",
+ description:
+ "오분순삭 #무한도전 #설날 #덕담 *무한도전 다시 보기 ✓ WAVVE ...",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/z5qPOGI0tic/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/z5qPOGI0tic/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/z5qPOGI0tic/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "오분순삭",
+ liveBroadcastContent: "none",
+ publishTime: "2023-01-17T08:30:24Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "hxHQLAaK8O4yr4k1uwIWRJQEbKo",
+ id: { kind: "youtube#video", videoId: "ruiBdjdtWKk" },
+ snippet: {
+ publishedAt: "2022-01-27T13:32:30Z",
+ channelId: "UCVA204vbrA11sV5ujqY_58Q",
+ title: "충격!!...진짜귀여운동그란고양이실존!!!...",
+ description: "",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/ruiBdjdtWKk/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/ruiBdjdtWKk/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/ruiBdjdtWKk/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "동글동글이",
+ liveBroadcastContent: "none",
+ publishTime: "2022-01-27T13:32:30Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "S5M5uBEJoCmDW0cvVFsqlOmBIZA",
+ id: { kind: "youtube#video", videoId: "5j5NtAnYjI8" },
+ snippet: {
+ publishedAt: "2022-11-12T10:33:24Z",
+ channelId: "UC78PMQprrZTbU0IlMDsYZPw",
+ title:
+ "이동진의 올해 두 번째 별 다섯 영화★ 완벽한 연출의 다중 우주를 담은 [에브리씽 에브리웨어 올 앳 원스] #홍진경의영화로운덕후생활 EP.68",
+ description:
+ "티빙에서 스트리밍 : https://tving.onelink.me/xHqC/30a78d6f 제공 : (주)더쿱디스트리뷰션 #홍진경 #이동진 #영화 홍진경의 영화로운 ...",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/5j5NtAnYjI8/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/5j5NtAnYjI8/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/5j5NtAnYjI8/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "tvN",
+ liveBroadcastContent: "none",
+ publishTime: "2022-11-12T10:33:24Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "0v5C_krEAR-XeD06Ggndd5RpwpA",
+ id: { kind: "youtube#video", videoId: "v8ZrddIEomE" },
+ snippet: {
+ publishedAt: "2021-03-18T14:11:08Z",
+ channelId: "UCy5JONsnnZes6DeXju-zeXg",
+ title:
+ "신이 질투한 연주 '우리의 밤은 당신의 낮보다 아름답다' 우쿨렐레!",
+ description: "함 께~ 가는거야~~~",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/v8ZrddIEomE/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/v8ZrddIEomE/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/v8ZrddIEomE/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "좋은삶",
+ liveBroadcastContent: "none",
+ publishTime: "2021-03-18T14:11:08Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "xxBKUK-x4lG493-Pv3hbbvSdwRM",
+ id: { kind: "youtube#video", videoId: "SshvI-q99ac" },
+ snippet: {
+ publishedAt: "2022-09-10T23:32:37Z",
+ channelId: "UCJ3TDTqBmtmgcDrvBby5KRA",
+ title:
+ "10박11일 런던여행🇬🇧 EP1. 극찬한 Breakfast🥯, 파이브가이즈, 하이드파크 자전거타기, 버로우마켓🍑🌽🍩, 비스터빌리지",
+ description:
+ "즐거운 추석 연휴 보내세요 :) Music by Julia Pauletti - Cold & Bitter - https://thmatc.co/?l=36A83E09 Music by mj apanay - in ...",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/SshvI-q99ac/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/SshvI-q99ac/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/SshvI-q99ac/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "두리Duri",
+ liveBroadcastContent: "none",
+ publishTime: "2022-09-10T23:32:37Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "27WtMhJqNhoN78n46AI0LxRIAkE",
+ id: { kind: "youtube#video", videoId: "RnNhDf7VlUw" },
+ snippet: {
+ publishedAt: "2023-01-18T23:00:14Z",
+ channelId: "UC22go5LdQEw-iDuxFb4C0hw",
+ title:
+ "세뱃돈이 생각과 다르자 강아지가 보인 반응ㅋㅋㅋ ㅣ Dog’s Reaction To Small New Year’s Allowance LOL",
+ description:
+ "1대 오마이독 우승에 빛나는 강아지 '파티' 금쪽이 시절 반성하며 할무니께 세배를 해보았습니다. #집에서함께애니멀봐 #애니멀봐 ...",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/RnNhDf7VlUw/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/RnNhDf7VlUw/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/RnNhDf7VlUw/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "SBS TV동물농장x애니멀봐",
+ liveBroadcastContent: "none",
+ publishTime: "2023-01-18T23:00:14Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "qcrMGBDujlVEf2zd6TqT6GVssTc",
+ id: { kind: "youtube#video", videoId: "c97KcMwJZX4" },
+ snippet: {
+ publishedAt: "2022-06-18T13:00:30Z",
+ channelId: "UCsRIHt5FkbGc6cQtCxt-ufA",
+ title:
+ "[#갓구운클립] 열자마자 뛰어갔는데도 기다려야 하는 소문난 우동 맛집🍜 튀김이 기가 막혀~ | #줄서는식당",
+ description:
+ "갓구운클립 #줄서는식당 #tvN 구독하기 ☞ https://www.youtube.com/c/tvNDENT.",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/c97KcMwJZX4/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/c97KcMwJZX4/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/c97KcMwJZX4/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "tvN D ENT",
+ liveBroadcastContent: "none",
+ publishTime: "2022-06-18T13:00:30Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "F7BMl-LghKUNECVaN1SKAKEXe4o",
+ id: { kind: "youtube#video", videoId: "e3ASuXL7hsM" },
+ snippet: {
+ publishedAt: "2022-09-10T08:00:14Z",
+ channelId: "UCAhKKbDO9-ymWZ_7iAFLBQQ",
+ title:
+ "🌕추석특집🌕 아기 응도 또 울어?! 강아지들 때문에 눈물 마를 날 없는 돌아온 응도 2시간 모아보기 1탄 | EP 1~11 | KBS 주주클럽 2002 방송",
+ description:
+ "연휴동안 귀여운 응도 보면서 힐링하세요..(○'◡'○)♡ ♥ ※ 회차 정보 : 주주클럽 ❤️타임라인❤️ 00:00 돌아온 응도! 그리고 뉴 ...",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/e3ASuXL7hsM/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/e3ASuXL7hsM/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/e3ASuXL7hsM/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "KBS동물티비 : 애니멀포유 animal4u",
+ liveBroadcastContent: "none",
+ publishTime: "2022-09-10T08:00:14Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "Yo3D8L_pw6MkjfZC1J5IK2Mj9Ug",
+ id: { kind: "youtube#video", videoId: "4Uy_KMydIlg" },
+ snippet: {
+ publishedAt: "2020-02-26T09:30:09Z",
+ channelId: "UC-CnwTZJ_A5v-AQK92fNYKw",
+ title:
+ "sub)정말 맛있는 4가지 샌드위치 레시피 l 주방에서 행복해지는 나의 방법 첫번째 이야기",
+ description:
+ "맛있고 건강한 라이프스타일 주제로 영상을 종종 올려 볼게요. 이번 주제는 샌드위치! 맛있는 치즈 한장만 있어도 충분히 맛있는 ...",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/4Uy_KMydIlg/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/4Uy_KMydIlg/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/4Uy_KMydIlg/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "maji마지",
+ liveBroadcastContent: "none",
+ publishTime: "2020-02-26T09:30:09Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "9Uw7fIhh6TkBnTM_MEwnJZuhHgk",
+ id: { kind: "youtube#video", videoId: "0bnFoRQebq0" },
+ snippet: {
+ publishedAt: "2020-09-14T08:45:12Z",
+ channelId: "UCyn-K7rZLXjGl7VXGweIlcA",
+ title: "집에서 '크림 파스타' 쯤이야",
+ description:
+ "백종원 #크림파스타 #파스타만들기 집에서도 쉽게 만들 수 있는 '크림파스타'를 가져왔습니다. 생각보다 만드는 방법은 아주 간단 ...",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/0bnFoRQebq0/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/0bnFoRQebq0/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/0bnFoRQebq0/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "백종원 PAIK JONG WON",
+ liveBroadcastContent: "none",
+ publishTime: "2020-09-14T08:45:12Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "Pxj2dtTMnwN1nhNicxkaP01jwn4",
+ id: { kind: "youtube#video", videoId: "UUOpe_sTKzA" },
+ snippet: {
+ publishedAt: "2022-11-12T01:00:10Z",
+ channelId: "UC3m0s5XAQydCtbLHc8j1Uog",
+ title:
+ "[#편스토랑] 평균 조리시간 단 10분! 어남선생표 ‘원팬 파스타’ 레시피 모음집💝 | KBS 방송",
+ description:
+ "편스토랑] 평균 조리시간 단 10분! 어남선생표 '원팬 파스타' 레시피 모음집 | KBS 방송 00:00 1탄 우유버터파스타 04:28 2탄 토마토 ...",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/UUOpe_sTKzA/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/UUOpe_sTKzA/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/UUOpe_sTKzA/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "KBS 한국방송",
+ liveBroadcastContent: "none",
+ publishTime: "2022-11-12T01:00:10Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "bIktCCEvOS_oCMLuPSS7sacYpUs",
+ id: { kind: "youtube#video", videoId: "JIfforrUjV8" },
+ snippet: {
+ publishedAt: "2022-04-02T09:00:06Z",
+ channelId: "UCG5bAssl2H0wjLG4BEv5ScQ",
+ title:
+ "[파스타/Pasta] EP16-2 | 세영(이하늬) VS 유경(공효진)🥊 다짜고짜 인삼 파스타를 만들어 달라는 노신사! 그의 정체는?! MBC100223방송",
+ description:
+ "[파스타] EP16-2. 한 신사(정동환)가 라스페라에 찾아와 인삼 파스타를 예약하고 돌아가고, 유경은 현욱의 레시피 노트에서 인삼 ...",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/JIfforrUjV8/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/JIfforrUjV8/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/JIfforrUjV8/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "옛드 : MBC 레전드 드라마",
+ liveBroadcastContent: "none",
+ publishTime: "2022-04-02T09:00:06Z",
+ },
+ },
+ ],
+};
+
+export const mainVideoDetailDummyData = [
+ {
+ kind: "youtube#videoListResponse",
+ etag: "qeX2yX3Uko7u3aYTB_mvVC3mmC4",
+ items: [
+ {
+ kind: "youtube#video",
+ etag: "dRMoLkbJM2Fsma24JSANCTciPr8",
+ id: "z5qPOGI0tic",
+ snippet: {
+ publishedAt: "2023-01-17T08:30:24Z",
+ channelId: "UC9idb-NIhZrI6wkPesc3MUg",
+ title:
+ "[#무한도전] 덕담... 이거 맞아? 차갑지만 따뜻해요 | 무한도전⏱오분순삭 MBC080209방송",
+ description:
+ "#오분순삭 #무한도전 #설날 #덕담\n\n*무한도전 다시 보기 \n\n✔ WAVVE : \nhttps://www.wavve.com/player/vod?programid=M_T72108G&page=1\n✔ iMBC : \nhttp://playvod.imbc.com/Vod/VodPlay?broadcastId=1000786100000100000\n✔ 카카오페이지\n(2006년~2015년) : https://page.kakao.com/home?seriesId=52717733\n(2015년~2018년) : https://page.kakao.com/home?seriesId=51222860\n✔ 네이버시리즈 \n(pc) : https://series.naver.com/broadcasting/detail.nhn?productNo=442717\n(moblie) : https://series.naver.com/broadcasting/detail.nhn?productNo=515199\n✔ 왓챠플레이 : https://play.watcha.net/search?q=%EB%AC%B4%ED%95%9C%EB%8F%84%EC%A0%84 \n✔ 곰TV : http://www.gomtv.com/622537",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/z5qPOGI0tic/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/z5qPOGI0tic/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/z5qPOGI0tic/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/z5qPOGI0tic/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/z5qPOGI0tic/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "오분순삭",
+ tags: [
+ "무한도전",
+ "무도 레전드",
+ "무도",
+ "정준하",
+ "정형돈",
+ "유재석",
+ "박명수",
+ "노홍철",
+ "하하",
+ "융드옥정",
+ "새해",
+ "설날",
+ "덕담",
+ "오분순삭",
+ "하하엄마",
+ "떡국",
+ "새해 맞이",
+ "설맞이",
+ "응원전",
+ "취준생",
+ "취업",
+ "공시생",
+ "응원",
+ "악담",
+ ],
+ categoryId: "24",
+ liveBroadcastContent: "none",
+ localized: {
+ title:
+ "[#무한도전] 덕담... 이거 맞아? 차갑지만 따뜻해요 | 무한도전⏱오분순삭 MBC080209방송",
+ description:
+ "#오분순삭 #무한도전 #설날 #덕담\n\n*무한도전 다시 보기 \n\n✔ WAVVE : \nhttps://www.wavve.com/player/vod?programid=M_T72108G&page=1\n✔ iMBC : \nhttp://playvod.imbc.com/Vod/VodPlay?broadcastId=1000786100000100000\n✔ 카카오페이지\n(2006년~2015년) : https://page.kakao.com/home?seriesId=52717733\n(2015년~2018년) : https://page.kakao.com/home?seriesId=51222860\n✔ 네이버시리즈 \n(pc) : https://series.naver.com/broadcasting/detail.nhn?productNo=442717\n(moblie) : https://series.naver.com/broadcasting/detail.nhn?productNo=515199\n✔ 왓챠플레이 : https://play.watcha.net/search?q=%EB%AC%B4%ED%95%9C%EB%8F%84%EC%A0%84 \n✔ 곰TV : http://www.gomtv.com/622537",
+ },
+ defaultAudioLanguage: "ko",
+ },
+ contentDetails: {
+ duration: "PT6M57S",
+ dimension: "2d",
+ definition: "hd",
+ caption: "false",
+ licensedContent: true,
+ contentRating: {},
+ projection: "rectangular",
+ },
+ statistics: {
+ viewCount: "145228",
+ likeCount: "1485",
+ favoriteCount: "0",
+ commentCount: "83",
+ },
+ player: {
+ embedHtml:
+ '',
+ },
+ },
+ ],
+ pageInfo: { totalResults: 1, resultsPerPage: 1 },
+ },
+ {
+ kind: "youtube#videoListResponse",
+ etag: "FXXnasAR5WqWMEUTLF9ZCqXhKR0",
+ items: [
+ {
+ kind: "youtube#video",
+ etag: "ioAsYGSQerXicDB2WRUS26kOKng",
+ id: "ruiBdjdtWKk",
+ snippet: {
+ publishedAt: "2022-01-27T13:32:30Z",
+ channelId: "UCVA204vbrA11sV5ujqY_58Q",
+ title: "충격!!...진짜귀여운동그란고양이실존!!!...",
+ description: "",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/ruiBdjdtWKk/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/ruiBdjdtWKk/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/ruiBdjdtWKk/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/ruiBdjdtWKk/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/ruiBdjdtWKk/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "동글동글이",
+ tags: [
+ "고양이",
+ "반려동물",
+ "동물",
+ "cat",
+ "강아지",
+ "브이로그",
+ "vlog",
+ "동글이",
+ "동글동글이",
+ "동그란고양이",
+ "귀여운 영상",
+ "dog",
+ ],
+ categoryId: "15",
+ liveBroadcastContent: "none",
+ localized: {
+ title: "충격!!...진짜귀여운동그란고양이실존!!!...",
+ description: "",
+ },
+ },
+ contentDetails: {
+ duration: "PT11M28S",
+ dimension: "2d",
+ definition: "hd",
+ caption: "false",
+ licensedContent: true,
+ contentRating: {},
+ projection: "rectangular",
+ },
+ statistics: {
+ viewCount: "2042855",
+ favoriteCount: "0",
+ commentCount: "3424",
+ },
+ player: {
+ embedHtml:
+ '',
+ },
+ },
+ ],
+ pageInfo: { totalResults: 1, resultsPerPage: 1 },
+ },
+ {
+ kind: "youtube#videoListResponse",
+ etag: "L0Vsydcr7f6T1JgUJ1-Dn30IzRY",
+ items: [
+ {
+ kind: "youtube#video",
+ etag: "Jzh4ji6Lj5xBJDs9mqY6vZ3SYmE",
+ id: "5j5NtAnYjI8",
+ snippet: {
+ publishedAt: "2022-11-12T10:33:24Z",
+ channelId: "UC78PMQprrZTbU0IlMDsYZPw",
+ title:
+ "이동진의 올해 두 번째 별 다섯 영화★ 완벽한 연출의 다중 우주를 담은 [에브리씽 에브리웨어 올 앳 원스] #홍진경의영화로운덕후생활 EP.68",
+ description:
+ "티빙에서 스트리밍 : https://tving.onelink.me/xHqC/30a78d6f\n\n제공 : (주)더쿱디스트리뷰션\n\n#홍진경 #이동진 #영화\n홍진경의 영화로운 덕후생활 The Ultimate Guide for Movie Junkies EP.68\n\n홍진경이 뇌에 다이렉트로 넣어주는 색다른 콘텐츠 추천 예능\n\n이토록 우아한 영화 가이드\n<홍진경의 영화로운 덕후생활>\n\n[금] 저녁 7:30 tvN 방송\n\n#티빙에서스트리밍",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/5j5NtAnYjI8/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/5j5NtAnYjI8/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/5j5NtAnYjI8/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/5j5NtAnYjI8/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/5j5NtAnYjI8/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "tvN",
+ tags: [
+ "드라마",
+ "송진우",
+ "양자경",
+ "에브리씽에브리웨어올앳원스",
+ "에에올",
+ "영화",
+ "유병재",
+ "이동진",
+ "콘텐츠 리뷰",
+ "티빙에서스트리밍",
+ "홍진경",
+ "홍진경의 영화로운 덕후생활",
+ ],
+ categoryId: "24",
+ liveBroadcastContent: "none",
+ defaultLanguage: "ko",
+ localized: {
+ title:
+ "이동진의 올해 두 번째 별 다섯 영화★ 완벽한 연출의 다중 우주를 담은 [에브리씽 에브리웨어 올 앳 원스] #홍진경의영화로운덕후생활 EP.68",
+ description:
+ "티빙에서 스트리밍 : https://tving.onelink.me/xHqC/30a78d6f\n\n제공 : (주)더쿱디스트리뷰션\n\n#홍진경 #이동진 #영화\n홍진경의 영화로운 덕후생활 The Ultimate Guide for Movie Junkies EP.68\n\n홍진경이 뇌에 다이렉트로 넣어주는 색다른 콘텐츠 추천 예능\n\n이토록 우아한 영화 가이드\n<홍진경의 영화로운 덕후생활>\n\n[금] 저녁 7:30 tvN 방송\n\n#티빙에서스트리밍",
+ },
+ defaultAudioLanguage: "ko",
+ },
+ contentDetails: {
+ duration: "PT17M56S",
+ dimension: "2d",
+ definition: "hd",
+ caption: "false",
+ licensedContent: true,
+ contentRating: {},
+ projection: "rectangular",
+ },
+ statistics: {
+ viewCount: "140027",
+ likeCount: "1627",
+ favoriteCount: "0",
+ commentCount: "199",
+ },
+ player: {
+ embedHtml:
+ '',
+ },
+ },
+ ],
+ pageInfo: { totalResults: 1, resultsPerPage: 1 },
+ },
+ {
+ kind: "youtube#videoListResponse",
+ etag: "QiYA_RPujj3aeZei8GzW76YfQm4",
+ items: [
+ {
+ kind: "youtube#video",
+ etag: "9-CenQRoNo5yJ3C_sQKuAitfRHs",
+ id: "v8ZrddIEomE",
+ snippet: {
+ publishedAt: "2021-03-18T14:11:08Z",
+ channelId: "UCy5JONsnnZes6DeXju-zeXg",
+ title:
+ "신이 질투한 연주 '우리의 밤은 당신의 낮보다 아름답다' 우쿨렐레!",
+ description: "함 께~ 가는거야~~~",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/v8ZrddIEomE/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/v8ZrddIEomE/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/v8ZrddIEomE/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/v8ZrddIEomE/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ },
+ channelTitle: "좋은삶",
+ categoryId: "22",
+ liveBroadcastContent: "none",
+ localized: {
+ title:
+ "신이 질투한 연주 '우리의 밤은 당신의 낮보다 아름답다' 우쿨렐레!",
+ description: "함 께~ 가는거야~~~",
+ },
+ },
+ contentDetails: {
+ duration: "PT1M12S",
+ dimension: "2d",
+ definition: "sd",
+ caption: "false",
+ licensedContent: false,
+ contentRating: {},
+ projection: "rectangular",
+ },
+ statistics: {
+ viewCount: "83",
+ likeCount: "5",
+ favoriteCount: "0",
+ commentCount: "2",
+ },
+ player: {
+ embedHtml:
+ '',
+ },
+ },
+ ],
+ pageInfo: { totalResults: 1, resultsPerPage: 1 },
+ },
+ {
+ kind: "youtube#videoListResponse",
+ etag: "4Y7BEqyPJfO8qegM88gDLyannxw",
+ items: [
+ {
+ kind: "youtube#video",
+ etag: "an_wqsCWodzzAxH6yQOub94UJqc",
+ id: "SshvI-q99ac",
+ snippet: {
+ publishedAt: "2022-09-10T23:32:37Z",
+ channelId: "UCJ3TDTqBmtmgcDrvBby5KRA",
+ title:
+ "10박11일 런던여행🇬🇧 EP1. 극찬한 Breakfast🥯, 파이브가이즈, 하이드파크 자전거타기, 버로우마켓🍑🌽🍩, 비스터빌리지",
+ description:
+ "즐거운 추석 연휴 보내세요 :)\n\nMusic by Julia Pauletti - Cold & Bitter - https://thmatc.co/?l=36A83E09\nMusic by mj apanay - in another life - https://thmatc.co/?l=16B82A27\n\n#런던여행 #유럽여행 #여행브이로그",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/SshvI-q99ac/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/SshvI-q99ac/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/SshvI-q99ac/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/SshvI-q99ac/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/SshvI-q99ac/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "두리Duri",
+ categoryId: "22",
+ liveBroadcastContent: "none",
+ localized: {
+ title:
+ "10박11일 런던여행🇬🇧 EP1. 극찬한 Breakfast🥯, 파이브가이즈, 하이드파크 자전거타기, 버로우마켓🍑🌽🍩, 비스터빌리지",
+ description:
+ "즐거운 추석 연휴 보내세요 :)\n\nMusic by Julia Pauletti - Cold & Bitter - https://thmatc.co/?l=36A83E09\nMusic by mj apanay - in another life - https://thmatc.co/?l=16B82A27\n\n#런던여행 #유럽여행 #여행브이로그",
+ },
+ },
+ contentDetails: {
+ duration: "PT22M34S",
+ dimension: "2d",
+ definition: "hd",
+ caption: "false",
+ licensedContent: true,
+ contentRating: {},
+ projection: "rectangular",
+ },
+ statistics: {
+ viewCount: "20840",
+ likeCount: "274",
+ favoriteCount: "0",
+ commentCount: "43",
+ },
+ player: {
+ embedHtml:
+ '',
+ },
+ },
+ ],
+ pageInfo: { totalResults: 1, resultsPerPage: 1 },
+ },
+ {
+ kind: "youtube#videoListResponse",
+ etag: "6059cZB9-c03wwWYsNKQ4QTXTDs",
+ items: [
+ {
+ kind: "youtube#video",
+ etag: "zgF0x4sBtJt6VtF2M14ILE9kPyg",
+ id: "RnNhDf7VlUw",
+ snippet: {
+ publishedAt: "2023-01-18T23:00:14Z",
+ channelId: "UC22go5LdQEw-iDuxFb4C0hw",
+ title:
+ "세뱃돈이 생각과 다르자 강아지가 보인 반응ㅋㅋㅋ ㅣ Dog’s Reaction To Small New Year’s Allowance LOL",
+ description:
+ "1대 오마이독 우승에 빛나는 강아지 '파티'\n금쪽이 시절 반성하며 할무니께 세배를 해보았습니다.\n\n#집에서함께애니멀봐 #애니멀봐강아지 #귀여운강아지\n-------------------------------------------------\n애니멀봐와 한배타고⛵\n☞ https://goo.gl/WL9mGy\n\n애니멀봐 강아지 더 보기🐶\n☞ https://youtu.be/vDtmZPhFMMQ\n\n아님 다른 동물 더 보고나서🐯\n☞ https://youtu.be/5DE_E6S7ARk\n\n[애니멀봐]와 베프되기\n 페이스북: https://www.facebook.com/sbstvanimal\n 인스타그램: https://www.instagram.com/sbsanimal\n 트위터: https://twitter.com/sbsyang",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/RnNhDf7VlUw/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/RnNhDf7VlUw/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/RnNhDf7VlUw/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "SBS TV동물농장x애니멀봐",
+ tags: [
+ "애니멀봐",
+ "동물농장",
+ "TV동물농장",
+ "동물농장 애니멀봐",
+ "애니멀봐 동물농장",
+ "sbs animal eng sub",
+ "sbs animal show",
+ "animals",
+ "animal farm",
+ "tv animal farm",
+ "동물영상",
+ "재미있는 동물영상",
+ "sbs animal farm 2023",
+ "강아지",
+ "강아지 설날",
+ "강아지 설날 음식",
+ "새해복많이받으세요",
+ "happy new year 2023",
+ "설연휴",
+ "강아지 먹방",
+ "강아지 음식",
+ "강아지 유튜브",
+ "강아지 세배",
+ "강아지 세뱃돈",
+ "강아지 영상",
+ ],
+ categoryId: "15",
+ liveBroadcastContent: "none",
+ defaultLanguage: "ko",
+ localized: {
+ title:
+ "세뱃돈이 생각과 다르자 강아지가 보인 반응ㅋㅋㅋ ㅣ Dog’s Reaction To Small New Year’s Allowance LOL",
+ description:
+ "1대 오마이독 우승에 빛나는 강아지 '파티'\n금쪽이 시절 반성하며 할무니께 세배를 해보았습니다.\n\n#집에서함께애니멀봐 #애니멀봐강아지 #귀여운강아지\n-------------------------------------------------\n애니멀봐와 한배타고⛵\n☞ https://goo.gl/WL9mGy\n\n애니멀봐 강아지 더 보기🐶\n☞ https://youtu.be/vDtmZPhFMMQ\n\n아님 다른 동물 더 보고나서🐯\n☞ https://youtu.be/5DE_E6S7ARk\n\n[애니멀봐]와 베프되기\n 페이스북: https://www.facebook.com/sbstvanimal\n 인스타그램: https://www.instagram.com/sbsanimal\n 트위터: https://twitter.com/sbsyang",
+ },
+ defaultAudioLanguage: "ko",
+ },
+ contentDetails: {
+ duration: "PT4M53S",
+ dimension: "2d",
+ definition: "hd",
+ caption: "true",
+ licensedContent: true,
+ contentRating: {},
+ projection: "rectangular",
+ },
+ statistics: {
+ viewCount: "73192",
+ likeCount: "1909",
+ favoriteCount: "0",
+ commentCount: "87",
+ },
+ player: {
+ embedHtml:
+ '',
+ },
+ },
+ ],
+ pageInfo: { totalResults: 1, resultsPerPage: 1 },
+ },
+ {
+ kind: "youtube#videoListResponse",
+ etag: "pzZD-1KjVZUM2QkmVHPr9JQGCKE",
+ items: [
+ {
+ kind: "youtube#video",
+ etag: "hIOYVliP94DjyQxQjCzwSFmTi7c",
+ id: "c97KcMwJZX4",
+ snippet: {
+ publishedAt: "2022-06-18T13:00:30Z",
+ channelId: "UCsRIHt5FkbGc6cQtCxt-ufA",
+ title:
+ "[#갓구운클립] 열자마자 뛰어갔는데도 기다려야 하는 소문난 우동 맛집🍜 튀김이 기가 막혀~ | #줄서는식당",
+ description:
+ "#갓구운클립 #줄서는식당 #tvN\n\n구독하기 ☞ https://www.youtube.com/c/tvNDENT",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/c97KcMwJZX4/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/c97KcMwJZX4/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/c97KcMwJZX4/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/c97KcMwJZX4/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/c97KcMwJZX4/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "tvN D ENT",
+ tags: [
+ "tvN",
+ "tvN D ENT",
+ "갓구운클립",
+ "갓클립",
+ "김태현 미자",
+ "나래 먹방",
+ "나래 절친",
+ "나래바",
+ "냉우동 먹방",
+ "먹방",
+ "미자",
+ "미자 결혼",
+ "미자 먹방",
+ "미자 언니",
+ "박나래",
+ "박나래 나래바",
+ "박나래 먹방",
+ "박나래 절친",
+ "배우 장광",
+ "연희동",
+ "우동 먹방",
+ "웨이팅맛집",
+ "입짧은햇님",
+ "입짧은햇님 맛집",
+ "입짧은햇님 먹방",
+ "장광",
+ "줄서는 식당 다시보기",
+ "줄서는 식당 하이라이트",
+ "줄서는식당",
+ "줄서는식당 21",
+ "줄서는식당 21회",
+ "줄서는식당 21회 다시보기",
+ "튀김우동 먹방",
+ "티비엔",
+ "햇님",
+ "햇님 냉우동",
+ "햇님 냉우동 먹방",
+ "햇님 맛집",
+ "햇님 먹방",
+ "햇님 우동",
+ "햇님 우동 먹방",
+ "햇님 튀김우동",
+ ],
+ categoryId: "24",
+ liveBroadcastContent: "none",
+ defaultLanguage: "ko",
+ localized: {
+ title:
+ "[#갓구운클립] 열자마자 뛰어갔는데도 기다려야 하는 소문난 우동 맛집🍜 튀김이 기가 막혀~ | #줄서는식당",
+ description:
+ "#갓구운클립 #줄서는식당 #tvN\n\n구독하기 ☞ https://www.youtube.com/c/tvNDENT",
+ },
+ defaultAudioLanguage: "ko",
+ },
+ contentDetails: {
+ duration: "PT10M12S",
+ dimension: "2d",
+ definition: "hd",
+ caption: "false",
+ licensedContent: true,
+ contentRating: {},
+ projection: "rectangular",
+ },
+ statistics: {
+ viewCount: "35865",
+ likeCount: "256",
+ favoriteCount: "0",
+ commentCount: "13",
+ },
+ player: {
+ embedHtml:
+ '',
+ },
+ },
+ ],
+ pageInfo: { totalResults: 1, resultsPerPage: 1 },
+ },
+ {
+ kind: "youtube#videoListResponse",
+ etag: "MeGhc8MXxad-DXUaBBobOaw8mkM",
+ items: [
+ {
+ kind: "youtube#video",
+ etag: "RaB_C6ne17oTawz-ua3mZKQkC3M",
+ id: "e3ASuXL7hsM",
+ snippet: {
+ publishedAt: "2022-09-10T08:00:14Z",
+ channelId: "UCAhKKbDO9-ymWZ_7iAFLBQQ",
+ title:
+ "🌕추석특집🌕 아기 응도 또 울어?! 강아지들 때문에 눈물 마를 날 없는 돌아온 응도 2시간 모아보기 1탄 | EP 1~11 | KBS 주주클럽 2002 방송",
+ description:
+ "연휴동안 귀여운 응도 보면서 힐링하세요..(●'◡'●)♡ ♥\n\n\n※ 회차 정보 : 주주클럽\n\n❤️타임라인❤️\n00:00 돌아온 응도! 그리고 뉴페이스 두리?\n13:08 응도 울리는게 제일 쉬운 말썽꾸러기 두리!\n19:30 응도 원픽 강아지 갑작스러운 병원행??\n31:54 갑자기 응도 껌딱지가 된 강아지 슈!\n43:24 안본사이 많이 변해버린 가둥이\n56:18 강아지들 괴롭힘에 못이겨 개집으로 들어간 응도 ㅋㅋ\n01:07:55 응도집에 놀러온 고슴도치!\n01:18:13 가둥이가 낳은 새끼가 무려 11마리?!\n01:31:08 응도 집앞을 떠돌던 새끼 강아지 한 마리\n01:44:34 졸면서도 새끼 강아지들을 챙기는 응도!\n01:57:10 응도 손을 거쳐간 새끼 강아지만 수십마리?!\n\n\n#애니멀포유 #주주클럽 #응도 #돌아온응도 #강아지 #반려견 #반려동물 #두리 #가둥이 #개 #덤보",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/e3ASuXL7hsM/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/e3ASuXL7hsM/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/e3ASuXL7hsM/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/e3ASuXL7hsM/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/e3ASuXL7hsM/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "KBS동물티비 : 애니멀포유 animal4u",
+ tags: [
+ "애니멀포유",
+ "animal4u",
+ "kbs동물",
+ "동물채널",
+ "강아지",
+ "고양이",
+ "사자",
+ "백호",
+ "늑대",
+ "dog",
+ "cat",
+ "개는 훌륭하다",
+ "개훌륭",
+ "강형욱",
+ "개는 훌륭하다 강형욱",
+ "aggressive dog",
+ "개훌륭 역대급",
+ "주주클럽",
+ "스펀지",
+ "단짝",
+ "동물다큐",
+ "야생동물",
+ "동물 다큐멘터리",
+ "골든 레트리버",
+ "포메라니안",
+ "보더콜리",
+ "사파리",
+ "애니멀봐",
+ "댕댕이",
+ "동물",
+ "귀여움",
+ "kbs",
+ "무한리필샐러드",
+ "추천",
+ "멧돼지",
+ "멧돼지할아버지",
+ "악어",
+ "멧돼지아저씨",
+ "애니멀포유멧돼지",
+ "신기",
+ "오랑이",
+ "오랑우탄",
+ "보라",
+ "위기탈출넘버원",
+ "위탈넘",
+ "햄스터",
+ "동물실험",
+ ],
+ categoryId: "15",
+ liveBroadcastContent: "none",
+ defaultLanguage: "en",
+ localized: {
+ title:
+ "🌕추석특집🌕 아기 응도 또 울어?! 강아지들 때문에 눈물 마를 날 없는 돌아온 응도 2시간 모아보기 1탄 | EP 1~11 | KBS 주주클럽 2002 방송",
+ description:
+ "연휴동안 귀여운 응도 보면서 힐링하세요..(●'◡'●)♡ ♥\n\n\n※ 회차 정보 : 주주클럽\n\n❤️타임라인❤️\n00:00 돌아온 응도! 그리고 뉴페이스 두리?\n13:08 응도 울리는게 제일 쉬운 말썽꾸러기 두리!\n19:30 응도 원픽 강아지 갑작스러운 병원행??\n31:54 갑자기 응도 껌딱지가 된 강아지 슈!\n43:24 안본사이 많이 변해버린 가둥이\n56:18 강아지들 괴롭힘에 못이겨 개집으로 들어간 응도 ㅋㅋ\n01:07:55 응도집에 놀러온 고슴도치!\n01:18:13 가둥이가 낳은 새끼가 무려 11마리?!\n01:31:08 응도 집앞을 떠돌던 새끼 강아지 한 마리\n01:44:34 졸면서도 새끼 강아지들을 챙기는 응도!\n01:57:10 응도 손을 거쳐간 새끼 강아지만 수십마리?!\n\n\n#애니멀포유 #주주클럽 #응도 #돌아온응도 #강아지 #반려견 #반려동물 #두리 #가둥이 #개 #덤보",
+ },
+ defaultAudioLanguage: "ko",
+ },
+ contentDetails: {
+ duration: "PT2H9M3S",
+ dimension: "2d",
+ definition: "hd",
+ caption: "false",
+ licensedContent: true,
+ contentRating: {},
+ projection: "rectangular",
+ },
+ statistics: {
+ viewCount: "291502",
+ likeCount: "3908",
+ favoriteCount: "0",
+ commentCount: "161",
+ },
+ player: {
+ embedHtml:
+ '',
+ },
+ },
+ ],
+ pageInfo: { totalResults: 1, resultsPerPage: 1 },
+ },
+ {
+ kind: "youtube#videoListResponse",
+ etag: "D9GS8VFmgLIykUIKmZ3s3y8RqAw",
+ items: [
+ {
+ kind: "youtube#video",
+ etag: "6oLa9eKqsOPODdW5RH8x0UPsl58",
+ id: "4Uy_KMydIlg",
+ snippet: {
+ publishedAt: "2020-02-26T09:30:09Z",
+ channelId: "UC-CnwTZJ_A5v-AQK92fNYKw",
+ title:
+ "sub)정말 맛있는 4가지 샌드위치 레시피 l 주방에서 행복해지는 나의 방법 첫번째 이야기",
+ description:
+ "맛있고 건강한 라이프스타일 주제로 영상을 종종 올려 볼게요.\n이번 주제는 샌드위치!\n맛있는 치즈 한장만 있어도 충분히 맛있는 샌드위치를 만들 수 있어요.\n좋아하는 샌드위치 레시피를 공유해요.\n\nFAQ\n발음이 왜 그런가요? : 제가 혀가 짧아서 발음이 부정확합니다. \n폰트 정보 : 헤움 디자인\n\n*영상과 상관없는 댓글이나 발음과 관련된 댓글은 삭제합니다.\n\n\n#maji 마지 \n\ninstagram :https://www.instagram.com/momurmaji\nemail : kirakira83@naver.com",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/4Uy_KMydIlg/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/4Uy_KMydIlg/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/4Uy_KMydIlg/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/4Uy_KMydIlg/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ },
+ channelTitle: "maji마지",
+ tags: [
+ "마지 브이로그",
+ "살림 브이로그",
+ "샌드위치 레시피",
+ "샌드위치 만들기",
+ "샌드위치",
+ "파니니",
+ "파니니 레시피",
+ "클럽 샌드위치",
+ "집밥",
+ "연어베이글",
+ "치즈 파니니",
+ "브리치즈 샌드위치",
+ "sandwich",
+ "bagel sandwich",
+ "panini",
+ ],
+ categoryId: "22",
+ liveBroadcastContent: "none",
+ defaultLanguage: "ko",
+ localized: {
+ title:
+ "sub)정말 맛있는 4가지 샌드위치 레시피 l 주방에서 행복해지는 나의 방법 첫번째 이야기",
+ description:
+ "맛있고 건강한 라이프스타일 주제로 영상을 종종 올려 볼게요.\n이번 주제는 샌드위치!\n맛있는 치즈 한장만 있어도 충분히 맛있는 샌드위치를 만들 수 있어요.\n좋아하는 샌드위치 레시피를 공유해요.\n\nFAQ\n발음이 왜 그런가요? : 제가 혀가 짧아서 발음이 부정확합니다. \n폰트 정보 : 헤움 디자인\n\n*영상과 상관없는 댓글이나 발음과 관련된 댓글은 삭제합니다.\n\n\n#maji 마지 \n\ninstagram :https://www.instagram.com/momurmaji\nemail : kirakira83@naver.com",
+ },
+ defaultAudioLanguage: "en",
+ },
+ contentDetails: {
+ duration: "PT10M25S",
+ dimension: "2d",
+ definition: "hd",
+ caption: "true",
+ licensedContent: true,
+ contentRating: {},
+ projection: "rectangular",
+ },
+ statistics: {
+ viewCount: "2012750",
+ likeCount: "55302",
+ favoriteCount: "0",
+ commentCount: "706",
+ },
+ player: {
+ embedHtml:
+ '',
+ },
+ },
+ ],
+ pageInfo: { totalResults: 1, resultsPerPage: 1 },
+ },
+ {
+ kind: "youtube#videoListResponse",
+ etag: "oGKKL2pR5ToSyTxsDLGKJNW3sDk",
+ items: [
+ {
+ kind: "youtube#video",
+ etag: "Coa_Vj_I92Nscto-lcJS69bvuPA",
+ id: "0bnFoRQebq0",
+ snippet: {
+ publishedAt: "2020-09-14T08:45:12Z",
+ channelId: "UCyn-K7rZLXjGl7VXGweIlcA",
+ title: "집에서 '크림 파스타'쯤이야",
+ description:
+ "#백종원 #크림파스타 #파스타만들기\n집에서도 쉽게 만들 수 있는 '크림파스타'를 가져왔습니다.\n생각보다 만드는 방법은 아주 간단합니다\n나중에 다른 재료들도 함께 넣어 응용해서 드세요~\n\n=======================\n\n베이컨 크림 파스타\n\n[재료]\n\n*면 삶기\n\n정수물 8과1/3컵(1.5L) \n스파게티면 90g\n꽃소금 1큰술(12g)\n올리브유 약간\n\n*베이컨크림파스타\n\n베이컨 2줄(32g)\n양파 1/2개(125g)\n양송이 버섯 1과 1/2개(30g)\n밀가루 1/2큰술(5g)\n우유 1팩(200ml)\n버터 약1큰술(15g)\n올리브유 2큰술(14g)\n파르메산 치즈 2큰술(16g)\n꽃소금 1/6큰술(2g)\n삶은스파게티면 전량\n후춧가루 적당량\n파슬리가루 적당량\n\n\n[만드는 법]\n\n*면 삶기\n\n1. 냄비에 정수물, 꽃소금, 올리브유를 넣고 스파게티면 삶을 물을 끓인다.\n2. 물이 끓어오르면 면을 돌려서 펼쳐 넣고 붙지않도록 저어주면서 약 6분 정도 삶아 준비한다.\nTip: 크림파스타 농도 조절을 위해 면수는 버리지 않고 따로 보관해둔다. \n3. 삶아진 스파게티면은 체에 밭쳐 건져낸다.\n\n*베이컨크림파스타\n\n1. 베이컨은 두께 1cm 정도로 자르고, 양파는 가로, 세로 0.5cm 정도로 다져 준비한다.\n2. 양송이 한 개는 가로,세로 0.5cm 정도로 다지고, 반 개는 두께 0.5cm로 편 썰어 준비한다.\nTip: 슬라이스 4조각 정도만 보이게 편 썰어서 넣어준다.\n3. 프라이팬에 베이컨, 다진양파, 다진 양송이 버섯, 올리브유를 넣고 중 불에 볶는다. \n4. 양파가 노릇해 질 때까지 충분히 볶는다.\n5. 양파에 색이 나면 버터를 넣어 볶고, 버터가 녹으면 우유, 편 썰은 양송이 버섯, 스파게티 면을 넣어 졸인다.\n6. 밀가루를 넣고 잘 풀어 주어 농도 조절을 한다.\n7. 불을 약 불로 줄인 후 꽃소금으로 간을 한다.\nTip: 소스 농도가 너무 되직하면 면수를 추가한다.\n8. 불을 끄고 파르메산 치즈를 골고루 뿌려 섞는다.\n9. 후춧가루를 뿌려준 후 접시에 담고 파슬리 가루를 뿌려 완성한다.\nTip: 기호에 따라 우유를 추가해 소스를 더 만들어 사용한다.\n\n\nBacon cream pasta\n\n[Ingredients]\n\n*Cooking noodles\n\n8&1/3 cups (1.5L) purified water\n90g spaghetti noodles\n1 tbsp (12g) fine salt\nOlive oil\n\n*Bacon cream pasta\n\n2 strips (32g) bacon\n1/2 (125g) onion\n1&1/2 (30g) button mushroom\n1/2 tbsp (5g) flour\n1 pack (200ml) milk\n1 tbsp (15g) butter\n2 tbsp (14g) olive oil\n2 tbsp (16g) Parmesan cheese\n1/6 tbsp (2g) fine salt\nCooked spaghetti noodles\nBlack pepper\nParsley\n\n\n[Directions]\n\n*Cooking pasta noodles\n\n1. Add purified water, fine salt, and olive oil to a pot and bring to boil.\n2. When water starts boiling, put in pasta noodles and cook for 6 minutes. Stir occasionally.\nTip: Set aside the pasta water to adjust the consistency of your creamy pasta. \n3. Drain the pasta noodles.\n\n*Bacon cream pasta\n\n1. Cut bacon 1cm thick and diced onion into 0.5cm big pieces.\n2. Dice one button mushroom into 0.5cm big pieces, and cut the half of a button mushroom into 0.5cm thick slices.\nTip: Make four slices of button mushroom.\n3. Add the bacon, diced onion, diced button mushroom, and olive oil into a pan and stir-fry. \n4. Stir-fry thoroughly until the onion becomes golden.\n5. Once the onion has goldened, add butter. When the butter has melted, add milk, sliced button mushroom, and cooked spaghetti noodles.\n6. Add flour and stir well to adjust the consistency.\n7. Reduce to low heat and season with fine salt.\nTip: Add pasta water if the sauce is too thick.\n8. Turn off the heat and add Parmesan cheese.\n9. Sprinkle black pepper, plate, and finish with a little bit of parsley.\nTip: Add more milk to make more sauce if desired.\n\n\n한식을 사랑하는 외국인분들을 위해 외국어 자막을 첨부하였습니다.\n본 영상의 자막은 통합 언어 플랫폼 ‘플리토’와 함께 합니다.\nSubtitles in foreign languages are provided for everyone who loves Korean food.\nAll subtitles are provided by an integrated language platform, Flitto.\nhttps://www.flitto.com/business/video-translation",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/0bnFoRQebq0/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/0bnFoRQebq0/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/0bnFoRQebq0/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/0bnFoRQebq0/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/0bnFoRQebq0/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "백종원 PAIK JONG WON",
+ tags: [
+ "백종원",
+ "파스타",
+ "백종원 파스타",
+ "크림파스타",
+ "cream pasta",
+ "pasta",
+ "스파게티",
+ "우유 파스타",
+ "집밥",
+ "요리비책",
+ "집밥백선생",
+ "간단요리",
+ "요리",
+ "베이컨파스타",
+ "bacon",
+ "cream",
+ ],
+ categoryId: "22",
+ liveBroadcastContent: "none",
+ defaultLanguage: "ko",
+ localized: {
+ title: "집에서 '크림 파스타'쯤이야",
+ description:
+ "#백종원 #크림파스타 #파스타만들기\n집에서도 쉽게 만들 수 있는 '크림파스타'를 가져왔습니다.\n생각보다 만드는 방법은 아주 간단합니다\n나중에 다른 재료들도 함께 넣어 응용해서 드세요~\n\n=======================\n\n베이컨 크림 파스타\n\n[재료]\n\n*면 삶기\n\n정수물 8과1/3컵(1.5L) \n스파게티면 90g\n꽃소금 1큰술(12g)\n올리브유 약간\n\n*베이컨크림파스타\n\n베이컨 2줄(32g)\n양파 1/2개(125g)\n양송이 버섯 1과 1/2개(30g)\n밀가루 1/2큰술(5g)\n우유 1팩(200ml)\n버터 약1큰술(15g)\n올리브유 2큰술(14g)\n파르메산 치즈 2큰술(16g)\n꽃소금 1/6큰술(2g)\n삶은스파게티면 전량\n후춧가루 적당량\n파슬리가루 적당량\n\n\n[만드는 법]\n\n*면 삶기\n\n1. 냄비에 정수물, 꽃소금, 올리브유를 넣고 스파게티면 삶을 물을 끓인다.\n2. 물이 끓어오르면 면을 돌려서 펼쳐 넣고 붙지않도록 저어주면서 약 6분 정도 삶아 준비한다.\nTip: 크림파스타 농도 조절을 위해 면수는 버리지 않고 따로 보관해둔다. \n3. 삶아진 스파게티면은 체에 밭쳐 건져낸다.\n\n*베이컨크림파스타\n\n1. 베이컨은 두께 1cm 정도로 자르고, 양파는 가로, 세로 0.5cm 정도로 다져 준비한다.\n2. 양송이 한 개는 가로,세로 0.5cm 정도로 다지고, 반 개는 두께 0.5cm로 편 썰어 준비한다.\nTip: 슬라이스 4조각 정도만 보이게 편 썰어서 넣어준다.\n3. 프라이팬에 베이컨, 다진양파, 다진 양송이 버섯, 올리브유를 넣고 중 불에 볶는다. \n4. 양파가 노릇해 질 때까지 충분히 볶는다.\n5. 양파에 색이 나면 버터를 넣어 볶고, 버터가 녹으면 우유, 편 썰은 양송이 버섯, 스파게티 면을 넣어 졸인다.\n6. 밀가루를 넣고 잘 풀어 주어 농도 조절을 한다.\n7. 불을 약 불로 줄인 후 꽃소금으로 간을 한다.\nTip: 소스 농도가 너무 되직하면 면수를 추가한다.\n8. 불을 끄고 파르메산 치즈를 골고루 뿌려 섞는다.\n9. 후춧가루를 뿌려준 후 접시에 담고 파슬리 가루를 뿌려 완성한다.\nTip: 기호에 따라 우유를 추가해 소스를 더 만들어 사용한다.\n\n\nBacon cream pasta\n\n[Ingredients]\n\n*Cooking noodles\n\n8&1/3 cups (1.5L) purified water\n90g spaghetti noodles\n1 tbsp (12g) fine salt\nOlive oil\n\n*Bacon cream pasta\n\n2 strips (32g) bacon\n1/2 (125g) onion\n1&1/2 (30g) button mushroom\n1/2 tbsp (5g) flour\n1 pack (200ml) milk\n1 tbsp (15g) butter\n2 tbsp (14g) olive oil\n2 tbsp (16g) Parmesan cheese\n1/6 tbsp (2g) fine salt\nCooked spaghetti noodles\nBlack pepper\nParsley\n\n\n[Directions]\n\n*Cooking pasta noodles\n\n1. Add purified water, fine salt, and olive oil to a pot and bring to boil.\n2. When water starts boiling, put in pasta noodles and cook for 6 minutes. Stir occasionally.\nTip: Set aside the pasta water to adjust the consistency of your creamy pasta. \n3. Drain the pasta noodles.\n\n*Bacon cream pasta\n\n1. Cut bacon 1cm thick and diced onion into 0.5cm big pieces.\n2. Dice one button mushroom into 0.5cm big pieces, and cut the half of a button mushroom into 0.5cm thick slices.\nTip: Make four slices of button mushroom.\n3. Add the bacon, diced onion, diced button mushroom, and olive oil into a pan and stir-fry. \n4. Stir-fry thoroughly until the onion becomes golden.\n5. Once the onion has goldened, add butter. When the butter has melted, add milk, sliced button mushroom, and cooked spaghetti noodles.\n6. Add flour and stir well to adjust the consistency.\n7. Reduce to low heat and season with fine salt.\nTip: Add pasta water if the sauce is too thick.\n8. Turn off the heat and add Parmesan cheese.\n9. Sprinkle black pepper, plate, and finish with a little bit of parsley.\nTip: Add more milk to make more sauce if desired.\n\n\n한식을 사랑하는 외국인분들을 위해 외국어 자막을 첨부하였습니다.\n본 영상의 자막은 통합 언어 플랫폼 ‘플리토’와 함께 합니다.\nSubtitles in foreign languages are provided for everyone who loves Korean food.\nAll subtitles are provided by an integrated language platform, Flitto.\nhttps://www.flitto.com/business/video-translation",
+ },
+ defaultAudioLanguage: "ko",
+ },
+ contentDetails: {
+ duration: "PT11M51S",
+ dimension: "2d",
+ definition: "hd",
+ caption: "true",
+ licensedContent: true,
+ contentRating: {},
+ projection: "rectangular",
+ },
+ statistics: {
+ viewCount: "5154541",
+ likeCount: "56854",
+ favoriteCount: "0",
+ commentCount: "2412",
+ },
+ player: {
+ embedHtml:
+ '',
+ },
+ },
+ ],
+ pageInfo: { totalResults: 1, resultsPerPage: 1 },
+ },
+ {
+ kind: "youtube#videoListResponse",
+ etag: "lza19ccqDuwlhV98RNsQWDGHvkg",
+ items: [
+ {
+ kind: "youtube#video",
+ etag: "l-mKZsAUH1AEI6yOidE_e9_sPWg",
+ id: "UUOpe_sTKzA",
+ snippet: {
+ publishedAt: "2022-11-12T01:00:10Z",
+ channelId: "UC3m0s5XAQydCtbLHc8j1Uog",
+ title:
+ "[#편스토랑] 평균 조리시간 단 10분! 어남선생표 ‘원팬 파스타’ 레시피 모음집💝 | KBS 방송",
+ description:
+ "[#편스토랑] 평균 조리시간 단 10분! 어남선생표 ‘원팬 파스타’ 레시피 모음집💝 | KBS 방송\n\n00:00 1탄 우유버터파스타\n04:28 2탄 토마토버터파스타\n09:13 3탄 알리오올리오\n13:26 4탄 카르보나라\n16:07 5탄 명란버터파스타\n20:53 6탄 후추치즈파스타\n\n#편스토랑 #신상출시편스토랑 #편스토랑 #붐 #김보민 #류수영 #이연복 #이찬원 #박수홍 #어남선생 #원팬파스타 #모음집 #우유버터파스타 #토마토버터파스타 #알리오올리오 #카르보나라 #명란버터파스타 #후추치즈파스타 #레시피 #파스타 #홈쿡 #주부 #요리 #먹방 #KBS",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/UUOpe_sTKzA/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/UUOpe_sTKzA/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/UUOpe_sTKzA/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/UUOpe_sTKzA/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/UUOpe_sTKzA/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "KBS 한국방송",
+ tags: ["KBS", "한국방송공사", "mylovekbs", "예고", "티저"],
+ categoryId: "24",
+ liveBroadcastContent: "none",
+ localized: {
+ title:
+ "[#편스토랑] 평균 조리시간 단 10분! 어남선생표 ‘원팬 파스타’ 레시피 모음집💝 | KBS 방송",
+ description:
+ "[#편스토랑] 평균 조리시간 단 10분! 어남선생표 ‘원팬 파스타’ 레시피 모음집💝 | KBS 방송\n\n00:00 1탄 우유버터파스타\n04:28 2탄 토마토버터파스타\n09:13 3탄 알리오올리오\n13:26 4탄 카르보나라\n16:07 5탄 명란버터파스타\n20:53 6탄 후추치즈파스타\n\n#편스토랑 #신상출시편스토랑 #편스토랑 #붐 #김보민 #류수영 #이연복 #이찬원 #박수홍 #어남선생 #원팬파스타 #모음집 #우유버터파스타 #토마토버터파스타 #알리오올리오 #카르보나라 #명란버터파스타 #후추치즈파스타 #레시피 #파스타 #홈쿡 #주부 #요리 #먹방 #KBS",
+ },
+ defaultAudioLanguage: "ko",
+ },
+ contentDetails: {
+ duration: "PT26M47S",
+ dimension: "2d",
+ definition: "hd",
+ caption: "false",
+ licensedContent: true,
+ contentRating: {},
+ projection: "rectangular",
+ },
+ statistics: {
+ viewCount: "637277",
+ likeCount: "14067",
+ favoriteCount: "0",
+ commentCount: "256",
+ },
+ player: {
+ embedHtml:
+ '',
+ },
+ },
+ ],
+ pageInfo: { totalResults: 1, resultsPerPage: 1 },
+ },
+ {
+ kind: "youtube#videoListResponse",
+ etag: "qhnN1qETYjZvIpyH11pv4aEVrqE",
+ items: [
+ {
+ kind: "youtube#video",
+ etag: "c-m3SuqvxcQ5t12xyVxceyJqSVw",
+ id: "JIfforrUjV8",
+ snippet: {
+ publishedAt: "2022-04-02T09:00:06Z",
+ channelId: "UCG5bAssl2H0wjLG4BEv5ScQ",
+ title:
+ "[파스타/Pasta] EP16-2 | 세영(이하늬) VS 유경(공효진)🥊 다짜고짜 인삼 파스타를 만들어 달라는 노신사! 그의 정체는?! MBC100223방송",
+ description:
+ "[파스타] \nEP16-2. 한 신사(정동환)가 라스페라에 찾아와 인삼 파스타를 예약하고 돌아가고, 유경은 현욱의 레시피 노트에서 인삼 파스타를 발견하고 현욱에게 전화한다. 석호(이형철)는 동료들에게 뉴쉐프대회 심사위원이 된 세영(이하늬)에게 도는 안 좋은 소문에 대해 전한다. 유경은 혼자 연습해보다 자신만의 비법을 찾게 되고, 유경의 인삼 파스타를 맛 본 현욱의 얼굴색이 달라진다.\n\n출연진: 공효진, 이선균, 이하늬, 알렉스, 이성민, 이형철, 노민우\n\n*<파스타> 풀버전 보러가기\n✔ WAVVE : https://www.wavve.com/player/vod?programid=M_T60109G&page=1\n✔ iMBC : https://program.imbc.com/pasta\n\n#옛드 #파스타 #pasta #겨울드라마 #요리드라마 #이선균 #공효진",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/JIfforrUjV8/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/JIfforrUjV8/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/JIfforrUjV8/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/JIfforrUjV8/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/JIfforrUjV8/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "옛드 : MBC 레전드 드라마",
+ tags: [
+ "옛드",
+ "옛날드라마",
+ "MBC드라마",
+ "MBC",
+ "MBC DRAMA",
+ "MBC drama",
+ "kdrama",
+ "레전드 드라마",
+ "파스타",
+ "셰프",
+ "겨울",
+ "겨울 드라마",
+ "로코추천",
+ "공효진",
+ "이선균",
+ "알리오 올리오",
+ "쿡방",
+ "먹방",
+ "크림 파스타",
+ "로제 파스타",
+ "맛집",
+ "라스페라",
+ "샘킴",
+ "이하늬",
+ "알렉스",
+ "pasta",
+ "love story",
+ "배달",
+ "파스타 배달",
+ "파스타 요리",
+ "라따뚜이",
+ "이태리",
+ "대환장",
+ "파티",
+ "콘테스트",
+ "로맨틱코미디",
+ "로코",
+ "겨울 로코",
+ "설렘",
+ "신경쓰이는 재질",
+ "뽀뽀",
+ ],
+ categoryId: "24",
+ liveBroadcastContent: "none",
+ localized: {
+ title:
+ "[파스타/Pasta] EP16-2 | 세영(이하늬) VS 유경(공효진)🥊 다짜고짜 인삼 파스타를 만들어 달라는 노신사! 그의 정체는?! MBC100223방송",
+ description:
+ "[파스타] \nEP16-2. 한 신사(정동환)가 라스페라에 찾아와 인삼 파스타를 예약하고 돌아가고, 유경은 현욱의 레시피 노트에서 인삼 파스타를 발견하고 현욱에게 전화한다. 석호(이형철)는 동료들에게 뉴쉐프대회 심사위원이 된 세영(이하늬)에게 도는 안 좋은 소문에 대해 전한다. 유경은 혼자 연습해보다 자신만의 비법을 찾게 되고, 유경의 인삼 파스타를 맛 본 현욱의 얼굴색이 달라진다.\n\n출연진: 공효진, 이선균, 이하늬, 알렉스, 이성민, 이형철, 노민우\n\n*<파스타> 풀버전 보러가기\n✔ WAVVE : https://www.wavve.com/player/vod?programid=M_T60109G&page=1\n✔ iMBC : https://program.imbc.com/pasta\n\n#옛드 #파스타 #pasta #겨울드라마 #요리드라마 #이선균 #공효진",
+ },
+ defaultAudioLanguage: "ko",
+ },
+ contentDetails: {
+ duration: "PT22M51S",
+ dimension: "2d",
+ definition: "hd",
+ caption: "false",
+ licensedContent: true,
+ regionRestriction: {
+ blocked: [
+ "AU",
+ "HK",
+ "ID",
+ "JP",
+ "MO",
+ "MY",
+ "NZ",
+ "PH",
+ "SG",
+ "TH",
+ "VN",
+ ],
+ },
+ contentRating: {},
+ projection: "rectangular",
+ },
+ statistics: {
+ viewCount: "41242",
+ likeCount: "278",
+ favoriteCount: "0",
+ commentCount: "32",
+ },
+ player: {
+ embedHtml:
+ '',
+ },
+ },
+ ],
+ pageInfo: { totalResults: 1, resultsPerPage: 1 },
+ },
+];
+
+export const searchVideoDummyData = [
+ {
+ kind: "youtube#searchResult",
+ etag: "nGP6BfI2SvkpbU1q7Wi0UHdVMAI",
+ id: {
+ kind: "youtube#video",
+ videoId: "zTcR0A9vPR4",
+ },
+ snippet: {
+ publishedAt: "2023-01-17T10:00:37Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title: "나 진짜 안 먹어도 된다니까?",
+ description:
+ "문쌤 #졸업식 #쿠티크에센셜짜장 이 영상은 삼양식품 쿠티크의 지원을 받아 제작되었습니다. 아니 쌤이 일부러 안 준게 아니라 어쩔 ...",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/zTcR0A9vPR4/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/zTcR0A9vPR4/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/zTcR0A9vPR4/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ liveBroadcastContent: "none",
+ publishTime: "2023-01-17T10:00:37Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "KZy881dHZA38QDVTjejs5cearpk",
+ id: {
+ kind: "youtube#video",
+ videoId: "b4jT8K-rOvc",
+ },
+ snippet: {
+ publishedAt: "2023-01-10T10:10:27Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title: "F는 이래서 안돼",
+ description: "문쌤 #MBTI #TF 쌤 MBTI 뭐게 Instagram @bdnspresents.",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/b4jT8K-rOvc/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/b4jT8K-rOvc/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/b4jT8K-rOvc/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ liveBroadcastContent: "none",
+ publishTime: "2023-01-10T10:10:27Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "mMZvd4KUMkKlvxnXpqYslAe2pSM",
+ id: {
+ kind: "youtube#video",
+ videoId: "idbT_FywEro",
+ },
+ snippet: {
+ publishedAt: "2023-01-15T04:00:11Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title:
+ "[복학생 vlog] 걸어다니는 중소기업 청년 사업가 브이로그 (퇴사, 성공스토리, 20대 건물주, 자기개발, 스마트스토어 입점, 무자본 창업, 프랜차이즈 환영, 자영업자 현실)",
+ description:
+ "복학생 #창업 #entrepreneur 더 많은 숙취해소 젤리 출시정보는 인스타그램을 통해 확인해주세요! Instagram @bdnspresents.",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/idbT_FywEro/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/idbT_FywEro/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/idbT_FywEro/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ liveBroadcastContent: "none",
+ publishTime: "2023-01-15T04:00:11Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "Sw6nbELRELTtQ8GVU7HuiSvPSM0",
+ id: {
+ kind: "youtube#video",
+ videoId: "sgFgfjF1e-8",
+ },
+ snippet: {
+ publishedAt: "2022-11-20T04:00:15Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title:
+ "[복학생 vlog] 속세 떠나 절간에서 공부하는 브이로그(주지스님 속마음 인터뷰, 절밥 먹방, 셀프 삭발 리뷰, 묵언 수행, 취뽀 108배, 달마야 놀자 결말, 순공 100시간)",
+ description:
+ "템플스테이 #복학생 #studywithme 장소협조 - 인천 강화군 전등사 Instagram @bdnspresents.",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/sgFgfjF1e-8/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/sgFgfjF1e-8/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/sgFgfjF1e-8/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ liveBroadcastContent: "none",
+ publishTime: "2022-11-20T04:00:15Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "g0H_0kV4pG1GgAnMEdudZSipPjs",
+ id: {
+ kind: "youtube#video",
+ videoId: "5sdB5272H_o",
+ },
+ snippet: {
+ publishedAt: "2022-12-08T10:04:31Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title: "얘들아 지각 좀 하지 말아주세요 제발",
+ description: "문쌤 #일진 #참교육 Instagram @bdnspresents.",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/5sdB5272H_o/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/5sdB5272H_o/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/5sdB5272H_o/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ liveBroadcastContent: "none",
+ publishTime: "2022-12-08T10:04:31Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "OX50zSY87k3AXyrz-eBdlHz0mAg",
+ id: {
+ kind: "youtube#video",
+ videoId: "2pi-PKzkwtA",
+ },
+ snippet: {
+ publishedAt: "2023-01-03T10:00:02Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title: "축구부면 수업 안 들어와도 되시나요?",
+ description:
+ "문쌤 #조규성 축구부도 학생이다 이 말이야 Instagram @bdnspresents.",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/2pi-PKzkwtA/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/2pi-PKzkwtA/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/2pi-PKzkwtA/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ liveBroadcastContent: "none",
+ publishTime: "2023-01-03T10:00:02Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "rPG-GGxmee_ThsiAzAxPgPnqT8k",
+ id: {
+ kind: "youtube#video",
+ videoId: "EqsCBihHLeU",
+ },
+ snippet: {
+ publishedAt: "2022-11-14T10:00:07Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title: "수업을 왜 그렇게 하세요?",
+ description: "문쌤 #수능응원 #일타강사 Instagram @bdnspresents.",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/EqsCBihHLeU/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/EqsCBihHLeU/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/EqsCBihHLeU/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ liveBroadcastContent: "none",
+ publishTime: "2022-11-14T10:00:07Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "ZMXtAww2LKWKvZhZ8t8KTLeQrOU",
+ id: {
+ kind: "youtube#video",
+ videoId: "AHoz1iihgLU",
+ },
+ snippet: {
+ publishedAt: "2023-01-01T04:00:03Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title:
+ "[복학생 vlog] 1월 1일 해돋이 여행 브이로그 (커플 펜션 추천, 다이어트, 첫키스, 새해 복 받아가세요, 강원도 정동진, 작심삼일 토익 공부법, 야간 산행 꿀팁)",
+ description:
+ "복학생 #커플여행 #시원스쿨랩 이 영상은 시원스쿨랩의 지원을 받아 제작되었습니다. 빠둥이 여러분과 이 자리에서 약속합니다,,, ...",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/AHoz1iihgLU/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/AHoz1iihgLU/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/AHoz1iihgLU/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ liveBroadcastContent: "none",
+ publishTime: "2023-01-01T04:00:03Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "oKhrYPsVL3qTOe4a-sTHTqEUQIQ",
+ id: {
+ kind: "youtube#video",
+ videoId: "035lAtnA96U",
+ },
+ snippet: {
+ publishedAt: "2022-09-10T03:49:57Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title: "그때 그 시절 홈비디오 몰아보기",
+ description:
+ "명절 내내 홈비디오와 함께 행복한 한가위 보내세요~! 00:00 [홈비디오] 유튜브 3개월 쉬다 돌아왔는데 작업실이 생겨버렸네 01:55 [홈 ...",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/035lAtnA96U/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/035lAtnA96U/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/035lAtnA96U/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ liveBroadcastContent: "none",
+ publishTime: "2022-09-10T03:49:57Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "lnp4aRcs5_TM1MV5KaTGKj9_WLo",
+ id: {
+ kind: "youtube#video",
+ videoId: "Lb1UMS-n-rY",
+ },
+ snippet: {
+ publishedAt: "2019-11-11T09:00:06Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title: "[ENG][문쌤] 수업 중 에어드랍 테러 그만해! 내가 돼지라는 소리야?",
+ description:
+ "기프티콘은 더 보내줘도 돼 ㅎㅎ 대신 안 쓴 것 Instagram @moonbdns Facebook / seoul.bdns.",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/Lb1UMS-n-rY/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/Lb1UMS-n-rY/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/Lb1UMS-n-rY/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ liveBroadcastContent: "none",
+ publishTime: "2019-11-11T09:00:06Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "y28ziEtKXg9s0ThwnlEVrrEYLbY",
+ id: {
+ kind: "youtube#video",
+ videoId: "rcZDzL7rMTM",
+ },
+ snippet: {
+ publishedAt: "2020-01-17T09:00:15Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title: "[문쌤] 에어드랍 꺼놨더니 또 이런 짓을 해? 문제 테러 당한 문쌤",
+ description:
+ "이 영상은 콴다의 유료광고를 포함하고 있습니다. THIS IS COMMERCIAL Instagram @moonbdns Facebook / seoul.bdns.",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/rcZDzL7rMTM/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/rcZDzL7rMTM/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/rcZDzL7rMTM/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ liveBroadcastContent: "none",
+ publishTime: "2020-01-17T09:00:15Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "2GuFgDSJo7t17brKcVThNIQEEp0",
+ id: {
+ kind: "youtube#video",
+ videoId: "30E9m3tWKzg",
+ },
+ snippet: {
+ publishedAt: "2022-09-28T10:00:03Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title: "제발 자리에 앉아라",
+ description:
+ "이 영상은 SKT ZEM의 지원을 받아 제작되었습니다. 우리 아이들 스마트폰 쓰기 시작하는 나이부터는 완전 새로운 세계로 내던져진 ...",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/30E9m3tWKzg/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/30E9m3tWKzg/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/30E9m3tWKzg/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ liveBroadcastContent: "none",
+ publishTime: "2022-09-28T10:00:03Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "c8SKEGl_KH6QntV3migf9LdeNeY",
+ id: {
+ kind: "youtube#video",
+ videoId: "oter9p3wqBE",
+ },
+ snippet: {
+ publishedAt: "2021-11-17T08:30:06Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title: "[문쌤] "쌤 몇 년 차세요?" 수업 중 대노한 군기반장 문쌤",
+ description: "문쌤 #수능응원 #동기부여 Instagram @bdnspresents.",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/oter9p3wqBE/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/oter9p3wqBE/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/oter9p3wqBE/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ liveBroadcastContent: "none",
+ publishTime: "2021-11-17T08:30:06Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "tCMeyk-pqCYn-Metn9oMFTsWiMQ",
+ id: {
+ kind: "youtube#video",
+ videoId: "475dCgzjNyE",
+ },
+ snippet: {
+ publishedAt: "2022-12-27T10:00:04Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title: "너 내가 1분에 얼마 버는지 알아?",
+ description: "문쌤 #일타강사 Instagram @bdnspresents.",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/475dCgzjNyE/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/475dCgzjNyE/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/475dCgzjNyE/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ liveBroadcastContent: "none",
+ publishTime: "2022-12-27T10:00:04Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "8Xr0XhXIoNRCjIkMDkpSJDTHuFs",
+ id: {
+ kind: "youtube#video",
+ videoId: "VmFFlK03WHc",
+ },
+ snippet: {
+ publishedAt: "2022-01-14T10:00:14Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title: "[문쌤] 실감나는 6.25전쟁 6분 요약",
+ description:
+ "문쌤 #625전쟁 #625전쟁요약 문쌤 강의의 풀버전은 리더스 사탐 홈페이지에서 확인할 수 있습니다. Instagram @bdnspresents.",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/VmFFlK03WHc/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/VmFFlK03WHc/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/VmFFlK03WHc/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ liveBroadcastContent: "none",
+ publishTime: "2022-01-14T10:00:14Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "2f7u7l4bQ7emRZmYyZfF1PRt_So",
+ id: {
+ kind: "youtube#video",
+ videoId: "CMYPJ1LLGGA",
+ },
+ snippet: {
+ publishedAt: "2022-12-20T08:12:41Z",
+ channelId: "UCma37fJBlF718VRgGlx4yGA",
+ title: "[메가스터디] 수능 지리, 이름만 들어도 지리는 문쌤",
+ description:
+ "2023년 수능 지리의 문이 열린다 자신 있게 말씀 드립니다. 최소 5등급! 이름만 들어도 지리는 문쌤 드디어 메가스터디에 COMING ...",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/CMYPJ1LLGGA/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/CMYPJ1LLGGA/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/CMYPJ1LLGGA/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "theMEGASTUDY",
+ liveBroadcastContent: "none",
+ publishTime: "2022-12-20T08:12:41Z",
+ },
+ },
+ {
+ kind: "youtube#searchResult",
+ etag: "YekBPSIOAEgSZopqZRZZ7K28kIo",
+ id: {
+ kind: "youtube#video",
+ videoId: "ADg08ZmrJ-Q",
+ },
+ snippet: {
+ publishedAt: "2021-12-29T10:00:09Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title: "[문쌤] 실감나는 2차세계대전 6분 요약",
+ description:
+ "문쌤 #2차세계대전 #2세계대전요약 문쌤 강의의 풀버전은 리더스 사탐 홈페이지에서 확인할 수 있습니다. Instagram ...",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/ADg08ZmrJ-Q/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/ADg08ZmrJ-Q/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/ADg08ZmrJ-Q/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ liveBroadcastContent: "none",
+ publishTime: "2021-12-29T10:00:09Z",
+ },
+ },
+];
+
+export const searchVideoDetailDummyData = {
+ kind: "youtube#videoListResponse",
+ etag: "nXMDwqw66U_g2O_i6IVUX6dehJc",
+ items: [
+ {
+ kind: "youtube#video",
+ etag: "Hc2Q9K7euFx5217qPuZp_RwdROA",
+ id: "5sdB5272H_o",
+ snippet: {
+ publishedAt: "2022-12-08T10:04:31Z",
+ channelId: "UC5xLohcPE65Y-U62X6snmRQ",
+ title: "얘들아 지각 좀 하지 말아주세요 제발",
+ description: "#문쌤 #일진 #참교육\n\n\n\nInstagram @bdnspresents",
+ thumbnails: {
+ default: {
+ url: "https://i.ytimg.com/vi/5sdB5272H_o/default.jpg",
+ width: 120,
+ height: 90,
+ },
+ medium: {
+ url: "https://i.ytimg.com/vi/5sdB5272H_o/mqdefault.jpg",
+ width: 320,
+ height: 180,
+ },
+ high: {
+ url: "https://i.ytimg.com/vi/5sdB5272H_o/hqdefault.jpg",
+ width: 480,
+ height: 360,
+ },
+ standard: {
+ url: "https://i.ytimg.com/vi/5sdB5272H_o/sddefault.jpg",
+ width: 640,
+ height: 480,
+ },
+ maxres: {
+ url: "https://i.ytimg.com/vi/5sdB5272H_o/maxresdefault.jpg",
+ width: 1280,
+ height: 720,
+ },
+ },
+ channelTitle: "빠더너스 BDNS",
+ tags: [
+ "comedy",
+ "코미디",
+ "코메디",
+ "스케치코미디",
+ "웃긴영상",
+ "문상훈",
+ "꽁트",
+ "레전드",
+ "문쌤",
+ "문상훈 문쌤",
+ "문상훈 인터뷰",
+ "문상훈 강사",
+ "문상훈 인강",
+ "문상훈 강의",
+ "문상훈 한국지리",
+ "문쌤 한국지리",
+ "한국지리 문쌤 강의",
+ "한국지리 문쌤 에어드랍",
+ "문쌤 에어드랍 돼지",
+ "문쌤 인강",
+ "빠더너스 문쌤 물",
+ "문쌤 에어드랍",
+ "문쌤 이기상",
+ "문쌤 최희준",
+ "문쌤 레전드",
+ "문쌤 강의",
+ "문쌤 공부하기 싫을때",
+ "문쌤 놀리기",
+ "일타강사",
+ "문쌤 현강",
+ "문쌤 현강반응",
+ "문쌤 직캠",
+ "일타강사 문쌤",
+ "문쌤 이지영",
+ "문쌤 정승제",
+ "한국지리 일타강사",
+ "한국지리 인강",
+ "한지 인강",
+ "한국지리",
+ "모의고사 한국지리",
+ "수능 한국지리",
+ "신승호",
+ "dp",
+ "d.p.",
+ "약한영웅",
+ "군대",
+ "선임으로 만나면",
+ "황장수",
+ "김루리",
+ "연시은",
+ "박지훈",
+ "환혼",
+ "에이틴",
+ "환혼 세자",
+ "일진 참교육",
+ "일진",
+ "인강",
+ "특강",
+ "수업",
+ ],
+ categoryId: "23",
+ liveBroadcastContent: "none",
+ localized: {
+ title: "얘들아 지각 좀 하지 말아주세요 제발",
+ description: "#문쌤 #일진 #참교육\n\n\n\nInstagram @bdnspresents",
+ },
+ defaultAudioLanguage: "ko",
+ },
+ contentDetails: {
+ duration: "PT6M19S",
+ dimension: "2d",
+ definition: "hd",
+ caption: "false",
+ licensedContent: true,
+ contentRating: {},
+ projection: "rectangular",
+ },
+ statistics: {
+ viewCount: "2620114",
+ likeCount: "47751",
+ favoriteCount: "0",
+ commentCount: "2374",
+ },
+ player: {
+ embedHtml:
+ '',
+ },
+ },
+ ],
+ pageInfo: {
+ totalResults: 1,
+ resultsPerPage: 1,
+ },
+};
+
+export const searchVideoChannelDummyData = {
+ kind: "youtube#channelListResponse",
+ etag: "1a45RuSZjwbxQgUUYPCUlT0u3bA",
+ pageInfo: {
+ totalResults: 1,
+ resultsPerPage: 5,
+ },
+ items: [
+ {
+ kind: "youtube#channel",
+ etag: "ie0BsZdzCpWvgViehuoxd2pPSqQ",
+ id: "UC5xLohcPE65Y-U62X6snmRQ",
+ snippet: {
+ title: "빠더너스 BDNS",
+ description:
+ "하이퍼 리얼리즘의 콩트와 코미디 영상을 만듭니다\n웰메이드 코미디를 지향합니다 \n콜라보, 비즈니스 문의는 문상훈을 춤추게 합니다\n\nInstagram : @bdnspresents @bdnsstudio\n비즈니스 문의 : seoul.bdns@gmail.com\n공식 홈페이지 : bdns.co.kr\n\n\nTHIS IS COMEDY!\nBDNS Presents\n\n",
+ customUrl: "@bdns",
+ publishedAt: "2016-05-31T03:31:12Z",
+ thumbnails: {
+ default: {
+ url: "https://yt3.ggpht.com/ytc/AMLnZu8Ia8DsIhh46F6WWu1xhktgEfbSZgSo8y-02K9dmQ=s88-c-k-c0x00ffffff-no-rj",
+ width: 88,
+ height: 88,
+ },
+ medium: {
+ url: "https://yt3.ggpht.com/ytc/AMLnZu8Ia8DsIhh46F6WWu1xhktgEfbSZgSo8y-02K9dmQ=s240-c-k-c0x00ffffff-no-rj",
+ width: 240,
+ height: 240,
+ },
+ high: {
+ url: "https://yt3.ggpht.com/ytc/AMLnZu8Ia8DsIhh46F6WWu1xhktgEfbSZgSo8y-02K9dmQ=s800-c-k-c0x00ffffff-no-rj",
+ width: 800,
+ height: 800,
+ },
+ },
+ localized: {
+ title: "빠더너스 BDNS",
+ description:
+ "하이퍼 리얼리즘의 콩트와 코미디 영상을 만듭니다\n웰메이드 코미디를 지향합니다 \n콜라보, 비즈니스 문의는 문상훈을 춤추게 합니다\n\nInstagram : @bdnspresents @bdnsstudio\n비즈니스 문의 : seoul.bdns@gmail.com\n공식 홈페이지 : bdns.co.kr\n\n\nTHIS IS COMEDY!\nBDNS Presents\n\n",
+ },
+ country: "KR",
+ },
+ contentDetails: {
+ relatedPlaylists: {
+ likes: "",
+ uploads: "UU5xLohcPE65Y-U62X6snmRQ",
+ },
+ },
+ statistics: {
+ viewCount: "360065413",
+ subscriberCount: "1080000",
+ hiddenSubscriberCount: false,
+ videoCount: "596",
+ },
+ },
+ ],
+};
diff --git a/src/global/globalStyles.ts b/src/global/globalStyles.ts
new file mode 100644
index 0000000..718c95f
--- /dev/null
+++ b/src/global/globalStyles.ts
@@ -0,0 +1,38 @@
+import { createGlobalStyle } from "styled-components";
+import reset from "styled-reset";
+
+const GlobalStyles = createGlobalStyle`
+${reset}
+
+ body {
+ font-family: 'Roboto', sans-serif;
+ background-color: #fff;
+ color: #0f0f0f
+ }
+
+ a {
+ text-decoration: none;
+ color: #0F0F0F;
+ }
+
+ @media (prefers-color-scheme: dark) {
+ body {
+ background-color: #0F0F0F;
+ color: #f1f1f1;
+ }
+
+ .mono {
+ fill: #f1f1f1
+ }
+
+ a {
+ color: #f1f1f1;
+ }
+
+ p {
+ color: #fff
+ }
+ }
+`;
+
+export default GlobalStyles;
diff --git a/src/main.tsx b/src/main.tsx
new file mode 100644
index 0000000..804c81a
--- /dev/null
+++ b/src/main.tsx
@@ -0,0 +1,11 @@
+import React from "react";
+import ReactDOM from "react-dom/client";
+import App from "./App";
+import GlobalStyles from "./global/globalStyles";
+
+ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
+ <>
+
+
+ >,
+);
diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx
new file mode 100644
index 0000000..b9f9648
--- /dev/null
+++ b/src/pages/Home/index.tsx
@@ -0,0 +1,58 @@
+import { instance } from "../../api/index";
+import { useEffect, useState } from "react";
+import styled from "styled-components";
+import MainCard from "../../components/home/MainCard";
+import { mainVideoDummyData } from "../../data/data";
+import { VideoSearchData } from "../../types/videoSearchTypes";
+import { getSearchData } from "../../api/api";
+
+const Home = ({ open }: { open: boolean }) => {
+ const [videoResult, setVideoResult] = useState(mainVideoDummyData);
+ const [isError, setIsError] = useState("");
+ const searchWord = "검색어";
+
+ useEffect(() => {
+ document.title = "YouTube";
+ }, []);
+
+ useEffect(() => {
+ getSearchData(searchWord, setVideoResult, setIsError);
+ }, [searchWord]);
+
+ // dummyData 로컬에 저장
+ localStorage.setItem(
+ "mainVideoDummyData",
+ JSON.stringify(mainVideoDummyData),
+ );
+
+ // dummyData 로컬에서 가져오기
+ const localData = JSON.parse(
+ localStorage.getItem("mainVideoDummyData") || "",
+ );
+
+ return (
+
+ {localData.items.map((item: VideoSearchData, i: number) => {
+ return ;
+ })}
+
+ );
+};
+
+const Container = styled.div<{ open: boolean }>`
+ width: ${(props) => (props.open ? "calc(100% - 240)" : "calc(100% - 72)")}px;
+ height: auto;
+ padding: 100px 33px 0 33px;
+ margin-left: ${(props) => (props.open ? "240" : "72")}px;
+ box-sizing: border-box;
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
+ @media (max-width: 1450px) {
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
+ }
+ @media (max-width: 1120px) {
+ grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
+ }
+`;
+
+export default Home;
diff --git a/src/pages/Search/index.tsx b/src/pages/Search/index.tsx
new file mode 100644
index 0000000..cd26084
--- /dev/null
+++ b/src/pages/Search/index.tsx
@@ -0,0 +1,86 @@
+import { useEffect, useState } from "react";
+import { useLocation } from "react-router-dom";
+import { searchVideoDummyData } from "../../data/data";
+import styled from "styled-components";
+import SearchCard from "../../components/search/SearchCard";
+import { getSearchData } from "../../api/api";
+import type { VideoSearchData } from "../../types/videoSearchTypes";
+
+const Search = ({ open }: { open: boolean }) => {
+ const [result, setResult] = useState(searchVideoDummyData);
+ const [isError, setIsError] = useState("");
+ const useQuery = () => {
+ return new URLSearchParams(useLocation().search);
+ };
+ const query = useQuery();
+ const searchWord = query.get("q") || "";
+
+ useEffect(() => {
+ document.title = "YouTube";
+ }, []);
+
+ useEffect(() => {
+ getSearchData(searchWord, setResult, setIsError);
+ }, [searchWord]);
+
+ return (
+
+
+
+
+ {result.map((data: VideoSearchData) => {
+ return ;
+ })}
+
+ );
+};
+
+const Container = styled.div<{ open: boolean }>`
+ box-sizing: border-box;
+ width: ${(props) => (props.open ? "calc(100% - 72)" : "calc(100% - 240)")}px;
+ margin-left: ${(props) => (props.open ? "280" : "200")}px;
+ padding: 70px 24px 16px 0px;
+ overflow-y: hidden;
+`;
+
+const Filter = styled.div`
+ width: 90%;
+ margin-left: 32px;
+ font-size: 14px;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+ .box {
+ display: flex;
+ align-items: center;
+ width: fit-content;
+ padding: 7px 10px;
+ &:hover {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-radius: 20px;
+ }
+ }
+
+ svg {
+ pointer-events: none;
+ display: block;
+ width: 24px;
+ height: 24px;
+ margin-right: 6px;
+ }
+`;
+
+export default Search;
diff --git a/src/pages/Watch/index.tsx b/src/pages/Watch/index.tsx
new file mode 100644
index 0000000..91fa797
--- /dev/null
+++ b/src/pages/Watch/index.tsx
@@ -0,0 +1,78 @@
+import axios from "axios";
+import { useEffect, useState } from "react";
+import { useParams } from "react-router-dom";
+import styled from "styled-components";
+import { getComments, getRelated, getVideoDetail } from "../../api/api";
+import Comments from "../../components/watch/Comments";
+import Description from "../../components/watch/Description";
+import MainVideo from "../../components/watch/MainVideo";
+import RelatedVideo from "../../components/watch/RelatedVideo";
+import {
+ commentsDummyData,
+ videoDetailDummyData,
+ relatedVideoDummyData,
+} from "../../data/data";
+import type { IComment } from "../../types/commentsTypes";
+
+import { VideoDetailData } from "../../types/videoDetailTypes";
+import type { RelatedType } from "../../types/relatedTypes";
+
+interface WatchProps {
+ open: boolean;
+}
+
+const Watch = ({ open }: WatchProps) => {
+ // type assertion
+ const { id } = useParams() as { id: string };
+ const [videoDetailData, setVideoDetailData] =
+ useState(videoDetailDummyData);
+ const [comments, setComments] = useState(commentsDummyData);
+ const [isError, setIsError] = useState("");
+ const [relatedData, setRelatedData] = useState(
+ relatedVideoDummyData,
+ );
+ useEffect(() => {
+ axios
+ .all([
+ getVideoDetail(id, setVideoDetailData, setIsError),
+ getComments(id, setComments, setIsError),
+ getRelated(id, setRelatedData, setIsError),
+ ])
+ .catch((error) => setIsError(error.message));
+ }, [id]);
+
+ useEffect(() => {
+ document.title = videoDetailData.items[0].snippet.title;
+ });
+
+ return (
+
+
+
+
+
+
+
+
+ );
+};
+
+const WatchPageWrapper = styled.div`
+ width: 1000px;
+ min-width: 500px;
+ @media screen and (max-width: 1000px) {
+ width: 100%;
+ }
+`;
+const WatchContainer = styled.div<{ open: boolean }>`
+ display: flex;
+ gap: 40px;
+ padding: 5rem 3.5rem;
+ margin-left: ${(props) => (props.open ? "240" : "0")}px;
+ justify-content: center;
+ @media screen and (max-width: 1000px) {
+ display: block;
+ }
+`;
+
+export default Watch;
diff --git a/src/types/commentsTypes.ts b/src/types/commentsTypes.ts
new file mode 100644
index 0000000..53bcb90
--- /dev/null
+++ b/src/types/commentsTypes.ts
@@ -0,0 +1,41 @@
+// 댓글 타입
+
+export interface ISnippet {
+ videoId: string;
+ textDisplay: string;
+ textOriginal: string;
+ authorDisplayName: string;
+ authorProfileImageUrl: string;
+ authorChannelUrl: string;
+ authorChannelId: {
+ value: string;
+ };
+ canRate: boolean;
+ viewerRating: string;
+ likeCount: number;
+ publishedAt: string;
+ updatedAt: string;
+}
+
+export interface IComment {
+ kind: string;
+ etag: string;
+ id: string;
+ snippet: {
+ videoId: string;
+ topLevelComment: {
+ kind: string;
+ etag: string;
+ id: string;
+ snippet: ISnippet;
+ };
+ canReply: boolean;
+ totalReplyCount: number;
+ isPublic: boolean;
+ };
+}
+
+export interface CommentsProp {
+ comments: IComment[];
+}
+
diff --git a/src/types/descriptionTypes.ts b/src/types/descriptionTypes.ts
new file mode 100644
index 0000000..7a9a390
--- /dev/null
+++ b/src/types/descriptionTypes.ts
@@ -0,0 +1,57 @@
+export interface IDescription {
+ kind: string;
+ etag: string;
+ pageInfo: {
+ totalResults: number;
+ resultsPerPage: number;
+ };
+ items: Array<{
+ kind: string;
+ etag: string;
+ id: string;
+ snippet: {
+ title: string;
+ description: string;
+ customUrl: string;
+ publishedAt: string;
+ thumbnails: {
+ default: {
+ url: string;
+ width: number;
+ height: number;
+ };
+ medium: {
+ url: string;
+ width: number;
+ height: number;
+ };
+ high: {
+ url: string;
+ width: number;
+ height: number;
+ };
+ };
+ localized: {
+ title: string;
+ description: string;
+ };
+ country: string;
+ };
+ contentDetails: {
+ relatedPlaylists: {
+ likes: string;
+ uploads: string;
+ };
+ };
+ statistics: {
+ viewCount: string;
+ subscriberCount: string;
+ hiddenSubscriberCount: boolean;
+ videoCount: string;
+ };
+ }>;
+}
+
+export interface IDescriptionProps {
+ channelId: string;
+}
diff --git a/src/types/relatedCardTypes.d.ts b/src/types/relatedCardTypes.d.ts
new file mode 100644
index 0000000..acfee4a
--- /dev/null
+++ b/src/types/relatedCardTypes.d.ts
@@ -0,0 +1,103 @@
+
+export interface Video {
+ kind: string;
+ etag: string;
+ items: Item[];
+ pageInfo: PageInfo;
+}
+
+export interface Item {
+ kind: string;
+ etag: string;
+ id: string;
+ snippet: Snippet;
+ contentDetails: ContentDetails;
+ statistics: Statistics;
+ player: Player;
+}
+
+export interface Snippet {
+ publishedAt: string;
+ channelId: string;
+ title: string;
+ description: string;
+ thumbnails: Thumbnails;
+ channelTitle: string;
+ tags: string[];
+ categoryId: string;
+ liveBroadcastContent: string;
+ localized: Localized;
+ defaultAudioLanguage: string;
+}
+
+export interface Thumbnails {
+ default: Default;
+ medium: Medium;
+ high: High;
+ standard: Standard;
+ maxres: Maxres;
+}
+
+export interface Default {
+ url: string;
+ width: number;
+ height: number;
+}
+
+export interface Medium {
+ url: string;
+ width: number;
+ height: number;
+}
+
+export interface High {
+ url: string;
+ width: number;
+ height: number;
+}
+
+export interface Standard {
+ url: string;
+ width: number;
+ height: number;
+}
+
+export interface Maxres {
+ url: string;
+ width: number;
+ height: number;
+}
+
+export interface Localized {
+ title: string;
+ description: string;
+}
+
+export interface ContentDetails {
+ duration: string;
+ dimension: string;
+ definition: string;
+ caption: string;
+ licensedContent: boolean;
+ contentRating: ContentRating;
+ projection: string;
+}
+
+export interface ContentRating {}
+
+export interface Statistics {
+ viewCount: string;
+ likeCount: string;
+ favoriteCount: string;
+ commentCount: string;
+}
+
+export interface Player {
+ embedHtml: string;
+}
+
+export interface PageInfo {
+ totalResults: number;
+ resultsPerPage: number;
+}
+
diff --git a/src/types/relatedItemType.d.ts b/src/types/relatedItemType.d.ts
new file mode 100644
index 0000000..2cbef39
--- /dev/null
+++ b/src/types/relatedItemType.d.ts
@@ -0,0 +1,60 @@
+export interface RelatedItem {
+ kind: string
+ etag: string
+ id: Id
+ snippet: Snippet
+}
+
+export interface Id {
+ kind: string
+ videoId: string
+}
+
+export interface Snippet {
+ publishedAt: string
+ channelId: string
+ title: string
+ description: string
+ thumbnails: Thumbnails
+ channelTitle: string
+ liveBroadcastContent: string
+ publishTime: string
+}
+
+export interface Thumbnails {
+ default: Default
+ medium: Medium
+ high: High
+ standard: Standard
+ maxres: Maxres
+}
+
+export interface Default {
+ url: string
+ width: number
+ height: number
+}
+
+export interface Medium {
+ url: string
+ width: number
+ height: number
+}
+
+export interface High {
+ url: string
+ width: number
+ height: number
+}
+
+export interface Standard {
+ url: string
+ width: number
+ height: number
+}
+
+export interface Maxres {
+ url: string
+ width: number
+ height: number
+}
diff --git a/src/types/relatedTypes.d.ts b/src/types/relatedTypes.d.ts
new file mode 100644
index 0000000..67d579b
--- /dev/null
+++ b/src/types/relatedTypes.d.ts
@@ -0,0 +1,62 @@
+export type RelatedType = Root2[]
+
+export interface Root2 {
+ kind: string
+ etag: string
+ id: Id
+ snippet: Snippet
+}
+
+export interface Id {
+ kind: string
+ videoId: string
+}
+
+export interface Snippet {
+ publishedAt: string
+ channelId: string
+ title: string
+ description: string
+ thumbnails: Thumbnails
+ channelTitle: string
+ liveBroadcastContent: string
+ publishTime: string
+}
+
+export interface Thumbnails {
+ default: Default
+ medium: Medium
+ high: High
+ standard: Standard
+ maxres: Maxres
+}
+
+export interface Default {
+ url: string
+ width: number
+ height: number
+}
+
+export interface Medium {
+ url: string
+ width: number
+ height: number
+}
+
+export interface High {
+ url: string
+ width: number
+ height: number
+}
+
+export interface Standard {
+ url: string
+ width: number
+ height: number
+}
+
+export interface Maxres {
+ url: string
+ width: number
+ height: number
+}
diff --git a/src/types/videoDetailTypes.ts b/src/types/videoDetailTypes.ts
new file mode 100644
index 0000000..562caeb
--- /dev/null
+++ b/src/types/videoDetailTypes.ts
@@ -0,0 +1,102 @@
+// 동영상 상세 정보 타입
+export interface VideoDetailData {
+ kind: string;
+ etag: string;
+ items: Item[];
+ pageInfo: PageInfo;
+}
+
+export interface Item {
+ kind: string;
+ etag: string;
+ id: string;
+ snippet: Snippet;
+ contentDetails: ContentDetails;
+ statistics: Statistics;
+ player: Player;
+}
+
+export interface Snippet {
+ publishedAt: string;
+ channelId: string;
+ title: string;
+ description: string;
+ thumbnails: Thumbnails;
+ channelTitle: string;
+ tags: string[];
+ categoryId: string;
+ liveBroadcastContent: string;
+ localized: Localized;
+ defaultAudioLanguage: string;
+}
+
+export interface Thumbnails {
+ default: Default;
+ medium: Medium;
+ high: High;
+ standard: Standard;
+ maxres: Maxres;
+}
+
+export interface Default {
+ url: string;
+ width: number;
+ height: number;
+}
+
+export interface Medium {
+ url: string;
+ width: number;
+ height: number;
+}
+
+export interface High {
+ url: string;
+ width: number;
+ height: number;
+}
+
+export interface Standard {
+ url: string;
+ width: number;
+ height: number;
+}
+
+export interface Maxres {
+ url: string;
+ width: number;
+ height: number;
+}
+
+export interface Localized {
+ title: string;
+ description: string;
+}
+
+export interface ContentDetails {
+ duration: string;
+ dimension: string;
+ definition: string;
+ caption: string;
+ licensedContent: boolean;
+ contentRating: ContentRating;
+ projection: string;
+}
+
+export interface ContentRating {}
+
+export interface Statistics {
+ viewCount: string;
+ likeCount: string;
+ favoriteCount: string;
+ commentCount: string;
+}
+
+export interface Player {
+ embedHtml: string;
+}
+
+export interface PageInfo {
+ totalResults: number;
+ resultsPerPage: number;
+}
diff --git a/src/types/videoSearchTypes.ts b/src/types/videoSearchTypes.ts
new file mode 100644
index 0000000..bd5d592
--- /dev/null
+++ b/src/types/videoSearchTypes.ts
@@ -0,0 +1,47 @@
+// 동영상 검색 정보 타입
+export interface VideoSearchData {
+ kind: string;
+ etag: string;
+ id: Id;
+ snippet: Snippet;
+}
+
+export interface Id {
+ kind: string;
+ videoId: string;
+}
+
+export interface Snippet {
+ publishedAt: string;
+ channelId: string;
+ title: string;
+ description: string;
+ thumbnails: Thumbnails;
+ channelTitle: string;
+ liveBroadcastContent: string;
+ publishTime: string;
+}
+
+export interface Thumbnails {
+ default: Default;
+ medium: Medium;
+ high: High;
+}
+
+export interface Default {
+ url: string;
+ width: number;
+ height: number;
+}
+
+export interface Medium {
+ url: string;
+ width: number;
+ height: number;
+}
+
+export interface High {
+ url: string;
+ width: number;
+ height: number;
+}
diff --git a/src/utils/ScrollToTop.ts b/src/utils/ScrollToTop.ts
new file mode 100644
index 0000000..f6cf8d2
--- /dev/null
+++ b/src/utils/ScrollToTop.ts
@@ -0,0 +1,11 @@
+import { useEffect } from "react";
+import { useLocation } from "react-router-dom";
+
+export default function ScrollToTop() {
+ const { pathname } = useLocation();
+
+ useEffect(() => {
+ window.scrollTo(0, 0);
+ }, [pathname]);
+ return null;
+}
diff --git a/src/utils/displayedAt.ts b/src/utils/displayedAt.ts
new file mode 100644
index 0000000..cb11c72
--- /dev/null
+++ b/src/utils/displayedAt.ts
@@ -0,0 +1,18 @@
+export function displayedAt(createdAt: string) {
+ const now = new Date().getTime();
+ const milliSeconds = now - new Date(createdAt).getTime();
+ const seconds = milliSeconds / 1000;
+ if (seconds < 60) return `방금전`;
+ const minutes = seconds / 60;
+ if (minutes < 60) return `${Math.floor(minutes)}분 전`;
+ const hours = minutes / 60;
+ if (hours < 24) return `${Math.floor(hours)}시간 전`;
+ const days = hours / 24;
+ if (days < 7) return `${Math.floor(days)}일 전`;
+ const weeks = days / 7;
+ if (weeks < 5) return `${Math.floor(weeks)}주 전`;
+ const months = days / 30;
+ if (months < 12) return `${Math.floor(months)}달 전`;
+ const years = days / 365;
+ return `${Math.floor(years)}년 전`;
+}
diff --git a/src/utils/nFormatter.ts b/src/utils/nFormatter.ts
new file mode 100644
index 0000000..d78aff5
--- /dev/null
+++ b/src/utils/nFormatter.ts
@@ -0,0 +1,13 @@
+export function nFormatter(num: number) {
+ //조회수 'k m'
+ if (num >= 100000000) {
+ return (num / 100000000).toFixed(1).replace(/\.0$/, "") + "억";
+ }
+ if (num >= 10000) {
+ return (num / 10000).toFixed(1).replace(/\.0$/, "") + "만";
+ }
+ if (num >= 1000) {
+ return (num / 1000).toFixed(1).replace(/\.0$/, "") + "천";
+ }
+ return num;
+}
diff --git a/src/utils/timeAgo.ts b/src/utils/timeAgo.ts
new file mode 100644
index 0000000..47c26de
--- /dev/null
+++ b/src/utils/timeAgo.ts
@@ -0,0 +1,27 @@
+export const timeAgo = (value: string) => {
+ const today = new Date();
+ const timeValue = new Date(value);
+
+ const betweenTime = Math.floor(
+ (today.getTime() - timeValue.getTime()) / 1000 / 60,
+ );
+
+ if (betweenTime < 1) return "방금 전";
+ if (betweenTime < 60) {
+ return `${betweenTime}분 전`;
+ }
+
+ const betweenTimeHour = Math.floor(betweenTime / 60);
+ if (betweenTimeHour < 24) {
+ return `${betweenTimeHour}시간 전`;
+ }
+
+ const betweenTimeDay = Math.floor(betweenTime / 60 / 24);
+ if (betweenTimeDay < 30) {
+ return `${betweenTimeDay}일 전`;
+ } else if (30 < betweenTimeDay && betweenTimeDay < 365) {
+ return `${Math.floor(betweenTime / 60 / 24 / 30)}개월 전`;
+ }
+
+ return `${Math.floor(betweenTimeDay / 365)}년 전`;
+};
diff --git a/src/utils/videoTime.ts b/src/utils/videoTime.ts
new file mode 100644
index 0000000..38fea30
--- /dev/null
+++ b/src/utils/videoTime.ts
@@ -0,0 +1,44 @@
+export const videoTime = (input: string) => {
+ // 영상길이
+ let reptms = /^PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?$/;
+ let hours = "",
+ minutes = "",
+ seconds = "";
+ if (reptms.test(input)) {
+ let matches: any = reptms.exec(input);
+ if (matches[1]) hours = matches[1];
+ if (matches[2]) minutes = matches[2];
+ if (matches[3]) seconds = matches[3];
+ }
+
+ if (minutes.length === 1) minutes = `0${minutes}`;
+ if (seconds.length === 1) seconds = `0${seconds}`;
+
+ if (hours.length === 0) {
+ if (minutes.length === 0) {
+ if (seconds.length === 0) {
+ return `00:00`;
+ } else {
+ return `00:${seconds}`;
+ }
+ } else {
+ if(seconds.length === 0){
+ return `${minutes}:00`;
+ } else {
+ return `${minutes}:${seconds}`;
+ }
+ }
+ } else {
+ if (minutes.length === 0) {
+ if (seconds.length === 0) {
+ return `${hours}:00:00`;
+ } else return `${hours}:00:${seconds}`;
+ } else {
+ if(seconds.length === 0){
+ return `${hours}:${minutes}:00`;
+ } else {
+ return `${hours}:${minutes}:${seconds}`;
+ }
+ }
+ }
+};
diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..3d0a51a
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "useDefineForClassFields": true,
+ "lib": ["DOM", "DOM.Iterable", "ESNext"],
+ "allowJs": false,
+ "skipLibCheck": true,
+ "esModuleInterop": false,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "module": "ESNext",
+ "moduleResolution": "Node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx"
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/tsconfig.node.json b/tsconfig.node.json
new file mode 100644
index 0000000..9d31e2a
--- /dev/null
+++ b/tsconfig.node.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "module": "ESNext",
+ "moduleResolution": "Node",
+ "allowSyntheticDefaultImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/vite.config.ts b/vite.config.ts
new file mode 100644
index 0000000..861b04b
--- /dev/null
+++ b/vite.config.ts
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react-swc'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+})