-
Notifications
You must be signed in to change notification settings - Fork 1
Staging #167
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Staging #167
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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; |
| 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,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: "", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Use consistent camelCase naming for JavaScript fields phone_number is snake_case; change it to phoneNumber and adjust the API mapping as needed. |
||
| }); | ||
|
|
||
| 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"> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (bug_risk): Attach handleSubmit to form onSubmit instead of button onClick Also update the button to type="submit" so pressing Enter submits the form and you don’t mix click and submit events. Suggested implementation: <form className="provider-profile-form" onSubmit={handleSubmit}> <button
type="submit"
className="provider-profile-submit"
> |
||
| <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> | ||
| ); | ||
| }; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Profile form fields initialized as empty
Fetch existing profile data on mount to pre-fill the form and avoid forcing users to re-enter unchanged values.