From 06dfaa94fabd73440ad8ad0eaae5b752de6c51c2 Mon Sep 17 00:00:00 2001 From: Jay Timbol Date: Mon, 29 Dec 2025 20:22:44 -0600 Subject: [PATCH 1/9] homepage image endpoint + random image on home screen --- api/main_endpoints/routes/Homepage.js | 24 ++++++++++++++++++++++++ src/APIFunctions/Homepage.js | 20 ++++++++++++++++++++ src/Pages/Home/Home.js | 20 +++++++++++++++++--- 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 api/main_endpoints/routes/Homepage.js create mode 100644 src/APIFunctions/Homepage.js diff --git a/api/main_endpoints/routes/Homepage.js b/api/main_endpoints/routes/Homepage.js new file mode 100644 index 000000000..1e64346c0 --- /dev/null +++ b/api/main_endpoints/routes/Homepage.js @@ -0,0 +1,24 @@ +const express = require ('express'); +const router = express.Router(); +const { OK, NOT_FOUND } = require('../../util/constants').STATUS_CODES; + +//sample images (all from openverse.org) for now!! +const imageUrls = [ + {url: "https://live.staticflickr.com/14/19329415_09b1eae0e8_b.jpg", label: "2025 internship"}, + {url: "https://live.staticflickr.com/2182/2377582173_89e0ca2f83_b.jpg", label: "empty room"}, + {url: "https://live.staticflickr.com/4045/4339898436_8283d8be54_b.jpg", label: "full room"}, + {url: "https://live.staticflickr.com/102/298812490_b57db6f58b_b.jpg", label: "decorating room"}, + {url: "https://live.staticflickr.com/204/468095839_bba3fc0e30_b.jpg", label: "office"}, + {url: "https://live.staticflickr.com/7208/14133744683_ae04e8f1e4_b.jpg", label: "dev team collaboration"}, +]; + +const getRandomImage = () => { + return imageUrls[Math.floor(Math.random() * imageUrls.length)]; +} + +router.get('/image', (req, res) => { + if(imageUrls.length === 0) return res.sendStatus(NOT_FOUND); + res.status(OK).send(getRandomImage().url); +}); + +module.exports = router; \ No newline at end of file diff --git a/src/APIFunctions/Homepage.js b/src/APIFunctions/Homepage.js new file mode 100644 index 000000000..6dff4d98f --- /dev/null +++ b/src/APIFunctions/Homepage.js @@ -0,0 +1,20 @@ +import { ApiResponse } from './ApiResponses'; +import { BASE_API_URL } from '../Enums'; + +export async function getHomeImageUrl() { + let status = new ApiResponse(); + try { + console.log(BASE_API_URL + 'api/Homepage/image'); + const res = await fetch (BASE_API_URL + 'api/Homepage/image'); + if (res.ok) { + const result = await res.text(); + status.responseData = result; + } else { + status.error = true; + } + } catch (err) { + status.responseData = err; + status.error = true; + } + return status; +} \ No newline at end of file diff --git a/src/Pages/Home/Home.js b/src/Pages/Home/Home.js index 9f9223f30..f6653150d 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 { getHomeImageUrl } from '../../APIFunctions/Homepage.js'; const Home = () => { const [message, setMessage] = useState(''); const [showMessage, setShowMessage] = useState(false); const [showAll, setShowAll] = useState(false); + const [homeImageUrl, setHomeImageUrl] = useState(''); + async function getMessage() { try { const messageData = await getAd(); @@ -20,8 +23,19 @@ const Home = () => { } } + async function loadHomeImage() { + const response = await getHomeImageUrl(); + const url = response.responseData; + if (!response.error && url) { + setHomeImageUrl(url.trim()); + } else { //old image if error + setHomeImageUrl('https://raw.githubusercontent.com/thebeninator/Clark/refs/heads/add_comp_homepage/public/images/compressed2.jpg'); + } + } + useEffect(() => { getMessage(); + loadHomeImage(); setTimeout(() => setShowAll(true), 100); }, []); @@ -91,9 +105,9 @@ const Home = () => {
+ className="w-full mx-auto transform md:w-4/5 rounded-xl" + src={homeImageUrl} + />
{renderMessageWithLinks(message)} From 72689072a4d11425ec113272385c4096093dd258 Mon Sep 17 00:00:00 2001 From: Jay Timbol Date: Mon, 29 Dec 2025 22:58:01 -0600 Subject: [PATCH 2/9] move array + helper fcn to util file --- api/main_endpoints/routes/Homepage.js | 20 ++++---------------- api/main_endpoints/util/HomepageImages.js | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 16 deletions(-) create mode 100644 api/main_endpoints/util/HomepageImages.js diff --git a/api/main_endpoints/routes/Homepage.js b/api/main_endpoints/routes/Homepage.js index 1e64346c0..7e7a1cfaf 100644 --- a/api/main_endpoints/routes/Homepage.js +++ b/api/main_endpoints/routes/Homepage.js @@ -1,24 +1,12 @@ const express = require ('express'); const router = express.Router(); const { OK, NOT_FOUND } = require('../../util/constants').STATUS_CODES; - -//sample images (all from openverse.org) for now!! -const imageUrls = [ - {url: "https://live.staticflickr.com/14/19329415_09b1eae0e8_b.jpg", label: "2025 internship"}, - {url: "https://live.staticflickr.com/2182/2377582173_89e0ca2f83_b.jpg", label: "empty room"}, - {url: "https://live.staticflickr.com/4045/4339898436_8283d8be54_b.jpg", label: "full room"}, - {url: "https://live.staticflickr.com/102/298812490_b57db6f58b_b.jpg", label: "decorating room"}, - {url: "https://live.staticflickr.com/204/468095839_bba3fc0e30_b.jpg", label: "office"}, - {url: "https://live.staticflickr.com/7208/14133744683_ae04e8f1e4_b.jpg", label: "dev team collaboration"}, -]; - -const getRandomImage = () => { - return imageUrls[Math.floor(Math.random() * imageUrls.length)]; -} +const { getRandomImageUrl } = require('../util/HomepageImages'); router.get('/image', (req, res) => { - if(imageUrls.length === 0) return res.sendStatus(NOT_FOUND); - res.status(OK).send(getRandomImage().url); + const url = getRandomImageUrl(); + if(!url) return res.sendStatus(NOT_FOUND); + res.status(OK).send(url); }); module.exports = router; \ No newline at end of file diff --git a/api/main_endpoints/util/HomepageImages.js b/api/main_endpoints/util/HomepageImages.js new file mode 100644 index 000000000..6adf30c3e --- /dev/null +++ b/api/main_endpoints/util/HomepageImages.js @@ -0,0 +1,16 @@ +//sample images (all from openverse.org) for now!! +const imageUrls = [ + {url: "https://live.staticflickr.com/14/19329415_09b1eae0e8_b.jpg", label: "2025 internship"}, + {url: "https://live.staticflickr.com/2182/2377582173_89e0ca2f83_b.jpg", label: "empty room"}, + {url: "https://live.staticflickr.com/4045/4339898436_8283d8be54_b.jpg", label: "full room"}, + {url: "https://live.staticflickr.com/102/298812490_b57db6f58b_b.jpg", label: "decorating room"}, + {url: "https://live.staticflickr.com/204/468095839_bba3fc0e30_b.jpg", label: "office"}, + {url: "https://live.staticflickr.com/7208/14133744683_ae04e8f1e4_b.jpg", label: "dev team collaboration"}, +]; + +const getRandomImageUrl = () => { + if(imageUrls.length === 0) return null; + return imageUrls[Math.floor(Math.random() * imageUrls.length)].url; +} + +module.exports = {imageUrls, getRandomImageUrl}; \ No newline at end of file From 3d49261e408eca6e10e3d7968a80e22ebe8c145b Mon Sep 17 00:00:00 2001 From: Jay Timbol Date: Wed, 31 Dec 2025 15:27:01 -0600 Subject: [PATCH 3/9] homepage image endpoint returns url and alt; update file names --- api/main_endpoints/routes/Homepage.js | 12 -------- .../HomepageImages.js => routes/Image.js} | 28 +++++++++++++------ src/APIFunctions/{Homepage.js => Image.js} | 7 ++--- src/Pages/Home/Home.js | 19 ++++++++----- 4 files changed, 34 insertions(+), 32 deletions(-) delete mode 100644 api/main_endpoints/routes/Homepage.js rename api/main_endpoints/{util/HomepageImages.js => routes/Image.js} (50%) rename src/APIFunctions/{Homepage.js => Image.js} (63%) diff --git a/api/main_endpoints/routes/Homepage.js b/api/main_endpoints/routes/Homepage.js deleted file mode 100644 index 7e7a1cfaf..000000000 --- a/api/main_endpoints/routes/Homepage.js +++ /dev/null @@ -1,12 +0,0 @@ -const express = require ('express'); -const router = express.Router(); -const { OK, NOT_FOUND } = require('../../util/constants').STATUS_CODES; -const { getRandomImageUrl } = require('../util/HomepageImages'); - -router.get('/image', (req, res) => { - const url = getRandomImageUrl(); - if(!url) return res.sendStatus(NOT_FOUND); - res.status(OK).send(url); -}); - -module.exports = router; \ No newline at end of file diff --git a/api/main_endpoints/util/HomepageImages.js b/api/main_endpoints/routes/Image.js similarity index 50% rename from api/main_endpoints/util/HomepageImages.js rename to api/main_endpoints/routes/Image.js index 6adf30c3e..2e37915c3 100644 --- a/api/main_endpoints/util/HomepageImages.js +++ b/api/main_endpoints/routes/Image.js @@ -1,16 +1,26 @@ +const express = require ('express'); +const router = express.Router(); +const { OK, NOT_FOUND } = require('../../util/constants').STATUS_CODES; + //sample images (all from openverse.org) for now!! const imageUrls = [ - {url: "https://live.staticflickr.com/14/19329415_09b1eae0e8_b.jpg", label: "2025 internship"}, - {url: "https://live.staticflickr.com/2182/2377582173_89e0ca2f83_b.jpg", label: "empty room"}, - {url: "https://live.staticflickr.com/4045/4339898436_8283d8be54_b.jpg", label: "full room"}, - {url: "https://live.staticflickr.com/102/298812490_b57db6f58b_b.jpg", label: "decorating room"}, - {url: "https://live.staticflickr.com/204/468095839_bba3fc0e30_b.jpg", label: "office"}, - {url: "https://live.staticflickr.com/7208/14133744683_ae04e8f1e4_b.jpg", label: "dev team collaboration"}, + {url: "https://live.staticflickr.com/14/19329415_09b1eae0e8_b.jpg", alt: "2025 internship"}, + {url: "https://live.staticflickr.com/2182/2377582173_89e0ca2f83_b.jpg", alt: "empty room"}, + {url: "https://live.staticflickr.com/4045/4339898436_8283d8be54_b.jpg", alt: "full room"}, + {url: "https://live.staticflickr.com/102/298812490_b57db6f58b_b.jpg", alt: "decorating room"}, + {url: "https://live.staticflickr.com/204/468095839_bba3fc0e30_b.jpg", alt: "office"}, + {url: "https://live.staticflickr.com/7208/14133744683_ae04e8f1e4_b.jpg", alt: "dev team collaboration"}, ]; -const getRandomImageUrl = () => { +const getRandomImage = () => { if(imageUrls.length === 0) return null; - return imageUrls[Math.floor(Math.random() * imageUrls.length)].url; + return imageUrls[Math.floor(Math.random() * imageUrls.length)]; } -module.exports = {imageUrls, getRandomImageUrl}; \ No newline at end of file +router.get('/Homepage', (req, res) => { + const image = getRandomImage(); + if(!image) return res.sendStatus(NOT_FOUND); + res.status(OK).send(image); +}); + +module.exports = router; \ No newline at end of file diff --git a/src/APIFunctions/Homepage.js b/src/APIFunctions/Image.js similarity index 63% rename from src/APIFunctions/Homepage.js rename to src/APIFunctions/Image.js index 6dff4d98f..b50bd9b35 100644 --- a/src/APIFunctions/Homepage.js +++ b/src/APIFunctions/Image.js @@ -1,13 +1,12 @@ import { ApiResponse } from './ApiResponses'; import { BASE_API_URL } from '../Enums'; -export async function getHomeImageUrl() { +export async function getHomeImage() { let status = new ApiResponse(); try { - console.log(BASE_API_URL + 'api/Homepage/image'); - const res = await fetch (BASE_API_URL + 'api/Homepage/image'); + const res = await fetch (BASE_API_URL + 'api/Image/Homepage'); if (res.ok) { - const result = await res.text(); + const result = await res.json(); status.responseData = result; } else { status.error = true; diff --git a/src/Pages/Home/Home.js b/src/Pages/Home/Home.js index f6653150d..45e7dd731 100755 --- a/src/Pages/Home/Home.js +++ b/src/Pages/Home/Home.js @@ -3,7 +3,7 @@ import Footer from '../../Components/Footer/Footer.js'; import './Home.css'; import { getAd } from '../../APIFunctions/Advertisement.js'; -import { getHomeImageUrl } from '../../APIFunctions/Homepage.js'; +import { getHomeImage } from '../../APIFunctions/Image.js'; const Home = () => { @@ -11,6 +11,7 @@ const Home = () => { const [showMessage, setShowMessage] = useState(false); const [showAll, setShowAll] = useState(false); const [homeImageUrl, setHomeImageUrl] = useState(''); + const [homeImageAlt, setHomeImageAlt] = useState(''); async function getMessage() { try { @@ -24,13 +25,16 @@ const Home = () => { } async function loadHomeImage() { - const response = await getHomeImageUrl(); - const url = response.responseData; - if (!response.error && url) { - setHomeImageUrl(url.trim()); - } else { //old image if error - setHomeImageUrl('https://raw.githubusercontent.com/thebeninator/Clark/refs/heads/add_comp_homepage/public/images/compressed2.jpg'); + const DEFAULT_IMAGE = 'https://raw.githubusercontent.com/thebeninator/Clark/refs/heads/add_comp_homepage/public/images/compressed2.jpg'; + const response = await getHomeImage(); + let url = DEFAULT_IMAGE; + let alt = 'sce club image'; + if (!response.error) { + url = response.responseData.url; + alt = response.responseData.alt; } + setHomeImageUrl(url); + setHomeImageAlt(alt); } useEffect(() => { @@ -107,6 +111,7 @@ const Home = () => { {homeImageAlt}
From bf3aa14c882425a2d0a959188e5f5ac2a0e93a5e Mon Sep 17 00:00:00 2001 From: Jay Timbol Date: Thu, 1 Jan 2026 21:38:04 -0600 Subject: [PATCH 4/9] add visit counter to home page --- api/main_endpoints/models/HomepageVisit.js | 14 ++++++++ api/main_endpoints/routes/Homepage.js | 29 ++++++++++++++++ src/APIFunctions/HomepageVisit.js | 40 ++++++++++++++++++++++ src/Pages/Home/Home.js | 14 ++++++-- 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 api/main_endpoints/models/HomepageVisit.js create mode 100644 api/main_endpoints/routes/Homepage.js create mode 100644 src/APIFunctions/HomepageVisit.js diff --git a/api/main_endpoints/models/HomepageVisit.js b/api/main_endpoints/models/HomepageVisit.js new file mode 100644 index 000000000..1e1caa59a --- /dev/null +++ b/api/main_endpoints/models/HomepageVisit.js @@ -0,0 +1,14 @@ +const mongoose = require('mongoose'); +const Schema = mongoose.Schema; + +const HomepageVisitSchema = new Schema( + { + visitCount: { + type: Number, + default: 0 + } + }, + { collection: 'HomepageVisit' } +); + +module.exports = mongoose.model('HomepageVisit', HomepageVisitSchema); \ No newline at end of file diff --git a/api/main_endpoints/routes/Homepage.js b/api/main_endpoints/routes/Homepage.js new file mode 100644 index 000000000..d6c962c1e --- /dev/null +++ b/api/main_endpoints/routes/Homepage.js @@ -0,0 +1,29 @@ +const express = require ('express'); +const router = express.Router(); +const visitCounter = require('../models/HomepageVisit'); +const { BAD_REQUEST, OK } = require('../../util/constants').STATUS_CODES; + +router.post('/visit', async (req, res) => { + try { + await visitCounter.findOneAndUpdate( + {}, + {$inc: {visitCount: 1}}, + { new: true, upsert: true } + ); + res.sendStatus(OK); + } catch (error) { + res.sendStatus(BAD_REQUEST); + } +}); + +router.get('/count', async (req, res) => { + try { + const response = await visitCounter.findOne({}); + const visitCount = response ? response.visitCount : 0; + return res.status(OK).send({visitCount}); + } catch (error) { + return res.sendStatus(BAD_REQUEST); + } +}) + +module.exports = router; \ No newline at end of file diff --git a/src/APIFunctions/HomepageVisit.js b/src/APIFunctions/HomepageVisit.js new file mode 100644 index 000000000..7eac3ac15 --- /dev/null +++ b/src/APIFunctions/HomepageVisit.js @@ -0,0 +1,40 @@ +import { ApiResponse } from './ApiResponses'; +import { BASE_API_URL } from '../Enums'; + +export async function incrementVisitCount() { + let status = new ApiResponse(); + try { + await fetch (BASE_API_URL + 'api/Homepage/visit', { + 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() { + let status = new ApiResponse(); + try { + const res = await fetch (BASE_API_URL + 'api/Homepage/count'); + 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; +} \ No newline at end of file diff --git a/src/Pages/Home/Home.js b/src/Pages/Home/Home.js index 45e7dd731..68525d8df 100755 --- a/src/Pages/Home/Home.js +++ b/src/Pages/Home/Home.js @@ -4,7 +4,7 @@ import './Home.css'; import { getAd } from '../../APIFunctions/Advertisement.js'; import { getHomeImage } from '../../APIFunctions/Image.js'; - +import { incrementVisitCount, getVisitCount } from '../../APIFunctions/HomepageVisit.js'; const Home = () => { const [message, setMessage] = useState(''); @@ -12,6 +12,7 @@ const Home = () => { const [showAll, setShowAll] = useState(false); const [homeImageUrl, setHomeImageUrl] = useState(''); const [homeImageAlt, setHomeImageAlt] = useState(''); + const [visitCount, setVisitCount] = useState(0); async function getMessage() { try { @@ -37,9 +38,16 @@ const Home = () => { setHomeImageAlt(alt); } + async function loadVisitCounter() { + await incrementVisitCount(); + const response = await getVisitCount(); + if(!response.error) setVisitCount(response.responseData.visitCount); + } + useEffect(() => { getMessage(); loadHomeImage(); + loadVisitCounter(); setTimeout(() => setShowAll(true), 100); }, []); @@ -121,7 +129,9 @@ const Home = () => {
- +
+ Visit Count: {visitCount} +
); From 9f9d883f703234ce82e775e670c3dce50c375f03 Mon Sep 17 00:00:00 2001 From: Jay Timbol Date: Thu, 1 Jan 2026 23:20:52 -0600 Subject: [PATCH 5/9] revert visit count changes; moved to new pr --- api/main_endpoints/models/HomepageVisit.js | 14 -------- api/main_endpoints/routes/Homepage.js | 29 ---------------- src/APIFunctions/HomepageVisit.js | 40 ---------------------- src/Pages/Home/Home.js | 14 ++------ 4 files changed, 2 insertions(+), 95 deletions(-) delete mode 100644 api/main_endpoints/models/HomepageVisit.js delete mode 100644 api/main_endpoints/routes/Homepage.js delete mode 100644 src/APIFunctions/HomepageVisit.js diff --git a/api/main_endpoints/models/HomepageVisit.js b/api/main_endpoints/models/HomepageVisit.js deleted file mode 100644 index 1e1caa59a..000000000 --- a/api/main_endpoints/models/HomepageVisit.js +++ /dev/null @@ -1,14 +0,0 @@ -const mongoose = require('mongoose'); -const Schema = mongoose.Schema; - -const HomepageVisitSchema = new Schema( - { - visitCount: { - type: Number, - default: 0 - } - }, - { collection: 'HomepageVisit' } -); - -module.exports = mongoose.model('HomepageVisit', HomepageVisitSchema); \ No newline at end of file diff --git a/api/main_endpoints/routes/Homepage.js b/api/main_endpoints/routes/Homepage.js deleted file mode 100644 index d6c962c1e..000000000 --- a/api/main_endpoints/routes/Homepage.js +++ /dev/null @@ -1,29 +0,0 @@ -const express = require ('express'); -const router = express.Router(); -const visitCounter = require('../models/HomepageVisit'); -const { BAD_REQUEST, OK } = require('../../util/constants').STATUS_CODES; - -router.post('/visit', async (req, res) => { - try { - await visitCounter.findOneAndUpdate( - {}, - {$inc: {visitCount: 1}}, - { new: true, upsert: true } - ); - res.sendStatus(OK); - } catch (error) { - res.sendStatus(BAD_REQUEST); - } -}); - -router.get('/count', async (req, res) => { - try { - const response = await visitCounter.findOne({}); - const visitCount = response ? response.visitCount : 0; - return res.status(OK).send({visitCount}); - } catch (error) { - return res.sendStatus(BAD_REQUEST); - } -}) - -module.exports = router; \ No newline at end of file diff --git a/src/APIFunctions/HomepageVisit.js b/src/APIFunctions/HomepageVisit.js deleted file mode 100644 index 7eac3ac15..000000000 --- a/src/APIFunctions/HomepageVisit.js +++ /dev/null @@ -1,40 +0,0 @@ -import { ApiResponse } from './ApiResponses'; -import { BASE_API_URL } from '../Enums'; - -export async function incrementVisitCount() { - let status = new ApiResponse(); - try { - await fetch (BASE_API_URL + 'api/Homepage/visit', { - 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() { - let status = new ApiResponse(); - try { - const res = await fetch (BASE_API_URL + 'api/Homepage/count'); - 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; -} \ No newline at end of file diff --git a/src/Pages/Home/Home.js b/src/Pages/Home/Home.js index 68525d8df..f1350f193 100755 --- a/src/Pages/Home/Home.js +++ b/src/Pages/Home/Home.js @@ -4,7 +4,7 @@ import './Home.css'; import { getAd } from '../../APIFunctions/Advertisement.js'; import { getHomeImage } from '../../APIFunctions/Image.js'; -import { incrementVisitCount, getVisitCount } from '../../APIFunctions/HomepageVisit.js'; + const Home = () => { const [message, setMessage] = useState(''); @@ -12,7 +12,6 @@ const Home = () => { const [showAll, setShowAll] = useState(false); const [homeImageUrl, setHomeImageUrl] = useState(''); const [homeImageAlt, setHomeImageAlt] = useState(''); - const [visitCount, setVisitCount] = useState(0); async function getMessage() { try { @@ -38,16 +37,9 @@ const Home = () => { setHomeImageAlt(alt); } - async function loadVisitCounter() { - await incrementVisitCount(); - const response = await getVisitCount(); - if(!response.error) setVisitCount(response.responseData.visitCount); - } - useEffect(() => { getMessage(); loadHomeImage(); - loadVisitCounter(); setTimeout(() => setShowAll(true), 100); }, []); @@ -129,9 +121,7 @@ const Home = () => {
-
- Visit Count: {visitCount} -
+