{"id":26542349,"url":"https://github.com/5j54d93/dcard-2022-web-frontend-intern-homework","last_synced_at":"2025-03-22T02:16:42.378Z","repository":{"id":43462012,"uuid":"458303324","full_name":"5j54d93/Dcard-2022-Web-Frontend-Intern-Homework","owner":"5j54d93","description":"A React app designed like Dcard with Bootstrap that could search a GitHub user's repositories from REST API and list with infinite scroll！","archived":false,"fork":false,"pushed_at":"2022-05-05T14:19:17.000Z","size":75234,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-05-20T22:42:57.609Z","etag":null,"topics":["api","bootstrap","css","dcard","github","hook","html","infinite-scroll","intersectionobserver","javascript","localstorage","react","router","rwd","sessionstorage","ui","web"],"latest_commit_sha":null,"homepage":"https://5j54d93.github.io/Dcard-2022-Web-Frontend-Intern-Homework","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/5j54d93.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"custom":["paypal.me/5j54d93","ethereum/0xf43b3B8B734A9aD9B9e18DBf1882053CC6D623de"]}},"created_at":"2022-02-11T18:46:17.000Z","updated_at":"2024-05-15T17:16:23.000Z","dependencies_parsed_at":"2022-08-23T16:30:40.979Z","dependency_job_id":null,"html_url":"https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/5j54d93%2FDcard-2022-Web-Frontend-Intern-Homework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/5j54d93%2FDcard-2022-Web-Frontend-Intern-Homework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/5j54d93%2FDcard-2022-Web-Frontend-Intern-Homework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/5j54d93%2FDcard-2022-Web-Frontend-Intern-Homework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/5j54d93","download_url":"https://codeload.github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244894308,"owners_count":20527678,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","bootstrap","css","dcard","github","hook","html","infinite-scroll","intersectionobserver","javascript","localstorage","react","router","rwd","sessionstorage","ui","web"],"created_at":"2025-03-22T02:16:41.670Z","updated_at":"2025-03-22T02:16:42.368Z","avatar_url":"https://github.com/5j54d93.png","language":"JavaScript","funding_links":["paypal.me/5j54d93","ethereum/0xf43b3B8B734A9aD9B9e18DBf1882053CC6D623de"],"categories":[],"sub_categories":[],"readme":"# Dcard 2022 Web Frontend Intern Homework\n\n[![pages-build-deployment](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/actions/workflows/pages/pages-build-deployment)\n[![CodeQL](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/actions/workflows/codeql-analysis.yml)\n![GitHub](https://img.shields.io/github/license/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework)\n![GitHub Repo stars](https://img.shields.io/github/stars/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework)\n![GitHub release (latest by date)](https://img.shields.io/github/v/release/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework)\n![GitHub repo size](https://img.shields.io/github/repo-size/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework)\n\nA [**React**](https://reactjs.org) app designed like [**Dcard**](https://www.dcard.tw) with [Bootstrap](https://github.com/twbs/bootstrap) that could：\n\n- search users/organizations on [GitHub](https://github.com)\n- list user's/organization's all repositories with `Infinite Scroll` from [**GitHub REST API**](https://docs.github.com/en/rest)\n- read repository's detail from [**GitHub REST API**](https://docs.github.com/en/rest)\n- follow or unfollow a user/organization which data store in `localStorage`\n\n\u003cimg src=\"https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/.github/Asset/Demo.gif\" width='100%' height='100%'/\u003e\n\n\u003e Doc：[Dcard 2022 Web Frontend Intern Homework.pdf](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/.github/File/2022%20Web%20Frontend%20Intern%20Homework.pdf)  \n\u003e Blog：[Dcard 面試｜應徵 Web Frontend Intern 實習經驗分享！](https://sharing-life-in-tw.blogspot.com/2022/04/Apply-Dcard-Web-Frontend-Intern.html)\n\n#### Comments from Dcard Web Frontend Team 技術夥伴：\n\n作業看的出來很用心，特別去研究了 Dcard 的 UI，體驗上也大致不錯，多做追蹤等功能也相當有特色，README 文件的詳細程度也很加分。\n\n## Overview\n\n1. [**How To Use**](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework#how-to-use)\n   - [On GitHub Page](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework#on-github-page)\n   - [On Your Computer](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework#on-your-computer)\n2. [**Architecture Design \u0026 Explanation**](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework#architecture-design--explanation)\n   - [index.js](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework#indexjsfor-direct-route)：for direct route\n   - [Home.js](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework#homejsfor-search-a-github-username--list-all-following-users)：for search a GitHub username ＆ list all following users\n   - [UserPage.js](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework#userpagejsfor-display-github-user--hisher-all-repositories)：for display GitHub user ＆ his/her all repositories\n   - [RepoDetail.js](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework#repodetailjsfor-display-repository-details)：for display repository details\n   - [Components](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework#componentsused-not-only-on-one-page)：used not only on one page\n3. [**Learn More**](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework#learn-more)\n   - [Rate Limit](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework#rate-limit)\n   - [Responsive Web Design](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework#responsive-web-design)\n   - [Better User Experience on small Devices](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework#better-user-experience-on-small-devices)\n4. [**LICENSE：MIT**](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework#licensemit)\n\n## How To Use\n\n### On GitHub Page\n\n🎊 This React app had deployed on GitHub page, you could try it on [**5j54d93.github.io/Dcard-2022-Web-Frontend-Intern-Homework**](https://5j54d93.github.io/Dcard-2022-Web-Frontend-Intern-Homework)！\n\n### On Your Computer\n\n0. Your computer should have downloaded [Node.js](https://nodejs.org/en) before（Node \u003e= 14.0.0 and npm \u003e= 5.6）\n\n1. Download this repository via `git clone` or from [Releases](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/releases)\n\n```shell\ngit clone https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework\n```\n\n2. Change directories to this repository via `cd` or drag this folder and drop in terminal\n\n```shell\ncd Dcard-2022-Web-Frontend-Intern-Homework\n```\n\n3. Run this React app\n\n```shell\nnpm install\nnpm start\n```\n\n`npm start` will automatically open [**http://localhost:3000**](http://localhost:3000) on your computer.\n\n## Architecture Design \u0026 Explanation\n\n### [index.js](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/src/index.js)：for direct route\n\n- every page will have [Navbar](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/src/Navbar.js) and [Footer](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/src/Footer.js)\n- [Home](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/src/Home.js)：route at `/`\n- [UserPage](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/src/UserPage.js)：route at `/users/{username}/repos`\n- [RepoDetail](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/src/RepoDetail.js)：route at `/users/{username}/repos/{repo}`\n\n```jsx\nReactDOM.render(\n  \u003cReact.StrictMode\u003e\n    \u003cdiv className='d-flex flex-column min-vh-100'\u003e\n      \u003cNavbar /\u003e\n      \u003cBrowserRouter\u003e\n        \u003cRoutes\u003e\n          \u003cRoute path='/' element={\u003cHome /\u003e} /\u003e\n          \u003cRoute path='/users/:owner/repos' element={\u003cUserPage /\u003e} /\u003e\n          \u003cRoute path='/users/:owner/repos/:repo' element={\u003cRepoDetail /\u003e} /\u003e\n        \u003c/Routes\u003e\n      \u003c/BrowserRouter\u003e\n      \u003cFooter /\u003e\n    \u003c/div\u003e\n  \u003c/React.StrictMode\u003e,\n  document.getElementById('root')\n);\n```\n\n### [Home.js](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/src/Home.js)：for search a GitHub username ＆ list all following users\n\n\u003cimg src=\"https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/.github/Asset/Home.png\" width='100%' height='100%'/\u003e\n\n1. [**`SearchBar()`**](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/b594b54a099a30a667a19790a0f4d0a75422421f/src/Home.js#L34-L83)\n   - a search bar for user to input GitHub username\n   - can't submit if there's no input\n   - use `useRef()` to prevent re-render while user is typing\n   - prepare data `onSubmit` before navigate to `UserPage` to ensure that `UserPage` will already have data to show on first render（won't render twice）\n   - store data that fetch from API in `sessionStorage` to prevent API recall if we need the same data later\n2. [**`FollowingUsers()`**](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/b594b54a099a30a667a19790a0f4d0a75422421f/src/Home.js#L85-L98)\n   - list all following users stored in `localStorage`\n   - prepare data `onClick` before navigate to `UserPage` to ensure that `UserPage` will already have data to show on first render（won't render twice）\n   - store data that fetch from API in `sessionStorage` to prevent API recall if we need the same data later\n\n### [UserPage.js](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/src/UserPage.js)：for display GitHub user ＆ his/her all repositories\n\n\u003cimg src=\"https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/.github/Asset/UserPage.png\" width='100%' height='100%'/\u003e\n\n- first check data we need had already saved in `sessionStorage`\n  - if yes（get this page from `Home` or `RepoDetail`）：get data from `sessionStorage`\n  - else（get this page via link directly）：fetch data from API call and save it in `sessionStorage`\n    - GitHub User：[`GET /users/{username}`](https://docs.github.com/en/rest/reference/users#get-a-user)\n    - Repos：[`GET /users/{username}/repos`](https://docs.github.com/en/rest/reference/repos#list-repositories-for-a-user)\n    - render [`Loading`](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/a41fb7a68d1f00aa88996e370b258804276f06b2/src/UserPage.js#L88-L114) while API call\n- check data in `sessionStorage`\n  - if username isn't exit：show「No Such User」\n  - else if number of user's public repo＝0：show「Haven't created any repository yet」\n    - else：show [`RepoList`](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/a9cb2cdfffe9c913d0721ecf4f35700b5bb0a432/src/UserPage.js#L171-L236)\n\n```jsx\n{userData.message === 'Not Found'\n  ? \u003cdiv className={`fs-3 text-center ${styles.textMiddleBlue}`}\u003eNo Such User.\u003c/div\u003e\n  : userData.public_repos === 0\n    ? \u003cdiv className={`fs-3 text-center ${styles.textMiddleBlue}`}\u003eHaven't created any repository yet.\u003c/div\u003e\n    : \u003cRepoList /\u003e\n}\n```\n\n\u003cimg src=\"https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/.github/Asset/404.png\" width='50%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/.github/Asset/0-public-repo.png\" width='50%' height='100%'/\u003e\n\n1. [**`GitHubUser()`**](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/43ed25d9a519423da8c4e36eb63424322d219bb9/src/UserPage.js#L116-L169)\n\nDifferences between user and organization：\n\n||User|Organization|\n|:-:|:-:|:-:|\n|**info**|num of repos、num of followers|location、blog link|\n|**tag above `RepoList`**|\"All Public Repositories\"|\"`.public_repos` Public Repositories\"|\n\n\u003cimg src=\"https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/.github/Asset/User-info.png\" width='50%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/.github/Asset/Organization-info.png\" width='50%' height='100%'/\u003e\n\n2. [**`RepoList()`**](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/e73501e7ed093ff15a63b9ebb8533aa071355dba/src/UserPage.js#L171-L236)\n   - use `useRef()` \u0026 [`IntersectionObserver`](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/e73501e7ed093ff15a63b9ebb8533aa071355dba/src/UserPage.js#L199-L210) on [ProgressView](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/e73501e7ed093ff15a63b9ebb8533aa071355dba/src/UserPage.js#L226-L230) to achieve infinite scroll without always listening to `window.innerHeight`、`document.documentElement.scrollTop`、`document.documentElement.offsetHeight`\n   - store repos data in `sessionStorage`, so when user go to `RepoDetail` and back, we won't re-fetch data from API\n   - use `window.scrollTo()` to ensure that when user go to `RepoDetail` and back, the position of `UserPage` will be the same of previous position（won't go back to top）\n     - because `window.scrollTo()` default with animation in Chrome, we use `behavior: 'instant'` to prevent that for better user experience\n\n```jsx\nwindow.scrollTo({\n  top: sessionStorage.getItem('offsetY'),\n  left: 0,\n  behavior: 'instant'\n});\n```\n\n3. [**`RepoRow()`**](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/e73501e7ed093ff15a63b9ebb8533aa071355dba/src/UserPage.js#L238-L282)\n   - use `React.memo` to prevent re-render every `RepoRow()` in `RepoList()`, only render the next 10 new repos or less in infinite scroll！\n   - prepare data `onClick` before navigate to `RepoDetail` to ensure that `RepoDetail` will already have data to show on first render（won't render twice）\n   - store data that fetch from API in `sessionStorage` to prevent API recall if we need the same data later\n     - we also save `document.documentElement.scrollTop` in `sessionStorage` onClick\n\n\u003cimg src=\"https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/.github/Asset/RepoList-prevent-rerender.gif\" width='100%' height='100%'/\u003e\n\n### [RepoDetail.js](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/src/RepoDetail.js)：for display repository details\n\n\u003cimg src=\"https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/.github/Asset/RepoDetail.png\" width='100%' height='100%'/\u003e\n\n- first check data we need had already saved in `sessionStorage`\n  - if yes（get this page from `UserPage`）：get data from `sessionStorage`\n  - else（get this page via link directly）：fetch data from API call and save it in `sessionStorage`\n    - GitHub User：[`GET /users/{username}`](https://docs.github.com/en/rest/reference/users#get-a-user)\n    - Repo Data：[`GET /repos/{owner}/{repo}`](https://docs.github.com/en/rest/reference/repos#get-a-repository)\n    - render [`Loading`](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/740823717bb658615f2ac42807d3a9c70825f71c/src/RepoDetail.js#L80-L126) while API call\n- Click right-bottom GitHub icon could go to repository page on GitHub\n\n### [Components](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/tree/main/src/Components)：used not only on one page\n\n- [**`CreateTime.js`**](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/src/Components/CreateTime.js)\n  - use `memo` to prevent re-render\n  - reusable：use `props.displayTime` to display\n    - day month year on `RepoRow`\n    - day month year time on `RepoDetail`\n- [**`IconGroup.js`**](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/src/Components/IconGroup.js)\n  - use `memo` to prevent re-render\n- [**`FollowButton.js`**](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/src/Components/FollowButton.js)\n  - return Following or Follow depends on wether the username is saved in [`localStorage`](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/2d6fba31f1e458306e705857f854a3d4d53a096f/src/Components/FollowButton.js#L9-L16)\n  - save or delete user data in `localStorage` while the button [`onClick`](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/2d6fba31f1e458306e705857f854a3d4d53a096f/src/Components/FollowButton.js#L19-L32)\n\n## Learn More\n\n### Rate Limit\n\nWith access tokens, GitHub Rest API Rate Limit could up to 5000 requests per hour. But because this is a public repo and our React app is depolied on Github page, we couldn't use token（GitHub will delete token if it detect that we commit it）. Rate Limit will only up to 60 requests per hour！For more information, [view this official doc](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting).\n\nI've used token like below when this repo is private, and the token won't remove itself！\n\n```jsx\nconst response = await fetch(URL, {\n  headers: {\n    Authorization: 'token TOKEN'\n  }\n});\n```\n\n### Responsive Web Design\n\nThanks to Bootstrap, our React app could response well on every different devices！\n\n### Better User Experience on small Devices\n\n1. Truncate Navbar title into「...」\n2. smaller `padding` with `@media (max-width: 760px)`\n3. somewhere `flex-wrap`, like：`FollowButton`、GitHub Icon、Topics\n\n\u003cimg src=\"https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/.github/Asset/Screen-Shot-on-iPhone-1.png\" width='33.33%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/.github/Asset/Screen-Shot-on-iPhone-2.png\" width='33.33%' height='100%'/\u003e\u003cimg src=\"https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/.github/Asset/Screen-Shot-on-iPhone-3.png\" width='33.33%' height='100%'/\u003e\n\n## License：MIT\n\nThis package is [MIT licensed](https://github.com/5j54d93/Dcard-2022-Web-Frontend-Intern-Homework/blob/main/LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F5j54d93%2Fdcard-2022-web-frontend-intern-homework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F5j54d93%2Fdcard-2022-web-frontend-intern-homework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F5j54d93%2Fdcard-2022-web-frontend-intern-homework/lists"}