diff --git a/api/main_endpoints/models/Visit.js b/api/main_endpoints/models/Visit.js new file mode 100644 index 000000000..b23643e42 --- /dev/null +++ b/api/main_endpoints/models/Visit.js @@ -0,0 +1,19 @@ +const mongoose = require('mongoose'); +const Schema = mongoose.Schema; + +const VisitSchema = new Schema( + { + visitCount: { + type: Number, + default: 0 + }, + type: { + type: String, + enum: ['HOME_PAGE'], + default: 'HOME_PAGE' + } + }, + { collection: 'Visit' } +); + +module.exports = mongoose.model('Visit', VisitSchema); diff --git a/api/main_endpoints/routes/Visit.js b/api/main_endpoints/routes/Visit.js new file mode 100644 index 000000000..d10150784 --- /dev/null +++ b/api/main_endpoints/routes/Visit.js @@ -0,0 +1,41 @@ +const express = require ('express'); +const router = express.Router(); +const Visit = require('../models/Visit'); +const { NOT_FOUND, FORBIDDEN, BAD_REQUEST, OK } = require('../../util/constants').STATUS_CODES; +const SCE_SJSU_EDU = 'https://sce.sjsu.edu'; +const pages = Visit.schema.path('type').enumValues; + +router.post('/:type', async (req, res) => { + if (process.env.NODE_ENV === 'production') { + const origin = req.get('origin'); + const referer = req.get('referer'); + const allowed = origin === SCE_SJSU_EDU || (referer && referer.startsWith(allowedOrigin)); + if(!allowed) return res.sendStatus(FORBIDDEN); + } + const {type} = req.params; + if(!pages.includes(type)) return res.sendStatus(NOT_FOUND); + try { + await Visit.findOneAndUpdate( + {type}, + {$inc: {visitCount: 1}}, + {new: true, upsert: true} + ); + res.sendStatus(OK); + } catch (error) { + res.sendStatus(BAD_REQUEST); + } +}); + +router.get('/:type', async (req, res) => { + const {type} = req.params; + if(!pages.includes(type)) return res.sendStatus(NOT_FOUND); + try { + const response = await Visit.findOne({type}); + const visitCount = response ? response.visitCount : 0; + return res.status(OK).send({visitCount}); + } catch (error) { + return res.sendStatus(BAD_REQUEST); + } +}); + +module.exports = router; diff --git a/src/APIFunctions/Visit.js b/src/APIFunctions/Visit.js new file mode 100644 index 000000000..d931ca0e0 --- /dev/null +++ b/src/APIFunctions/Visit.js @@ -0,0 +1,42 @@ +import { ApiResponse } from './ApiResponses'; +import { BASE_API_URL } from '../Enums'; + +export async function incrementVisitCount(type) { + let status = new ApiResponse(); + try { + const url = new URL(`api/Visit/${type}`, BASE_API_URL); + await fetch (url.href, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }); + if (res.ok) { + status.responseData = result; + } else { + status.error = true; + } + } catch (err) { + status.responseData = err; + status.error = true; + } + return status; +} + +export async function getVisitCount(type) { + let status = new ApiResponse(); + try { + const url = new URL(`api/Visit/${type}`, BASE_API_URL); + const res = await fetch (url.href); + if (res.ok) { + const result = await res.json(); + status.responseData = result; + } else { + status.error = true; + } + } catch (err) { + status.responseData = err; + status.error = true; + } + return status; +} diff --git a/src/Pages/Home/Home.js b/src/Pages/Home/Home.js index 53b42e00d..9bace9ca7 100755 --- a/src/Pages/Home/Home.js +++ b/src/Pages/Home/Home.js @@ -3,12 +3,15 @@ import Footer from '../../Components/Footer/Footer.js'; import './Home.css'; import { getAd } from '../../APIFunctions/Advertisement.js'; +import { incrementVisitCount, getVisitCount } from '../../APIFunctions/Visit.js'; const Home = () => { const [message, setMessage] = useState(''); const [showMessage, setShowMessage] = useState(false); const [showAll, setShowAll] = useState(false); + const [visitCount, setVisitCount] = useState(0); + async function getMessage() { try { const messageData = await getAd(); @@ -20,8 +23,16 @@ const Home = () => { } } + async function loadVisitCounter() { + const type = 'HOME_PAGE'; + await incrementVisitCount(type); + const response = await getVisitCount(type); + if(!response.error) setVisitCount(response.responseData.visitCount); + } + useEffect(() => { getMessage(); + loadVisitCounter(); setTimeout(() => setShowAll(true), 100); }, []); @@ -96,6 +107,10 @@ const Home = () => { +
+ Visit Count: {visitCount} +
+