Skip to content

Commit

Permalink
Merge pull request #34 from dheffer/backend-garage-api
Browse files Browse the repository at this point in the history
ViewInfo functional & VehicleHistory removal and editing now functional
  • Loading branch information
BrandonJohnson97 authored Mar 31, 2024
2 parents cacc587 + 9625f6a commit e07bd49
Show file tree
Hide file tree
Showing 17 changed files with 673 additions and 225 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# ignoring modules
node_modules
backend/.env
.env
.env
Project_Default.xml
package-lock.json
37 changes: 8 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# **Predictive Vehicle Maintenance System**
[![GitHub privacy-policy](https://img.shields.io/badge/privacy-policy-blue.svg)](https://github.com/dheffer/PredictiveVehicleMaintenanceSystem/privacy-policy.md)
# **Driveline**
[![GitHub privacy-policy](https://img.shields.io/badge/privacy-policy-blue.svg)](https://github.com/dheffer/PredictiveVehicleMaintenanceSystem/blob/main/privacy-policy.md)
[![GitHub issues](https://img.shields.io/github/issues/dheffer/PredictiveVehicleMaintenanceSystem.svg)](https://github.com/dheffer/PredictiveVehicleMaintenanceSystem/issues)
[![GitHub stars](https://img.shields.io/github/stars/dheffer/PredictiveVehicleMaintenanceSystem.svg)](https://github.com/dheffer/PredictiveVehicleMaintenanceSystem/stargazers)

#### Driveline - A predictive vehicle maintenance system for our Capstone Project in the Winter 2024 semester.
#### A predictive vehicle maintenance system for our Capstone Project in the Winter 2024 semester.

## Description:
Driveline is a web application designed to streamline and automate the process of vehicle maintenance tracking and notification. The primary goal of this application is to provide users with timely alerts regarding recommended upcoming maintenance tasks for their vehicles. Additionally, users will have access to their personalized 'Garage', where they can upload, manage, and view maintenance information about the vehicles they own.
Expand All @@ -12,35 +11,15 @@ Driveline is a web application designed to streamline and automate the process o

## Key Features:
- [x] **OAuth Login Page:** Utilizes OAuth for secure login, enabling users to create profiles seamlessly.
- [ ] **User Profile & Garage:** Each user will have a dedicated profile and a 'My Garage' page containing personal information and details of their vehicle(s).
- [ ] **Vehicle Management:** Users can upload, edit, and remove vehicles from their garage with ease.
- [x] **Service History & Upcoming Services:** Users can view detailed service history, upcoming maintenance tasks, and general vehicle information when selecting a vehicle in their garage.
- [ ] **Settings Configuration:** The settings page empowers users to customize their profile and app settings, including preferences like light & dark mode, and control over the information they wish to display publicly.
- [ ] **Vehicle Management:** Users can upload, edit, and remove vehicles from their Garage with ease.
- [ ] **Service History & Upcoming Services:** Users can view detailed service history, upcoming maintenance tasks, and general vehicle information when selecting a vehicle in their garage.
- [ ] **Settings Configuration:** The settings page allows users to customize their profile and app settings, including preferences like light & dark mode

## Technologies Used:
- Frontend: HTML5, CSS3, JavaScript, React
- Backend: Node.js, Express.js
- Database: MongoDB
- Authentication: OAuth

## Installation:
1. Clone the repository:
```bash
git clone https://github.com/dheffer/PredictiveVehicleMaintenanceSystem
```
2. Navigate to the project directory:
```bash
cd PredictiveVehicleMaintenanceSystem
```
3. Install dependencies:
```bash
npm install
```
4. Start the server:
```bash
npm start
```
5. Access the application at `http://localhost:3000` in your web browser.

## License:
This project is licensed under the [MIT License](LICENSE).
## Privacy Policy:
By using Driveline, you accept the terms stated under our [Privacy Policy](privacy-policy.md).
204 changes: 167 additions & 37 deletions backend/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ import { oauthClient } from './OauthClient.js';
import 'dotenv/config';
import client from "./mongo.js";
import mongo from "./mongo.js"
import client from './mongo.js'
import {parse} from "dotenv";


const CLIENT_ID = process.env.GOOGLE_CLIENT_ID;
const CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET;
const DATABASE = client.db("vehicleDB");
const EMAIL = process.env.EMAIL;


console.log("\n\nPROCESS APP PAGE"+CLIENT_ID)
console.log("PROCESS APP PAGE"+CLIENT_SECRET)
Expand Down Expand Up @@ -103,8 +106,8 @@ app.get('/api/user', async (req, res) => {

console.log("Decoded: "+decoded);

const database = client.db("vehicleDB");
const users = database.collection("users");
const DATABASE = client.db("vehicleDB");
const users = DATABASE.collection("users");

const user = await users.findOne({email: decoded.email});
console.log("AUTHORIZ USER: "+user);
Expand All @@ -129,9 +132,8 @@ const updateOrCreateUserFromOauth = async (oauthUserInfo) => {

console.log(name);
console.log(email);

const database = client.db("vehicleDB");
const users = database.collection("users");

const users = DATABASE.collection("users");

const existingUser = await users.findOne({email})

Expand All @@ -148,35 +150,112 @@ const updateOrCreateUserFromOauth = async (oauthUserInfo) => {
}
}

// TODO: Configure this route using the getVehicleConfig function below
app.get('/api/get-configuration', async (req, res) => {
const database = client.db("vehicleDB");
const message = database.collection("configurations");
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/***
* This route is used to get the vehicle information from the DATABASE
* @param configId - The config_id of the vehicle
*/
app.get('/api/get-vehicle-info', async (req, res) => {
const vehicle = DATABASE.collection("configurations");
const configId = req.query.configId;
const getConfiguration = await vehicle.findOne({config_id: parseInt(configId)});

const docObject = await message.findOne({config_id: 402001368});
res.send(docObject);
res.json(getConfiguration);
});

const getVehicleConfig = async (config_id) => {
const database = client.db("vehicleDB");
const message = database.collection("configurations");
/***
* This route is used to get the vehicle history from the DATABASE
* @param configId - The config_id of the vehicle
* @param email - The email of the user
*/

const docObject = await message.findOne({config_id: config_id});
return docObject;
}
app.get('/api/get-vehicle-history', async (req, res) => {
const history = DATABASE.collection("user_vehicle_info");
const configId = req.query.configId;

const getHistory = await history.aggregate([
{
$match: {
config_id: parseInt(configId),
email: EMAIL
}
},
{
$project: {
_id: 0,
completed_maintenance: 1
}
}
]).toArray();
res.send(getHistory);
});

app.post('/api/update-maintenance-history', async (req, res) => {
try {
const garage = DATABASE.collection("user_vehicle_info");

const {
old_type, old_date, old_maintenance, old_cost,
new_type, new_date, new_maintenance, new_cost
} = req.body;
const update = await garage.updateOne(
{
email: EMAIL,
"completed_maintenance.type": old_type,
"completed_maintenance.date": old_date,
"completed_maintenance.maintenance": old_maintenance,
"completed_maintenance.cost": parseInt(old_cost)
},
{
$set: {
"completed_maintenance.$.type": new_type,
"completed_maintenance.$.date": new_date,
"completed_maintenance.$.maintenance": new_maintenance,
"completed_maintenance.$.cost": parseInt(new_cost)
}
}
);
return res.json(update.modifiedCount);
} catch (error) {
return res.status(500).json({message: error.message});
}

});

app.delete('/api/delete-maintenance-history', async (req, res) => {
const garage = DATABASE.collection("user_vehicle_info");

const { type, date, maintenance, cost } = req.body;
const deletion = await garage.updateOne(
{
email: EMAIL
},
{$pull:
{
completed_maintenance: {
type: type,
date: date,
maintenance: maintenance,
cost: cost
}
}
}
);
return res.json(deletion.modifiedCount);
});

/***
* This route is used to get the user's vehicles from the database
* This route is used to get the user's vehicles from the DATABASE
*/
app.get('/api/get-user-vehicles', async (req, res) => {
const database = client.db("vehicleDB");
const garage = database.collection("user_garage");
const garage = DATABASE.collection("user_garage");

const vehicles = await garage.aggregate([
{
$match: {
user_id: 'dheffer'
email: EMAIL
}
},
{
Expand All @@ -197,31 +276,34 @@ app.get('/api/get-user-vehicles', async (req, res) => {
}
}
]).toArray();

/*
for (let vehicle of vehicles) {
let v = vehicle.configurations
console.log(`Year: ${v.year}\t Make: ${v.make}\t Model: ${v.model}`);
}
*/


res.send(vehicles);
});
app.delete('/api/delete-user-vehicle', async (req, res) => {
const garage = DATABASE.collection("user_garage");

const { config_id } = req.body;
const deletion = await garage.updateOne(
{email: EMAIL},
{$pull: { vehicle_config_ids: config_id } }
);
return res.json(deletion.modifiedCount);
});

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//const config_id = 401988727;
// app.get('/api/get-maintenance', async (req , res) => {
// const database = client.db("vehicleDB");
// const message = database.collection("maintenance");
// const DATABASE = client.db("vehicleDB");
// const message = DATABASE.collection("maintenance");
//
// const docObject = await message.findOne({config_id: 401988727});
// await console.log(docObject);
// res.send(docObject.message);
// })

app.get('/api/get-maintenance', async (req , res) => {
const database = client.db("vehicleDB");
const message = database.collection("maintenance");
const message = DATABASE.collection("maintenance");

// const docObject = await message.findOne({ config_id: { $eq: 401988727} });

Expand All @@ -239,8 +321,7 @@ const selected_transmission = "8A";

//TODO: Request to get a config_id given a vehicle's Year, Make, Model, Engine, and Transmission.
app.get('/api/get-config-id', async (req, res) => {
const database = client.db("vehicleDB");
const message = database.collection("configurations");
const message = DATABASE.collection("configurations");

//Use for loop to iterate through all the objects in the collection and get the config_id for the object that matches the selected year, make, model, engine, and transmission.
const docObject = await message.find({year: selected_year, make: selected_make, model: selected_model, engine: selected_engine, transmission: selected_transmission});
Expand All @@ -256,6 +337,55 @@ app.get('/api/get-config-id', async (req, res) => {
//TODO: Request to get a list of all years (Non-repeating).

//TODO: Request to get a list of all makes given a year (Non-repeating).
app.get('/api/get-makes', async (req, res) => {
console.log("hit get makes route");

const carYear = req.query.year;
console.log("year INSIDE MAKES: "+carYear);

if(!carYear) {
return res.status(400).json({message: "Missing required fields"});
}

const database = client.db("vehicleDB");
const configurations = database.collection("configurations");

const makesYear = await configurations.find({year: parseInt(carYear)});
console.log("makesYear " + makesYear)

const makesGroup = await configurations.aggregate([
{ $match: { year: parseInt(carYear) }},
{ $group: { _id: "$make", makes: { $addToSet: "$make" } }}
]).toArray();
/*
const makesGroup = await configurations.aggregate([
{ $match: { year: parseInt(carYear) }},
{ $project: { _id: 0, make: 1 }}
]).toArray();
*/
console.log("makesGroup " + makesGroup)

const makesSort = await configurations.aggregate([
{ $match: { year: parseInt(carYear) }},
{ $group: { _id: "$make", makes: { $addToSet: "$make" } }},
{ $sort: { _id: 1 }}
]).toArray();

console.log("makesSort " + makesSort)

// const makes = await configurations.aggregate([
// { $match: { year: year }},
// { $group: { _id: "$make", makes: { $addToSet: "$make" } }},
// { $sort: { _id: 1 }}
// ]).toArray();
// console.log("makes " + makes)

// const uniqueMakes = makes.map(make => make._id);

// console.log("makes " +uniqueMakes)
res.send(makesSort);
})

//TODO: Request to get a list of all models given a year and make (Non-repeating).

Expand Down
5 changes: 1 addition & 4 deletions backend/src/mongo.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ import { MongoClient, ServerApiVersion } from "mongodb";
import 'dotenv/config'


// const uri = process.env.MONGO_URI;
const uri = 'mongodb+srv://user:[email protected]/'
const uri = 'mongodb+srv://brandon:[email protected]/';
// const uri ='mongodb+srv://<username>:<password>]@driveline-cluster-01.kiepke5.mongodb.net/'
const uri = process.env.MONGO_URI;

// Create a MongoClient with a MongoClientOptions object to set the Stable API version
const client = new MongoClient(uri, {
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/pages/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {useState} from "react";

function App() {
const [garageInfo, setGarageInfo] = useState();
const [configId, setConfigId] = useState();
const authenticated = localStorage.getItem('token') !== null;
return (
<BrowserRouter>
Expand All @@ -26,10 +27,9 @@ function App() {
<>
<Route path="/garage" element={<Garage info={garageInfo} setInfo={setGarageInfo}/>}/>
<Route path="/garage/add" element={<AddVehicle />}/>
<Route path="/garage/remove/:vehicle" element={<RemoveVehicle />}/>

<Route path="/garage/vehicle-info/:vehicle" element={<VehicleInfo />} />
<Route path="/garage/vehicle-history/:vehicle" element={<VehicleHistory />} />
<Route path="/garage/vehicle-info/:vehicle/*" element={<VehicleInfo configId={configId} setConfig={setConfigId}/>} />
<Route path="/garage/vehicle-history/:vehicle/*" element={<VehicleHistory configId={configId} setConfig={setConfigId}/>} />
<Route path="/garage/vehicle-history/upload" element={<UploadVehicleHistory />} />
<Route path="/garage/vehicle-history/manual" element={<ManualVehicleHistory />} />

Expand Down
Loading

0 comments on commit e07bd49

Please sign in to comment.