├── src ├── utils │ ├── test.js │ ├── Portal.js │ ├── isRTL.js │ ├── radialToLinearGradient.js │ ├── useOnClickOutside.js │ ├── messagesPosition.js │ └── dataURItoBlob.js ├── pages │ ├── login │ │ ├── style.module.css │ │ └── index.jsx │ ├── forgot │ │ ├── style.module.css │ │ └── index.jsx │ ├── post │ │ ├── style.module.css │ │ └── PostPage.jsx │ ├── messages │ │ ├── SeenStatus.jsx │ │ └── index.jsx │ ├── profile │ │ ├── ProfileMenu.jsx │ │ ├── Photos.jsx │ │ └── Friends.jsx │ ├── home │ │ └── style.module.css │ └── friends │ │ └── FreindCard.jsx ├── assets │ ├── chat_notification.wav │ └── notification_sweet.wav ├── components │ ├── UI │ │ ├── Card │ │ │ ├── Card.module.css │ │ │ └── Card.jsx │ │ ├── Loading │ │ │ ├── Loading.module.css │ │ │ └── Loading.jsx │ │ ├── Error │ │ │ ├── ErrorPage.module.css │ │ │ └── ErrorPage.jsx │ │ └── Notification │ │ │ ├── Notification.module.css │ │ │ └── Notification.jsx │ ├── home │ │ ├── left │ │ │ ├── Shortcut.jsx │ │ │ └── LeftLink.jsx │ │ ├── right │ │ │ ├── Contact.jsx │ │ │ ├── HomeRight.jsx │ │ │ └── HomeRight.module.css │ │ ├── stories │ │ │ ├── Story.jsx │ │ │ └── Stories.jsx │ │ ├── SendVerification │ │ │ ├── SendVerification.module.css │ │ │ └── SendVerification.jsx │ │ └── posts │ │ │ └── CreatePost │ │ │ ├── CreatePost.jsx │ │ │ └── CreatePost.module.css │ ├── header │ │ ├── AllMenuItem.jsx │ │ ├── userMenu │ │ │ ├── HelpSupport.jsx │ │ │ └── SettingsPrivacy.jsx │ │ └── notificationMenu │ │ │ └── NotificationMenu.module.css │ ├── noAuthHeader │ │ ├── style.module.css │ │ └── index.jsx │ ├── posts │ │ ├── post │ │ │ ├── MenuItem.jsx │ │ │ ├── likes │ │ │ │ ├── ReactsPopup.module.css │ │ │ │ └── ReactsPopup.jsx │ │ │ ├── shares │ │ │ │ ├── CreateSharePost.module.css │ │ │ │ └── ShareMenu.jsx │ │ │ └── comments │ │ │ │ ├── CreateComment.module.css │ │ │ │ └── Comments.jsx │ │ └── CreatePostPopup │ │ │ └── AddToYourPost.jsx │ ├── messages │ │ ├── chatInfo │ │ │ ├── chatInfo.module.css │ │ │ └── chatInfo.jsx │ │ ├── chatTheme │ │ │ └── ChatTheme.module.css │ │ ├── createGroup │ │ │ └── CreateGroup.module.css │ │ └── SearchUser.module.css │ ├── input │ │ ├── login │ │ │ ├── input.module.css │ │ │ └── index.jsx │ │ └── signup │ │ │ ├── style.module.css │ │ │ └── index.jsx │ ├── ActivateAccount │ │ └── ActivateAccount.module.css │ ├── login │ │ ├── LoginFooter.module.css │ │ ├── LoginForm.module.css │ │ ├── GenderSelector.jsx │ │ ├── LoginFooter.jsx │ │ └── SignupForm.module.css │ ├── profile │ │ ├── cover │ │ │ ├── OldCovers.module.css │ │ │ ├── Cover.module.css │ │ │ └── OldCovers.jsx │ │ └── intro │ │ │ ├── EditDetails.module.css │ │ │ ├── Detail.jsx │ │ │ ├── intro.module.css │ │ │ └── EditArea.jsx │ ├── FormLoader │ │ ├── style.module.css │ │ └── index.jsx │ ├── skeleton │ │ └── PostSkeleton.jsx │ ├── Popper │ │ └── Popper.jsx │ └── forgot │ │ └── SendEmail.jsx ├── app │ ├── store.js │ └── slices │ │ ├── soketSlice.js │ │ └── createPostSlice.js ├── routes │ ├── NotLoggedIn.js │ ├── router.jsx │ └── pagesData.jsx ├── svg │ ├── arrowDown.js │ ├── dots.js │ ├── arrowDow1.js │ ├── gaming.js │ ├── unseen.js │ ├── plus.js │ ├── watch.js │ ├── menu.js │ ├── homeActive.js │ ├── messenger.js │ ├── notifications.js │ ├── friendsActive.js │ ├── arrowRight.js │ ├── return.js │ ├── newRoom.js │ ├── info.js │ ├── home.js │ ├── like.js │ ├── send.js │ ├── liveVideo.js │ ├── friends.js │ ├── smile.js │ ├── feeling.js │ ├── photo.js │ ├── index.js │ ├── market.js │ ├── phone.js │ ├── public.js │ └── search.js ├── data │ └── post.js ├── styles │ └── dark.css ├── hooks │ ├── useSearch.js │ ├── useGetChat.js │ ├── useDeletePost.js │ ├── useAddToSearch.js │ ├── useRemoveFromSearch.js │ ├── useAddFCM.js │ ├── useOnClickOutside.js │ ├── useWindowDimensions .js │ ├── useReaction.js │ ├── useCommentLike.js │ ├── useComment.js │ ├── useCreateChatGroup.js │ ├── useSeenMessage.js │ ├── useRealationship.js │ ├── useSendMessage.js │ ├── useRenameGroup.js │ ├── useSeenNotification.js │ ├── useAddMember.js │ ├── useCreatePost.js │ ├── useRemoveMember.js │ └── useChangeTheme.js ├── fcm.js ├── index.js └── App.js ├── public ├── left │ ├── ad.png │ ├── ads.png │ ├── fav.png │ ├── feed.png │ ├── fund.png │ ├── jobs.png │ ├── live.png │ ├── pay.png │ ├── play.png │ ├── campus.png │ ├── climate.png │ ├── covid.png │ ├── events.png │ ├── friends.png │ ├── gaming.png │ ├── groups.png │ ├── pages.png │ ├── recent.png │ ├── saved.png │ ├── watch.png │ ├── weather.png │ ├── community.png │ ├── emotional.png │ ├── memories.png │ ├── messenger.png │ ├── messkids.png │ ├── recentad.png │ ├── fundraisers.png │ └── marketplace.png ├── google6a1d9096156ee381.html ├── icons │ ├── fb.png │ ├── job.png │ ├── follow.png │ ├── from.png │ ├── home.png │ ├── icon.png │ ├── icons1.png │ ├── icons2.png │ ├── icons3.png │ ├── icons4.png │ ├── icons5.png │ ├── icons6.png │ ├── icons7.png │ ├── icons8.png │ ├── icons9.png │ ├── join.png │ ├── lock.png │ ├── plus.png │ ├── public.png │ ├── report.png │ ├── colorful.png │ ├── friends.png │ ├── hometown.png │ ├── icons10.png │ ├── icons11.png │ ├── icons12.png │ ├── icons13.png │ ├── icons14.png │ ├── icons15.png │ ├── icons16.png │ ├── icons17.png │ ├── icons18.png │ ├── icons19.png │ ├── icons20.png │ ├── icons21.png │ ├── icons22.png │ ├── icons23.png │ ├── icons24.png │ ├── icons25.png │ ├── icons26.png │ ├── icons27.png │ ├── icons28.png │ ├── icons29.png │ ├── icons30.png │ ├── icons31.png │ ├── icons32.png │ ├── icons33.png │ ├── icons34.png │ ├── icons35.png │ ├── icons36.png │ ├── icons37.png │ ├── icons38.png │ ├── icons39.png │ ├── icons40.png │ ├── icons41.png │ ├── message.png │ ├── refresh.png │ ├── studies.png │ ├── addFriend.png │ ├── editFriends.png │ ├── following.png │ ├── instagram.png │ ├── publicpack.png │ ├── backbook-icon.png │ ├── cancelRequest.png │ ├── relationship.png │ ├── favoritesOutline.png │ ├── unfollowOutlined.png │ ├── facebook.svg │ └── backbook.svg ├── images │ ├── insta.png │ ├── ytb.png │ ├── github.png │ ├── linkedin.png │ ├── background.webp │ ├── default_pic.png │ ├── default_profile.png │ └── postBackgrounds │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ ├── 4.jpg │ │ ├── 5.jpg │ │ ├── 6.jpg │ │ ├── 7.jpg │ │ ├── 8.jpg │ │ ├── 9.jpg │ │ └── 10.jpg ├── reacts │ ├── angry.gif │ ├── haha.gif │ ├── like.gif │ ├── like.png │ ├── love.gif │ ├── sad.gif │ ├── wow.gif │ ├── love.svg │ ├── like.svg │ └── haha.svg ├── robots.txt ├── stories │ ├── 1.webp │ ├── 2.webp │ ├── 3.webp │ ├── 4.webp │ ├── 5.webp │ ├── profile1.webp │ ├── profile2.webp │ ├── profile3.webp │ ├── profile4.webp │ └── profile5.webp ├── manifest.json ├── index.html └── firebase-messaging-sw.js ├── .gitignore ├── .vscode └── settings.json └── package.json /src/utils/test.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/left/ad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/ad.png -------------------------------------------------------------------------------- /public/google6a1d9096156ee381.html: -------------------------------------------------------------------------------- 1 | google-site-verification: google6a1d9096156ee381.html 2 | -------------------------------------------------------------------------------- /public/icons/fb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/fb.png -------------------------------------------------------------------------------- /public/icons/job.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/job.png -------------------------------------------------------------------------------- /public/left/ads.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/ads.png -------------------------------------------------------------------------------- /public/left/fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/fav.png -------------------------------------------------------------------------------- /public/left/feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/feed.png -------------------------------------------------------------------------------- /public/left/fund.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/fund.png -------------------------------------------------------------------------------- /public/left/jobs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/jobs.png -------------------------------------------------------------------------------- /public/left/live.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/live.png -------------------------------------------------------------------------------- /public/left/pay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/pay.png -------------------------------------------------------------------------------- /public/left/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/play.png -------------------------------------------------------------------------------- /src/pages/login/style.module.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | background: var(--bg-secondary); 3 | } 4 | -------------------------------------------------------------------------------- /public/icons/follow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/follow.png -------------------------------------------------------------------------------- /public/icons/from.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/from.png -------------------------------------------------------------------------------- /public/icons/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/home.png -------------------------------------------------------------------------------- /public/icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icon.png -------------------------------------------------------------------------------- /public/icons/icons1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons1.png -------------------------------------------------------------------------------- /public/icons/icons2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons2.png -------------------------------------------------------------------------------- /public/icons/icons3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons3.png -------------------------------------------------------------------------------- /public/icons/icons4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons4.png -------------------------------------------------------------------------------- /public/icons/icons5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons5.png -------------------------------------------------------------------------------- /public/icons/icons6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons6.png -------------------------------------------------------------------------------- /public/icons/icons7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons7.png -------------------------------------------------------------------------------- /public/icons/icons8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons8.png -------------------------------------------------------------------------------- /public/icons/icons9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons9.png -------------------------------------------------------------------------------- /public/icons/join.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/join.png -------------------------------------------------------------------------------- /public/icons/lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/lock.png -------------------------------------------------------------------------------- /public/icons/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/plus.png -------------------------------------------------------------------------------- /public/icons/public.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/public.png -------------------------------------------------------------------------------- /public/icons/report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/report.png -------------------------------------------------------------------------------- /public/images/insta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/insta.png -------------------------------------------------------------------------------- /public/images/ytb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/ytb.png -------------------------------------------------------------------------------- /public/left/campus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/campus.png -------------------------------------------------------------------------------- /public/left/climate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/climate.png -------------------------------------------------------------------------------- /public/left/covid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/covid.png -------------------------------------------------------------------------------- /public/left/events.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/events.png -------------------------------------------------------------------------------- /public/left/friends.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/friends.png -------------------------------------------------------------------------------- /public/left/gaming.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/gaming.png -------------------------------------------------------------------------------- /public/left/groups.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/groups.png -------------------------------------------------------------------------------- /public/left/pages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/pages.png -------------------------------------------------------------------------------- /public/left/recent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/recent.png -------------------------------------------------------------------------------- /public/left/saved.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/saved.png -------------------------------------------------------------------------------- /public/left/watch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/watch.png -------------------------------------------------------------------------------- /public/left/weather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/weather.png -------------------------------------------------------------------------------- /public/reacts/angry.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/reacts/angry.gif -------------------------------------------------------------------------------- /public/reacts/haha.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/reacts/haha.gif -------------------------------------------------------------------------------- /public/reacts/like.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/reacts/like.gif -------------------------------------------------------------------------------- /public/reacts/like.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/reacts/like.png -------------------------------------------------------------------------------- /public/reacts/love.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/reacts/love.gif -------------------------------------------------------------------------------- /public/reacts/sad.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/reacts/sad.gif -------------------------------------------------------------------------------- /public/reacts/wow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/reacts/wow.gif -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/stories/1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/stories/1.webp -------------------------------------------------------------------------------- /public/stories/2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/stories/2.webp -------------------------------------------------------------------------------- /public/stories/3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/stories/3.webp -------------------------------------------------------------------------------- /public/stories/4.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/stories/4.webp -------------------------------------------------------------------------------- /public/stories/5.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/stories/5.webp -------------------------------------------------------------------------------- /public/icons/colorful.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/colorful.png -------------------------------------------------------------------------------- /public/icons/friends.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/friends.png -------------------------------------------------------------------------------- /public/icons/hometown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/hometown.png -------------------------------------------------------------------------------- /public/icons/icons10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons10.png -------------------------------------------------------------------------------- /public/icons/icons11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons11.png -------------------------------------------------------------------------------- /public/icons/icons12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons12.png -------------------------------------------------------------------------------- /public/icons/icons13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons13.png -------------------------------------------------------------------------------- /public/icons/icons14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons14.png -------------------------------------------------------------------------------- /public/icons/icons15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons15.png -------------------------------------------------------------------------------- /public/icons/icons16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons16.png -------------------------------------------------------------------------------- /public/icons/icons17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons17.png -------------------------------------------------------------------------------- /public/icons/icons18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons18.png -------------------------------------------------------------------------------- /public/icons/icons19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons19.png -------------------------------------------------------------------------------- /public/icons/icons20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons20.png -------------------------------------------------------------------------------- /public/icons/icons21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons21.png -------------------------------------------------------------------------------- /public/icons/icons22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons22.png -------------------------------------------------------------------------------- /public/icons/icons23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons23.png -------------------------------------------------------------------------------- /public/icons/icons24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons24.png -------------------------------------------------------------------------------- /public/icons/icons25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons25.png -------------------------------------------------------------------------------- /public/icons/icons26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons26.png -------------------------------------------------------------------------------- /public/icons/icons27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons27.png -------------------------------------------------------------------------------- /public/icons/icons28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons28.png -------------------------------------------------------------------------------- /public/icons/icons29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons29.png -------------------------------------------------------------------------------- /public/icons/icons30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons30.png -------------------------------------------------------------------------------- /public/icons/icons31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons31.png -------------------------------------------------------------------------------- /public/icons/icons32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons32.png -------------------------------------------------------------------------------- /public/icons/icons33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons33.png -------------------------------------------------------------------------------- /public/icons/icons34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons34.png -------------------------------------------------------------------------------- /public/icons/icons35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons35.png -------------------------------------------------------------------------------- /public/icons/icons36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons36.png -------------------------------------------------------------------------------- /public/icons/icons37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons37.png -------------------------------------------------------------------------------- /public/icons/icons38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons38.png -------------------------------------------------------------------------------- /public/icons/icons39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons39.png -------------------------------------------------------------------------------- /public/icons/icons40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons40.png -------------------------------------------------------------------------------- /public/icons/icons41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/icons41.png -------------------------------------------------------------------------------- /public/icons/message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/message.png -------------------------------------------------------------------------------- /public/icons/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/refresh.png -------------------------------------------------------------------------------- /public/icons/studies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/studies.png -------------------------------------------------------------------------------- /public/images/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/github.png -------------------------------------------------------------------------------- /public/left/community.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/community.png -------------------------------------------------------------------------------- /public/left/emotional.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/emotional.png -------------------------------------------------------------------------------- /public/left/memories.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/memories.png -------------------------------------------------------------------------------- /public/left/messenger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/messenger.png -------------------------------------------------------------------------------- /public/left/messkids.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/messkids.png -------------------------------------------------------------------------------- /public/left/recentad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/recentad.png -------------------------------------------------------------------------------- /public/icons/addFriend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/addFriend.png -------------------------------------------------------------------------------- /public/icons/editFriends.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/editFriends.png -------------------------------------------------------------------------------- /public/icons/following.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/following.png -------------------------------------------------------------------------------- /public/icons/instagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/instagram.png -------------------------------------------------------------------------------- /public/icons/publicpack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/publicpack.png -------------------------------------------------------------------------------- /public/images/linkedin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/linkedin.png -------------------------------------------------------------------------------- /public/left/fundraisers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/fundraisers.png -------------------------------------------------------------------------------- /public/left/marketplace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/left/marketplace.png -------------------------------------------------------------------------------- /public/stories/profile1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/stories/profile1.webp -------------------------------------------------------------------------------- /public/stories/profile2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/stories/profile2.webp -------------------------------------------------------------------------------- /public/stories/profile3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/stories/profile3.webp -------------------------------------------------------------------------------- /public/stories/profile4.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/stories/profile4.webp -------------------------------------------------------------------------------- /public/stories/profile5.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/stories/profile5.webp -------------------------------------------------------------------------------- /public/icons/backbook-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/backbook-icon.png -------------------------------------------------------------------------------- /public/icons/cancelRequest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/cancelRequest.png -------------------------------------------------------------------------------- /public/icons/relationship.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/relationship.png -------------------------------------------------------------------------------- /public/images/background.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/background.webp -------------------------------------------------------------------------------- /public/images/default_pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/default_pic.png -------------------------------------------------------------------------------- /public/icons/favoritesOutline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/favoritesOutline.png -------------------------------------------------------------------------------- /public/icons/unfollowOutlined.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/icons/unfollowOutlined.png -------------------------------------------------------------------------------- /public/images/default_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/default_profile.png -------------------------------------------------------------------------------- /src/assets/chat_notification.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/src/assets/chat_notification.wav -------------------------------------------------------------------------------- /src/assets/notification_sweet.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/src/assets/notification_sweet.wav -------------------------------------------------------------------------------- /public/images/postBackgrounds/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/postBackgrounds/1.jpg -------------------------------------------------------------------------------- /public/images/postBackgrounds/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/postBackgrounds/2.jpg -------------------------------------------------------------------------------- /public/images/postBackgrounds/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/postBackgrounds/3.jpg -------------------------------------------------------------------------------- /public/images/postBackgrounds/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/postBackgrounds/4.jpg -------------------------------------------------------------------------------- /public/images/postBackgrounds/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/postBackgrounds/5.jpg -------------------------------------------------------------------------------- /public/images/postBackgrounds/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/postBackgrounds/6.jpg -------------------------------------------------------------------------------- /public/images/postBackgrounds/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/postBackgrounds/7.jpg -------------------------------------------------------------------------------- /public/images/postBackgrounds/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/postBackgrounds/8.jpg -------------------------------------------------------------------------------- /public/images/postBackgrounds/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/postBackgrounds/9.jpg -------------------------------------------------------------------------------- /public/images/postBackgrounds/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msobkyy/backbook/HEAD/public/images/postBackgrounds/10.jpg -------------------------------------------------------------------------------- /src/components/UI/Card/Card.module.css: -------------------------------------------------------------------------------- 1 | .card { 2 | background: var(--bg-primary); 3 | border-radius: 10px; 4 | box-shadow: 0 2px 4px var(--shadow-1); 5 | padding: 1rem; 6 | } 7 | -------------------------------------------------------------------------------- /src/pages/forgot/style.module.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | background: var(--bg-secondary); 3 | height: 78vh; 4 | min-height: 600px; 5 | display: flex; 6 | justify-content: center; 7 | align-items: center; 8 | padding: 10px; 9 | } 10 | -------------------------------------------------------------------------------- /src/components/UI/Loading/Loading.module.css: -------------------------------------------------------------------------------- 1 | .main { 2 | height: 100vh; 3 | width: 100%; 4 | color: var(--color-primary); 5 | background: var(--bg-primary); 6 | display: flex; 7 | align-items: center; 8 | justify-content: center; 9 | } 10 | -------------------------------------------------------------------------------- /src/utils/Portal.js: -------------------------------------------------------------------------------- 1 | import { createPortal } from "react-dom"; 2 | 3 | function Portal({ children, id }) { 4 | const portalDom = id ? document.getElementById(id) : document.body; 5 | 6 | return createPortal(children, portalDom); 7 | } 8 | 9 | export default Portal; 10 | -------------------------------------------------------------------------------- /src/pages/post/style.module.css: -------------------------------------------------------------------------------- 1 | .post { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | justify-content: center; 6 | width: 100%; 7 | height: 100%; 8 | background: var(--bg-secondary); 9 | padding: 70px 6px; 10 | } 11 | .container { 12 | width: 100%; 13 | max-width: 590px; 14 | } 15 | -------------------------------------------------------------------------------- /src/components/UI/Error/ErrorPage.module.css: -------------------------------------------------------------------------------- 1 | .main { 2 | height: calc(100vh - 100px); 3 | width: 100%; 4 | color: var(--color-primary); 5 | background: var(--bg-secondary); 6 | display: flex; 7 | align-items: center; 8 | justify-content: center; 9 | flex-direction: column; 10 | gap: 20px; 11 | font-size: 24px; 12 | } 13 | -------------------------------------------------------------------------------- /src/components/UI/Card/Card.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styles from "./Card.module.css"; 3 | 4 | function Card({ children, className, innerRef, style }) { 5 | return ( 6 |
7 | {children} 8 |
9 | ); 10 | } 11 | 12 | export default Card; 13 | -------------------------------------------------------------------------------- /src/components/UI/Loading/Loading.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import classes from "./Loading.module.css"; 3 | import PuffLoader from "react-spinners/PuffLoader"; 4 | 5 | function Loading() { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | } 12 | 13 | export default Loading; 14 | -------------------------------------------------------------------------------- /src/components/home/left/Shortcut.jsx: -------------------------------------------------------------------------------- 1 | import styles from "./HomeLeft.module.css"; 2 | 3 | export default function Shortcut({ link, img, name }) { 4 | return ( 5 | 11 | 12 | {name} 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /src/utils/isRTL.js: -------------------------------------------------------------------------------- 1 | export default function isRTL(s) { 2 | const ltrChars = 3 | "A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF" + 4 | "\u2C00-\uFB1C\uFDFE-\uFE6F\uFEFD-\uFFFF"; 5 | const rtlChars = "\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC"; 6 | const rtlDirCheck = new RegExp("^[^" + ltrChars + "]*[" + rtlChars + "]"); 7 | 8 | return rtlDirCheck.test(s); 9 | } 10 | -------------------------------------------------------------------------------- /src/app/store.js: -------------------------------------------------------------------------------- 1 | import { configureStore } from "@reduxjs/toolkit"; 2 | import userSlice from "./slices/userSlice"; 3 | import createPostSlice from "./slices/createPostSlice"; 4 | import createSoketSlice from "./slices/soketSlice"; 5 | 6 | export const store = configureStore({ 7 | reducer: { 8 | user: userSlice, 9 | createPost: createPostSlice, 10 | soketSlice: createSoketSlice, 11 | }, 12 | }); 13 | -------------------------------------------------------------------------------- /src/routes/NotLoggedIn.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { Navigate, Outlet } from "react-router-dom"; 4 | import Loading from "../components/UI/Loading/Loading"; 5 | 6 | export default function NotLoggedIn({ user }) { 7 | return user.userinfo ? ( 8 | 9 | ) : ( 10 | }> 11 | 12 | 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /src/svg/arrowDown.js: -------------------------------------------------------------------------------- 1 | function ArrowDown({ color }) { 2 | return ( 3 | 4 | 5 | 6 | ); 7 | } 8 | 9 | export default ArrowDown; 10 | -------------------------------------------------------------------------------- /src/components/home/right/Contact.jsx: -------------------------------------------------------------------------------- 1 | import styles from "./HomeRight.module.css"; 2 | 3 | export default function Contact({ user }) { 4 | return ( 5 |
6 |
7 | 8 |
9 | 10 | {user.first_name} {user.last_name} 11 | 12 |
13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | *.env 8 | 9 | # testing 10 | /coverage 11 | 12 | # production 13 | /build 14 | 15 | # misc 16 | .DS_Store 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | -------------------------------------------------------------------------------- /src/components/header/AllMenuItem.jsx: -------------------------------------------------------------------------------- 1 | import styles from "./AllMenu.module.css"; 2 | 3 | export default function AllMenuItem({ name, description, icon }) { 4 | return ( 5 |
6 | 7 |
8 | {name} 9 | {description} 10 |
11 |
12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /src/svg/dots.js: -------------------------------------------------------------------------------- 1 | function Dots({ color }) { 2 | return ( 3 | 4 | 9 | 10 | ); 11 | } 12 | 13 | export default Dots; 14 | -------------------------------------------------------------------------------- /src/components/noAuthHeader/style.module.css: -------------------------------------------------------------------------------- 1 | .header { 2 | position: fixed; 3 | top: 0; 4 | left: 0; 5 | height: 56px; 6 | z-index: 99; 7 | background: var(--bg-primary); 8 | width: 100%; 9 | box-shadow: 0 2px 4px var(--shadow-1); 10 | display: flex; 11 | justify-content: space-between; 12 | padding: 10px 25px; 13 | align-items: center; 14 | color: var(--color-primary); 15 | } 16 | .login button { 17 | height: auto; 18 | font-weight: 500; 19 | } 20 | -------------------------------------------------------------------------------- /src/svg/arrowDow1.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | function ArrowDown1({ color }) { 4 | return ( 5 | 6 | 11 | 12 | ); 13 | } 14 | 15 | export default ArrowDown1; 16 | -------------------------------------------------------------------------------- /src/components/posts/post/MenuItem.jsx: -------------------------------------------------------------------------------- 1 | import classes from "./Post.module.css"; 2 | 3 | export default function MenuItem({ icon, title, subtitle, img }) { 4 | return ( 5 |
  • 6 | {img ? : } 7 |
    8 | {title} 9 | {subtitle && {subtitle}} 10 |
    11 |
  • 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /src/components/home/stories/Story.jsx: -------------------------------------------------------------------------------- 1 | import styles from "./Stories.module.css"; 2 | 3 | export default function Story({ story }) { 4 | return ( 5 |
    6 | 7 |
    8 | 9 |
    10 |
    {story.profile_name}
    11 |
    12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /src/components/messages/chatInfo/chatInfo.module.css: -------------------------------------------------------------------------------- 1 | .main { 2 | display: flex; 3 | justify-content: space-between; 4 | align-items: center; 5 | padding: 10px; 6 | border-radius: 8px; 7 | cursor: pointer; 8 | font-size: 14px; 9 | font-weight: 600; 10 | } 11 | .rotate360 { 12 | transform: rotate(180deg); 13 | } 14 | .content { 15 | padding: 5px; 16 | max-height: 320px; 17 | overflow: auto; 18 | } 19 | 20 | :global(.dark) .icon svg { 21 | fill: rgb(144, 144, 144); 22 | } 23 | -------------------------------------------------------------------------------- /src/data/post.js: -------------------------------------------------------------------------------- 1 | export const postBackgrounds = [ 2 | "../../images/postBackgrounds/1.jpg", 3 | "../../images/postBackgrounds/2.jpg", 4 | "../../images/postBackgrounds/3.jpg", 5 | "../../images/postBackgrounds/4.jpg", 6 | "../../images/postBackgrounds/5.jpg", 7 | "../../images/postBackgrounds/6.jpg", 8 | "../../images/postBackgrounds/7.jpg", 9 | "../../images/postBackgrounds/8.jpg", 10 | "../../images/postBackgrounds/9.jpg", 11 | "../../images/postBackgrounds/10.jpg", 12 | ]; 13 | -------------------------------------------------------------------------------- /src/utils/radialToLinearGradient.js: -------------------------------------------------------------------------------- 1 | export default function radialToLinearGradient(radialGradient) { 2 | var linearGradient = "linear-gradient("; 3 | var colorsAndPositions = radialGradient.match(/rgb\(\d+, \d+, \d+\)/g); 4 | for (var i = 0; i < colorsAndPositions.length; i++) { 5 | linearGradient += colorsAndPositions[i]; 6 | if (i < colorsAndPositions.length - 1) { 7 | linearGradient += ", "; 8 | } 9 | } 10 | linearGradient += ")"; 11 | return linearGradient; 12 | } 13 | -------------------------------------------------------------------------------- /src/styles/dark.css: -------------------------------------------------------------------------------- 1 | .dark { 2 | --bg-primary: #242526; 3 | --bg-secondary: #18191a; 4 | --bg-third: #3a3b3c; 5 | --bg-forth: #3a3b3c; 6 | --bg-fifth: #888888; 7 | --color-primary: #e4e6eb; 8 | --color-secondary: #b0b3b8; 9 | --divider: #4e4e4e; 10 | --light-blue-color: rgba(45, 136, 255, 0.1); 11 | } 12 | .dark .blur { 13 | background: rgba(1, 1, 1, 0.53); 14 | } 15 | .dark .small_circle i { 16 | filter: invert(100%); 17 | } 18 | 19 | .dark .create_icon { 20 | filter: invert(100%); 21 | } 22 | -------------------------------------------------------------------------------- /src/hooks/useSearch.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | 4 | const Search = async ({ term }) => { 5 | const { data } = await axios.post( 6 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/users/search`, 7 | { term }, 8 | { 9 | withCredentials: true, 10 | } 11 | ); 12 | return data; 13 | }; 14 | 15 | export const useSearch = () => { 16 | return useMutation({ 17 | mutationKey: "useSearch", 18 | mutationFn: Search, 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /src/svg/gaming.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function Gaming({ color }) { 4 | return ( 5 | 6 | 7 | 8 | ); 9 | } 10 | 11 | export default Gaming; 12 | -------------------------------------------------------------------------------- /src/hooks/useGetChat.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | 4 | const GetChat = async ({ user }) => { 5 | const { data } = await axios.post( 6 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/chats/create/private`, 7 | { userId: user }, 8 | { 9 | withCredentials: true, 10 | } 11 | ); 12 | return data; 13 | }; 14 | 15 | export const useGetChat = () => { 16 | return useMutation({ 17 | mutationKey: "useGetChat", 18 | mutationFn: GetChat, 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /src/hooks/useDeletePost.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | 4 | const DeletePost = async ({ post }) => { 5 | const { data } = await axios.put( 6 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/posts/${post}`, 7 | {}, 8 | { 9 | withCredentials: true, 10 | } 11 | ); 12 | return data; 13 | }; 14 | 15 | export const useDeletePost = (post) => { 16 | return useMutation({ 17 | mutationKey: ["useDeletePost", post], 18 | mutationFn: DeletePost, 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /src/svg/unseen.js: -------------------------------------------------------------------------------- 1 | function UnSeen({ color = "#ffffff4d" }) { 2 | return ( 3 | 11 | Delivered 12 | 13 | 14 | ); 15 | } 16 | 17 | export default UnSeen; 18 | -------------------------------------------------------------------------------- /src/hooks/useAddToSearch.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | 4 | const AddToSearch = async ({ user }) => { 5 | const { data } = await axios.post( 6 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/users/search/add`, 7 | { searchUser: user }, 8 | { 9 | withCredentials: true, 10 | } 11 | ); 12 | return data; 13 | }; 14 | 15 | export const useAddToSearch = () => { 16 | return useMutation({ 17 | mutationKey: "useAddToSearch", 18 | mutationFn: AddToSearch, 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /src/fcm.js: -------------------------------------------------------------------------------- 1 | import { initializeApp } from "firebase/app"; 2 | import { getMessaging } from "firebase/messaging"; 3 | 4 | const firebaseConfig = { 5 | apiKey: "AIzaSyD8bk57MfPgPmzRQU6fA2x89AZ4ldQlS80", 6 | authDomain: "backbook-370316.firebaseapp.com", 7 | projectId: "backbook-370316", 8 | storageBucket: "backbook-370316.appspot.com", 9 | messagingSenderId: "398150721140", 10 | appId: "1:398150721140:web:d93f0193496929a5037b21", 11 | measurementId: "G-VVEDB7NXXQ", 12 | }; 13 | 14 | export const app = initializeApp(firebaseConfig); 15 | export const messaging = getMessaging(app); 16 | -------------------------------------------------------------------------------- /src/hooks/useRemoveFromSearch.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | 4 | const RemoveFromSearch = async ({ user }) => { 5 | const { data } = await axios.post( 6 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/users/search/remove`, 7 | { searchUser: user }, 8 | { 9 | withCredentials: true, 10 | } 11 | ); 12 | return data; 13 | }; 14 | 15 | export const useRemoveFromSearch = () => { 16 | return useMutation({ 17 | mutationKey: "useRemoveFromSearch", 18 | mutationFn: RemoveFromSearch, 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /src/components/home/left/LeftLink.jsx: -------------------------------------------------------------------------------- 1 | import styles from "./HomeLeft.module.css"; 2 | 3 | export default function LeftLink({ img, text, notification }) { 4 | return ( 5 |
    6 | 7 | {notification !== undefined ? ( 8 |
    9 |
    {text}
    10 |
    {notification}
    11 |
    12 | ) : ( 13 | {text} 14 | )} 15 |
    16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /src/components/input/login/input.module.css: -------------------------------------------------------------------------------- 1 | .wrap { 2 | width: 100%; 3 | position: relative; 4 | } 5 | .wrap input { 6 | background: var(--bg-primary); 7 | border: 1px solid var(--bg-third); 8 | border-radius: 10px; 9 | color: var(--color-primary); 10 | font-size: 17px; 11 | height: 50px; 12 | margin-bottom: 10px; 13 | outline: none; 14 | padding-left: 10px; 15 | width: 100%; 16 | } 17 | .error { 18 | border-color: #b94a48 !important; 19 | } 20 | .wrap i { 21 | position: absolute; 22 | right: 5px; 23 | top: 15px; 24 | -webkit-transform: scale(0.8); 25 | transform: scale(0.8); 26 | } 27 | -------------------------------------------------------------------------------- /src/components/input/signup/style.module.css: -------------------------------------------------------------------------------- 1 | .wrap { 2 | width: 100%; 3 | position: relative; 4 | } 5 | .wrap input { 6 | background: var(--bg-secondary); 7 | border: 1px solid var(--bg-third); 8 | border-radius: 10px; 9 | color: var(--color-primary); 10 | font-size: 17px; 11 | height: 50px; 12 | margin-bottom: 10px; 13 | outline: none; 14 | padding-left: 10px; 15 | width: 100%; 16 | } 17 | .error { 18 | border-color: #b94a48 !important; 19 | } 20 | .wrap i { 21 | position: absolute; 22 | right: 5px; 23 | top: 15px; 24 | -webkit-transform: scale(0.8); 25 | transform: scale(0.8); 26 | } 27 | -------------------------------------------------------------------------------- /src/components/ActivateAccount/ActivateAccount.module.css: -------------------------------------------------------------------------------- 1 | .card { 2 | min-width: 400px; 3 | display: flex; 4 | flex-direction: column; 5 | justify-content: center; 6 | position: absolute; 7 | left: 50%; 8 | top: 50%; 9 | -webkit-transform: translate(-50%, -50%); 10 | transform: translate(-50%, -50%); 11 | } 12 | 13 | .header { 14 | width: 100%; 15 | padding: 8px 5px; 16 | text-align: center; 17 | } 18 | .body { 19 | display: flex; 20 | align-items: center; 21 | justify-content: center; 22 | padding: 10px; 23 | } 24 | @media (max-width: 400px) { 25 | .card { 26 | min-width: 95%; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/svg/plus.js: -------------------------------------------------------------------------------- 1 | function Plus({ color }) { 2 | return ( 3 | 4 | 5 | 9 | 13 | 14 | 15 | ); 16 | } 17 | 18 | export default Plus; 19 | -------------------------------------------------------------------------------- /src/svg/watch.js: -------------------------------------------------------------------------------- 1 | function Watch({ color }) { 2 | return ( 3 | 4 | 5 | 6 | ); 7 | } 8 | 9 | export default Watch; 10 | -------------------------------------------------------------------------------- /src/utils/useOnClickOutside.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | 3 | export default function useOnClickOutside(ref, handler) { 4 | useEffect(() => { 5 | const listener = (event) => { 6 | if (!ref.current || ref.current.contains(event.target)) { 7 | return; 8 | } 9 | handler(event); 10 | }; 11 | document.addEventListener("mousedown", listener); 12 | document.addEventListener("touchstart", listener); 13 | return () => { 14 | document.removeEventListener("mousedown", listener); 15 | document.removeEventListener("touchstart", listener); 16 | }; 17 | }, [ref, handler]); 18 | } 19 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "icons/backbook-icon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "icons/backbook-icon.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "icons/backbook-icon.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/components/noAuthHeader/index.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styles from "./style.module.css"; 3 | import { Link } from "react-router-dom"; 4 | import { Logo } from "../../svg"; 5 | 6 | function NoAuthHeader() { 7 | return ( 8 |
    9 | 10 |
    11 | 12 |
    13 | 14 | 15 | 16 | 17 |
    18 | ); 19 | } 20 | 21 | export default NoAuthHeader; 22 | -------------------------------------------------------------------------------- /src/svg/menu.js: -------------------------------------------------------------------------------- 1 | function Menu() { 2 | return ( 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | } 16 | 17 | export default Menu; 18 | -------------------------------------------------------------------------------- /src/svg/homeActive.js: -------------------------------------------------------------------------------- 1 | function HomeActive({ className }) { 2 | return ( 3 | 10 | 11 | 12 | ); 13 | } 14 | 15 | export default HomeActive; 16 | -------------------------------------------------------------------------------- /src/utils/messagesPosition.js: -------------------------------------------------------------------------------- 1 | export function isSameUser(msg, user) { 2 | return msg.sender._id !== user._id; 3 | } 4 | 5 | export function isLastMsg(msg, msgs, i) { 6 | return ( 7 | msg.sender._id !== msgs[i - 1]?.sender._id && 8 | msg.sender._id === msgs[i + 1]?.sender._id 9 | ); 10 | } 11 | 12 | export function isFirstMsg(msg, msgs, i) { 13 | return ( 14 | msg.sender._id !== msgs[i + 1]?.sender._id && 15 | msg.sender._id === msgs[i - 1]?.sender._id 16 | ); 17 | } 18 | export function isSingleMsg(msg, msgs, i) { 19 | return ( 20 | msg.sender._id !== msgs[i + 1]?.sender._id && 21 | msg.sender._id !== msgs[i - 1]?.sender._id 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /src/svg/messenger.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function Messenger() { 4 | return ( 5 | 6 | 7 | 8 | ); 9 | } 10 | 11 | export default Messenger; 12 | -------------------------------------------------------------------------------- /src/hooks/useAddFCM.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | import Cookies from "js-cookie"; 4 | 5 | const AddFCM = async ({ fcm }) => { 6 | const { data } = await axios.post( 7 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/users/fcm`, 8 | { fcmToken: fcm }, 9 | { 10 | withCredentials: true, 11 | } 12 | ); 13 | return data; 14 | }; 15 | 16 | export const useAddFCM = () => { 17 | return useMutation({ 18 | mutationKey: "useAddFCM", 19 | mutationFn: AddFCM, 20 | onSuccess: (data) => { 21 | Cookies.set("fcm", JSON.stringify(data.fcmToken), { 22 | expires: 90, 23 | }); 24 | }, 25 | }); 26 | }; 27 | -------------------------------------------------------------------------------- /src/svg/notifications.js: -------------------------------------------------------------------------------- 1 | function Notifications() { 2 | return ( 3 | 4 | 5 | 6 | ); 7 | } 8 | 9 | export default Notifications; 10 | -------------------------------------------------------------------------------- /src/hooks/useOnClickOutside.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | 3 | export default function useOnClickOutside(ref, state, handler) { 4 | useEffect(() => { 5 | const listener = (event) => { 6 | if ( 7 | !ref.current || 8 | ref.current.contains(event.target) || 9 | state === false 10 | ) { 11 | return; 12 | } 13 | handler(event); 14 | }; 15 | document.addEventListener("mousedown", listener); 16 | document.addEventListener("touchstart", listener); 17 | return () => { 18 | document.removeEventListener("mousedown", listener); 19 | document.removeEventListener("touchstart", listener); 20 | }; 21 | }, [ref, handler, state]); 22 | } 23 | -------------------------------------------------------------------------------- /src/hooks/useWindowDimensions .js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | 3 | function getWindowDimensions() { 4 | const { innerWidth: width, innerHeight: height } = window; 5 | return { 6 | width, 7 | height, 8 | }; 9 | } 10 | 11 | export default function useWindowDimensions() { 12 | const [windowDimensions, setWindowDimensions] = useState( 13 | getWindowDimensions() 14 | ); 15 | 16 | useEffect(() => { 17 | function handleResize() { 18 | setWindowDimensions(getWindowDimensions()); 19 | } 20 | 21 | window.addEventListener("resize", handleResize); 22 | return () => window.removeEventListener("resize", handleResize); 23 | }, []); 24 | 25 | return windowDimensions; 26 | } 27 | -------------------------------------------------------------------------------- /src/svg/friendsActive.js: -------------------------------------------------------------------------------- 1 | function FriendsActive() { 2 | return ( 3 | 4 | 5 | 6 | ); 7 | } 8 | 9 | export default FriendsActive; 10 | -------------------------------------------------------------------------------- /src/svg/arrowRight.js: -------------------------------------------------------------------------------- 1 | function ArrowRight({ color }) { 2 | return ( 3 | 4 | 5 | 9 | 13 | 14 | 15 | ); 16 | } 17 | 18 | export default ArrowRight; 19 | -------------------------------------------------------------------------------- /src/components/posts/post/likes/ReactsPopup.module.css: -------------------------------------------------------------------------------- 1 | .popup { 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | background: var(--bg-primary); 6 | padding: 7px; 7 | border-radius: 50px; 8 | gap: 12px; 9 | border: 0.4px solid var(--divider); 10 | box-shadow: 0 0 2px 1px rgb(0 0 0 / 6%); 11 | } 12 | .react { 13 | display: flex; 14 | align-items: center; 15 | justify-content: center; 16 | background-color: white; 17 | border-radius: 100%; 18 | transform: scale(0.98); 19 | transition: transform 0.2s; 20 | } 21 | 22 | .react:hover { 23 | transform: scale(1.2) translateY(-10px); 24 | } 25 | .react img { 26 | width: 35px; 27 | height: 35px; 28 | cursor: pointer; 29 | 30 | transform: scale(1.2); 31 | } 32 | -------------------------------------------------------------------------------- /src/svg/return.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function Return({ color }) { 4 | return ( 5 | 6 | 7 | 11 | 15 | 16 | 17 | ); 18 | } 19 | 20 | export default Return; 21 | -------------------------------------------------------------------------------- /src/pages/messages/SeenStatus.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { UnSeen } from "../../svg"; 3 | import styles from "./messages.module.css"; 4 | 5 | function SeenStatus({ chat, user }) { 6 | return ( 7 | <> 8 | {chat?.latestMessage?.sender._id === user._id ? ( 9 | chat?.latestMessage?.seen === "seen" ? ( 10 | 11 | ) : ( 12 | 13 | 14 | 15 | ) 16 | ) : chat?.latestMessage?.seen === "unseen" ? ( 17 | 18 | ) : ( 19 | "" 20 | )} 21 | 22 | ); 23 | } 24 | 25 | export default SeenStatus; 26 | -------------------------------------------------------------------------------- /src/svg/newRoom.js: -------------------------------------------------------------------------------- 1 | function NewRoom({ color }) { 2 | return ( 3 | 4 | 9 | 10 | ); 11 | } 12 | 13 | export default NewRoom; 14 | -------------------------------------------------------------------------------- /src/components/messages/chatInfo/chatInfo.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useState } from "react"; 3 | import { ArrowDown1 } from "../../../svg"; 4 | import styles from "./chatInfo.module.css"; 5 | 6 | function ChatInfo({ title, children }) { 7 | const [show, setShow] = useState(false); 8 | return ( 9 | <> 10 |
    { 13 | setShow((prev) => !prev); 14 | }} 15 | > 16 | {title} 17 |
    18 | 19 |
    20 |
    21 | {show &&
    {children}
    } 22 | 23 | ); 24 | } 25 | 26 | export default ChatInfo; 27 | -------------------------------------------------------------------------------- /src/pages/profile/ProfileMenu.jsx: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | import { Dots } from "../../svg"; 3 | import classes from "./style.module.css"; 4 | 5 | export default function ProfileMenu() { 6 | return ( 7 |
    8 |
    9 | 10 | Posts 11 | 12 | 13 | About 14 | 15 | 16 | Friends 17 | 18 | 19 | Photos 20 | 21 |
    22 |
    23 | 24 |
    25 |
    26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /src/hooks/useReaction.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | import { socket } from "../routes/IsLoggedIn"; 4 | 5 | const AddReact = async ({ post, type }) => { 6 | const { data } = await axios.put( 7 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/posts/${post}/reacts`, 8 | { type }, 9 | { 10 | withCredentials: true, 11 | } 12 | ); 13 | return data; 14 | }; 15 | 16 | export const useReaction = () => { 17 | return useMutation({ 18 | mutationKey: "useReaction", 19 | mutationFn: AddReact, 20 | onSuccess: (data) => { 21 | const newNotification = data?.data?.newNotification; 22 | if (newNotification) { 23 | socket.emit("notification", { notification: newNotification }); 24 | } 25 | }, 26 | }); 27 | }; 28 | -------------------------------------------------------------------------------- /src/pages/login/index.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import LoginForm from "../../components/login/LoginForm"; 3 | import LoginFooter from "../../components/login/LoginFooter"; 4 | import styles from "./style.module.css"; 5 | import SignupForm from "../../components/login/SignupForm"; 6 | 7 | function Login() { 8 | const [renderSignUp, setRenderSignUp] = useState(false); 9 | return ( 10 |
    11 |
    12 | 13 | {renderSignUp && ( 14 | 18 | )} 19 | 20 |
    21 |
    22 | ); 23 | } 24 | 25 | export default Login; 26 | -------------------------------------------------------------------------------- /src/hooks/useCommentLike.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | import { socket } from "../routes/IsLoggedIn"; 4 | 5 | const AddCommentLike = async ({ comment }) => { 6 | const { data } = await axios.put( 7 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/posts/comments/${comment}/like`, 8 | {}, 9 | { 10 | withCredentials: true, 11 | } 12 | ); 13 | return data; 14 | }; 15 | 16 | export const useCommentLike = (comment) => { 17 | return useMutation({ 18 | mutationKey: ["useCommentLike", comment], 19 | mutationFn: AddCommentLike, 20 | onSuccess: (data) => { 21 | const newNotification = data?.data?.newNotification; 22 | if (newNotification) { 23 | socket.emit("notification", { notification: newNotification }); 24 | } 25 | }, 26 | }); 27 | }; 28 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import * as ReactDOMClient from "react-dom/client"; 3 | import "./index.css"; 4 | import "./styles/dark.css"; 5 | import "react-loading-skeleton/dist/skeleton.css"; 6 | 7 | import "./styles/icons/icons.css"; 8 | import App from "./App"; 9 | import { BrowserRouter } from "react-router-dom"; 10 | import { Provider } from "react-redux"; 11 | import { store } from "./app/store"; 12 | import axios from "axios"; 13 | import Cookies from "js-cookie"; 14 | 15 | const token = Cookies.get("token") ? JSON.parse(Cookies.get("token")) : null; 16 | 17 | if (token) axios.defaults.headers.common["Authorization"] = `Bearer ${token}`; 18 | 19 | const root = ReactDOMClient.createRoot(document.getElementById("backbook")); 20 | root.render( 21 | 22 | 23 | 24 | 25 | 26 | ); 27 | -------------------------------------------------------------------------------- /src/svg/info.js: -------------------------------------------------------------------------------- 1 | function Info({ color = "#0096ff" }) { 2 | return ( 3 | 11 | 12 | 17 | 18 | 19 | ); 20 | } 21 | 22 | export default Info; 23 | -------------------------------------------------------------------------------- /src/utils/dataURItoBlob.js: -------------------------------------------------------------------------------- 1 | export default function dataURItoBlob(dataURI) { 2 | // convert base64 to raw binary data held in a string 3 | // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this 4 | var byteString = atob(dataURI.split(",")[1]); 5 | 6 | // separate out the mime component 7 | var mimeString = dataURI.split(",")[0].split(":")[1].split(";")[0]; 8 | 9 | // write the bytes of the string to an ArrayBuffer 10 | var ab = new ArrayBuffer(byteString.length); 11 | 12 | // create a view into the buffer 13 | var ia = new Uint8Array(ab); 14 | 15 | // set the bytes of the buffer to the correct values 16 | for (var i = 0; i < byteString.length; i++) { 17 | ia[i] = byteString.charCodeAt(i); 18 | } 19 | 20 | // write the ArrayBuffer to a blob, and you're done 21 | var blob = new Blob([ab], { type: mimeString }); 22 | return blob; 23 | } 24 | -------------------------------------------------------------------------------- /src/svg/home.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | function Home({ color, className }) { 4 | return ( 5 | 12 | 13 | 14 | ); 15 | } 16 | 17 | export default Home; 18 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 15 | 16 | 17 | 21 | Backbook 22 | 23 | 24 |
    25 | 26 | 27 | -------------------------------------------------------------------------------- /src/components/header/userMenu/HelpSupport.jsx: -------------------------------------------------------------------------------- 1 | import styles from "./UserMenu.module.css"; 2 | import { user_menu2 } from "../../..//data/allMenu"; 3 | 4 | export default function HelpSupport({ setVisible }) { 5 | return ( 6 |
    7 |
    8 |
    { 11 | setVisible(0); 12 | }} 13 | > 14 | 15 |
    16 | Settings & privacy 17 |
    18 | {user_menu2.map(({ name, icon }) => ( 19 |
    20 |
    21 | 22 |
    23 | {name} 24 |
    25 | ))} 26 |
    27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /src/svg/like.js: -------------------------------------------------------------------------------- 1 | function Like({ color = "#0096ff", height = "20", width = "20", style }) { 2 | return ( 3 | 14 | ); 15 | } 16 | 17 | export default Like; 18 | -------------------------------------------------------------------------------- /src/components/header/userMenu/SettingsPrivacy.jsx: -------------------------------------------------------------------------------- 1 | import styles from "./UserMenu.module.css"; 2 | import { user_menu1 } from "../../..//data/allMenu"; 3 | 4 | export default function SettingsPrivacy({ setVisible }) { 5 | return ( 6 |
    7 |
    8 |
    { 11 | setVisible(0); 12 | }} 13 | > 14 | 15 |
    16 | Settings & privacy 17 |
    18 | {user_menu1.map(({ name, icon }, i) => ( 19 |
    20 |
    21 | 22 |
    23 | {name} 24 |
    25 | ))} 26 |
    27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.enabled": true, 3 | "workbench.colorCustomizations": { 4 | "activityBar.activeBackground": "#93e6fc", 5 | "activityBar.background": "#93e6fc", 6 | "activityBar.foreground": "#15202b", 7 | "activityBar.inactiveForeground": "#15202b99", 8 | "activityBarBadge.background": "#fa45d4", 9 | "activityBarBadge.foreground": "#15202b", 10 | "commandCenter.border": "#15202b99", 11 | "sash.hoverBorder": "#93e6fc", 12 | "statusBar.background": "#61dafb", 13 | "statusBar.foreground": "#15202b", 14 | "statusBarItem.hoverBackground": "#2fcefa", 15 | "statusBarItem.remoteBackground": "#61dafb", 16 | "statusBarItem.remoteForeground": "#15202b", 17 | "titleBar.activeBackground": "#61dafb", 18 | "titleBar.activeForeground": "#15202b", 19 | "titleBar.inactiveBackground": "#61dafb99", 20 | "titleBar.inactiveForeground": "#15202b99" 21 | }, 22 | "peacock.color": "#61dafb" 23 | } 24 | -------------------------------------------------------------------------------- /src/components/UI/Error/ErrorPage.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import classes from "./ErrorPage.module.css"; 3 | import e404Animation from "../../UI/Lottie/404.json"; 4 | import Lottie from "react-lottie-player"; 5 | import { useNavigate } from "react-router-dom"; 6 | 7 | function ErrorPage({ error }) { 8 | const navigate = useNavigate(); 9 | 10 | return ( 11 |
    12 | 22 |

    Something Went Wrong

    23 |
    { 27 | navigate("/"); 28 | }} 29 | > 30 | Go to home 31 |
    32 |
    33 | ); 34 | } 35 | 36 | export default ErrorPage; 37 | -------------------------------------------------------------------------------- /public/firebase-messaging-sw.js: -------------------------------------------------------------------------------- 1 | importScripts("https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"); 2 | importScripts( 3 | "https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js" 4 | ); 5 | 6 | const firebaseConfig = { 7 | apiKey: "AIzaSyD8bk57MfPgPmzRQU6fA2x89AZ4ldQlS80", 8 | projectId: "backbook-370316", 9 | messagingSenderId: "398150721140", 10 | appId: "1:398150721140:web:d93f0193496929a5037b21", 11 | }; 12 | 13 | firebase.initializeApp(firebaseConfig); 14 | const messaging = firebase.messaging(); 15 | 16 | messaging.onBackgroundMessage((payload) => { 17 | console.log( 18 | "[firebase-messaging-sw.js] Received background message ", 19 | payload 20 | ); 21 | const notificationTitle = payload.notification.title; 22 | const notificationOptions = { 23 | body: payload.notification.body, 24 | icon: payload.notification.image, 25 | }; 26 | 27 | // self.registration.showNotification(notificationTitle, notificationOptions); 28 | }); 29 | -------------------------------------------------------------------------------- /src/components/login/LoginFooter.module.css: -------------------------------------------------------------------------------- 1 | .footer { 2 | background: var(--bg-primary); 3 | padding: 1.5rem; 4 | } 5 | .warp { 6 | color: var(--color-secondary); 7 | display: flex; 8 | flex-wrap: wrap; 9 | font-size: 13px; 10 | gap: 3px 10px; 11 | margin: 0 auto; 12 | max-width: 350px; 13 | } 14 | .warp a { 15 | align-items: center; 16 | display: flex; 17 | } 18 | .warp a:hover { 19 | text-decoration: underline; 20 | } 21 | .footer div:nth-child(2) { 22 | margin: 1rem auto; 23 | max-width: 350px; 24 | } 25 | .square { 26 | align-items: center; 27 | background: var(--bg-secondary); 28 | border: 1px solid var(--bg-third); 29 | display: flex; 30 | height: 19px; 31 | justify-content: center; 32 | width: 30px; 33 | } 34 | @media (min-width: 539px) { 35 | .warp, 36 | .footer div:nth-child(2) { 37 | max-width: 520px; 38 | } 39 | } 40 | @media (min-width: 850px) { 41 | .warp, 42 | .footer div:nth-child(2) { 43 | max-width: 900px; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/hooks/useComment.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | import { socket } from "../routes/IsLoggedIn"; 4 | 5 | const AddComment = async ({ form, post, type }) => { 6 | const commentUrl = `${process.env.REACT_APP_BACKEND_URL}/api/v1/posts/AddComment/${post}`; 7 | const replyUrl = `${process.env.REACT_APP_BACKEND_URL}/api/v1/posts/comments/${post}/reply`; 8 | 9 | const { data } = await axios.post( 10 | type === "reply" ? replyUrl : commentUrl, 11 | form, 12 | { 13 | withCredentials: true, 14 | } 15 | ); 16 | return data; 17 | }; 18 | 19 | export const useComment = () => { 20 | return useMutation({ 21 | mutationKey: "useComment", 22 | mutationFn: AddComment, 23 | onSuccess: (data) => { 24 | const newNotification = data?.data?.newNotification; 25 | if (newNotification) { 26 | socket.emit("notification", { notification: newNotification }); 27 | } 28 | }, 29 | }); 30 | }; 31 | -------------------------------------------------------------------------------- /src/hooks/useCreateChatGroup.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | import { queryClient } from "../App"; 4 | 5 | const CreateChatGroup = async ({ users, chatName }) => { 6 | const { data } = await axios.post( 7 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/chats/create/group`, 8 | { users, chatName }, 9 | { 10 | withCredentials: true, 11 | } 12 | ); 13 | return data; 14 | }; 15 | 16 | export const useCreateChatGroup = () => { 17 | return useMutation({ 18 | mutationKey: "useCreateChatGroup", 19 | mutationFn: CreateChatGroup, 20 | onSuccess: (data) => { 21 | const newChat = data?.data?.chat; 22 | 23 | queryClient.setQueryData(["getChats"], (oldData) => { 24 | if (!oldData) return oldData; 25 | let newData = oldData; 26 | newData.data.chats = [newChat, ...newData.data.chats]; 27 | return { 28 | ...oldData, 29 | newData, 30 | }; 31 | }); 32 | }, 33 | }); 34 | }; 35 | -------------------------------------------------------------------------------- /src/components/profile/cover/OldCovers.module.css: -------------------------------------------------------------------------------- 1 | .wrap { 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | } 6 | .card { 7 | width: 100%; 8 | max-width: 700px; 9 | min-height: 70vh; 10 | padding: 0; 11 | margin: 8px; 12 | } 13 | .header { 14 | display: flex; 15 | align-items: center; 16 | justify-content: center; 17 | padding: 16px 0; 18 | border-bottom: 1px solid var(--divider); 19 | font-size: 20px; 20 | font-weight: 700; 21 | position: relative; 22 | } 23 | .header div { 24 | position: absolute; 25 | right: 0; 26 | } 27 | .content { 28 | padding: 16px; 29 | display: flex; 30 | flex-direction: column; 31 | gap: 16px; 32 | } 33 | 34 | .old_photos { 35 | display: flex; 36 | flex-wrap: wrap; 37 | gap: 5px; 38 | justify-content: center; 39 | margin: 10px 0; 40 | max-height: 150px; 41 | overflow: auto; 42 | } 43 | .old_photos img { 44 | width: 100px; 45 | height: 100px; 46 | object-fit: cover; 47 | border-radius: 10px; 48 | cursor: pointer; 49 | } 50 | -------------------------------------------------------------------------------- /src/svg/send.js: -------------------------------------------------------------------------------- 1 | function Send({ color = "#0096ff" }) { 2 | return ( 3 | 4 | 8 | 9 | ); 10 | } 11 | 12 | export default Send; 13 | -------------------------------------------------------------------------------- /src/components/FormLoader/style.module.css: -------------------------------------------------------------------------------- 1 | .wrap { 2 | position: relative; 3 | } 4 | .loader { 5 | position: absolute; 6 | left: 50%; 7 | top: 50%; 8 | -webkit-transform: translate(-50%, -50%); 9 | transform: translate(-50%, -50%); 10 | z-index: 10; 11 | } 12 | .content { 13 | filter: blur(2px); 14 | } 15 | .loaderback, 16 | .isError { 17 | background: #ffffff78; 18 | width: 100%; 19 | height: 100%; 20 | position: absolute; 21 | top: 0; 22 | left: 0; 23 | z-index: 1; 24 | } 25 | .isError { 26 | background: #ffffffb7; 27 | display: flex; 28 | justify-content: center; 29 | flex-direction: column; 30 | align-items: center; 31 | gap: 20px; 32 | color: var(--red-color); 33 | padding: 30px; 34 | text-align: center; 35 | } 36 | .isError button { 37 | width: auto; 38 | font-weight: unset; 39 | font-size: small; 40 | } 41 | 42 | :global(.dark) .isError { 43 | background: rgba(19, 19, 19, 0.59); 44 | } 45 | :global(.dark) .loaderback, 46 | .isError { 47 | background: rgba(25, 25, 25, 0.594); 48 | } 49 | -------------------------------------------------------------------------------- /src/components/UI/Notification/Notification.module.css: -------------------------------------------------------------------------------- 1 | .main { 2 | display: flex; 3 | gap: 6px; 4 | flex-direction: column; 5 | background: var(--bg-primary); 6 | padding: 15px; 7 | border-radius: 10px; 8 | box-shadow: 0px 4px 7px var(--shadow-2); 9 | } 10 | .header { 11 | display: flex; 12 | justify-content: space-between; 13 | font-size: 14px; 14 | font-weight: 600; 15 | } 16 | .content { 17 | display: flex; 18 | align-items: center; 19 | justify-content: space-between; 20 | gap: 15px; 21 | font-size: 14px; 22 | font-weight: 400; 23 | cursor: pointer; 24 | } 25 | 26 | .content_2 { 27 | display: flex; 28 | flex-direction: column; 29 | } 30 | .img { 31 | position: relative; 32 | } 33 | .img img:nth-child(1) { 34 | width: 56px; 35 | height: 56px; 36 | border-radius: 100%; 37 | } 38 | .type { 39 | width: 28px; 40 | height: 28px; 41 | position: absolute; 42 | right: -5px; 43 | bottom: 0; 44 | } 45 | 46 | .time time { 47 | font-size: 12px; 48 | font-weight: 600; 49 | color: #0096ff; 50 | } 51 | -------------------------------------------------------------------------------- /public/reacts/love.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/slices/soketSlice.js: -------------------------------------------------------------------------------- 1 | import { createSlice } from "@reduxjs/toolkit"; 2 | 3 | // type = ['normal','image','background'] 4 | 5 | const initialValue = { 6 | onlineUsers: [], 7 | selectedChat: null, 8 | }; 9 | export const createSoketSlice = createSlice({ 10 | name: "soketSlice", 11 | initialState: initialValue, 12 | 13 | reducers: { 14 | setOnlineUsers: (state, action) => { 15 | const { type, info } = action.payload; 16 | if ( 17 | type === "add" && 18 | !state.onlineUsers.find((u) => u?.id === info?.id) 19 | ) { 20 | state.onlineUsers = [...state.onlineUsers, info]; 21 | } else if (type === "remove") { 22 | state.onlineUsers = state.onlineUsers.filter((u) => u?.id !== info?.id); 23 | } else if (type === "connect") { 24 | state.onlineUsers = info; 25 | } 26 | }, 27 | setSelectedChat: (state, action) => { 28 | state.selectedChat = action.payload; 29 | }, 30 | }, 31 | }); 32 | export const { setOnlineUsers, setSelectedChat } = createSoketSlice.actions; 33 | 34 | export default createSoketSlice.reducer; 35 | -------------------------------------------------------------------------------- /src/components/home/stories/Stories.jsx: -------------------------------------------------------------------------------- 1 | import { Plus } from "../../../svg"; 2 | import styles from "./Stories.module.css"; 3 | import { stories } from "../../../data/home"; 4 | import Story from "./Story"; 5 | import Card from "../../UI/Card/Card"; 6 | import { ScrollContainer } from "react-indiana-drag-scroll"; 7 | 8 | function Stories() { 9 | return ( 10 | 11 | 12 |
    13 |
    14 | 19 |
    20 | 21 |
    22 |
    Create Story
    23 |
    24 | {stories.map((story, i) => ( 25 | 26 | ))} 27 |
    28 |
    29 |
    30 | ); 31 | } 32 | 33 | export default Stories; 34 | -------------------------------------------------------------------------------- /src/routes/router.jsx: -------------------------------------------------------------------------------- 1 | import { useSelector } from "react-redux"; 2 | import { Route, Routes } from "react-router-dom"; 3 | import ErrorPage from "../components/UI/Error/ErrorPage"; 4 | import IsLoggedIn from "./IsLoggedIn"; 5 | import NotLoggedIn from "./NotLoggedIn"; 6 | import pagesData from "./pagesData"; 7 | 8 | const Router = () => { 9 | const { soketSlice, user } = useSelector((state) => ({ ...state })); 10 | 11 | const pageRoutes = pagesData 12 | .filter(({ priv }) => !priv) 13 | .map(({ path, title, element }) => { 14 | return ; 15 | }); 16 | 17 | const pageRoutesPriv = pagesData 18 | .filter(({ priv }) => priv) 19 | .map(({ path, title, element }) => { 20 | return ; 21 | }); 22 | 23 | return ( 24 | 25 | }>{pageRoutesPriv} 26 | }> {pageRoutes} 27 | } /> 28 | 29 | ); 30 | }; 31 | 32 | export default Router; 33 | -------------------------------------------------------------------------------- /src/svg/liveVideo.js: -------------------------------------------------------------------------------- 1 | function LiveVideo({ color }) { 2 | return ( 3 | 4 | 5 | 9 | 13 | 14 | 15 | ); 16 | } 17 | 18 | export default LiveVideo; 19 | -------------------------------------------------------------------------------- /src/svg/friends.js: -------------------------------------------------------------------------------- 1 | function Friends({ color }) { 2 | return ( 3 | 4 | 5 | 6 | ); 7 | } 8 | 9 | export default Friends; 10 | -------------------------------------------------------------------------------- /src/components/skeleton/PostSkeleton.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import classes from "../posts/post/Post.module.css"; 3 | import Card from "../UI/Card/Card"; 4 | import Skeleton from "react-loading-skeleton"; 5 | 6 | function PostSkeleton() { 7 | return ( 8 | 9 |
    10 |
    11 | 17 |
    18 |
    19 | 26 | 27 |
    28 |
    29 |
    30 | 31 | 32 |
    33 |
    34 | ); 35 | } 36 | 37 | export default PostSkeleton; 38 | -------------------------------------------------------------------------------- /src/hooks/useSeenMessage.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | import { socket } from "../routes/IsLoggedIn"; 4 | import { useDispatch } from "react-redux"; 5 | import { updateNStats } from "../app/slices/userSlice"; 6 | import { updateSeenMessages } from "../utils/rqUpdate"; 7 | 8 | const SeenMessage = async ({ messageId }) => { 9 | const { data } = await axios.put( 10 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/messages/${messageId}/seen`, 11 | {}, 12 | { 13 | withCredentials: true, 14 | } 15 | ); 16 | return data; 17 | }; 18 | 19 | export const useSeenMessage = (chat) => { 20 | const dispatch = useDispatch(); 21 | 22 | return useMutation({ 23 | mutationKey: "useSeenMessage", 24 | mutationFn: SeenMessage, 25 | onSuccess: (data) => { 26 | const newMessage = data?.data?.message; 27 | const unseenMessages = data?.data?.unseenMessages; 28 | 29 | updateSeenMessages(newMessage, chat); 30 | 31 | dispatch( 32 | updateNStats({ 33 | unseenMessages, 34 | }) 35 | ); 36 | 37 | socket.emit("seen", { message: newMessage, chat }); 38 | }, 39 | }); 40 | }; 41 | -------------------------------------------------------------------------------- /src/components/posts/CreatePostPopup/AddToYourPost.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Dots, Feeling, Photo } from "../../../svg"; 3 | import classes from "./CreatePostPopup.module.css"; 4 | import { useDispatch } from "react-redux"; 5 | import * as createPostSlice from "../../../app/slices/createPostSlice"; 6 | 7 | function AddToYourPost() { 8 | const dispatch = useDispatch(); 9 | 10 | return ( 11 |
    12 |
    Add to your post
    13 |
    14 |
    dispatch(createPostSlice.type("image"))} 17 | > 18 | 19 |
    20 |
    21 | 22 |
    23 |
    24 | 25 |
    26 |
    27 | 28 |
    29 |
    30 | 31 |
    32 |
    33 |
    34 | ); 35 | } 36 | 37 | export default AddToYourPost; 38 | -------------------------------------------------------------------------------- /src/hooks/useRealationship.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | import { socket } from "../routes/IsLoggedIn"; 4 | import { queryClient } from "./../App"; 5 | 6 | const AddFriend = async ({ id, type }) => { 7 | const { data } = await axios.put( 8 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/friends/${type}/${id}`, 9 | {}, 10 | { 11 | withCredentials: true, 12 | } 13 | ); 14 | return data; 15 | }; 16 | 17 | export const useRelationship = (usernameID) => { 18 | return useMutation({ 19 | mutationKey: "useRelationship", 20 | mutationFn: AddFriend, 21 | onSuccess: (data) => { 22 | const newNotification = data?.data?.newNotification; 23 | 24 | queryClient.setQueryData(["getProfile", usernameID], (oldData) => { 25 | if (!oldData) return oldData; 26 | 27 | let newData = oldData; 28 | newData.data.friendship = data.data.friendship; 29 | return oldData 30 | ? { 31 | ...oldData, 32 | newData, 33 | } 34 | : oldData; 35 | }); 36 | if (newNotification) { 37 | socket.emit("notification", { notification: newNotification }); 38 | } 39 | }, 40 | }); 41 | }; 42 | -------------------------------------------------------------------------------- /src/components/home/right/HomeRight.jsx: -------------------------------------------------------------------------------- 1 | import { Dots, NewRoom, Search } from "../../../svg"; 2 | import Contact from "./Contact"; 3 | import styles from "./HomeRight.module.css"; 4 | 5 | function HomeRight({ user }) { 6 | const color = "#65676b"; 7 | 8 | return ( 9 |
    10 |
    Sponsored
    11 |
    12 |
    13 |
    14 |
    Contacts
    15 |
    16 |
    17 | 18 |
    19 |
    20 | 21 |
    22 |
    23 | 24 |
    25 |
    26 |
    27 |
    28 | 29 |
    30 |
    31 |
    32 | ); 33 | } 34 | 35 | export default HomeRight; 36 | -------------------------------------------------------------------------------- /src/components/header/notificationMenu/NotificationMenu.module.css: -------------------------------------------------------------------------------- 1 | .menu { 2 | padding: 0 0.3rem; 3 | position: absolute; 4 | top: 100%; 5 | right: 0; 6 | width: calc(100vw - 20px); 7 | margin: 10px; 8 | max-width: 400px; 9 | border-radius: 10px; 10 | background: var(--bg-primary); 11 | box-shadow: 2px 2px 2px var(--shadow-1); 12 | user-select: none; 13 | padding: 10px; 14 | max-height: 600px; 15 | overflow: auto; 16 | } 17 | .menu h2 { 18 | padding: 10px; 19 | } 20 | 21 | .notification { 22 | padding: 10px; 23 | border-radius: 10px; 24 | } 25 | 26 | .content { 27 | display: flex; 28 | align-items: center; 29 | justify-content: flex-start; 30 | gap: 15px; 31 | font-size: 14px; 32 | font-weight: 400; 33 | cursor: pointer; 34 | } 35 | 36 | .content_2 { 37 | display: flex; 38 | flex-direction: column; 39 | flex: 1; 40 | } 41 | .img { 42 | position: relative; 43 | } 44 | .img img:nth-child(1) { 45 | width: 56px; 46 | height: 56px; 47 | border-radius: 100%; 48 | } 49 | .type { 50 | width: 28px; 51 | height: 28px; 52 | position: absolute; 53 | right: -5px; 54 | bottom: 0; 55 | } 56 | 57 | .time time { 58 | font-size: 12px; 59 | font-weight: 600; 60 | color: #0096ff; 61 | } 62 | 63 | :global(.dark) .menu i { 64 | filter: invert(100%); 65 | } 66 | -------------------------------------------------------------------------------- /src/hooks/useSendMessage.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | import { toast } from "react-hot-toast"; 4 | import { useSelector } from "react-redux"; 5 | import { socket } from "../routes/IsLoggedIn"; 6 | import { updateMessages } from "../utils/rqUpdate"; 7 | 8 | export const useSendMessage = (chat) => { 9 | const user = useSelector((state) => ({ ...state.user.userinfo })); 10 | 11 | return useMutation({ 12 | mutationKey: "useSendMessage", 13 | mutationFn: async ({ content, chatId, type }) => { 14 | updateMessages({ 15 | _id: Math.floor(Math.random() * 100000000000 + 1), 16 | content, 17 | chat: chatId, 18 | type, 19 | sender: user, 20 | }); 21 | 22 | const { data } = await axios.put( 23 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/messages/${chatId}/send`, 24 | { content, type }, 25 | { 26 | withCredentials: true, 27 | } 28 | ); 29 | return data; 30 | }, 31 | onError: (error) => { 32 | toast.error(error?.response?.data?.message); 33 | }, 34 | onSuccess: (data) => { 35 | const newMessage = data?.data?.message; 36 | 37 | socket.emit("new_message", { message: newMessage, chat }); 38 | }, 39 | }); 40 | }; 41 | -------------------------------------------------------------------------------- /src/hooks/useRenameGroup.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | import { socket } from "../routes/IsLoggedIn"; 4 | import { updateChatName } from "../utils/rqUpdate"; 5 | import { useSendMessage } from "./useSendMessage"; 6 | 7 | const RenameGroup = async ({ chatId, chatName }) => { 8 | const { data } = await axios.put( 9 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/chats/group/rename`, 10 | { chatId, chatName }, 11 | { 12 | withCredentials: true, 13 | } 14 | ); 15 | return data; 16 | }; 17 | 18 | export const useRenameGroup = (chat) => { 19 | const { mutate: sendMessage } = useSendMessage(chat); 20 | 21 | return useMutation({ 22 | mutationKey: "useRenameGroup", 23 | mutationFn: RenameGroup, 24 | onSuccess: (data) => { 25 | const newchatName = data?.data?.chatName; 26 | const userId = data?.data?.user; 27 | 28 | updateChatName(newchatName, chat._id); 29 | 30 | sendMessage({ 31 | content: `Group name changed to ${newchatName}`, 32 | type: "info", 33 | chatId: chat._id, 34 | }); 35 | 36 | socket.emit("customize_chat", { 37 | userId, 38 | type: "name", 39 | content: newchatName, 40 | chat, 41 | }); 42 | }, 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /src/hooks/useSeenNotification.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | import { queryClient } from "../App"; 4 | 5 | const SeenNotification = async ({ nid }) => { 6 | const { data } = await axios.put( 7 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/users/notifications/${nid}/seen`, 8 | {}, 9 | { 10 | withCredentials: true, 11 | } 12 | ); 13 | return data; 14 | }; 15 | 16 | export const useSeenNotification = () => { 17 | return useMutation({ 18 | mutationKey: "useSeenNotification", 19 | mutationFn: SeenNotification, 20 | onSuccess: (data) => { 21 | const newNotification = data?.data?.notification; 22 | 23 | queryClient.setQueryData(["getNotifications"], (oldData) => { 24 | if (!oldData) return oldData; 25 | let newData = oldData; 26 | newData.data.notifications = newData.data.notifications.map( 27 | (notification) => { 28 | if (notification._id === newNotification._id) { 29 | return { 30 | ...notification, 31 | seen: "seen", 32 | }; 33 | } 34 | return notification; 35 | } 36 | ); 37 | return { 38 | ...oldData, 39 | newData, 40 | }; 41 | }); 42 | }, 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /src/svg/smile.js: -------------------------------------------------------------------------------- 1 | function Smile({ color = "#0096ff" }) { 2 | return ( 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | ); 18 | } 19 | 20 | export default Smile; 21 | -------------------------------------------------------------------------------- /src/svg/feeling.js: -------------------------------------------------------------------------------- 1 | function Feeling({ color }) { 2 | return ( 3 | 4 | 5 | 9 | 14 | 18 | 19 | 20 | ); 21 | } 22 | 23 | export default Feeling; 24 | -------------------------------------------------------------------------------- /src/hooks/useAddMember.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | import { queryClient } from "../App"; 4 | import { useSendMessage } from "./useSendMessage"; 5 | 6 | const AddMember = async ({ chatId, userId }) => { 7 | const { data } = await axios.put( 8 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/chats/group/add`, 9 | { chatId, userId }, 10 | { 11 | withCredentials: true, 12 | } 13 | ); 14 | return data; 15 | }; 16 | 17 | export const useAddMember = (chat) => { 18 | const { mutate: sendMessage } = useSendMessage(chat); 19 | 20 | return useMutation({ 21 | mutationKey: "useAddMember", 22 | mutationFn: AddMember, 23 | onSuccess: (data) => { 24 | const user = data?.data?.user; 25 | 26 | queryClient.setQueryData(["getMessages", chat._id], (oldData) => { 27 | if (!oldData) return oldData; 28 | let newData = oldData; 29 | newData.pages[0].data.chat.users = [ 30 | user, 31 | ...newData.pages[0].data.chat.users, 32 | ]; 33 | 34 | return { 35 | ...oldData, 36 | newData, 37 | }; 38 | }); 39 | 40 | sendMessage({ 41 | content: `${user.first_name} ${user.last_name} Added to this group`, 42 | type: "info", 43 | chatId: chat._id, 44 | }); 45 | }, 46 | }); 47 | }; 48 | -------------------------------------------------------------------------------- /src/pages/home/style.module.css: -------------------------------------------------------------------------------- 1 | .home { 2 | min-height: 100vh; 3 | background: var(--bg-secondary); 4 | display: grid; 5 | grid-template-columns: repeat(3, 1fr); 6 | } 7 | 8 | .home_middle { 9 | margin-top: 75px; 10 | position: absolute; 11 | left: 50%; 12 | transform: translateX(-50%); 13 | max-width: 590px; 14 | } 15 | .posts { 16 | margin-top: 10px; 17 | display: flex; 18 | flex-direction: column; 19 | gap: 10px; 20 | margin-bottom: 20px; 21 | } 22 | 23 | @media (max-width: 1175px) { 24 | .home_middle { 25 | margin-left: 5%; 26 | } 27 | .ActiveAccount { 28 | width: 84%; 29 | } 30 | } 31 | @media (max-width: 1030px) { 32 | .home_middle { 33 | position: relative; 34 | margin-left: 55px; 35 | } 36 | .ActiveAccount { 37 | width: 100%; 38 | } 39 | } 40 | @media (max-width: 960px) { 41 | .home_middle { 42 | margin-left: 10%; 43 | } 44 | .ActiveAccount { 45 | width: 93%; 46 | } 47 | } 48 | 49 | @media (max-width: 885px) { 50 | .ActiveAccount { 51 | width: 110%; 52 | } 53 | } 54 | 55 | @media (max-width: 620px) { 56 | .home_middle { 57 | position: absolute; 58 | margin-left: 0; 59 | width: 100%; 60 | padding: 6px; 61 | } 62 | .ActiveAccount { 63 | width: 100%; 64 | } 65 | } 66 | @media (max-width: 400px) { 67 | .home_middle { 68 | width: 100%; 69 | margin: 56px auto; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/svg/photo.js: -------------------------------------------------------------------------------- 1 | function Photo({ color = "#0096ff" }) { 2 | return ( 3 | 4 | 5 | 9 | 14 | 15 | 16 | ); 17 | } 18 | 19 | export default Photo; 20 | -------------------------------------------------------------------------------- /src/pages/post/PostPage.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import classes from "./style.module.css"; 3 | import { useParams } from "react-router-dom"; 4 | import axios from "axios"; 5 | import { useQuery } from "@tanstack/react-query"; 6 | import Post from "../../components/posts/post"; 7 | import PostSkeleton from "../../components/skeleton/PostSkeleton"; 8 | import { useNavigate } from "react-router-dom"; 9 | 10 | function PostPage() { 11 | const navigate = useNavigate(); 12 | 13 | const { post } = useParams(); 14 | const { isLoading, isError, data, isFetching, isSuccess } = useQuery({ 15 | queryKey: ["getPost", post], 16 | queryFn: async () => { 17 | const { data } = await axios.get( 18 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/posts/${post}`, 19 | { 20 | withCredentials: true, 21 | } 22 | ); 23 | return data; 24 | }, 25 | refetchOnWindowFocus: false, 26 | }); 27 | 28 | const postsSkelton = isLoading || isFetching; 29 | 30 | useEffect(() => { 31 | if (isError) { 32 | navigate("/404"); 33 | } 34 | }, [isError]); 35 | 36 | return ( 37 |
    38 |
    39 | {postsSkelton && } 40 | {isSuccess && !isLoading && } 41 |
    42 |
    43 | ); 44 | } 45 | 46 | export default PostPage; 47 | -------------------------------------------------------------------------------- /src/components/home/SendVerification/SendVerification.module.css: -------------------------------------------------------------------------------- 1 | .ActiveAccount { 2 | width: 100%; 3 | margin: 5px 0; 4 | display: flex; 5 | flex-direction: column; 6 | font-size: smaller; 7 | } 8 | .done { 9 | width: 100%; 10 | margin: 5px 0; 11 | display: flex; 12 | flex-direction: row; 13 | font-size: smaller; 14 | align-items: center; 15 | justify-content: center; 16 | gap: 6px; 17 | } 18 | .done div:nth-child(2) { 19 | margin: 0 !important; 20 | } 21 | 22 | .ActiveAccount span { 23 | color: var(--color-secondary); 24 | } 25 | .ActiveAccount a { 26 | color: var(--blue-color); 27 | cursor: pointer; 28 | width: fit-content; 29 | } 30 | .ActiveAccount a:hover { 31 | text-decoration: underline; 32 | } 33 | .link { 34 | color: var(--blue-color); 35 | cursor: pointer; 36 | width: fit-content; 37 | } 38 | .link:hover { 39 | text-decoration: underline; 40 | } 41 | @media (max-width: 1175px) { 42 | .ActiveAccount, 43 | .done { 44 | width: 84%; 45 | } 46 | } 47 | @media (max-width: 1030px) { 48 | .ActiveAccount, 49 | .done { 50 | width: 100%; 51 | } 52 | } 53 | @media (max-width: 960px) { 54 | .ActiveAccount, 55 | .done { 56 | width: 93%; 57 | } 58 | } 59 | 60 | @media (max-width: 885px) { 61 | .ActiveAccount, 62 | .done { 63 | width: 100%; 64 | } 65 | } 66 | 67 | @media (max-width: 620px) { 68 | .ActiveAccount, 69 | .done { 70 | width: 100%; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/hooks/useCreatePost.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | import { queryClient } from "./../App"; 4 | 5 | const CreatePost = async ({ data, type }) => { 6 | const reqdata = axios.post( 7 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/posts/createPost${ 8 | type === "image" ? "/images" : "" 9 | }`, 10 | data, 11 | { 12 | withCredentials: true, 13 | } 14 | ); 15 | return reqdata; 16 | }; 17 | 18 | export const useCreatePost = (usernameID) => { 19 | return useMutation({ 20 | mutationKey: "useCreatePost", 21 | mutationFn: CreatePost, 22 | onSuccess: (data) => { 23 | queryClient.setQueryData(["getProfilePosts", usernameID], (oldData) => { 24 | if (!oldData) return; 25 | 26 | let newData = oldData; 27 | const newPost = data.data.data; 28 | newData.pages[0].data = [newPost, ...newData.pages[0].data]; 29 | return { 30 | ...oldData, 31 | newData, 32 | }; 33 | }); 34 | 35 | queryClient.setQueryData(["allPosts"], (oldData) => { 36 | if (!oldData) return oldData; 37 | 38 | let newData = oldData; 39 | const newPost = data.data.data; 40 | newData.pages[0].data = [newPost, ...newData?.pages[0]?.data]; 41 | return { 42 | ...oldData, 43 | newData, 44 | }; 45 | }); 46 | }, 47 | }); 48 | }; 49 | -------------------------------------------------------------------------------- /public/reacts/like.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/hooks/useRemoveMember.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | import { queryClient } from "../App"; 4 | import { useSendMessage } from "./useSendMessage"; 5 | 6 | const RemoveMember = async ({ chatId, userId }) => { 7 | const { data } = await axios.put( 8 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/chats/group/remove`, 9 | { chatId, userId }, 10 | { 11 | withCredentials: true, 12 | } 13 | ); 14 | return data; 15 | }; 16 | 17 | export const useRemoveMember = (chat) => { 18 | const { mutate: sendMessage } = useSendMessage(chat); 19 | 20 | return useMutation({ 21 | mutationKey: "useRemoveMember", 22 | mutationFn: RemoveMember, 23 | onSuccess: (data) => { 24 | const userId = data?.data?.user; 25 | const deletedUser = data?.data?.deletedUser; 26 | 27 | queryClient.setQueryData(["getMessages", chat._id], (oldData) => { 28 | if (!oldData) return oldData; 29 | let newData = oldData; 30 | newData.pages[0].data.chat.users = 31 | newData.pages[0].data.chat.users.filter((m) => m._id !== userId); 32 | 33 | return { 34 | ...oldData, 35 | newData, 36 | }; 37 | }); 38 | 39 | sendMessage({ 40 | content: `${deletedUser.first_name} ${deletedUser.last_name} Removed from this group`, 41 | type: "info", 42 | chatId: chat._id, 43 | }); 44 | }, 45 | }); 46 | }; 47 | -------------------------------------------------------------------------------- /src/components/posts/post/shares/CreateSharePost.module.css: -------------------------------------------------------------------------------- 1 | .wrap { 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | } 6 | .card { 7 | width: 100%; 8 | max-width: 700px; 9 | padding: 0; 10 | margin: 8px; 11 | max-height: 98vh; 12 | overflow: auto; 13 | } 14 | .header { 15 | display: flex; 16 | align-items: center; 17 | justify-content: center; 18 | padding: 16px 0; 19 | border-bottom: 1px solid var(--divider); 20 | font-size: 20px; 21 | font-weight: 700; 22 | position: relative; 23 | } 24 | .header div { 25 | position: absolute; 26 | right: 0; 27 | } 28 | .content { 29 | padding: 16px; 30 | display: flex; 31 | flex-direction: column; 32 | gap: 16px; 33 | } 34 | .textarea_blue { 35 | width: 100%; 36 | height: 80px; 37 | resize: none; 38 | border-radius: 7px; 39 | outline-offset: 5px; 40 | border-color: var(--bg-third); 41 | padding: 0.8rem; 42 | font-size: 16px; 43 | font-family: inherit; 44 | background: var(--bg-primary); 45 | color: var(--color-primary); 46 | margin-bottom: 10px; 47 | } 48 | 49 | .textarea_blue:focus { 50 | outline-color: var(--blue-color); 51 | } 52 | 53 | .textarea_blue:hover { 54 | border-color: var(--color-secondary); 55 | } 56 | 57 | .btns { 58 | margin-top: 10px; 59 | display: flex; 60 | justify-content: flex-end; 61 | gap: 10px; 62 | } 63 | 64 | .btns button { 65 | width: -webkit-fill-available; 66 | font-weight: 500; 67 | font-size: 15px; 68 | } 69 | -------------------------------------------------------------------------------- /src/components/posts/post/likes/ReactsPopup.jsx: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import useOnClickOutside from "../../../../hooks/useOnClickOutside"; 3 | import styles from "./ReactsPopup.module.css"; 4 | 5 | const reactsArray = [ 6 | { 7 | name: "like", 8 | image: "../../../reacts/like.gif", 9 | }, 10 | { 11 | name: "love", 12 | image: "../../../reacts/love.gif", 13 | }, 14 | { 15 | name: "haha", 16 | image: "../../../reacts/haha.gif", 17 | }, 18 | { 19 | name: "wow", 20 | image: "../../../reacts/wow.gif", 21 | }, 22 | { 23 | name: "sad", 24 | image: "../../../reacts/sad.gif", 25 | }, 26 | { 27 | name: "angry", 28 | image: "../../../reacts/angry.gif", 29 | }, 30 | ]; 31 | 32 | export default function ReactsPopup({ 33 | handleMouseEnter, 34 | handleMouseLeave, 35 | reactHandler, 36 | setShowReact, 37 | showReact, 38 | }) { 39 | const popUpRef = useRef(); 40 | useOnClickOutside(popUpRef, showReact, () => { 41 | setShowReact(false); 42 | }); 43 | return ( 44 |
    50 | {reactsArray.map((react, i) => ( 51 |
    reactHandler(react.name)} 55 | > 56 | {react.name} 57 |
    58 | ))} 59 |
    60 | ); 61 | } 62 | -------------------------------------------------------------------------------- /src/svg/index.js: -------------------------------------------------------------------------------- 1 | import Logo from "./logo"; 2 | import HomeActive from "./homeActive"; 3 | import Friends from "./friends.js"; 4 | import Watch from "./watch"; 5 | import Market from "./market"; 6 | import Gaming from "./gaming"; 7 | import Menu from "./menu"; 8 | import Messenger from "./messenger"; 9 | import ArrowDown from "./arrowDown"; 10 | import Notifications from "./notifications"; 11 | import Search from "./search"; 12 | import Return from "./return"; 13 | import ArrowDown1 from "./arrowDow1"; 14 | import Plus from "./plus"; 15 | import ArrowRight from "./arrowRight"; 16 | import LiveVideo from "./liveVideo"; 17 | import Photo from "./photo"; 18 | import Feeling from "./feeling"; 19 | import Dots from "./dots"; 20 | import Public from "./public"; 21 | import NewRoom from "./newRoom"; 22 | import Home from "./home"; 23 | import FriendsActive from "./friendsActive"; 24 | import Info from "./info"; 25 | import Like from "./like"; 26 | import Smile from "./smile"; 27 | import Send from "./send"; 28 | import UnSeen from "./unseen"; 29 | import Phone from "./phone"; 30 | 31 | export { 32 | Logo, 33 | HomeActive, 34 | Friends, 35 | Watch, 36 | Market, 37 | Gaming, 38 | Menu, 39 | Messenger, 40 | Notifications, 41 | ArrowDown, 42 | Search, 43 | Return, 44 | ArrowDown1, 45 | Plus, 46 | ArrowRight, 47 | LiveVideo, 48 | Photo, 49 | Feeling, 50 | Dots, 51 | Public, 52 | NewRoom, 53 | Home, 54 | FriendsActive, 55 | Info, 56 | Like, 57 | Smile, 58 | Send, 59 | UnSeen, 60 | Phone, 61 | }; 62 | -------------------------------------------------------------------------------- /src/hooks/useChangeTheme.js: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import axios from "axios"; 3 | import { toast } from "react-hot-toast"; 4 | import { chatThemes } from "../data/chatThemes"; 5 | import { socket } from "../routes/IsLoggedIn"; 6 | import { updateChatTheme } from "../utils/rqUpdate"; 7 | import { useSendMessage } from "./useSendMessage"; 8 | 9 | const ChangeTheme = async ({ theme, chatId }) => { 10 | const { data } = await axios.put( 11 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/chats/${chatId}/theme`, 12 | { theme }, 13 | { 14 | withCredentials: true, 15 | } 16 | ); 17 | return data; 18 | }; 19 | 20 | export const useChangeTheme = (chat) => { 21 | const { mutate: sendMessage } = useSendMessage(chat); 22 | 23 | return useMutation({ 24 | mutationKey: "useChangeTheme", 25 | mutationFn: ChangeTheme, 26 | onSuccess: (data) => { 27 | const newTheme = data?.data?.theme; 28 | const name = data?.data?.name; 29 | const userId = data?.data?.user; 30 | 31 | updateChatTheme(newTheme, chat._id); 32 | 33 | sendMessage({ 34 | content: ` 35 | ${name} changed the theme to ${chatThemes[newTheme - 1].name}.`, 36 | type: "info", 37 | chatId: chat._id, 38 | }); 39 | 40 | toast.success("Theme changed successfully"); 41 | 42 | socket.emit("customize_chat", { 43 | userId, 44 | type: "theme", 45 | content: newTheme, 46 | chat, 47 | }); 48 | }, 49 | }); 50 | }; 51 | -------------------------------------------------------------------------------- /src/components/FormLoader/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import BeatLoader from "react-spinners/BeatLoader"; 3 | import PulseLoader from "react-spinners/PulseLoader"; 4 | 5 | import styles from "./style.module.css"; 6 | function FormLoader({ children, loading, className, isError, type }) { 7 | const [shoswError, setShowError] = useState(isError); 8 | const error = shoswError; 9 | 10 | useEffect(() => { 11 | setShowError(isError); 12 | }, [isError]); 13 | 14 | return ( 15 |
    18 | {loading ?
    : ""} 19 | {error ? ( 20 |
    21 |
    {isError?.response?.data.message}
    22 | 25 |
    26 | ) : ( 27 | "" 28 | )} 29 | {loading ? ( 30 |
    31 | {type === 2 ? ( 32 | 33 | ) : ( 34 | 35 | )} 36 |
    37 | ) : ( 38 | "" 39 | )} 40 |
    41 | {children} 42 |
    43 |
    44 | ); 45 | } 46 | 47 | export default FormLoader; 48 | -------------------------------------------------------------------------------- /src/pages/forgot/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import ChangePassword from "../../components/forgot/ChangePassword"; 3 | import CodeVerification from "../../components/forgot/CodeVerification"; 4 | import SearchAccount from "../../components/forgot/SearchAccount"; 5 | import SendEmail from "../../components/forgot/SendEmail"; 6 | import LoginFooter from "../../components/login/LoginFooter"; 7 | import NoAuthHeader from "../../components/noAuthHeader"; 8 | import styles from "./style.module.css"; 9 | 10 | function Forgot() { 11 | const [visible, setVisible] = useState(0); 12 | const [userInfos, setUserInfos] = useState(""); 13 | 14 | return ( 15 |
    16 | 17 |
    18 | {visible === 0 && ( 19 | 20 | )} 21 | {visible === 1 && ( 22 | 23 | )} 24 | {visible === 2 && ( 25 | 30 | )} 31 | {visible === 3 && ( 32 | 37 | )} 38 |
    39 | 40 |
    41 | ); 42 | } 43 | 44 | export default Forgot; 45 | -------------------------------------------------------------------------------- /src/components/input/signup/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import styles from "./style.module.css"; 3 | import { useField, ErrorMessage } from "formik"; 4 | import { useMediaQuery } from "react-responsive"; 5 | import Popper from "../../Popper/Popper"; 6 | 7 | function LoginInput({ placeholder, dir, type, disabled, ...props }) { 8 | const [field, meta] = useField(props); 9 | const [trigger, setTrigger] = useState(null); 10 | const [show, setShow] = useState(false); 11 | 12 | const desktopView = useMediaQuery({ 13 | query: "(min-width: 850px)", 14 | }); 15 | 16 | return ( 17 |
    18 | {meta.touched && meta.error && show && ( 19 | 24 | 25 | 26 | )} 27 | setShow(true)} 36 | onBlurCapture={(e) => { 37 | setShow(false); 38 | }} 39 | /> 40 | {meta.touched && meta.error && ( 41 | 42 | )} 43 |
    44 | ); 45 | } 46 | 47 | export default LoginInput; 48 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | import Router from "./routes/router"; 3 | import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; 4 | import CreatePostPopup from "./components/posts/CreatePostPopup"; 5 | import { useSelector } from "react-redux"; 6 | import { Toaster } from "react-hot-toast"; 7 | import Portal from "./utils/Portal"; 8 | 9 | export const queryClient = new QueryClient(); 10 | 11 | function App() { 12 | const user = useSelector((state) => ({ ...state.user.userinfo })); 13 | const theme = useSelector((state) => state.user.theme); 14 | const createPost = useSelector((state) => state.createPost); 15 | 16 | window.oncontextmenu = function (event) { 17 | event.preventDefault(); 18 | event.stopPropagation(); 19 | return false; 20 | }; 21 | 22 | useEffect(() => { 23 | if (theme === "dark") { 24 | document.body.classList.add("dark"); 25 | } else { 26 | document.body.classList.remove("dark"); 27 | } 28 | }, [theme]); 29 | 30 | useEffect(() => { 31 | if (createPost.isOpen) { 32 | document.documentElement.style.overflow = "hidden"; 33 | } else { 34 | document.documentElement.style.overflow = "auto"; 35 | } 36 | }, [createPost.isOpen]); 37 | 38 | return ( 39 | 40 | {createPost.isOpen && } 41 | 42 | 43 | 44 | 45 | 46 | ); 47 | } 48 | 49 | export default App; 50 | -------------------------------------------------------------------------------- /src/app/slices/createPostSlice.js: -------------------------------------------------------------------------------- 1 | import { createSlice } from "@reduxjs/toolkit"; 2 | 3 | // type = ['normal','image','background'] 4 | 5 | const initialValue = { 6 | isOpen: false, 7 | type: "normal", 8 | postText: "", 9 | background: null, 10 | images: [], 11 | }; 12 | export const createPostSlice = createSlice({ 13 | name: "createPost", 14 | initialState: initialValue, 15 | 16 | reducers: { 17 | type: (state, action) => { 18 | state.type = action.payload; 19 | if (action.payload === "normal" || action.payload === "background") { 20 | state.images = []; 21 | } 22 | }, 23 | images: (state, action) => { 24 | state.images.push(action.payload); 25 | }, 26 | background: (state, action) => { 27 | state.type = "background"; 28 | state.background = action.payload; 29 | }, 30 | postText: (state, action) => { 31 | state.postText = action.payload; 32 | }, 33 | open: (state, action) => { 34 | if (state.isOpen) state.type = "normal"; 35 | state.isOpen = !state.isOpen; 36 | if (action.payload === "photo") state.type = "image"; 37 | }, 38 | success: (state, action) => { 39 | state.isOpen = initialValue.isOpen; 40 | state.type = initialValue.type; 41 | state.postText = initialValue.postText; 42 | state.background = initialValue.background; 43 | state.images = initialValue.images; 44 | }, 45 | }, 46 | }); 47 | export const { type, images, background, postText, open, success } = 48 | createPostSlice.actions; 49 | 50 | export default createPostSlice.reducer; 51 | -------------------------------------------------------------------------------- /src/components/input/login/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import styles from "./input.module.css"; 3 | import { useField, ErrorMessage } from "formik"; 4 | import { useMediaQuery } from "react-responsive"; 5 | import Popper from "../../Popper/Popper"; 6 | 7 | function LoginInput({ placeholder, type, disabled, className, ...props }) { 8 | const [field, meta] = useField(props); 9 | const [trigger, setTrigger] = useState(null); 10 | const [show, setShow] = useState(false); 11 | 12 | const desktopView = useMediaQuery({ 13 | query: "(min-width: 850px)", 14 | }); 15 | 16 | return ( 17 |
    18 | {meta.touched && meta.error && show && ( 19 | 24 | 25 | 26 | )} 27 | setShow(true)} 36 | onBlurCapture={(e) => { 37 | setShow(false); 38 | }} 39 | /> 40 | {meta.touched && meta.error && ( 41 | 42 | )} 43 |
    44 | ); 45 | } 46 | 47 | export default LoginInput; 48 | -------------------------------------------------------------------------------- /src/svg/market.js: -------------------------------------------------------------------------------- 1 | function Market({ color }) { 2 | return ( 3 | 4 | 5 | 6 | ); 7 | } 8 | 9 | export default Market; 10 | -------------------------------------------------------------------------------- /src/pages/profile/Photos.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | import Card from "../../components/UI/Card/Card"; 4 | import classes from "./style.module.css"; 5 | import PuffLoader from "react-spinners/PuffLoader"; 6 | import Skeleton from "react-loading-skeleton"; 7 | 8 | function Photos({ photosData, photosSkelton }) { 9 | return ( 10 | 11 |
    12 | Photos 13 | 14 | See all photos 15 | 16 |
    17 |
    18 |
    19 | {photosSkelton ? ( 20 | 21 | ) : ( 22 | `${photosData.total_count} photos` 23 | )} 24 |
    25 | 26 | {photosSkelton ? ( 27 |
    28 | 29 |
    30 | ) : ( 31 |
    32 | {photosData.resources && 33 | photosData.resources 34 | .slice(0, 9) 35 | .map((img) => ( 36 |
    41 | ))} 42 |
    43 | )} 44 |
    45 |
    46 | ); 47 | } 48 | 49 | export default Photos; 50 | -------------------------------------------------------------------------------- /src/svg/phone.js: -------------------------------------------------------------------------------- 1 | function Phone({ color = "#0096ff" }) { 2 | return ( 3 | 10 | 11 | 16 | 17 | ); 18 | } 19 | 20 | export default Phone; 21 | -------------------------------------------------------------------------------- /src/components/messages/chatTheme/ChatTheme.module.css: -------------------------------------------------------------------------------- 1 | .wrap { 2 | display: flex; 3 | justify-content: center; 4 | align-items: center; 5 | } 6 | 7 | .card { 8 | width: 97%; 9 | max-width: 450px; 10 | padding: 0 !important; 11 | margin: 0 6px; 12 | box-shadow: 0 6px 28px 0 var(--shadow-2), 0 2px 4px 0 var(--shadow-1), 13 | inset 0 0 0 1px var(--shadow-inset) !important; 14 | border: none; 15 | } 16 | .header { 17 | display: flex; 18 | justify-content: center; 19 | align-items: center; 20 | height: 60px; 21 | border-bottom: 1px solid var(--divider); 22 | position: relative; 23 | } 24 | .header span { 25 | font-size: 18px; 26 | font-weight: 700; 27 | } 28 | .exit { 29 | position: absolute; 30 | right: 5px; 31 | } 32 | .content { 33 | padding: 15px; 34 | } 35 | .themes { 36 | display: flex; 37 | flex-wrap: wrap; 38 | } 39 | .theme { 40 | position: relative; 41 | flex-basis: calc(16.666666666% - 10px); 42 | box-sizing: border-box; 43 | border-radius: 15px; 44 | cursor: pointer; 45 | margin: 5px; 46 | } 47 | .theme::before { 48 | content: ""; 49 | display: block; 50 | padding-top: 100%; 51 | } 52 | 53 | .theme_wrap { 54 | position: absolute; 55 | top: 0; 56 | left: 0; 57 | height: 100%; 58 | width: 100%; 59 | display: flex; 60 | justify-content: center; 61 | align-items: center; 62 | } 63 | .theme_con { 64 | width: 48px; 65 | height: 48px; 66 | border-radius: 100%; 67 | background: red; 68 | } 69 | 70 | .btns { 71 | display: flex; 72 | justify-content: flex-end; 73 | gap: 10px; 74 | } 75 | 76 | .btns button { 77 | font-size: 14px; 78 | font-weight: 600; 79 | width: auto; 80 | } 81 | -------------------------------------------------------------------------------- /src/components/login/LoginForm.module.css: -------------------------------------------------------------------------------- 1 | .main { 2 | height: 78vh; 3 | min-height: 600px; 4 | padding-top: 2rem; 5 | } 6 | .header { 7 | margin: 0 auto; 8 | width: 300px; 9 | display: flex; 10 | flex-direction: column; 11 | align-items: center; 12 | } 13 | .header img { 14 | width: 80%; 15 | } 16 | .header span { 17 | font-size: 20px; 18 | } 19 | .login { 20 | display: flex; 21 | align-items: center; 22 | flex-direction: column; 23 | } 24 | .login button { 25 | height: 50px; 26 | } 27 | .login_wrapper { 28 | width: 350px; 29 | display: flex; 30 | flex-direction: column; 31 | align-items: center; 32 | gap: 1rem; 33 | margin: 1rem auto; 34 | } 35 | .form { 36 | width: 100%; 37 | } 38 | .forgot { 39 | color: var(--blue); 40 | cursor: pointer; 41 | font-size: 14px; 42 | } 43 | .forgot:hover { 44 | text-decoration: underline; 45 | } 46 | .signup_btn { 47 | background: var(--green-color); 48 | font-size: 17px !important; 49 | font-weight: 600 !important; 50 | margin-top: 1rem; 51 | width: 70% !important; 52 | } 53 | .extra { 54 | font-size: 15px; 55 | } 56 | .error_text { 57 | color: var(--color-error); 58 | text-align: center; 59 | margin: 0 auto 10px; 60 | } 61 | 62 | @media (min-width: 900px) { 63 | .main { 64 | align-items: center; 65 | display: flex; 66 | margin: 0 auto; 67 | max-width: 1000px; 68 | } 69 | .header { 70 | width: 50%; 71 | margin: 0 auto 8rem; 72 | align-items: start; 73 | } 74 | .header span { 75 | font-size: 27px; 76 | } 77 | .header img { 78 | width: 300px; 79 | margin-left: -1.4rem; 80 | } 81 | .login_wrapper { 82 | width: 400px; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/svg/public.js: -------------------------------------------------------------------------------- 1 | function Public({ color }) { 2 | return ( 3 | 4 | 5 | 9 | 13 | 18 | 19 | 20 | ); 21 | } 22 | 23 | export default Public; 24 | -------------------------------------------------------------------------------- /src/components/profile/intro/EditDetails.module.css: -------------------------------------------------------------------------------- 1 | .wrap { 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | } 6 | .card { 7 | width: 100%; 8 | max-width: 700px; 9 | min-height: 70vh; 10 | padding: 0; 11 | margin: 8px; 12 | } 13 | .header { 14 | display: flex; 15 | align-items: center; 16 | justify-content: center; 17 | padding: 16px 0; 18 | border-bottom: 1px solid var(--divider); 19 | font-size: 20px; 20 | font-weight: 700; 21 | position: relative; 22 | } 23 | .header div { 24 | position: absolute; 25 | right: 0; 26 | } 27 | .content { 28 | padding: 16px; 29 | display: flex; 30 | flex-direction: column; 31 | gap: 16px; 32 | overflow: scroll; 33 | max-height: 600px; 34 | } 35 | .h_col { 36 | display: flex; 37 | flex-direction: column; 38 | } 39 | .t1 { 40 | font-size: 16px; 41 | font-weight: 600; 42 | } 43 | .t2 { 44 | font-size: 14px; 45 | font-weight: 400; 46 | color: var(--color-secondary); 47 | } 48 | .details_header { 49 | margin-top: 15px; 50 | font-weight: 600; 51 | font-size: 20px; 52 | } 53 | 54 | .add_details_flex { 55 | display: flex; 56 | align-items: center; 57 | gap: 0.8rem; 58 | margin-top: 15px; 59 | color: var(--blue-color); 60 | font-size: 14px; 61 | cursor: pointer; 62 | } 63 | 64 | .add_details_flex i { 65 | right: 1rem; 66 | cursor: pointer; 67 | transform: scale(0.9); 68 | } 69 | .info_profile { 70 | margin-top: 10px; 71 | display: flex; 72 | align-items: center; 73 | gap: 10px; 74 | font-size: 15px; 75 | color: var(--color-primary); 76 | width: 100%; 77 | } 78 | 79 | .info_profile img { 80 | filter: invert(40%); 81 | } 82 | .underline:hover { 83 | text-decoration: underline; 84 | } 85 | -------------------------------------------------------------------------------- /src/components/profile/intro/Detail.jsx: -------------------------------------------------------------------------------- 1 | import { useState, useRef } from "react"; 2 | import useOnClickOutside from "../../../hooks/useOnClickOutside"; 3 | import EditArea from "./EditArea"; 4 | import classes from "./EditDetails.module.css"; 5 | 6 | function Detail({ 7 | img, 8 | value, 9 | placeholder, 10 | name, 11 | handleChange, 12 | updateDetails, 13 | infos, 14 | text, 15 | max, 16 | details, 17 | rel, 18 | }) { 19 | const [show, setShow] = useState(false); 20 | 21 | const editAreaRef = useRef(null); 22 | 23 | useOnClickOutside(editAreaRef, show, () => { 24 | setShow(false); 25 | }); 26 | return ( 27 |
    28 |
    setShow(true)} 31 | ref={editAreaRef} 32 | > 33 | {value ? ( 34 |
    35 | 36 | {value} 37 | 38 |
    39 | ) : ( 40 | <> 41 | 42 | Add {text} 43 | 44 | )} 45 |
    46 | {show && ( 47 | 59 | )} 60 |
    61 | ); 62 | } 63 | 64 | export default Detail; 65 | -------------------------------------------------------------------------------- /src/pages/friends/FreindCard.jsx: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | import { useEffect } from "react"; 3 | import { useRelationship } from "../../hooks/useRealationship"; 4 | import classes from "./style.module.css"; 5 | 6 | export default function FriendCard({ user, type, requestId, refetch }) { 7 | const { mutate, data } = useRelationship(user.username); 8 | 9 | const acceptRequest = async (requestId) => { 10 | mutate({ id: requestId, type: "acceptRequest" }); 11 | }; 12 | 13 | const cancelRequestHandler = async (userId) => { 14 | mutate({ id: requestId, type: "cancel" }); 15 | }; 16 | 17 | useEffect(() => { 18 | if (data?.status === "success") { 19 | refetch(); 20 | } 21 | }, [data]); 22 | 23 | return ( 24 |
    25 | 26 | 27 |
    28 | {user.first_name} {user.last_name} 29 |
    30 | 31 | {type === "sent" ? ( 32 |
    33 | 39 |
    40 | ) : type === "request" ? ( 41 |
    42 | 45 | 51 |
    52 | ) : ( 53 | "" 54 | )} 55 |
    56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /src/svg/search.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function Search({ color }) { 4 | return ( 5 | 6 | 7 | 11 | 15 | 19 | 23 | 24 | 25 | ); 26 | } 27 | 28 | export default Search; 29 | -------------------------------------------------------------------------------- /src/routes/pagesData.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const Home = React.lazy(() => import("../pages/home")); 4 | const Login = React.lazy(() => import("../pages/login")); 5 | const Forgot = React.lazy(() => import("../pages/forgot")); 6 | const Profile = React.lazy(() => import("../pages/profile")); 7 | const FriendsPage = React.lazy(() => import("../pages/friends")); 8 | const PostPage = React.lazy(() => import("../pages/post/PostPage")); 9 | const Messages = React.lazy(() => import("../pages/messages")); 10 | 11 | const pagesData = [ 12 | { 13 | path: "", 14 | element: , 15 | title: "home", 16 | priv: true, 17 | }, 18 | { 19 | path: "/activate/:token", 20 | element: , 21 | title: "home", 22 | priv: true, 23 | }, 24 | { 25 | path: "/profile", 26 | element: , 27 | title: "profile", 28 | priv: true, 29 | }, 30 | { 31 | path: "/messages", 32 | element: , 33 | title: "messages", 34 | priv: true, 35 | }, 36 | { 37 | path: "/messages/:chatId", 38 | element: , 39 | title: "messages", 40 | priv: true, 41 | }, 42 | { 43 | path: "/friends", 44 | element: , 45 | title: "profile", 46 | priv: true, 47 | }, 48 | { 49 | path: "/friends/:type", 50 | element: , 51 | title: "profile", 52 | priv: true, 53 | }, 54 | { 55 | path: "/profile/:username", 56 | element: , 57 | title: "profile", 58 | priv: true, 59 | }, 60 | { 61 | path: "/:username/posts/:post", 62 | element: , 63 | title: "profile", 64 | priv: true, 65 | }, 66 | { 67 | path: "forgot", 68 | element: , 69 | title: "home", 70 | priv: false, 71 | }, 72 | { 73 | path: "login", 74 | element: , 75 | title: "login", 76 | priv: false, 77 | }, 78 | ]; 79 | 80 | export default pagesData; 81 | -------------------------------------------------------------------------------- /src/components/home/posts/CreatePost/CreatePost.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Feeling, LiveVideo, Photo } from "../../../../svg"; 3 | import styles from "./CreatePost.module.css"; 4 | import * as createPostSlice from "../../../../app/slices/createPostSlice"; 5 | import { useSelector, useDispatch } from "react-redux"; 6 | 7 | function CreatePost({ user, profile }) { 8 | const dispatch = useDispatch(); 9 | const createPost = useSelector((state) => state.createPost); 10 | 11 | return ( 12 |
    13 |
    14 | 15 |
    { 18 | dispatch(createPostSlice.open()); 19 | }} 20 | > 21 | {createPost.postText 22 | ? createPost.postText 23 | : ` What's on your mind, ${user?.first_name}`} 24 |
    25 |
    26 |
    27 |
    28 |
    29 | 30 | Live Video 31 |
    32 | 33 |
    { 36 | dispatch(createPostSlice.open("photo")); 37 | }} 38 | > 39 | 40 | Photo/Video 41 |
    42 | {profile ? ( 43 |
    44 | 45 | Life Event 46 |
    47 | ) : ( 48 |
    49 | 50 | Feeling/Activity 51 |
    52 | )} 53 |
    54 |
    55 | ); 56 | } 57 | 58 | export default CreatePost; 59 | -------------------------------------------------------------------------------- /src/components/profile/intro/intro.module.css: -------------------------------------------------------------------------------- 1 | .card_header { 2 | font-size: 20px; 3 | font-weight: 700; 4 | display: flex; 5 | justify-content: space-between; 6 | } 7 | .content { 8 | display: flex; 9 | flex-direction: column; 10 | align-items: flex-start; 11 | } 12 | .info_profile { 13 | margin-top: 10px; 14 | display: flex; 15 | align-items: center; 16 | gap: 10px; 17 | font-size: 15px; 18 | color: var(--color-primary); 19 | } 20 | 21 | .info_profile img { 22 | filter: invert(40%); 23 | } 24 | .bio { 25 | white-space: pre-line; 26 | padding: 4px; 27 | text-align: center; 28 | margin-bottom: 10px; 29 | width: 100%; 30 | word-break: break-all; 31 | } 32 | .edit_btn { 33 | width: 100%; 34 | margin: 10px 0; 35 | } 36 | .bio_wrap { 37 | width: 100%; 38 | display: flex; 39 | flex-direction: column; 40 | gap: 10px; 41 | } 42 | .textarea_blue { 43 | margin-top: 10px; 44 | width: 100%; 45 | height: 80px; 46 | resize: none; 47 | border-radius: 4px; 48 | outline-offset: 4px; 49 | border: 1px solid var(--bg-third); 50 | padding: 0.8rem; 51 | font-size: 16px; 52 | font-family: inherit; 53 | background: var(--bg-secondary); 54 | color: var(--color-primary); 55 | } 56 | 57 | .textarea_blue:focus { 58 | outline-color: var(--blue-color); 59 | background: var(--bg-primary); 60 | } 61 | 62 | .textarea_blue:hover { 63 | border-color: var(--color-secondary); 64 | background: var(--bg-secondary); 65 | } 66 | .remaining { 67 | font-size: 12px; 68 | color: var(--color-secondary); 69 | align-self: flex-end; 70 | margin-top: 2px; 71 | } 72 | .save_btns { 73 | display: flex; 74 | justify-content: flex-end; 75 | gap: 10px; 76 | } 77 | .save_btns button { 78 | width: auto; 79 | font-weight: 600; 80 | font-size: 14px; 81 | } 82 | .select_rel { 83 | height: 30px; 84 | outline: none; 85 | border: none; 86 | background: var(--bg-secondary); 87 | margin: 10px 0; 88 | padding: 0 10px; 89 | border-radius: 5px; 90 | } 91 | -------------------------------------------------------------------------------- /src/components/posts/post/comments/CreateComment.module.css: -------------------------------------------------------------------------------- 1 | .wrap { 2 | padding: 5px 0px; 3 | display: flex; 4 | align-items: center; 5 | gap: 10px; 6 | margin-bottom: 5px; 7 | } 8 | 9 | .left { 10 | display: flex; 11 | text-align: center; 12 | justify-content: center; 13 | } 14 | .left img { 15 | width: 32px; 16 | height: 32px; 17 | border-radius: 50%; 18 | } 19 | .right { 20 | background: var(--bg-forth); 21 | color: var(--color-secondary); 22 | height: 38px; 23 | flex: 1 1; 24 | border-radius: 50px; 25 | font-size: 15px; 26 | line-height: 21px; 27 | display: flex; 28 | align-items: center; 29 | padding: 0 10px; 30 | display: flex; 31 | justify-content: space-between; 32 | align-items: center; 33 | gap: 10px; 34 | } 35 | .right:hover { 36 | background: var(--bg-third); 37 | } 38 | .input { 39 | width: 100%; 40 | height: 100%; 41 | } 42 | .input input { 43 | outline: none; 44 | border: none; 45 | background: transparent; 46 | width: 100%; 47 | height: 100%; 48 | font-size: 14px; 49 | padding-left: 5px; 50 | } 51 | .emoji_picker { 52 | z-index: 1; 53 | } 54 | .emoji_wrap { 55 | display: flex; 56 | gap: 15px; 57 | } 58 | 59 | .camera { 60 | display: flex; 61 | align-items: center; 62 | justify-content: center; 63 | } 64 | .camera i { 65 | transform: scale(1.3); 66 | cursor: pointer; 67 | } 68 | .emoji i { 69 | margin-top: 6px; 70 | } 71 | .img_perview { 72 | position: relative; 73 | width: max-content; 74 | margin: 16px 60px 10px; 75 | } 76 | .img_perview img { 77 | width: 150px; 78 | height: 100px; 79 | object-fit: cover; 80 | border-radius: 10px; 81 | box-shadow: 0 4px 10px 0 var(--shadow-2); 82 | border: 1px solid var(--divider); 83 | } 84 | .img_perview .exit { 85 | cursor: pointer; 86 | display: flex; 87 | align-items: center; 88 | justify-content: center; 89 | background: white; 90 | padding: 4px; 91 | border-radius: 50px; 92 | border: 1px solid var(--divider); 93 | position: absolute; 94 | top: -15px; 95 | right: -15px; 96 | } 97 | -------------------------------------------------------------------------------- /src/pages/profile/Friends.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | import Card from "../../components/UI/Card/Card"; 4 | import classes from "./style.module.css"; 5 | import PuffLoader from "react-spinners/PuffLoader"; 6 | import Skeleton from "react-loading-skeleton"; 7 | 8 | function Friends({ userData, userFriends, photosSkelton }) { 9 | return ( 10 | 11 |
    12 | Friends 13 | 14 | See all Friends 15 | 16 |
    17 |
    18 |
    19 | {photosSkelton ? ( 20 | 21 | ) : ( 22 | `${userData?.friendsCount} Friends` 23 | )} 24 |
    25 | {photosSkelton ? ( 26 |
    27 | 28 |
    29 | ) : ( 30 |
    31 | {userFriends && 32 | userFriends.slice(0, 9).map((user, i) => ( 33 | 34 |
    38 | 39 | {user.first_name} {user.last_name}{" "} 40 | {user?.confirmed && ( 41 | 45 | )} 46 | 47 | 48 | ))} 49 |
    50 | )} 51 |
    52 |
    53 | ); 54 | } 55 | 56 | export default Friends; 57 | -------------------------------------------------------------------------------- /src/components/login/GenderSelector.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import styles from "./SignupForm.module.css"; 3 | import { Field, ErrorMessage, useField } from "formik"; 4 | 5 | import { useMediaQuery } from "react-responsive"; 6 | import Popper from "../Popper/Popper"; 7 | 8 | export default function GenderSelector({ handleSignupChange, x, disabled }) { 9 | const [trigger, setTrigger] = useState(null); 10 | const [show, setShow] = useState(false); 11 | const [field, meta] = useField({ name: "gender" }); 12 | const genderError = meta.error; 13 | 14 | const desktopView = useMediaQuery({ 15 | query: "(min-width: 850px)", 16 | }); 17 | 18 | return ( 19 |
    setShow(true)} 23 | onMouseLeave={() => setShow(false)} 24 | > 25 |
    26 | Gender{" "} 27 | {genderError ? ( 28 | 29 | ) : ( 30 | 31 | )} 32 |
    33 |
    34 | 44 | 54 | {genderError && show && ( 55 | 60 | 61 | 62 | )} 63 |
    64 |
    65 | ); 66 | } 67 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backbook", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@popperjs/core": "^2.11.6", 7 | "@reduxjs/toolkit": "^1.9.1", 8 | "@tanstack/react-query": "^4.19.1", 9 | "@testing-library/jest-dom": "^5.14.1", 10 | "@testing-library/react": "^13.0.0", 11 | "@testing-library/user-event": "^13.2.1", 12 | "axios": "^1.2.1", 13 | "emoji-picker-react": "^4.4.7", 14 | "file-saver": "^2.0.5", 15 | "firebase": "^9.15.0", 16 | "formik": "^2.2.9", 17 | "js-cookie": "^3.0.1", 18 | "moment": "^2.29.4", 19 | "react": "^18.2.0", 20 | "react-copy-to-clipboard": "^5.1.0", 21 | "react-dom": "^18.2.0", 22 | "react-easy-crop": "^4.6.3", 23 | "react-hot-toast": "^2.4.0", 24 | "react-icons": "^4.7.1", 25 | "react-indiana-drag-scroll": "^3.0.3-alpha", 26 | "react-intersection-observer": "^9.4.1", 27 | "react-loading-skeleton": "^3.1.0", 28 | "react-lottie-player": "^1.5.4", 29 | "react-moment": "^1.1.2", 30 | "react-popper": "^2.3.0", 31 | "react-redux": "^8.0.5", 32 | "react-responsive": "^9.0.2", 33 | "react-router-dom": "^6.4.4", 34 | "react-scripts": "^5.0.1", 35 | "react-simple-image-viewer": "^1.2.2", 36 | "react-spinners": "^0.13.7", 37 | "redux": "^4.2.0", 38 | "socket.io-client": "^4.5.4", 39 | "styled-components": "^5.3.6", 40 | "web-vitals": "^2.1.0", 41 | "yup": "^0.32.11" 42 | }, 43 | "scripts": { 44 | "start": "react-scripts start", 45 | "build": "react-scripts build", 46 | "test": "react-scripts test", 47 | "eject": "react-scripts eject" 48 | }, 49 | "eslintConfig": { 50 | "extends": [ 51 | "react-app", 52 | "react-app/jest" 53 | ] 54 | }, 55 | "browserslist": { 56 | "production": [ 57 | ">0.2%", 58 | "not dead", 59 | "not op_mini all" 60 | ], 61 | "development": [ 62 | "last 1 chrome version", 63 | "last 1 firefox version", 64 | "last 1 safari version" 65 | ] 66 | }, 67 | "engines": { 68 | "node": ">=16.0.0" 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /public/reacts/haha.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Popper/Popper.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import styled from "styled-components"; 3 | import { usePopper } from "react-popper"; 4 | import Portal from "../../utils/Portal"; 5 | 6 | export const TooltipArrow = styled.div` 7 | width: 0.6rem; 8 | height: 0.6rem; 9 | &::before { 10 | content: ""; 11 | background: #b94a48; 12 | width: 0.6rem; 13 | height: 0.6rem; 14 | transform: translate(-50%, -50%) rotate(45deg); 15 | position: absolute; 16 | top: 0; 17 | left: 0; 18 | } 19 | `; 20 | 21 | const TipWrapper = styled.div` 22 | background: #b94a48; 23 | border-radius: 5px; 24 | color: white; 25 | padding: 0.8rem; 26 | font-weight: 300; 27 | font-size: 13px; 28 | z-index: 99; 29 | max-width: 318px; 30 | 31 | &[data-popper-placement^="right"] { 32 | ${TooltipArrow} { 33 | left: 0px; 34 | } 35 | } 36 | 37 | &[data-popper-placement^="left"] { 38 | ${TooltipArrow} { 39 | right: -0.6rem; 40 | } 41 | } 42 | 43 | &[data-popper-placement^="top"] { 44 | ${TooltipArrow} { 45 | bottom: -0.6rem; 46 | } 47 | } 48 | 49 | &[data-popper-placement^="bottom"] { 50 | ${TooltipArrow} { 51 | top: 0px; 52 | } 53 | } 54 | `; 55 | 56 | const Popper = ({ children, trigger, placement, offsetNum }) => { 57 | const [popperElement, setPopperElement] = useState(null); 58 | const [arrowElement, setArrowElement] = useState(null); 59 | 60 | const { styles, attributes } = usePopper(trigger, popperElement, { 61 | placement, 62 | modifiers: [ 63 | { name: "arrow", options: { element: arrowElement } }, 64 | { 65 | name: "offset", 66 | options: { 67 | offset: [0, parseInt(offsetNum || 8)], 68 | }, 69 | }, 70 | ], 71 | }); 72 | 73 | return ( 74 | 75 | 80 | {children} 81 | 82 | 83 | 84 | ); 85 | }; 86 | 87 | export default Popper; 88 | -------------------------------------------------------------------------------- /src/components/UI/Notification/Notification.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Moment from "react-moment"; 3 | import { useNavigate } from "react-router-dom"; 4 | import styles from "./Notification.module.css"; 5 | 6 | function Notification({ toast, t, notification }) { 7 | const navigate = useNavigate(); 8 | return ( 9 |
    10 |
    11 | New notification 12 |
    toast.dismiss(t.id)} 14 | className="small_circle" 15 | style={{ 16 | width: "25px", 17 | height: "25px", 18 | margin: "0", 19 | }} 20 | > 21 | 27 |
    28 |
    29 |
    { 32 | toast.dismiss(t.id); 33 | navigate(notification.click); 34 | }} 35 | > 36 |
    37 | 38 | 47 |
    48 |
    49 | {notification.content} 50 | 51 | 52 | {notification.createdAt} 53 | 54 | 55 |
    56 |
    57 |

    65 |

    66 |
    67 |
    68 | ); 69 | } 70 | 71 | export default Notification; 72 | -------------------------------------------------------------------------------- /src/components/messages/createGroup/CreateGroup.module.css: -------------------------------------------------------------------------------- 1 | .wrap { 2 | display: flex; 3 | justify-content: center; 4 | align-items: center; 5 | } 6 | 7 | .card { 8 | width: 97%; 9 | max-width: 500px; 10 | padding: 0 !important; 11 | margin: 0 6px; 12 | box-shadow: 0 6px 28px 0 var(--shadow-2), 0 2px 4px 0 var(--shadow-1), 13 | inset 0 0 0 1px var(--shadow-inset) !important; 14 | } 15 | .header { 16 | display: flex; 17 | justify-content: center; 18 | align-items: center; 19 | height: 60px; 20 | border-bottom: 1px solid var(--divider); 21 | position: relative; 22 | } 23 | .header span { 24 | font-size: 18px; 25 | font-weight: 700; 26 | } 27 | .exit { 28 | position: absolute; 29 | right: 5px; 30 | } 31 | .content { 32 | padding: 15px; 33 | } 34 | /***************************/ 35 | .input_wrap { 36 | width: 100%; 37 | position: relative; 38 | } 39 | .input_wrap input { 40 | background: var(--bg-primary); 41 | border: 1px solid var(--bg-third); 42 | border-radius: 10px; 43 | color: var(--color-primary); 44 | font-size: 17px; 45 | height: 50px; 46 | margin-bottom: 10px; 47 | outline: none; 48 | padding-left: 10px; 49 | width: 100%; 50 | } 51 | .error { 52 | border-color: #b94a48 !important; 53 | } 54 | .input_wrap i { 55 | position: absolute; 56 | right: 5px; 57 | top: 15px; 58 | -webkit-transform: scale(0.8); 59 | transform: scale(0.8); 60 | } 61 | .label { 62 | font-size: 14px; 63 | font-weight: 400; 64 | color: var(--color-secondary); 65 | margin: 4px 0; 66 | } 67 | /****************************/ 68 | 69 | .members { 70 | display: flex; 71 | flex-wrap: wrap; 72 | margin: 8px 0; 73 | gap: 8px; 74 | max-height: 250px; 75 | overflow: auto; 76 | } 77 | 78 | .member { 79 | background: var(--blue-color); 80 | color: #fff; 81 | padding: 4px 8px; 82 | border-radius: 6px; 83 | font-size: 13px; 84 | display: flex; 85 | align-items: center; 86 | justify-content: center; 87 | gap: 4px; 88 | position: relative; 89 | margin-left: 15px; 90 | padding-left: 20px; 91 | } 92 | .member img { 93 | position: absolute; 94 | left: -15px; 95 | width: 32px; 96 | border-radius: 100%; 97 | border: 4px solid var(--blue-color); 98 | } 99 | -------------------------------------------------------------------------------- /src/components/home/posts/CreatePost/CreatePost.module.css: -------------------------------------------------------------------------------- 1 | .create_post { 2 | width: 100%; 3 | background: var(--bg-primary); 4 | border-radius: 10px; 5 | box-shadow: 0 1px 2px var(--shadow-1); 6 | cursor: pointer; 7 | } 8 | .header { 9 | display: flex; 10 | align-items: center; 11 | gap: 8px; 12 | padding: 10px 17px 5px 15px; 13 | } 14 | 15 | .header img { 16 | width: 40px; 17 | height: 40px; 18 | border-radius: 50%; 19 | object-fit: cover; 20 | } 21 | .open_post { 22 | background: var(--bg-forth); 23 | color: var(--color-secondary); 24 | height: 41px; 25 | flex: 1; 26 | border-radius: 50px; 27 | font-size: 17px; 28 | line-height: 21px; 29 | display: flex; 30 | align-items: center; 31 | padding-left: 10px; 32 | -webkit-line-clamp: 1; 33 | -webkit-box-orient: horizontal; 34 | overflow: hidden; 35 | line-height: 2rem; 36 | } 37 | .splitter { 38 | height: 1px; 39 | width: 95%; 40 | background: var(--bg-third); 41 | margin: 7px 10px; 42 | } 43 | 44 | .post_body { 45 | padding: 0 10px 8px 10px; 46 | display: grid; 47 | grid-template-columns: repeat(3, 1fr); 48 | } 49 | 50 | .createPost_icon { 51 | display: flex; 52 | align-items: center; 53 | justify-content: center; 54 | gap: 8px; 55 | font-weight: 600; 56 | padding: 7px; 57 | color: var(--color-secondary); 58 | border-radius: 10px; 59 | font-size: 14px; 60 | } 61 | @media (max-width: 1175px) { 62 | .create_post { 63 | width: 84%; 64 | } 65 | } 66 | @media (max-width: 1030px) { 67 | .create_post { 68 | width: 100%; 69 | } 70 | } 71 | @media (max-width: 960px) { 72 | .create_post { 73 | width: 93%; 74 | } 75 | } 76 | 77 | @media (max-width: 885px) { 78 | .create_post { 79 | width: 100%; 80 | } 81 | } 82 | 83 | @media (max-width: 620px) { 84 | .create_post { 85 | width: 100%; 86 | } 87 | } 88 | @media (max-width: 400px) { 89 | .create_post { 90 | width: 100%; 91 | } 92 | 93 | .post_body { 94 | padding: 5px; 95 | } 96 | .createPost_icon { 97 | gap: 4px; 98 | padding: 5px; 99 | font-size: 12px; 100 | } 101 | .createPost_icon svg { 102 | width: 20px; 103 | height: 20px; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/components/profile/cover/Cover.module.css: -------------------------------------------------------------------------------- 1 | .cover { 2 | width: 100%; 3 | padding: 18%; 4 | background: var(--bg-third); 5 | border-radius: 0 0 10px 10px; 6 | position: relative; 7 | min-height: 170px; 8 | background-size: cover; 9 | background-position: center; 10 | } 11 | .edit_cover_wrapper { 12 | position: absolute; 13 | right: 20px; 14 | bottom: 20px; 15 | } 16 | .edit_cover { 17 | background: var(--bg-third); 18 | padding: 7px 15px; 19 | display: flex; 20 | align-items: center; 21 | gap: 10px; 22 | font-weight: 600; 23 | font-size: 14px; 24 | color: #111; 25 | border-radius: 10px; 26 | cursor: pointer; 27 | width: max-content; 28 | position: relative; 29 | } 30 | .edit_cover i { 31 | transform: scale(0.9); 32 | margin-top: 4px; 33 | } 34 | .edit_cover span { 35 | display: none; 36 | } 37 | .cover_upload_menu { 38 | position: absolute; 39 | right: 50%; 40 | top: 41px; 41 | padding: 10px; 42 | z-index: 8; 43 | width: 250px; 44 | } 45 | .open_cover_menu_item { 46 | display: flex; 47 | align-items: center; 48 | gap: 10px; 49 | padding: 10px; 50 | cursor: pointer; 51 | font-weight: 600; 52 | font-size: 14px; 53 | border-radius: 10px; 54 | } 55 | .cover_cropper { 56 | width: 100%; 57 | height: 100%; 58 | } 59 | .mediaClassName { 60 | width: 100%; 61 | } 62 | 63 | .save_cover { 64 | position: fixed; 65 | left: 0; 66 | top: 56px; 67 | height: 56px; 68 | width: 100%; 69 | background: rgb(0 0 0 / 70%); 70 | z-index: 1; 71 | display: flex; 72 | align-items: center; 73 | justify-content: space-between; 74 | padding: 0 20px; 75 | } 76 | .btns { 77 | display: flex; 78 | justify-content: flex-end; 79 | gap: 10px; 80 | } 81 | 82 | .btns button { 83 | font-weight: 500; 84 | } 85 | 86 | .save_cover .left { 87 | display: flex; 88 | align-items: center; 89 | gap: 10px; 90 | color: #fff; 91 | } 92 | 93 | .save_cover .left i { 94 | filter: invert(100%); 95 | } 96 | 97 | @media (min-width: 900px) { 98 | .edit_cover span { 99 | display: inline; 100 | } 101 | } 102 | 103 | :global(.dark) .cover i { 104 | filter: invert(100%); 105 | } 106 | 107 | :global(.dark) .cover { 108 | background-color: #2d2d2d; 109 | } 110 | -------------------------------------------------------------------------------- /public/icons/facebook.svg: -------------------------------------------------------------------------------- 1 | FBWordmark_Hex-RGB-1024 2 | -------------------------------------------------------------------------------- /src/components/posts/post/shares/ShareMenu.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useState } from "react"; 2 | import useOnClickOutside from "../../../../hooks/useOnClickOutside"; 3 | import Card from "../../../UI/Card/Card"; 4 | import MenuItem from "../MenuItem"; 5 | import classes from "../Post.module.css"; 6 | import { IoIosLink } from "react-icons/io"; 7 | import { CopyToClipboard } from "react-copy-to-clipboard"; 8 | import toast from "react-hot-toast"; 9 | import CreateSharePost from "./CreateSharePost"; 10 | 11 | function ShareMenu({ 12 | showMenu, 13 | setShowMenu, 14 | post, 15 | user, 16 | postRef, 17 | setSharesCount, 18 | }) { 19 | const menuRef = useRef(); 20 | 21 | const [showSharePost, setShowSharePost] = useState(false); 22 | 23 | useOnClickOutside(menuRef, showMenu, () => { 24 | if (showSharePost) return; 25 | setShowMenu(false); 26 | }); 27 | 28 | const full = `${window.location.origin}/${post.user.username}/posts/${post._id}`; 29 | 30 | return ( 31 | 36 |
      37 | { 40 | toast.success("Successfully Copied!"); 41 | setShowMenu(false); 42 | }} 43 | > 44 |
    • 45 | 46 |
      47 | Copy post link 48 | 49 | Copy post link to clipboard 50 | 51 |
      52 |
    • 53 |
      54 | 55 |
      56 |
      setShowSharePost((perv) => !perv)}> 57 | 62 |
      63 |
    64 | {showSharePost && ( 65 | 71 | )} 72 |
    73 | ); 74 | } 75 | 76 | export default ShareMenu; 77 | -------------------------------------------------------------------------------- /src/components/profile/cover/OldCovers.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from "react"; 2 | import useOnClickOutside from "../../../hooks/useOnClickOutside"; 3 | import Card from "../../UI/Card/Card"; 4 | import classes from "./OldCovers.module.css"; 5 | 6 | function OldCovers({ setShowOldCover, setImage, photosData, showOldCover }) { 7 | const oldCoversCardRef = useRef(null); 8 | 9 | useOnClickOutside(oldCoversCardRef, showOldCover, () => { 10 | setShowOldCover(false); 11 | }); 12 | 13 | return ( 14 |
    15 | 16 |
    17 | Update Cover Photo 18 |
    setShowOldCover(false)}> 19 | 20 |
    21 |
    22 |
    23 | {photosData?.profileCovers.length > 0 && ( 24 | <> 25 |
    Choose from old cover picture
    26 |
    27 | {photosData?.profileCovers.map((photo) => ( 28 | {photo.id} { 32 | setImage(photo.url); 33 | setShowOldCover(false); 34 | }} 35 | key={photo.id} 36 | /> 37 | ))} 38 |
    39 | 40 | )} 41 | {photosData?.resources.length > 0 && ( 42 | <> 43 |
    Choose from your profile photos
    44 |
    45 | {photosData?.resources.map((photo) => ( 46 | {photo.id} { 50 | setImage(photo.url); 51 | setShowOldCover(false); 52 | }} 53 | key={photo.id} 54 | /> 55 | ))} 56 |
    57 | 58 | )} 59 |
    60 |
    61 |
    62 | ); 63 | } 64 | 65 | export default OldCovers; 66 | -------------------------------------------------------------------------------- /src/components/home/SendVerification/SendVerification.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Card from "../../UI/Card/Card"; 3 | import styles from "./SendVerification.module.css"; 4 | import { useQuery } from "@tanstack/react-query"; 5 | import axios from "axios"; 6 | import Lottie from "react-lottie-player"; 7 | import successAnimation from "../../UI/Lottie/success.json"; 8 | import BarLoader from "react-spinners/BarLoader"; 9 | 10 | function SendVerification() { 11 | const enabled = false; 12 | const { fetchStatus, status, error, data, refetch } = useQuery({ 13 | queryKey: ["resendEmail"], 14 | queryFn: async () => { 15 | const { data } = await axios.post( 16 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/users/resendEmailVerifivation`, 17 | {}, 18 | { 19 | withCredentials: true, 20 | } 21 | ); 22 | return data; 23 | }, 24 | enabled, 25 | retry: false, 26 | }); 27 | 28 | const resendEmail = () => { 29 | refetch(); 30 | }; 31 | 32 | if (data?.status === "success") 33 | return ( 34 | 35 |

    Email verification sent successfully

    36 | 37 | 47 |
    48 | ); 49 | 50 | if (fetchStatus === "fetching" && status === "loading") 51 | return ( 52 | 53 | 59 | 60 | ); 61 | 62 | return ( 63 | 64 | 65 | Your account is not verified, verify your account to avoid deleting Your 66 | acccount. 67 | 68 |
    69 | Resend email verification 70 |
    71 | {error ? ( 72 |

    {error.response?.data?.message}

    73 | ) : ( 74 | "" 75 | )} 76 |
    77 | ); 78 | } 79 | 80 | export default SendVerification; 81 | -------------------------------------------------------------------------------- /src/components/login/LoginFooter.jsx: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | import styles from "./LoginFooter.module.css"; 3 | 4 | export default function LoginFooter() { 5 | return ( 6 |
    7 |
    8 | English(UK) 9 | Français(FR) 10 | العربية 11 | ⵜⴰⵎⴰⵣⵉⵖⵜ 12 | Español (España) 13 | italiano 14 | Deutsch 15 | Português (Brasil) 16 | हिन्दी 17 | 中文(简体) 18 | 日本語 19 | 20 | 21 | 22 |
    23 |
    24 |
    25 | Sign Up 26 | Log in 27 | Messenger 28 | Backbook Lite 29 | Watch 30 | Places 31 | Games 32 | Marketplace 33 | Backbook Pay 34 | Oculus 35 | Portal 36 | Instagram 37 | Bulletin 38 | Local 39 | Fundraisers 40 | Services 41 | Voting Information Centre 42 | Groups 43 | About 44 | Create ad 45 | Create Page 46 | Developers 47 | Careers 48 | Privacy 49 | Cookies 50 | 51 | AdChoices 52 | 53 | 54 | Terms 55 | Help 56 |
    57 |
    58 | 59 | Backbook © 2022 60 | 61 |
    62 |
    63 | ); 64 | } 65 | -------------------------------------------------------------------------------- /src/pages/messages/index.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styles from "./messages.module.css"; 3 | import { useParams } from "react-router-dom"; 4 | import Middle from "./Middle"; 5 | import Left from "./Left"; 6 | import { useDispatch, useSelector } from "react-redux"; 7 | import { useMediaQuery } from "react-responsive"; 8 | import { useState } from "react"; 9 | import { useEffect } from "react"; 10 | import Lottie from "react-lottie-player"; 11 | import homeDesk from "../../components/UI/Lottie/messages.json"; 12 | import { setSelectedChat } from "../../app/slices/soketSlice"; 13 | 14 | function Messages() { 15 | const { soketSlice, user: userState } = useSelector((state) => ({ 16 | ...state, 17 | })); 18 | const dispatch = useDispatch(); 19 | 20 | const user = userState.userinfo; 21 | const { chatId } = useParams(); 22 | const desktopView = useMediaQuery({ 23 | query: "(min-width: 850px)", 24 | }); 25 | 26 | const pView = desktopView || !chatId; 27 | 28 | const [openInfo, setOpenInfo] = useState(pView); 29 | 30 | useEffect(() => { 31 | setOpenInfo(pView); 32 | }, [pView]); 33 | 34 | useEffect(() => { 35 | dispatch(setSelectedChat(chatId)); 36 | }, [chatId]); 37 | 38 | useEffect(() => { 39 | const appHeight = (e) => { 40 | const doc = document.documentElement; 41 | const h = window.visualViewport.height; 42 | doc.style.setProperty("--app-height", `${h}px`); 43 | }; 44 | window.addEventListener("resize", appHeight); 45 | appHeight(); 46 | 47 | return () => { 48 | window.addEventListener("resize", appHeight); 49 | }; 50 | }, []); 51 | 52 | return ( 53 |
    58 | {pView && } 59 | {chatId ? ( 60 | 68 | ) : ( 69 |
    70 | 79 |

    Start a conversation

    80 |
    81 | )} 82 |
    83 | ); 84 | } 85 | 86 | export default Messages; 87 | -------------------------------------------------------------------------------- /src/components/forgot/SendEmail.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import Card from "../UI/Card/Card"; 3 | import styles from "./style.module.css"; 4 | import axios from "axios"; 5 | import FormLoader from "../FormLoader"; 6 | 7 | function SendEmail({ setVisible, userInfos }) { 8 | const [error, setError] = useState(""); 9 | const [loading, setLoading] = useState(false); 10 | 11 | const submitHandler = async () => { 12 | try { 13 | setLoading(true); 14 | await axios.post( 15 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/users/forgotPassword`, 16 | { 17 | email: userInfos.email, 18 | }, 19 | { 20 | withCredentials: true, 21 | } 22 | ); 23 | setError(""); 24 | setLoading(false); 25 | setVisible(2); 26 | } catch (error) { 27 | setError(error.response?.data?.message); 28 | setTimeout(() => { 29 | setLoading(false); 30 | }, 1000); 31 | } 32 | }; 33 | 34 | return ( 35 | 36 |
    Reset Your Password
    37 | {error ? ( 38 |
    39 |
    Error
    40 | {error} 41 |
    42 | ) : ( 43 | "" 44 | )} 45 | 46 | 47 |
    48 |
    49 | 50 | How do you want to receive the code to reset your password? 51 | 52 | 59 |
    60 |
    61 | 62 | {userInfos.email} 63 | {userInfos.first_name} 64 |
    65 |
    66 |
    67 |
    68 | 71 | 74 |
    75 |
    76 | ); 77 | } 78 | 79 | export default SendEmail; 80 | -------------------------------------------------------------------------------- /src/components/posts/post/comments/Comments.jsx: -------------------------------------------------------------------------------- 1 | import { useInfiniteQuery } from "@tanstack/react-query"; 2 | import { useState, useEffect } from "react"; 3 | 4 | import classes from "./Comments.module.css"; 5 | import axios from "axios"; 6 | import Comment from "./Comment"; 7 | 8 | function Comments({ 9 | lastComment, 10 | commentsCount, 11 | postID, 12 | lastCommentData, 13 | commentRef, 14 | }) { 15 | const [comments, setComments] = useState([]); 16 | 17 | const fetchProjects = async ({ pageParam = 1 }) => { 18 | const { data } = await axios.get( 19 | `${process.env.REACT_APP_BACKEND_URL}/api/v1/posts/comments/${postID}?limit=4&page=${pageParam}&sort=-createdAt`, 20 | { 21 | withCredentials: true, 22 | } 23 | ); 24 | return data; 25 | }; 26 | 27 | const { fetchNextPage, isFetching } = useInfiniteQuery({ 28 | queryKey: ["comments", postID], 29 | queryFn: fetchProjects, 30 | getNextPageParam: (lastPage, pages) => { 31 | if (lastPage.datalength < 4) { 32 | return undefined; 33 | } else { 34 | return pages.length + 1; 35 | } 36 | }, 37 | onSuccess: (data) => { 38 | const newCommemnts = data.pages[data.pages.length - 1].data.comments; 39 | if (data.pages.length === 1) { 40 | setComments([...newCommemnts]); 41 | } else { 42 | setComments((prev) => [...prev, ...newCommemnts]); 43 | } 44 | }, 45 | enabled: false, 46 | }); 47 | 48 | const viewMoreHandler = () => { 49 | fetchNextPage(); 50 | }; 51 | 52 | useEffect(() => { 53 | if (lastComment) { 54 | setComments((prev) => [...prev, lastComment]); 55 | } 56 | }, []); 57 | 58 | useEffect(() => { 59 | if (lastCommentData) setComments((prev) => [lastCommentData, ...prev]); 60 | }, [lastCommentData]); 61 | 62 | return ( 63 |
    64 | {comments.map((comment) => ( 65 | 66 | ))} 67 | {commentsCount > comments.length ? ( 68 | <> 69 |
    70 | View more comments 71 | {isFetching && " Loading..."} 72 |
    73 | 74 | ) : ( 75 | <> 76 |
    { 79 | commentRef.current.focus(); 80 | }} 81 | > 82 | Write a comment... 83 |
    84 | 85 | )} 86 |
    87 | ); 88 | } 89 | 90 | export default Comments; 91 | -------------------------------------------------------------------------------- /src/components/home/right/HomeRight.module.css: -------------------------------------------------------------------------------- 1 | .right_home { 2 | position: fixed; 3 | right: 20px; 4 | top: 4rem; 5 | width: 21vw; 6 | } 7 | 8 | .heading { 9 | font-size: 16px; 10 | font-weight: 600; 11 | color: var(--color-secondary); 12 | padding: 13px 10px 11px 10px; 13 | } 14 | 15 | .splitter { 16 | height: 1.3px; 17 | background: var(--divider); 18 | width: 21vw; 19 | margin: 6px 2px 0 12px; 20 | } 21 | 22 | .contacts_header { 23 | position: relative; 24 | display: flex; 25 | align-items: center; 26 | justify-content: space-between; 27 | padding: 12px 0 7px 10px; 28 | font-weight: 600; 29 | color: var(--color-secondary); 30 | } 31 | 32 | .contacts_header_right { 33 | display: flex; 34 | align-items: center; 35 | gap: 6px; 36 | position: absolute; 37 | right: -9px; 38 | top: 7px; 39 | } 40 | 41 | .contact_circle { 42 | width: 35px; 43 | height: 35px; 44 | border-radius: 50%; 45 | display: flex; 46 | align-items: center; 47 | justify-content: center; 48 | cursor: pointer; 49 | } 50 | 51 | .contact_circle:nth-child(1) { 52 | margin-right: -1px; 53 | } 54 | 55 | .contact_circle:nth-child(2) { 56 | margin-right: 1px; 57 | } 58 | 59 | .contact_circle:nth-child(3) { 60 | margin-top: -1px; 61 | } 62 | 63 | .contacts_list { 64 | padding: 5px; 65 | } 66 | 67 | .contact { 68 | display: flex; 69 | align-items: center; 70 | gap: 12px; 71 | font-size: 14px; 72 | padding: 5px; 73 | border-radius: 10px; 74 | cursor: pointer; 75 | color: var(--color-primary); 76 | font-weight: 600; 77 | } 78 | 79 | .contact_img img { 80 | width: 36px; 81 | height: 36px; 82 | border-radius: 50%; 83 | object-fit: cover; 84 | } 85 | 86 | .contact span { 87 | transform: translateY(-5px); 88 | } 89 | 90 | @media (max-width: 1175px) { 91 | .right_home { 92 | width: 18vw; 93 | } 94 | } 95 | 96 | @media (max-width: 1030px) { 97 | .right_home { 98 | width: 20vw; 99 | } 100 | 101 | .contacts_header_right { 102 | right: 10%; 103 | } 104 | 105 | .contact_circle { 106 | width: 20px; 107 | } 108 | } 109 | @media (max-width: 1030px) { 110 | .right_home { 111 | width: 20vw; 112 | } 113 | } 114 | @media (max-width: 960px) { 115 | .right_home { 116 | width: 25vw; 117 | } 118 | 119 | .splitter1 { 120 | width: 25vw; 121 | } 122 | 123 | .contact_circle { 124 | width: 30px; 125 | } 126 | 127 | .contacts_header_right { 128 | right: 0; 129 | } 130 | } 131 | 132 | @media (max-width: 885px) { 133 | .right_home { 134 | display: none; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/components/messages/SearchUser.module.css: -------------------------------------------------------------------------------- 1 | /*---Search menu-----*/ 2 | .search_area { 3 | position: absolute; 4 | align-items: flex-start; 5 | flex-direction: column; 6 | gap: 6px; 7 | background: var(--bg-primary); 8 | box-shadow: 0 12px 12px var(--shadow-1), inset 0 0 0 0 var(--shadow-inset); 9 | transition: all 0.2s; 10 | -webkit-font-smoothing: antialiased; 11 | z-index: 1; 12 | padding: 8px 6px 10px 6px; 13 | overflow: hidden; 14 | height: -webkit-fill-available; 15 | width: 100%; 16 | top: 48px; 17 | } 18 | 19 | .search_wrap { 20 | display: flex; 21 | align-items: center; 22 | } 23 | 24 | .search { 25 | display: flex; 26 | align-items: center; 27 | gap: 6px; 28 | background: var(--bg-forth); 29 | padding: 7px 20px 7px 13px; 30 | border-radius: 50px; 31 | cursor: text; 32 | width: 100%; 33 | min-width: 233px; 34 | } 35 | .input { 36 | outline: none; 37 | border: none; 38 | background: transparent; 39 | font-size: 15px; 40 | font-family: inherit; 41 | padding-left: 2px; 42 | width: 100%; 43 | } 44 | .search_area .search svg { 45 | transform: translateY(1px); 46 | } 47 | 48 | .input::placeholder { 49 | transform: translateY(-2px); 50 | } 51 | 52 | .input:focus::placeholder { 53 | transform: translateY(-1px); 54 | } 55 | 56 | .search_history { 57 | width: 100%; 58 | } 59 | 60 | .search_history_header { 61 | width: 100%; 62 | display: flex; 63 | align-items: center; 64 | justify-content: space-between; 65 | padding: 10px; 66 | font-size: 14px; 67 | } 68 | 69 | .search_history_header span { 70 | font-weight: 600; 71 | font-size: 16px; 72 | } 73 | 74 | .search_history_header a { 75 | cursor: pointer; 76 | color: var(--blue-color); 77 | } 78 | 79 | /*---Search menu-----*/ 80 | 81 | .search_results { 82 | display: flex; 83 | flex-direction: column; 84 | gap: 5px; 85 | } 86 | .search_result { 87 | display: flex; 88 | align-items: center; 89 | gap: 12px; 90 | font-size: 14px; 91 | padding: 5px; 92 | border-radius: 10px; 93 | cursor: pointer; 94 | color: var(--color-primary); 95 | font-weight: 600; 96 | } 97 | 98 | .search_result_img { 99 | width: 36px; 100 | height: 36px; 101 | border-radius: 50%; 102 | object-fit: cover; 103 | } 104 | 105 | .search_result span { 106 | transform: translateY(-5px); 107 | } 108 | 109 | .search_item { 110 | border-radius: 10px; 111 | padding: 2px 5px; 112 | } 113 | .search_user_item { 114 | display: flex; 115 | align-items: center; 116 | width: 100%; 117 | justify-content: space-between; 118 | padding-right: 10px; 119 | } 120 | -------------------------------------------------------------------------------- /src/components/login/SignupForm.module.css: -------------------------------------------------------------------------------- 1 | .signup { 2 | position: absolute; 3 | left: 50%; 4 | top: 50%; 5 | -webkit-transform: translate(-50%, -50%); 6 | transform: translate(-50%, -50%); 7 | z-index: 10; 8 | width: 350px; 9 | box-shadow: 0 2px 4px var(--shadow-1); 10 | } 11 | .signup_header { 12 | border-bottom: 1px solid var(--bg-third); 13 | display: flex; 14 | flex-direction: column; 15 | gap: 10px; 16 | padding-bottom: 10px; 17 | position: relative; 18 | margin-bottom: 10px; 19 | } 20 | .signup_header i { 21 | cursor: pointer; 22 | position: absolute; 23 | right: 0; 24 | } 25 | .signup_header span:first-of-type { 26 | font-size: 32px; 27 | font-weight: 700; 28 | } 29 | .signup_header span:last-of-type { 30 | color: var(--color-secondary); 31 | font-size: 15px; 32 | } 33 | .line { 34 | display: flex; 35 | gap: 10px; 36 | } 37 | .col { 38 | margin-bottom: 10px; 39 | } 40 | .colHeader { 41 | align-items: center; 42 | color: var(--color-secondary); 43 | display: flex; 44 | font-size: 13px; 45 | gap: 4px; 46 | } 47 | .colHeader i { 48 | margin-top: 3px; 49 | } 50 | .colHeader .error_icon { 51 | margin-top: 30px; 52 | } 53 | .grid { 54 | grid-gap: 10px; 55 | display: grid; 56 | gap: 10px; 57 | grid-template-columns: repeat(3, 1fr); 58 | height: 35px; 59 | margin-top: 5px; 60 | width: 100%; 61 | } 62 | .gender { 63 | grid-template-columns: repeat(2, 1fr); 64 | } 65 | .grid select { 66 | border-radius: 5px; 67 | color: var(--color-primary); 68 | cursor: pointer; 69 | font-size: 16px; 70 | width: 100%; 71 | padding: 0 10px; 72 | background: var(--bg-primary); 73 | } 74 | .grid label { 75 | border-radius: 5px; 76 | align-items: center; 77 | border: 1px solid var(--color-secondary); 78 | display: flex; 79 | justify-content: space-between; 80 | padding: 0 15px; 81 | } 82 | .err_icon { 83 | transform: scale(0.6); 84 | } 85 | .info { 86 | color: var(--color-secondary); 87 | font-size: 11px; 88 | margin-top: 10px; 89 | } 90 | .info span { 91 | color: var(--blue); 92 | cursor: pointer; 93 | } 94 | .info span:hover { 95 | text-decoration: underline; 96 | } 97 | .btn_wrap { 98 | align-items: center; 99 | display: flex; 100 | justify-content: center; 101 | margin: 20px 0 10px; 102 | width: 100%; 103 | } 104 | .btn_wrap button { 105 | background: var(--green-color); 106 | font-size: 17px !important; 107 | font-weight: 600 !important; 108 | margin-top: 1rem; 109 | width: 70% !important; 110 | } 111 | @media (min-width: 539px) { 112 | .signup { 113 | width: 400px; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/components/profile/intro/EditArea.jsx: -------------------------------------------------------------------------------- 1 | import { useRef, useEffect } from "react"; 2 | import isRTL from "../../../utils/isRTL"; 3 | import classes from "./intro.module.css"; 4 | 5 | function EditArea({ 6 | innerRef, 7 | infos, 8 | handleChange, 9 | setShow, 10 | max, 11 | remain, 12 | updateDetails, 13 | details, 14 | name, 15 | placeholder, 16 | rel, 17 | }) { 18 | const isChanged = rel ? false : details?.[name] === infos?.[name]; 19 | const editAreaRef = useRef(null); 20 | 21 | useEffect(() => { 22 | editAreaRef.current.focus(); 23 | }, []); 24 | 25 | return ( 26 |
    27 | {rel ? ( 28 | 45 | ) : ( 46 | 61 | )} 62 | {name === "bio" && ( 63 |
    {remain} characters remaining
    64 | )} 65 |
    66 | 69 | 83 |
    84 |
    85 | ); 86 | } 87 | 88 | export default EditArea; 89 | -------------------------------------------------------------------------------- /public/icons/backbook.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 11 | 14 | 17 | 20 | 22 | 26 | 28 | 29 | --------------------------------------------------------------------------------