diff --git a/package.json b/package.json index d2d2650..191dc56 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "antd": "^5.19.1", "axios": "^1.2.2", "framer-motion": "^10.8.3", + "lodash": "^4.17.21", "prettier": "^3.3.3", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/src/components/Resources/ResourceSection.jsx b/src/components/Resources/ResourceSection.jsx index 6d18c56..3f912a8 100644 --- a/src/components/Resources/ResourceSection.jsx +++ b/src/components/Resources/ResourceSection.jsx @@ -1,14 +1,18 @@ import ResourceCard from "./ResourceCard"; -const ResourceSection = ({ title, resources }) => ( -
-

{title}

-
- {resources.map((resource, index) => ( - - ))} -
-
-); - +const ResourceSection = ({ id, title, resources }) => { + return ( +
+

{title}

+
+ {resources.length === 0 ?
+

No resources found

+
: + resources.map((resource, index) => ( + + ))} +
+
+ ); +} export default ResourceSection; diff --git a/src/data/Resources.json b/src/data/Resources.json index c7dc3ec..2f104d4 100644 --- a/src/data/Resources.json +++ b/src/data/Resources.json @@ -59,6 +59,48 @@ "description": "Comprehensive guide to modern JavaScript.", "link": "https://javascript.info", "image": "https://javascript.info/img/site_preview_en_1200x630.png" + }, + { + "title": "CS50 by Harvard", + "description": "An introduction to computer science, available for free online.", + "link": "https://cs50.harvard.edu", + "image": "https://cs50.harvard.edu/images/cs50x-logo.png" + }, + { + "title": "MIT OpenCourseWare", + "description": "Free lecture notes, exams, and videos from MIT.", + "link": "https://ocw.mit.edu", + "image": "https://ocw.mit.edu/courses/media/ocw_logo-2x.png" + }, + { + "title": "Udemy Free Courses", + "description": "A collection of free courses on various topics.", + "link": "https://www.udemy.com/courses/free", + "image": "https://udemy-images.udemy.com/course/480x270/1071882_59a0.jpg" + }, + { + "title": "Codecademy Learn", + "description": "Free interactive coding lessons on various programming languages.", + "link": "https://www.codecademy.com/learn", + "image": "https://upload.wikimedia.org/wikipedia/commons/6/63/Codecademy_Logo.png" + }, + { + "title": "Frontend Masters", + "description": "Free webinars and courses on front-end development.", + "link": "https://frontendmasters.com", + "image": "https://frontendmasters.com/images/logo.svg" + }, + { + "title": "Pluralsight Free Courses", + "description": "Access to a selection of free courses on technology and development.", + "link": "https://www.pluralsight.com/offer/2020/free", + "image": "https://www.pluralsight.com/content/dam/pluralsight2/marketing/graphics/ps-logo.png" + }, + { + "title": "Treehouse", + "description": "Interactive learning with a focus on web development and design.", + "link": "https://teamtreehouse.com", + "image": "https://teamtreehouse.com/assets/images/logo.svg" } ], "toolsLibraries": [ @@ -92,6 +134,12 @@ "link": "https://angular.io", "image": "https://w7.pngwing.com/pngs/311/952/png-transparent-angular-logo-landscape-tech-companies-thumbnail.png" }, + { + "title": "Svelte", + "description": "A modern JavaScript framework for building fast user interfaces.", + "link": "https://svelte.dev", + "image": "https://svelte.dev/svelte-logo.svg" + }, { "title": "Sass", "description": "A CSS preprocessor that makes writing CSS easier.", @@ -110,6 +158,12 @@ "link": "https://lodash.com", "image": "https://almablog-media.s3.ap-south-1.amazonaws.com/008_7fe10d3c4a.png" }, + { + "title": "Gulp", + "description": "A toolkit for automating painful or time-consuming tasks in your development workflow.", + "link": "https://gulpjs.com", + "image": "https://gulpjs.com/images/gulp-2x.png" + }, { "title": "Webpack", "description": "A static module bundler for JavaScript applications.", @@ -121,6 +175,72 @@ "description": "A zero-configuration web application bundler.", "link": "https://parceljs.org", "image": "https://i0.wp.com/css-tricks.com/wp-content/uploads/2019/10/parcel-box-title.png?fit=1200%2C600&ssl=1" + }, + { + "title": "Alpine.js", + "description": "A minimal framework for composing JavaScript behavior in your HTML.", + "link": "https://alpinejs.dev", + "image": "https://alpinejs.dev/img/logo.svg" + }, + { + "title": "Chart.js", + "description": "A JavaScript library for creating beautiful charts.", + "link": "https://www.chartjs.org", + "image": "https://www.chartjs.org/media/logo-title.png" + }, + { + "title": "D3.js", + "description": "A JavaScript library for producing dynamic, interactive data visualizations.", + "link": "https://d3js.org", + "image": "https://d3js.org/logo.png" + }, + { + "title": "PixiJS", + "description": "A fast 2D rendering engine for web applications.", + "link": "https://pixijs.com", + "image": "https://pixijs.com/assets/images/logo.png" + }, + { + "title": "Moment.js", + "description": "A library for parsing, validating, manipulating, and formatting dates.", + "link": "https://momentjs.com", + "image": "https://momentjs.com/docs/images/moment-logo.svg" + }, + { + "title": "Three.js", + "description": "A JavaScript library for creating 3D graphics in the browser.", + "link": "https://threejs.org", + "image": "https://threejs.org/examples/favicon.png" + }, + { + "title": "Axios", + "description": "A promise-based HTTP client for the browser and Node.js.", + "link": "https://axios-http.com", + "image": "https://axios-http.com/assets/logo.svg" + }, + { + "title": "Eslint", + "description": "A tool for identifying and fixing problems in JavaScript code.", + "link": "https://eslint.org", + "image": "https://eslint.org/assets/img/logo.svg" + }, + { + "title": "Jest", + "description": "A JavaScript testing framework with a focus on simplicity.", + "link": "https://jestjs.io", + "image": "https://jestjs.io/img/jest.svg" + }, + { + "title": "Prettier", + "description": "An opinionated code formatter for consistent code style.", + "link": "https://prettier.io", + "image": "https://prettier.io/favicon.ico" + }, + { + "title": "Cypress", + "description": "A JavaScript end-to-end testing framework.", + "link": "https://www.cypress.io", + "image": "https://www.cypress.io/images/brand/logo.svg" } ], "careerRoadmaps": [ diff --git a/src/pages/Resources.jsx b/src/pages/Resources.jsx index 2a6f999..6eef91e 100644 --- a/src/pages/Resources.jsx +++ b/src/pages/Resources.jsx @@ -1,23 +1,93 @@ +import React, { useState, useCallback } from 'react'; import Layout from '../components/Layout/Layout'; -import { Space } from 'antd'; import MainTitle from '../components/Common/MainTitle'; import ResourceSection from '../components/Resources/ResourceSection'; import resources from '../data/Resources'; +import { Input } from 'antd'; +import { SearchOutlined } from '@ant-design/icons'; +import debounce from 'lodash/debounce'; // Import lodash debounce +const { Search } = Input; const Resources = () => { + const [searchQuery, setSearchQuery] = useState(''); + const [filteredResources, setFilteredResources] = useState(resources); + + const handleSearch = useCallback( + debounce((query) => { + const lowerQuery = query.toLowerCase(); + + // Update filtered resources + const newFilteredResources = { + learningResources: resources.learningResources.filter(resource => + resource.title.toLowerCase().includes(lowerQuery) || + resource.description.toLowerCase().includes(lowerQuery) + ), + toolsLibraries: resources.toolsLibraries.filter(resource => + resource.title.toLowerCase().includes(lowerQuery) || + resource.description.toLowerCase().includes(lowerQuery) + ), + careerRoadmaps: resources.careerRoadmaps.filter(resource => + resource.title.toLowerCase().includes(lowerQuery) || + resource.description.toLowerCase().includes(lowerQuery) + ) + }; + setFilteredResources(newFilteredResources); + + // Scroll to the relevant section if there are results + if (lowerQuery) { + const sections = [ + { id: 'learning-resources', resources: newFilteredResources.learningResources }, + { id: 'tools-libraries', resources: newFilteredResources.toolsLibraries }, + { id: 'career-roadmaps', resources: newFilteredResources.careerRoadmaps } + ]; + const targetSection = sections.find(section => section.resources.length > 0); + if (targetSection) { + const sectionElement = document.getElementById(targetSection.id); + if (sectionElement) { + sectionElement.scrollIntoView({ behavior: 'smooth' }); + } + } + } + }, 300), // Debounce delay in milliseconds + [] + ); + + const handleChange = (e) => { + const query = e.target.value; + setSearchQuery(query); + handleSearch(query); + }; + return (
- - - - - +
+ {/* Icon and Input container */} +
+ + +
+
+ {filteredResources.learningResources.length > 0 && ( + + )} + {filteredResources.toolsLibraries.length > 0 && ( + + )} + {filteredResources.careerRoadmaps.length > 0 && ( + + )}
); diff --git a/yarn.lock b/yarn.lock index e9bf368..6a2a6e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1514,6 +1514,11 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + longest-streak@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.1.0.tgz#62fa67cd958742a1574af9f39866364102d90cd4"