diff --git a/README.md b/README.md index dd706ac..807bc77 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,19 @@ -This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). +## Hi! +Thank you for taking time to look at this work sample. This app is my personal site with the work sample added as a page at /truss. + ## Getting Started +First, clone the repo and navigate to the root of the project. + +Then, install the project dependencies: + +```bash +npm install +# or +yarn +``` -First, run the development server: +Next, run the development server: ```bash npm run dev @@ -10,15 +21,23 @@ npm run dev yarn dev ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +Checkout the branch that this feature is being developed on: +```bash +git checkout feature/truss +``` + + +Finally, navigate to [http://localhost:3000/truss](http://localhost:3000/truss) to see the work sample. There is a navigation link in the header. -You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. -[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. +## Files to look at +The files to be concerned with are `pages/truss.js` (displaying the table of planet data) and `hooks/useFetch.js` (abstracting the fetch into a custom hook to help with loading and error states). -The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. +(Please note the other pages in the app will not work without the api key environment variables. See briandridge.com if you are curious). -## Learn More +## Next.js resources + +The app is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). To learn more about Next.js, take a look at the following resources: @@ -26,14 +45,3 @@ To learn more about Next.js, take a look at the following resources: - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/import?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. - -## Weird stuff to know - -In Husky v5 git pre-commit hooks do not get created on install. Downgraded specifically to version 4.2.3 to make them work. -See this issue: https://github.com/typicode/husky/issues/326#issuecomment-769309475 diff --git a/career-goals.md b/career-goals.md deleted file mode 100644 index dc49ff3..0000000 --- a/career-goals.md +++ /dev/null @@ -1,27 +0,0 @@ -- How do you approach PM - - Agile - - Team makeup (cross-functional ?) roles? - -- Tell me about you develop talent - - foster learning, give time resources for education - - career ladder - - leveling - - performance - reviews? - -- 5 year vision and focus for company and eng team - -- Is devops a part of the cultrue? - - CI/CD process - -- - - -- At this point, I'm interested in gaining breadth of knowledge - have FE down, want to start to learn more skills, eventually towards a Staff Engineer tech leadership role.ch$$ - -- I want to be able to impact my teeammates quality of life by making building tools that take away toil and make their jobs joyful and interesting. - -- mission driven product organization. - -- product org consultancy can be hectic, no follow through, no planning, no communicty (silod teams) - -- want to make an impact and foster community and development in an engineering group \ No newline at end of file diff --git a/components/Header.jsx b/components/Header.jsx index 7531a75..71028d1 100644 --- a/components/Header.jsx +++ b/components/Header.jsx @@ -27,9 +27,9 @@ const Header = () => { Resume - + - Blog + Truss Work Sample fetch(url).then(res => res.json()) + + // Recursively get planet pages until data.next is null and all the pages are fetched, collect pages into a single array + const getAllPlanetPages = async (url, planetCollection = []) => { + const { results, next } = await getPlanetPage(url) + planetCollection = [...planetCollection, ...results] + if (next !== null) { + return getAllPlanetPages(next, planetCollection) + } + return planetCollection + } + + // all planet data + const rawPlanets = await getAllPlanetPages('https://swapi.dev/api/planets/') + + // alphabetically sort the collection of all planet data + const sortedPlanets = rawPlanets.sort((first, second) => { + const firstPlanet = first.name.toUpperCase() + const secondPlanet = second.name.toUpperCase() + return firstPlanet < secondPlanet ? -1 : firstPlanet > secondPlanet ? 1 : 0 + }) + return sortedPlanets +} + +// custom hook to fetch data and provide loading, data, and error +export const useFetch = url => { + const [loading, setLoading] = useState(false) + const [data, setData] = useState([]) + const [error, setError] = useState(null) + + useEffect(() => { + let isStale = false + setLoading(true) + + fetch(url) + .then(res => res.json()) + .then(data => { + if (!isStale) { + setData(data) + setError(null) + setLoading(false) + } + }) + .catch(error => { + console.warn(error.message) + setError(error) + setLoading(false) + }) + + return () => { + isStale = true + } + }, [url]) + + return { loading, data, error } +} diff --git a/pages/truss.js b/pages/truss.js new file mode 100644 index 0000000..5283142 --- /dev/null +++ b/pages/truss.js @@ -0,0 +1,137 @@ +/** @jsxRuntime classic / +/* @jsx jsx */ +import { jsx, Flex, Spinner } from 'theme-ui' +import Layout from '@components/Layout' +import { useFetch } from '../hooks/useFetch' + +// take an integer and format with a space at every group of 3 (thousand) +const formatNumber = number => + number?.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ') // https://stackoverflow.com/questions/16637051/adding-space-between-numbers + +// display a "?" in table if values are unknown +const formatUnknown = value => (value === 'unknown' ? '?' : value) + +// calculate the surface area of a planet that is covered by water +const calculateSurfaceAreaCoveredByWater = ( + planetDiameter, + percentageCoveredByWater +) => { + const planetRadius = planetDiameter / 2 + const totalSurfaceArea = 4 * Math.PI * Math.pow(planetRadius, 2) // use this calc to confirm: https://www.calculatorsoup.com/calculators/geometry-solids/sphere.php + const areaCoveredByWater = totalSurfaceArea * (percentageCoveredByWater / 100) + return areaCoveredByWater ? formatNumber(Math.round(areaCoveredByWater)) : '?' +} + +// display planet data in a table (with loading and error states) +const Planets = () => { + const { loading, data, error } = useFetch('https://swapi.dev/api/planets/') + + // alphabetically sort the planet data + const sortedPlanets = data.results?.sort((first, second) => { + const firstPlanet = first.name.toUpperCase() + const secondPlanet = second.name.toUpperCase() + return firstPlanet < secondPlanet ? -1 : firstPlanet > secondPlanet ? 1 : 0 + }) + + // if data is loading show a spinner + if (loading) { + return + } + + // if error, show the error message + if (error) { + return ( +
+
There was a problem getting the data.
+
+ Error: {error.name} - {error.message} +
+
+ ) + } + + // otherwise return the table with the data + return ( + + + + + + + + + + + + + {sortedPlanets?.map(planet => ( + + + + + + + + + ))} + +
PlanetClimateResidentsTerrainPopulationSurface area water
+ + {formatUnknown(planet.name)} + + {formatUnknown(planet.climate)}{planet.residents?.length}{formatUnknown(planet.terrain)}{formatUnknown(formatNumber(planet.population))} + {calculateSurfaceAreaCoveredByWater( + planet.diameter, + planet.surface_water + )} +
+ ) +} + +// page component that provides header, nav, and layout +const TrussWorkSample = () => ( + + + This is my solution to the requested +
+ work sample. + + Displaying planet data from the Star Wars API. + + + +) + +export default TrussWorkSample