├── src ├── api │ └── agent.js ├── features │ ├── Profile │ │ ├── profileSlice.js │ │ ├── Profile.css │ │ └── Profile.jsx │ ├── Missions │ │ ├── Missions.css │ │ ├── missionSlice.js │ │ └── Missions.jsx │ └── Rockets │ │ ├── Rockets.css │ │ ├── Rockets.jsx │ │ └── rocketSlice.js ├── App.css ├── setupTests.js ├── App.js ├── store │ └── store.js ├── reportWebVitals.js ├── index.css ├── index.js └── components │ ├── Navbar.css │ └── Navbar.jsx ├── README.old.md ├── public ├── robots.txt ├── favicon.ico ├── logo192.png ├── logo512.png ├── planet.png ├── manifest.json └── index.html ├── .babelrc ├── .stylelintrc.json ├── .eslintrc.json ├── LICENSE ├── package.json ├── .github └── workflows │ └── linters.yml ├── .gitignore └── README.md /src/api/agent.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.old.md: -------------------------------------------------------------------------------- 1 | # space-traveller-hub -------------------------------------------------------------------------------- /src/features/Profile/profileSlice.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .home { 2 | padding: 10px; 3 | } 4 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naledi-Dikgale/space-traveller-hub/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naledi-Dikgale/space-traveller-hub/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naledi-Dikgale/space-traveller-hub/HEAD/public/logo512.png -------------------------------------------------------------------------------- /public/planet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naledi-Dikgale/space-traveller-hub/HEAD/public/planet.png -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-react" 4 | ], 5 | "plugins": ["@babel/plugin-syntax-jsx"] 6 | } -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import React from 'react'; 3 | import Navbar from './components/Navbar'; 4 | 5 | function App() { 6 | return ( 7 |
8 |
9 | 10 |
11 |
12 | ); 13 | } 14 | 15 | export default App; 16 | -------------------------------------------------------------------------------- /src/store/store.js: -------------------------------------------------------------------------------- 1 | import { configureStore } from '@reduxjs/toolkit'; 2 | import { rocketSlice } from '../features/Rockets/rocketSlice'; 3 | import { missionSlice } from '../features/Missions/missionSlice'; 4 | 5 | export default configureStore({ 6 | reducer: { 7 | rockets: rocketSlice.reducer, 8 | missions: missionSlice.reducer, 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = (onPerfEntry) => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ 4 | getCLS, getFID, getFCP, getLCP, getTTFB, 5 | }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: 4 | -apple-system, 5 | BlinkMacSystemFont, 6 | 'Segoe UI', 7 | 'Roboto', 8 | 'Oxygen', 9 | 'Ubuntu', 10 | 'Cantarell', 11 | 'Fira Sans', 12 | 'Droid Sans', 13 | 'Helvetica Neue', 14 | sans-serif; 15 | -webkit-font-smoothing: antialiased; 16 | -moz-osx-font-smoothing: grayscale; 17 | } 18 | 19 | code { 20 | font-family: 21 | source-code-pro, 22 | Menlo, 23 | Monaco, 24 | Consolas, 25 | 'Courier New', 26 | monospace; 27 | } 28 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import { BrowserRouter } from 'react-router-dom'; 4 | import { Provider } from 'react-redux'; 5 | import store from './store/store'; 6 | 7 | import './index.css'; 8 | import App from './App'; 9 | 10 | const root = ReactDOM.createRoot(document.getElementById('root')); 11 | root.render( 12 | 13 | 14 | 15 | 16 | 17 | 18 | , 19 | ); 20 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/features/Profile/Profile.css: -------------------------------------------------------------------------------- 1 | .profile { 2 | display: flex; 3 | justify-content: space-around; 4 | } 5 | 6 | .listtitle { 7 | margin-bottom: 8px; 8 | padding: 0; 9 | font-size: xx-large; 10 | } 11 | 12 | .listbox { 13 | display: flex; 14 | flex-direction: column; 15 | text-align: start; 16 | width: 45%; 17 | height: auto; 18 | } 19 | 20 | .itemlist { 21 | all: unset; 22 | display: flex; 23 | flex-direction: column; 24 | justify-content: flex-end; 25 | } 26 | 27 | .listitems { 28 | border: 1px solid black; 29 | list-style: none; 30 | font-size: larger; 31 | height: auto; 32 | padding: 20px; 33 | } 34 | -------------------------------------------------------------------------------- /.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["stylelint-config-standard"], 3 | "plugins": ["stylelint-scss", "stylelint-csstree-validator"], 4 | "rules": { 5 | "at-rule-no-unknown": [ 6 | true, 7 | { 8 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"] 9 | } 10 | ], 11 | "scss/at-rule-no-unknown": [ 12 | true, 13 | { 14 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"] 15 | } 16 | ], 17 | "csstree/validator": true 18 | }, 19 | "ignoreFiles": ["build/**", "dist/**", "**/reset*.css", "**/bootstrap*.css", "**/*.js", "**/*.jsx"] 20 | } 21 | -------------------------------------------------------------------------------- /src/components/Navbar.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif; 3 | font-size: large; 4 | } 5 | 6 | .navbar { 7 | display: flex; 8 | flex-direction: column; 9 | height: 100px; 10 | } 11 | 12 | .navbar a { 13 | all: unset; 14 | } 15 | 16 | .navlist { 17 | display: flex; 18 | align-items: center; 19 | justify-content: space-between; 20 | } 21 | 22 | .navtitle { 23 | display: flex; 24 | align-items: center; 25 | } 26 | 27 | .logo { 28 | height: 80px; 29 | } 30 | 31 | .menu { 32 | padding-right: 80px; 33 | color: aqua; 34 | } 35 | 36 | .navitems { 37 | all: unset; 38 | padding: 6px; 39 | } 40 | 41 | .navitems:hover { 42 | text-align: center; 43 | cursor: pointer; 44 | text-decoration: underline; 45 | } 46 | 47 | .navitems a.active { 48 | text-decoration: underline; 49 | } 50 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "jest": true 6 | }, 7 | "parser": "@babel/eslint-parser", 8 | "parserOptions": { 9 | "ecmaFeatures": { 10 | "jsx": true 11 | }, 12 | "ecmaVersion": 2018, 13 | "sourceType": "module" 14 | }, 15 | "extends": ["airbnb", "plugin:react/recommended", "plugin:react-hooks/recommended"], 16 | "plugins": ["react"], 17 | "rules": { 18 | "react/jsx-filename-extension": ["warn", { "extensions": [".js", ".jsx"] }], 19 | "react/react-in-jsx-scope": "off", 20 | "import/no-unresolved": "off", 21 | "no-shadow": "off" 22 | }, 23 | "overrides": [ 24 | { 25 | // feel free to replace with your preferred file pattern - eg. 'src/**/*Slice.js' or 'redux/**/*Slice.js' 26 | "files": ["src/**/*Slice.js"], 27 | // avoid state param assignment 28 | "rules": { "no-param-reassign": ["error", { "props": false }] } 29 | } 30 | ], 31 | "ignorePatterns": [ 32 | "dist/", 33 | "build/" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /src/features/Profile/Profile.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './Profile.css'; 3 | import { useSelector } from 'react-redux'; 4 | 5 | function Profile() { 6 | const rockets = useSelector((state) => state.rockets.rockets.filter((elem) => elem.reserved)); 7 | const missions = useSelector((state) => state.missions.missions.filter((elem) => elem.joined)); 8 | return ( 9 |
10 |
11 |

My Missions

12 | 17 |
18 |
19 |

My Rockets

20 | 25 |
26 |
27 | ); 28 | } 29 | 30 | export default Profile; 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Naledi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/features/Missions/Missions.css: -------------------------------------------------------------------------------- 1 | .missions { 2 | padding: 25px; 3 | display: flex; 4 | justify-content: center; 5 | } 6 | 7 | table { 8 | width: 90%; 9 | border-right: 1px solid black; 10 | border-top: 1px solid black; 11 | border-bottom: 1px solid black; 12 | } 13 | 14 | tr:nth-child(odd) { 15 | background-color: #f1f2f2; 16 | } 17 | 18 | th { 19 | background-color: white !important; 20 | text-align: center; 21 | padding: 18px; 22 | border-left: 1px solid black; 23 | } 24 | 25 | td { 26 | text-align: center; 27 | padding: 18px; 28 | border-left: 1px solid black; 29 | } 30 | 31 | .mstatus { 32 | width: max-content; 33 | } 34 | 35 | td button { 36 | width: max-content; 37 | padding: 8px; 38 | border-radius: 5px; 39 | } 40 | 41 | .mstat { 42 | border: 1px solid black; 43 | border-radius: 5px; 44 | padding: 5px; 45 | width: max-content; 46 | color: white; 47 | font-weight: bolder; 48 | } 49 | 50 | .member { 51 | background-color: rgb(15, 112, 157); 52 | } 53 | 54 | .notmember { 55 | background-color: rgb(70, 72, 72); 56 | } 57 | 58 | .leavebtn { 59 | border: 2px solid red; 60 | } 61 | -------------------------------------------------------------------------------- /src/components/Navbar.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | NavLink, 4 | Routes, 5 | Route, 6 | } from 'react-router-dom'; 7 | import Profile from '../features/Profile/Profile'; 8 | import Missions from '../features/Missions/Missions'; 9 | import Rockets from '../features/Rockets/Rockets'; 10 | import './Navbar.css'; 11 | 12 | function Navbar() { 13 | return ( 14 |
15 | 41 |
42 | ); 43 | } 44 | 45 | export default Navbar; 46 | -------------------------------------------------------------------------------- /src/features/Rockets/Rockets.css: -------------------------------------------------------------------------------- 1 | .rockets { 2 | display: flex; 3 | flex-direction: column; 4 | } 5 | 6 | .rocketimg { 7 | height: 150px; 8 | aspect-ratio: 4 / 3; 9 | } 10 | 11 | .rocketTile { 12 | display: flex; 13 | align-items: center; 14 | padding: 10px; 15 | margin-bottom: 8px; 16 | } 17 | 18 | .reserved { 19 | margin-right: 10px; 20 | font-size: medium; 21 | background-color: rgb(51, 87, 219); 22 | color: white; 23 | width: fit-content; 24 | width: -moz-fit-content; 25 | padding: 6px; 26 | border-radius: 8px; 27 | font-weight: bolder; 28 | } 29 | 30 | .notReserved { 31 | display: none; 32 | } 33 | 34 | .rocketDetails { 35 | display: flex; 36 | flex-direction: column; 37 | justify-content: flex-start; 38 | align-items: flex-start; 39 | margin-left: 20px; 40 | } 41 | 42 | .rocketName { 43 | font-size: larger !important; 44 | margin: 0; 45 | } 46 | 47 | .rocketDescription { 48 | max-width: 800px; 49 | margin-top: 10px; 50 | margin-bottom: 10px; 51 | line-height: 28px; 52 | } 53 | 54 | .reserveButton { 55 | all: unset; 56 | padding: 8px; 57 | text-align: center; 58 | border-radius: 8px; 59 | color: white; 60 | width: fit-content; 61 | width: -moz-fit-content; 62 | } 63 | 64 | .reserveButton:hover { 65 | cursor: pointer; 66 | } 67 | 68 | .cancel { 69 | cursor: pointer; 70 | background-color: rgb(220, 224, 227); 71 | color: black; 72 | } 73 | 74 | .reserve { 75 | background-color: rgb(16, 77, 168); 76 | } 77 | -------------------------------------------------------------------------------- /src/features/Missions/missionSlice.js: -------------------------------------------------------------------------------- 1 | import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; 2 | import axios from 'axios'; 3 | 4 | const initialState = { 5 | missions: [], 6 | loading: false, 7 | error: '', 8 | }; 9 | 10 | export const fetchMissions = createAsyncThunk('missions/fetchmissions', () => axios.get('https://api.spacexdata.com/v3/missions') 11 | .then((response) => response.data.map((mission) => ( 12 | { 13 | mission_id: mission.mission_id, 14 | mission_name: mission.mission_name, 15 | mission_description: mission.description, 16 | joined: false, 17 | } 18 | )))); 19 | 20 | export const missionSlice = createSlice({ 21 | name: 'missions', 22 | initialState, 23 | reducers: { 24 | join: (state, action) => { 25 | const temp = []; 26 | state.missions.forEach((elem) => { 27 | if (elem.mission_id === action.payload) { 28 | temp.push({ ...elem, joined: !elem.joined }); 29 | } else { 30 | temp.push(elem); 31 | } 32 | }); 33 | return { ...state, missions: temp }; 34 | }, 35 | }, 36 | extraReducers: (builder) => { 37 | builder.addCase(fetchMissions.pending, (state) => ({ ...state, loading: true })); 38 | builder.addCase(fetchMissions.fulfilled, (state, action) => ({ 39 | ...state, loading: false, missions: action.payload, error: '', 40 | })); 41 | }, 42 | }); 43 | 44 | export const { join } = missionSlice.actions; 45 | export default missionSlice.reducer; 46 | -------------------------------------------------------------------------------- /src/features/Rockets/Rockets.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import './Rockets.css'; 3 | import { useSelector, useDispatch } from 'react-redux'; 4 | import { fetchRockets, reserve } from './rocketSlice'; 5 | 6 | function Rockets() { 7 | const rockets = useSelector((state) => state.rockets.rockets); 8 | const loading = useSelector((state) => state.rockets.loading); 9 | const dispatch = useDispatch(); 10 | useEffect(() => { 11 | if (rockets.length === 0) dispatch(fetchRockets()); 12 | }, []); 13 | if (loading) { 14 | return
Loading...
; 15 | } return ( 16 |
17 | { 18 | rockets.map((elem) => ( 19 |
20 | 21 |
22 |

{elem.rocket_name}

23 |

24 | Reserved 25 | {elem.rocket_description} 26 | 27 |

28 | 31 |
32 |
33 | )) 34 | } 35 |
36 | ); 37 | } 38 | 39 | export default Rockets; 40 | -------------------------------------------------------------------------------- /src/features/Rockets/rocketSlice.js: -------------------------------------------------------------------------------- 1 | import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; 2 | import axios from 'axios'; 3 | 4 | const initialState = { 5 | rockets: [], 6 | loading: false, 7 | error: '', 8 | }; 9 | 10 | export const fetchRockets = createAsyncThunk('rockets/fetchRockets', () => axios.get('https://api.spacexdata.com/v3/rockets') 11 | .then((response) => response.data.map((rocket) => ( 12 | { 13 | rocket_id: rocket.rocket_id, 14 | rocket_img: rocket.flickr_images[0], 15 | rocket_name: rocket.rocket_name, 16 | rocket_description: rocket.description, 17 | reserved: false, 18 | } 19 | )))); 20 | 21 | export const rocketSlice = createSlice({ 22 | name: 'rockets', 23 | initialState, 24 | reducers: { 25 | reserve: (state, action) => { 26 | const temp = []; 27 | state.rockets.forEach((rocket) => { 28 | if (rocket.rocket_id === action.payload) { 29 | temp.push({ ...rocket, reserved: !rocket.reserved }); 30 | // return { ...rocket, reserved: true }; 31 | } else { 32 | temp.push(rocket); 33 | } 34 | // return rocket; 35 | }); 36 | return { ...state, rockets: temp }; 37 | }, 38 | 39 | }, 40 | extraReducers: (builder) => { 41 | builder.addCase(fetchRockets.pending, (state) => ({ ...state, loading: true })); 42 | builder.addCase(fetchRockets.fulfilled, (state, action) => ({ 43 | ...state, loading: false, rockets: action.payload, error: '', 44 | })); 45 | }, 46 | }); 47 | 48 | export const { reserve } = rocketSlice.actions; 49 | export default rocketSlice.reducer; 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "space-traveller-hub", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@reduxjs/toolkit": "^1.9.5", 7 | "@testing-library/jest-dom": "^5.16.5", 8 | "@testing-library/react": "^13.4.0", 9 | "@testing-library/user-event": "^13.5.0", 10 | "axios": "^1.4.0", 11 | "react": "^18.2.0", 12 | "react-dom": "^18.2.0", 13 | "react-redux": "^8.0.5", 14 | "react-router-dom": "^6.11.1", 15 | "react-scripts": "5.0.1", 16 | "web-vitals": "^2.1.4" 17 | }, 18 | "scripts": { 19 | "start": "react-scripts start", 20 | "build": "react-scripts build", 21 | "test": "react-scripts test", 22 | "eject": "react-scripts eject" 23 | }, 24 | "eslintConfig": { 25 | "extends": [ 26 | "react-app", 27 | "react-app/jest" 28 | ] 29 | }, 30 | "browserslist": { 31 | "production": [ 32 | ">0.2%", 33 | "not dead", 34 | "not op_mini all" 35 | ], 36 | "development": [ 37 | "last 1 chrome version", 38 | "last 1 firefox version", 39 | "last 1 safari version" 40 | ] 41 | }, 42 | "devDependencies": { 43 | "@babel/core": "^7.21.8", 44 | "@babel/eslint-parser": "^7.21.8", 45 | "@babel/plugin-syntax-jsx": "^7.21.4", 46 | "@babel/preset-env": "^7.21.5", 47 | "@babel/preset-react": "^7.18.6", 48 | "eslint": "^7.32.0", 49 | "eslint-config-airbnb": "^18.2.1", 50 | "eslint-plugin-import": "^2.27.5", 51 | "eslint-plugin-jsx-a11y": "^6.7.1", 52 | "eslint-plugin-react": "^7.32.2", 53 | "eslint-plugin-react-hooks": "^4.6.0", 54 | "stylelint": "^13.13.1", 55 | "stylelint-config-standard": "^21.0.0", 56 | "stylelint-csstree-validator": "^1.9.0", 57 | "stylelint-scss": "^3.21.0" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/features/Missions/Missions.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import './Missions.css'; 3 | import { useSelector, useDispatch } from 'react-redux'; 4 | import { fetchMissions, join } from './missionSlice'; 5 | 6 | function Missions() { 7 | const missions = useSelector((state) => state.missions.missions); 8 | const loading = useSelector((state) => state.missions.loading); 9 | const dispatch = useDispatch(); 10 | useEffect(() => { 11 | if (missions.length === 0) dispatch(fetchMissions()); 12 | }, []); 13 | if (loading) { 14 | return
Loading...
; 15 | } return ( 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | { 28 | missions.map((elem) => ( 29 | 30 | 31 | 39 | 45 | 51 | 52 | )) 53 | } 54 | 55 | 56 |
MissionDescriptionStatus
{elem.mission_name} 32 | {' '} 33 |

34 | {' '} 35 | {elem.mission_description} 36 | {' '} 37 |

38 |
40 | { 41 | elem.joined ?

A member

:

Not a member

42 | } 43 | 44 |
46 | 49 | 50 |
57 |
58 | ); 59 | } 60 | 61 | export default Missions; 62 | -------------------------------------------------------------------------------- /.github/workflows/linters.yml: -------------------------------------------------------------------------------- 1 | name: Linters 2 | 3 | on: pull_request 4 | 5 | env: 6 | FORCE_COLOR: 1 7 | 8 | jobs: 9 | eslint: 10 | name: ESLint 11 | runs-on: ubuntu-22.04 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: actions/setup-node@v3 15 | with: 16 | node-version: "18.x" 17 | - name: Setup ESLint 18 | run: | 19 | npm install --save-dev eslint@7.x eslint-config-airbnb@18.x eslint-plugin-import@2.x eslint-plugin-jsx-a11y@6.x eslint-plugin-react@7.x eslint-plugin-react-hooks@4.x @babel/eslint-parser@7.x @babel/core@7.x @babel/plugin-syntax-jsx@7.x @babel/preset-env@7.x @babel/preset-react@7.x 20 | [ -f .eslintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.eslintrc.json 21 | [ -f .babelrc ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.babelrc 22 | - name: ESLint Report 23 | run: npx eslint "**/*.{js,jsx}" 24 | stylelint: 25 | name: Stylelint 26 | runs-on: ubuntu-22.04 27 | steps: 28 | - uses: actions/checkout@v3 29 | - uses: actions/setup-node@v3 30 | with: 31 | node-version: "18.x" 32 | - name: Setup Stylelint 33 | run: | 34 | npm install --save-dev stylelint@13.x stylelint-scss@3.x stylelint-config-standard@21.x stylelint-csstree-validator@1.x 35 | [ -f .stylelintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.stylelintrc.json 36 | - name: Stylelint Report 37 | run: npx stylelint "**/*.{css,scss}" 38 | nodechecker: 39 | name: node_modules checker 40 | runs-on: ubuntu-22.04 41 | steps: 42 | - uses: actions/checkout@v3 43 | - name: Check node_modules existence 44 | run: | 45 | if [ -d "node_modules/" ]; then echo -e "\e[1;31mThe node_modules/ folder was pushed to the repo. Please remove it from the GitHub repository and try again."; echo -e "\e[1;32mYou can set up a .gitignore file with this folder included on it to prevent this from happening in the future." && exit 1; fi 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # TernJS port file 120 | .tern-port 121 | 122 | # Stores VSCode versions used for testing VSCode extensions 123 | .vscode-test 124 | 125 | # yarn v2 126 | .yarn/cache 127 | .yarn/unplugged 128 | .yarn/build-state.yml 129 | .yarn/install-state.gz 130 | .pnp.* 131 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 132 | 133 | # dependencies 134 | /node_modules 135 | /.pnp 136 | .pnp.js 137 | 138 | # testing 139 | /coverage 140 | 141 | # production 142 | /build 143 | 144 | # misc 145 | .DS_Store 146 | .env.local 147 | .env.development.local 148 | .env.test.local 149 | .env.production.local 150 | 151 | npm-debug.log* 152 | yarn-debug.log* 153 | yarn-error.log* 154 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 📗 Table of Contents 4 | 5 | - [📖 About the Project](#about-project) 6 | - [🛠 Built With](#built-with) 7 | - [Video Walkthrough](#video-walkthrough) 8 | - [Tech Stack](#tech-stack) 9 | - [Key Features](#key-features) 10 | - [💻 Getting Started](#getting-started) 11 | - [Setup](#setup) 12 | - [Prerequisites](#prerequisites) 13 | - [Install](#install) 14 | - [Usage](#usage) 15 | - [Run tests](#run-tests) 16 | - [Deployment](#triangular_flag_on_post-deployment) 17 | - [👥 Authors](#authors) 18 | - [🔭 Future Features](#future-features) 19 | - [🤝 Contributing](#contributing) 20 | - [⭐️ Show your support](#support) 21 | - [🙏 Acknowledgements](#acknowledgements) 22 | - [❓ FAQ (OPTIONAL)](#faq) 23 | - [📝 License](#license) 24 | 25 | 26 | 27 | # 📖 Space Travelers' Hub 28 | 29 | 30 | **Space Travelers' Hub** "Space Travelers hub" is aa web application for a company that provides commercial and scientific space travel services. The application will allow users to book rockets and join selected space missions. 31 | 32 | 33 | ## 🛠 Built With Create React App 34 | 35 | 36 | ### Key Features 37 | 38 | - **Project setup with Create React App** 39 | 40 |

(back to top)

41 | 42 | ## 💻 Getting Started 43 | 44 | Try to have these in your local machine 45 | 46 | - Git and GitHub 47 | - VS Code or any code editor 48 | 49 | ### Prerequisites 50 | 51 | In order to run this project you need 52 | - A web browser 53 | - Code editor 54 | 55 | ### Setup 56 | 57 | Clone this repository to your desired folder: 58 | 59 | git clone (https://github.com/Amazinggracee/rocket-mission) 60 | 61 | ### Install 62 | 63 | Install this project using the cloned repo or download and use the files to your local machine. 64 | 65 | ### Usage 66 | 67 | - Clone the repository first 68 | - Commnads to Run: 69 | - npm install 70 | - npm run build 71 | - npm start 72 | 73 | ### Run tests 74 | 75 | - tests are included using Jest framework 76 | - commands to run: npm run test 77 | 78 | ### Deployment 79 | 80 | You can deploy this project through Github Pages 81 | 82 |

(back to top)

83 | 84 | 85 | 86 | ## 👥 Authors 87 | 88 | 👤 **Naledi Dikgale** 89 | 90 | - GitHub: [@githubhandle](https://github.com/Naledi-Dikgale) 91 | - Twitter: [@twitterhandle](https://twitter.com/ChichiTheStar) 92 | - LinkedIn: [LinkedIn](https://www.linkedin.com/in/naledi-dikgale-068423159/) 93 | - Website: [@naledi_dikgale](https://nalediportfolio.netlify.app/) 94 | 95 | 96 |

(back to top)

97 | 98 | ## 🔭 Future Features 99 | 100 | - [ ] **Changes will be made as comming project requirement.** 101 | 102 |

(back to top)

103 | 104 | 105 | 106 | ## 🤝 Contributing 107 | 108 | Contributions, issues, and feature requests are welcome! 109 | 110 | Feel free to check the [issues page](../../issues/). 111 | 112 |

(back to top)

113 | 114 | ## ⭐️ Show your support 115 | 116 | If you like this project give a star to this repositiory. 117 | 118 |

(back to top)

119 | 120 | ## 🙏 Acknowledgments 121 | 122 | - I would also like to thank Microverse for the guidance they made all the way up to this point. 123 | 124 |

(back to top)

125 | 126 | ## ❓ FAQ 127 | 128 | - **Is it allowed to copy the contents of this project and use it for personal use?** 129 | 130 | - This project is free for copying and reusing in any way you like. 131 | 132 | ## 📝 License 133 | 134 | This project is [MIT](/LICENSE.md) licensed. 135 | 136 |

(back to top)

137 | --------------------------------------------------------------------------------