{"id":21307274,"url":"https://github.com/jdegand/shoppingify-frontend","last_synced_at":"2026-04-14T23:33:24.057Z","repository":{"id":110668845,"uuid":"560085417","full_name":"jdegand/shoppingify-frontend","owner":"jdegand","description":"DevChallenges - Legacy - Full-Stack Developer - Shoppingify","archived":false,"fork":false,"pushed_at":"2024-10-06T03:26:13.000Z","size":860,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-08T16:40:26.132Z","etag":null,"topics":["axios","devchallenges","devchallenges-legacy","react","recharts"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jdegand.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-10-31T17:52:22.000Z","updated_at":"2024-10-06T03:26:17.000Z","dependencies_parsed_at":"2024-09-06T23:32:15.957Z","dependency_job_id":"2ac07c8d-c0a9-47cb-8c40-d853a907acfc","html_url":"https://github.com/jdegand/shoppingify-frontend","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jdegand/shoppingify-frontend","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdegand%2Fshoppingify-frontend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdegand%2Fshoppingify-frontend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdegand%2Fshoppingify-frontend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdegand%2Fshoppingify-frontend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jdegand","download_url":"https://codeload.github.com/jdegand/shoppingify-frontend/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdegand%2Fshoppingify-frontend/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31819782,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T18:05:02.291Z","status":"ssl_error","status_checked_at":"2026-04-14T18:05:01.765Z","response_time":153,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["axios","devchallenges","devchallenges-legacy","react","recharts"],"created_at":"2024-11-21T16:30:58.240Z","updated_at":"2026-04-14T23:33:24.035Z","avatar_url":"https://github.com/jdegand.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Shoppingify Frontend\n\nSolution for a challenge from [DevChallenges.io](https://web.archive.org/web/20231130033807/https://legacy.devchallenges.io/challenges/mGd5VpbO4JnzU6I9l96x).\n\n## Table of Contents\n\n- [Overview](#overview)\n  - [Screenshots](#screenshots)\n  - [Built With](#built-with)\n- [Features](#features)\n- [How to use](#how-to-use)\n- [Thoughts](#thoughts)\n- [Continued Development](#continued-development)\n- [Useful Resources](#useful-resources)\n- [Acknowledgements](#acknowledgements)\n\n## Overview\n\n### Screenshots\n\n![Register](screenshots/shoppingify-register.png)\n\n***\n\n![Sign In](screenshots/shoppingify-sign-in.png)\n\n***\n\n![Items](screenshots/shoppingify-items.png)\n\n***\n\n![Add New Item](screenshots/shoppingify-add-new-item.png)\n\n***\n\n![Shopping History](screenshots/shoppingify-shopping-history.png)\n\n***\n\n![Stats 1](screenshots/shoppingify-stats-1.png)\n\n***\n\n![Stats 2](screenshots/shoppingify-stats-2.png)\n\n***\n\n![Item Detail](screenshots/shoppingify-item-detail.png)\n\n***\n\n![Item in Chart](screenshots/shoppingify-item-in-cart.png)\n\n***\n\n![Quantity Panel](screenshots/shoppingify-quantity-panel.png)\n\n***\n\n![Quantity Panel Changed](screenshots/shoppingify-quantity-panel-changed.png)\n\n***\n\n![Item Editing 1](screenshots/shoppingify-item-editing-1.png)\n\n***\n\n![Item Editing 2](screenshots/shoppingify-item-editing-2.png)\n\n***\n\n![New List](screenshots/shoppingify-new-list.png)\n\n***\n\n![List Detail](screenshots/shoppingify-list-detail.png)\n\n***\n\n![Stats Updated](screenshots/shoppingify-stats-updated.png)\n\n***\n\n![Mobile 1](screenshots/shoppingify-mobile-1.png)\n\n***\n\n![Mobile 2](screenshots/shoppingify-mobile-2.png)\n\n***\n\n![Mobile 3](screenshots/shoppingify-mobile-3.png)\n\n***\n\n### Built With\n\n- [React](https://reactjs.org)\n- [Axios](https://axios-http.com)\n- [Material Design Icons](https://materialdesignicons.com)\n- [Recharts](https://recharts.org/en-US)\n\n## Features\n\nThis application/site was created as a submission to a [DevChallenges](https://devchallenges.io/challenges) challenge. The [challenge](https://web.archive.org/web/20231130033807/https://legacy.devchallenges.io/challenges/mGd5VpbO4JnzU6I9l96x) was to build an application to complete the given user stories. **Note**: The previous design document may be incomplete, as you need to find an archived version of the challenge as all `legacy` challenges have had their documentation removed from DevChallenges.\n\n## How To Use\n\nTo clone and run this application, you'll need [Git](https://git-scm.com) and [Node.js](https://nodejs.org/en/download/) (which comes with [npm](http://npmjs.com)) installed on your computer. From your command line:\n\n```bash\n# Clone this repository \u0026 the companion backend repo\n$ git clone https://github.com/jdegand/shoppingify-backend.git\n$ git clone https://github.com/jdegand/shoppingify-frontend.git\n\n# Install dependencies in both repos\n$ npm install\n\n# Add env variables \u0026\u0026 run both apps (match PORT number with BASE_URL in axios.js) (in browser - enable cookies)\n$ npm start\n```\n\n## Thoughts\n\n- Added basic testing with Cypress\n- Used a `cypress.env.json` for `env` variables in the Cypress tests.\n- Need to change username for register test each time - could possibly use nanoid for random value for name but can't reuse that user for login tests easily - have to look up in mongo atlas\n- Can install eslint plugin to prevent errors in terminal when looking at the cypress e2e test files\n- Home component holds state - pass as props to other components\n- Project may have benefited from global state management but I do not think it is necessary\n- No categories selection panel\n- Build this desktop first - is design really mobile friendly? - mobile styling based on 375px width - did not look at all possible screen sizes - Tweaks are required for most sizes since I used grids with set pixel values vs percentages\n- Overflow containers could be annoying on mobile\n- Put the item panel after the other 2 sections - easiest mobile solution\n- Mobile - ItemDetail comes after the cart - not great at all - scroll to its location?\n- Added a scrolling hook but not perfect - doesn't reach top of screen or bottom of screen on first click - issue in hook?\n- Problems when resizing as well\n- The cart was not designed to be opened and closed and it may require a significant rework if you were to go that route\n- I think that would help a lot for mobile - as you could replace the items section with itemDetail or itemPanel components\n- Tons of data manipulation done versus more network requests - performance optimizations definitely possible here - useMemo etc\n- Stats page - use all lists from all users or per user - I originally had it for all list items and switched to per-user\n- Top Categories - categories in lists versus total categories used in all lists\n- Top Items - overall percentage of items purchased across all lists (items / total items)\n- Had to repeat overflow containers often.\n- Had multiple 'missing key' warnings - should be mostly solved - I used nanoid - using map inside of another map, need to give keys to both wrapping divs?\n- Could have put navbar and listpanel inside of layout component\n- Change navbar tabs to nav-links and add styling for active link\n- I went with tab system not tied to react router - using react router preferrable - better for bookmarking \u0026 accessbility\n- Changing to nav-links requires changing the :/id api routes - using query params vs search params - need to duplicate backend route - one for each approach or could try to use ' req.params.id || req.query.id' logic in route\n- The state of the list feature is half-baked - should list be available to update \u0026 where ? - in the shopping history detail view ?\n- If all items are purchased (crossed-out), the list is complete - otherwise it is active.  Saving a cancelled list makes no sense.\n- Nor should saving a list require multiple prompts as design implies - creating friction in the process -\u003e lose users who get tired of the process\n- Add toggling of purchased items in the shopping history detail component - the purchased property is present and can be accessed inside of it - I cross out items on list that are purchased - send api request back to update the list and grab list id from url\n- Didn't use gray for input labels - harder to see for no real benefit\n- Various styling differences - disabled input border, bottle\n- Tooltip reminded me -\u003e if something needs to used multiple times -\u003e make a component for it -\u003e this can sometimes slip your mind and you find yourself using multiple state values and multiple handlers\n- The ItemDetail Component had a lot of functionality that I kept removing as development progressed - its click handler had to be moved to the Link component otherwise keyboard functionality would have been broken\n- Added keyboard functionality for the plus button and item panel - should be able to add items to list and save it all with keyboard - checkbox works with spacebar but not with enter key\n- Handle case when no shopping history and no stats to display - right now shows empty chart on stats page\n- problem with list names being unique - can't have different users have same list name ? Problem with having list being a separate model ?\n- need to wrap nav in a header tag?\n\n## Continued Development\n\n- Styling issues. \"Completed\" will overflow with present grid in the shopping list history component.\n- Refactor some component logic.\n- Folder structure improvements\n- Look into Cypress test improvements.\n- Migrate from Create React App or just update dependencies.\n\n## Useful Resources\n\n- [Stack Overflow](https://stackoverflow.com/questions/56828017/testing-usecontext-with-react-testing-library) - testing useContext\n- [Code Sandbox](https://codesandbox.io/s/r4m5jp6jjq) - Vertical React Tabs\n- [Stack Overflow](https://stackoverflow.com/questions/11755628/can-i-use-div-as-a-direct-child-of-ul) - div direct child of ul\n- [React Router Docs](https://reactrouter.com/en/main/components/nav-link) - nav link\n- [Medium](https://medium.com/developer-rants/what-if-height-100vh-is-bigger-than-your-screen-7f39c62ac170) - 100vh overflows\n- [React Docs](https://beta.reactjs.org/learn/you-might-not-need-an-effect) - you might not need an effect\n- [Codepen](https://codepen.io/manabox/pen/KzzeNy) - subtle box shadow\n- [Dev.to](https://dev.to/samba_code/nested-ternary-statements-in-react-jsx-35kp) - nested ternary statements in react\n- [Codepen](https://codepen.io/huferr/pen/GRmZJJx) - react tabs\n- [React Docs](https://beta.reactjs.org/learn/updating-objects-in-state) - updating objects in state\n- [Stack Overflow](https://stackoverflow.com/questions/63614183/react-router-dom-link-how-can-i-put-an-id-into-the-path-of-link) - react router id \u0026 links\n- [React Router Docs](https://reactrouter.com/en/main/components/link) - link\n- [Ultimate Courses](https://ultimatecourses.com/blog/query-strings-search-params-react-router) - search params react router 6\n- [Mongoose Docs](https://mongoosejs.com/docs/defaults.html) - mongoose defaults\n- [Stack Overflow](https://stackoverflow.com/questions/52954908/add-an-object-with-setstate-to-an-array-of-objects) - add an object with setState to array of objects\n- [Stack Overflow](https://stackoverflow.com/questions/71938368/how-to-prevent-adding-duplicate-objects-into-array-in-state-in-reactjs) - prevent duplicate objects in state\n- [AppsLoveWorld](https://www.appsloveworld.com/reactjs/200/440/how-to-avoid-pushing-duplicate-objects-in-state-array-in-reactjs) - avoid pushing duplicate objects\n- [Stack Overflow](https://stackoverflow.com/questions/8837050/allow-specific-tag-to-override-overflowhidden) - override overflow hidden\n- [Stack Overflow](https://stackoverflow.com/questions/35663653/make-a-scrollbar-always-visible-in-a-div-chrome) - make scrollbar always visible\n- [FreeCodeCamp](https://www.freecodecamp.org/news/how-to-work-with-multiple-checkboxes-in-react/) - multiple checkboxes in react\n- [Stack Overflow](https://stackoverflow.com/questions/32923255/react-checkbox-doesnt-toggle) - checkbox \u0026 react\n- [Pluralsight](https://www.pluralsight.com/guides/handling-multiple-inputs-with-single-onchange-handler-react) - handling multiple inputs with single onchange handler\n- [Stack Overflow](https://stackoverflow.com/questions/11922383/how-can-i-access-and-process-nested-objects-arrays-or-json) - nested object arrays\n- [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat) - array flat\n- [Stack Overflow](https://stackoverflow.com/questions/68075339/javascript-find-in-nested-array) - find in nested array\n- [YouTube](https://www.youtube.com/watch?v=10CehsAWk7E) - find unique objects in array\n- [Stack Overflow](https://stackoverflow.com/questions/51573892/update-state-in-nested-array-react-js) - update state in nested array\n- [LearnBestCoding](https://www.learnbestcoding.com/post/56/how-to-update-nested-state-objects-reactjs) - update nested state objects\n- [Stack Overflow](https://stackoverflow.com/questions/29537299/how-can-i-update-state-item1-in-state-using-setstate) - how can update state with index\n- [Stack Overflow](https://stackoverflow.com/questions/26069238/call-multiple-functions-onclick-reactjs) - call multiple function onclick react\n- [Stack Overflow](https://stackoverflow.com/questions/43476729/react-checkbox-does-not-update) - react checkbox not updating\n- [Stack Overflow](https://stackoverflow.com/questions/49226450/how-can-i-pass-multiple-props-in-a-single-event-handler-in-reactjs) - multiple props in a single event handler\n- [Bobby Hadz](https://bobbyhadz.com/blog/react-router-go-back-to-previous-page#:~:text=To%20go%20back%20to%20the,as%20hitting%20the%20back%20button.) - useNavigate\n- [Bobby Hadz](https://bobbyhadz.com/blog/react-remove-query-params) - remove query params\n- [Stack Overflow](https://stackoverflow.com/questions/155188/trigger-a-button-click-with-javascript-on-the-enter-key-in-a-text-box) - keyup enter key\n- [Stack Overflow](https://stackoverflow.com/questions/41580032/group-the-same-category-objects) - group the same category objects\n- [Stack Overflow](https://stackoverflow.com/questions/14446511/most-efficient-method-to-groupby-on-an-array-of-objects) - groupby on an array of objects\n- [Stack Overflow](https://stackoverflow.com/questions/56247433/how-to-use-setstate-callback-on-react-hooks) - setState callback with react hooks\n- [Stack Overflow](https://stackoverflow.com/questions/70223082/updated-variable-is-not-rendered) - updated variable is not rendered\n- [Stack Overflow](https://stackoverflow.com/questions/71804437/how-to-display-the-values-from-a-map-on-a-react-web-app-javascript) - display values from a map object in react\n- [ReactTraining](https://reacttraining.com/blog/how-to-use-and-not-use-state/) - react state\n- [FreeCodeCamp](https://www.freecodecamp.org/news/iterate-through-nested-object-in-react-js/) - iterate nested object in react\n- [Stack Overflow](https://stackoverflow.com/questions/61938375/having-trouble-listing-all-values-of-json-using-map-in-react) - map object \u0026 react\n- [Stack Overflow](https://stackoverflow.com/questions/40803828/how-can-i-map-through-an-object-in-reactjs) - map through an object in react\n- [Bobby Hadz](https://bobbyhadz.com/blog/react-map-nested-array) - react map nested array\n- [Stack Overflow](https://stackoverflow.com/questions/53605759/react-setting-state-to-an-es6-map) - react setting state to an es6 map\n- [Bobby Hadz](https://bobbyhadz.com/blog/javascript-sum-values-of-object) - sum values of object\n- [Stack Overflow](https://stackoverflow.com/questions/44752138/in-react-how-to-pass-a-dynamic-variable-to-a-const-css-style-list) - dynamic variable \u0026 react inline style\n- [Stack Overflow](https://stackoverflow.com/questions/64671325/how-do-i-set-the-width-of-a-component-in-my-react-web-app-based-off-the-output-o) - width of a component based off a variable react\n- [Stack Overflow](https://stackoverflow.com/questions/45100477/how-to-render-a-object-in-react) - render an object in react\n- [Bobby Hadz](https://bobbyhadz.com/blog/javascript-count-occurrences-of-each-element-in-array) - count occurrences of each element in array\n- [Blog](https://www.paigeniedringhaus.com/blog/build-and-custom-style-recharts-data-charts) - recharts data charts\n- [Stack Overflow](https://stackoverflow.com/questions/19480008/javascript-merging-objects-by-id) - merge object by id\n- [Stack Overflow](https://stackoverflow.com/questions/70797166/how-to-match-objects-with-the-same-key-value-pairs-passed-as-arguments) - match objects with same key value pair\n- [Stack Overflow](https://stackoverflow.com/questions/52311150/find-all-matching-elements-with-in-an-array-of-objects) - matching elements within an array of objects\n- [YouTube](https://www.youtube.com/watch?v=Gj0ZOr0N6Ck) - React Charts\n- [Stack Overflow](https://stackoverflow.com/questions/6913512/how-to-sort-an-array-of-objects-by-multiple-fields) - sort an array of objects by multiple fields\n- [Stack Overflow](https://stackoverflow.com/questions/59269676/change-the-value-of-object-in-an-array-on-click-event) - change value of object in array on click event\n- [Stack Overflow](https://stackoverflow.com/questions/59633005/how-is-eslint-integrated-into-create-react-app) - eslint integration with create react app\n- [Codepen](https://codepen.io/anon/pen/YwWRVb) - react tooltip (have to add react and reactDOM to see it working) - change end to ReactDOM.render\n- [Paladini Blog](https://paladini.dev/posts/how-to-make-an-extremely-reusable-tooltip-component-with-react--and-nothing-else/) - reusable tooltip\n- [Codesandbox](https://codesandbox.io/s/how-to-make-an-extremely-reusable-tooltip-component-with-react-and-nothing-else-7opo3?from-embed=\u0026file=/src/App.js) - extremely reusable tooltip component\n- [TestCafe](https://testcafe.io/402905/resources/blog/2020-12-28-randomize-your-end-to-end-tests-how-to-generate-input-data-for-testcafe) - randomize e2e tests\n- [Reddit](https://www.reddit.com/r/copypasta/comments/78yfyh/wall_of_text/) - wall of text\n- [Stack Abuse](https://stackabuse.com/how-to-scroll-to-top-in-react-with-a-button-component/) - scroll\n- [Stack Overflow](https://stackoverflow.com/questions/36862334/get-viewport-window-height-in-reactjs) - get viewport width and height\n- [Stack Overflow](https://stackoverflow.com/questions/33211672/how-to-submit-a-form-using-enter-key-in-react-js) - submit form on enter key\n- [Stack Overflow](https://stackoverflow.com/questions/54579558/clicking-a-link-when-enter-key-is-pressed-using-react) - click a link with keyboard\n- [Github](https://github.com/remix-run/react-router/issues/6600) - react router onKeyPress\n- [Stack Overflow](https://stackoverflow.com/questions/33850412/merge-javascript-objects-in-array-with-same-key) - merge objects\n- [Stack Overflow](https://stackoverflow.com/questions/5732043/how-to-call-reduce-on-an-array-of-objects-to-sum-their-properties) - reduce on array of objects\n- [YouTube](https://www.youtube.com/watch?v=6rNIY7W8IZM) - reduce on array of objects\n- [Medium](https://vmarchesin.medium.com/using-array-prototype-reduce-in-objects-using-javascript-dfcdae538fc8) - array reduce\n- [Stack Overflow](https://stackoverflow.com/questions/29886552/why-are-objects-not-iterable-in-javascript) - objects are not iterable\n- [Stack Overflow](https://stackoverflow.com/questions/62219461/merge-same-object-property-name-and-combine-other-properties-in-one-array-object) - merge objects\n- [TutorialsPoint](https://www.tutorialspoint.com/add-matching-object-values-in-javascript) - matching object values\n- [Stack Overflow](https://stackoverflow.com/questions/65870360/how-to-combine-objects-with-same-value-in-an-array) - combine objects\n- [Stack Overflow](https://stackoverflow.com/questions/39966125/using-indexof-to-filter-an-array) - indexOf and filter\n- [TutorialsPoint](https://www.tutorialspoint.com/merge-javascript-objects-with-the-same-key-value-and-count-them) - merge js objects\n- [Dev.to](https://dev.to/ramonak/javascript-how-to-merge-multiple-objects-with-sum-of-values-43fd) - merge multiple objects\n- [Stack Overflow](https://stackoverflow.com/questions/41824462/sum-of-same-object-name-in-javascript) - sum of same object name\n- [Stack Overflow](https://stackoverflow.com/questions/24444738/sum-similar-keys-in-an-array-of-objects) - sum similar keys in an array of objects\n\n## Acknowledgements\n\n- [Vitor Paladini](https://github.com/vtrpldn) - reused his tooltip\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdegand%2Fshoppingify-frontend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjdegand%2Fshoppingify-frontend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdegand%2Fshoppingify-frontend/lists"}