diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000000..b369958e81 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,57 @@ +name: 'Lint Code' + +on: + push: + branches: [master, main] + pull_request: + branches: [master, main] + +jobs: + lint_python: + name: Lint Python Files + runs-on: ubuntu-latest + + steps: + + - name: Checkout Repository + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.12 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 + - name: Print working directory + run: pwd + + - name: Run Linter + run: | + pwd + # This command finds all Python files recursively and runs flake8 on them + find . -name "*.py" -exec flake8 {} + + echo "Linted all the python files successfully" + lint_js: + name: Lint JavaScript Files + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: 14 + + - name: Install JSHint + run: npm install jshint --global + + - name: Run Linter + run: | + # This command finds all JavaScript files recursively and runs JSHint on them + find ./server/database -name "*.js" -exec jshint {} + + echo "Linted all the js files successfully" diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 0000000000..fc4ff4f381 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,25 @@ +FROM python:3.12.0-slim-bookworm + + ENV PYTHONBUFFERED 1 + ENV PYTHONWRITEBYTECODE 1 + + ENV APP=/app + + # Change the workdir. + WORKDIR $APP + + # Install the requirements + COPY requirements.txt $APP + + RUN pip3 install -r requirements.txt + + # Copy the rest of the files + COPY . $APP + + EXPOSE 8000 + + RUN chmod +x /app/entrypoint.sh + + ENTRYPOINT ["/bin/bash","/app/entrypoint.sh"] + + CMD ["gunicorn", "--bind", ":8000", "--workers", "3", "djangoproj.wsgi"] \ No newline at end of file diff --git a/server/carsInventory/Dockerfile b/server/carsInventory/Dockerfile new file mode 100644 index 0000000000..9065af91ae --- /dev/null +++ b/server/carsInventory/Dockerfile @@ -0,0 +1,13 @@ +FROM node:18.12.1-bullseye-slim + +RUN npm install -g npm@9.1.3 + +ADD package.json . +ADD app.js . +ADD data/car_records.json . +COPY . . +RUN npm install + +EXPOSE 3050 + +CMD [ "node", "app.js" ] \ No newline at end of file diff --git a/server/carsInventory/app.js b/server/carsInventory/app.js new file mode 100644 index 0000000000..af64fa046d --- /dev/null +++ b/server/carsInventory/app.js @@ -0,0 +1,125 @@ +/*jshint esversion: 8 */ + +const express = require('express'); +const mongoose = require('mongoose'); +const fs = require('fs'); +const cors = require('cors'); + +const app = express(); +const port = 3050; + +app.use(cors()); +app.use(express.urlencoded({ extended: false })); + +const carsData = JSON.parse(fs.readFileSync('car_records.json', 'utf8')); + +mongoose.connect('mongodb://mongo_db:27017/', { dbName: 'dealershipsDB' }) + .then(() => console.log('MongoDB connected')) + .catch(err => console.error('MongoDB connection error:', err)); + + +const Cars = require('./inventory'); + +try { + + Cars.deleteMany({}).then(() => { + Cars.insertMany(carsData.cars); + }); +} catch (error) { + console.error(error); + // Handle errors properly here +} + +app.get('/', async (req, res) => { + res.send('Welcome to the Mongoose API'); +}); + + + +app.get('/cars/:id', async (req, res) => { + try { + const documents = await Cars.find({dealer_id: req.params.id}); + res.json(documents); + } catch (error) { + res.status(500).json({ error: 'Error fetching reviews' }); + } +}); + +app.get('/carsbymake/:id/:make', async (req, res) => { + try { + const documents = await Cars.find({dealer_id: req.params.id, make: req.params.make}); + res.json(documents); + } catch (error) { + res.status(500).json({ error: 'Error fetching reviews by car make and model' }); + } +}); + +app.get('/carsbymodel/:id/:model', async (req, res) => { + try { + const documents = await Cars.find({ dealer_id: req.params.id, model: req.params.model }); + res.json(documents); + } catch (error) { + res.status(500).json({ error: 'Error fetching dealers by ID' }); + } +}); + +app.get('/carsbymaxmileage/:id/:mileage', async (req, res) => { + try { + let mileage = parseInt(req.params.mileage) + let condition = {} + if(mileage === 50000) { + condition = { $lte : mileage} + } else if (mileage === 100000){ + condition = { $lte : mileage, $gt : 50000} + } else if (mileage === 150000){ + condition = { $lte : mileage, $gt : 100000} + } else if (mileage === 200000){ + condition = { $lte : mileage, $gt : 150000} + } else { + condition = { $gt : 200000} + } + const documents = await Cars.find({ dealer_id: req.params.id, mileage : condition }); + res.json(documents); + } catch (error) { + res.status(500).json({ error: 'Error fetching dealers by ID' }); + } +}); + + +app.get('/carsbyprice/:id/:price', async (req, res) => { + try { + let price = parseInt(req.params.price) + let condition = {} + if(price === 20000) { + condition = { $lte : price} + } else if (price=== 40000){ + console.log("\n \n \n "+ price) + condition = { $lte : price, $gt : 20000} + } else if (price === 60000){ + condition = { $lte : price, $gt : 40000} + } else if (price === 80000){ + condition = { $lte : price, $gt : 60000} + } else { + condition = { $gt : 80000} + } + const documents = await Cars.find({ dealer_id: req.params.id, price : condition }); + res.json(documents); + } catch (error) { + res.status(500).json({ error: 'Error fetching dealers by ID' }); + } +}); + + + +app.get('/carsbyyear/:id/:year', async (req, res) => { + try { + const documents = await Cars.find({ dealer_id: req.params.id, year : { $gte :req.params.year }}); + res.json(documents); + } catch (error) { + res.status(500).json({ error: 'Error fetching dealers by ID' }); + } +}); + +app.listen(port, () => { + console.log(`Server is running on http://localhost:${port}`); +}); \ No newline at end of file diff --git a/server/carsInventory/data/car_records.json b/server/carsInventory/data/car_records.json new file mode 100644 index 0000000000..c2bb813f90 --- /dev/null +++ b/server/carsInventory/data/car_records.json @@ -0,0 +1,1930 @@ +{ + "cars": [ + { + "make": "Nissan", + "model": "Pathfinder", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 1, + "mileage": 15000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Seltos", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 8, + "mileage": 8000, + "price": 15000 + }, + { + "make": "Audi", + "model": "A4", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 15, + "mileage": 12000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLE", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 22, + "mileage": 5000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Camry", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 30, + "mileage": 10000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Rogue", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 2, + "mileage": 6000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Telluride", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 11, + "mileage": 3000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q5", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 18, + "mileage": 20000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "C-Class", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 25, + "mileage": 7000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Highlander", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 33, + "mileage": 15000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Altima", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 5, + "mileage": 18000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Sportage", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 12, + "mileage": 12000, + "price": 15000 + }, + { + "make": "Audi", + "model": "A3", + "bodyType": "Hatchback", + "year": 2020, + "dealer_id": 19, + "mileage": 8000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "E-Class", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 26, + "mileage": 3000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "RAV4", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 35, + "mileage": 25000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Maxima", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 3, + "mileage": 10000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Cadenza", + "bodyType": "Sedan", + "year": 2020, + "dealer_id": 14, + "mileage": 15000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q7", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 21, + "mileage": 5000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLC", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 28, + "mileage": 7000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Corolla", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 38, + "mileage": 12000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Murano", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 6, + "mileage": 20000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Optima", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 16, + "mileage": 4000, + "price": 15000 + }, + { + "make": "Audi", + "model": "S5", + "bodyType": "Coupe", + "year": 2022, + "dealer_id": 23, + "mileage": 6000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "S-Class", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 30, + "mileage": 9000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Sienna", + "bodyType": "Minivan", + "year": 2020, + "dealer_id": 41, + "mileage": 30000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "370Z", + "bodyType": "Coupe", + "year": 2023, + "dealer_id": 8, + "mileage": 1500, + "price": 30000 + }, + { + "make": "Kia", + "model": "Rio", + "bodyType": "Hatchback", + "year": 2022, + "dealer_id": 18, + "mileage": 18000, + "price": 15000 + }, + { + "make": "Audi", + "model": "TT", + "bodyType": "Convertible", + "year": 2021, + "dealer_id": 25, + "mileage": 10000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "CLA", + "bodyType": "Sedan", + "year": 2020, + "dealer_id": 33, + "mileage": 22000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Tacoma", + "bodyType": "Pickup", + "year": 2023, + "dealer_id": 45, + "mileage": 8000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Versa", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 10, + "mileage": 14000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Stinger", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 22, + "mileage": 18000, + "price": 15000 + }, + { + "make": "Audi", + "model": "A5", + "bodyType": "Convertible", + "year": 2020, + "dealer_id": 28, + "mileage": 10000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLA", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 35, + "mileage": 5000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Prius", + "bodyType": "Hatchback", + "year": 2022, + "dealer_id": 42, + "mileage": 12000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Armada", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 2, + "mileage": 8000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Niro", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 12, + "mileage": 15000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q3", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 19, + "mileage": 3000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLE Coupe", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 25, + "mileage": 7000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Avalon", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 30, + "mileage": 10000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Sentra", + "bodyType": "Sedan", + "year": 2020, + "dealer_id": 7, + "mileage": 20000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Soul", + "bodyType": "Hatchback", + "year": 2023, + "dealer_id": 15, + "mileage": 4000, + "price": 15000 + }, + { + "make": "Audi", + "model": "S7", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 23, + "mileage": 6000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLB", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 31, + "mileage": 9000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "4Runner", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 38, + "mileage": 25000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Juke", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 9, + "mileage": 1500, + "price": 30000 + }, + { + "make": "Kia", + "model": "Forte", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 18, + "mileage": 17000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q8", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 26, + "mileage": 11000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "A-Class", + "bodyType": "Sedan", + "year": 2020, + "dealer_id": 33, + "mileage": 22000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Tundra", + "bodyType": "Pickup", + "year": 2023, + "dealer_id": 46, + "mileage": 7500, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Versa", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 9, + "mileage": 15000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Forte", + "bodyType": "Sedan", + "year": 2020, + "dealer_id": 19, + "mileage": 12000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q3", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 26, + "mileage": 8000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "A-Class", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 34, + "mileage": 3000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Prius", + "bodyType": "Hatchback", + "year": 2021, + "dealer_id": 40, + "mileage": 25000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Sentra", + "bodyType": "Sedan", + "year": 2020, + "dealer_id": 5, + "mileage": 10000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Niro", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 14, + "mileage": 15000, + "price": 15000 + }, + { + "make": "Audi", + "model": "A6", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 21, + "mileage": 5000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLA", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 28, + "mileage": 7000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Yaris", + "bodyType": "Hatchback", + "year": 2020, + "dealer_id": 37, + "mileage": 12000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Cube", + "bodyType": "Hatchback", + "year": 2023, + "dealer_id": 7, + "mileage": 20000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Stinger", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 17, + "mileage": 4000, + "price": 15000 + }, + { + "make": "Audi", + "model": "A5", + "bodyType": "Convertible", + "year": 2021, + "dealer_id": 24, + "mileage": 6000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLS", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 32, + "mileage": 9000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "4Runner", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 43, + "mileage": 30000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Juke", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 10, + "mileage": 1500, + "price": 30000 + }, + { + "make": "Kia", + "model": "Soul", + "bodyType": "Hatchback", + "year": 2021, + "dealer_id": 20, + "mileage": 18000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q8", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 27, + "mileage": 10000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "AMG GT", + "bodyType": "Coupe", + "year": 2023, + "dealer_id": 36, + "mileage": 22000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Avalon", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 47, + "mileage": 8000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Armada", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 12, + "mileage": 22000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Telluride", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 21, + "mileage": 18000, + "price": 15000 + }, + { + "make": "Audi", + "model": "S3", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 28, + "mileage": 8000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "M-Class", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 37, + "mileage": 3000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Land Cruiser", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 44, + "mileage": 25000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "370Z", + "bodyType": "Coupe", + "year": 2020, + "dealer_id": 5, + "mileage": 10000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Rio", + "bodyType": "Hatchback", + "year": 2023, + "dealer_id": 15, + "mileage": 15000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q5", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 22, + "mileage": 5000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "C-Class", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 29, + "mileage": 7000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Highlander", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 38, + "mileage": 12000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Versa", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 6, + "mileage": 20000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Seltos", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 16, + "mileage": 4000, + "price": 15000 + }, + { + "make": "Audi", + "model": "A4", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 23, + "mileage": 6000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLE", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 30, + "mileage": 9000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Camry", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 39, + "mileage": 30000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Rogue", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 7, + "mileage": 1500, + "price": 30000 + }, + { + "make": "Kia", + "model": "Telluride", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 17, + "mileage": 18000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q3", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 24, + "mileage": 10000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLC", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 33, + "mileage": 22000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Corolla", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 46, + "mileage": 8000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Murano", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 8, + "mileage": 18000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Optima", + "bodyType": "Sedan", + "year": 2020, + "dealer_id": 18, + "mileage": 12000, + "price": 15000 + }, + { + "make": "Audi", + "model": "S5", + "bodyType": "Coupe", + "year": 2023, + "dealer_id": 25, + "mileage": 6000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "S-Class", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 34, + "mileage": 9000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Sienna", + "bodyType": "Minivan", + "year": 2021, + "dealer_id": 43, + "mileage": 30000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Altima", + "bodyType": "Sedan", + "year": 2020, + "dealer_id": 9, + "mileage": 15000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Sportage", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 19, + "mileage": 12000, + "price": 15000 + }, + { + "make": "Audi", + "model": "A3", + "bodyType": "Hatchback", + "year": 2022, + "dealer_id": 26, + "mileage": 8000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "E-Class", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 35, + "mileage": 3000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "RAV4", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 42, + "mileage": 25000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Maxima", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 11, + "mileage": 10000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Cadenza", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 20, + "mileage": 15000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q7", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 27, + "mileage": 5000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLC", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 36, + "mileage": 7000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Yaris", + "bodyType": "Hatchback", + "year": 2023, + "dealer_id": 45, + "mileage": 12000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Cube", + "bodyType": "Hatchback", + "year": 2022, + "dealer_id": 13, + "mileage": 20000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Stinger", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 22, + "mileage": 4000, + "price": 15000 + }, + { + "make": "Audi", + "model": "A5", + "bodyType": "Convertible", + "year": 2020, + "dealer_id": 29, + "mileage": 6000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLS", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 38, + "mileage": 9000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "4Runner", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 47, + "mileage": 30000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Juke", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 14, + "mileage": 1500, + "price": 30000 + }, + { + "make": "Kia", + "model": "Soul", + "bodyType": "Hatchback", + "year": 2020, + "dealer_id": 23, + "mileage": 18000, + "price": 15000 + }, + { + "make": "Audi", + "model": "TT", + "bodyType": "Convertible", + "year": 2023, + "dealer_id": 30, + "mileage": 10000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "CLA", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 39, + "mileage": 22000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Tacoma", + "bodyType": "Pickup", + "year": 2021, + "dealer_id": 48, + "mileage": 8000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Versa", + "bodyType": "Sedan", + "year": 2020, + "dealer_id": 15, + "mileage": 15000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Forte", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 24, + "mileage": 12000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q3", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 31, + "mileage": 8000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "A-Class", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 40, + "mileage": 3000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Prius", + "bodyType": "Hatchback", + "year": 2020, + "dealer_id": 49, + "mileage": 25000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Armada", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 1, + "mileage": 22000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Stinger", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 8, + "mileage": 18000, + "price": 15000 + }, + { + "make": "Audi", + "model": "S3", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 15, + "mileage": 8000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "M-Class", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 22, + "mileage": 3000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Land Cruiser", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 29, + "mileage": 25000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "370Z", + "bodyType": "Coupe", + "year": 2020, + "dealer_id": 6, + "mileage": 10000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Rio", + "bodyType": "Hatchback", + "year": 2023, + "dealer_id": 16, + "mileage": 15000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q5", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 23, + "mileage": 5000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "C-Class", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 30, + "mileage": 7000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Highlander", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 39, + "mileage": 12000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Versa", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 7, + "mileage": 20000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Seltos", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 17, + "mileage": 4000, + "price": 15000 + }, + { + "make": "Audi", + "model": "A4", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 24, + "mileage": 6000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLE", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 31, + "mileage": 9000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Camry", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 40, + "mileage": 30000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Rogue", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 8, + "mileage": 1500, + "price": 30000 + }, + { + "make": "Kia", + "model": "Telluride", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 18, + "mileage": 18000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q3", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 25, + "mileage": 10000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLC", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 34, + "mileage": 22000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Corolla", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 47, + "mileage": 8000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Murano", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 9, + "mileage": 18000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Optima", + "bodyType": "Sedan", + "year": 2020, + "dealer_id": 19, + "mileage": 12000, + "price": 15000 + }, + { + "make": "Audi", + "model": "S5", + "bodyType": "Coupe", + "year": 2023, + "dealer_id": 26, + "mileage": 6000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "S-Class", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 35, + "mileage": 9000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Sienna", + "bodyType": "Minivan", + "year": 2021, + "dealer_id": 44, + "mileage": 30000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Altima", + "bodyType": "Sedan", + "year": 2020, + "dealer_id": 10, + "mileage": 15000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Sportage", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 20, + "mileage": 12000, + "price": 15000 + }, + { + "make": "Audi", + "model": "A3", + "bodyType": "Hatchback", + "year": 2022, + "dealer_id": 27, + "mileage": 8000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "E-Class", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 36, + "mileage": 3000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "RAV4", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 43, + "mileage": 25000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Maxima", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 11, + "mileage": 10000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Cadenza", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 21, + "mileage": 15000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q7", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 28, + "mileage": 5000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLC", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 37, + "mileage": 7000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Yaris", + "bodyType": "Hatchback", + "year": 2023, + "dealer_id": 46, + "mileage": 12000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Cube", + "bodyType": "Hatchback", + "year": 2022, + "dealer_id": 13, + "mileage": 20000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Stinger", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 22, + "mileage": 4000, + "price": 15000 + }, + { + "make": "Audi", + "model": "A5", + "bodyType": "Convertible", + "year": 2020, + "dealer_id": 29, + "mileage": 6000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLS", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 38, + "mileage": 9000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "4Runner", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 47, + "mileage": 30000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Juke", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 14, + "mileage": 1500, + "price": 30000 + }, + { + "make": "Kia", + "model": "Soul", + "bodyType": "Hatchback", + "year": 2020, + "dealer_id": 23, + "mileage": 18000, + "price": 15000 + }, + { + "make": "Audi", + "model": "TT", + "bodyType": "Convertible", + "year": 2023, + "dealer_id": 30, + "mileage": 10000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "CLA", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 39, + "mileage": 22000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Tacoma", + "bodyType": "Pickup", + "year": 2021, + "dealer_id": 48, + "mileage": 8000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Versa", + "bodyType": "Sedan", + "year": 2020, + "dealer_id": 15, + "mileage": 15000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Forte", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 24, + "mileage": 12000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q3", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 31, + "mileage": 8000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "A-Class", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 40, + "mileage": 3000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Prius", + "bodyType": "Hatchback", + "year": 2020, + "dealer_id": 49, + "mileage": 25000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Armada", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 1, + "mileage": 22000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Stinger", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 8, + "mileage": 18000, + "price": 15000 + }, + { + "make": "Audi", + "model": "S3", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 15, + "mileage": 8000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "M-Class", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 22, + "mileage": 3000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Land Cruiser", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 29, + "mileage": 25000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "370Z", + "bodyType": "Coupe", + "year": 2020, + "dealer_id": 6, + "mileage": 10000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Rio", + "bodyType": "Hatchback", + "year": 2023, + "dealer_id": 16, + "mileage": 15000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q5", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 23, + "mileage": 5000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "C-Class", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 30, + "mileage": 7000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Highlander", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 39, + "mileage": 12000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Versa", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 7, + "mileage": 20000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Seltos", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 17, + "mileage": 4000, + "price": 15000 + }, + { + "make": "Audi", + "model": "A4", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 24, + "mileage": 6000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLE", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 31, + "mileage": 9000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Camry", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 40, + "mileage": 30000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Rogue", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 8, + "mileage": 1500, + "price": 30000 + }, + { + "make": "Kia", + "model": "Telluride", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 18, + "mileage": 18000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q3", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 25, + "mileage": 10000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLC", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 34, + "mileage": 22000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Corolla", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 47, + "mileage": 8000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Murano", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 9, + "mileage": 18000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Optima", + "bodyType": "Sedan", + "year": 2020, + "dealer_id": 19, + "mileage": 12000, + "price": 15000 + }, + { + "make": "Audi", + "model": "S5", + "bodyType": "Coupe", + "year": 2023, + "dealer_id": 26, + "mileage": 6000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "S-Class", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 35, + "mileage": 9000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Sienna", + "bodyType": "Minivan", + "year": 2021, + "dealer_id": 44, + "mileage": 30000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Altima", + "bodyType": "Sedan", + "year": 2020, + "dealer_id": 10, + "mileage": 15000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Sportage", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 20, + "mileage": 12000, + "price": 15000 + }, + { + "make": "Audi", + "model": "A3", + "bodyType": "Hatchback", + "year": 2022, + "dealer_id": 27, + "mileage": 8000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "E-Class", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 36, + "mileage": 3000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "RAV4", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 43, + "mileage": 25000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Maxima", + "bodyType": "Sedan", + "year": 2023, + "dealer_id": 11, + "mileage": 10000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Cadenza", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 21, + "mileage": 15000, + "price": 15000 + }, + { + "make": "Audi", + "model": "Q7", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 28, + "mileage": 5000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLC", + "bodyType": "SUV", + "year": 2020, + "dealer_id": 37, + "mileage": 7000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "Yaris", + "bodyType": "Hatchback", + "year": 2023, + "dealer_id": 46, + "mileage": 12000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Cube", + "bodyType": "Hatchback", + "year": 2022, + "dealer_id": 13, + "mileage": 20000, + "price": 30000 + }, + { + "make": "Kia", + "model": "Stinger", + "bodyType": "Sedan", + "year": 2021, + "dealer_id": 22, + "mileage": 4000, + "price": 15000 + }, + { + "make": "Audi", + "model": "A5", + "bodyType": "Convertible", + "year": 2020, + "dealer_id": 29, + "mileage": 6000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "GLS", + "bodyType": "SUV", + "year": 2023, + "dealer_id": 38, + "mileage": 9000, + "price": 60000 + }, + { + "make": "Toyota", + "model": "4Runner", + "bodyType": "SUV", + "year": 2022, + "dealer_id": 47, + "mileage": 30000, + "price": 25000 + }, + { + "make": "Nissan", + "model": "Juke", + "bodyType": "SUV", + "year": 2021, + "dealer_id": 14, + "mileage": 1500, + "price": 30000 + }, + { + "make": "Kia", + "model": "Soul", + "bodyType": "Hatchback", + "year": 2020, + "dealer_id": 23, + "mileage": 18000, + "price": 15000 + }, + { + "make": "Audi", + "model": "TT", + "bodyType": "Convertible", + "year": 2023, + "dealer_id": 30, + "mileage": 10000, + "price": 70000 + }, + { + "make": "Mercedes", + "model": "CLA", + "bodyType": "Sedan", + "year": 2022, + "dealer_id": 39, + "mileage": 22000, + "price": 60000 + } + ] +} \ No newline at end of file diff --git a/server/carsInventory/docker-compose.yml b/server/carsInventory/docker-compose.yml new file mode 100644 index 0000000000..0d381d8666 --- /dev/null +++ b/server/carsInventory/docker-compose.yml @@ -0,0 +1,23 @@ +version: '3.9' + +services: + # Mongodb service + mongo_db: + container_name: carsInventory_container + image: mongo:latest + ports: + - 27018:27017 + restart: always + volumes: + - mongo_data:/data/db + + # Node api service + api: + image: nodeapp + ports: + - 3050:3050 + depends_on: + - mongo_db + +volumes: + mongo_data: {} \ No newline at end of file diff --git a/server/carsInventory/inventory.js b/server/carsInventory/inventory.js new file mode 100644 index 0000000000..46e871d7c8 --- /dev/null +++ b/server/carsInventory/inventory.js @@ -0,0 +1,38 @@ +/*jshint esversion: 8 */ +const { Int32 } = require('mongodb'); +const mongoose = require('mongoose'); + +const Schema = mongoose.Schema; + +const cars = new Schema({ +dealer_id: { + type: Number, + required: true +}, +make: { + type: String, + required: true + }, +model: { + type: String, + required: true + }, +bodyType: { + type: String, + required: true + }, +year: { + type: Number, + required: true + }, +mileage: { + type: Number, + required: true + }, +price: { + type: Number, + required: true + } +}); + +module.exports = mongoose.model('cars', cars); \ No newline at end of file diff --git a/server/carsInventory/package-lock.json b/server/carsInventory/package-lock.json new file mode 100644 index 0000000000..79757522a1 --- /dev/null +++ b/server/carsInventory/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "carsinventory", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "carsinventory", + "version": "1.0.0", + "license": "ISC" + } + } +} diff --git a/server/carsInventory/package.json b/server/carsInventory/package.json new file mode 100644 index 0000000000..679693ef0b --- /dev/null +++ b/server/carsInventory/package.json @@ -0,0 +1,19 @@ +{ + "name": "carsinventory", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/upadhyaysaumya55/xrwvm-fullstack_developer_capstone.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/upadhyaysaumya55/xrwvm-fullstack_developer_capstone/issues" + }, + "homepage": "https://github.com/upadhyaysaumya55/xrwvm-fullstack_developer_capstone#readme", + "description": "" +} diff --git a/server/database/app.js b/server/database/app.js index 00f52b2008..ac68836754 100644 --- a/server/database/app.js +++ b/server/database/app.js @@ -1,11 +1,13 @@ +/*jshint esversion: 8 */ +/*jshint esversion: 6 */ const express = require('express'); const mongoose = require('mongoose'); const fs = require('fs'); -const cors = require('cors') -const app = express() +const cors = require('cors'); +const app = express(); const port = 3030; -app.use(cors()) +app.use(cors()); app.use(require('body-parser').urlencoded({ extended: false })); const reviews_data = JSON.parse(fs.readFileSync("reviews.json", 'utf8')); @@ -19,11 +21,11 @@ const Reviews = require('./review'); const Dealerships = require('./dealership'); try { - Reviews.deleteMany({}).then(()=>{ - Reviews.insertMany(reviews_data['reviews']); + Reviews.deleteMany({}).then(() => { + Reviews.insertMany(reviews_data.reviews); }); - Dealerships.deleteMany({}).then(()=>{ - Dealerships.insertMany(dealerships_data['dealerships']); + Dealerships.deleteMany({}).then(() => { + Dealerships.insertMany(dealerships_data.dealerships); }); } catch (error) { @@ -58,35 +60,51 @@ app.get('/fetchReviews/dealer/:id', async (req, res) => { // Express route to fetch all dealerships app.get('/fetchDealers', async (req, res) => { -//Write your code here + try { + const documents = await Dealerships.find(); + res.json(documents); + } catch (error) { + res.status(500).json({ error: 'Error fetching documents' }); + } }); // Express route to fetch Dealers by a particular state app.get('/fetchDealers/:state', async (req, res) => { -//Write your code here + try { + const documents = await Dealerships.find({ state: req.params.state }); + res.json(documents); + } catch (error) { + res.status(500).json({ error: 'Error fetching documents' }); + } }); // Express route to fetch dealer by a particular id app.get('/fetchDealer/:id', async (req, res) => { -//Write your code here + try { + const documents = await Dealerships.find({ id: req.params.id }); + res.json(documents); + } catch (error) { + console.error(error); + res.status(500).json({ error: 'Error fetching dealer' }); + } }); //Express route to insert review app.post('/insert_review', express.raw({ type: '*/*' }), async (req, res) => { data = JSON.parse(req.body); - const documents = await Reviews.find().sort( { id: -1 } ) - let new_id = documents[0]['id']+1 + const documents = await Reviews.find().sort( { id: -1 } ); + let new_id = documents[0].id + 1; const review = new Reviews({ "id": new_id, - "name": data['name'], - "dealership": data['dealership'], - "review": data['review'], - "purchase": data['purchase'], - "purchase_date": data['purchase_date'], - "car_make": data['car_make'], - "car_model": data['car_model'], - "car_year": data['car_year'], + "name": data.name, + "dealership": data.dealership, + "review": data.review, + "purchase": data.purchase, + "purchase_date": data.purchase_date, + "car_make": data.car_make, + "car_model": data.car_model, + "car_year": data.car_year, }); try { diff --git a/server/database/dealership.js b/server/database/dealership.js index b10d6b4730..d4f22054d1 100644 --- a/server/database/dealership.js +++ b/server/database/dealership.js @@ -1,3 +1,4 @@ +/*jshint esversion: 6 */ const mongoose = require('mongoose'); const Schema = mongoose.Schema; diff --git a/server/database/inventory.js b/server/database/inventory.js index 2c22fd092c..2935099086 100644 --- a/server/database/inventory.js +++ b/server/database/inventory.js @@ -1,3 +1,4 @@ +/*jshint esversion: 6 */ const { Int32 } = require('mongodb'); const mongoose = require('mongoose'); diff --git a/server/database/review.js b/server/database/review.js index 4759725a3a..c945019476 100644 --- a/server/database/review.js +++ b/server/database/review.js @@ -1,3 +1,4 @@ +/*jshint esversion: 6 */ const mongoose = require('mongoose'); const Schema = mongoose.Schema; diff --git a/server/deployment.yaml b/server/deployment.yaml new file mode 100644 index 0000000000..201c18a624 --- /dev/null +++ b/server/deployment.yaml @@ -0,0 +1,29 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + run: dealership + name: dealership +spec: + replicas: 1 + selector: + matchLabels: + run: dealership + strategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 25% + type: RollingUpdate + template: + metadata: + labels: + run: dealership + spec: + containers: + - image: us.icr.io/sn-labs-saumyaupadhy/dealership:latest + imagePullPolicy: Always + name: dealership + ports: + - containerPort: 8000 + protocol: TCP + restartPolicy: Always \ No newline at end of file diff --git a/server/djangoapp/.env b/server/djangoapp/.env index 01822e542a..b003ce0b73 100644 --- a/server/djangoapp/.env +++ b/server/djangoapp/.env @@ -1,2 +1,3 @@ -backend_url =your backend url -sentiment_analyzer_url=your code engine deployment url +backend_url =https://saumyaupadhy-3030.theiadockernext-0-labs-prod-theiak8s-4-tor01.proxy.cognitiveclass.ai +sentiment_analyzer_url=https://sentianalyzer.1tmu51o6g6vj.us-south.codeengine.appdomain.cloud/ +searchcars_url=https://saumyaupadhy-3050.theiadockernext-0-labs-prod-theiak8s-4-tor01.proxy.cognitiveclass.ai \ No newline at end of file diff --git a/server/djangoapp/admin.py b/server/djangoapp/admin.py index 433657fc64..8b53fb60b4 100644 --- a/server/djangoapp/admin.py +++ b/server/djangoapp/admin.py @@ -1,8 +1,10 @@ -# from django.contrib import admin -# from .models import related models +from django.contrib import admin +from .models import CarMake, CarModel # Register your models here. +admin.site.register(CarMake) +admin.site.register(CarModel) # CarModelInline class diff --git a/server/djangoapp/models.py b/server/djangoapp/models.py index eb101a68c8..283b05f48f 100644 --- a/server/djangoapp/models.py +++ b/server/djangoapp/models.py @@ -1,8 +1,6 @@ -# Uncomment the following imports before adding the Model code - -# from django.db import models -# from django.utils.timezone import now -# from django.core.validators import MaxValueValidator, MinValueValidator +from django.db import models +from django.utils.timezone import now +from django.core.validators import MaxValueValidator, MinValueValidator # Create your models here. @@ -12,6 +10,13 @@ # - Description # - Any other fields you would like to include in car make model # - __str__ method to print a car make object +class CarMake(models.Model): + name = models.CharField(max_length=100) + description = models.TextField() + # Other fields as needed + + def __str__(self): + return self.name # Create a Car Model model `class CarModel(models.Model):`: @@ -23,3 +28,18 @@ # - Year (IntegerField) with min value 2015 and max value 2023 # - Any other fields you would like to include in car model # - __str__ method to print a car make object +class CarModel(models.Model): + car_make = models.ForeignKey(CarMake, on_delete=models.CASCADE) + name = models.CharField(max_length=100) + CAR_TYPES = [ + ('SEDAN', 'Sedan'), + ('SUV', 'SUV'), + ('WAGON', 'Wagon'), + # Add more choices as required + ] + type = models.CharField(max_length=10, choices=CAR_TYPES, default='SUV') + year = models.IntegerField(default=2023, validators=[ MaxValueValidator(2023), MinValueValidator(2015)]) + # Other fields as needed + + def __str__(self): + return self.name # Return the name as the string representation diff --git a/server/djangoapp/populate.py b/server/djangoapp/populate.py index 1927e09e18..ebe07cfdfc 100644 --- a/server/djangoapp/populate.py +++ b/server/djangoapp/populate.py @@ -1,2 +1,57 @@ +from .models import CarMake, CarModel + + def initiate(): - print("Populate not implemented. Add data manually") + car_make_data = [ + {"name": "NISSAN", "description":"Great cars. Japanese technology"}, + {"name": "Mercedes", "description":"Great cars. German technology"}, + {"name": "Audi", "description":"Great cars. German technology"}, + {"name": "Kia", "description":"Great cars. Korean technology"}, + {"name": "Toyota", "description":"Great cars. Japanese technology"}, + ] + + car_make_instances = [] + for data in car_make_data: + car_make_instances.append( + CarMake.objects.create( + name=data['name'], + description=data['description'] + )) + + + # Create CarModel instances with the corresponding CarMake instances + car_model_data = [ + {"name": "Pathfinder", "type":"SUV", "year": 2023, + "car_make":car_make_instances[0]}, + {"name": "Qashqai", "type":"SUV", "year": 2023, + "car_make":car_make_instances[0]}, + {"name": "XTRAIL", "type":"SUV", "year": 2023, + "car_make":car_make_instances[0]}, + {"name": "A-Class", "type":"SUV", "year": 2023, + "car_make":car_make_instances[1]}, + {"name": "C-Class", "type":"SUV", "year": 2023, + "car_make":car_make_instances[1]}, + {"name": "E-Class", "type":"SUV", "year": 2023, + "car_make":car_make_instances[1]}, + {"name": "A4", "type":"SUV", "year": 2023, + "car_make":car_make_instances[2]}, + {"name": "A5", "type":"SUV", "year": 2023, + "car_make":car_make_instances[2]}, + {"name": "A6", "type":"SUV", "year": 2023, + "car_make":car_make_instances[2]}, + {"name": "Sorrento", "type":"SUV", "year": 2023, + "car_make":car_make_instances[3]}, + {"name": "Carnival", "type":"SUV", "year": 2023, + "car_make":car_make_instances[3]}, + {"name": "Cerato", "type":"Sedan", "year": 2023, + "car_make":car_make_instances[3]}, + {"name": "Corolla", "type":"Sedan", "year": 2023, + "car_make":car_make_instances[4]}, + {"name": "Camry", "type":"Sedan", "year": 2023, + "car_make":car_make_instances[4]}, + {"name": "Kluger", "type":"SUV", "year": 2023, + "car_make":car_make_instances[4]}, + # Add more CarModel instances as needed + ] + for data in car_model_data: + CarModel.objects.create(name=data['name'], car_make=data['car_make'], type=data['type'], year=data['year']) diff --git a/server/djangoapp/restapis.py b/server/djangoapp/restapis.py index 90709d9e3b..a828b94588 100644 --- a/server/djangoapp/restapis.py +++ b/server/djangoapp/restapis.py @@ -1,5 +1,4 @@ -# Uncomment the imports below before you add the function code -# import requests +import requests import os from dotenv import load_dotenv @@ -10,13 +9,62 @@ sentiment_analyzer_url = os.getenv( 'sentiment_analyzer_url', default="http://localhost:5050/") +searchcars_url = os.getenv( + 'searchcars_url', + default="http://localhost:3050/") -# def get_request(endpoint, **kwargs): -# Add code for get requests to back end +def get_request(endpoint, **kwargs): + params = "" + if(kwargs): + for key, value in kwargs.items(): + params = params+key+"="+value+"&" + + request_url = backend_url+endpoint+"?"+params + + print("GET from {} ".format(request_url)) + try: + # Call get method of requests library with URL and parameters + response = requests.get(request_url) + return response.json() + except: + # If any error occurs + print("Network exception occurred") -# def analyze_review_sentiments(text): -# request_url = sentiment_analyzer_url+"analyze/"+text -# Add code for retrieving sentiments +def analyze_review_sentiments(text): + request_url = sentiment_analyzer_url+"analyze/"+text + try: + # Call get method of requests library with URL and parameters + response = requests.get(request_url) + return response.json() + except Exception as err: + print(f"Unexpected {err=}, {type(err)=}") + print("Network exception occurred") -# def post_review(data_dict): -# Add code for posting review +def post_review(data_dict): + request_url = backend_url+"/insert_review" + try: + response = requests.post(request_url,json=data_dict) + print(response.json()) + return response.json() + except: + print("Network exception occurred") + + +def searchcars_request(endpoint, **kwargs): + params = "" + if (kwargs): + for key, value in kwargs.items(): + params = params+key + "=" + value + "&" + + request_url = searchcars_url+endpoint+"?"+params + + print("GET from {} ".format(request_url)) + try: + # Call get method of requests library with URL and parameters + response = requests.get(request_url) + return response.json() + except: + # If any error occurs + print("Network exception occurred") + finally: + print("GET request call complete!") diff --git a/server/djangoapp/urls.py b/server/djangoapp/urls.py index 0edc274f90..c9fada0c10 100644 --- a/server/djangoapp/urls.py +++ b/server/djangoapp/urls.py @@ -1,18 +1,35 @@ # Uncomment the imports before you add the code -# from django.urls import path +from django.urls import path from django.conf.urls.static import static from django.conf import settings -# from . import views +from . import views app_name = 'djangoapp' urlpatterns = [ # # path for registration + path('register', views.registration, name='registration'), # path for login - # path(route='login', view=views.login_user, name='login'), + path(route='login', view=views.login_user, name='login'), + # path for logout + path('logout', views.logout, name='logout'), + + # path for get cars + path(route='get_cars', view=views.get_cars, name ='getcars'), + # path for dealer reviews view + path(route='get_dealers/', view=views.get_dealerships, name='get_dealers'), + path(route='get_dealers/', + view=views.get_dealerships, name='get_dealers_by_state'), + path(route='dealer/', + view=views.get_dealer_details, name='dealer_details'), + path(route='reviews/dealer/', + view=views.get_dealer_reviews, name='dealer_details'), + path(route='get_inventory/', +view=views.get_inventory, name='get_inventory'), # path for add a review view + path(route='add_review', view=views.add_review, name='add_review'), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/server/djangoapp/views.py b/server/djangoapp/views.py index b16409f419..c0b51a57c7 100644 --- a/server/djangoapp/views.py +++ b/server/djangoapp/views.py @@ -1,26 +1,30 @@ # Uncomment the required imports before adding the code -# from django.shortcuts import render -# from django.http import HttpResponseRedirect, HttpResponse -# from django.contrib.auth.models import User -# from django.shortcuts import get_object_or_404, render, redirect -# from django.contrib.auth import logout -# from django.contrib import messages -# from datetime import datetime +from django.shortcuts import render +from django.http import HttpResponseRedirect, HttpResponse +from django.contrib.auth.models import User +from django.shortcuts import get_object_or_404, render, redirect +from django.contrib.auth import logout +from django.contrib import messages +from datetime import datetime from django.http import JsonResponse from django.contrib.auth import login, authenticate import logging import json from django.views.decorators.csrf import csrf_exempt -# from .populate import initiate +from .populate import initiate +from .models import CarMake, CarModel + +from .restapis import get_request, analyze_review_sentiments, post_review +from .restapis import get_request, analyze_review_sentiments, post_review, searchcars_request # Get an instance of a logger logger = logging.getLogger(__name__) -# Create your views here. +# Creating my views here. # Create a `login_request` view to handle sign in request @csrf_exempt @@ -39,27 +43,102 @@ def login_user(request): return JsonResponse(data) # Create a `logout_request` view to handle sign out request -# def logout_request(request): -# ... +def logout_request(request): + data = {"userName": ""} + return JsonResponse(data) # Create a `registration` view to handle sign up request -# @csrf_exempt -# def registration(request): +@csrf_exempt +def registration(request): + context = {} + + data = json.loads(request.body) + username = data['userName'] + password = data['password'] + first_name = data['firstName'] + last_name = data['lastName'] + email = data['email'] + username_exist = False + email_exist = False + try: + # Check if user already exists + User.objects.get(username=username) + username_exist = True + except: + # If not, simply log this is a new user + logger.debug("{} is new user".format(username)) + # If it is a new user + if not username_exist: + # Create user in auth_user table + user = User.objects.create_user( + username=username, first_name=first_name, + last_name=last_name,password=password, email=email + ) + # Login the user and redirect to list page + login(request, user) + data = {"userName": username,"status": "Authenticated"} + return JsonResponse(data) + else : + data = {"userName": username,"error": "Already Registered"} + return JsonResponse(data) # ... +# # Updating the 'get_cars' view to get cars make and model +# list of cars and models + +def get_cars(request): + count = CarMake.objects.filter().count() + print(count) + if(count == 0): + initiate() + car_models = CarModel.objects.select_related('car_make') + cars = [] + for car_model in car_models: + cars.append({"CarModel": car_model.name, + "CarMake": car_model.car_make.name}) + return JsonResponse({"CarModels": cars}) + # # Update the `get_dealerships` view to render the index page with # a list of dealerships -# def get_dealerships(request): -# ... +def get_dealerships(request, state="All"): + if(state == "All"): + endpoint = "/fetchDealers" + else: + endpoint = "/fetchDealers/"+state + dealerships = get_request(endpoint) + return JsonResponse({"status": 200, "dealers": dealerships}) # Create a `get_dealer_reviews` view to render the reviews of a dealer -# def get_dealer_reviews(request,dealer_id): -# ... +def get_dealer_reviews(request,dealer_id): + # if dealer id has been provided + if(dealer_id): + endpoint = "/fetchReviews/dealer/"+str(dealer_id) + reviews = get_request(endpoint) + for review_detail in reviews: + response = analyze_review_sentiments(review_detail['review']) + print(response) + review_detail['sentiment'] = response['sentiment'] + return JsonResponse({"status": 200, "reviews": reviews}) + else: + return JsonResponse({"status": 400, "message": "Bad Request"}) # Create a `get_dealer_details` view to render the dealer details -# def get_dealer_details(request, dealer_id): -# ... +def get_dealer_details(request, dealer_id): + if(dealer_id): + endpoint = "/fetchDealer/"+str(dealer_id) + dealership = get_request(endpoint) + return JsonResponse({"status": 200, "dealer": dealership}) + else: + return JsonResponse({"status": 400, "message": "Bad Request"}) # Create a `add_review` view to submit a review -# def add_review(request): -# ... +def add_review(request): + if(request.user.is_anonymous == False): + data = json.loads(request.body) + try: + response = post_review(data) + return JsonResponse({"status": 200}) + except: + return JsonResponse({"status": 401, "message": "Error in posting review"}) + else: + return JsonResponse({"status": 403, "message": "Unauthorized"}) diff --git a/server/djangoproj/settings.py b/server/djangoproj/settings.py index e0b1092a5c..5499179027 100644 --- a/server/djangoproj/settings.py +++ b/server/djangoproj/settings.py @@ -28,8 +28,13 @@ # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -ALLOWED_HOSTS = [] -CSRF_TRUSTED_ORIGINS = [] +ALLOWED_HOSTS = ['localhost', + 'https://saumyaupadhy-8000.theiadockernext-0-labs-prod-' + 'theiak8s-4-tor01.proxy.cognitiveclass.ai', '127.0.0.1' + ] +CSRF_TRUSTED_ORIGINS = [ + 'https://saumyaupadhy-8000.theiadockernext-0-labs-prod-theiak8s-4-tor01.proxy.cognitiveclass.ai' +] REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [], @@ -61,7 +66,11 @@ TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], + 'DIRS': [ + os.path.join(BASE_DIR,'frontend/static'), + os.path.join(BASE_DIR, 'frontend/build'), + os.path.join(BASE_DIR, 'frontend/build/static'), + ], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ @@ -134,5 +143,9 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' -STATICFILES_DIRS = [] +STATICFILES_DIRS = [ + os.path.join(BASE_DIR,'frontend/static'), + os.path.join(BASE_DIR, 'frontend/build'), + os.path.join(BASE_DIR, 'frontend/build/static'), +] diff --git a/server/djangoproj/urls.py b/server/djangoproj/urls.py index 6808da9141..3dd0defae4 100644 --- a/server/djangoproj/urls.py +++ b/server/djangoproj/urls.py @@ -23,4 +23,13 @@ path('admin/', admin.site.urls), path('djangoapp/', include('djangoapp.urls')), path('', TemplateView.as_view(template_name="Home.html")), + path('about/', TemplateView.as_view(template_name="About.html")), + path('contact/', TemplateView.as_view(template_name="Contact.html")), + path('login/', TemplateView.as_view(template_name="index.html")), + path('register/', TemplateView.as_view(template_name="index.html")), + path('dealers/', TemplateView.as_view(template_name="index.html")), + path('dealer/', + TemplateView.as_view(template_name="index.html")), + path('postreview/', + TemplateView.as_view(template_name="index.html")), ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/server/entrypoint.sh b/server/entrypoint.sh new file mode 100644 index 0000000000..b24c7e80a4 --- /dev/null +++ b/server/entrypoint.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +# Make migrations and migrate the database. +echo "Making migrations and migrating the database. " +python manage.py makemigrations --noinput +python manage.py migrate --noinput +python manage.py collectstatic --noinput +exec "$@" \ No newline at end of file diff --git a/server/frontend/package-lock.json b/server/frontend/package-lock.json index 0797425307..bdb21fad35 100644 --- a/server/frontend/package-lock.json +++ b/server/frontend/package-lock.json @@ -16,6 +16,9 @@ "react-router-dom": "^6.19.0", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" + }, + "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -646,9 +649,18 @@ } }, "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "version": "7.21.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", + "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead.", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, "engines": { "node": ">=6.9.0" }, @@ -1891,6 +1903,18 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-env/node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/preset-env/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", diff --git a/server/frontend/src/App.js b/server/frontend/src/App.js index aceac6974d..091143e2a5 100644 --- a/server/frontend/src/App.js +++ b/server/frontend/src/App.js @@ -1,10 +1,18 @@ import LoginPanel from "./components/Login/Login" import { Routes, Route } from "react-router-dom"; +import Register from "./components/Register/Register"; +import Dealers from './components/Dealers/Dealers'; +import Dealer from "./components/Dealers/Dealer" +import PostReview from "./components/Dealers/PostReview" function App() { return ( } /> + }/> + } /> + } /> + } /> ); } diff --git a/server/frontend/src/components/Dealers/Dealers.css b/server/frontend/src/components/Dealers/Dealers.css index 301d59ae27..0ef3f1ad55 100644 --- a/server/frontend/src/components/Dealers/Dealers.css +++ b/server/frontend/src/components/Dealers/Dealers.css @@ -1,7 +1,7 @@ table{ margin:5px; padding:10px; - border: grey solid 1px; + border: solid grey 1px; width:100% } @@ -16,7 +16,7 @@ table{ .review_panel{ display: flex; flex-direction: column; - border: solid grey; + border: solid purple; position: relative; height:7cm; width:6cm; @@ -59,7 +59,7 @@ table{ margin: 10px; /* Optional margin for spacing */ font-style: italic; color: gray; - font-size: small; + font-size: 18px; } .review { @@ -84,5 +84,5 @@ table{ .review_icon:hover { transform: scale(1.1); - border: solid lightgray; + border: 2px solid #080808; } \ No newline at end of file diff --git a/server/frontend/src/components/Dealers/Dealers.jsx b/server/frontend/src/components/Dealers/Dealers.jsx index db3410680c..b7eab353c7 100644 --- a/server/frontend/src/components/Dealers/Dealers.jsx +++ b/server/frontend/src/components/Dealers/Dealers.jsx @@ -6,6 +6,8 @@ import review_icon from "../assets/reviewicon.png" const Dealers = () => { const [dealersList, setDealersList] = useState([]); + const [searchQuery, setSearchQuery] = useState(''); + const [originalDealers, setOriginalDealers] = useState([]); // let [state, setState] = useState("") let [states, setStates] = useState([]) @@ -39,13 +41,30 @@ const Dealers = () => { }); setStates(Array.from(new Set(states))) - setDealersList(all_dealers) + setDealersList(all_dealers); + setOriginalDealers(all_dealers); } } useEffect(() => { get_dealers(); },[]); + const handleInputChange = (event) => { + const query = event.target.value; + setSearchQuery(query); + const filtered = originalDealers.filter(dealer => + dealer.state.toLowerCase().includes(query.toLowerCase()) + ); + setDealersList(filtered); + }; + + + const handleLostFocus = () => { + if (!searchQuery) { + setDealersList(originalDealers); + } + } + let isLoggedIn = sessionStorage.getItem("username") != null ? true : false; return( @@ -60,14 +79,7 @@ return( Address Zip - - + {isLoggedIn ? ( Review Dealer diff --git a/server/frontend/src/components/Register/Register.jsx b/server/frontend/src/components/Register/Register.jsx new file mode 100644 index 0000000000..9f1a290327 --- /dev/null +++ b/server/frontend/src/components/Register/Register.jsx @@ -0,0 +1,98 @@ +import React, { useState } from "react"; +import "./Register.css"; +import user_icon from "../assets/person.png" +import email_icon from "../assets/email.png" +import password_icon from "../assets/password.png" +import close_icon from "../assets/close.png" + +const Register = () => { + + const [userName, setUserName] = useState(""); + const [password, setPassword] = useState(""); + const [email, setEmail] = useState(""); + const [firstName, setFirstName] = useState(""); + const [lastName, setlastName] = useState(""); + + + const gohome = ()=> { + window.location.href = window.location.origin; + } + + const register = async (e) => { + e.preventDefault(); + + let register_url = window.location.origin+"/djangoapp/register"; + + const res = await fetch(register_url, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + "userName": userName, + "password": password, + "firstName":firstName, + "lastName":lastName, + "email":email + }), + }); + + const json = await res.json(); + if (json.status) { + sessionStorage.setItem('username', json.userName); + window.location.href = window.location.origin; + } + else if (json.error === "Already Registered") { + alert("The user with same username is already registered"); + window.location.href = window.location.origin; + } +}; + + return( +
+ + +
+
+
+ Username + setUserName(e.target.value)}/> +
+
+ First Name + setFirstName(e.target.value)}/> +
+ +
+ Last Name + setlastName(e.target.value)}/> +
+ +
+ Email + setEmail(e.target.value)}/> +
+ +
+ password + setPassword(e.target.value)}/> +
+ +
+
+ +
+
+
+ ) +} + +export default Register; \ No newline at end of file diff --git a/server/frontend/static/About.html b/server/frontend/static/About.html index 484efd960f..f2a14276d0 100644 --- a/server/frontend/static/About.html +++ b/server/frontend/static/About.html @@ -1,6 +1,8 @@ + +