├── .eslintrc.json
├── .github
├── ISSUE_TEMPLATE
│ ├── bug.yml
│ ├── documentation.yml
│ └── feature.yml
└── workflows
│ └── greetings.yaml
├── .gitignore
├── .prettierrc
├── CODE_OF_CONDUCT
├── Contributing.md
├── LICENSE
├── README.md
├── app
├── about
│ └── page.tsx
├── blog-details
│ └── page.tsx
├── blog-sidebar
│ └── page.tsx
├── blog
│ ├── ChargingStationDayDataset.js
│ ├── EVLocations.js
│ └── page.tsx
├── contact
│ └── page.tsx
├── error
│ └── page.tsx
├── layout.tsx
├── page.tsx
├── providers.tsx
├── signin
│ └── page.tsx
└── signup
│ └── page.tsx
├── components
├── About
│ ├── AboutSectionOne.tsx
│ └── AboutSectionTwo.tsx
├── Blog
│ ├── RelatedPost.tsx
│ ├── SharePost.tsx
│ ├── SingleBlog.tsx
│ ├── TagButton.tsx
│ ├── blogData.tsx
│ └── index.tsx
├── Brands
│ ├── brandsData.tsx
│ └── index.tsx
├── Common
│ ├── Breadcrumb.tsx
│ ├── ScrollUp.tsx
│ └── SectionTitle.tsx
├── Contact
│ ├── NewsLatterBox.tsx
│ └── index.tsx
├── Features
│ ├── SingleFeature.tsx
│ ├── featuresData.tsx
│ └── index.tsx
├── Footer
│ ├── index.tsx
│ └── styles.css
├── Header
│ ├── ChargingStationDayDataset.js
│ ├── EVLocations.js
│ ├── ThemeToggler.tsx
│ ├── index.tsx
│ └── menuData.tsx
├── Hero
│ ├── ChargingStationDayDataset.js
│ ├── EVLocations.js
│ └── index.tsx
├── Pricing
│ ├── OfferList.tsx
│ ├── PricingBox.tsx
│ └── index.tsx
├── ScrollToTop
│ └── index.tsx
├── Testimonials
│ ├── SingleTestimonial.tsx
│ └── index.tsx
└── Video
│ └── index.tsx
├── firebaseConfig.js
├── global.d.ts
├── jsconfig.json
├── next-env.d.ts
├── next.config.js
├── package-lock.json
├── package.json
├── pnpm-lock.yaml
├── postcss.config.js
├── public
├── favicon.ico
└── images
│ ├── 404.svg
│ ├── about
│ ├── about-image-2-dark.svg
│ ├── about-image-2.svg
│ ├── about-image-dark.svg
│ └── about-image.svg
│ ├── blog
│ ├── author-01.png
│ ├── author-02.png
│ ├── author-03.png
│ ├── blog-01.jpg
│ ├── blog-02.jpg
│ ├── blog-03.jpg
│ ├── blog-details-01.jpg
│ ├── blog-details-02.jpg
│ ├── post-01.jpg
│ ├── post-02.jpg
│ └── post-03.jpg
│ ├── brands
│ ├── ayroui-light.svg
│ ├── ayroui.svg
│ ├── ecommerce-html.svg
│ ├── graygrids.svg
│ ├── lineicons-light.svg
│ ├── lineicons.svg
│ ├── plainadmin-light.svg
│ ├── plainadmin.svg
│ ├── tailadmin.svg
│ ├── tailgrids-light.svg
│ ├── tailgrids.svg
│ ├── uideck-light.svg
│ └── uideck.svg
│ ├── favicon.png
│ ├── hero
│ ├── shape-01.svg
│ └── shape-02.svg
│ ├── logo
│ ├── logo1.png
│ └── logo2.jpg
│ ├── testimonials
│ ├── auth-01.png
│ ├── auth-02.png
│ ├── auth-03.png
│ ├── author-01.png
│ ├── author-02.png
│ └── author-03.png
│ └── video
│ ├── shape.svg
│ └── video.jpg
├── styles
└── index.css
├── tailwind.config.js
├── trained.h5
├── tsconfig.json
└── types
├── blog.ts
├── brand.ts
├── feature.ts
├── menu.ts
└── testimonial.ts
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug.yml:
--------------------------------------------------------------------------------
1 | name: "🐞 Bug Report"
2 | description: "Create a report to help us improve"
3 | title: "BUG:"
4 | labels: ["Bug"]
5 | body:
6 | - type: checkboxes
7 | attributes:
8 | label: "Is there an existing issue for this?"
9 | description: "Please search to see if an issue already exists for the bug you encountered."
10 | options:
11 | - label: "I have searched the existing issues"
12 | required: true
13 | - type: textarea
14 | attributes:
15 | label: "What happened?"
16 | description: "A concise description of what you're experiencing."
17 | validations:
18 | required: true
19 | - type: checkboxes
20 | attributes:
21 | label: "Record"
22 | options:
23 | - label: "I agree to follow this project's Code of Conduct"
24 | required: true
25 | - label: "I'm a GSSOC'24 contributor"
26 | - label: "I want to work on this issue"
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/documentation.yml:
--------------------------------------------------------------------------------
1 | name: "📑 Documentation Update"
2 | description: "Improve Documentation"
3 | title: "DOC:"
4 | labels: [DOC, Needs Triage]
5 | body:
6 | - type: textarea
7 | attributes:
8 | label: "What's wrong with the existing documentation"
9 | description: "Which things do we need to add or delete"
10 | validations:
11 | required: true
12 | - type: textarea
13 | attributes:
14 | label: "Add ScreenShots"
15 | description: "Add sufficient SS to explain your issue."
16 | validations:
17 | required: false
18 |
19 | - type: checkboxes
20 | attributes:
21 | label: "Record"
22 | options:
23 | - label: "I agree to follow this project's Code of Conduct"
24 | required: true
25 | - label: "I'm a GSSOC'24 contributor"
26 | - label: "I want to work on this issue"
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature.yml:
--------------------------------------------------------------------------------
1 | name: "✨ Feature Request"
2 | description: "Suggest an idea for this project "
3 | title: "Feat:"
4 | labels: [Feat, Needs Triage]
5 | body:
6 | - type: textarea
7 | attributes:
8 | label: "Describe the feature"
9 | description:
10 | validations:
11 | required: true
12 | - type: textarea
13 | attributes:
14 | label: "Add ScreenShots"
15 | description: "Add sufficient SS to explain your issue."
16 | validations:
17 | required: true
18 | - type: checkboxes
19 | attributes:
20 | label: "Record"
21 | options:
22 | - label: "I agree to follow this project's Code of Conduct"
23 | required: true
24 | - label: "I'm a GSSOC'24 contributor"
25 | - label: "I want to work on this issue"
--------------------------------------------------------------------------------
/.github/workflows/greetings.yaml:
--------------------------------------------------------------------------------
1 | name: Greetings
2 |
3 | on: [pull_request_target, issues]
4 |
5 | jobs:
6 | greeting:
7 | runs-on: ubuntu-latest
8 | permissions:
9 | issues: write
10 | pull-requests: write
11 | steps:
12 | - uses: actions/first-interaction@v1
13 | with:
14 | repo-token: ${{ secrets.GITHUB_TOKEN }}
15 | issue-message: "Hi there! Thanks for opening this issue. We appreciate your contribution to this open-source project. We aim to respond or assign your issue as soon as possible."
16 | pr-message: "Welcome to Our repository.🎊 Thank you so much for taking the time to point this out."
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 | .vscode
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 | .pnpm-debug.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["prettier-plugin-tailwindcss"]
3 | }
4 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT:
--------------------------------------------------------------------------------
1 | # Smart-grid - GSSoC Contributors Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | - Demonstrating empathy and kindness toward other people
21 | - Being respectful of differing opinions, viewpoints, and experiences
22 | - Giving and gracefully accepting constructive feedback
23 | - Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | - Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | - The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | - Trolling, insulting or derogatory comments, and personal or political attacks
33 | - Public or private harassment
34 | - Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | - Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | [Mayank Sharma]https://www.linkedin.com/in/mayanksharma2808/
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
--------------------------------------------------------------------------------
/Contributing.md:
--------------------------------------------------------------------------------
1 | # Contributing to Smart-grid
2 |
3 | Welcome to **Smart-grid!** We are glad that you are interested in contributing.
4 |
5 | ## How to Contribute
6 |
7 | We welcome contributions from everyone. Here are some ways you can contribute:
8 |
9 | 1. **Reporting Bugs**: If you encounter a bug, please open an issue and provide as much detail as possible, including steps to reproduce the bug.
10 |
11 | 2. **Requesting Features**: If you have a feature request, feel free to open an issue to discuss it. We appreciate detailed descriptions of the requested feature and its use case.
12 |
13 | 3. **Fixing Issues**: Raise an issue if you find any issue.
14 |
15 | 4. **Improving Documentation**: Documentation is crucial. If you find any errors or areas that need improvement in our documentation, feel free to submit a pull request with your changes.
16 |
17 | 5. **Adding Features**: If you want to add a new feature, please open an issue first to discuss it. Once approved, you can work on it and submit a pull request.
18 |
19 | ## Getting Started
20 |
21 | To start contributing, follow these steps:
22 |
23 | 1. Fork the repository to your GitHub account using the **Fork** button.
24 |
25 | 2. Clone your forked repository to your local machine:
26 | ```
27 | git clone
28 | ```
29 |
30 | 3. Create a new branch for your changes:
31 | ```
32 | git checkout -b feature/your-feature
33 | ```
34 |
35 | 4. To run the project make sure to download all the packages using npm:
36 | ```
37 | npm install
38 | ```
39 |
40 | 5. Make your changes and commit them with descriptive commit messages:
41 | ```
42 | git add .
43 | git commit -m "Add your commit message"
44 | ```
45 |
46 | 6. Push your changes to your forked repository:
47 | ```
48 | git push origin
49 | ```
50 |
51 | 7. Finally, open a pull request on the original repository.
52 |
53 |
54 | ## Code Style
55 |
56 | Please follow the existing code style and conventions used in the project. If you are unsure about anything, feel free to ask.
57 |
58 | ## Code Review
59 |
60 | All submissions require review. GitHub pull requests are used for this purpose.
61 |
62 |
63 | Thank you for your interest in contributing to **Smart-grid!**
64 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Next.js Templates
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # EVNotify
2 |
3 | 
4 |
5 |
6 | EVNotify is a revolutionary application designed to streamline communication between powerhouses and electric vehicle (EV) charging stations. By harnessing decentralized networks, EVNotify provides users with real-time updates on charging station status, maintenance schedules, and nearby optimal charging options. Our mission is to simplify EV charging for a greener future.
7 |
8 | ## Visit our [Website](https://smart-ethindia.vercel.app/blog)
9 |
10 | 
11 |
12 |
13 | ## Features
14 |
15 | ### Integrated Map
16 | - Displays nearby charging stations with red, yellow, and green markers indicating high, medium, and low traffic respectively.
17 |
18 | 
19 |
20 |
21 | ### Nearest Station
22 | - Guides users to the nearest charging station with high power availability and less traffic.
23 |
24 | 
25 |
26 |
27 | ### Station Updates
28 | - Utilizes push protocol to keep users informed about closed EV stations, maintenance schedules, and updates on high-traffic charging stations.
29 | - Employs the power of Long-Short Term Memory models (LLMs) and machine learning models to predict the load of charging stations.
30 |
31 | 
32 |
33 |
34 | ### Real-time Data Storage
35 | - Utilizes [InterPlanetary File System (IPFS)](https://ipfs.tech/) to store real-time data of EVs at power stations.
36 |
37 | ## Getting Started
38 |
39 | To get started with EVNotify, follow these steps:
40 |
41 | 1. Click on the website [EVNotify](https://smart-ethindia.vercel.app/)
42 |
43 | 
44 |
45 | 2. Connect your wallet using [Metamask](https://metamask.io/), follow the on-screen instructions to connect your MetaMask wallet to EVNotify.
46 |
47 | 
48 |
49 | 3. Sign up for an account or log in if you already have one.
50 | 4. Enable location services to access nearby charging stations.
51 | 5. Explore the integrated map to find charging stations near you.
52 | 6. Receive real-time updates on station status, maintenance schedules, and optimal charging options.
53 |
54 | ## Install Locally on your system
55 |
56 | To run EVNotify locally on your system, follow these steps:
57 |
58 | 1. Clone the repository:
59 |
60 | ```bash
61 | git clone https://github.com/SmartGrid-ETHIndia/Smart-grid
62 |
63 | 2. Install Dependencies:
64 | Use npm (Node Package Manager) to install the project dependencies. In your project directory, run:
65 |
66 | ```bash
67 | npm install
68 |
69 | 3. Environment Configuration:
70 | If your project uses environment variables, make sure to set them up. Typically, you would create a .env file in your project directory and define your environment variables there.
71 |
72 | 4. Start the Application:
73 | Once the dependencies are installed, you can start your Next.js application. If your package.json file has a start script defined, you can simply run:
74 |
75 | ```bash
76 | npm run dev
77 |
78 | 5. Access the Application:
79 | Once the development server is running, open your web browser and navigate to `http://localhost:3000` to view your Next.js application.
80 |
81 | ## License
82 |
83 | [MIT License](LICENSE)
84 |
85 | ## Feedback
86 |
87 | We are constantly working to improve EVNotify and contributions are highly appriciated.
88 |
89 | Let's drive towards a sustainable future together!
90 |
91 | 🔋⚡️🌱 #EVNotify #GreenTech #ElectricVehicles
92 |
93 |
--------------------------------------------------------------------------------
/app/about/page.tsx:
--------------------------------------------------------------------------------
1 | import AboutSectionOne from "@/components/About/AboutSectionOne";
2 | import AboutSectionTwo from "@/components/About/AboutSectionTwo";
3 | import Breadcrumb from "@/components/Common/Breadcrumb";
4 |
5 | import { Metadata } from "next";
6 |
7 | export const metadata: Metadata = {
8 | title: "About Page | Free Next.js Template for Startup and SaaS",
9 | description: "This is About Page for Startup Nextjs Template",
10 | // other metadata
11 | };
12 |
13 | const AboutPage = () => {
14 | return (
15 | <>
16 |
20 |
21 |
22 | >
23 | );
24 | };
25 |
26 | export default AboutPage;
27 |
--------------------------------------------------------------------------------
/app/blog/page.tsx:
--------------------------------------------------------------------------------
1 |
2 | "use client"
3 | import React, { useEffect, useRef, useState } from 'react';
4 | import { Loader } from '@googlemaps/js-api-loader';
5 | import chargingData from './ChargingStationDayDataset';
6 | import data from './EVLocations.js';
7 | import { db } from "./../../firebaseConfig";
8 | import { getDocs, collection } from 'firebase/firestore';
9 |
10 | const MapComponent = () => {
11 | const googlemap = useRef(null);
12 | const [addresses, setAddresses] = useState(data);
13 | const EVStationData = chargingData;
14 | const [userLocation, setUserLocation] = useState({ lat: 28.6107, lng: 77.219666 }); // Default location
15 |
16 | const fetchUserLocation = () => {
17 | if (navigator.geolocation) {
18 | navigator.geolocation.getCurrentPosition(position => {
19 | setUserLocation({
20 | lat: position.coords.latitude,
21 | lng: position.coords.longitude
22 | });
23 | }, () => {
24 | console.log("Error in getting your location");
25 | });
26 | } else {
27 | console.log("Geolocation is not supported by this browser.");
28 | }
29 | };
30 |
31 | const calculateDistance = (lat1, lon1, lat2, lon2) => {
32 | const R = 6371; // Radius of the Earth in km
33 | const dLat = (lat2 - lat1) * (Math.PI / 180);
34 | const dLon = (lon2 - lon1) * (Math.PI / 180);
35 | const a =
36 | Math.sin(dLat / 2) * Math.sin(dLat / 2) +
37 | Math.cos(lat1 * (Math.PI / 180)) * Math.cos(lat2 * (Math.PI / 180)) *
38 | Math.sin(dLon / 2) * Math.sin(dLon / 2);
39 | const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
40 | return R * c;
41 | };
42 |
43 | const searchNearbyStations = (radius) => {
44 | return addresses.filter(address => {
45 | const distance = calculateDistance(userLocation.lat, userLocation.lng, address.latitude, address.longitude);
46 | return distance <= radius;
47 | });
48 | };
49 |
50 | let nearbyAddresses = searchNearbyStations(5);
51 |
52 | const searchNearbyStationsWithIncreasedRadius = (radius, maxRadius) => {
53 | if (radius > maxRadius) {
54 | return null; // Stop searching if reached the maximum radius
55 | }
56 |
57 | const nearbyStations = searchNearbyStations(radius);
58 | if (nearbyStations.length === 0) {
59 | // If no stations found in the current radius, try with increased radius
60 | return searchNearbyStationsWithIncreasedRadius(radius * 2, maxRadius);
61 | } else {
62 | return nearbyStations;
63 | }
64 | };
65 |
66 | // Use the recursive function to search for stations with increasing radii
67 | nearbyAddresses = searchNearbyStationsWithIncreasedRadius(10, 3000);
68 |
69 | const calculateBestStation = () => {
70 | const loadValues = { LOW: 1, MEDIUM: 2, HIGH: 3 };
71 | const loadTotals = {};
72 | const loadCounts = {};
73 |
74 | EVStationData.forEach(record => {
75 | if (nearbyAddresses.some(addr => addr.name === record.station_id)) {
76 | const loadValue = loadValues[record.status.toUpperCase()] || 0;
77 | loadTotals[record.station_id] = (loadTotals[record.station_id] || 0) + loadValue;
78 | loadCounts[record.station_id] = (loadCounts[record.station_id] || 0) + 1;
79 | }
80 | });
81 |
82 | let minAvgLoad = Infinity;
83 | let bestStation = null;
84 |
85 | Object.keys(loadTotals).forEach(station => {
86 | const avgLoad = loadTotals[station] / loadCounts[station];
87 | if (avgLoad < minAvgLoad) {
88 | minAvgLoad = avgLoad;
89 | bestStation = nearbyAddresses.find(addr => addr.name === station);
90 | }
91 | });
92 |
93 | return bestStation;
94 | };
95 |
96 | const highestCapacityAddress = calculateBestStation();
97 |
98 | const fetchEVStations = async () => {
99 | const querySnapshot = await getDocs(collection(db, "EVStations"));
100 | const stations = [];
101 | querySnapshot.forEach((doc) => {
102 | stations.push(doc.data());
103 | });
104 | setAddresses(stations);
105 | };
106 |
107 | useEffect(() => {
108 | fetchUserLocation();
109 | }, []);
110 |
111 | useEffect(() => {
112 | const openGoogleMaps = (event) => {
113 | const lat = event.target.getAttribute('data-lat');
114 | const lng = event.target.getAttribute('data-lng');
115 | const url = `https://www.google.com/maps/search/?api=1&query=${lat},${lng}`;
116 | window.open(url, '_blank');
117 | };
118 |
119 | window.openGoogleMaps = openGoogleMaps;
120 |
121 | const loader = new Loader({
122 | apiKey: "AIzaSyBvdxOyyKyljBkWE2M4Y8WUTlVBkBvHwQw",
123 | version: "weekly",
124 | });
125 |
126 | loader.load().then(() => {
127 | const map = new window.google.maps.Map(googlemap.current, {
128 | center: userLocation,
129 | zoom: 13.3,
130 | mapTypeControl: false
131 | });
132 |
133 | const greenIcon = { url: 'http://maps.google.com/mapfiles/ms/icons/green-dot.png' };
134 | const yellowIcon = { url: 'http://maps.google.com/mapfiles/ms/icons/yellow-dot.png' };
135 | const redIcon = { url: 'http://maps.google.com/mapfiles/ms/icons/red-dot.png' };
136 | const blueIcon = { url: 'http://maps.google.com/mapfiles/ms/icons/blue-dot.png' }; // Blue icon for user location
137 |
138 | new window.google.maps.Marker({
139 | position: { lat: userLocation.lat, lng: userLocation.lng },
140 | map: map,
141 | title: "Your Location",
142 | icon: blueIcon,
143 | });
144 |
145 | const infoWindow = new window.google.maps.InfoWindow();
146 |
147 | addresses.forEach(address => {
148 | const isNearby = nearbyAddresses.includes(address);
149 | const isHighestCapacity = address === highestCapacityAddress;
150 | const marker = new window.google.maps.Marker({
151 | position: { lat: address.latitude, lng: address.longitude },
152 | map: map,
153 | title: address.name,
154 | icon: isNearby ? (isHighestCapacity ? greenIcon : yellowIcon) : redIcon,
155 | });
156 |
157 | marker.addListener("click", () => {
158 | const distance = calculateDistance(userLocation.lat, userLocation.lng, address.latitude, address.longitude).toFixed(2);
159 | const contentString = `
160 |