PhotoComponent

김종민·2022년 5월 6일
0

insta-reactJS

목록 보기
16/27

insta에서 사진을 보여주는 component
photo.js 라는 component가 Home.js에서 props들을 받아서 뿌려줌.

1. src/components/Photo.js

import { gql, useMutation } from '@apollo/client'
import styled from 'styled-components'
import Avatar from './Avatar'
import { FatText } from './shared'
import { faHeart as SolidHeart } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import {
  faHeart,
  faComment,
  faPaperPlane,
  faBookmark,
} from '@fortawesome/free-regular-svg-icons'
import { FEED_QUERY } from '../screens/Home'
///좋아요를 누른 다음에 바로 refetchQueries하기 위해서 FEED_QUERY를 볼러옴.


const TOGGLE_LIKE_MUTATION = gql`
  mutation toggleLike($id: Int!) {
    toggleLike(id: $id) {
      ok
      error
    }
  }
`
///backend에서 만든 togglgeLike Mutation을 불러다 사용함.
///좋아요 누르는거거~

const PhotoContainer = styled.div`
  background-color: white;
  border: 1px solid ${(props) => props.theme.borderColor};
  margin-bottom: 20px;
  max-width: 615px;
`
///전제 container


const PhotoHeader = styled.div`
  padding: 15px;
  display: flex;
  align-items: center;
  border-bottom: 1px solid ${(props) => props.theme.borderColor};
`
///맨위에 아바타 사진이랑 username들어가는 부분.
///align-items는 세로에서 center
///justify-content는 가로에서 center

const Username = styled(FatText)`
  margin-left: 5px;
  font-size: 20px;
`
///photoHeader부분의 username, FatText는 shared.utils.js에서 만들어 놓음

const PhotoFile = styled.img`
  min-width: 100%;
  max-width: 100%;
`
//사진뿌려주는 부분, min-width: 100% ,max-width:100% 하면, 알아서 맞게 사진이 들어감.

const PhotoData = styled.div`
  padding: 15px;
  border-top: 1px solid ${(props) => props.theme.borderColor};
`
///사진밑에 하트, 비행기, 댓글등이 들어가는 부분.

const PhotoActions = styled.div`
  display: flex;
  align-items: cneter;
  justify-content: space-between;

  div {
    display: flex;
    align-items: center;
  }
`
///하트, 비행기, 댓글등이 들어가는 Icon들을 통으로 담아줌.

const PhotoAction = styled.div`
  margin-right: 15px;
  cursor: pointer;
`
//Icon들 하나하나에 대한 CSS

const Likes = styled(FatText)`
  margin-top: 15px;
  display: block;
`
///2 likes를 표현하는 CSS

const Photo = ({ id, user, file, isLiked, likes }) => {
/// Home.js로 부터 id, user, file, isLiked, likes를 props로 받음.

  const [toggleLike, { loading }] = useMutation(TOGGLE_LIKE_MUTATION, {
    variables: {
      id,
    },
    ///useMutation사용시, react-hook-form과 연결안되었을 때는, 여기에 바로,
    ///variables를 넣어버림.
    refetchQueries: [{ query: FEED_QUERY }],
  })
  ///위에서 만든 toggleLike mutation을 사용함,
  ///refetchQueries는 좋아요를 누른 다음에 바로 SEE_FEED Query를 불러옴
  
  return (
    <div>
      <PhotoContainer key={id}>
      ///key를 반드시 넣어야 하며, key는 HOME.js에서 보내준 photo.id 임.
      
        <PhotoHeader>
          <Avatar lg url={user.avatar} />
          <Username>{user.username}</Username>
          ///Home.js에서 user를 받음.
          
        </PhotoHeader>
        <PhotoFile src={file} />
        ///Home.js에서 file을 props로 받음.
        
        <PhotoData>
          <PhotoActions>
            <div>
              <PhotoAction onClick={toggleLike}>
              ///heart를 누르면 toggleLike Mutation이 실행됨.
              
                <FontAwesomeIcon
                  style={{ color: isLiked ? 'tomato' : 'inherit' }}
                  ///server에서 만든 isLikes computed Fileld로 내가 like를
                  ///눌렀으면 색이 tomato 아니면 원래색으로~
                  
                  size={'2x'}
                  icon={isLiked ? SolidHeart : faHeart}
                  ///내가 좋아요 눌렀으면 색이 채워진 SolidHeart로 아님 테두리만~
                  
                />
              </PhotoAction>
              <PhotoAction>
                <FontAwesomeIcon size={'2x'} icon={faComment} />
              </PhotoAction>
              <PhotoAction>
                <FontAwesomeIcon size={'2x'} icon={faPaperPlane} />
              </PhotoAction>
            </div>
            <div style={{ marginRight: '15px' }}>
              <FontAwesomeIcon size={'2x'} icon={faBookmark} />
            </div>
            ///PhotoActions를 <div>2개로 만들어 between으로 양쪽에 배치
            
            
          </PhotoActions>
          <Likes>{likes === 1 ? '1 likes' : `${likes} likes`}</Likes>
          ///likes를 Home.js에서 props로 받아와 뿌려줌...
          
        </PhotoData>
      </PhotoContainer>
    </div>
  )
}
export default Photo

2. src/screens/Home.js

import useUser from '../hooks/useUser'
import { gql, useQuery } from '@apollo/client'
import Photo from '../components/Photo'

export const FEED_QUERY = gql`
  query seeFeed {
    seeFeed {
      id
      user {
        username
        avatar
      }
      file
      caption
      likes
      comments
      createdAt
      isMine
      isLiked
    }
  }
`
///seeFeed Query, Photo.js에서도 사용할 예정이라 export 해줌.

const Home = () => {
  const User = useUser()
  ///useUser hook을 이용해서 User의 정보를 받아옴
  
  console.log(User)
  const { data } = useQuery(FEED_QUERY)
  ///useQuery로 seeFeed Query를 실행한 다음, data를 불러옴.
  
  return (
    <div>
      {data?.seeFeed?.map((photo) => (
        <Photo
          key={photo.id}
          id={photo.id}
          user={photo.user}
          file={photo.file}
          isLiked={photo.isLiked}
          likes={photo.likes}
        />
      ))}
      ///seeFeed로 불러온 data들을 Photo.js component에 보내줌.
      
    </div>
  )
}

export default Home

3. photo.resolvers.js(isLiked, likes)

import prisma from '../client'

export default {
  Photo: {
    user: ({ userId }) => prisma.user.findUnique({ where: { id: userId } }),
    hashtags: ({ id }) =>
      prisma.hashtag.findMany({
        where: {
          photos: { some: { id } },
        },
      }),
    likes: ({ id }) => prisma.like.count({ where: { photoId: id } }),
    comments: ({ id }) => prisma.comment.count({ where: { photoId: id } }),
    isMine: ({ userId }, _, { loggedInUser }) => {
      if (!loggedInUser) {
        return false
      }
      return userId === loggedInUser.id
    },
    isLiked: async ({ id }, _, { loggedInUser }) => {
      if (!loggedInUser) {
        return false
      }
      const ok = await prisma.like.findUnique({
        where: {
          photoId_userId: {
            photoId: id,
            userId: loggedInUser.id,
          },
        },
        ///like DB에서 photoId와 userId를 찾아서 존재하면 true를 return
        ///그래서 computer Field가 조르 중요한 것임.
        select: { id: true },
      })
      if (ok) {
        return true
      }
      return false
    },
  },
profile
코딩하는초딩쌤

0개의 댓글