-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Feature/#44/project edit
- Loading branch information
Showing
14 changed files
with
894 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,279 @@ | ||
import * as Styles from "./styles"; | ||
import SelectStackType from "../SelectStackType/SelectStackType"; | ||
import NewpostEditor from "./MDEditor/MdeditorWriter"; | ||
import NewpostImages from "./ImageUpload/ImageUpload"; | ||
import { FaPlus, FaMinus } from "react-icons/fa"; | ||
import { Button } from "../ui/button"; | ||
import { useMutation, useQuery } from "@apollo/client"; | ||
import { useSelectStacks } from "@/stores/selectStackType/selectStacksStore"; | ||
import { useSelectTypes } from "@/stores/selectStackType/selectTypesStore"; | ||
import { | ||
ProjectCategory, | ||
getCategoryKey, | ||
} from "@/libs/enum/projectCategoryEnum"; | ||
import { useRouter } from "next/router"; | ||
import { useEffect } from "react"; | ||
import { useEditProject } from "@/stores/editProjectStore"; | ||
import { GET_PROJECT_BY_ID } from "@/services/gql/getProjectDetailById"; | ||
import { UPDATE_PROJECT } from "@/services/gql/updateProject"; | ||
|
||
interface EditProjectProps { | ||
projectId: number; | ||
categories: ProjectCategory[]; | ||
stackNames: string[]; | ||
} | ||
|
||
// 프로젝트 이름 | ||
function EditProjectName({ | ||
title, | ||
setTitle, | ||
}: { | ||
title: string; | ||
setTitle: (title: string) => void; | ||
}) { | ||
return ( | ||
<Styles.EditProjectCard> | ||
<Styles.EditProjectNameInput | ||
type="text" | ||
placeholder="프로젝트 이름을 입력하세요" | ||
value={title} | ||
onChange={(e) => setTitle(e.target.value)} | ||
></Styles.EditProjectNameInput> | ||
</Styles.EditProjectCard> | ||
); | ||
} | ||
|
||
// 한 줄 소개글 | ||
function EditProjectOneline({ | ||
bio, | ||
setBio, | ||
}: { | ||
bio: string; | ||
setBio: (bio: string) => void; | ||
}) { | ||
return ( | ||
<Styles.EditProjectCard> | ||
<Styles.EditProjectText>한 줄 소개글</Styles.EditProjectText> | ||
<Styles.EditProjectOnelineInput | ||
type="text" | ||
placeholder="한 줄 소개글" | ||
value={bio} | ||
onChange={(e) => setBio(e.target.value)} | ||
></Styles.EditProjectOnelineInput> | ||
</Styles.EditProjectCard> | ||
); | ||
} | ||
|
||
// 참고 링크 | ||
function EditProjectUrls({ | ||
urls, | ||
setUrls, | ||
}: { | ||
urls: string[]; | ||
setUrls: (urls: string[]) => void; | ||
}) { | ||
const addLink = () => { | ||
if (urls.length >= 3) { | ||
alert("링크는 최대 3개까지 등록 가능합니다"); | ||
return; | ||
} | ||
setUrls([...urls, ""]); | ||
}; | ||
const minusLink = (trg: number) => { | ||
setUrls(urls.filter((_, idx) => idx !== trg)); | ||
}; | ||
|
||
return ( | ||
<Styles.EditProjectCard> | ||
<Styles.EditProjectText>참고 링크</Styles.EditProjectText> | ||
<div style={{ display: "flex", flexDirection: "column", gap: "10px" }}> | ||
{urls.map((url, index) => ( | ||
<div key={index} style={{ display: "flex", gap: "10px" }}> | ||
<Styles.EditProjectOnelineInput | ||
type="text" | ||
value={url} | ||
placeholder="링크 입력 (https://github.com)" | ||
onChange={(e) => { | ||
const newLinks = [...urls]; | ||
newLinks[index] = e.target.value; | ||
setUrls(newLinks); | ||
}} | ||
></Styles.EditProjectOnelineInput> | ||
{index === 0 ? ( | ||
<Styles.EditProjectLinkBtn | ||
onClick={() => { | ||
addLink(); | ||
}} | ||
> | ||
<FaPlus /> | ||
</Styles.EditProjectLinkBtn> | ||
) : ( | ||
<Styles.EditProjectLinkBtn | ||
onClick={() => { | ||
minusLink(index); | ||
}} | ||
> | ||
<FaMinus /> | ||
</Styles.EditProjectLinkBtn> | ||
)} | ||
</div> | ||
))} | ||
</div> | ||
</Styles.EditProjectCard> | ||
); | ||
} | ||
|
||
function EditProjectRepresentativeImg({ | ||
imageUrls, | ||
setImageUrls, | ||
}: { | ||
imageUrls: string[]; | ||
setImageUrls: (imageUrls: string[]) => void; | ||
}) { | ||
return ( | ||
<Styles.EditProjectCard> | ||
<Styles.EditProjectText>대표 이미지</Styles.EditProjectText> | ||
<NewpostImages imageUrls={imageUrls} setImageUrls={setImageUrls} /> | ||
</Styles.EditProjectCard> | ||
); | ||
} | ||
|
||
function EditProjectButton({ | ||
projectId, | ||
categories, | ||
stackNames, | ||
}: EditProjectProps) { | ||
const categoryKeys = categories.map((category) => getCategoryKey(category)); | ||
const [editProject] = useMutation(UPDATE_PROJECT); | ||
const router = useRouter(); | ||
|
||
const { title, bio, urls, imageUrls, content, setUrls } = useEditProject(); | ||
|
||
return ( | ||
<Button | ||
style={{ fontSize: "20px", padding: "20px" }} | ||
onClick={async () => { | ||
setUrls(urls.filter((url) => url.trim() !== "" || url.trim() !== "")); | ||
try { | ||
const response = await editProject({ | ||
variables: { | ||
projectId, | ||
title, | ||
bio, | ||
urls, | ||
imageUrls, | ||
content, | ||
categories: categoryKeys, | ||
stackNames, | ||
}, | ||
fetchPolicy: "no-cache", | ||
}); | ||
if (response && response.data) { | ||
alert("프로젝트 수정이 완료되었습니다!"); | ||
router.push(`/project/${projectId}`); | ||
} | ||
} catch (err) { | ||
alert(err); | ||
} | ||
}} | ||
> | ||
프로젝트 수정 | ||
</Button> | ||
); | ||
} | ||
|
||
export default function EditProjectComponents() { | ||
const { | ||
title, | ||
bio, | ||
urls, | ||
imageUrls, | ||
content, | ||
|
||
setTitle, | ||
setBio, | ||
setUrls, | ||
setContent, | ||
setImageUrls, | ||
} = useEditProject(); | ||
const { | ||
stackToggle, | ||
selectedStacks, | ||
clickStackToggle, | ||
clickStack, | ||
resetStack, | ||
} = useSelectStacks(); | ||
const { typeToggle, selectedTypes, clickTypeToggle, clickType, resetType } = | ||
useSelectTypes(); | ||
|
||
useEffect(() => { | ||
if (stackToggle) { | ||
clickStackToggle(); | ||
} | ||
resetStack(); | ||
if (typeToggle) { | ||
clickTypeToggle(); | ||
} | ||
resetType(); | ||
}, [resetStack, resetType]); | ||
|
||
const router = useRouter(); | ||
const { id } = router.query; | ||
|
||
const { loading, error } = useQuery(GET_PROJECT_BY_ID, { | ||
variables: { projectId: parseInt(id as string) }, | ||
fetchPolicy: "no-cache", | ||
onCompleted: (fetchedData) => { | ||
const project = fetchedData.projectById; | ||
console.log(project); | ||
setTitle(project.title); | ||
console.log(project.bio); | ||
setBio(project.bio); | ||
setContent(project.content); | ||
setImageUrls(project.imageUrls); | ||
if (project.urls.length > 0) { | ||
setUrls(project.urls); | ||
} | ||
|
||
if (project.stacks !== undefined) { | ||
project.stacks.array.forEach((stack: string) => { | ||
clickStack(stack); | ||
}); | ||
} | ||
if (project.categories !== undefined) { | ||
project.categories.array.forEach((category: ProjectCategory) => { | ||
clickType(category); | ||
}); | ||
} | ||
}, | ||
}); | ||
|
||
if (loading) return; | ||
if (error) | ||
return <p style={{ margin: "20px 20px" }}>Error: {error.message}</p>; | ||
|
||
return ( | ||
<Styles.EditProjectContainer> | ||
<EditProjectName title={title} setTitle={setTitle} /> | ||
<Styles.EditProjectText> | ||
기술 스택 및 프로젝트 구분 | ||
</Styles.EditProjectText> | ||
<SelectStackType /> | ||
<EditProjectOneline bio={bio} setBio={setBio} /> | ||
<EditProjectUrls urls={urls} setUrls={setUrls} /> | ||
<Styles.EditProjectCard> | ||
<Styles.EditProjectText>프로젝트 소개</Styles.EditProjectText> | ||
<NewpostEditor content={content} setContent={setContent} /> | ||
</Styles.EditProjectCard> | ||
<EditProjectRepresentativeImg | ||
imageUrls={imageUrls} | ||
setImageUrls={setImageUrls} | ||
/> | ||
<EditProjectButton | ||
projectId={parseInt(id as string)} | ||
categories={selectedTypes} | ||
stackNames={selectedStacks} | ||
/> | ||
</Styles.EditProjectContainer> | ||
); | ||
} |
Oops, something went wrong.