Skip to content

Commit

Permalink
[#35] feat : Add function which edits issue title
Browse files Browse the repository at this point in the history
  • Loading branch information
Seohyoung committed Jun 23, 2021
1 parent 538bfb7 commit ab38ae6
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 44 deletions.
125 changes: 115 additions & 10 deletions FE/frontend/src/components/main/issue/IssueDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,66 @@
import React from 'react';
import React, { useState } from 'react';
import styled from 'styled-components';
import { useLocation } from 'react-router-dom';
import moment from 'moment';
import 'moment/locale/ko';
import { useMutation, useQueryClient } from 'react-query';
import useMutate from '../../../util/useMutate';
import useFetch from '../../../util/useFetch';
import User from '../../../styles/atoms/User';
import Buttons from '../../../styles/atoms/Buttons';
import { ReactComponent as AlertCircle } from '../../../icons/alertCircle.svg';
import { ReactComponent as XSquare } from '../../../icons/xSquare.svg';
import { ReactComponent as Edit } from '../../../icons/edit.svg';

const IssueDetail = () => {
const queryClient = useQueryClient();
const location = useLocation();
const { isLoading, data, error } = useFetch('issue', 'detail', {
id: location.pathname,
});
const { mutateAsync, isError, isSuccess } = useMutation(
useMutate('issue', 'editTitle')
);

const [isEditOpen, setIsEditOpen] = useState(false);
const [editedTitle, setEditedTitle] = useState(data?.title);
const setEditOpen = () => {
setIsEditOpen(!isEditOpen);
};

const editTitle = async (id: number) => {
await mutateAsync({ data: editedTitle, id: id });

if (isSuccess) {
queryClient.invalidateQueries(['issue', 'detail']);
setEditOpen();
}
};

return (
<>
{data && (
<LabelListContainer>
<TopContainer>
<InfoContainer>
<div>
<Title>{data.title}</Title> <Id>#{data.id}</Id>
</div>
<TitleContainer>
{!isEditOpen && (
<>
<Title>{data.title}</Title> <Id>#{data.id}</Id>
</>
)}
{isEditOpen && (
<>
<label htmlFor="editTitle">제목</label>
<EditTitle
id="editTitle"
value={editedTitle}
onChange={e => {
setEditedTitle(e.target.value);
}}></EditTitle>
</>
)}
</TitleContainer>
<LowerTitleContainer>
<IssueStatus>
<AlertCircle />
Expand All @@ -36,12 +74,39 @@ const IssueDetail = () => {
</LowerTitleContainer>
</InfoContainer>
<ButtonContainer>
<Buttons small detail>
제목 편집
</Buttons>
<Buttons small detail>
이슈 닫기
</Buttons>
<div>
{!isEditOpen && (
<>
<Buttons small detail onClick={setEditOpen}>
제목 편집
</Buttons>
<Buttons small detail>
이슈 닫기
</Buttons>
</>
)}
{isEditOpen && (
<>
<Buttons small detail onClick={setEditOpen}>
<XSquareWrapper>
<XSquare />
</XSquareWrapper>
편집 취소
</Buttons>
<Buttons
small
initial
onClick={(e: Event) => {
editTitle(data.id);
}}>
<EditWrapper>
<Edit />
</EditWrapper>
편집 완료
</Buttons>
</>
)}
</div>
</ButtonContainer>
</TopContainer>
<Line />
Expand Down Expand Up @@ -82,6 +147,16 @@ const Line = styled.div`

const InfoContainer = styled.div``;

const TitleContainer = styled.div`
position: relative;
& > label {
color: ${props => props.theme.greyscale.label};
position: absolute;
left: 3%;
top: 30%;
}
`;

const Title = styled.span`
font-size: 32px;
padding-right: 20px;
Expand All @@ -90,6 +165,18 @@ const Title = styled.span`
color: ${props => props.theme.greyscale.titleActive};
`;

const EditTitle = styled.input`
display: flex;
align-items: center;
padding-left: 12%;
font-size: ${props => props.theme.fontSize.sm};
color: ${props => props.theme.greyscale.titleActive};
width: 940px;
height: 40px;
background: ${props => props.theme.greyscale.inputBackground};
border-radius: 11px;
`;

const Id = styled.span`
font-size: 32px;
color: ${props => props.theme.greyscale.label};
Expand Down Expand Up @@ -127,7 +214,25 @@ const TopContainer = styled.div`
const ButtonContainer = styled.div`
display: flex;
& > div {
display: flex;
margin-left: 10px;
& > div {
margin-left: 10px;
}
}
`;

const XSquareWrapper = styled.div`
padding-right: 8px;
svg {
stroke: ${props => props.theme.colors.primary};
}
`;

const EditWrapper = styled.div`
padding-right: 8px;
svg {
stroke: ${props => props.theme.greyscale.offWhite};
}
`;

Expand Down
1 change: 1 addition & 0 deletions FE/frontend/src/components/main/issue/IssueTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import User from '../../../styles/atoms/User';
import { ReactComponent as AlertCircle } from '../../../icons/alertCircle.svg';
import { ReactComponent as Archive } from '../../../icons/archive.svg';
import { ReactComponent as MilestoneIcon } from '../../../icons/milestone.svg';
import { ChangeEvent } from 'react';

const IssueTable = () => {
const { isLoading, data, error } = useFetch('issue', 'getAllData');
Expand Down
2 changes: 1 addition & 1 deletion FE/frontend/src/components/main/label/NewLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const NewLabel = () => {
const { mutateAsync, isError } = useMutation(useMutate('label', 'add'));

const registerNewLabel = async () => {
await mutateAsync(input);
await mutateAsync({ data: input });
};

return (
Expand Down
12 changes: 8 additions & 4 deletions FE/frontend/src/styles/atoms/CheckBox.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import React from 'react';
import React, { ChangeEvent } from 'react';
import styled from 'styled-components';

const CheckBox = () => {
const foo = (e: ChangeEvent<HTMLInputElement>) => {
console.log(e.target.checked);
};

return (
<>
<Box type="checkbox" />
</>
<div>
<Box type="checkbox" onChange={foo} />
</div>
);
};

Expand Down
93 changes: 64 additions & 29 deletions FE/frontend/src/util/useMutate.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,70 @@
import axios from 'axios';
const url = 'http://52.78.35.48/api';

const useMutate = (type: string, action: string) => async (data: unknown) => {
const axiosConfig = {
headers: {
'Content-Type': 'application/json;charset=UTF-8',
Authorization: 'Bearer ' + localStorage.getItem('token'),
},
};
interface Props {
data: unknown;
id?: number;
}

const useMutate =
(type: string, action: string) =>
async ({ data, id }: Props) => {
const axiosConfig = {
headers: {
'Content-Type': 'application/json;charset=UTF-8',
Authorization: 'Bearer ' + localStorage.getItem('token'),
},
};

switch (type) {
case 'issue':
switch (action) {
case 'add':
return axios.post(`${url}/issues`, data, axiosConfig);
}
return;
case 'label':
switch (action) {
case 'add':
return axios.post(`${url}/labels`, data, axiosConfig);
}
return;
case 'milestone':
switch (action) {
}
return;
case 'common':
switch (action) {
}
}
};
switch (type) {
case 'issue':
switch (action) {
case 'add':
return axios.post(`${url}/issues`, data, axiosConfig);
case 'close':
return axios.post(`${url}/issues/close`, data, axiosConfig);
case 'open':
return axios.post(`${url}/issues/open`, data, axiosConfig);
case 'delete':
return axios.delete(`${url}/issues/${id}`, axiosConfig);
case 'editTitle':
return axios.patch(
`${url}/issues/${id}/title`,
{
title: data,
},
axiosConfig
);
case 'editAssignees':
return axios.patch(
`${url}/issues/${id}/assignees`,
data,
axiosConfig
);
case 'editLabels':
return axios.patch(`${url}/issues/${id}/labels`, data, axiosConfig);
case 'editMilestones':
return axios.patch(
`${url}/issues/${id}/milestones`,
data,
axiosConfig
);
}
return;
case 'label':
switch (action) {
case 'add':
return axios.post(`${url}/labels`, data, axiosConfig);
}
return;
case 'milestone':
switch (action) {
}
return;
case 'common':
switch (action) {
}
}
};

export default useMutate;

0 comments on commit ab38ae6

Please sign in to comment.