Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,10 @@
<img src="./readme/demo/Diagrams/ERD.png"/>
</center>

### Component Diagram
### System Architect Diagram

<center>
<img src="./readme/demo/Diagrams/Component Diagram.png"/>
</center>

### Flow Diagram

<center>
<img src="./readme/demo/Diagrams/Flow Diagram.png"/>
<img src="./readme/demo/Diagrams/System Architect Diagram.png"/>
</center>

### Project Box Design
Expand All @@ -55,6 +49,12 @@ I used for this project ESP32 DevKit V1. It is based on the ESP32 microcontrolle

- <b>Personalized AI Optimization Plans:</b> Clients receive intelligent, data-driven strategies to optimize energy usage, reduce costs, and promote sustainability based on their consumption behaviors.

### Remarkable Features

<center>
<img src="./readme/demo/Highlights/Highlight Section.png"/>
</center>

<br><br>

<!-- Demo -->
Expand Down Expand Up @@ -88,6 +88,10 @@ I used for this project ESP32 DevKit V1. It is based on the ESP32 microcontrolle
<!-- Development & Testing -->
<img src="./readme/title6.svg"/>

#### Postman API Documentation

- You can check the full API documentation using this [link](https://documenter.getpostman.com/view/42830816/2sB2qXji4H).

### Code Test Cases

| Test Case | Test Case |
Expand Down Expand Up @@ -138,9 +142,13 @@ I used for this project ESP32 DevKit V1. It is based on the ESP32 microcontrolle
<!-- Deployment -->
<img src="./readme/title8.svg"/>

### EC2 Docker containers deployment
### Deployment Diagram

- You can check the full API documentation using this [link](https://documenter.getpostman.com/view/42830816/2sB2qXji4H).
<center>
<img src="./readme/demo/Diagrams/Flow Diagram.png"/>
</center>

### EC2 Docker containers deployment

| Deployment Pipeline Sample | GitHub Deployment Pipeline Success | EC2 Instance docker deployed |
| --------------------------------------- | ------------------------------------- | ------------------------------------- |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,56 +36,4 @@ const InputField = ({
);
};

// V2
// const InputField = ({
// label,
// placeholder,
// value,
// onChange,
// width,
// textarea,
// type,
// required = true,
// }) => {
// return (
// <div className="input-field-container" style={{ width: width || "100%" }}>
// <label className="subtitle black-color">
// {label} {required && <span>*</span>}
// </label>
// {textarea ? (
// <textarea placeholder={placeholder} value={value} onChange={onChange} />
// ) : (
// <input
// type={type || "text"}
// placeholder={placeholder}
// value={value}
// onChange={onChange}
// />
// )}
// </div>
// );
// };

// const InputField = ({ label, placeholder, value, onChange, width, textarea, type }) => {
// return (
// <div className="input-field-container" style={{ width: width || '100%' }}>
// <label className="subtitle black-color">{label}*</label>
// {textarea ? (
// <textarea
// placeholder={placeholder}
// value={value}
// onChange={onChange}
// />
// ) : (
// <input
// type={type?type:"text"}
// placeholder={placeholder}
// value={value}
// onChange={onChange}
// />
// )}
// </div>
// );
// }

export default InputField;
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import "./styles.css";
import { useState } from "react";
import { Link } from "react-router-dom";
import { useLogout } from "../../../Hooks/useLogoutHook";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faSignOutAlt,
faUser,
faChevronDown,
} from "@fortawesome/free-solid-svg-icons";

const ProfileMenu = () => {
const [isOpen, setIsOpen] = useState(false);
const logout = useLogout();

const handleToggle = () => {
setIsOpen((prev) => !prev);
};

const handleLogout = async () => {
try {
await logout();
} catch (error) {
console.error("Logout failed:", error);
}
};

return (
<div className="profile-menu-container">
<div className="profile-summary" onClick={handleToggle}>
<span className="username">Profile Menu</span>
<FontAwesomeIcon
icon={faChevronDown}
className={`arrow-icon ${isOpen ? "open" : ""}`}
/>
</div>

{isOpen && (
<div className="dropdown-menu">
<Link to="/provider/profile" className="dropdown-item">
<FontAwesomeIcon icon={faUser} className="item-icon" />
Profile
</Link>
<button onClick={handleLogout} className="dropdown-item logout">
<FontAwesomeIcon icon={faSignOutAlt} className="item-icon" />
Logout
</button>
</div>
)}
</div>
);
};

export default ProfileMenu;
81 changes: 81 additions & 0 deletions amp-client/src/Components/CommonComponents/ProfileMenu/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
.profile-menu-container {
position: relative;
display: flex;
}

.profile-summary {
border: 2px solid #fff;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
width: 100%;
padding: 10px 14px;
font-size: 18px;
background-color: transparent;
border-radius: 8px;
cursor: pointer;
transition: background-color 0.3s ease;
}

.profile-summary:hover {
background-color: #fff;
border: none;
color: #f9a43a;
}

.username {
font-size: 18px;
font-weight: 500;
}

.arrow-icon {
transition: transform 0.3s ease;
}

.arrow-icon.open {
transform: rotate(-180deg);
}

.dropdown-menu {
position: absolute;
bottom: 100%;
right: 0;
background-color: #ffffff;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
margin-bottom: 2px;
min-width: 100%;
/* min-width: 160px; */
z-index: 100;
overflow: hidden;
}

.dropdown-item {
display: flex;
align-items: center;
gap: 10px;
padding: 12px 16px;
font-size: 14px;
color: #374151;
text-decoration: none;
background-color: #fff;
border: none;
width: 100%;
text-align: left;
cursor: pointer;
}

.dropdown-item:hover {
background-color: #f3f4f6;
}

.logout {
color: #b91c1c;
}

.item-icon {
width: 16px;
height: 16px;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import "./styles.css";
import { Link } from "react-router-dom";
import logo from "../../../assets/logo.png";
import LogoutButton from "../../CommonComponents/LogoutButton/LogoutButton";
import ProfileMenu from "../../CommonComponents/ProfileMenu/ProfileMenu";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faTachometerAlt,
Expand Down Expand Up @@ -34,13 +34,9 @@ const ProviderSidebar = () => {
<FontAwesomeIcon icon={faBolt} className="sidebar-icon" />
<span className="link-text">Power Prediction</span>
</Link>
<Link to="/provider/profile" className="sidebar-link">
<FontAwesomeIcon icon={faUser} className="sidebar-icon" />
<span className="link-text">Profile</span>
</Link>
</nav>
<div className="sidebar-footer">
<LogoutButton />
<ProfileMenu />
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,102 @@
import "./styles.css";
import { useState } from "react";
import { toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import ProviderProfileService from "../Services/ProviderProfile/ProviderProfile";
import InputField from "../../../Components/CommonComponents/InputField/InputField";
import ActionButton from "../../../Components/CommonComponents/ActionButton/ActionButton";

const ProviderProfile = () => {
const [formData, setFormData] = useState({
name: "",
email: "",
password: "",
phone_number: "",
});

const { updateProfile } = ProviderProfileService();

const handleChange = (field, value) => {
setFormData((prev) => ({
...prev,
[field]: value,
}));
};

const handleSubmit = async (e) => {
e.preventDefault();
await updateProfile(formData);
};

return (
<>
<div className="provider-profile-container">
<div className="main-content">
<h1 className="main-content-title section-titles">Provider Profile</h1>
<div className="provider-profile-wrapper">
<div className="provider-profile-main">
<h2 className="provider-profile-heading">Provider Profile</h2>

<div className="provider-profile-card">
<h2 className="provider-profile-subtitle">Edit Provider Profile</h2>
<form className="provider-profile-form">
<div className="provider-profile-form-group">
<InputField
label="Name"
placeholder="Enter your name"
value={formData.name}
onChange={(e) => handleChange("name", e.target.value)}
type="text"
width="90%"
required={false}
/>
</div>

<div className="provider-profile-form-group">
<InputField
label="Email"
placeholder="Enter your email"
value={formData.email}
onChange={(e) => handleChange("email", e.target.value)}
type="email"
width="90%"
required={false}
/>
</div>

<div className="provider-profile-form-group">
<InputField
label="Password"
placeholder="Enter new password"
value={formData.password}
onChange={(e) => handleChange("password", e.target.value)}
type="password"
width="90%"
required={false}
/>
</div>

<div className="provider-profile-form-group">
<InputField
label="Phone Number"
placeholder="Enter phone number"
value={formData.phone_number}
onChange={(e) => handleChange("phone_number", e.target.value)}
type="tel"
width="90%"
required={false}
/>
</div>

<ActionButton
text="Save Changes"
backgroundColor="#f9a43a"
className="submit-action-button"
color="#FFF"
width="50%"
margin="20px 0 0"
onClick={handleSubmit}
/>
</form>
</div>
</div>
</>
</div>
);
};

Expand Down
Loading