{"id":49458356,"url":"https://github.com/ogrodev/squad-management-tool","last_synced_at":"2026-04-30T08:04:50.182Z","repository":{"id":111400714,"uuid":"353355627","full_name":"ogrodev/squad-management-tool","owner":"ogrodev","description":null,"archived":false,"fork":false,"pushed_at":"2021-04-09T18:31:16.000Z","size":1543,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2023-07-21T03:28:51.639Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"squad-management-tool-sweetsoul.vercel.app","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/ogrodev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-03-31T12:52:09.000Z","updated_at":"2023-07-21T03:28:55.175Z","dependencies_parsed_at":"2023-03-29T04:18:10.113Z","dependency_job_id":null,"html_url":"https://github.com/ogrodev/squad-management-tool","commit_stats":null,"previous_names":["ogrodev/squad-management-tool"],"tags_count":null,"template":null,"template_full_name":null,"purl":"pkg:github/ogrodev/squad-management-tool","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ogrodev%2Fsquad-management-tool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ogrodev%2Fsquad-management-tool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ogrodev%2Fsquad-management-tool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ogrodev%2Fsquad-management-tool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ogrodev","download_url":"https://codeload.github.com/ogrodev/squad-management-tool/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ogrodev%2Fsquad-management-tool/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32458254,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T22:27:22.272Z","status":"online","status_checked_at":"2026-04-30T02:00:05.929Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2026-04-30T08:04:16.899Z","updated_at":"2026-04-30T08:04:50.169Z","avatar_url":"https://github.com/ogrodev.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align='center'\u003e \n  \u003cimg src='https://sweetsoul.sirv.com/Images/venturus/logo192.png' width='50' align='center'/\u003e \n  \u003cb\u003eSquad Management Tool\u003c/b\u003e\n\u003c/h1\u003e\n\n\u003cp align='center'\u003e\n\u003cimg src='https://img.shields.io/github/license/sweetsoul/squad-management-tool' align='center'\u003e\n\u003cimg src='https://img.shields.io/tokei/lines/github/sweetsoul/squad-management-tool' align='center'\u003e\n\u003c/p\u003e\n\n👉 [![Demo Badge](https://img.shields.io/badge/Demo-online-brightgreen)](https://squad-management-tool-ochre.vercel.app/) 👈\n\n\n\nhttps://squad-management-tool-ochre.vercel.app/\n## 1. \u003cb\u003eTechnologies used\u003c/b\u003e\n\nThis application was made using only the mostly needed technology within the application. Above is a descriptive list of everything used.\n\n### 1.1. \u003cb\u003eLayout\u003c/b\u003e\n\n- Pure-css3\n- HTML5 native elements\n\n### 1.2. \u003cb\u003eState Management\u003c/b\u003e\n\n- [React Redux](https://react-redux.js.org/)\n\n### 1.3. \u003cb\u003eRouting\u003c/b\u003e\n\n- [React Router](https://reactrouter.com/web/guides/quick-start)\n\n### 1.4. \u003cb\u003eAPI\u003c/b\u003e\n\n- Comms via [Axios](https://github.com/axios/axios)\n- Data from [AllSportApi](https://allsportsapi.com/) better organized at [MockApi](https://mockapi.io)\n- [Teams endpoint](https://6040127af3abf00017785815.mockapi.io/api/v3/teams) \u0026 [Players endpoint](https://6040127af3abf00017785815.mockapi.io/api/v3/players)\n\n----\n\n## 2. \u003cb\u003eTable of Content\u003c/b\u003e\n\n- [1. \u003cb\u003eTechnologies used\u003c/b\u003e](#1-btechnologies-usedb)\n  - [1.1. \u003cb\u003eLayout\u003c/b\u003e](#11-blayoutb)\n  - [1.2. \u003cb\u003eState Management\u003c/b\u003e](#12-bstate-managementb)\n  - [1.3. \u003cb\u003eRouting\u003c/b\u003e](#13-broutingb)\n  - [1.4. \u003cb\u003eAPI\u003c/b\u003e](#14-bapib)\n- [2. \u003cb\u003eTable of Content\u003c/b\u003e](#2-btable-of-contentb)\n- [3. \u003cb\u003eInstallation\u003c/b\u003e](#3-binstallationb)\n- [4. \u003cb\u003eCode explaining\u003c/b\u003e](#4-bcode-explainingb)\n  - [4.1. \u003cb\u003eFolder Structure\u003c/b\u003e](#41-bfolder-structureb)\n  - [4.2. \u003cb\u003eDashboard page\u003c/b\u003e 📊](#42-bdashboard-pageb-)\n    - [4.2.1. \u003cb\u003eTeamsBoard (My teams) 📋\u003c/b\u003e](#421-bteamsboard-my-teams-b)\n    - [4.2.2. \u003cb\u003eAvgBoard\u003c/b\u003e ➗](#422-bavgboardb-)\n    - [4.2.3. \u003cb\u003ePlayersHighlight\u003c/b\u003e 🌟](#423-bplayershighlightb-)\n  - [4.3. \u003cb\u003eTeamEditor Page\u003c/b\u003e ✏️](#43-bteameditor-pageb-️)\n    - [4.3.1. \u003cb\u003e TeamInfoForm \u003c/b\u003e](#431-b-teaminfoform-b)\n    - [4.3.2. \u003cb\u003eTeam Information Section (TeamInformationSection.js)\u003c/b\u003e ✍️](#432-bteam-information-section-teaminformationsectionjsb-️)\n    - [4.3.3. \u003cb\u003eConfigure Squad Section(ConfigureSquadSection.js)\u003c/b\u003e ⚙️](#433-bconfigure-squad-sectionconfiguresquadsectionjsb-️)\n    - [4.3.4. \u003cb\u003eSave Button\u003c/b\u003e 💾](#434-bsave-buttonb-)\n    - [4.3.5. \u003cb\u003eUnsaved validation\u003c/b\u003e ⚠️](#435-bunsaved-validationb-️)\n- [Testing Scope](#testing-scope)\n\n----\n\n## 3. \u003cb\u003eInstallation\u003c/b\u003e\n\nThis is just a showcase of my skills, but in case you want to see it in action on localhost, just follow the steps below.\n\nClone the repo\n\n```bash\ngit clone https://github.com/SweetSoul/squad-management-tool\n```\n\nEnter folder and install deps\n\n```bash\ncd squad-management-tool \nnpm i\n```\n\nStart node server as you would in create-react-app\n\n```bash\nnpm start\n```\n\nOpen any browser in [localhost:3000](http://localhost:3000)\n\n----\n\n## 4. \u003cb\u003eCode explaining\u003c/b\u003e\n\n### 4.1. \u003cb\u003eFolder Structure\u003c/b\u003e\n\nFirst in the folder structure i tried to be as clean as the time let me be. I had the objective to deliver all features working in the given time.\n\n![Folder Structure](https://sweetsoul.sirv.com/Images/venturus/Screenshot_1.png)\n\nsrc/components -\u003e Contains every component child from the pages and its childs  \nsrc/features -\u003e Redux slices  \nsrc/media -\u003e Used media  \nsrc/pages -\u003e Parent pages to components (Are called in routes)  \nsrc/styles -\u003e Contains all css modules for pages and components  \nsrc/utils -\u003e Some reusable functions  \n\n### 4.2. \u003cb\u003eDashboard page\u003c/b\u003e 📊\n\nThere is 4 components being loaded\n\n![Dashboard](https://sweetsoul.sirv.com/Images/venturus/dashboard.png)\n\n- Topbar - just the topbar\n- TeamsBoard (My teams)\n- AvgBoard (Top 5)\n- PlayersHighlight (Most / Less pickeds player)\n  \n#### 4.2.1. \u003cb\u003eTeamsBoard (My teams) 📋\u003c/b\u003e\n\nThis component is composed by html title row and a table which is a child component named SortingTable.js that gets the dataSource for table mounting (in our case the teams redux store)  \nExpect to see a fully functional table with pagination (10 to 10 rows) and sorting when clicking on one of the two table headings [Name || Description]  \nBy default it won't sort by anything  \n\n```javascript\n\u003cSortingTable \n  teams={teamStore} //Redux teams store\n/\u003e\n```\n  \nP.S.: TablePagination is built inside utils and has some needed props. I've made it a reusable component in order to access it easily. Props needed:\n\n```javascript\n\u003cTablePaginationActions \n  count={items.length} //Total length of table items\n  rowsPerPage={10} // Current page (state controlled)\n  page={page} // # of rows shown per page\n  onChangePage={handleChangePage} //Function that will handle what happens when clicking the next/previous buttons\n/\u003e\n```\n\n#### 4.2.2. \u003cb\u003eAvgBoard\u003c/b\u003e ➗\n\nThis components loads the playerStore from redux that was accessed by the page Dashboard and passed through props and calculates the averages after the first render, then it renders a list of divs organizing as requested.\n\n```javascript\n\u003cAvgBoard \n  players={playerStore} //Redux players store\n/\u003e\n```\n\nInside the component we have all the logic that is needed.\n\n#### 4.2.3. \u003cb\u003ePlayersHighlight\u003c/b\u003e 🌟\n\nAs AvgBoard, it will access the playerStore passed from props and do his math. It uses the utils/ImageFromText.js to generate the image from given player name. If user access the teams and save players to new positions it will recalculate once going back to dashboard.\n\n```javascript\n\u003cPlayersHighlight \n  players={playerStore} //Redux players store\n/\u003e\n```\n\n### 4.3. \u003cb\u003eTeamEditor Page\u003c/b\u003e ✏️\n\nThere are two ways of accessing the TeamEditor page component. First if we access directly throug '\u003ci\u003e/team\u003c/i\u003e' route or '\u003ci\u003e/team/:id\u003c/i\u003e' route. In either way the components are the same, only changing it's content and save action.\n\nEg.: If you enter through '\u003ci\u003e/team\u003c/i\u003e' route you'll see the following title in rendered card\n\n![Create team title](https://sweetsoul.sirv.com/Images/venturus/create_team.png)\n\nNow if you enter through route that passes id as a URL param you'll see\n\n![Edit team title](https://sweetsoul.sirv.com/Images/venturus/edit_team.png)\n\nThat's one of the many content that are loaded dynamically. Most of them accessing the teamStore and retrieving the correct value for the specified field.\n\n#### 4.3.1. \u003cb\u003e TeamInfoForm \u003c/b\u003e\n\nReceives the two sections of inputs and perform some data gathering.\n\n#### 4.3.2. \u003cb\u003eTeam Information Section (TeamInformationSection.js)\u003c/b\u003e ✍️\n\nThis section of the page holds many fields that could be filled with team information or empty in case you're trying to add a new team. \u003cb\u003eVALIDATION OF THE FIELDS ARE ASYNCHRONOUS AND ON THE FLY, except Team type\u003c/b\u003e\n\n![Team info form](https://sweetsoul.sirv.com/Images/venturus/teamInfoForm.png)\n\nOn the left side we have a col holding two form inputs. Plain and simple. Just the Team name will be validated.  \nOn the right side there is two normal inputs, one text and one radio and a tag with a textarea. Team website is validated through  The expected behaviour is to add a new tag when the user press 'ENTER', ';' or try to click out of the field with text inside the input. In this particular field there is a simple validation of tags, if you try to put a tag that is already present it would not accept it.\n\n#### 4.3.3. \u003cb\u003eConfigure Squad Section(ConfigureSquadSection.js)\u003c/b\u003e ⚙️\n\nIn this section there is two cols, one with the formation select and the field (with the dropzone) and other with a serch input and the rendered cards of the players.\n\n![Configure Squad](https://sweetsoul.sirv.com/Images/venturus/configure_squad2.png)\n\nIf you change the formation, the field would arrange the drop zones accordingly.  \nTo assign a player, just drag its card and drop at spot that you want it to be. When doing this, it will generate an image with the First Name and Last Name letters. If you hover the player in field it will show a popover with further information of the player. As seen below. If you want to remove the player, you could just replace it for another player or click on it in the field.\n\n![Hover image](https://sweetsoul.sirv.com/Images/venturus/hover_field.png)\n\nYou will notice that uppon dragging the player and putting it into the field will remove it from the player list. And uppon entering some text in the search input you'll see the list being filtered by the name and everything working as they should.\n\n#### 4.3.4. \u003cb\u003eSave Button\u003c/b\u003e 💾\n\nThe save button will only be enabled if you change any information on the page. However, it will only save if you have filled the minimun required fields such as Team Name, Team Website and Team type fields.  \n\n#### 4.3.5. \u003cb\u003eUnsaved validation\u003c/b\u003e ⚠️\n\nIf you try to exit the page without saving and having made some change, it will trigger a modal showing you what you are about to do.  \n\n![ModalShown](https://sweetsoul.sirv.com/Images/venturus/modal.png)\n\n----\n\n## Testing Scope\n\nCoding...\n\n![Coding Gif](https://media.giphy.com/media/LmNwrBhejkK9EFP504/source.gif)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fogrodev%2Fsquad-management-tool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fogrodev%2Fsquad-management-tool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fogrodev%2Fsquad-management-tool/lists"}