From be44492ae239b8b657e3bbc88f7a11b806fab381 Mon Sep 17 00:00:00 2001 From: Coderpurohit Date: Wed, 13 May 2026 18:57:07 +0530 Subject: [PATCH 1/2] Add React Router support with 404 page --- package-lock.json | 77 +++++++++++++++++++++++++++++++++++++++++++++-- package.json | 3 +- src/App.css | 31 +++++++++++++++++-- src/App.tsx | 28 +++++++++++++---- src/index.css | 22 ++++++-------- src/main.tsx | 8 +++-- 6 files changed, 141 insertions(+), 28 deletions(-) diff --git a/package-lock.json b/package-lock.json index ab0e168..dc08902 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,16 @@ { - "name": "orgexplorer", + "name": "OrgExplorer", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "orgexplorer", + "name": "OrgExplorer", "version": "0.0.0", "dependencies": { "react": "^19.2.0", - "react-dom": "^19.2.0" + "react-dom": "^19.2.0", + "react-router-dom": "^7.15.0" }, "devDependencies": { "@eslint/js": "^9.39.1", @@ -57,6 +58,7 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -959,6 +961,7 @@ "integrity": "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -969,6 +972,7 @@ "integrity": "sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -1028,6 +1032,7 @@ "integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.54.0", "@typescript-eslint/types": "8.54.0", @@ -1279,6 +1284,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1384,6 +1390,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -1480,6 +1487,19 @@ "dev": true, "license": "MIT" }, + "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.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1573,6 +1593,7 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -2520,6 +2541,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -2581,6 +2603,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -2590,6 +2613,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -2607,6 +2631,44 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.15.0.tgz", + "integrity": "sha512-HW9vYwuM8f4yx66Izy8xfrzCM+SBJluoZcCbww9A1TySax11S5Vgw6fi3ZjMONw9J4gQwngL7PzkyIpJJpJ7RQ==", + "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.15.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.15.0.tgz", + "integrity": "sha512-VcrVg64Fo8nwBvDscajG8gRTLIuTC6N50nb22l2HOOV4PTOHgoGp8mUjy9wLiHYoYTSYI36tUnXZgasSRFZorQ==", + "license": "MIT", + "dependencies": { + "react-router": "7.15.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -2673,6 +2735,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", @@ -2789,6 +2857,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2876,6 +2945,7 @@ "integrity": "sha512-u09tdk/huMiN8xwoiBbig197jKdCamQTtOruSalOzbqGje3jdHiV0njQlAW0YvzoahkirFePNQ4RYlfnRQpXZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@oxc-project/runtime": "0.97.0", "fdir": "^6.5.0", @@ -2998,6 +3068,7 @@ "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "dev": true, "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index d75669c..7e56d5a 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ }, "dependencies": { "react": "^19.2.0", - "react-dom": "^19.2.0" + "react-dom": "^19.2.0", + "react-router-dom": "^7.15.0" }, "devDependencies": { "@eslint/js": "^9.39.1", diff --git a/src/App.css b/src/App.css index 027945e..f2913ac 100644 --- a/src/App.css +++ b/src/App.css @@ -1,6 +1,31 @@ #root { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; + width: 100%; +} + +.home-container, +.notfound-container { + min-height: 100vh; + + display: flex; + flex-direction: column; + + justify-content: center; + align-items: center; + text-align: center; +} + +h1 { + font-size: 4rem; + margin-bottom: 20px; +} + +a { + color: #4ea1ff; + text-decoration: none; + font-size: 18px; +} + +a:hover { + text-decoration: underline; } \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 0a3deb1..fa2faa1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,12 +1,28 @@ -import './App.css' +import { Routes, Route } from 'react-router-dom' -function App() { +function Home() { + return ( +

Hello, OrgExplorer!

+ ) +} + +function NotFoundPage() { + return ( +
+

404 - Page Not Found

+ Go Back Home +
+ ) +} +function App() { return ( - <> -

Hello, OrgExplorer!

- + + } /> + + } /> + ) } -export default App +export default App \ No newline at end of file diff --git a/src/index.css b/src/index.css index e0dbee4..82a5c55 100644 --- a/src/index.css +++ b/src/index.css @@ -1,15 +1,11 @@ -: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; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; +* { + margin: 0; + padding: 0; + box-sizing: border-box; } +body { + font-family: Arial, sans-serif; + background-color: #111; + color: white; +} \ No newline at end of file diff --git a/src/main.tsx b/src/main.tsx index bef5202..cce2966 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,10 +1,14 @@ import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' +import { BrowserRouter } from 'react-router-dom' + import './index.css' import App from './App.tsx' createRoot(document.getElementById('root')!).render( - + + + , -) +) \ No newline at end of file From e4cd98c1897fce0f19b4a96813a6ccc8cb14236a Mon Sep 17 00:00:00 2001 From: Coderpurohit Date: Thu, 14 May 2026 22:29:16 +0530 Subject: [PATCH 2/2] Add GitHub organization search feature --- src/App.css | 71 +++++++++++++++++++++++++++++++----- src/App.tsx | 61 ++++++++++++++++++++++--------- src/components/orgcard.tsx | 35 ++++++++++++++++++ src/components/serachbar.tsx | 35 ++++++++++++++++++ src/services/githubapi.ts | 15 ++++++++ src/types/github.ts | 8 ++++ 6 files changed, 198 insertions(+), 27 deletions(-) create mode 100644 src/components/orgcard.tsx create mode 100644 src/components/serachbar.tsx create mode 100644 src/services/githubapi.ts create mode 100644 src/types/github.ts diff --git a/src/App.css b/src/App.css index f2913ac..0a36f0d 100644 --- a/src/App.css +++ b/src/App.css @@ -2,30 +2,83 @@ width: 100%; } -.home-container, -.notfound-container { +.app-container { min-height: 100vh; + min-height: 100dvh; display: flex; flex-direction: column; - - justify-content: center; align-items: center; + padding: 40px; + + background-color: #111; + color: white; +} + +.app-container h1 { + margin-bottom: 30px; + font-size: 3rem; +} + +form { + display: flex; + gap: 12px; + margin-bottom: 30px; +} + +input { + padding: 12px; + width: 300px; + + border: none; + border-radius: 10px; + + font-size: 16px; +} + +button { + padding: 12px 20px; + + border: none; + border-radius: 10px; + + cursor: pointer; + + font-size: 16px; + font-weight: bold; +} + +.org-card { + max-width: 500px; + + padding: 30px; + + border-radius: 16px; + + background-color: #1d1d1d; + text-align: center; } -h1 { - font-size: 4rem; +.org-card img { + border-radius: 50%; margin-bottom: 20px; } -a { +.org-card h2 { + margin-bottom: 10px; +} + +.org-card p { + margin-bottom: 12px; +} + +.org-card a { color: #4ea1ff; text-decoration: none; - font-size: 18px; } -a:hover { +.org-card a:hover { text-decoration: underline; } \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index fa2faa1..3bb8809 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,27 +1,52 @@ -import { Routes, Route } from 'react-router-dom' +import { useState } from 'react' -function Home() { - return ( -

Hello, OrgExplorer!

- ) -} +import './App.css' -function NotFoundPage() { - return ( -
-

404 - Page Not Found

- Go Back Home -
- ) -} +import OrgCard from './components/orgcard' +import SearchBar from './components/serachbar' + +import { fetchOrganization } from './services/githubapi' + +import type { GitHubOrg } from './types/github' function App() { + const [organization, setOrganization] = + useState(null) + + const [loading, setLoading] = useState(false) + + const [error, setError] = useState('') + + async function handleSearch(orgName: string) { + try { + setLoading(true) + setError('') + + const data = await fetchOrganization(orgName) + + setOrganization(data) + } catch { + setOrganization(null) + setError('Organization not found') + } finally { + setLoading(false) + } + } + return ( - - } /> +
+

OrgExplorer

- } /> - + + + {loading &&

Loading...

} + + {error &&

{error}

} + + {organization && ( + + )} +
) } diff --git a/src/components/orgcard.tsx b/src/components/orgcard.tsx new file mode 100644 index 0000000..6131b47 --- /dev/null +++ b/src/components/orgcard.tsx @@ -0,0 +1,35 @@ +import type { GitHubOrg } from '../types/github' + +interface OrgCardProps { + organization: GitHubOrg +} + +function OrgCard({ organization }: OrgCardProps) { + return ( +
+ {organization.login} + +

{organization.login}

+ +

{organization.description}

+ +

Followers: {organization.followers}

+ +

Public Repositories: {organization.public_repos}

+ + + Visit GitHub Profile + +
+ ) +} + +export default OrgCard \ No newline at end of file diff --git a/src/components/serachbar.tsx b/src/components/serachbar.tsx new file mode 100644 index 0000000..7251d28 --- /dev/null +++ b/src/components/serachbar.tsx @@ -0,0 +1,35 @@ +import { useState } from 'react' + +interface SearchBarProps { + onSearch: (orgName: string) => void +} + +function SearchBar({ onSearch }: SearchBarProps) { + const [input, setInput] = useState('') + + function handleSubmit(event: React.FormEvent) { + event.preventDefault() + + if (!input.trim()) { + return + } + + onSearch(input) + setInput('') + } + + return ( +
+ setInput(event.target.value)} + /> + + +
+ ) +} + +export default SearchBar \ No newline at end of file diff --git a/src/services/githubapi.ts b/src/services/githubapi.ts new file mode 100644 index 0000000..56be261 --- /dev/null +++ b/src/services/githubapi.ts @@ -0,0 +1,15 @@ +import type { GitHubOrg } from '../types/github' + +export async function fetchOrganization( + orgName: string, +): Promise { + const response = await fetch( + `https://api.github.com/orgs/${orgName}`, + ) + + if (!response.ok) { + throw new Error('Organization not found') + } + + return response.json() +} \ No newline at end of file diff --git a/src/types/github.ts b/src/types/github.ts new file mode 100644 index 0000000..966189e --- /dev/null +++ b/src/types/github.ts @@ -0,0 +1,8 @@ +export interface GitHubOrg { + login: string + avatar_url: string + description: string + public_repos: number + followers: number + html_url: string +} \ No newline at end of file