Merge branch 'dev' of github.com:JoaquinPar/2800-202510-BBY14 into fix/account_details_update
This commit is contained in:
5 files changed
+72
-33
No files matched your search
@@ -5,6 +5,7 @@ function getLocation() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function update(data) {
|
function update(data) {
|
||||||
|
if (data.data.message != "error") {
|
||||||
document.getElementById("loading").style = "display: none";
|
document.getElementById("loading").style = "display: none";
|
||||||
document.getElementById("currencyExchange").style = "display: flex";
|
document.getElementById("currencyExchange").style = "display: flex";
|
||||||
|
|
||||||
@@ -37,6 +38,14 @@ function update(data) {
|
|||||||
|
|
||||||
dropdown.appendChild(listItem);
|
dropdown.appendChild(listItem);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
document.getElementById("loading").style = "display: none";
|
||||||
|
document.getElementById("exFrom").style = "display: none";
|
||||||
|
document.getElementById("dropdown-country-button").style = "display: none";
|
||||||
|
document.getElementById("currencyExchange").style = "display: flex";
|
||||||
|
document.getElementById("exchange").innerHTML = "Country not supported";
|
||||||
|
document.getElementById("exchange").className = "block rounded-lg text-center p-2.5 w-50 z-20 text-sm border bg-gray-700 border-gray-600 placeholder-gray-400 text-white focus:border-blue-500";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function switchButton(clickedButton) {
|
function switchButton(clickedButton) {
|
||||||
@@ -65,5 +74,11 @@ async function getLatestExchange(position) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function error(err) {
|
function error(err) {
|
||||||
console.error("Geolocation error: ", err);
|
const data = {
|
||||||
|
data: {
|
||||||
|
message: "error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update(data);
|
||||||
}
|
}
|
||||||
+18
-17
@@ -101,18 +101,17 @@ module.exports = (middleware, users, plans, assets) => {
|
|||||||
try {
|
try {
|
||||||
const userPlansFromDB = await plans.find({ userId: new ObjectId(req.session.userId) }).toArray();
|
const userPlansFromDB = await plans.find({ userId: new ObjectId(req.session.userId) }).toArray();
|
||||||
|
|
||||||
// Use a for...of loop for proper async/await behavior in series for updates
|
|
||||||
for (const plan of userPlansFromDB) {
|
for (const plan of userPlansFromDB) {
|
||||||
const percentage = await calculatePlanProgress(plan, assets, req.session.userId);
|
const percentage = await calculatePlanProgress(plan, assets, req.session.user._id);
|
||||||
await updatePlanProgressInDB(plan._id, percentage, plans); // Pass the 'plans' collection
|
await updatePlanProgressInDB(plan._id, percentage, plans);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-fetch plans to get updated progress for rendering
|
const updatedUserPlans = await plans.find({ userId: new ObjectId(req.session.user._id) }).toArray();
|
||||||
const updatedUserPlans = await plans.find({ userId: new ObjectId(req.session.userId) }).toArray();
|
|
||||||
|
|
||||||
res.render('plans', {
|
res.render('plans', {
|
||||||
user: req.session.user,
|
user: req.session.user,
|
||||||
plans: updatedUserPlans, // Send the most up-to-date plans
|
plans: updatedUserPlans,
|
||||||
geoData: req.session.geoData
|
geoData: req.session.geoData
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -141,16 +140,9 @@ module.exports = (middleware, users, plans, assets) => {
|
|||||||
return res.status(status.NotFound).redirect('/plans');
|
return res.status(status.NotFound).redirect('/plans');
|
||||||
}
|
}
|
||||||
|
|
||||||
// The plan.progress should be up-to-date from the database as it was updated in the /plans route
|
|
||||||
// or when assets/plans are modified. If an immediate recalculation for this specific view is absolutely needed,
|
|
||||||
// (e.g., if assets were modified without an immediate plan progress update elsewhere),
|
|
||||||
// you could do it here:
|
|
||||||
// const currentProgress = await calculatePlanProgress(plan, assets, req.session.user._id);
|
|
||||||
// plan.progress = currentProgress; // This would only update the 'plan' object for this render, not in DB
|
|
||||||
|
|
||||||
res.render('planDetail', {
|
res.render('planDetail', {
|
||||||
user: req.session.user,
|
user: req.session.user,
|
||||||
plan: plan, // This plan object will have the progress from the database
|
plan: plan,
|
||||||
geoData: req.session.geoData,
|
geoData: req.session.geoData,
|
||||||
assets: userAssets,
|
assets: userAssets,
|
||||||
suggestions: await suggestions.generateSuggestions(),
|
suggestions: await suggestions.generateSuggestions(),
|
||||||
@@ -217,9 +209,10 @@ module.exports = (middleware, users, plans, assets) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/pun', async (req, res) => {
|
router.post('/fact', async (req, res) => {
|
||||||
const pun = await suggestions.generatePun();
|
const factInput = req.body.fact;
|
||||||
return res.status(status.Ok).json({ pun });
|
const fact = await suggestions.generateFact(factInput);
|
||||||
|
return res.status(status.Ok).json({ fact });
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/more', (req, res) => {
|
router.get('/more', (req, res) => {
|
||||||
@@ -659,6 +652,12 @@ module.exports = (middleware, users, plans, assets) => {
|
|||||||
|
|
||||||
country = data.results[0].formatted_address;
|
country = data.results[0].formatted_address;
|
||||||
let results = await getRates(country);
|
let results = await getRates(country);
|
||||||
|
|
||||||
|
if (!results.exRates) {
|
||||||
|
req.session.geoData = {
|
||||||
|
message: "error"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
req.session.geoData = {
|
req.session.geoData = {
|
||||||
country: results.abbreviation,
|
country: results.abbreviation,
|
||||||
toCurrencyRates: results.exRates,
|
toCurrencyRates: results.exRates,
|
||||||
@@ -666,6 +665,8 @@ module.exports = (middleware, users, plans, assets) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return res.status(status.Ok).send({ data: req.session.geoData });
|
return res.status(status.Ok).send({ data: req.session.geoData });
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ const { GoogleGenAI } = require("@google/genai");
|
|||||||
|
|
||||||
const ai = new GoogleGenAI({ apiKey: process.env.GOOGLE_API_KEY });
|
const ai = new GoogleGenAI({ apiKey: process.env.GOOGLE_API_KEY });
|
||||||
|
|
||||||
async function generatePun() {
|
async function generateFact(factInput) {
|
||||||
const response = await ai.models.generateContent({
|
const response = await ai.models.generateContent({
|
||||||
model: "gemini-2.0-flash",
|
model: "gemini-2.0-flash",
|
||||||
contents: "Return a funny pun about investments, answer the pun only, no additional text.",
|
contents: `Generate a concise investment fact about "${factInput}". If "${factInput}" is not directly investment-related, provide a general, useful investment fact instead. Deliver only the fact itself, with no extra text or explanation.`,
|
||||||
});
|
});
|
||||||
return response.text;
|
return response.text;
|
||||||
}
|
}
|
||||||
@@ -19,6 +19,6 @@ async function generateSuggestions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
generatePun,
|
generateFact,
|
||||||
generateSuggestions
|
generateSuggestions
|
||||||
};
|
};
|
||||||
@@ -1,7 +1,14 @@
|
|||||||
<div data-dial-init class="fixed end-6 bottom-20 group">
|
<div class="fixed end-6 bottom-20 group">
|
||||||
<button type="button" id="punButton" class="flex items-center justify-center text-white bg-blue-700 rounded-full w-14 h-14 hover:bg-blue-800 dark:bg-blue-600 dark:hover:bg-blue-700 focus:ring-4 focus:ring-blue-300 focus:outline-none dark:focus:ring-blue-800">
|
<div id="factMenu" class="absolute right-0 bottom-full mb-2 hidden">
|
||||||
|
<div id="factContainer" class="bg-white p-4 rounded-lg shadow-md dark:bg-gray-700 w-64">
|
||||||
|
<p class="mb-2 text-sm text-gray-700 dark:text-gray-300">Insert the kind of short fact you would like to know more about:</p>
|
||||||
|
<input type="text" id="factInput" placeholder="Enter your topic here" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-600 dark:border-gray-500 dark:text-white dark:placeholder-gray-400">
|
||||||
|
<button type="button" id="factSubmitButton" class="mt-3 w-full px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-700">Submit</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button type="button" id="factButton" class="flex items-center justify-center text-white bg-blue-700 rounded-full w-14 h-14 hover:bg-blue-800 dark:bg-blue-600 dark:hover:bg-blue-700 focus:ring-4 focus:ring-blue-300 focus:outline-none dark:focus:ring-blue-800">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>
|
||||||
<span class="sr-only">Get a Pun</span>
|
<span class="sr-only">Get a Fact</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -13,19 +20,33 @@
|
|||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/flowbite@3.1.2/dist/flowbite.min.js"></script>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
<script>
|
<script>
|
||||||
const punButton = document.getElementById("punButton");
|
const factButton = document.getElementById("factButton");
|
||||||
punButton.addEventListener("click", () => {
|
const factMenu = document.getElementById("factMenu");
|
||||||
fetch("/pun")
|
const factInput = document.getElementById("factInput");
|
||||||
|
const factSubmitButton = document.getElementById("factSubmitButton");
|
||||||
|
|
||||||
|
factButton.addEventListener("click", () => {
|
||||||
|
factMenu.classList.toggle("hidden");
|
||||||
|
});
|
||||||
|
factSubmitButton.addEventListener("click", () => {
|
||||||
|
fetch("/fact", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
fact: factInput.value,
|
||||||
|
}),
|
||||||
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
Swal.fire('Here is a pun!', data.pun, 'success');
|
Swal.fire('Here is a fact!', data.fact, 'success');
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error("Error fetching pun:", error);
|
console.error("Error fetching fact:", error);
|
||||||
Swal.fire('Error fetching pun', 'Please try again later', 'error');
|
Swal.fire('Error fetching fact', 'Please try again later', 'error');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -17,12 +17,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display: none;" class="flex items-center" id="currencyExchange">
|
<div style="display: none;" class="flex items-center" id="currencyExchange">
|
||||||
<div class="shrink-0 z-10 inline-flex items-center py-2.5 px-4 text-sm font-medium text-center text-gray-900 bg-gray-100 border border-gray-300 rounded-s-lg focus:ring-4 focus:outline-none focus:ring-gray-100 dark:bg-gray-700 dark:focus:ring-gray-700 dark:text-white dark:border-gray-600">
|
<div id="exFrom" class="shrink-0 z-10 inline-flex items-center py-2.5 px-4 text-sm font-medium text-center text-gray-900 bg-gray-100 border border-gray-300 rounded-s-lg focus:ring-4 focus:outline-none focus:ring-gray-100 dark:bg-gray-700 dark:focus:ring-gray-700 dark:text-white dark:border-gray-600">
|
||||||
<img src="" id="yourFlag" class="h-4 w-4 me-2" alt="">
|
<img src="" id="yourFlag" class="h-4 w-4 me-2" alt="">
|
||||||
<p id="flagTag"></p>
|
<p id="flagTag"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="relative w-full">
|
<div class="relative w-full">
|
||||||
<p id="exchange" class="block text-center p-2.5 w-40 z-20 text-sm text-gray-900 bg-gray-50 border-s-0 border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-s-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:border-blue-500">
|
<p id="exchange" class="block text-center p-2.5 w-40 z-20 text-sm border bg-gray-700 border-gray-600 placeholder-gray-400 text-white focus:border-blue-500">
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button id="dropdown-country-button" value="" data-dropdown-toggle="dropdown-country" class="shrink-0 z-10 inline-flex items-center py-2.5 px-4 text-sm font-medium text-center text-gray-900 bg-gray-100 border border-gray-300 rounded-e-lg hover:bg-gray-200 focus:ring-4 focus:outline-none focus:ring-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 dark:focus:ring-gray-700 dark:text-white dark:border-gray-600" type="button">
|
<button id="dropdown-country-button" value="" data-dropdown-toggle="dropdown-country" class="shrink-0 z-10 inline-flex items-center py-2.5 px-4 text-sm font-medium text-center text-gray-900 bg-gray-100 border border-gray-300 rounded-e-lg hover:bg-gray-200 focus:ring-4 focus:outline-none focus:ring-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 dark:focus:ring-gray-700 dark:text-white dark:border-gray-600" type="button">
|
||||||
@@ -38,6 +38,8 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<% } else if(geoData.message == "error") { %>
|
||||||
|
<p>error</p>
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="shrink-0 z-10 inline-flex items-center py-2.5 px-4 text-sm font-medium text-center text-gray-900 bg-gray-100 border border-gray-300 rounded-s-lg focus:ring-4 focus:outline-none focus:ring-gray-100 dark:bg-gray-700 dark:focus:ring-gray-700 dark:text-white dark:border-gray-600">
|
<div class="shrink-0 z-10 inline-flex items-center py-2.5 px-4 text-sm font-medium text-center text-gray-900 bg-gray-100 border border-gray-300 rounded-s-lg focus:ring-4 focus:outline-none focus:ring-gray-100 dark:bg-gray-700 dark:focus:ring-gray-700 dark:text-white dark:border-gray-600">
|
||||||
|
|||||||
Reference in new issue
Block a user