Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: section 추가 #77

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4,472 changes: 2,236 additions & 2,236 deletions .pnp.cjs

Large diffs are not rendered by default.

12 changes: 7 additions & 5 deletions src/components/Editor/Components/EditSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import clsx from "clsx";
interface Props {
id: number;
title: string | undefined;
markdown: string | undefined;
onDeleteSection: (e: React.MouseEvent<HTMLElement, MouseEvent>, targetId: number) => void;
// markdown: string | undefined;
// onDeleteSection: (e: React.MouseEvent<HTMLElement, MouseEvent>, targetId: number) => void;
}

const EditSection = ({ id, title, markdown, onDeleteSection }: Props) => {
// , markdown, onDeleteSection

const EditSection = ({ id, title }: Props) => {
const [hover, setHover] = useState<boolean>(false);
const onMouseEnter = () => setHover(true);
const onMouseLeave = () => setHover(false);
Expand Down Expand Up @@ -47,13 +49,13 @@ const EditSection = ({ id, title, markdown, onDeleteSection }: Props) => {
<button>
<Reset size={20} className="fill-[#ADB5BD]" onClick={() => alert("rest")} />
</button>
<button
{/* <button
onClick={e => {
onDeleteSection(e, id);
}}
>
<TrashCan size={20} className="fill-textPrimary" />
</button>
</button> */}
</div>
)}
</div>
Expand Down
32 changes: 21 additions & 11 deletions src/components/Editor/Components/EditSections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ import { useSection } from "context/SectionContext";
import { KeyNameType, SectionsType } from "../types";

const EditSections = ({ keyName }: KeyNameType) => {
const { value, setValue } = useSection();
const [sections, setSections] = useState<SectionsType[]>([]);
const { sections, addSection } = useSection();
const [section, setSection] = useState<SectionsType[]>([]);

const getIndex = (id: number) => sections.findIndex(el => el.id === id);
const getIndex = (id: number) => section.findIndex(el => el.id === id);

const handleDragEnd = (event: DragEndEvent) => {
const { active, over } = event;
if (active.id === over?.id) return;
setSections(sections => {
setSection(section => {
const oldIndex = getIndex(active.id as number);
const newIndex = getIndex(over?.id as number);

return arrayMove(sections, oldIndex, newIndex);
return arrayMove(section, oldIndex, newIndex);
});
};

Expand All @@ -47,7 +47,7 @@ const EditSections = ({ keyName }: KeyNameType) => {

const onDeleteSection = (e: React.MouseEvent<HTMLElement, MouseEvent>, targetId: number) => {
e.stopPropagation();
setSections(prev => prev.filter(el => el.id !== targetId));
setSection(prev => prev.filter(el => el.id !== targetId));
};

const onResetSection = (e: React.MouseEvent<HTMLElement, MouseEvent>, targetId: number) => {
Expand All @@ -57,15 +57,15 @@ const EditSections = ({ keyName }: KeyNameType) => {
useEffect(() => {
const sectionsList = JSON.parse(localStorage.getItem(`${keyName}`) || "[]");
if (sectionsList.length > 0) {
setSections(sectionsList);
setSection(sectionsList);
}
}, []);

useEffect(() => {
localStorage.setItem(`${keyName}`, JSON.stringify(sections));
const sectionsList = JSON.parse(localStorage.getItem(`${keyName}`) || "[]");
const markdownList = sectionsList.map((el: SectionsType) => el.markdown).join("");
setValue(markdownList);
// const sectionsList = JSON.parse(localStorage.getItem(`${keyName}`) || "[]");
// const markdownList = sectionsList.map((el: SectionsType) => el.markdown).join("");
// addSection(markdownList);
}, [sections]);

return (
Expand All @@ -81,14 +81,24 @@ const EditSections = ({ keyName }: KeyNameType) => {
modifiers={[restrictToVerticalAxis]}
>
<SortableContext items={sections} strategy={verticalListSortingStrategy}>
{sections.map(section => (
{/* {section.map(section => (
<EditSection
key={section.id}
title={section.title}
id={section.id}
markdown={section.markdown}
onDeleteSection={onDeleteSection}
/>
))} */}
{sections.map((section, index) => (
<EditSection
key={index}
title={section}
id={index}
// id={section.id}
// markdown={section.markdown}
// onDeleteSection={onDeleteSection}
/>
))}
</SortableContext>
</DndContext>
Expand Down
6 changes: 3 additions & 3 deletions src/components/Editor/Components/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useSection } from "context/SectionContext";
import MDEditor, { commands } from "@uiw/react-md-editor";

const Editor = () => {
const { value: markdown, setValue } = useSection();
const { sections, addSection } = useSection();
const commandsList = [...commands.getCommands()].slice(0, 17);

return (
Expand All @@ -13,8 +13,8 @@ const Editor = () => {
>
<MDEditor
className="editor"
value={markdown}
onChange={value => setValue(value!)}
value={sections[0]}
onChange={value => addSection(value!)}
preview="edit"
height="100%"
commands={commandsList}
Expand Down
8 changes: 6 additions & 2 deletions src/components/Editor/Components/SelectSection.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import React from "react";

const SelectSection = () => {
interface SelectSectionProps {
sectionTitle: string; // sectionTitle prop 타입 정의
}

const SelectSection: React.FC<SelectSectionProps> = ({ sectionTitle }) => {
return (
<div
className="
Expand All @@ -9,7 +13,7 @@ const SelectSection = () => {
rounded-[8px] border-solid border bg-white border-[#F1F3F5] drop-shadow-[0_1px_1px_rgba(173,181,189,0.25)]
cursor-pointer"
>
<p className="text-textPrimary mb-0 truncate"></p>
<p className="text-textPrimary mb-0 truncate">{sectionTitle}</p> {/* sectionTitle 값을 표시 */}
</div>
);
};
Expand Down
18 changes: 8 additions & 10 deletions src/components/Editor/Components/SelectSections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { Add } from "@carbon/icons-react";
import SearchSection from "./SearchSection";
import SelectSection from "./SelectSection";
import AddSectionModal from "../Modal/AddSectionModal";
import { useSection } from "context/SectionContext";

const SelectSections = () => {
const [openModal, setOpenModal] = useState(false);
const modalRef = useRef<HTMLDivElement | null>(null);
const { sections } = useSection(); // Context에서 value 가져오기

const modalOutSideClick = (e: any) => {
if (modalRef.current === e.target) {
Expand All @@ -17,6 +19,7 @@ const SelectSections = () => {
const openModalAlert = () => {
setOpenModal(!openModal);
};
console.log("value", sections);

return (
<div className="h-full flex flex-col gap-[10px] px-[10px]">
Expand All @@ -26,16 +29,11 @@ const SelectSections = () => {
</div>
<div className="h-full max-h-auto flex flex-col gap-[10px]">
<SearchSection />
<SelectSection />
<SelectSection />
<SelectSection />
<SelectSection />
<SelectSection />
<SelectSection />
<SelectSection />
<SelectSection />
<SelectSection />
<SelectSection />
{/* value를 각 SelectSection에 전달 */}
{sections.map((section, index) => (
<SelectSection sectionTitle={section} key={index} />
))}
{/* <SelectSection sectionTitle={sections} /> */}
</div>
{openModal && (
<AddSectionModal
Expand Down
30 changes: 18 additions & 12 deletions src/components/Editor/EditorPreviewContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import Preview from "./Components/Preview";
import Raw from "./Components/Raw";
import { Tab, Tabs } from "../Common/Tabs";
import { useSection } from "../../context/SectionContext";
import { useSection, useActiveSection } from "../../context/SectionContext";
import Editor from "./Components/Editor";
import { Download } from "@carbon/icons-react";
import clsx from "clsx";

const EditorPreviewContainer = () => {
const { value } = useSection();
const { sections } = useSection();
const { setActiveContent, activeContent } = useActiveSection();

const [selectedTab, setSelectedTab] = useState<string | undefined>("Preview");

useEffect(() => {
// sections 배열의 모든 요소를 하나의 문자열로 합치기
const combinedSections = sections.join("\n");
setActiveContent(combinedSections);
}, [sections, setActiveContent]); // sections가 변경될 때마다 실행

const handleTabClick = (value?: string | undefined) => {
setSelectedTab(value);
};

const onDownloadMarkdown = () => {
try {
const element = document.createElement("a");
const file = new Blob([value], { type: "text/plain" });
const file = new Blob([activeContent], { type: "text/plain" });
element.href = URL.createObjectURL(file);
element.download = "README.md";
document.body.appendChild(element);
element.click();
document.body.removeChild(element); // Clean up
alert("Download is complete");
} catch (error) {
alert("Download failed.");
Expand Down Expand Up @@ -56,22 +65,19 @@ const EditorPreviewContainer = () => {
"px-[12px]",
"bg-textBlue text-white ",
"rounded-[8px]",
{ "hover:bg-[#6E9EFF]": sections.length > 0, "cursor-pointer": sections.length > 0 },
{
"hover:bg-[#6E9EFF]": value.length > 0,
"cursor-pointer": value.length > 0,
},
{
"bg-textTertiary": value.length === 0,
"bg-textTertiary": sections.length === 0,
},
)}
disabled={value.length > 0 ? false : true}
disabled={sections.length > 0 ? false : true}
>
<Download size={16} />
<p className="mb-0 text-sm">Download</p>
</button>
</div>
{selectedTab === "Preview" && <Preview value={value} />}
{selectedTab === "Raw" && <Raw value={value} />}
{selectedTab === "Preview" && <Preview value={activeContent} />}
{selectedTab === "Raw" && <Raw value={activeContent} />}
</div>
</div>
</>
Expand Down
21 changes: 18 additions & 3 deletions src/components/Editor/Modal/AddSectionModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useSection } from "context/SectionContext";
import React, { useEffect, useRef } from "react";

// Props interface는 그대로 유지
interface Props {
modalRef: React.ForwardedRef<HTMLDivElement>;
modalOutSideClick: (e: any) => void;
Expand All @@ -9,12 +11,20 @@ interface Props {

const AddSectionModal = ({ modalRef, modalOutSideClick, onClose, openModal }: Props) => {
const inputRef = useRef<HTMLInputElement | null>(null);
const { addSection } = useSection(); // Context에서 addSection 함수 가져오기

useEffect(() => {
if (openModal) {
inputRef.current?.focus();
}
}, []);
}, [openModal]); // useEffect 의존성 배열에 openModal 추가

const handleCreate = () => {
if (inputRef.current?.value) {
addSection(inputRef.current.value); // 입력된 값을 배열에 추가
}
onClose();
};

return (
<div
Expand Down Expand Up @@ -43,9 +53,14 @@ const AddSectionModal = ({ modalRef, modalOutSideClick, onClose, openModal }: Pr
className="w-1/2 rounded-[8px] border-solid border border-textTertiary text-textPrimary hover:bg-gray-50"
onClick={onClose}
>
Cancle
Cancel
</button>
<button
className="w-1/2 rounded-[8px] bg-textBlue text-white hover:bg-[#6E9EFF]"
onClick={handleCreate} // Create 버튼에 핸들러 연결
>
Create
</button>
<button className="w-1/2 rounded-[8px] bg-textBlue text-white hover:bg-[#6E9EFF]">Create</button>
</div>
</div>
</div>
Expand Down
52 changes: 36 additions & 16 deletions src/context/SectionContext.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,43 @@
import React, { createContext, useContext, useState } from "react";

// src/context/SectionContext.tsx
interface SectionContextType {
value: string;
setValue: (value: string) => void;
sections: string[];
addSection: (newSection: string) => void;
}

interface SectionContextProviderProps {
interface SectionProviderProps {
children: React.ReactNode;
}

const SectionContext = createContext<SectionContextType | null>(null);

interface ActiveSectionContextType {
activeContent: string;
setActiveContent: (content: string) => void;
}

const ActiveSectionContext = createContext<ActiveSectionContextType | null>(null);

export const SectionProvider: React.FC<SectionProviderProps> = ({ children }) => {
const [sections, setSections] = useState<string[]>([]);
const addSection = (newSection: string) => {
setSections(prevSections => [...prevSections, newSection]);
};

return <SectionContext.Provider value={{ sections, addSection }}>{children}</SectionContext.Provider>;
};

export const ActiveSectionProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [activeContent, setActiveContent] = useState("");

return (
<ActiveSectionContext.Provider value={{ activeContent, setActiveContent }}>
{children}
</ActiveSectionContext.Provider>
);
};

export const useSection = () => {
const context = useContext(SectionContext);
if (!context) {
Expand All @@ -19,17 +46,10 @@ export const useSection = () => {
return context;
};

export const SectionProvider = ({ children }: SectionContextProviderProps) => {
const [value, setValue] = useState<string>("# Welcome To README-MONSTER");

return (
<SectionContext.Provider
value={{
value,
setValue,
}}
>
{children}
</SectionContext.Provider>
);
export const useActiveSection = () => {
const context = useContext(ActiveSectionContext);
if (!context) {
throw new Error("useActiveSection must be used within an ActiveSectionProvider");
}
return context;
};
Loading
Loading