diff --git a/package-lock.json b/package-lock.json index 1f425f5..5accf57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,8 @@ "eslint-plugin-import": "^2.25.3", "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-react": "^7.27.1", - "eslint-plugin-react-hooks": "^4.3.0" + "eslint-plugin-react-hooks": "^4.3.0", + "mkcert": "^3.2.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -10804,6 +10805,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mkcert": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mkcert/-/mkcert-3.2.0.tgz", + "integrity": "sha512-026Eivq9RoOjOuLJGzbhGwXUAjBxRX11Z7Jbm4/7lqT/Av+XNy9SPrJte6+UpEt7i+W3e/HZYxQqlQcqXZWSzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^11.0.0", + "node-forge": "^1.3.1" + }, + "bin": { + "mkcert": "dist/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/mkcert/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -23742,6 +23770,24 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, + "mkcert": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mkcert/-/mkcert-3.2.0.tgz", + "integrity": "sha512-026Eivq9RoOjOuLJGzbhGwXUAjBxRX11Z7Jbm4/7lqT/Av+XNy9SPrJte6+UpEt7i+W3e/HZYxQqlQcqXZWSzg==", + "dev": true, + "requires": { + "commander": "^11.0.0", + "node-forge": "^1.3.1" + }, + "dependencies": { + "commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true + } + } + }, "mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", diff --git a/package.json b/package.json index 1d9863d..2b81a01 100644 --- a/package.json +++ b/package.json @@ -1,47 +1,49 @@ { - "name": "website-react", - "version": "0.1.0", - "private": true, - "homepage": "https://waterloorocketry.com", - "dependencies": { - "@fortawesome/fontawesome-free": "^6.6.0", - "@fortawesome/free-solid-svg-icons": "^6.6.0", - "@fortawesome/react-fontawesome": "^0.2.2", - "@testing-library/jest-dom": "^5.16.1", - "@testing-library/react": "^11.2.7", - "@testing-library/user-event": "^12.8.3", - "bootstrap": "^5.3.1", - "react": "^17.0.2", - "react-bootstrap": "^2.0.3", - "react-dom": "^17.0.2", - "react-helmet": "^6.1.0", - "react-router-dom": "^6.1.1", - "react-scripts": "^5.0.1", - "web-vitals": "^1.1.2" - }, - "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", - "eject": "react-scripts eject" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - }, - "devDependencies": { - "eslint-config-airbnb": "^19.0.2", - "eslint-plugin-import": "^2.25.3", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.27.1", - "eslint-plugin-react-hooks": "^4.3.0" - } + "name": "website-react", + "version": "0.1.0", + "private": true, + "homepage": "https://waterloorocketry.com", + "dependencies": { + "@fortawesome/fontawesome-free": "^6.6.0", + "@fortawesome/free-solid-svg-icons": "^6.6.0", + "@fortawesome/react-fontawesome": "^0.2.2", + "@testing-library/jest-dom": "^5.16.1", + "@testing-library/react": "^11.2.7", + "@testing-library/user-event": "^12.8.3", + "bootstrap": "^5.3.1", + "react": "^17.0.2", + "react-bootstrap": "^2.0.3", + "react-dom": "^17.0.2", + "react-helmet": "^6.1.0", + "react-router-dom": "^6.1.1", + "react-scripts": "^5.0.1", + "web-vitals": "^1.1.2" + }, + "scripts": { + "start": "react-scripts start", + "start-https": "set HTTPS=true&&set SSL_CRT_FILE=cert.pem&&set SSL_KEY_FILE=key.pem&&react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "devDependencies": { + "eslint-config-airbnb": "^19.0.2", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.27.1", + "eslint-plugin-react-hooks": "^4.3.0", + "mkcert": "^3.2.0" + } } diff --git a/public/index.html b/public/index.html index e537ccb..618bf3f 100644 --- a/public/index.html +++ b/public/index.html @@ -1,42 +1,71 @@ - - - - - - - - - - Waterloo Rocketry - - - -
- + + + + + + + + + + + Waterloo Rocketry + + + +
+ diff --git a/public/service-worker.js b/public/service-worker.js new file mode 100644 index 0000000..e77027c --- /dev/null +++ b/public/service-worker.js @@ -0,0 +1,71 @@ +// Cache name - update this when you want to force cache refresh +const CACHE_NAME = "waterloo-rocketry-v1"; + +// Files to cache +const urlsToCache = [ + "/", + "/index.html", + "/manifest.json", + "/favicon.ico", + "/logo192.png", + "/logo512.png", +]; + +// Install service worker and cache files +self.addEventListener("install", (event) => { + event.waitUntil( + caches.open(CACHE_NAME).then((cache) => { + return cache.addAll(urlsToCache); + }) + ); +}); + +// Fetch cached resources +self.addEventListener("fetch", (event) => { + event.respondWith( + caches.match(event.request).then((response) => { + // Cache hit - return response + if (response) { + return response; + } + + // Clone the request because it's a stream and can only be consumed once + const fetchRequest = event.request.clone(); + + return fetch(fetchRequest).then((response) => { + // Check if we received a valid response + if ( + !response || + response.status !== 200 || + response.type !== "basic" + ) { + return response; + } + + // Clone the response because it's a stream and can only be consumed once + const responseToCache = response.clone(); + + caches.open(CACHE_NAME).then((cache) => { + cache.put(event.request, responseToCache); + }); + + return response; + }); + }) + ); +}); + +// Clean up old caches when a new service worker takes over +self.addEventListener("activate", (event) => { + event.waitUntil( + caches.keys().then((cacheNames) => { + return Promise.all( + cacheNames.map((cacheName) => { + if (cacheName !== CACHE_NAME) { + return caches.delete(cacheName); + } + }) + ); + }) + ); +}); diff --git a/src/index.jsx b/src/index.jsx index da023ce..3cb52b5 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -1,170 +1,276 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import { - Route, BrowserRouter, Routes, -} from 'react-router-dom'; +import React from "react"; +import ReactDOM from "react-dom"; +import { Route, BrowserRouter, Routes } from "react-router-dom"; -import Navigation from './components/Navigation/Navigation'; -import Page from './components/Page'; -import Redirect from './components/Redirect/Redirect'; +import Navigation from "./components/Navigation/Navigation"; +import Page from "./components/Page"; +import Redirect from "./components/Redirect/Redirect"; // pages -import Home from './routes/Home'; -import Competition from './routes/Competition'; -import Join from './routes/Join'; -import Awards from './routes/Awards'; +import Home from "./routes/Home"; +import Competition from "./routes/Competition"; +import Join from "./routes/Join"; +import Awards from "./routes/Awards"; -import Rockets from './routes/Rockets'; -import Sponsors from './routes/Sponsors'; -import Subsystems from './routes/Subsystems'; -import Team from './routes/Team'; -import Outreach from './routes/Outreach'; -import Contact from './routes/Contact'; -import Documentation from './routes/Documentation'; +import Rockets from "./routes/Rockets"; +import Sponsors from "./routes/Sponsors"; +import Subsystems from "./routes/Subsystems"; +import Team from "./routes/Team"; +import Outreach from "./routes/Outreach"; +import Contact from "./routes/Contact"; +import Documentation from "./routes/Documentation"; -import Footer from './components/Footer/Footer'; +import Footer from "./components/Footer/Footer"; -import Borealis from './routes/rocketPages/Borealis'; -import LeviathanOfTheSky from './routes/rocketPages/LeviathanOfTheSky'; -import KrakenOfTheSky from './routes/rocketPages/KrakenOfTheSky'; -import SharkOfTheSky from './routes/rocketPages/SharkOfTheSky'; -import UnexplodedOrdnance from './routes/rocketPages/UnexplodedOrdnance'; -import Vidar3 from './routes/rocketPages/Vidar3'; -import Vidar2 from './routes/rocketPages/Vidar2'; -import Vidar from './routes/rocketPages/Vidar'; -import SilverBrant from './routes/rocketPages/SilverBrant'; -import Eridani from './routes/rocketPages/Eridani'; -import WRT1 from './routes/rocketPages/WRT1'; -import ScrollToTop from './components/ScrollToTop/ScrollToTop'; +import Borealis from "./routes/rocketPages/Borealis"; +import LeviathanOfTheSky from "./routes/rocketPages/LeviathanOfTheSky"; +import KrakenOfTheSky from "./routes/rocketPages/KrakenOfTheSky"; +import SharkOfTheSky from "./routes/rocketPages/SharkOfTheSky"; +import UnexplodedOrdnance from "./routes/rocketPages/UnexplodedOrdnance"; +import Vidar3 from "./routes/rocketPages/Vidar3"; +import Vidar2 from "./routes/rocketPages/Vidar2"; +import Vidar from "./routes/rocketPages/Vidar"; +import SilverBrant from "./routes/rocketPages/SilverBrant"; +import Eridani from "./routes/rocketPages/Eridani"; +import WRT1 from "./routes/rocketPages/WRT1"; +import ScrollToTop from "./components/ScrollToTop/ScrollToTop"; -import 'bootstrap/dist/css/bootstrap.min.css'; -import './index.css'; +import "bootstrap/dist/css/bootstrap.min.css"; +import "./index.css"; ReactDOM.render( - - - - - - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - } - /> - -