Skip to content

Commit

Permalink
diary_day : Editor 완성 Refactoring 도 완료
Browse files Browse the repository at this point in the history
  • Loading branch information
onejuice98 committed Feb 1, 2023
1 parent 8e0532c commit 495126c
Show file tree
Hide file tree
Showing 9 changed files with 375 additions and 150 deletions.
40 changes: 35 additions & 5 deletions src/components/common/SetBtn.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { DragControls } from "framer-motion";
import React, { useState } from "react";
import { useSetRecoilState } from "recoil";
import { textSize, textSizeType } from "../../recoil/diary";
import { useRecoilState, useSetRecoilState } from "recoil";
import {
itemTextBgColor,
itemTextBgColorType,
itemTextColor,
itemTextColorType,
itemTextSize,
itemTextSizeType,
} from "../../recoil/diary";

interface ISetBtn {
onClick?: React.MouseEventHandler<HTMLButtonElement>;
Expand All @@ -18,11 +24,22 @@ const SetBtn = ({
isSettingBox,
}: ISetBtn) => {
const [hover, setHover] = useState(false);
const setTextSize = useSetRecoilState<textSizeType>(textSize);
const setTextSize = useSetRecoilState<itemTextSizeType>(itemTextSize);
const setTextColor = useSetRecoilState<itemTextColorType>(itemTextColor);
const setTextBgColor =
useSetRecoilState<itemTextBgColorType>(itemTextBgColor);
const handleTextSize = (event: React.ChangeEvent<HTMLSelectElement>) => {
const value: textSizeType = event.currentTarget.value;
const value: itemTextSizeType = event.currentTarget.value;
setTextSize(value);
};
const handleTextColor = (event: React.ChangeEvent<HTMLSelectElement>) => {
const value: itemTextColorType = event.currentTarget.value;
setTextColor(value);
};
const handleTextBgColor = (event: React.ChangeEvent<HTMLSelectElement>) => {
const value: itemTextBgColorType = event.currentTarget.value;
setTextBgColor(value);
};
return (
<>
<button
Expand Down Expand Up @@ -58,6 +75,19 @@ const SetBtn = ({
<option value="text-sm"> 작게 </option>
<option value="text-lg"> 크게 </option>
</select>
<select onChange={handleTextColor}>
<option value=""> 검정 </option>
<option value="text-green-500"> 초롱 </option>
<option value="text-blue-500"> 파랑 </option>
<option value="text-red-500"> 빨강 </option>
</select>
<select onChange={handleTextBgColor}>
<option value=""> 기본 </option>
<option value="#FFFF00"> 노랑 </option>
<option value="#00FEFE"> 청록 </option>
<option value="#00FF00"> 녹색 </option>
<option value="#FF00FF"> 분홍 </option>
</select>
<button onClick={onClick}> 적용 </button>
</div>
)}
Expand Down
2 changes: 1 addition & 1 deletion src/components/diary/CanvasInput.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FormEvent, useState } from "react";
import { useRecoilState, useSetRecoilState } from "recoil";
import { canvasHeight, canvasWidth, diaryText } from "../../recoil/diary";
import { canvasHeight, canvasWidth } from "../../recoil/diary";

interface ICanvasLimit {
maxWidth: number | undefined;
Expand Down
3 changes: 0 additions & 3 deletions src/components/diary/DiaryInput.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import { FormEvent, useState } from "react";
import { useRecoilState } from "recoil";
import { diaryText } from "../../recoil/diary";

const DiaryInput = () => {
const [text, setText] = useState("");
const [textList, setTextList] = useRecoilState<string[]>(diaryText);
const handleChange = (event: FormEvent<HTMLInputElement>) => {
setText(event.currentTarget.value);
};
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
setTextList([...textList, text]);
event.currentTarget.reset();
};
return (
Expand Down
137 changes: 11 additions & 126 deletions src/components/diary/Editor.tsx
Original file line number Diff line number Diff line change
@@ -1,138 +1,23 @@
import { Reorder } from "framer-motion";
import React, {
MouseEventHandler,
RefObject,
useEffect,
useRef,
useState,
} from "react";
import { useForm } from "react-hook-form";
import { useParams } from "react-router-dom";
import { useRecoilState, useRecoilValue } from "recoil";
import { dDayListState, UserInput } from "../../recoil/dDay";
import {
DiaryContext,
diaryContextState,
textSize,
textSizeType,
} from "../../recoil/diary";
import Divider from "../common/Divider";
import JuiceFont from "../common/JuiceFont";
import SetBtn from "../common/SetBtn";
import EditorHead from "./EditorHead";
import ItemList from "./ItemList";
import Title from "./Title";

interface IEditor {
day: string;
}
/**
* Editor 의 컴포넌트 모음이다.
* @param day string(yyyy-MM-dd)
* @returns Editor, 결과적으로 Day의 키를 가진 상태인 diaryContent을 최신화 시킨다.
*/
const Editor = ({ day }: IEditor) => {
const { register, watch } = useForm();
const [contextList, setContextList] =
useRecoilState<DiaryContext[]>(diaryContextState);
const contextRef = useRef<(HTMLInputElement | null)[]>([]);
const [isEnter, setIsEnter] = useState(false);
const [contextNumber, setContextNumber] = useState(1);
const [makeDisable, setMakeDisable] = useState(true);
const [onSetting, setOnSetting] = useState(false);
const [inputTextSize, setInputTextSize] = useState<string[]>([]);
const [fontSize, setFontSize] = useRecoilState<textSizeType>(textSize);
const onKeyEnter = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === "Enter") {
setIsEnter(true);
}
return isEnter;
};
const onContextClick = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>,
index: number
) => {
console.log(index);
let copiedInputTextSize = [...inputTextSize];
copiedInputTextSize[index] = fontSize;
setInputTextSize(copiedInputTextSize);
};

const onSettingClick = (index: number) => {
let copiedInputTextSize = [...inputTextSize];
copiedInputTextSize[index] = fontSize;
setInputTextSize(copiedInputTextSize);
setFontSize("");
};

useEffect(() => {
if (isEnter) {
setContextNumber((num) => num + 1);
setContextList([
...contextList,
{
id: "context" + contextNumber,
context: watch("context" + contextNumber),
},
]);
setInputTextSize([...inputTextSize, ""]);
setIsEnter(false);
}
}, [isEnter]);

return (
<div className="p-4 gap-1 flex flex-col">
<div className="flex justify-between items-center">
<JuiceFont>{day}</JuiceFont>
<button
onClick={() => setMakeDisable((prev) => !prev)}
className="font-mono bg-emerald-400 p-1 rounded-md shadow-md text-white hover:bg-emerald-600 duration-300"
>
{makeDisable ? "Save" : "Edit"}
</button>
</div>
<div className="flex gap-4 items-center">
<JuiceFont isBold isBig others="whitespace-nowrap">
제목
</JuiceFont>
<input
disabled={makeDisable}
className="p-2 font-bold text-lg border-none w-full rounded-md bg-gray-100/[0.1]"
/>
</div>
<EditorHead day={day} />
<Title />
<Divider />
<Reorder.Group axis="y" values={contextList} onReorder={setContextList}>
{contextList.map((value, idx) => (
<Reorder.Item
key={value.id}
value={value}
dragConstraints={{
top: -50,
bottom: 100,
left: 0,
right: 0,
}}
>
<div
key={value.id}
className="flex gap-1 group relative items-center"
>
<button
onClick={() => setIsEnter(true)}
className="group-hover:opacity-100 relative opacity-0 hover:opacity-100 hover:bg-gray-200 w-8 h-8 rounded-md duration-500 text-gray-400"
>
+
</button>
<SetBtn
isWeakGray
isSettingBox
onClick={() => onSettingClick(idx)}
others="relative opacity-0 group-hover:opacity-100 hover:opacity-100 hover:bg-gray-200 duration-500"
/>
<div
{...register("context" + idx, {})}
onKeyUp={onKeyEnter}
contentEditable={makeDisable}
key={value.id}
className={`font-mono border-none bg-gray-100/[0.1] w-full px-1 active:bg-blue-200 active:rounded-sm duration-150 whitespace-pre-line resize-none ${inputTextSize[idx]}`}
placeholder="내용을 입력하세요. 다음 줄 입력시 'Enter' 입니다."
/>
</div>
</Reorder.Item>
))}
</Reorder.Group>
<ItemList />
</div>
);
};
Expand Down
45 changes: 45 additions & 0 deletions src/components/diary/EditorHead.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useEffect } from "react";
import { useRecoilState, useRecoilValue, useSetRecoilState } from "recoil";
import {
diaryContent,
diaryContentType,
diaryItemList,
diaryItemType,
isDisabled,
titleText,
} from "../../recoil/diary";
import JuiceFont from "../common/JuiceFont";

interface IEditorHead {
day: string;
}
/**
* Editor 의 최상단부 Save / Edit 기능
* @param day : string(yyyy-MM-dd)
* @returns Mode Save & Edit 통해 Edit 하고 diaryContent State push
*/
const EditorHead = ({ day }: IEditorHead) => {
const [disabled, setDisabled] = useRecoilState<boolean>(isDisabled);
const title = useRecoilValue<string>(titleText);
const items = useRecoilValue<diaryItemType[]>(diaryItemList);
const [diary, setDiary] = useRecoilState<diaryContentType[]>(diaryContent);
// 여기 뭔가 이상함ㅋㅋ 왜지?
useEffect(() => {
!disabled &&
setDiary([...diary, { day: day, title: title, content: items }]);
console.log(diary);
}, [disabled]);
return (
<div className="flex justify-between items-center">
<JuiceFont>{day}</JuiceFont>
<button
onClick={() => setDisabled((prev) => !prev)}
className="font-mono bg-emerald-400 p-1 rounded-md shadow-md text-white hover:bg-emerald-600 duration-300"
>
{disabled ? "Edit" : "Save"}
</button>
</div>
);
};

export default EditorHead;
113 changes: 113 additions & 0 deletions src/components/diary/ItemList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { Reorder } from "framer-motion";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { useRecoilState, useRecoilValue } from "recoil";
import {
diaryItemList,
diaryItemType,
isDisabled,
itemStyle,
itemStyleType,
itemTextBgColor,
itemTextBgColorType,
itemTextColor,
itemTextColorType,
itemTextSize,
itemTextSizeType,
} from "../../recoil/diary";
import SetBtn from "../common/SetBtn";

/**
* Editor의 중하단부, context의 List를 더하거나 CSS를 수정한다. 내용을 추가 할 수 있다.
* @returns Item List 가 출력 (Item -> 내용)
*/
const ItemList = () => {
const { register, watch, setValue } = useForm();
const disabled = useRecoilValue<boolean>(isDisabled);
const [items, setItems] = useRecoilState<diaryItemType[]>(diaryItemList);
// recoil default 가 0 가 있어서 1부터다!
const [itemId, setItemId] = useState<number>(1);
const [style, setStyle] = useRecoilState<itemStyleType[]>(itemStyle);
const [size, setSize] = useRecoilState<itemTextSizeType>(itemTextSize);
const [color, setColor] = useRecoilState<itemTextColorType>(itemTextColor);
const [bgColor, setBgColor] =
useRecoilState<itemTextBgColorType>(itemTextBgColor);

const onPlusClick = () => {
setItemId((prev) => prev + 1);
setStyle([...style, { textSize: "text-base", textColor: "", textBg: "" }]);
setItems([
...items,
{
id: "context" + itemId,
context: "",
style: { textSize: "text-base", textColor: "", textBg: "" },
},
]);
};
const onSettingClick = (index: number) => {
let tempStyle: itemStyleType[] = [...style];
tempStyle[index] = { textSize: size, textColor: color, textBg: bgColor };
setStyle(tempStyle);
setSize("text-base");
setColor("");
setBgColor("");
};

useEffect(() => {
let tempItemList: diaryItemType[] = [];
for (let i = 0; i < items.length; i++) {
let temp: diaryItemType = {
id: "context" + i,
context: watch("context" + i),
style: style[i],
};
tempItemList.push(temp);
}
setItems(tempItemList);
}, [disabled, style]);

return (
<Reorder.Group axis="y" values={items} onReorder={setItems}>
<div>
{items.map((value, index) => (
<Reorder.Item
key={value.id}
value={value}
dragConstraints={{
top: -50,
bottom: 100,
left: 0,
right: 0,
}}
>
<div
key={value.id}
className="flex gap-1 group relative items-center"
>
<button
onClick={onPlusClick}
className="group-hover:opacity-100 relative opacity-0 hover:opacity-100 hover:bg-gray-200 w-8 h-8 rounded-md duration-500 text-gray-400"
>
+
</button>
<SetBtn
isWeakGray
isSettingBox
onClick={() => onSettingClick(index)}
others="relative opacity-0 group-hover:opacity-100 hover:opacity-100 hover:bg-gray-200 duration-500"
/>
<div
{...register(value.id)}
contentEditable={!disabled}
onInput={(e) => setValue(value.id, e.currentTarget.textContent)}
className={`font-mono border-none rounded-sm w-full px-1 active:bg-blue-200 active:rounded-sm duration-150 whitespace-pre-line ${value.style.textSize} ${value.style.textColor} bg-[${value.style.textBg}]`}
/>
</div>
</Reorder.Item>
))}
</div>
</Reorder.Group>
);
};
export default ItemList;
Loading

0 comments on commit 495126c

Please sign in to comment.