diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..1561cf3 Binary files /dev/null and b/.DS_Store differ diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 1473d4c..1c0028b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,8 +9,10 @@ "version": "0.0.0", "dependencies": { "axios": "^1.11.0", + "lucide-react": "^0.542.0", "react": "^19.1.1", - "react-dom": "^19.1.1" + "react-dom": "^19.1.1", + "react-router-dom": "^7.8.2" }, "devDependencies": { "@eslint/js": "^9.33.0", @@ -1892,6 +1894,15 @@ "dev": true, "license": "MIT" }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -2981,6 +2992,15 @@ "yallist": "^3.0.2" } }, + "node_modules/lucide-react": { + "version": "0.542.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.542.0.tgz", + "integrity": "sha512-w3hD8/SQB7+lzU2r4VdFyzzOzKnUjTZIF/MQJGSSvni7Llewni4vuViRppfRAa2guOsY5k4jZyxw/i9DQHv+dw==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -3539,6 +3559,44 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.8.2.tgz", + "integrity": "sha512-7M2fR1JbIZ/jFWqelpvSZx+7vd7UlBTfdZqf6OSdF9g6+sfdqJDAWcak6ervbHph200ePlu+7G8LdoiC3ReyAQ==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.8.2.tgz", + "integrity": "sha512-Z4VM5mKDipal2jQ385H6UBhiiEDlnJPx6jyWsTYoZQdl5TrjxEV2a9yl3Fi60NBJxYzOTGTTHXPi0pdizvTwow==", + "license": "MIT", + "dependencies": { + "react-router": "7.8.2" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -3684,6 +3742,12 @@ "semver": "bin/semver.js" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 3bf3790..da01403 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,8 +11,10 @@ }, "dependencies": { "axios": "^1.11.0", + "lucide-react": "^0.542.0", "react": "^19.1.1", - "react-dom": "^19.1.1" + "react-dom": "^19.1.1", + "react-router-dom": "^7.8.2" }, "devDependencies": { "@eslint/js": "^9.33.0", diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index b5078f6..95879a8 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,5 +1,91 @@ -import { useState } from 'react' +import { tvShows, movies, mustSeeHits } from "./data"; +import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; +import SectionHeader from "./components/SectionHeader"; +import ContentCard from "./components/ContentCard"; +import FullListPage from "./components/FullListPage"; +const App = () => { + + + return ( + +
+
+ + + {/* TV Shows Section */} + +
+ +
+ {tvShows.map((show, index) => ( + + ))} +
+
+ + {/* Movies Section */} +
+ +
+ {movies.map((movie, index) => ( + + ))} +
+
+ + {/* Must-See Hits */} +
+ +
+ {mustSeeHits.map((item, index) => ( + + ))} +
+
+ + } + /> + {/* Full lists */} + } /> + } /> + } /> +
+
+ +
+
+ ); +}; + +export default App; + +{ + /** function App() { const [count, setCount] = useState(0) @@ -39,4 +125,6 @@ function App() { ) } -export default App \ No newline at end of file +export default App +*/ +} diff --git a/frontend/src/components/ContentCard.jsx b/frontend/src/components/ContentCard.jsx new file mode 100644 index 0000000..57e9aab --- /dev/null +++ b/frontend/src/components/ContentCard.jsx @@ -0,0 +1,30 @@ +const ContentCard = ({ item, index, isMovie = false }) => ( +
+
+ {item.title} + +
+
+
+
+
+
+
+
+ {index} +
+
+

{item.title}

+

+ {isMovie ? `${item.year} ยท ${item.genre}` : item.genre} +

+
+
+
+ ); + +export default ContentCard; \ No newline at end of file diff --git a/frontend/src/components/FullListPage.jsx b/frontend/src/components/FullListPage.jsx new file mode 100644 index 0000000..9550014 --- /dev/null +++ b/frontend/src/components/FullListPage.jsx @@ -0,0 +1,21 @@ +import ContentCard from "../components/ContentCard"; + +const FullListPage = ({ title, items }) => { + return ( +
+

{title}

+
+ {items.map((item, index) => ( + + ))} +
+
+ ); +}; + +export default FullListPage; diff --git a/frontend/src/components/SectionHeader.jsx b/frontend/src/components/SectionHeader.jsx new file mode 100644 index 0000000..81a21da --- /dev/null +++ b/frontend/src/components/SectionHeader.jsx @@ -0,0 +1,15 @@ +import { ChevronRight } from "lucide-react"; +import { Link } from "react-router-dom"; + +const SectionHeader = ({ title, to }) => ( +
+

{title}

+ {to && ( + + + + )} +
+ ); + +export default SectionHeader; \ No newline at end of file diff --git a/frontend/src/data.js b/frontend/src/data.js new file mode 100644 index 0000000..bdade06 --- /dev/null +++ b/frontend/src/data.js @@ -0,0 +1,157 @@ +export const tvShows = [ + { + id: 1, + title: "Platonic", + genre: "Comedy", + image: + "https://is1-ssl.mzstatic.com/image/thumb/rBI93Qq60YpBP60maTBNbg/680x382.webp", + }, + { + id: 2, + title: "Invasion", + genre: "Sci-Fi", + image: + "https://is1-ssl.mzstatic.com/image/thumb/hH3rVWDItz3USIX5bBSEcw/680x382.webp", + }, + { + id: 3, + title: "Chief of War", + genre: "Drama", + image: + "https://is1-ssl.mzstatic.com/image/thumb/twLCcLLXmcLBqEf3Af3vww/680x382.webp", + }, + { + id: 4, + title: "Foundation", + genre: "Sci-Fi", + image: + "https://is1-ssl.mzstatic.com/image/thumb/Xye2zsX5gxLetoLRdTgNLA/680x382.webp", + }, + { + id: 5, + title: "Ted Lasso", + genre: "Comedy", + image: + "https://is1-ssl.mzstatic.com/image/thumb/ageP1PYyLi7UlNiWMva32Q/680x382.webp", + }, + { + id: 6, + title: "Acapulco", + genre: "Comdey", + image: + "https://is1-ssl.mzstatic.com/image/thumb/Ec4GedDwtKAxOrCp_VOF-g/680x382.webp", + }, + { + id: 7, + title: "Severance", + genre: "Thriller", + image: + "https://is1-ssl.mzstatic.com/image/thumb/EUeDAPovZrBtOcrP2Da5Lw/680x382.webp", + }, + { + id: 8, + title: "Slow Horses", + genre: "Thriller", + image: + "https://is1-ssl.mzstatic.com/image/thumb/S2T1FMcov5a0GzmninlU4Q/680x382.webp", + }, + { + id: 9, + title: "Shrinking", + genre: "Comedy", + image: + "https://is1-ssl.mzstatic.com/image/thumb/C34jADlGtR5wObjPAMbW4w/680x382.webp", + }, + { + id: 10, + title: "Stick", + genre: "Comdey", + image: + "https://is1-ssl.mzstatic.com/image/thumb/Axf6fFibiK2puSTzKXvgpA/680x382.webp", + }, +]; + +export const movies = [ + { + id: 1, + title: "The Gorge", + year: "2025", + genre: "Thriller", + image: + "https://is1-ssl.mzstatic.com/image/thumb/3pfG0GJkoI0OFlPiIDdvUQ/680x382.webp", + }, + { + id: 2, + title: "Fountain of Youth", + year: "2025", + genre: "Action", + image: + "https://is1-ssl.mzstatic.com/image/thumb/4UEcdeb6Xoc40fhFSAr3Og/680x382.webp", + }, + { + id: 3, + title: "Echo Valley", + year: "2025", + genre: "Thriller", + image: + "https://is1-ssl.mzstatic.com/image/thumb/gy_-HeK7Awo48x2fPuAy_w/680x382.webp", + }, + { + id: 4, + title: "Greyhound", + year: "2020", + genre: "Action", + image: + "https://is1-ssl.mzstatic.com/image/thumb/oANBVngpEJDvHRhdyozySA/680x382.webp", + }, + { + id: 5, + title: "Wolfs", + year: "2024", + genre: "Action", + image: + "https://is1-ssl.mzstatic.com/image/thumb/2eBqvT3JXPbdzHWj6HM5_w/680x382.webp", + }, + { + id: 6, + title: "The Family Plan", + year: "2023", + genre: "Comdey", + image: + "https://is1-ssl.mzstatic.com/image/thumb/tPJwMGtsAr_psAVlyf2Rzg/680x382.webp", + }, + { + id: 7, + title: "Killers of the Moon", + year: "2023", + genre: "Crime", + image: + "https://is1-ssl.mzstatic.com/image/thumb/rss8pF-klNy76S-NWFue-A/680x382.webp", + }, + { + id: 8, + title: "Ghosted", + year: "2023", + genre: "Action", + image: + "https://is1-ssl.mzstatic.com/image/thumb/Ze8uZ-TWJ2JMbqmtcz8_BA/680x382.webp", + }, + { + id: 9, + title: "A Summer Musical", + year: "2025", + genre: "Animation", + image: + "https://is1-ssl.mzstatic.com/image/thumb/qnArJ6qO8I8hoZv2OhnO5A/680x382.webp", + }, + { + id: 10, + title: "Luck", + year: "2022", + genre: "Animation", + image: + "https://is1-ssl.mzstatic.com/image/thumb/gHMoyFnOUJLH6d0rSgyIbg/680x382.webp", + }, +]; + +export const mustSeeHits = [...tvShows, ...movies]; \ No newline at end of file