[ react ] 활동게시판 만들기 (feat. Pagination mui & 좋아요누르기)

Suji Kang·2023년 10월 25일
0
post-thumbnail
post-custom-banner

🐾 하나의 Card component 를 만들어보자

activityCard.js

import { CardLikeButton, CardImg, CardWrap, CardContent, CardTitle, CardDetail } from "../../styles/dashboard/activityCard.styles";
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
import FavoriteIcon from '@mui/icons-material/Favorite';

const ActivityCard = () => {
    return (
        <CardWrap>
            <CardImg>
              <CardCheckBox type="checkbox"/>
            </CardImg> 
        	<CardContent>
                <CardTitle>유기견 봉사활동</CardTitle>
                <CardDetail>강아지들과 함께 34일 동안 잊을 수 없는 경험을 했으며 동물에 대한 소중함을 느낄 수 있는 순간이었습니다.</CardDetail>
              	<CardDetail>
                    작성자: abc@test.com
                </CardDetail>
                <CardDetail>
                    작성일자: 2023-05-15
                </CardDetail>
                <CardDetail>
                    좋아요: 54
                </CardDetail>
              	<button>자세히 보기</button>
            </CardContent>
        </CardWrap>
    );
}

export default ActivityCard;

activityCard.styles.js

import styled from "@emotion/styled";

export const CardWrap = styled.div`
    box-shadow: 3px 4px 12px rgba(0, 0, 0, 0.08);
    border-radius: 6px;
    overflow: hidden;
    width: 350px;
`;

export const CardImg = styled.div`
    background-image: url('activity-default.jpg');
    height: 250px;
    background-repeat: no-repeat;
    background-position: center;
    background-size: cover;

    position: relative;
`;

export const CardContent = styled.div`
    padding: 15px 20px;
`;

export const CardTitle = styled.h2`
    font-size: 18px;
    color: black;
    margin: 5px 0;
`;

export const CardDetail = styled.p`
    font-size: 16px;
    color: silver;
    margin: 5px 0;
`;

export const CardLikeButton = styled.div`
    position: absolute;
    top: 20px;
    left: 20px;
`;

activity.js

import DashboardLayout from "../../components/common/layout";
import ActivityCard from "../../components/activity/ActivityCard";

const ActivityPage = ()=>{
  return(
    <DashboardLayout>
      <h1>활동 게시판 페이지 입니다</h1>
      <p>다양한 사람들의 다양한 활동을 경험해 보세요~</p>
      <section>
        <ActivityCard/> 
      </section>
    </DashboardLayout>
  );
}

export default ActivityPage;

📝 section을 하나의 input을 컴포넌트로 한번 나눠보자.

activity.styles.js

import styled from "@emotion/styled";

export const ActivitySectionHeader = styled.div`
    display: flex;
    column-gap: 10px;
    border-bottom: 1px solid silver;
    padding: 20px 0;
`;

export const ActivityInput = styled.input`
    flex-grow: 1;
    padding: 5px 10px;
`;

export const ActivitySelect = styled.select`

`;

export const ActivityWriteBtn = styled.button`
    flex-shrink: 0;
`;

activitySection.js

import { ActivityInput, ActivitySectionHeader, ActivitySelect, ActivityWriteBtn } from "../../styles/dashboard/activity.
const ActivitySection = ()=>{
  
return(
        <section>
            <ActivitySectionHeader>
                <ActivityInput/>
                <ActivitySelect>
                    <option>최신순</option>
                    <option>오래된순</option>
                    <option>좋아요순</option>
                    <option>조회수순</option>
                </ActivitySelect>
                <ActivityWriteBtn>글 쓰기</ActivityWriteBtn>
            </ActivitySectionHeader>
    	 </section>
  }


📝 여러 개의 컴포넌트를 조합하여 UI를 정의하고, 부모 컴포넌트에서 한 번에 반환된다.

activitySection.js

import ActivityCard from "./activityCard";
import { ActivityInput, ActivitySectionHeader, ActivitySelect, ActivityWriteBtn, ActivityBody} from "../../styles/dashboard/activity.

const ActivitySection = ()=>{
  
return(
        <section>
            <ActivitySectionHeader>
                <ActivityInput/>
                <ActivitySelect>
                    <option>최신순</option>
                    <option>오래된순</option>
                    <option>좋아요순</option>
                    <option>조회수순</option>
                </ActivitySelect>
                <ActivityWriteBtn>글 쓰기</ActivityWriteBtn>
            </ActivitySectionHeader>
    		<ActivityBody>
               <ActivityCard/>
               <ActivityCard/>
               <ActivityCard/>
            </ActivityBody>
    	 </section>
  }

activity.styles.js

import styled from "@emotion/styled";

export const ActivityBody = styled.div`
    padding: 50px 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 20px;
`;

<ActivityCard/>를 3번쓰니까 3개의 card가 나온다

🐾 Pagination MUI사용해보기

activitySection.js

import { Pagination } from "@mui/material";

const ActivitySection = ()=>{

    return(
        <section>
  			<ActivityFooter >
                <Pagination count={20}/>
            </ActivityFooter>
        </section>
    );
}

export default ActivitySection;

activity.styles.js

export const ActivityFooter = styled.div`
    display: flex;
    justify-content: center;
    ${(props)=>props.location === 'left' && 'justify-content:flex-start'}
    ${(props)=>props.location === 'right' && 'justify-content:flex-end'}
`;

count={20} 설정가능. MUI..너..너무나도 간단하다..😆


📝 개별 컴포넌트를 정의하고 외부에서 전달된 props를 사용하여 UI를 렌더링합니다.

activityCard.js

const ActivityCard = (props)=>{
  
   return (
 <CardContent>
                <CardTitle>{props.activity.title}</CardTitle>
                <CardDetail>
                    {props.activity.content}
                </CardDetail>
                <CardDetail>
                    작성자 : {props.activity.email}
                </CardDetail>
                <CardDetail>
                    작성일자 : {props.activity.createdDate}
                </CardDetail>
                <CardDetail>좋아요 : {props.activity.like}</CardDetail>
                <button>자세히 보기</button>
            </CardContent>
  );
}

export default ActivityCard;

📝 객체 activity안에 넣은것 유의! {props.activity.content} props.activity안에 content

activitySection.js

 <ActivityBody>
                <ActivityCard activity={{
                    title: '',
                    content: 'dfwefqf',
                    email: 'dd@dd.com',
                    createdDate: '2023-01-01',
                    like: 56,
                    imgURL: 'https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg'
                }} />
                <ActivityCard activity={{
                    title: '강아지 봉사활동',
                    content: '봉사활동은 재미있어요',
                    email: 'abc@dd.com',
                    createdDate: '2023-05-01',
                    like: 102,
                    imgURL: null
                }} />
 </ActivityBody>

이미지 받기.
이미지가 null 이면 이미지 기본값이 나온다.

activityCard.styles.js

import styled from "@emotion/styled";

export const CardImg = styled.div`
    background-image: url(${(props)=> props.imgURL === null ? 'activity-default.jpg' : props.imgURL});
    height: 250px;
    background-repeat: no-repeat;
    background-position: center;
    background-size: cover;

    position: relative;
`;

activityCard.js

const ActivityCard = (props)=>{
    console.log(props.activity.imgURL);
    
  return (
     <CardImg imgURL = { props.activity.imgURL }></CardImg>
    );


🐾 하트 좋아요 누르기

📝 state변수를 만들어보자

activityCard.styles.js

export const CardLikeButton = styled.div`
    position: absolute;
    top: 20px;
    left: 20px;
    cursor: pointer;
`;

activityCard.js

import React, { useState } from "react";

const ActivityCard = () => {
    const [isLiked, setIsLiked] = useState(false);

    return (
		<CardImg>
            <CardLikeButton onClick={() => { setIsLiked(!isLiked) }}>
                {isLiked ? <FavoriteIcon style={{color:'red'}} /> : <FavoriteBorderIcon />}
            </CardLikeButton>
        </CardImg>


🐾 데이터 테이블만들어서 테이블에서 가져오기 3:07

테이블이 3개가 필요.

# 활동게시물 테이블
create table tbl_activities(
   id int auto_increment primary key,
    title varchar(200) not null,
    content text not null,
    writer_email varchar(30) references tbl_users (email),
    created_date datetime default now() not null,
    updated_date datetime default now() not null
);
# 활동게시물 이미지 테이블
create table tbl_activity_img(
   activity_id int references tbl_activities(id) ,
    img_url varchar(500),
    constraint tbl_activity_img_pk primary key (activity_id , img_url)
);
# 활동게시물 좋아요 테이블
create table tbl_activity_like(
   activity_id int references tbl_activities(id),
    email varchar(30) references tbl_users(email),
    constraint tbl_activity_like_pk primary key (activity_id, email)
);

to be continued..🌟

profile
나를위한 노트필기 📒🔎📝
post-custom-banner

0개의 댓글