From 30658806095302540d3425d9ea98cf45d3b0c9ae Mon Sep 17 00:00:00 2001 From: chaKK Date: Mon, 19 Feb 2024 02:10:34 +0900 Subject: [PATCH] =?UTF-8?q?Feat:=20=EB=A9=94=EC=9D=B4=ED=8A=B8=20=EA=B7=9C?= =?UTF-8?q?=EC=B9=99=20=EC=83=81=EC=84=B8=EB=B3=B4=EA=B8=B0,=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20=EC=88=98=EC=A0=95=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=8A=A4=EC=BC=88=EB=A0=88?= =?UTF-8?q?=ED=86=A4=20UI=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mate/ruleCheck/MateRuleDetailCheck.jsx | 97 +++++------ .../MateRuleDetailSkeleton.jsx | 30 ++++ .../MateRuleDetailSkeleton.style.js | 151 +++++++++++++++++ src/pages/mate/ruleEdit/RuleEdit.jsx | 135 ++++++++------- .../RuleEditSkeleton/RuleEditSkeleton.jsx | 25 +++ .../RuleEditSkeleton.style.js | 156 ++++++++++++++++++ 6 files changed, 485 insertions(+), 109 deletions(-) create mode 100644 src/pages/mate/ruleCheck/MateRuleDetailSkeleton/MateRuleDetailSkeleton.jsx create mode 100644 src/pages/mate/ruleCheck/MateRuleDetailSkeleton/MateRuleDetailSkeleton.style.js create mode 100644 src/pages/mate/ruleEdit/RuleEditSkeleton/RuleEditSkeleton.jsx create mode 100644 src/pages/mate/ruleEdit/RuleEditSkeleton/RuleEditSkeleton.style.js diff --git a/src/pages/mate/ruleCheck/MateRuleDetailCheck.jsx b/src/pages/mate/ruleCheck/MateRuleDetailCheck.jsx index 4f2a47bf..76e46f81 100644 --- a/src/pages/mate/ruleCheck/MateRuleDetailCheck.jsx +++ b/src/pages/mate/ruleCheck/MateRuleDetailCheck.jsx @@ -2,6 +2,7 @@ import React, { useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import * as S from './MateRuleDetailCheck.style'; +import MateRuleDetailSkeleton from './MateRuleDetailSkeleton/MateRuleDetailSkeleton'; import Logo from '/images/mypage/MyPageLogo.svg'; import MateCommentList from '@/components/comment/mate/MateCommentList'; import MateCommentInput from '@/components/comment/mate/commentInput/MateCommentInput'; @@ -14,60 +15,62 @@ const MateRuleDetailCheckPage = () => { const navigate = useNavigate(); - if (loading) { - return
로딩 중 입니다..
; - } - if (error) { return
에러가 발생했습니다.
; } return ( - - - - {data?.mainTitle} - - {data?.detailMembers?.slice(0, 5).map(p => ( - - -

{p.name}

-
- ))} - {data?.detailMembers?.length > 5 && ( // - -

외 {data.detailMembers.length - 5} 명

-
- )} -
-
- - {data?.rulePairs?.map((rule, index) => ( - -

{rule.ruleTitle}

-

{rule.ruleDetail}

-
- ))} -
-
- {editMode ? ( - { - handleSubmit(); - setEditMode(false); - }}> - 저장하기 - + <> + {loading ? ( + ) : ( - navigate(`/mate/rule-edit/${ruleId}`)}> - 수정하기 - + + + + {data?.mainTitle} + + {data?.detailMembers?.slice(0, 5).map(p => ( + + +

{p.name}

+
+ ))} + {data?.detailMembers?.length > 5 && ( // + +

외 {data.detailMembers.length - 5} 명

+
+ )} +
+
+ + {data?.rulePairs?.map((rule, index) => ( + +

{rule.ruleTitle}

+

{rule.ruleDetail}

+
+ ))} +
+
+ {editMode ? ( + { + handleSubmit(); + setEditMode(false); + }}> + 저장하기 + + ) : ( + navigate(`/mate/rule-edit/${ruleId}`)}> + 수정하기 + + )} + + + + +
)} - - - - -
+ ); }; diff --git a/src/pages/mate/ruleCheck/MateRuleDetailSkeleton/MateRuleDetailSkeleton.jsx b/src/pages/mate/ruleCheck/MateRuleDetailSkeleton/MateRuleDetailSkeleton.jsx new file mode 100644 index 00000000..9a4d2153 --- /dev/null +++ b/src/pages/mate/ruleCheck/MateRuleDetailSkeleton/MateRuleDetailSkeleton.jsx @@ -0,0 +1,30 @@ +import * as S from './MateRuleDetailSkeleton.style'; + +const MateRuleDetailSkeleton = () => { + return ( + + + + + + + + + + + + + {new Array(5).fill(0).map(() => ( + + + + + ))} + + + + + ); +}; + +export default MateRuleDetailSkeleton; diff --git a/src/pages/mate/ruleCheck/MateRuleDetailSkeleton/MateRuleDetailSkeleton.style.js b/src/pages/mate/ruleCheck/MateRuleDetailSkeleton/MateRuleDetailSkeleton.style.js new file mode 100644 index 00000000..8aef318a --- /dev/null +++ b/src/pages/mate/ruleCheck/MateRuleDetailSkeleton/MateRuleDetailSkeleton.style.js @@ -0,0 +1,151 @@ +import styled, { keyframes } from 'styled-components'; + +import theme from '@/theme'; + +const skeletonGradient = keyframes` + 0% { + background-color: rgba(165, 165, 165, 0.1); + } + 50% { + background-color: rgba(165, 165, 165, 0.3); + } + 100% { + background-color: rgba(165, 165, 165, 0.1); + } +`; + +const Container = styled.div` + ${theme.ALIGN.COLUMN_CENTER}; +`; + +const Wrapper = styled.div` + width: 80%; + height: 900px; + + border-radius: 20px; + padding: 20px; + + &::-webkit-scrollbar { + width: 4px; + } + &::-webkit-scrollbar-thumb { + border-radius: 20px; + } + animation: ${skeletonGradient} 1.5s infinite; +`; + +const Header = styled.div` + ${theme.ALIGN.COLUMN_CENTER}; + gap: 20px; +`; + +const Title = styled.div` + width: 200px; + padding: 15px; + border-radius: 20px; + animation: ${skeletonGradient} 1.5s infinite; +`; + +const ProfileContainer = styled.div` + ${theme.ALIGN.ROW_CENTER}; +`; + +const ProfileBox = styled.div` + ${theme.ALIGN.COLUMN_CENTER}; + margin-right: 10px; +`; + +const ProfileImages = styled.div` + border-radius: 50%; + width: 40px; + height: 40px; + margin-bottom: 10px; + object-fit: cover; + animation: ${skeletonGradient} 1.5s infinite; +`; + +const Content = styled.div` + width: 100%; + height: 100%; + padding: 15px; + border-radius: 20px; + margin-top: 20px; +`; + +const TextContainer = styled.div` + ${theme.ALIGN.COLUMN_CENTER}; + padding: 10px; + gap: 5px; + align-items: flex-start; + margin-bottom: 20px; +`; + +const ContentTextInput = styled.textarea` + width: 80%; + padding: 9px; + border: none; + resize: none; + font-size: 0.8rem; + color: ${theme.COLOR.MAIN.GRAY}; +`; + +const AddButtonWrapper = styled.div` + ${theme.ALIGN.ROW_CENTER} +`; + +const AddQuestionButton = styled.button` + width: 120px; + height: 40px; + border: none; + border-radius: 10px; + background-color: ${theme.COLOR.MAIN.LIGHT_GREEN}; + cursor: pointer; + + &:hover { + transform: scale(0.9); + } + animation: ${skeletonGradient} 1.5s infinite; +`; + +const UpdateBtn = styled.button` + border: none; + width: 200px; + height: 50px; + margin-top: 20px; + border-radius: 20px; + + animation: ${skeletonGradient} 1.5s infinite; +`; + +const CommentsContainer = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + width: 100%; + padding: 20px 40px; +`; + +const Text = styled.div` + width: 50%; + padding: 10px; + border-radius: 20px; + animation: ${skeletonGradient} 1.5s infinite; +`; + +export { + Container, + Wrapper, + ProfileBox, + ProfileContainer, + ProfileImages, + Header, + Content, + TextContainer, + Title, + ContentTextInput, + AddButtonWrapper, + AddQuestionButton, + UpdateBtn, + CommentsContainer, + Text, +}; diff --git a/src/pages/mate/ruleEdit/RuleEdit.jsx b/src/pages/mate/ruleEdit/RuleEdit.jsx index 1388e087..bbb435e4 100644 --- a/src/pages/mate/ruleEdit/RuleEdit.jsx +++ b/src/pages/mate/ruleEdit/RuleEdit.jsx @@ -2,7 +2,9 @@ import { useEffect, useState } from 'react'; import { toast } from 'react-hot-toast'; import { useNavigate, useParams } from 'react-router-dom'; +import MateRuleDetailSkeleton from '../ruleCheck/MateRuleDetailSkeleton/MateRuleDetailSkeleton'; import * as S from './RuleEdit.style'; +import RuleEditSkeleton from './RuleEditSkeleton/RuleEditSkeleton'; import PlusUser from '/images/mate/add-user.svg'; import Logo from '/images/mypage/MyPageLogo.svg'; import { updateTeamMateRule } from '@/apis/request/mate'; @@ -99,68 +101,77 @@ const RuleEditPage = () => { }; return ( - - - - - - setPostData({ ...postData, mainTitle: e.target.value }) - } - placeholder="규칙 제목을 입력해주세요." - /> - inviteMatesModal.onOpen()} /> - - - {selectedMates.map(s => ( - <> - - - ))} - - - {postData.rulePairs.map((rule, index) => ( - - - { - const newRulePairs = [...postData.rulePairs]; - newRulePairs[index].ruleTitle = e.target.value; - setPostData({ ...postData, rulePairs: newRulePairs }); - }} - /> - { - const newRulePairs = [...postData.rulePairs]; - newRulePairs[index].ruleDetail = e.target.value; - setPostData({ ...postData, rulePairs: newRulePairs }); - }} - rows="5" - columns="2" - /> - handleRemoveRule(index)}> - X - - - - ))} - - - {postData.rulePairs.length < 10 && ( - - 규칙 추가하기 - - )} - - - 수정하기 - {isLoading && } - + <> + {loading ? ( + + ) : ( + + + + + + setPostData({ ...postData, mainTitle: e.target.value }) + } + placeholder="규칙 제목을 입력해주세요." + /> + inviteMatesModal.onOpen()} + /> + + + {selectedMates.map(s => ( + <> + + + ))} + + + {postData.rulePairs.map((rule, index) => ( + + + { + const newRulePairs = [...postData.rulePairs]; + newRulePairs[index].ruleTitle = e.target.value; + setPostData({ ...postData, rulePairs: newRulePairs }); + }} + /> + { + const newRulePairs = [...postData.rulePairs]; + newRulePairs[index].ruleDetail = e.target.value; + setPostData({ ...postData, rulePairs: newRulePairs }); + }} + rows="5" + columns="2" + /> + handleRemoveRule(index)}> + X + + + + ))} + + + {postData.rulePairs.length < 10 && ( + + 규칙 추가하기 + + )} + + + 수정하기 + {isLoading && } + + )} + ); }; diff --git a/src/pages/mate/ruleEdit/RuleEditSkeleton/RuleEditSkeleton.jsx b/src/pages/mate/ruleEdit/RuleEditSkeleton/RuleEditSkeleton.jsx new file mode 100644 index 00000000..294e50da --- /dev/null +++ b/src/pages/mate/ruleEdit/RuleEditSkeleton/RuleEditSkeleton.jsx @@ -0,0 +1,25 @@ +import * as S from './RuleEditSkeleton.style'; + +const RuleEditSkeleton = () => { + return ( + + + + + + + + + + + + + + + + + + ); +}; + +export default RuleEditSkeleton; diff --git a/src/pages/mate/ruleEdit/RuleEditSkeleton/RuleEditSkeleton.style.js b/src/pages/mate/ruleEdit/RuleEditSkeleton/RuleEditSkeleton.style.js new file mode 100644 index 00000000..60d03bc7 --- /dev/null +++ b/src/pages/mate/ruleEdit/RuleEditSkeleton/RuleEditSkeleton.style.js @@ -0,0 +1,156 @@ +import styled, { keyframes } from 'styled-components'; + +import theme from '@/theme'; + +const skeletonGradient = keyframes` + 0% { + background-color: rgba(165, 165, 165, 0.1); + } + 50% { + background-color: rgba(165, 165, 165, 0.3); + } + 100% { + background-color: rgba(165, 165, 165, 0.1); + } +`; + +const Container = styled.div` + ${theme.ALIGN.COLUMN_CENTER}; +`; + +const Wrapper = styled.div` + width: 80%; + height: 900px; + overflow-y: scroll; + + border-radius: 20px; + padding: 20px; + animation: ${skeletonGradient} 1.5s infinite; +`; + +const Header = styled.div` + ${theme.ALIGN.COLUMN_CENTER}; + gap: 20px; + + h1 { + ${theme.ALIGN.ROW_CENTER}; + } +`; + +const TitleInput = styled.div` + padding: 20px; + width: 60%; + border-radius: 20px; + animation: ${skeletonGradient} 1.5s infinite; +`; + +const PlusSvg = styled.div` + width: 25px; + height: 25px; + border-radius: 20px; + margin-bottom: 20px; + animation: ${skeletonGradient} 1.5s infinite; +`; + +const MatesContainer = styled.div` + ${theme.ALIGN.ROW_CENTER}; + gap: 2px; + margin-bottom: 20px; +`; + +const MatesImages = styled.div` + width: 30px; + height: 30px; + margin-bottom: 10px; + border-radius: 50%; + animation: ${skeletonGradient} 1.5s infinite; +`; + +const Content = styled.div` + ${theme.ALIGN.COLUMN_CENTER}; + gap: 20px; + margin-top: 20px; +`; + +const ContentBox = styled.div` + ${theme.ALIGN.ROW_CENTER}; + + width: 300px; + height: 100px; + border-radius: 20px; + animation: ${skeletonGradient} 1.5s infinite; +`; + +const TextContainer = styled.div` + position: relative; + display: flex; + flex-direction: column; + gap: 10px; +`; + +const DeleteRuleButton = styled.div` + position: absolute; + top: 23px; + right: -90px; + width: 30px; + height: 30px; + border: none; + border-radius: 10px; + animation: ${skeletonGradient} 1.5s infinite; +`; + +const ContentTitleInput = styled.div` + width: 200px; + border-radius: 20px; + padding: 15px; + border: none; + animation: ${skeletonGradient} 1.5s infinite; +`; + +const ContentTextInput = styled.div` + width: 80%; + padding: 9px; + animation: ${skeletonGradient} 1.5s infinite; +`; + +const AddButtonWrapper = styled.div` + ${theme.ALIGN.ROW_CENTER}; + margin-top: 100px; +`; + +const AddQuestionButton = styled.div` + width: 120px; + height: 40px; + border: none; + border-radius: 10px; + + animation: ${skeletonGradient} 1.5s infinite; +`; + +const SubmitBtn = styled.div` + border: none; + width: 200px; + height: 50px; + margin-top: 20px; + border-radius: 20px; + animation: ${skeletonGradient} 1.5s infinite; +`; + +export { + Container, + Wrapper, + PlusSvg, + MatesContainer, + MatesImages, + Header, + Content, + ContentBox, + TextContainer, + TitleInput, + ContentTextInput, + ContentTitleInput, + DeleteRuleButton, + AddButtonWrapper, + AddQuestionButton, + SubmitBtn, +};