From f552b8e3e5c46b6a3afb8199ec4f04fdaa308b7f Mon Sep 17 00:00:00 2001 From: Alexandra Domareski Date: Mon, 2 Mar 2026 11:49:13 +0100 Subject: [PATCH] lab done --- package-lock.json | 87 ++++++++++- package.json | 3 +- src/App.css | 294 +++++++++++++++++++++++++++++++---- src/App.jsx | 30 +++- src/components/Navbar.jsx | 10 +- src/main.jsx | 5 +- src/pages/CompanyPage.jsx | 39 ++++- src/pages/HomePage.jsx | 29 +++- src/pages/TechnologyPage.jsx | 35 ++++- 9 files changed, 490 insertions(+), 42 deletions(-) diff --git a/package-lock.json b/package-lock.json index eadb7c4..3156ff7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,8 @@ "version": "0.0.0", "dependencies": { "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-router-dom": "^7.10.1" }, "devDependencies": { "@types/react": "^18.0.37", @@ -1505,6 +1506,19 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -3555,6 +3569,44 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.10.1.tgz", + "integrity": "sha512-gHL89dRa3kwlUYtRQ+m8NmxGI6CgqN+k4XyGjwcFoQwwCWF6xXpOCUlDovkXClS0d0XJN/5q7kc5W3kiFEd0Yw==", + "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.10.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.10.1.tgz", + "integrity": "sha512-JNBANI6ChGVjA5bwsUIwJk7LHKmqB4JYnYfzFwyp2t12Izva11elds2jx7Yfoup2zssedntwU0oZ5DEmk5Sdaw==", + "license": "MIT", + "dependencies": { + "react-router": "7.10.1" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", @@ -3723,6 +3775,12 @@ "semver": "bin/semver.js" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5464,6 +5522,11 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, + "cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==" + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -6960,6 +7023,23 @@ "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", "dev": true }, + "react-router": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.10.1.tgz", + "integrity": "sha512-gHL89dRa3kwlUYtRQ+m8NmxGI6CgqN+k4XyGjwcFoQwwCWF6xXpOCUlDovkXClS0d0XJN/5q7kc5W3kiFEd0Yw==", + "requires": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + } + }, + "react-router-dom": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.10.1.tgz", + "integrity": "sha512-JNBANI6ChGVjA5bwsUIwJk7LHKmqB4JYnYfzFwyp2t12Izva11elds2jx7Yfoup2zssedntwU0oZ5DEmk5Sdaw==", + "requires": { + "react-router": "7.10.1" + } + }, "regexp.prototype.flags": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", @@ -7073,6 +7153,11 @@ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, + "set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==" + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", diff --git a/package.json b/package.json index 727f1c1..52955cc 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ }, "dependencies": { "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-router-dom": "^7.10.1" }, "devDependencies": { "@types/react": "^18.0.37", diff --git a/src/App.css b/src/App.css index b9d355d..9bbcf36 100644 --- a/src/App.css +++ b/src/App.css @@ -1,42 +1,282 @@ -#root { - max-width: 1280px; +body { + margin: 0; + padding: 0; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); + /* min-height: 100vh; */ +} + +.navbar { + background: linear-gradient( + 90deg, + rgb(56, 75, 245) 0%, + rgb(80, 100, 255) 100% + ); + color: white; + padding: 20px 40px; + width: 100%; + position: fixed; + top: 0; + left: 0; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); + z-index: 100; + box-sizing: border-box; + font-weight: 600; + font-size: 1.3em; +} + +.companies-container { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 30px; + padding: 40px 20px; +} + +.page-title { + font-size: 2.5rem; + margin-top: 100px; + text-align: center; + color: rgb(56, 75, 245); + font-weight: 700; + letter-spacing: -0.5px; +} + +.company-card { + display: flex; + flex-direction: column; + align-items: center; + padding: 30px; + background: white; + border-radius: 16px; + width: 200px; + box-shadow: 0 8px 25px rgba(56, 75, 245, 0.15); + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + cursor: pointer; + border: none; +} + +.company-card:hover { + transform: translateY(-8px); + box-shadow: 0 15px 40px rgba(56, 75, 245, 0.25); +} + +.company-logo, +.tech-logo-details { + width: 100px; + height: 100px; + object-fit: contain; + transition: transform 0.3s ease; +} + +.company-card:hover .company-logo { + transform: scale(1.1); +} + +.company-name { + text-align: center; + font-size: 1.2em; + margin-top: 15px; + color: rgb(56, 75, 245); + font-weight: 600; +} + +.details-page { + display: flex; + width: 100%; + flex-wrap: wrap; + justify-content: center; + align-items: center; + padding: 40px 60px; + background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); + box-sizing: border-box; +} + +.details-title { + text-align: center; + margin-top: 80px; + font-size: 2.5em; + color: rgb(56, 75, 245); + font-weight: 700; + margin-bottom: 30px; +} + +.company-profile, +.tech-profile { + display: flex; + align-items: center; + justify-content: center; + gap: 60px; + width: 100%; + max-width: 1200px; margin: 0 auto; - padding: 2rem; + padding: 40px; + box-sizing: border-box; + background: white; + border-radius: 20px; + box-shadow: 0 12px 40px rgba(56, 75, 245, 0.2); +} + +.company-content, +.tech-content { + display: flex; + flex-direction: column; + align-items: center; + max-width: 500px; +} + +.company-name, +.tech-name-2 { + font-size: 2em; + margin-bottom: 15px; + color: rgb(56, 75, 245); + font-weight: 700; +} + +.company-image, +.tech-image { + margin: 0; + padding: 30px; + background: linear-gradient(135deg, #f5f7fa 0%, #e8ecf1 100%); + border-radius: 16px; + border: none; + display: flex; + align-items: center; + justify-content: center; +} + +.company-image img, +.tech-image img { + max-width: 150px; + max-height: 150px; +} + +.company-description, +.tech-description { + padding: 20px 0; text-align: center; + font-size: 1.05em; + line-height: 1.6; + margin: 0; + color: #333; +} + +h3 { + margin: 20px 0 15px 0; + color: rgb(56, 75, 245); + font-size: 1.3em; + font-weight: 600; +} + +.tech-list { + display: flex; + gap: 15px; + list-style: none; + padding: 0; + margin-top: 50px; + justify-content: center; + flex-wrap: wrap; +} + +.tech-item { + margin: 0; + padding: 0; + border: none; + border-radius: 12px; +} + +.tech-link { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 10px; + text-decoration: none; + color: inherit; + padding: 20px; + background: white; + border-radius: 12px; + box-shadow: 0 6px 20px rgba(56, 75, 245, 0.12); + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + min-width: 120px; } -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: filter 300ms; +.tech-link:hover { + transform: translateY(-5px); + box-shadow: 0 12px 30px rgba(56, 75, 245, 0.2); + color: rgb(56, 75, 245); } -.logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); + +.tech-logo { + width: 50px; + height: 50px; + object-fit: contain; + transition: transform 0.3s ease; } -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); + +.tech-link:hover .tech-logo { + transform: scale(1.15); +} + +.tech-name { + font-weight: 600; + font-size: 0.95em; +} + +.nav-brand { + text-decoration: none; + color: white; + display: flex; + align-items: center; + gap: 10px; + font-size: 1.3em; + font-weight: 700; + letter-spacing: 0.5px; + transition: opacity 0.3s ease; +} + +.nav-brand:hover { + opacity: 0.9; +} + +button, +.btn { + background: linear-gradient( + 90deg, + rgb(56, 75, 245) 0%, + rgb(80, 100, 255) 100% + ); + color: white; + border: none; + padding: 12px 30px; + font-size: 1em; + font-weight: 600; + border-radius: 10px; + cursor: pointer; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + box-shadow: 0 6px 20px rgba(56, 75, 245, 0.3); + text-decoration: none; + display: inline-flex; + align-items: center; + gap: 8px; } -@keyframes logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } +button:hover, +.btn:hover { + transform: translateY(-3px); + box-shadow: 0 10px 30px rgba(56, 75, 245, 0.4); } -@media (prefers-reduced-motion: no-preference) { - a:nth-of-type(2) .logo { - animation: logo-spin infinite 20s linear; - } +button:active, +.btn:active { + transform: translateY(-1px); } -.card { - padding: 2em; +.back-button { + margin-top: 40px; } -.read-the-docs { - color: #888; +.card-link { + text-decoration: none; + color: inherit; } diff --git a/src/App.jsx b/src/App.jsx index 1b51d87..1038ce3 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,10 +1,34 @@ import "./App.css"; +import { useState } from "react"; +import { Route, Routes } from "react-router-dom"; +import companiesData from "./companies.json"; +import technologiesData from "./technologies.json"; +import HomePage from "../src/pages/HomePage"; +import CompanyPage from "../src/pages/CompanyPage"; +import TechnologiesPage from "../src/pages/TechnologyPage"; +import Navbar from "../src/components/Navbar"; function App() { + const [companies, setCompanies] = useState(companiesData); + const [technologies, setTechnologies] = useState(technologiesData); + return ( -
-

LAB | React Stack Tracker

-
+ <> + +
+ + } /> + } + /> + } + /> + +
+ ); } diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx index 09e2806..6eb72a2 100644 --- a/src/components/Navbar.jsx +++ b/src/components/Navbar.jsx @@ -1,5 +1,13 @@ +import { Link } from "react-router-dom"; + function Navbar() { - return ; + return ( + + ); } export default Navbar; diff --git a/src/main.jsx b/src/main.jsx index 54b39dd..622dec4 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -2,9 +2,12 @@ import React from 'react' import ReactDOM from 'react-dom/client' import App from './App.jsx' import './index.css' +import { BrowserRouter as Router } from "react-router-dom"; ReactDOM.createRoot(document.getElementById('root')).render( - + + + , ) diff --git a/src/pages/CompanyPage.jsx b/src/pages/CompanyPage.jsx index cc5903c..ae0ed41 100644 --- a/src/pages/CompanyPage.jsx +++ b/src/pages/CompanyPage.jsx @@ -1,7 +1,40 @@ -function CompanyPage() { +import { Link, useParams } from "react-router-dom"; + +function CompanyPage({ companies }) { + const { companySlug } = useParams(); + + const company = companies.find( + (oneCompany) => oneCompany.slug === companySlug, + ); + + if (!company) return

Company not found

; + return ( -
-

CompanyPage

+
+

Company Profile

+ +
+
+ {company.name} +
+ +
+

{company.name}

+ +

About

+

{company.description}

+
+
+
    + {company.techStack.map((tech) => ( +
  • + + {tech.name} + {tech.name} + +
  • + ))} +
); } diff --git a/src/pages/HomePage.jsx b/src/pages/HomePage.jsx index e97e7de..7e8ce35 100644 --- a/src/pages/HomePage.jsx +++ b/src/pages/HomePage.jsx @@ -1,7 +1,32 @@ -function HomePage() { +import { Link } from "react-router-dom"; + +function HomePage({ companies }) { return (
-

HomePage

+

+ StackTracker: Discover Tech Stacks Used by Top Companies +

+ +
+ {companies.map((oneCompany) => { + return ( + +
+ {oneCompany.name} +

{oneCompany.name}

+
+ + ); + })} +
); } diff --git a/src/pages/TechnologyPage.jsx b/src/pages/TechnologyPage.jsx index 30f9414..b88855d 100644 --- a/src/pages/TechnologyPage.jsx +++ b/src/pages/TechnologyPage.jsx @@ -1,7 +1,36 @@ -function TechnologyPage() { +import { Link, useParams } from "react-router-dom"; + +function TechnologyPage({ technologies }) { + const { slug } = useParams(); + + const technologie = technologies.find((oneTech) => oneTech.slug === slug); + + if (!technologie) return

Technology not found

; + return ( -
-

TechnologyPage

+
+

Technology Details

+ +
+
+ {technologie.name} +
+ +
+

{technologie.name}

+ +

About

+

{technologie.description}

+
+
+ + + ← Back to Company +
); }