Compare commits

...
Author SHA1 Message Date
SowinskiBraeden e0ba913257 Update README.md 2025-09-18 20:53:37 -07:00
nicoagostini 33fa0b4a89 Suggestions updated 2025-06-07 11:04:15 -07:00
knighthawk4227 19b340b004 correcting reset link sent to user 2025-06-02 23:00:09 -07:00
SowinskiBraeden cc178edb1e update/prerequisites 2025-05-23 12:59:14 -07:00
nicoagostini dac0f6ecc2 update/Test logs updated 2025-05-23 12:55:12 -07:00
Nícolas Agostini 46d6d2e036 Update README.md 2025-05-23 02:35:48 -07:00
Nícolas Agostini 38074fdc36 Update README.md 2025-05-23 02:35:34 -07:00
nicoagostini b11d5ceca3 refactor/ RREADME updated, About Us updated, unused route removed 2025-05-23 02:29:59 -07:00
SowinskiBraeden ed8b2b47b6 Merge pull request #41 from JoaquinPar/feature/asset_sort
Feature/asset sort
2025-05-22 14:05:35 -07:00
SowinskiBraeden 3f8dbef6ad Merge latest 2025-05-22 14:05:06 -07:00
SowinskiBraeden 0b9a90fabe update/sort assets 2025-05-22 14:03:18 -07:00
Joaquin Paredes 5afdd6a8d0 Merge branch 'main' of https://github.com/JoaquinPar/2800-202510-BBY14 2025-05-22 13:34:33 -07:00
Joaquin Paredes f409602e22 fix/assets page layout now fits in phone view.
SVGs colours changed to white
2025-05-22 13:32:00 -07:00
Joaquin Paredes 7d26825c63 fix/plans layout now fits in phone view. SVGs colours changed to white 2025-05-22 13:31:37 -07:00
Nícolas Agostini b346ee6222 Merge pull request #40 from JoaquinPar/fix/calculation-depreciation
Fix/calculation depreciation
2025-05-22 13:09:59 -07:00
nicoagostini 343a4f8275 fix/depreciation again 2025-05-22 13:09:26 -07:00
nicoagostini 0129315523 fix/depreciation again 2025-05-22 13:02:04 -07:00
knighthawk4227 f498386f96 Merge branch 'dev' 2025-05-22 12:39:46 -07:00
knighthawk4227 b3b06226ee fix/mobile layout 2025-05-22 12:39:17 -07:00
SowinskiBraeden d82bfd5b56 fix/name allow spaces 2025-05-22 12:23:34 -07:00
19 changed files with 218 additions and 105 deletions

No files matched your search

Vendored
BIN
View File
Binary file not shown.
+50 -30
View File
@@ -1,27 +1,43 @@
# Retirement Calculator
## 2800-202510-BBY14
### 2800-202510-BBY14
## Overview
Retirement Calculator - The goal of the application is to help users manage and track their financial progress in a way that reflects real life. Instead of just acting as a calculator, the app functions as a dynamic tracker. It shows the user a percentage of how much of their goal has been achieved and compares their actual performance to their planned targets.
RCalculator is a dynamic financial tracking application designed to help users manage and monitor their progress towards long-term financial goals, particularly retirement. It moves beyond simple calculations by providing personalized insights, tracking actual performance against planned targets, and offering a clear view of your financial journey towards achieving your desired future.
---
## Features
- Do calculator stuff
- **Personalized Financial Profile:** Users complete a comprehensive questionnaire to build a financial profile, enabling tailored guidance and projections.
- **Comprehensive Asset Management:** Add, track, and manage various types of assets including savings, stocks, real estate, and other investments for a holistic view of net worth.
- **Strategic Goal Planning:** Define long-term financial objectives (e.g., retirement, home purchase, education) and create detailed plans with actionable steps.
- **Clear Financial Projections:** Visualize potential investment growth and assess the feasibility of financial plans through easy-to-understand projections and charts.
- **User-Friendly Dashboard:** An intuitive dashboard provides an at-a-glance overview of financial health, asset allocation, and progress towards goals.
- **Secure User Authentication:** Robust authentication system to protect sensitive financial data, including secure registration and login processes.
- **Dynamic Currency Conversion:** (If applicable) Utilizes geolocation to provide relevant currency information and conversion rates for international users or assets.
---
## Technologies Used
Example:
- **Frontend**: HTML, CSS, JavaScript
- **Backend**: Express.js
- **Database**: MongoDB
- **Frontend:** EJS (Embedded JavaScript templates), Tailwind CSS, Vanilla JavaScript
- **Backend:** Node.js, Express.js
- **Database:** MongoDB
- **Authentication:** express-session for session management, bcrypt for password hashing.
- **Data Validation:** Joi for schema validation.
- **APIs:** Google Gemini API for generating financial advice. **Geolocation API** for currency conversion.
---
## Prerequisites
1. You'll need to setup an instance of MongoDB. You can use the cloud platform, MongoDB Atlas, or create your own instance locally.
i. [Create your MongoDB Altas instance.](https://www.mongodb.com/docs/manual/tutorial/getting-started/)
ii. [Create your local MongoDB server instance.](https://www.mongodb.com/docs/manual/administration/install-community/)
After this, you'll need to get your MongoURI from your database instance, as well as your database name for later configuration in the `.env` file.
## Usage
1. **Clone the repository:**
@@ -47,32 +63,30 @@ Example:
The application should now be running, typically on `http://localhost:3000` (or the port specified in your `.env` file).
---
## Project Structure
```
retirementCalculator/
├── src/
| ├── auth/
| ├── database/
│ ├── public/
│ │ ├── images/
│ │ ├── scripts/
│ │ └── svgs/
| |
│ ├── router/
── utils/
└── views/
│ └── partials/
├── auth/ # Authentication logic (e.g., passport setup, strategies)
├── database/ # MongoDB connection, schemas, models
│ ├── public/ # Static assets
│ │ ├── images/ # Site images and icons
│ │ ├── scripts/ # Client-side JavaScript files
│ │ └── svgs/ # SVG icons
│ ├── router/ # Express route definitions
│ ├── util/ # Utility functions (e.g., calculations, helpers)
── views/ # EJS templates
└── partials/ # Reusable EJS partials (headers, footers, nav)
├── .env.example
├── .gitignore
├── app.js
├── CONTRIBUTING.md
├── LICENSE
├── package-lock.json
├── package.json
└── README.md
├── .env.example # Example environment variables file
├── .gitignore # Specifies intentionally untracked files that Git should ignore
├── app.js # Main application entry point
├── CONTRIBUTING.md # Guidelines for contributing to the project
├── LICENSE # Project license information
├── package-lock.json # Records exact versions of dependencies
├── package.json # Project metadata and dependencies
└── README.md # This file
```
---
@@ -84,16 +98,22 @@ retirementCalculator/
- **[Mitchell Schaeffer](https://github.com/knighthawk4227)** - BCIT CST Student with a passion for technology.
---
## more details to come...
## Limitations and Future Work
### Limitations
- None
- **Generalized Advice:** The application provides financial guidance based on user input and common models; it does not substitute professional financial advisory services.
- **Market Volatility:** Projections are based on assumed rates of return and do not account for all potential market fluctuations or unforeseen economic events.
- **Manual Data Entry:** Asset information and updates currently require manual input.
- **Single User Focus:** Primarily designed for individual financial planning.
### Future Work
- All work
- **Third-Party API Integrations:** Connect with financial institutions (e.g., Plaid) for automated asset tracking and transaction importing.
- **Advanced Reporting:** Implement more detailed financial reports, customizable charts, and data export options (e.g., PDF, CSV).
- **Enhanced Security Features:** Implement Two-Factor Authentication (2FA) and advanced security audits.
- **Educational Resources:** Integrate a section with articles, tips, and resources on financial literacy and planning.
---
+1 -1
View File
@@ -73,7 +73,7 @@ module.exports = (users) => {
router.post("/signup", async (req, res) => {
const userSchema = joi.object({
email: joi.string().email({ minDomainSegments: 2, tlds: { allow: true } }).required(),
name: joi.string().pattern(new RegExp('^[a-zA-Z]+$')).max(20).required(),
name: joi.string().pattern(new RegExp('^[a-zA-Z0-9_ ]*$')).max(20).required(),
password: joi.string().max(20).min(8).required(),
repassword: joi.string().max(20).min(8).required(),
});
+1 -1
View File
@@ -47,7 +47,7 @@ module.exports = (users) => {
$set: { resetToken: token, resetTokenExpires: expiration }
});
const resetUrl = `http://localhost:${PORT}/reset/${token}`;
const resetUrl = `https://rcalculator.sowinski.dev/reset/${token}`;
const mailSend = {
from: process.env.EMAIL_USER,
+35
View File
@@ -150,6 +150,41 @@ function selectIcon(selectedIcon, assetId="") {
`;
}
/**
* selectFilter to filter assets by type
* @param {button elemenbt} filter
*/
function selectFilter(filter) {
const types = ["other", "saving", "stock"];
console.log(filter.value);
types.forEach((type) => {
if (filter.value == "all") {
document.querySelectorAll(`.${type}-asset`).forEach((preview) => {
preview.style.display = "block";
});
} else if (type != filter.value) {
document.querySelectorAll(`.${type}-asset`).forEach((preview) => {
preview.style.display = "none";
});
} else if (type == filter.value) {
document.querySelectorAll(`.${type}-asset`).forEach((preview) => {
preview.style.display = "block";
});
}
});
document.getElementById("dropdown-filters-button").innerHTML = `
<span class="inline-flex items-center">
${filter.value.charAt(0).toUpperCase() + filter.value.slice(1)} Assets
<svg class="w-2.5 h-2.5 ms-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
</svg>
</span>
`;
}
/**
* toggleYear shows or hides year input
* @param {string} type of asset
+1 -1
View File
@@ -6,7 +6,7 @@ const factSubmitButton = document.getElementById("factSubmitButton");
var path = window.location.pathname;
var page = path.split("/").pop();
if(page !== "login" && page !== "signup" && page !== "forgotPassword" && page !== "") {
if(page !== "login" && page !== "signup" && page !== "forgotPassword" && page !== "aboutUs" && page !== "") {
factButton.classList.remove("hidden");
}
+1 -1
View File
@@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" fill="white" viewBox="0 0 24 24" aria-hidden="true">
<path d="M10.464 8.746c.227-.18.497-.311.786-.394v2.795a2.252 2.252 0 0 1-.786-.393c-.394-.313-.546-.681-.546-1.004 0-.323.152-.691.546-1.004ZM12.75 15.662v-2.824c.347.085.664.228.921.421.427.32.579.686.579.991 0 .305-.152.671-.579.991a2.534 2.534 0 0 1-.921.42Z" />
<path fill-rule="evenodd" d="M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25ZM12.75 6a.75.75 0 0 0-1.5 0v.816a3.836 3.836 0 0 0-1.72.756c-.712.566-1.112 1.35-1.112 2.178 0 .829.4 1.612 1.113 2.178.502.4 1.102.647 1.719.756v2.978a2.536 2.536 0 0 1-.921-.421l-.879-.66a.75.75 0 0 0-.9 1.2l.879.66c.533.4 1.169.645 1.821.75V18a.75.75 0 0 0 1.5 0v-.81a4.124 4.124 0 0 0 1.821-.749c.745-.559 1.179-1.344 1.179-2.191 0-.847-.434-1.632-1.179-2.191a4.122 4.122 0 0 0-1.821-.75V8.354c.29.082.559.213.786.393l.415.33a.75.75 0 0 0 .933-1.175l-.415-.33a3.836 3.836 0 0 0-1.719-.755V6Z" clip-rule="evenodd" />
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

+1 -1
View File
@@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" fill="currentColor" viewBox="0 0 24 24">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" fill="white" viewBox="0 0 24 24">
<path fill-rule="evenodd" d="M11.293 3.293a1 1 0 0 1 1.414 0l6 6 2 2a1 1 0 0 1-1.414 1.414L19 12.414V19a2 2 0 0 1-2 2h-3a1 1 0 0 1-1-1v-3h-2v3a1 1 0 0 1-1 1H7a2 2 0 0 1-2-2v-6.586l-.293.293a1 1 0 0 1-1.414-1.414l2-2 6-6Z" clip-rule="evenodd"/>
</svg>

Before

Width:  |  Height:  |  Size: 358 B

After

Width:  |  Height:  |  Size: 351 B

+2 -2
View File
@@ -1,3 +1,3 @@
<svg height="30" width="30" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 17 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h15M1 7h15M1 13h15"></path>
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" fill="white" viewBox="0 0 24 24">
<path stroke="white" stroke-linecap="round" stroke-width="2" d="M5 6h14 M5 14h14 M5 22h14"/>
</svg>

Before

Width:  |  Height:  |  Size: 260 B

After

Width:  |  Height:  |  Size: 199 B

+1 -1
View File
@@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" fill="currentColor" viewBox="0 0 24 24">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" fill="white" viewBox="0 0 24 24">
<path d="M13.09 3.294c1.924.95 3.422 1.69 5.472.692a1 1 0 0 1 1.438.9v9.54a1 1 0 0 1-.562.9c-2.981 1.45-5.382.24-7.25-.701a38.739 38.739 0 0 0-.622-.31c-1.033-.497-1.887-.812-2.756-.77-.76.036-1.672.357-2.81 1.396V21a1 1 0 1 1-2 0V4.971a1 1 0 0 1 .297-.71c1.522-1.506 2.967-2.185 4.417-2.255 1.407-.068 2.653.453 3.72.967.225.108.443.216.655.32Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 463 B

After

Width:  |  Height:  |  Size: 456 B

+4 -16
View File
@@ -172,6 +172,8 @@ module.exports = (middleware, users, plans, assets) => {
const progress = await calculateProgress(plan, assets, users, req.session.userId);
const suggestions = await generateSuggestions(totalUserAssetValue, plan);
res.render('planDetail', {
user: req.session.user,
plan: plan,
@@ -179,7 +181,7 @@ module.exports = (middleware, users, plans, assets) => {
totalUserAssetValue: totalUserAssetValue,
assets: userAssets,
progress: progress,
suggestions: await suggestions.generateSuggestions(),
suggestions: suggestions,
});
} catch (err) {
@@ -189,20 +191,6 @@ module.exports = (middleware, users, plans, assets) => {
}
});
// router.get('/newPlan', (req, res) => {
// if (!req.session.user.financialData || !req.session.user) {
// req.session.errMessage = "Please complete your financial data before creating a plan.";
// return res.status(status.Unauthorized).redirect('/questionnaire');
// }
// const errMessage = req.session.errMessage;
// req.session.errMessage = "";
// res.render('newPlan', {
// user: req.session.user,
// errMessage: errMessage,
// geoData: req.session.geoData
// });
// });
router.post('/newPlan', async (req, res) => {
if (!req.session.user.financialData || !req.session.user) {
@@ -477,7 +465,7 @@ module.exports = (middleware, users, plans, assets) => {
router.post("/updateAccount", async (req, res) => {
const accountSchema = joi.object({
email: joi.string().email({ minDomainSegments: 2, tlds: { allow: true } }),
name: joi.string().pattern(new RegExp('^[a-zA-Z]+$')).max(20),
name: joi.string().pattern(new RegExp('^[a-zA-Z0-9_ ]*$')).max(20),
password: joi.string().max(20).min(8),
repassword: joi.string().max(20).min(8),
});
+8 -2
View File
@@ -56,9 +56,15 @@ async function calculateTotalAssetValue(assets) {
if (asset.value < 1000) {
totalAssetValue += asset.value;
} else {
const assetYear = new Date(asset.year).getFullYear();
const assetYear = asset.year;
const age = today.getFullYear() - assetYear;
let depreciatedValue = asset.value * Math.pow(0.85, age);
let depreciatedValue;
if (age < 1){
depreciatedValue = asset.value * 0.9;
}else{
depreciatedValue = asset.value * Math.pow(0.90, age);
}
if (depreciatedValue < 1000) {
totalAssetValue += 1000;
+6 -2
View File
@@ -10,10 +10,14 @@ async function generateFact(factInput) {
return response.text;
}
async function generateSuggestions() {
async function generateSuggestions(totalUserAssetValue, plan) {
const response = await ai.models.generateContent({
model: "gemini-2.0-flash",
contents: "Return a mock investment suggestion 3-5 lines only",
contents: `Return an investment suggestion 3-5 based on the user's total asset value and their plan. Please do not include any extra text or explanation.
Total User Asset Value: ${totalUserAssetValue}
Plan: ${plan}`,
});
return response.text;
}
+48 -16
View File
@@ -10,27 +10,59 @@
<section class="bg-gray-900 py-12 md:py-20">
<div class="max-w-screen-lg mx-auto px-4 text-center">
<h1 class="mb-4 text-4xl font-extrabold tracking-tight leading-none md:text-5xl lg:text-6xl text-white">About RCalculator</h1>
<p class="mb-12 text-lg font-normal lg:text-xl sm:px-16 text-gray-400">Welcome to RCalculator, your partner in building a secure and fulfilling financial future.</p>
<p class="mb-12 text-lg font-normal lg:text-xl sm:px-16 text-gray-400">Welcome to RCalculator, your partner in navigating the path to a secure and fulfilling financial future. We simplify financial planning, making it accessible and actionable for everyone.</p>
</div>
<div class="max-w-screen-md mx-auto px-4">
<h2 class="mb-4 text-3xl font-bold tracking-tight text-white text-center">Our Mission</h2>
<p class="mb-6 font-normal text-gray-400 text-lg text-center">
Our mission is to empower you with the tools and insights needed to take control of your long-term financial goals.
</p>
<div class="prose lg:prose-lg mx-auto text-gray-400">
<p class="mb-4">
We believe that planning for your desired future, especially retirement, shouldn't be daunting. It doesn't matter what your current age or career status is starting now is what counts.
</p>
<p class="mb-4">
At RCalculator, we help you trace a personalized plan that suits your unique aspirations. We provide clear, actionable advice and projections to guide you on how to get there, whether you're just starting your career, mid-way through, or nearing retirement.
</p>
<p>
Let us help you navigate the path to financial independence and achieve the retirement lifestyle you envision.
</p>
<!-- What RCalculator Offers Section -->
<div class="max-w-screen-md mx-auto px-4 mb-16">
<h2 class="mb-8 text-3xl font-bold tracking-tight text-white text-center">What RCalculator Offers</h2>
<div class="space-y-8 text-gray-400 text-lg">
<div class="p-6 border border-gray-700 rounded-lg bg-gray-800/30 shadow-lg">
<h3 class="font-semibold text-xl text-white mb-2">Personalized Financial Insights</h3>
<p>Start by completing our comprehensive questionnaire. Your answers help us tailor financial guidance and projections specifically to your situation and goals.</p>
</div>
<div class="p-6 border border-gray-700 rounded-lg bg-gray-800/30 shadow-lg">
<h3 class="font-semibold text-xl text-white mb-2">Comprehensive Asset Tracking</h3>
<p>Easily add and monitor various types of assets, from savings accounts and stocks to real estate and other investments. Get a clear overview of your net worth in one place.</p>
</div>
<div class="p-6 border border-gray-700 rounded-lg bg-gray-800/30 shadow-lg">
<h3 class="font-semibold text-xl text-white mb-2">Strategic Goal Planning</h3>
<p>Define your long-term financial objectives, such as retirement, buying a home, or funding education. Create detailed plans and see how you can achieve them.</p>
</div>
<div class="p-6 border border-gray-700 rounded-lg bg-gray-800/30 shadow-lg">
<h3 class="font-semibold text-xl text-white mb-2">Clear Financial Projections</h3>
<p>Understand the potential growth of your investments and the feasibility of your financial plans with our easy-to-understand projections and visual tools.</p>
</div>
</div>
</div>
<!-- Getting Started Section -->
<div class="max-w-screen-md mx-auto px-4 mb-16">
<h2 class="mb-8 text-3xl font-bold tracking-tight text-white text-center">Getting Started with RCalculator</h2>
<ol class="list-decimal list-inside space-y-6 text-gray-400 text-lg">
<li class="p-4 border border-gray-700 rounded-lg bg-gray-800 shadow-md">
<span class="font-semibold text-white">Sign Up & Build Your Profile:</span> Create your account and fill out our initial questionnaire. This provides the foundation for personalized advice.
</li>
<li class="p-4 border border-gray-700 rounded-lg bg-gray-800 shadow-md">
<span class="font-semibold text-white">Log Your Assets:</span> Navigate to the 'Assets' section to add details about your current savings, investments, and other valuable possessions.
</li>
<li class="p-4 border border-gray-700 rounded-lg bg-gray-800 shadow-md">
<span class="font-semibold text-white">Create Financial Plans:</span> Head to the 'Plans' section to outline your financial goals. Set targets, timelines, and see projected outcomes.
</li>
<li class="p-4 border border-gray-700 rounded-lg bg-gray-800 shadow-md">
<span class="font-semibold text-white">Monitor & Adjust:</span> Regularly review your dashboard to track your progress. Adjust your plans and asset information as your circumstances change.
</li>
</ol>
</div>
<!-- Our Commitment Section -->
<div class="max-w-screen-md mx-auto px-4">
<h2 class="mb-6 text-3xl font-bold tracking-tight text-white text-center">Our Commitment</h2>
<p class="text-gray-400 text-lg text-center">
Our mission is to empower you with clarity and confidence in your financial decisions. We believe that with the right tools and guidance, anyone can achieve their financial aspirations. Let RCalculator be your guide to financial independence.
</p>
</div>
<% if (!geoData) { %>
<div class="flex flex-col space-y-4 sm:flex-row sm:justify-center sm:space-y-0">
<a href="/signup" class="inline-flex justify-center items-center mt-4 py-3 px-5 text-base font-medium text-center text-white rounded-lg bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-900">
+44 -8
View File
@@ -10,7 +10,7 @@
<!-- Main display -->
<section>
<div class="mt-2 max-w-md mx-auto bg-white px-8 py-6 rounded-lg shadow-md flex flex-col justify-center">
<div class="my-2 mx-4 md:max-w-md md:mx-auto bg-white px-8 py-6 rounded-lg shadow-md flex flex-col justify-center">
<div class="flex flex-row justify-between text-right">
<h1 class="text-lg font-medium">Assets:</h1>
<h1 class="text-lg font-medium"><%= assets.length %></h1>
@@ -24,12 +24,48 @@
</div>
</div>
<div class="w-md my-6 max-w-md mx-auto px-4 flex flex-row justify-between">
<a href="/home" class="text-center w-sm py-2 mx-2 px-4 border
border-transparent rounded-md shadow-sm text-sm font-medium
text-white bg-blue-600 hover:bg-blue-700 focus:outline-none">
Back to Dashboard
</a>
<div class="my-6 md:w-md md:mx-auto px-4 flex flex-row justify-between">
<button
id="dropdown-filters-button"
value=""
data-dropdown-toggle="dropdown-filters"
class="text-center w-sm py-2 mx-2 px-4 border
border-transparent rounded-md shadow-sm text-sm font-medium
text-white bg-blue-600 hover:bg-blue-700 focus:outline-none cursor-pointer"
type="button"
>
<span class="inline-flex items-center">
All Assets
<svg class="w-2.5 h-2.5 ms-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
</svg>
</span>
</button>
<div id="dropdown-filters" class="overflow-y-auto h-40 z-10 hidden divide-y divide-gray-100 rounded-lg shadow-sm w-32 bg-gray-700">
<ul id="dropdown-filters-ul" class="py-2 text-sm text-gray-200" aria-labelledby="dropdown-filters-button">
<li>
<button onclick="selectFilter(this)" type="button" value="all" class="inline-flex w-full px-4 py-2 text-sm text-gray-200 hover:bg-gray-600 hover:text-white" role="menuitem">
<span class="inline-flex items-center">All Assets</span>
</button>
</li>
<li>
<button onclick="selectFilter(this)" type="button" value="other" class="inline-flex w-full px-4 py-2 text-sm text-gray-200 hover:bg-gray-600 hover:text-white" role="menuitem">
<span class="inline-flex items-center">Other Assets</span>
</button>
</li>
<li>
<button onclick="selectFilter(this)" type="button" value="saving" class="inline-flex w-full px-4 py-2 text-sm text-gray-200 hover:bg-gray-600 hover:text-white" role="menuitem">
<span class="inline-flex items-center">Savings Assets</span>
</button>
</li>
<li>
<button onclick="selectFilter(this)" type="button" value="stock" class="inline-flex w-full px-4 py-2 text-sm text-gray-200 hover:bg-gray-600 hover:text-white" role="menuitem">
<span class="inline-flex items-center">Stocks Assets</span>
</button>
</li>
</ul>
</div>
<button
class="text-center w-sm py-2 py-2 mx-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600
hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 cursor-pointer"
@@ -43,7 +79,7 @@
<hr class="h-px my-8 bg-gray-500 border-0 mx-10">
<!-- list each asset and create hidden popup modal for view/edit -->
<section class="mt-6">
<section class="my-6 mx-4">
<% if (assets.length == 0) { %>
<div class="max-w-md mx-auto mb-10 rounded-lg shadow-md text-white font-bold bg-red-400 py-4 text-center">
You have no assets, create a new asset.
+12 -10
View File
@@ -3,7 +3,7 @@
<main class="pt-24 pb-14">
<!-- Buttons -->
<div class="flex justify-end gap-4 px-5 py-6">
<div class="flex md:justify-end justify-center gap-4 px-5 py-6 md:py-0">
<a href="/assets?popup"
id="addAss" class="text-center cursor-pointer min-w-[150px] bg-green-600 px-4 py-2 text-white rounded hover:bg-green-800"
type="button">Add Asset</a>
@@ -14,15 +14,17 @@
<div class="w-full">
<div class="mb-12 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-y-4 gap-x-6">
<% if (plans.length === 0) { %>
<div class="col-span-1 col-start-2 ml-28 mt-25">
<div class="w-86 p-4 bg-white rounded-lg shadow-xl border border-slate-200">
<h1 class="text-2xl block text-center font-semibold text-slate-700">Don't have any retirement plans? </h1>
<div class="mt-4 flex justify-center items-center">
<div class="mt-4 flex justify-center">
<a href="/plans" class="cursor-pointer border-2 border-blue-600 bg-blue-600 text-white py-2 px-6
rounded-md hover:bg-blue-700 hover:border-blue-700 font-semibold
transition-colors duration-200 focus:outline-none ">Make one</a>
</div>
<div class="flex justify-center md:col-start-2">
<div class="col-span-1 mt-25">
<div class="w-86 p-4 bg-white rounded-lg shadow-xl border border-slate-200">
<h1 class="text-2xl block text-center font-semibold text-slate-700">Don't have any retirement plans? </h1>
<div class="mt-4 flex justify-center items-center">
<div class="mt-4 flex justify-center">
<a href="/plans" class="cursor-pointer border-2 border-blue-600 bg-blue-600 text-white py-2 px-6
rounded-md hover:bg-blue-700 hover:border-blue-700 font-semibold
transition-colors duration-200 focus:outline-none ">Make one</a>
</div>
</div>
</div>
</div>
</div>
-10
View File
@@ -15,16 +15,6 @@
</svg>
</div>
</a>
<a href="/settings" class="relative flex flex-col bg-clip-border rounded-xl bg-white text-gray-700 shadow-md">
<div class="p-4 flex items-center justify-between">
<p class="font-sans text-2xl leading-normal font-normal text-blue-gray-600">
Settings
</p>
<svg class="w-[40px] h-[40px]" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="m10 16 4-4-4-4"/>
</svg>
</div>
</a>
<a href="/aboutUs" class="relative flex flex-col bg-clip-border rounded-xl bg-white text-gray-700 shadow-md">
<div class="p-4 flex items-center justify-between">
<p class="font-sans text-2xl leading-normal font-normal text-blue-gray-600">
+1 -1
View File
@@ -1,5 +1,5 @@
<!-- Clickable asset list item -->
<div class="mt-4 max-w-md mx-auto bg-white rounded-lg shadow-md">
<div class="mt-4 max-w-md mx-auto bg-white rounded-lg shadow-md <%= asset.type %>-asset">
<button
onclick="document.getElementById('<%= asset._id %>-modal').showModal()"
style="width: 100%; height: 100%;"
+2 -2
View File
@@ -87,10 +87,10 @@
<li>
<div class="text-center">
<button class="flex flex-row text-white hover:bg-blue-700 focus:ring-4 font-medium rounded-full text-sm focus:outline-none focus:ring-blue-800" type="button" id="drawer-toggle" data-drawer-target="drawer-navigation" data-drawer-placement="right" aria-controls="drawer-navigation">
<svg class="w-[30px] h-[30px] text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
<svg class="w-[30px] h-[30px] text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="white" viewBox="0 0 24 24">
<path fill-rule="evenodd" d="M12 20a7.966 7.966 0 0 1-5.002-1.756l.002.001v-.683c0-1.794 1.492-3.25 3.333-3.25h3.334c1.84 0 3.333 1.456 3.333 3.25v.683A7.966 7.966 0 0 1 12 20ZM2 12C2 6.477 6.477 2 12 2s10 4.477 10 10c0 5.5-4.44 9.963-9.932 10h-.138C6.438 21.962 2 17.5 2 12Zm10-5c-1.84 0-3.333 1.455-3.333 3.25S10.159 13.5 12 13.5c1.84 0 3.333-1.455 3.333-3.25S13.841 7 12 7Z" clip-rule="evenodd"/>
</svg>
<svg class="w-[30px] h-[30px] text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<svg class="w-[30px] h-[30px] text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="white" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M5 7h14M5 12h14M5 17h14"/>
</svg>