feat: show friend request modal when click on sidebar

This commit is contained in:
Zamitto 2024-07-16 12:39:16 -03:00
parent 49fd34c3c0
commit 5aec973882
9 changed files with 91 additions and 42 deletions

View File

@ -25,6 +25,7 @@ import {
setGameRunning, setGameRunning,
} from "@renderer/features"; } from "@renderer/features";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { UserFriendRequestModal } from "./pages/shared-modals/user-friend-request-modal";
export interface AppProps { export interface AppProps {
children: React.ReactNode; children: React.ReactNode;
@ -38,6 +39,13 @@ export function App() {
const { clearDownload, setLastPacket } = useDownload(); const { clearDownload, setLastPacket } = useDownload();
const {
userDetails,
showFriendRequestsModal,
setShowFriendRequestModal,
updateFriendRequests,
} = useUserDetails();
const { fetchUserDetails, updateUserDetails, clearUserDetails } = const { fetchUserDetails, updateUserDetails, clearUserDetails } =
useUserDetails(); useUserDetails();
@ -94,7 +102,10 @@ export function App() {
} }
fetchUserDetails().then((response) => { fetchUserDetails().then((response) => {
if (response) updateUserDetails(response); if (response) {
updateUserDetails(response);
updateFriendRequests();
}
}); });
}, [fetchUserDetails, updateUserDetails, dispatch]); }, [fetchUserDetails, updateUserDetails, dispatch]);
@ -102,6 +113,7 @@ export function App() {
fetchUserDetails().then((response) => { fetchUserDetails().then((response) => {
if (response) { if (response) {
updateUserDetails(response); updateUserDetails(response);
updateFriendRequests();
showSuccessToast(t("successfully_signed_in")); showSuccessToast(t("successfully_signed_in"));
} }
}); });
@ -206,6 +218,11 @@ export function App() {
onClose={handleToastClose} onClose={handleToastClose}
/> />
<UserFriendRequestModal
visible={showFriendRequestsModal}
onClose={() => setShowFriendRequestModal(false)}
/>
<main> <main>
<Sidebar /> <Sidebar />

View File

@ -93,6 +93,6 @@ export const friendRequestButton = style({
width: "40px", width: "40px",
height: "40px", height: "40px",
":hover": { ":hover": {
color: vars.color.body, color: vars.color.muted,
}, },
}); });

View File

@ -12,7 +12,12 @@ export function SidebarProfile() {
const { t } = useTranslation("sidebar"); const { t } = useTranslation("sidebar");
const { userDetails, profileBackground } = useUserDetails(); const {
userDetails,
profileBackground,
friendRequests,
setShowFriendRequestModal,
} = useUserDetails();
const { gameRunning } = useAppSelector((state) => state.gameRunning); const { gameRunning } = useAppSelector((state) => state.gameRunning);
@ -77,17 +82,15 @@ export function SidebarProfile() {
)} )}
</div> </div>
</button> </button>
{userDetails && !gameRunning && ( {userDetails && friendRequests?.length && !gameRunning && (
<div className={styles.friendRequestContainer}> <div className={styles.friendRequestContainer}>
<button <button
type="button" type="button"
className={styles.friendRequestButton} className={styles.friendRequestButton}
onClick={() => { onClick={() => setShowFriendRequestModal(true)}
console.log("alshdaksjhdskajhd");
}}
> >
<PersonAddIcon size={24} /> <PersonAddIcon size={24} />
30 {friendRequests.length}
</button> </button>
</div> </div>
)} )}

View File

@ -5,12 +5,14 @@ export interface UserDetailsState {
userDetails: UserDetails | null; userDetails: UserDetails | null;
profileBackground: null | string; profileBackground: null | string;
friendRequests: FriendRequest[] | null; friendRequests: FriendRequest[] | null;
showFriendRequestsModal: boolean;
} }
const initialState: UserDetailsState = { const initialState: UserDetailsState = {
userDetails: null, userDetails: null,
profileBackground: null, profileBackground: null,
friendRequests: null, friendRequests: null,
showFriendRequestsModal: false,
}; };
export const userDetailsSlice = createSlice({ export const userDetailsSlice = createSlice({
@ -29,8 +31,15 @@ export const userDetailsSlice = createSlice({
) => { ) => {
state.friendRequests = action.payload; state.friendRequests = action.payload;
}, },
setShowFriendRequestsModal: (state, action: PayloadAction<boolean>) => {
state.showFriendRequestsModal = action.payload;
},
}, },
}); });
export const { setUserDetails, setProfileBackground, setFriendRequests } = export const {
userDetailsSlice.actions; setUserDetails,
setProfileBackground,
setFriendRequests,
setShowFriendRequestsModal,
} = userDetailsSlice.actions;

View File

@ -6,6 +6,7 @@ import {
setProfileBackground, setProfileBackground,
setUserDetails, setUserDetails,
setFriendRequests, setFriendRequests,
setShowFriendRequestsModal,
} from "@renderer/features"; } from "@renderer/features";
import { darkenColor } from "@renderer/helpers"; import { darkenColor } from "@renderer/helpers";
import { FriendRequestAction, UserDetails } from "@types"; import { FriendRequestAction, UserDetails } from "@types";
@ -13,9 +14,12 @@ import { FriendRequestAction, UserDetails } from "@types";
export function useUserDetails() { export function useUserDetails() {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { userDetails, profileBackground, friendRequests } = useAppSelector( const {
(state) => state.userDetails userDetails,
); profileBackground,
friendRequests,
showFriendRequestsModal,
} = useAppSelector((state) => state.userDetails);
const clearUserDetails = useCallback(async () => { const clearUserDetails = useCallback(async () => {
dispatch(setUserDetails(null)); dispatch(setUserDetails(null));
@ -87,6 +91,16 @@ export function useUserDetails() {
dispatch(setFriendRequests(friendRequests)); dispatch(setFriendRequests(friendRequests));
}, [dispatch]); }, [dispatch]);
const setShowFriendRequestModal = useCallback(
(showModal: boolean) => {
dispatch(setShowFriendRequestsModal(showModal));
if (showModal) {
updateFriendRequests();
}
},
[dispatch]
);
const sendFriendRequest = useCallback( const sendFriendRequest = useCallback(
async (userId: string) => { async (userId: string) => {
return window.electron return window.electron
@ -109,6 +123,7 @@ export function useUserDetails() {
userDetails, userDetails,
profileBackground, profileBackground,
friendRequests, friendRequests,
showFriendRequestsModal,
fetchUserDetails, fetchUserDetails,
signOut, signOut,
clearUserDetails, clearUserDetails,
@ -117,5 +132,6 @@ export function useUserDetails() {
sendFriendRequest, sendFriendRequest,
updateFriendRequests, updateFriendRequests,
updateFriendRequestState, updateFriendRequestState,
setShowFriendRequestModal,
}; };
} }

View File

@ -11,7 +11,7 @@ export interface UserAddFriendsModalProps {
onClose: () => void; onClose: () => void;
} }
export const UserAddFriendsModal = ({ export const UserFriendRequestModal = ({
visible, visible,
onClose, onClose,
}: UserAddFriendsModalProps) => { }: UserAddFriendsModalProps) => {

View File

@ -3,7 +3,7 @@ import {
PersonIcon, PersonIcon,
XCircleIcon, XCircleIcon,
} from "@primer/octicons-react"; } from "@primer/octicons-react";
import * as styles from "./user.css"; import * as styles from "../user/user.css";
import cn from "classnames"; import cn from "classnames";
import { SPACING_UNIT } from "@renderer/theme.css"; import { SPACING_UNIT } from "@renderer/theme.css";

View File

@ -16,12 +16,13 @@ import { buildGameDetailsPath, steamUrlBuilder } from "@renderer/helpers";
import { import {
PersonAddIcon, PersonAddIcon,
PersonIcon, PersonIcon,
PlusCircleIcon,
PlusIcon,
TelescopeIcon, TelescopeIcon,
} from "@primer/octicons-react"; } from "@primer/octicons-react";
import { Button, Link } from "@renderer/components"; import { Button, Link } from "@renderer/components";
import { UserEditProfileModal } from "./user-edit-modal"; import { UserEditProfileModal } from "./user-edit-modal";
import { UserSignOutModal } from "./user-signout-modal"; import { UserSignOutModal } from "./user-signout-modal";
import { UserAddFriendsModal } from "./user-add-friends-modal";
const MAX_MINUTES_TO_SHOW_IN_PLAYTIME = 120; const MAX_MINUTES_TO_SHOW_IN_PLAYTIME = 120;
@ -36,13 +37,17 @@ export function UserContent({
}: ProfileContentProps) { }: ProfileContentProps) {
const { t, i18n } = useTranslation("user_profile"); const { t, i18n } = useTranslation("user_profile");
const { userDetails, profileBackground, signOut, updateFriendRequests } = const {
useUserDetails(); userDetails,
profileBackground,
signOut,
updateFriendRequests,
setShowFriendRequestModal,
} = useUserDetails();
const { showSuccessToast } = useToast(); const { showSuccessToast } = useToast();
const [showEditProfileModal, setShowEditProfileModal] = useState(false); const [showEditProfileModal, setShowEditProfileModal] = useState(false);
const [showSignOutModal, setShowSignOutModal] = useState(false); const [showSignOutModal, setShowSignOutModal] = useState(false);
const [showAddFriendsModal, setShowAddFriendsModal] = useState(false);
const { gameRunning } = useAppSelector((state) => state.gameRunning); const { gameRunning } = useAppSelector((state) => state.gameRunning);
@ -117,11 +122,6 @@ export function UserContent({
onConfirm={handleConfirmSignout} onConfirm={handleConfirmSignout}
/> />
<UserAddFriendsModal
visible={showAddFriendsModal}
onClose={() => setShowAddFriendsModal(false)}
/>
<section <section
className={styles.profileContentBox} className={styles.profileContentBox}
style={{ style={{
@ -335,14 +335,7 @@ export function UserContent({
{(isMe || {(isMe ||
(userProfile.friends && userProfile.friends.length > 0)) && ( (userProfile.friends && userProfile.friends.length > 0)) && (
<div className={styles.friendsSection}> <div className={styles.friendsSection}>
<div <div className={styles.friendsSectionHeader}>
style={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
gap: `${SPACING_UNIT * 2}px`,
}}
>
<h2>{t("friends")}</h2> <h2>{t("friends")}</h2>
<div <div
@ -352,16 +345,9 @@ export function UserContent({
height: "1px", height: "1px",
}} }}
/> />
{isMe && ( <h3 style={{ fontWeight: "400" }}>
<button {userProfile.friends?.length || 0}
type="button" </h3>
style={{ color: vars.color.success, cursor: "pointer" }}
onClick={() => setShowAddFriendsModal(true)}
>
<PersonAddIcon size={24} />
30
</button>
)}
</div> </div>
<div <div
@ -399,6 +385,13 @@ export function UserContent({
</button> </button>
); );
})} })}
<Button
theme="outline"
onClick={() => setShowFriendRequestModal(true)}
>
<PlusIcon /> Add friend
</Button>
</div> </div>
</div> </div>
)} )}

View File

@ -119,6 +119,17 @@ export const friendsSection = style({
gap: `${SPACING_UNIT * 2}px`, gap: `${SPACING_UNIT * 2}px`,
}); });
export const friendsSectionHeader = style({
cursor: "pointer",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
gap: `${SPACING_UNIT * 2}px`,
":hover": {
color: vars.color.muted,
},
});
export const contentSidebar = style({ export const contentSidebar = style({
width: "100%", width: "100%",
display: "flex", display: "flex",