diff --git a/frontend/.gitignore b/frontend/.gitignore index a547bf3..af0ae58 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -22,3 +22,5 @@ dist-ssr *.njsproj *.sln *.sw? + +/node_modules \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index 9099999..0bacc52 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,9 +12,12 @@ "dependencies": { "react": "^18.3.1", "react-dom": "^18.3.1", - "react-router-dom": "^6.24.0" + "react-router-dom": "^6.24.0", + "react-swipeable": "^7.0.1", + "swiper": "^11.1.4" }, "devDependencies": { + "@types/fullpage.js": "^2.9.6", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.13.1", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 1fa189f..5222215 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -17,7 +17,16 @@ importers: react-router-dom: specifier: ^6.24.0 version: 6.24.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-swipeable: + specifier: ^7.0.1 + version: 7.0.1(react@18.3.1) + swiper: + specifier: ^11.1.4 + version: 11.1.4 devDependencies: + '@types/fullpage.js': + specifier: ^2.9.6 + version: 2.9.6 '@types/react': specifier: ^18.3.3 version: 18.3.3 @@ -436,6 +445,12 @@ packages: '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@types/fullpage.js@2.9.6': + resolution: {integrity: sha512-NNl9nQc2g7C0Dc7rokZhyy8IJJh/HNVdPE23Tne6nb6rOknetNzwu3gBNP/zMRMeawHRe8i149yWrpzJ4lUwxg==} + + '@types/jquery@3.5.30': + resolution: {integrity: sha512-nbWKkkyb919DOUxjmRVk8vwtDb0/k8FKncmUKFi+NY+QXqWltooxTrswvz4LspQwxvLdvzBN1TImr6cw3aQx2A==} + '@types/prop-types@15.7.12': resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} @@ -445,6 +460,9 @@ packages: '@types/react@18.3.3': resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} + '@types/sizzle@2.3.8': + resolution: {integrity: sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==} + '@typescript-eslint/eslint-plugin@7.14.1': resolution: {integrity: sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==} engines: {node: ^18.18.0 || >=20.0.0} @@ -1110,6 +1128,11 @@ packages: peerDependencies: react: '>=16.8' + react-swipeable@7.0.1: + resolution: {integrity: sha512-RKB17JdQzvECfnVj9yDZsiYn3vH0eyva/ZbrCZXZR0qp66PBRhtg4F9yJcJTWYT5Adadi+x4NoG53BxKHwIYLQ==} + peerDependencies: + react: ^16.8.3 || ^17 || ^18 + react@18.3.1: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} @@ -1207,6 +1230,10 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + swiper@11.1.4: + resolution: {integrity: sha512-1n7kbYJB2dFEpUHRFszq7gys/ofIBrMNibwTiMvPHwneKND/t9kImnHt6CfGPScMHgI+dWMbGTycCKGMoOO1KA==} + engines: {node: '>= 4.7.0'} + tailwindcss@3.4.4: resolution: {integrity: sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==} engines: {node: '>=14.0.0'} @@ -1570,6 +1597,14 @@ snapshots: '@types/estree@1.0.5': {} + '@types/fullpage.js@2.9.6': + dependencies: + '@types/jquery': 3.5.30 + + '@types/jquery@3.5.30': + dependencies: + '@types/sizzle': 2.3.8 + '@types/prop-types@15.7.12': {} '@types/react-dom@18.3.0': @@ -1581,6 +1616,8 @@ snapshots: '@types/prop-types': 15.7.12 csstype: 3.1.3 + '@types/sizzle@2.3.8': {} + '@typescript-eslint/eslint-plugin@7.14.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2)': dependencies: '@eslint-community/regexpp': 4.11.0 @@ -2258,6 +2295,10 @@ snapshots: '@remix-run/router': 1.17.0 react: 18.3.1 + react-swipeable@7.0.1(react@18.3.1): + dependencies: + react: 18.3.1 + react@18.3.1: dependencies: loose-envify: 1.4.0 @@ -2366,6 +2407,8 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + swiper@11.1.4: {} + tailwindcss@3.4.4: dependencies: '@alloc/quick-lru': 5.2.0 diff --git a/frontend/src/App.css b/frontend/src/App.css index e69de29..8000d6b 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -0,0 +1,50 @@ +/* index.css */ + +html, body { + margin: 0; + padding: 0; + height: 100%; + display: flex; + justify-content: center; + align-items: center; +} + +.swipeable-cards-container { + height: 100vh; + display: flex; + justify-content: center; + align-items: center; +} + +.swipeable-card { + width: 300px; + height: 400px; + margin: 10px; + background-color: #f2f2f2; + display: flex; + justify-content: center; + align-items: center; + font-size: 1.5em; + border-radius: 10px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + transition: transform 0.6s ease; + transform-style: preserve-3d; +} + +.swipeable-card.flipped { + transform: rotateY(180deg); +} + +.swipeable-card:active { + transform: scale(0.95); +} + +.swipeable-card-content { + backface-visibility: hidden; +} + +.swipeable-card-back { + position: absolute; + transform: rotateY(180deg); + backface-visibility: hidden; +} diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index adf9c00..72ced54 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,11 +1,10 @@ import React from 'react'; -import { Routes, Route, Link } from 'react-router-dom'; +import {Link, Route, Routes} from 'react-router-dom'; import Home from './pages/Home'; import About from './pages/About'; import './App.css' function App() { - return ( <>

Top

diff --git a/frontend/src/components/SwipeableCard.tsx b/frontend/src/components/SwipeableCard.tsx new file mode 100644 index 0000000..c34335a --- /dev/null +++ b/frontend/src/components/SwipeableCard.tsx @@ -0,0 +1,39 @@ +import React, { useState } from 'react'; +import { useSwipeable } from 'react-swipeable'; + +interface SwipeableCardProps { + content: string; + onSwiped: (dir: string) => void; +} + +function SwipeableCard({ content, onSwiped }: SwipeableCardProps) { + const [isFlipped, setIsFlipped] = useState(false); + + const handlers = useSwipeable({ + onSwipedLeft: () => handleSwipe('left'), + onSwipedRight: () => handleSwipe('right'), + onSwipedUp: () => handleSwipe('up'), + onSwipedDown: () => handleSwipe('down'), + }); + + const handleSwipe = (dir: string) => { + setIsFlipped(true); + setTimeout(() => { + onSwiped(dir); + setIsFlipped(false); + }, 600); // Match the duration of the CSS transition + }; + + return ( +
+
+ {content} +
+
+ {content} (Back) +
+
+ ); +} + +export default SwipeableCard; diff --git a/frontend/src/pages/Home.tsx b/frontend/src/pages/Home.tsx index a738303..4df127a 100644 --- a/frontend/src/pages/Home.tsx +++ b/frontend/src/pages/Home.tsx @@ -1,10 +1,41 @@ -import React from 'react'; +import React, {useState} from 'react'; + +// Import Swiper styles +import "swiper/css"; +import "swiper/css/effect-coverflow"; +import 'swiper/css/navigation'; +import 'swiper/css/pagination'; +import SwipeableCard from "../components/SwipeableCard.tsx"; + +// Initialize Swiper modules +// SwiperCore.use([Navigation, Pagination]); function Home() { + const [cards, setCards] = useState([ + {id: 1, content: 'Card 1'}, + {id: 2, content: 'Card 2'}, + {id: 3, content: 'Card 3'}, + ]); + + const [currentCardIndex, setCurrentCardIndex] = useState(0); + + const handleSwiped = (dir: string) => { + if (dir === 'left') { + setCurrentCardIndex((prev) => (prev > 0 ? prev - 1 : cards.length - 1)); + } else if (dir === 'right') { + setCurrentCardIndex((prev) => (prev + 1) % cards.length); + } + }; + return ( -
-

Home

-

Welcome to the Home page!

+
+ {cards.length > 0 && ( + + )}
); } diff --git a/node_modules/.yarn-integrity b/node_modules/.yarn-integrity deleted file mode 100644 index 553cf2e..0000000 --- a/node_modules/.yarn-integrity +++ /dev/null @@ -1,10 +0,0 @@ -{ - "systemParams": "linux-x64-115", - "modulesFolders": [], - "flags": [], - "linkedModules": [], - "topLevelPatterns": [], - "lockfileEntries": {}, - "files": [], - "artifacts": {} -} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index fb57ccd..0000000 --- a/yarn.lock +++ /dev/null @@ -1,4 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - -