/
SOFG1
/
hasida
Обзор
Документация
Войти
/
SOFG1
/
hasida
Код
Запросы
0
Задачи
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/components/AdminPanelComponents/UserCheck.tsx
280 строк
7 KB
Eddy
initial commit
22 июл 2024, 17:14
22 июл 2024, 17:14
b43c0d0
Код
Авторство
О чём код?
import React, {useCallback, useState} from "react"; import styled from "styled-components"; import avatar from "../../images/avatar.png"; import { BanIcon, CallIcon, EllipsisIcon, EmailIcon, InfoCircleIcon, LocationIcon, ReloadIcon, TrashIcon } from "../../UI/SVG"; import { useAdminBlockProfileMutation, useAdminDeleteProfileMutation, } from "../../api/admin"; import {getLastOnlineTime} from "../../utils/getLastOnlineTime"; import {hostUrl} from "../../api"; import {useTranslation} from "react-i18next"; import {Loader2} from "../../UI/Loader"; import {IProfile} from "../../api/home"; import {useDispatch} from "react-redux"; import {removeFeedData} from "../../store/home"; import {IUserLoader} from "../../views/AdminPanelViews/UsersCheckView"; const StyledWrapper = styled.div` position: relative; display: flex; flex-direction: column; gap: 20px; width: 360px; `; const StyledWrapperCard = styled.div` display: flex; justify-content: space-between; width: 100%; background-color: transparent; img { width: 106px; height: 91px; object-fit: cover; } `; const StyledMainBox = styled.div` display: flex; flex-direction: column; align-items: flex-start; gap: 10px; `; const StyledTitle = styled.div` display: flex; flex-wrap: nowrap; font-size: 20px; font-weight: 600; line-height: 132%; letter-spacing: 0.2px; `; const StyledName = styled.span` max-width: 185px; overflow: hidden; `; const StyledAge = styled.span` font-weight: 300; margin-left: 5px; `; const StyledLocation = styled.div` display: flex; align-items: center; font-size: 14px; font-weight: 300; line-height: 132%; letter-spacing: 0.14px; gap: 7px; svg { width: 24px; height: 24px; } `; const StyledLastView = styled.div` font-size: 12px; font-weight: 300; line-height: 132%; letter-spacing: 0.12px; span { font-size: 14px; font-weight: 600; letter-spacing: 0.14px; } `; const StyledOnline = styled.span` font-weight: 300; color: green; `; const StyledControlBox = styled.div` display: flex; flex-direction: column; gap: 12px; svg { cursor: pointer; } `; const StyledInfoIconWrapper = styled.div` height: 28px; width: 28px; border-radius: 50%; &:hover { box-shadow: 3px 5px 10px rgba(0, 0, 0, 0.12); } svg { width: 28px; height: 28px; fill: #2A9B9F; } `; const EllipsisIconWrapper = styled.div<{ isOpenControlMenu: boolean }>` display: flex; svg circle { opacity: ${({isOpenControlMenu}) => (isOpenControlMenu && "0.29")}; } `; const StyledControlMenu = styled.div` display: flex; flex-wrap: wrap; position: absolute; gap: 9px; right: 0; bottom: -83px; width: 83px; height: 83px; padding: 5px; box-sizing: border-box; z-index: 2; background-color: #FFF; a, div { width: 32px; height: 32px; cursor: pointer; border-radius: 50%; &:hover { box-shadow: 3px 5px 10px rgba(0, 0, 0, 0.12); } svg { width: 32px; height: 32px; } } `; interface IProps { profileData: IProfile; setUserCard: (userId: number) => void; updateDataHandler: (userId: number, action?: string) => void; updatedUserLoader: { id: number, action: string}; setUpdatedUserLoader: (obj: IUserLoader) => void; } const UserCheck = React.memo( ({ profileData, setUserCard, updateDataHandler, updatedUserLoader, setUpdatedUserLoader }: IProps) => { const {t} = useTranslation(); const dispatch = useDispatch(); const [isOpenControlMenu, setIsOpenControlMenu] = useState<boolean>(false); const { id, main_photo, age, city, distance, online, user_name } = profileData; const [setDeleteProfile] = useAdminDeleteProfileMutation(); const [setBlockProfile] = useAdminBlockProfileMutation(); const banProfileHandler = useCallback(() => { setUpdatedUserLoader({id: profileData.id, action: "block"}); setBlockProfile(profileData.id).then(() => { updateDataHandler(profileData.id); }); }, [setBlockProfile]); const deleteProfileHandler = useCallback(() => { setDeleteProfile(profileData.id).then(() => { dispatch(removeFeedData()); }) }, [dispatch, setDeleteProfile]); const openControlMenuHandler = useCallback(() => { updateDataHandler(profileData.id) setIsOpenControlMenu(prev => !prev); }, [updateDataHandler, setIsOpenControlMenu]); const updateData = useCallback(() => { updateDataHandler(profileData.id, "update"); setUpdatedUserLoader({id: profileData.id, action: "update"}); }, [updateDataHandler, setUpdatedUserLoader]); return ( <StyledWrapper> <StyledWrapperCard> <img src={main_photo ? `${hostUrl}${main_photo.url}` : avatar} alt="user photo"/> <StyledMainBox> <StyledTitle> <StyledName>{user_name}</StyledName>,<StyledAge>{age}</StyledAge> </StyledTitle> <StyledLocation> <LocationIcon/> <span>{city?.name}, {distance}km away</span> </StyledLocation> {online !== true ? <StyledLastView> {t("last_view")}: <span>{getLastOnlineTime(online)}</span> </StyledLastView> : <StyledOnline>Online</StyledOnline>} </StyledMainBox> <StyledControlBox> <StyledInfoIconWrapper onClick={() => setUserCard(id)}> <InfoCircleIcon stroke="#FFF"/> </StyledInfoIconWrapper> <div onClick={() => updateDataHandler(profileData.id, "call")}> <CallIcon/> </div> <EllipsisIconWrapper onClick={openControlMenuHandler} isOpenControlMenu={isOpenControlMenu}> <EllipsisIcon/> </EllipsisIconWrapper> </StyledControlBox> </StyledWrapperCard> {isOpenControlMenu && <StyledControlMenu> <a href={`mailto:${profileData.admin_data?.email}`}> <EmailIcon/> </a> {updatedUserLoader.id === profileData.id && updatedUserLoader.action === "block" ? <div><Loader2/></div> : <div onClick={banProfileHandler}> <BanIcon fill={profileData?.admin_data?.is_active === false ? "#f35b5b" : "#2A9B9F"}/> </div> } <div onClick={deleteProfileHandler}><TrashIcon/></div> {updatedUserLoader.id === profileData.id && updatedUserLoader.action === "update" ? <div><Loader2/></div> : <div onClick={updateData}> <ReloadIcon/> </div> } </StyledControlMenu>} </StyledWrapper> ); }); export default UserCheck;