diff --git a/backend/.github/workflows/backend-ci.yml b/backend/.github/workflows/backend-ci.yml deleted file mode 100644 index 68668fe..0000000 --- a/backend/.github/workflows/backend-ci.yml +++ /dev/null @@ -1,144 +0,0 @@ -name: Backend CI Pipeline - -on: - push: - branches: [main, develop] - pull_request: - branches: [main, develop] - -jobs: - lint: - runs-on: self-hosted - defaults: - run: - working-directory: backend - - steps: - - name: Checkout code without submodules - uses: actions/checkout@v2 # Using v2 for actions/checkout - with: - submodules: false # Skips submodule initialization - - - name: Set up Python - uses: actions/setup-python@v2 # Using v2 for setup-python - with: - python-version: '3.11' - - - name: Install dependencies - run: | - python -m venv venv - source venv/bin/activate - pip install -r requirements.txt # Ensure all dependencies are installed, including requests - - - name: Cache Python dependencies - uses: actions/cache@v2 # Using v2 for actions/cache - with: - path: venv - key: ${{ runner.os }}-python-${{ hashFiles('**/requirements.txt') }} - restore-keys: | - ${{ runner.os }}-python- - - - name: Run pylint (backend only on changed files) - run: | - source venv/bin/activate - changed_files=$(git diff --name-only origin/main...HEAD | grep '\.py$' || true) - - if [ -n "$changed_files" ]; then - pylint $changed_files --exit-zero | tee pylint.log - SCORE=$(tail -n 2 pylint.log | grep -oP '[0-9]+\.[0-9]+(?=/10)') - echo "Pylint score: $SCORE" - python -c "import sys; sys.exit(0 if float('$SCORE') >= 8.0 else 1)" - else - echo "No Python files changed, skipping pylint." - exit 0 # Exit with status 0 (success) if no Python files changed - fi - - test: - runs-on: self-hosted - needs: lint - - steps: - - name: Checkout code without submodules - uses: actions/checkout@v2 # Using v2 for actions/checkout - with: - submodules: false # Skips submodule initialization - - - name: Set up Python - uses: actions/setup-python@v2 # Using v2 for setup-python - with: - python-version: '3.11' - - - name: Install dependencies - run: | - python -m venv venv - source venv/bin/activate - pip install -r backend/requirements.txt # Ensure all dependencies are installed, including requests - pip install pytest-html - - - name: Cache Python dependencies - uses: actions/cache@v2 # Using v2 for actions/cache - with: - path: venv - key: ${{ runner.os }}-python-${{ hashFiles('backend/requirements.txt') }} - restore-keys: | - ${{ runner.os }}-python- - - - name: Start Flask API server - run: | - nohup python backend/main.py > flask.log 2>&1 & - for i in {1..10}; do - if curl --silent --fail http://127.0.0.1:5000/; then - echo "Flask is ready" - break - fi - echo "Waiting for Flask... Attempt $i/10" - sleep 5 - done - - - name: Run backend tests with pytest - env: - BASE_URL: http://127.0.0.1:5000 - run: | - source venv/bin/activate # Activate the virtual environment before running tests - pytest backend/tests --html=backend/test-report.html --self-contained-html - - - name: Upload test report - uses: actions/upload-artifact@v2 # Using v2 for actions/upload-artifact - with: - name: backend-test-report - path: backend/test-report.html - - - name: Kill Flask server - run: | - pkill -f "python backend/main.py" || echo "Flask already exited" - - build-frontend: - runs-on: self-hosted - needs: [lint, test] - - steps: - - name: Checkout repository without submodules - uses: actions/checkout@v2 # Using v2 for actions/checkout - with: - submodules: false # Skips submodule initialization - - - name: Set up Node.js - uses: actions/setup-node@v3 # Using the latest stable version for Node.js - with: - node-version: '20' - - - name: Cache node modules - uses: actions/cache@v2 # Using v2 for actions/cache - with: - path: frontend/node_modules - key: ${{ runner.os }}-node-${{ hashFiles('frontend/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Install frontend dependencies - working-directory: frontend - run: npm install - - - name: Build frontend app - working-directory: frontend - run: npm run build diff --git a/backend/__pycache__/utils.cpython-311.pyc b/backend/__pycache__/utils.cpython-311.pyc index 7216985..566dd7b 100644 Binary files a/backend/__pycache__/utils.cpython-311.pyc and b/backend/__pycache__/utils.cpython-311.pyc differ diff --git a/backend/images/shadow.jpg b/backend/images/shadow.jpg new file mode 100644 index 0000000..1ff6baf Binary files /dev/null and b/backend/images/shadow.jpg differ diff --git a/backend/tests/test_api.py b/backend/tests/test_api.py index e86176d..e174084 100644 --- a/backend/tests/test_api.py +++ b/backend/tests/test_api.py @@ -87,7 +87,7 @@ def test_duplicate_pet_submission(): "breed": "Black", "age": 3, "personality": "Sneaky", - "image_path": "/images/shadow.jpg", + "image_path": "../images/shadow.jpg", } # First submit (should succeed) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index b743de7..47c8748 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -9,14 +9,12 @@ function App() { return ( <> -
- - } /> - } /> - } /> - } /> - -
+ + } /> + } /> + } /> + } /> + ); } diff --git a/frontend/src/assets/facebook_logo.png b/frontend/src/assets/facebook_logo.png new file mode 100644 index 0000000..b6dad0a Binary files /dev/null and b/frontend/src/assets/facebook_logo.png differ diff --git a/frontend/src/assets/instagram_logo.png b/frontend/src/assets/instagram_logo.png new file mode 100644 index 0000000..7424704 Binary files /dev/null and b/frontend/src/assets/instagram_logo.png differ diff --git a/frontend/src/assets/menu_logo.png b/frontend/src/assets/menu_logo.png new file mode 100644 index 0000000..5edfefd Binary files /dev/null and b/frontend/src/assets/menu_logo.png differ diff --git a/frontend/src/assets/twitter_logo.png b/frontend/src/assets/twitter_logo.png new file mode 100644 index 0000000..201f15d Binary files /dev/null and b/frontend/src/assets/twitter_logo.png differ diff --git a/frontend/src/assets/youtube_logo.png b/frontend/src/assets/youtube_logo.png new file mode 100644 index 0000000..bd7109e Binary files /dev/null and b/frontend/src/assets/youtube_logo.png differ diff --git a/frontend/src/index.css b/frontend/src/index.css index 08a3ac9..f80e59c 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -1,16 +1,17 @@ -:root { - font-family: system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; +html, body, #root { + margin: 0; + padding: 0; + height: 100%; + width: 100%; + overflow-x: hidden; + background-color: rgb(180, 164, 143); + font-family: system-ui, Avenir, Helvetica, Arial, sans-serif; } a { @@ -24,10 +25,11 @@ a:hover { body { margin: 0; - display: flex; - place-items: center; - min-width: 320px; + min-width: 100vw; min-height: 100vh; + width: 100%; + height: 100%; + box-sizing: border-box; } h1 { @@ -35,6 +37,11 @@ h1 { line-height: 1.1; } +h2 { + margin: 0; + padding: 0; +} + button { border-radius: 8px; border: 1px solid transparent; @@ -66,3 +73,28 @@ button:focus-visible { background-color: #f9f9f9; } } + + +@media (max-width: 600px) { + h2 { + font-size: 1.5rem; + } + + footer img { + width: 24px; + height: 24px; + } +} + +.pet-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 2rem; + justify-items: center; +} + +@media (max-width: 768px) { + .pet-grid { + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + } +} \ No newline at end of file diff --git a/frontend/src/pages/Home.tsx b/frontend/src/pages/Home.tsx index 94e75b0..9c2f54c 100644 --- a/frontend/src/pages/Home.tsx +++ b/frontend/src/pages/Home.tsx @@ -4,60 +4,161 @@ import catImg from '../assets/cat.png'; import bird from '../assets/bird.png'; import turtle from '../assets/turtle.png'; import doggo from '../assets/puppy.png'; +import instagramLogo from '../assets/instagram_logo.png'; +import facebookLogo from '../assets/facebook_logo.png'; +import twitterLogo from '../assets/twitter_logo.png'; +import youtubeLogo from '../assets/youtube_logo.png'; +import menuLogo from '../assets/menu_logo.png'; +import { useNavigate } from 'react-router-dom'; export default function Home() { + const navigate = useNavigate(); + const pets = [ + { name: "Stella", age: 1, type: "Golden Retriever", img: doggo }, + { name: "Bowser", age: 13, type: "Western Painted Turtle", img: turtle }, + { name: "Moon", age: 9, type: "Cockatiel", img: bird }, + { name: "Cleo", age: 7, type: "Maine Coon Cat", img: catImg }, + ]; + return ( -
-

Home Page

+
+
+
+ Dog handshake + Animal group +
-
- Dog handshake - Animal group -
+
+

+ Adopt your perfect companion today! +

-
-

Adopt your perfect companion today!

- - +
+ + +
+
+
+ + {/*Full-width Featured Header */} +
+

Featured Pets

-

Featured Pets

- -
- {[ - { name: "Stella", age: 1, type: "Golden Retriever", img: doggo }, - { name: "Cleo", age: 7, type: "Maine Coon Cat", img: catImg }, - { name: "Bowser", age: 13, type: "Western Painted Turtle", img: turtle }, - { name: "Moon", age: 9, type: "Cockatiel", img: bird }, - ].map((pet) => ( -
- {pet.name} -
+ {/* ✅ Full-width Grid */} +
+ {pets.map((pet) => ( +
+ {pet.name} +
Name: {pet.name}
Age: {pet.age}
Type: {pet.type}
))} -
+
- Instagram - Facebook - Twitter - YouTube - Menu +
+ Instagram + Facebook + Twitter + YouTube +
+
+ Menu +
); } + +const buttonStyle = { + backgroundColor: "black", + color: "white", + padding: "0.6rem 1.5rem", + borderRadius: "6px", + border: "none", + fontSize: "1rem", + cursor: "pointer" +}; + +const iconStyle = { + width: "36px", + height: "36px" +}; diff --git a/frontend/src/pages/PetProfile.tsx b/frontend/src/pages/PetProfile.tsx index 70b8ad6..393386d 100644 --- a/frontend/src/pages/PetProfile.tsx +++ b/frontend/src/pages/PetProfile.tsx @@ -17,28 +17,60 @@ function PetProfile() { fetch('http://localhost:5000/api/pets') .then(res => res.json()) .then(data => { - console.log('Received pets:', data); // ✅ inside the .then block + console.log('Received pets:', data); setPets(data); }) .catch(err => console.error('Error fetching pets:', err)); }, []); - return ( -
-

Adoptable Pets

-
+
+

Adoptable Pets

+ +
{pets.map(pet => ( -
+
{pet.name} -

{pet.name}

-

Breed: {pet.breed}

-

Age: {pet.age}

-

Temperament: {pet.personality}

+

{pet.name}, {pet.age}

+

Breed: {pet.breed}

+

Temperament: {pet.personality}

+
+ + +
))}
@@ -46,6 +78,15 @@ function PetProfile() { ); } - +const buttonStyle = { + backgroundColor: "black", + color: "white", + padding: "0.5rem 1.25rem", + border: "none", + borderRadius: "8px", + fontSize: "0.9rem", + cursor: "pointer", + flex: "1" +}; export default PetProfile;