Skip to content
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

HER-45 Speaker Index Page #47

Open
wants to merge 66 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
5b0607e
Fixed problems on main
Jan 4, 2025
879a896
Started work on speaker index
Jan 5, 2025
08f497c
Styling the speaker index page, altered profile route to allow proper…
Jan 5, 2025
4afb88a
Fixed problems on main
Jan 4, 2025
f2ef55a
Started work on speaker index
Jan 5, 2025
f91bfb9
Styling the speaker index page, altered profile route to allow proper…
Jan 5, 2025
0e0757c
Merge main into branch
Jan 6, 2025
5791a19
Allow bio as a parameter in registration for devise
Jan 6, 2025
86161f0
Removed comment
Jan 6, 2025
500e7a4
Removed elements from speaker card
Jan 7, 2025
32a2a3f
Started work on speaker index
Jan 5, 2025
9fec5e2
Styling the speaker index page, altered profile route to allow proper…
Jan 5, 2025
f333370
Started work on speaker index
Jan 5, 2025
be022fc
Styling the speaker index page, altered profile route to allow proper…
Jan 5, 2025
2717380
Allow bio as a parameter in registration for devise
Jan 6, 2025
545d509
Removed comment
Jan 6, 2025
a4dc454
Removed elements from speaker card
Jan 7, 2025
1ee9cdd
Merge branch 'HER-45-Speaker-Index-Page' of https://github.com/Code-t…
Jan 7, 2025
55c26a1
Add code snippet to user model for profile_image_url
Jan 7, 2025
a1ead31
Add seed data to test frontend
Jan 8, 2025
d97faea
Merge branch 'main' into HER-45-Speaker-Index-Page
mhope21 Jan 8, 2025
5ebf45c
Fixed tests for modified permissions, fixed unintended deletion on css
Jan 8, 2025
4036be5
Merge branch 'HER-45-Speaker-Index-Page' of https://github.com/Code-t…
Jan 8, 2025
07d00ca
Attached test images, modified serializers and user model to display …
Jan 8, 2025
28ee50e
Started work on speaker index
Jan 5, 2025
7346dd5
Styling the speaker index page, altered profile route to allow proper…
Jan 5, 2025
f8f4757
Started work on speaker index
Jan 5, 2025
b169289
Styling the speaker index page, altered profile route to allow proper…
Jan 5, 2025
a471851
Allow bio as a parameter in registration for devise
Jan 6, 2025
bc85b98
Removed comment
Jan 6, 2025
1637d8b
Removed elements from speaker card
Jan 7, 2025
0a2a440
Started work on speaker index
Jan 5, 2025
95d1eac
Styling the speaker index page, altered profile route to allow proper…
Jan 5, 2025
9b924a4
Started work on speaker index
Jan 5, 2025
50a7233
Styling the speaker index page, altered profile route to allow proper…
Jan 5, 2025
f546bfb
Add seed data to test frontend
Jan 8, 2025
5fb387d
Fixed tests for modified permissions, fixed unintended deletion on css
Jan 8, 2025
81cb4ba
Attached test images, modified serializers and user model to display …
Jan 8, 2025
83aac86
Merge main into branch
Jan 8, 2025
e700589
Fixed profile image display
Jan 8, 2025
a103544
Started work on speaker index
Jan 5, 2025
641f065
Styling the speaker index page, altered profile route to allow proper…
Jan 5, 2025
5772732
Started work on speaker index
Jan 5, 2025
b4c2bcc
Styling the speaker index page, altered profile route to allow proper…
Jan 5, 2025
99b9073
Allow bio as a parameter in registration for devise
Jan 6, 2025
ca57f75
Removed comment
Jan 6, 2025
86a01dd
Removed elements from speaker card
Jan 7, 2025
fe57fe4
Started work on speaker index
Jan 5, 2025
c1abc67
Styling the speaker index page, altered profile route to allow proper…
Jan 5, 2025
50c69c6
Started work on speaker index
Jan 5, 2025
13cfd8b
Styling the speaker index page, altered profile route to allow proper…
Jan 5, 2025
89e8ddf
Add seed data to test frontend
Jan 8, 2025
68ce5c3
Fixed tests for modified permissions, fixed unintended deletion on css
Jan 8, 2025
a148a64
Attached test images, modified serializers and user model to display …
Jan 8, 2025
5c8eb36
Started work on speaker index
Jan 5, 2025
e061454
Styling the speaker index page, altered profile route to allow proper…
Jan 5, 2025
ccf26bc
Started work on speaker index
Jan 5, 2025
4998086
Styling the speaker index page, altered profile route to allow proper…
Jan 5, 2025
685bf6f
Started work on speaker index
Jan 5, 2025
58be7d6
Styling the speaker index page, altered profile route to allow proper…
Jan 5, 2025
3b30dca
Started work on speaker index
Jan 5, 2025
51edbc7
Styling the speaker index page, altered profile route to allow proper…
Jan 5, 2025
d637904
Fixed tests for modified permissions, fixed unintended deletion on css
Jan 8, 2025
42fd3d3
Fixed profile image display
Jan 8, 2025
8889ac7
Ran migrations for product
Jan 8, 2025
1101f05
Merge branch 'HER-45-Speaker-Index-Page' of https://github.com/Code-t…
Jan 8, 2025
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
3 changes: 2 additions & 1 deletion app/controllers/api/v1/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ def destroy

# Add profile action and pass current_user as params
def profile
render json: UserProfileSerializer.new(current_user)
@user = User.find(params[:id])
render json: UserProfileSerializer.new(@user)
end

private
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/users/registrations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ def respond_with(resource, _opts = {})

# Permit additional parameters for sign up
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [ :first_name, :last_name, :role ])
devise_parameter_sanitizer.permit(:sign_up, keys: [ :first_name, :last_name, :role, :bio ])
end

# Permit additional parameters for account update
def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [ :first_name, :last_name, :role ])
devise_parameter_sanitizer.permit(:account_update, keys: [ :first_name, :last_name, :role, :bio ])
end
end
3 changes: 2 additions & 1 deletion app/models/ability.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ def initialize(user)
can :manage, Donation
else
can :update, User, id: user.id
can :profile, User, id: user.id
can :profile, User
can :read, User
can :read, Order, user_id: user.id # Users can read their own kit requests
can :create, Order # Users can create new kit requests
can [ :update ], Order, user_id: user.id # Users can update their own kit requests
Expand Down
6 changes: 6 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ class User < ApplicationRecord

# Added profile_image here
has_one_attached :profile_image
# Add profile_image_url method for user to facilitate user_profile_serializer
include Rails.application.routes.url_helpers

def profile_image_url
rails_blob_url(profile_image, only_path: true) if profile_image.attached?
end

before_create :set_default_role

Expand Down
2 changes: 0 additions & 2 deletions app/serializers/user_profile_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ class UserProfileSerializer
def profile_image_url
if object.profile_image.attached?
Rails.application.routes.url_helpers.rails_blob_url(object.profile_image_url, only_path: true)
else
ActionController::Base.helpers.asset_path("default_profile_image.png")
end
end
end
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
get "kit_items_only", to: "kit_items#index_kit_items_only"
post "kit_items_only", to: "kit_items#create_kit_items_only"
patch "kit_items_only/:id", to: "kit_items#update_kit_items_only"
get "profile", to: "users#profile"
get "profile/:id", to: "users#profile"
resources :users
resources :donations
resources :contacts
Expand Down
99 changes: 96 additions & 3 deletions db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
KitItem.destroy_all
Kit.destroy_all
Address.destroy_all
Donation.destroy_all
User.destroy_all


Expand Down Expand Up @@ -294,9 +295,101 @@
perspectives_kit.kit_items << goldfish_boy_book << sevens_book << frankie_book << earth_blue_book << same_book << awesome_guide_book << mockingbird_book << classroom_book << neurotribes_book
impact_kit.kit_items << curious_dog_book << rosie_book << different_book << classroom_book << neurotribes_book

# Seed users
3.times do
FactoryBot.create(:user)
users = [
{
id: 1,
email: "[email protected]",
role: "user",
first_name: "Test",
last_name: "User",
bio: "Test User is a dedicated individual who loves exploring new technologies. In their free time, they enjoy hiking and reading science fiction novels.",
organization_id: nil,
password: "password"
},
{
id: 2,
email: "[email protected]",
role: "speaker",
first_name: "Speaker",
last_name: "One",
bio: "Speaker One is a seasoned public speaker with a passion for motivational talks. They have inspired thousands through their engaging presentations.",
organization_id: nil,
password: "password"
},
{
id: 3,
email: "[email protected]",
role: "admin",
first_name: "Admin",
last_name: "Jones",
bio: "Admin Jones is an experienced administrator who excels in managing complex systems. They are known for their problem-solving skills and attention to detail.",
organization_id: nil,
password: "password"
},
{
id: 4,
email: "[email protected]",
role: "speaker",
first_name: "Speaker",
last_name: "Two",
bio: "Speaker Two is a dynamic presenter with expertise in technology trends. They have a knack for making complex topics accessible to all audiences.",
organization_id: nil,
password: "password"
},
{
id: 5,
email: "[email protected]",
role: "speaker",
first_name: "Speaker",
last_name: "Three",
bio: "Speaker Three is a renowned keynote speaker with a background in business strategy. They have helped numerous companies achieve their goals through insightful talks.",
organization_id: nil,
password: "password"
},
{
id: 6,
email: "[email protected]",
role: "speaker",
first_name: "Speaker",
last_name: "Four",
bio: "Speaker Four is an expert in digital marketing with a focus on social media strategies. They have successfully led multiple campaigns for top brands.",
organization_id: nil,
password: "password"
},
{
id: 7,
email: "[email protected]",
role: "speaker",
first_name: "Speaker",
last_name: "Five",
bio: "Speaker Five is a motivational speaker who specializes in personal development. They have a unique ability to connect with audiences on a deep level.",
organization_id: nil,
password: "password"
},
{
id: 8,
email: "[email protected]",
role: "speaker",
first_name: "Speaker",
last_name: "Six",
bio: "Speaker Six is a thought leader in the field of innovation and creativity. They have authored several books on how to foster a culture of innovation.",
organization_id: nil,
password: "password"
},
{
id: 9,
email: "[email protected]",
role: "speaker",
first_name: "Sarah",
last_name: "Thompson",
bio: "I am a neurodiversity consultant with over 15 years of experience in inclusive education. My work focuses on training teachers and staff to better understand the needs of neurodivergent students, ensuring classrooms are environments of empathy and acceptance.",
organization_id: nil,
password: "password"
}
]

users.each do |user|
User.create!(user)
end

# Seed addresses
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions frontend/public/css/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,32 @@
}
}

.speaker-background {
background-color: white;
}

.speaker-card {
margin: 0 auto;
max-width: 100%;
width: 300px;
box-shadow: 0 15px 25px rgba(58, 57, 57, 0.2);
height: auto;
border-radius: 5px;
backdrop-filter: blur(14px);
background-color: rgba(163, 159, 159, 0.2);
padding: 10px;
text-align: center;
transition: transform 0.2s ease;
}

.speaker-card img {
transition: transform 0.2s ease;
}

.speaker-card:hover img {
transform: scale(1.1);
}

body {
margin: 0;
font-family: var(--bs-body-font-family);
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ function App() {
<Route path="add_kit_item" element={<AddNew header="Add New Kit Item"><NewKitItem /></AddNew>} />
<Route path="add_item_to_kit" element={<AddNew header="Add New Kit Item To Kit"><AddItemToKit /></AddNew>} />
</Route>
<Route path="/profile" element={<UserProfile/>}/>
<Route path="/profile/:id" element={<UserProfile/>}/>
</Routes>
</PageWrapper>
</Router>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/auth/CurrentUser.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const CurrentUser = ({ setLoggedIn, setUser, user }) => {
</p>
{user.role === 'admin' && <Link to="/admin"><i className="fas fa-user-shield"></i>
</Link>}
{user.role != 'admin' && <Link to="/profile"><i className='fas fa-user'></i></Link>}
{user.role != 'admin' && <Link to={`/profile/${user.id}`}><i className='fas fa-user'></i></Link>}
</div>
);
};
Expand Down
26 changes: 22 additions & 4 deletions frontend/src/components/auth/Registration.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default function Registration() {
const [password, setPassword] = useState("");

const [isTeacher, setIsTeacher] = useState(false);
const [isSpeaker, setIsSpeaker] = useState(false);
// Removed useState for name and added for firstName, lastName
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
Expand All @@ -19,6 +20,7 @@ export default function Registration() {
const handleClick = () => {

setIsTeacher((prevIsTeacher) => !prevIsTeacher);
setIsSpeaker((prevIsSpeaker) => !prevIsSpeaker);

};
// Handles initial signup, sets default role as user since only admin can assign a user as admin. Uses a POST action to sign up new user.
Expand All @@ -31,8 +33,8 @@ export default function Registration() {
user: {
email,
password,
// if isTeacher is true, then role set as teacher, otherwise, user
role: isTeacher ? "teacher" : "user",
// if isTeacher is true, then role set as teacher, if is isSpeaker, then speaker, otherwise, user
role: isTeacher ? "teacher" : isSpeaker ? "speaker" : "user",
// Removed name, and added firstName and lastName, mapped name details to column names
first_name: firstName,
last_name: lastName,
Expand Down Expand Up @@ -186,6 +188,7 @@ export default function Registration() {
>
A password is required.
</div>
<div className="d-flex">
{/* Added checkbox for teacher role */}
<div className="form-check">
<input
Expand All @@ -196,13 +199,28 @@ export default function Registration() {
onChange={handleClick}
/>
<label
className="form-check-label mt-4 text-muted"
className="form-check-label mt-4 text-muted me-5"
htmlFor="isTeacher"
>
<strong>I am a teacher</strong>
</label>
</div>

<div className="form-check">
<input
className="form-check-input mt-3 me-3"
type="checkbox"
id="isSpeaker"
checked={isSpeaker}
onChange={handleClick}
/>
<label
className="form-check-label mt-4 text-muted"
htmlFor="isSpeaker"
>
<strong>I am a speaker</strong>
</label>
</div>
</div>
</div>
</div>
</div>
Expand Down
98 changes: 84 additions & 14 deletions frontend/src/components/pages/RequestSpeaker.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,89 @@
import React, {useEffect} from "react";
import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import { API_URL } from "../../constants";


// Possible new feature: Ability to schedule a speaker to come to a user's school
function RequestSpeaker() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

const userUrl = `${API_URL}/users`;
const jwt = localStorage.getItem("jwt");

useEffect(() => {
window.scrollTo(0, 0);
}, []);

const fetchUsers = async () => {
try {
const response = await fetch(userUrl, {
method: "GET",
headers: {
Authorization: `Bearer ${jwt}`,
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error(`Error: ${response.status}`);
}
const data = await response.json();

setUsers(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};

// useEffect to fetch users when the component mounts
useEffect(() => {
fetchUsers();
}, []);

useEffect(() => {
window.scrollTo(0, 0);
}, []);
if (loading) return <p>Loading...</p>;
if (error)
return <p>Error: Unable to fetch speakers. Please try again later.</p>;

return(
<>
<div className="black-strip"></div>
<section className="speaker p-5"><div></div></section>

</>
)
};
return (
<div className="speaker-background">
<div className="black-strip"></div>
<section className="page-section">
<div>
<h1 className="text-center mt-5">Speakers</h1>
<div className="container p-5">
<div className="row d-flex">
{users
.filter((user) => user.role === "speaker")
.map((user) => (
<div className="col-lg-4 col-md-6 mb-5" key={user.id}>
<div className="speaker-card">
<div className="team-member">
<img
className="mx-auto rounded-circle w-50 h-50"
src={
user.profile_image_url || "assets/img/default-profile.png"
}
alt={`${user.first_name} ${user.last_name}`}
/>
<h4>{`${user.first_name} ${user.last_name}`}</h4>
<div className="text-start ms-3 me-3 mt-3">
<p><strong>Bio:</strong> {user.bio ? user.bio : "The user has not provided a bio yet."}</p>
</div>
<Link className="btn btn-primary" to={`/profile/${user.id}`}>
See My Profile
</Link>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</section>
</div>
);
}

export default RequestSpeaker;
export default RequestSpeaker;
Loading
Loading