diff --git a/components/Header/Header.tsx b/components/Header/Header.tsx index 0082cbc92..61c8d57dc 100644 --- a/components/Header/Header.tsx +++ b/components/Header/Header.tsx @@ -6,9 +6,11 @@ import { GlobalContext } from 'context/GlobalContext' import { ThemeToggler } from '../ThemeToggler/themeToggler' import { TopBar } from '../TopBar/TopBar' import { SocialMediaIconsList } from 'components/SocialMedia/SocialMediaIconsList' +import { useResults } from 'hooks/ResultsContext' export const Header: FC = () => { const { toggleNav } = useContext(GlobalContext) + const { results } = useResults() return (
@@ -18,7 +20,10 @@ export const Header: FC = () => {
- +
diff --git a/components/TopBar/TopBar.tsx b/components/TopBar/TopBar.tsx index f72f1a0db..c046bf426 100644 --- a/components/TopBar/TopBar.tsx +++ b/components/TopBar/TopBar.tsx @@ -1,19 +1,38 @@ -import { FC, useState } from 'react' +import { FC, useEffect, useState } from 'react' import { useRouter } from 'next/router' import { FaSlackHash, FaInfoCircle } from 'react-icons/fa' import PopupDesc from 'components/popup/popupCategoryDesc' import { ICategoryData } from 'types' import categoryDescriptions from './CategoryDescriptions' +import { useResults } from 'hooks/ResultsContext' import { Tooltip } from 'react-tooltip' -export const TopBar: FC<{ className?: string | undefined }> = (props) => { - const { className } = props +interface TopBarProps { + className?: string + results: number +} + +export const TopBar: FC = ({ className }) => { + const { results } = useResults() + const [isSearchFound, setIsSearchFound] = useState(false) const [currentCategory, setCurrentCategory] = useState( null ) const router = useRouter() const category = router.asPath.replace('/', '') const categoryName = category.split('-').join(' ') + const regEx = /[ `!@#$%^&*()_+\=\[\]{};':"\\|,.<>\/?~]/g + const cleanedCategory = category + .replaceAll(regEx, ' ') + .replaceAll('search query ', '') + + useEffect(() => { + if (results > 0) { + setIsSearchFound(true) + } else if (results === 0) { + setIsSearchFound(false) + } + }, [results]) if (router.pathname.length === 1) { return null @@ -33,28 +52,78 @@ export const TopBar: FC<{ className?: string | undefined }> = (props) => { } return ( -
- - - {category.split('-').join(' ')} - - + + +
+ ) : ( +
- + + {category.split('-').join(' ')} + + + - - - -
+ +
+ )} + ) } diff --git a/components/popup/popupInfo.tsx b/components/popup/popupInfo.tsx index 3f24b51f9..0d204edc5 100644 --- a/components/popup/popupInfo.tsx +++ b/components/popup/popupInfo.tsx @@ -55,7 +55,7 @@ export const PopupInfo: React.FC<{

{currentCard?.description}

-
+
e.stopPropagation()} href={currentCard?.url} @@ -66,6 +66,16 @@ export const PopupInfo: React.FC<{ Visit site
+ + {/* Close Text */} +
+

+ Close +

+
, overlayRoot )} diff --git a/database/cloud_computing_platforms/azure.json b/database/cloud_computing_platforms/azure.json index 7b1391fae..f68c63436 100644 --- a/database/cloud_computing_platforms/azure.json +++ b/database/cloud_computing_platforms/azure.json @@ -5,5 +5,12 @@ "url": "https://learn.microsoft.com/en-us/azure/?product=popular", "category": "cloud computing", "subcategory": "azure" + }, + { + "name": "Microsoft Learn & Certified", + "description": "Microsoft has certification paths for many technical job roles. Each of these certifications consists of passing a series of exams to earn them. ", + "url": "https://learn.microsoft.com/en-us/certifications/", + "category": "cloud computing", + "subcategory": "azure" } ] \ No newline at end of file diff --git a/database/competitive_programming/platforms.json b/database/competitive_programming/platforms.json new file mode 100644 index 000000000..7a05d241c --- /dev/null +++ b/database/competitive_programming/platforms.json @@ -0,0 +1,16 @@ +[ + { + "name": "LeetCode", + "description": "This site offers competitive coding challenges and interview preparation resources for software engineers and developers.", + "url": "https://leetcode.com/", + "category": "competitive_programming", + "subcategory": "platforms" + }, + { + "name": "HackerRank", + "description": "This resource provides developers with competitive programming challenges to improve their skills in multiple languages. It also allows tech recruiters to assess developers on their problem-solving skills.", + "url": "https://www.hackerrank.com/", + "category": "competitive_programming", + "subcategory": "platforms" + } +] diff --git a/database/data.ts b/database/data.ts index 824373c77..b3e9495a7 100644 --- a/database/data.ts +++ b/database/data.ts @@ -260,4 +260,10 @@ export const sidebarData: ISidebar[] = [ { name: 'communities', url: '/communities', resources: DB.communities }, ], }, + { + category: 'competitive_programming', + subcategory: [ + { name: 'platforms', url: '/platforms', resources: DB.platforms }, + ], + }, ] diff --git a/database/frontend/online-code-editors.json b/database/frontend/online-code-editors.json index 02a89ddf7..0d148eb1c 100644 --- a/database/frontend/online-code-editors.json +++ b/database/frontend/online-code-editors.json @@ -83,20 +83,6 @@ "category": "frontend", "subcategory": "online-code-editors" }, - { - "name": "HackerRank", - "description": "An online IDE to practice your competitive programming skills. It allows you to code in multiple languages.", - "url": "https://www.hackerrank.com/", - "category": "frontend", - "subcategory": "online-code-editors" - }, - { - "name": "LeetCode", - "description": "LeetCode is the best platform to help you enhance your programming skills, and expand your knowledge.", - "url": "https://leetcode.com/", - "category": "frontend", - "subcategory": "online-code-editors" - }, { "name": "Programiz", "description": "Learn to program with our beginner-friendly tutorials and examples. Read tutorials, try examples, write code, and learn to program.", diff --git a/database/index.ts b/database/index.ts index 0d8641a82..b44becb29 100644 --- a/database/index.ts +++ b/database/index.ts @@ -89,3 +89,5 @@ export { default as devtools } from './other/devtools.json' export { default as podcasts } from './other/podcasts.json' export { default as otherResources } from './other/other-resources.json' export { default as communities } from './other/communities.json' +// competitive programming +export {default as platforms } from './competitive_programming/platforms.json' \ No newline at end of file diff --git a/database/other/podcasts.json b/database/other/podcasts.json index 4337b487e..4a02804ad 100644 --- a/database/other/podcasts.json +++ b/database/other/podcasts.json @@ -12,5 +12,13 @@ "url": "https://www.codenewbie.org/podcast", "category": "other", "subcategory": "podcasts" + }, + { + "name": "Stackoverflow Podcast", + "description": " In Stack Overflow Podcast, hosts Ben Popper, Cassidy Williams, and Ceora Ford explore what it means to work in software and how code is reshaping our world.", + "url": "https://stackoverflow.blog/podcast/", + "category": "other", + "subcategory": "podcasts" } + ] \ No newline at end of file diff --git a/database/resources/e-book.json b/database/resources/e-book.json index 2cf169f2f..57f113aac 100644 --- a/database/resources/e-book.json +++ b/database/resources/e-book.json @@ -46,5 +46,13 @@ "category": "resource", "subcategory": "e-book", "language": "english" + }, + { + "name": "Book Yard", + "description": "'The Library to the World', in which books, education materials, information, reference materials, documents, and content will be provided freely", + "url": "www.bookyards.com", + "category": "resource", + "subcategory": "e-book", + "language": "english" } ] \ No newline at end of file diff --git a/database/resources/official-docs.json b/database/resources/official-docs.json index d1dc8160c..44fe149b0 100644 --- a/database/resources/official-docs.json +++ b/database/resources/official-docs.json @@ -79,10 +79,24 @@ { "name": "Express", "description": "Express is a fast, unopinionated, and minimalist web framework for Node.js", - "url": "https://svelte.dev/docs/introduction", + "url": "https://expressjs.com", + "category": "resources", + "subcategory": "officialdocs" + } , + { + "name": "Laravel", + "description": "Laravel is a web application framework with the expressive, elegant syntax", + "url": "https://laravel.com/", + "category": "resources", + "subcategory": "officialdocs" + }, + { + "name": "Ember.js", + "description": "Ember.js is a productive, battle-tested JavaScript framework used for building modern web applications", + "url": "https://guides.emberjs.com/release/", "category": "resources", "subcategory": "officialdocs" - } + } ] diff --git a/database/youtube/data-structures.json b/database/youtube/data-structures.json index 13931bee9..7e754cf06 100644 --- a/database/youtube/data-structures.json +++ b/database/youtube/data-structures.json @@ -26,6 +26,7 @@ { "name": "Kunal Kushwaha", "description": "This channel provides free Java-specific DSA course with interview preparation.", + "description": "This channel provides a free Java-specific DSA course with interview preparation.", "url": "https://youtube.com/playlist?list=PL9gnSGHSqcnr_DxHsP7AW9ftq0AtAyYqJ", "category": "youtube", "subcategory": "data-structures", @@ -121,16 +122,20 @@ }, { "name": "CODING NINJAS", + "description": "This channel provides a DSA and Python course from beginner to advanced.", + + "description": "This channel provides a DSA course about Python from beginner to advanced.", + "url": "https://youtube.com/playlist?list=PLrk5tgtnMN6TYBW0-U4YhIRyYEVpqVEnJ", "category": "youtube", "subcategory": "data-structures", "language": "english" }, { - "name": "CampusX", - "description": "Since Python is a widely used language in the tech industry, a playlist that focuses on various aspects of this programming language would be a valuable addition to this website.", - "url": "https://www.youtube.com/watch?v=f9Aje_cN_CY&list=RDCMUCCWi3hpnq_Pe03nGxuS7isg&start_radio=1&rv=f9Aje_cN_CY&t=41378", + "name": "Data Structures - Full Course Using C and C++", + "description": "Learn about DSAs and how they are implemented in C or C++ in this comprehensive course by FreeCodeCamp. ", + "url": "https://www.youtube.com/watch?v=B31LgI4Y4DQ", "category": "youtube", "subcategory": "data-structures", "language": "english" diff --git a/database/youtube/web-development.json b/database/youtube/web-development.json index 2da7a23c6..f28c9b4cd 100644 --- a/database/youtube/web-development.json +++ b/database/youtube/web-development.json @@ -302,5 +302,13 @@ "category": "youtube", "subcategory": "web-development", "language": "english" + }, + { + "name": "The Coder Coder", + "description": "This site provides practical tips for beginner web developers.", + "url": "https://www.youtube.com/c/TheCoderCoder", + "category": "youtube", + "subcategory": "web-development", + "language": "english" } ] diff --git a/hooks/ResultsContext.tsx b/hooks/ResultsContext.tsx new file mode 100644 index 000000000..cb9941e65 --- /dev/null +++ b/hooks/ResultsContext.tsx @@ -0,0 +1,28 @@ +import React, { createContext, useContext, useState, ReactNode } from 'react' + +interface ResultsContextValue { + results: number + setResults: React.Dispatch> +} + +const ResultsContext = createContext(null) + +export const ResultsProvider: React.FC<{ children: ReactNode }> = ({ + children, +}) => { + const [results, setResults] = useState(-1) + + return ( + + {children} + + ) +} + +export const useResults = () => { + const context = useContext(ResultsContext) + if (!context) { + throw new Error('useResults must be used within a ResultsProvider') + } + return context +} diff --git a/pages/[subcategory]/index.tsx b/pages/[subcategory]/index.tsx index 726181dcd..55cc006f6 100644 --- a/pages/[subcategory]/index.tsx +++ b/pages/[subcategory]/index.tsx @@ -5,9 +5,11 @@ import Head from 'next/head' import useFilterDB from 'hooks/useFilterDB' import CardsList from 'components/Cards/CardsList' import ComingSoon from 'components/NewIssue/NewIssue' +import { useResults } from 'hooks/ResultsContext' const SubCategory = () => { const router = useRouter() + const { results } = useResults() const title = `LinksHub - ${router.asPath .charAt(1) .toUpperCase()}${router.asPath.slice(2)}` @@ -32,7 +34,10 @@ const SubCategory = () => { content="LinksHub is the ultimate hub of ready-to-use tech resources. Discover free tools and libraries to streamline your development process and build better projects." /> - + @@ -80,7 +85,10 @@ const SubCategory = () => { content="https://discord.com/invite/NvK67YnJX5" /> - +
{content}
diff --git a/pages/_app.tsx b/pages/_app.tsx index 5d6e9489c..c0a18b28a 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -4,15 +4,18 @@ import GeneralLayout from 'layouts/GeneralLayout' import { GlobalProvider } from 'context/GlobalContext' import { Preloader } from 'components/Loader/Preloader' import { ThemeProvider } from 'next-themes' +import { ResultsProvider } from 'hooks/ResultsContext' export default function App({ Component, pageProps }: AppProps) { return ( - - - - - + + + + + + + ) diff --git a/pages/search.tsx b/pages/search.tsx index 9ea5f755c..1da0074bc 100644 --- a/pages/search.tsx +++ b/pages/search.tsx @@ -7,8 +7,10 @@ import { TopBar } from 'components/TopBar/TopBar' import ComingSoon from 'components/NewIssue/NewIssue' import useFilterSearch from 'hooks/useFilterSearch' +import { useResults } from 'hooks/ResultsContext' const Search = () => { + const { results, setResults } = useResults() const router = useRouter() const title = `LinksHub - ${router.asPath .charAt(1) @@ -17,12 +19,20 @@ const Search = () => { const { filterSearch } = useFilterSearch() useEffect(() => { - if (!query || query === '') router.replace('/') - }, [query, router]) + if (!query || query === '') router.replace('/'); + }, [query, router]); let content: JSX.Element[] | JSX.Element - - const data = filterSearch(query as string) + + const data = filterSearch(query as string); + + useEffect(() => { + if (data.length > 0 && data.length !== -1) { + setResults(data.length) + } else { + setResults(0) + } + }, [data]) if (data.length > 0) { content = @@ -41,7 +51,10 @@ const Search = () => { content="LinksHub is the ultimate hub of ready-to-use tech resources. Discover free tools and libraries to streamline your development process and build better projects." /> - + @@ -49,10 +62,7 @@ const Search = () => { {/* Open Graph */} - + { {/* Twitter */} - + { property="discord:invite" content="https://discord.com/invite/NvK67YnJX5" /> + - +
{content}
- ) -} + ); +}; -export default Search +export default Search; diff --git a/types/index.ts b/types/index.ts index b5bc0afc5..b7faaac66 100644 --- a/types/index.ts +++ b/types/index.ts @@ -44,6 +44,7 @@ export type Category = | 'youtube' | 'other' | 'devops' + | 'competitive_programming' export type SubCategories = { name: string @@ -158,4 +159,6 @@ export const subcategoryArray = [ 'github', 'other-resources', 'podcasts', + // competitive programming + 'platforms', ]