Skip to content

Commit

Permalink
userPage: Created user page
Browse files Browse the repository at this point in the history
  • Loading branch information
evan-scales committed Jan 21, 2024
1 parent 2b9551f commit ed22170
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 24 deletions.
27 changes: 14 additions & 13 deletions FU.API/FU.API/Hubs/ChatHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class ChatHub : Hub
/// <summary>
/// List of the connected users names.
/// </summary>
public static readonly List<string> ConnectedUsers = new ();
private static List<string> connectedUsers;

Check warning on line 19 in FU.API/FU.API/Hubs/ChatHub.cs

View workflow job for this annotation

GitHub Actions / test

Non-nullable field 'connectedUsers' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

/// <summary>
/// The app db context.
Expand All @@ -30,61 +30,62 @@ public class ChatHub : Hub
public ChatHub(AppDbContext context)
{
_context = context;
connectedUsers = new List<string>();
}

/// <summary>
/// Connect the user to the hub.
/// </summary>
/// <returns>Task.</returns>
public override Task OnConnectedAsync()
public async override Task OnConnectedAsync()
{
var userId = UserId;
var user = _context.Users.Find(userId);

if (user is null || user.Username is null)
{
return Task.CompletedTask;
return;
}

if (!ConnectedUsers.Contains(user.Username))
if (!connectedUsers.Contains(user.Username))
{
ConnectedUsers.Add(user.Username);
connectedUsers.Add(user.Username);
}

// Update the online status of the user
user.IsOnline = true;
_context.Users.Update(user);
_context.SaveChanges();
await _context.SaveChangesAsync();

return base.OnConnectedAsync();
await base.OnConnectedAsync();
}

/// <summary>
/// Disconnect the user from the hub.
/// </summary>
/// <param name="exception">Exception.</param>
/// <returns>Task.</returns>
public override Task OnDisconnectedAsync(Exception? exception)
public override async Task OnDisconnectedAsync(Exception? exception)
{
var userId = UserId;
var user = _context.Users.Find(userId);

if (user is null || user.Username is null)
{
return Task.CompletedTask;
return;
}

if (ConnectedUsers.Contains(user.Username))
if (connectedUsers.Contains(user.Username))
{
ConnectedUsers.Remove(user.Username);
connectedUsers.Remove(user.Username);
}

// Update the online status of the user
user.IsOnline = false;
_context.Users.Update(user);
_context.SaveChanges();
await _context.SaveChangesAsync();

return base.OnDisconnectedAsync(exception);
base.OnDisconnectedAsync(exception);

Check warning on line 88 in FU.API/FU.API/Hubs/ChatHub.cs

View workflow job for this annotation

GitHub Actions / test

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
}

/// <summary>
Expand Down
47 changes: 47 additions & 0 deletions FU.SPA/src/components/pages/UserProfile.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
height: 155px;
display: flex;
align-items: center;
justify-content: space-between;
flex-direction: row;

.userImage {
width: 100px;
Expand Down Expand Up @@ -32,7 +34,52 @@
font-weight: 700;
}
}

.buttons {
display: flex;
flex-direction: column;
margin-right: 75px;
height: 100px;
vertical-align: middle;

button {
width: 233px;
background-color: #E340DCDC;
color: #fff;
padding: 15px;
border: none;
margin: 5px;
/* height: 55px; */
}

button:hover {
background-color: #E340DC;
}
}
}

.body {
display: flex;
flex: row;

.bio {
margin-top: 20px;
background-color: #31084a;
color: #fff;
display: flex;
flex-direction: column;
align-items: flex-start;
min-width: 300px;
padding-left: 20px;
padding-bottom: 20px;

h1 {
margin: 0%;
}

p {
margin: 0%;
padding-top: 10px;
}
}
}
132 changes: 121 additions & 11 deletions FU.SPA/src/components/pages/UserProfile.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,140 @@ import UserContext from '../../context/userContext';
import UserService from '../../services/userService';
import NoPage from './NoPage';
import './UserProfile.css';
import { getDirectChat } from '../../services/chatService';
import { useNavigate } from 'react-router-dom';

export default function UserProfile() {
const navigate = useNavigate();
const { username } = useParams();
const { user } = useContext(UserContext);
const [userProfile, setUserProfile] = useState(null);
const [defaultPFP, setDefaultPFP] = useState(false);

const update = useCallback(async () => {
try {
const profile = await UserService.getUserprofile(username);
setUserProfile(profile);
setDefaultPFP(profile.pfpUrl.includes('https://tr.rbxcdn.com/38c6edcb50633730ff4cf39ac8859840/420/420/Hat/Png'));
} catch (error) {
console.error('Error fetching profile:', error);
}
}, [username]);

useEffect(() => {
update();
}, [username, update]);

// convert dob to years old
const dob = new Date(userProfile?.dob);
const today = new Date();
const age = Math.floor(
(today.getTime() - dob.getTime()) / (1000 * 3600 * 24 * 365)
);

const stringToColor = (string) => {
let hash = 0;
let i;
for (i = 0; i < string.length; i += 1) {
hash = string.charCodeAt(i) + ((hash << 5) - hash);
}
let color = '#';
for (i = 0; i < 3; i += 1) {
const value = (hash >> (i * 8)) & 0xff;
color += `00${value.toString(16)}`.slice(-2);
}
return color;
}

const initials = (name) => {
// split name by spaces and filter empty entries
let nameParts = name.split(' ').filter(Boolean);
// get the first letter of the first part
let initials = nameParts[0][0];
// if there is a second part to name
if (nameParts.length > 1) {
initials += nameParts[1][0];
}

return initials;
}

const renderPfp = () => {
return !defaultPFP ? (
<img
src={userProfile.pfpUrl}
className="userImage"
/>
) : (
<div
className="userImage"
style={{
backgroundColor: stringToColor(userProfile.username),
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
fontSize: '40px',
color: 'white',
fontWeight: 'bold',
}}
>
{initials(userProfile.username)}
</div>
);
}

const renderBio = () => {
if (!userProfile.bio) {
return;
}

if (user) {
return (
<div className="bio">
<h1>About Me</h1>
<p>{userProfile.bio}</p>
</div>
);
};

const renderHeaderButtons = () => {
if (!user || user.username === userProfile.username) {
return;
}

return (
<div className="buttons">
<button className="messageButton" onClick={clickSendMessage}>Send Message</button>
<button className="friendButton">Send Friend Request</button>
</div>
);
};

const clickSendMessage = async () => {
const chat = await getDirectChat(userProfile.id);
navigate(`/chat/${chat.id}`);
}

if (userProfile) {
return (
<>
<div className="header">
<img
src="https://tr.rbxcdn.com/38c6edcb50633730ff4cf39ac8859840/420/420/Hat/Png"
className="userImage"
/>
<div className="userInfo">
<p className="userName">{username}</p>
<p>Online Status</p>
<p>Age: 17</p>
<div className='left-content'>
{renderPfp()}
<div className="userInfo">
<p className="userName">{userProfile.username}</p>
{userProfile.dob && <p>Age: {age} years old</p>}
</div>
</div>
<div className='right-content'>
{renderHeaderButtons()}
</div>
</div>
<div className="body">
{renderBio()}
</div>
<div className="body"></div>
</>
);
} else {
return <NoPage />;
}
}
}

0 comments on commit ed22170

Please sign in to comment.