Skip to content

Commit

Permalink
diary_day
Browse files Browse the repository at this point in the history
✨ canvas draw style
 🛠 setting button design
🐛 useEffect hell
  • Loading branch information
onejuice98 committed Feb 5, 2023
1 parent 472a30a commit 1fee217
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 55 deletions.
8 changes: 8 additions & 0 deletions src/components/common/GrayText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
interface IGrayText {
children: React.ReactNode;
}
const GrayText = ({ children }: IGrayText) => {
return <div className="text-gray-500 text-sm"> {children} </div>;
};

export default GrayText;
22 changes: 22 additions & 0 deletions src/components/common/Select.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
interface ISelect {
children: React.ReactNode;
onSelectChange?: React.ChangeEventHandler<HTMLSelectElement> | undefined;
}

/**
*
* @param children option tag
* @param onSelectChange onChange Fn
* @returns Select Tag in style
*/
const Select = ({ children, onSelectChange }: ISelect) => {
return (
<select
className="w-full bg-gray-50 border border-gray-300 text-gray-600 text-sm rounded-md"
onChange={onSelectChange}
>
{children}
</select>
);
};
export default Select;
70 changes: 48 additions & 22 deletions src/components/common/SetBtn.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState } from "react";
import { useRecoilState, useSetRecoilState } from "recoil";
import { useSetRecoilState } from "recoil";
import {
itemTextBgColor,
itemTextBgColorType,
Expand All @@ -8,6 +8,8 @@ import {
itemTextSize,
itemTextSizeType,
} from "../../recoil/diary";
import GrayText from "./GrayText";
import Select from "./Select";

interface ISetBtn {
onClick?: React.MouseEventHandler<HTMLButtonElement>;
Expand Down Expand Up @@ -68,27 +70,51 @@ const SetBtn = ({
</svg>
</button>
{isSettingBox && hover && (
<div className="w-32 h-72 bg-amber-200 absolute translate-y-[45%] duration-300 z-[999]">
<button onClick={() => setHover(false)}> X </button>
<select onChange={handleTextSize}>
<option value="text-base"> 적당히 </option>
<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 className="flex flex-col justify-between p-4 rounded-md w-48 h-72 bg-cyan-200 absolute translate-y-[45%] z-[999]">
<div>
<GrayText>Text Size</GrayText>
<Select onSelectChange={handleTextSize}>
<option value="text-base"> 적당히 </option>
<option value="text-sm"> 작게 </option>
<option value="text-lg"> 크게 </option>
</Select>
</div>
<div>
<GrayText>Text Color</GrayText>
<Select onSelectChange={handleTextColor}>
<option value=""> 검정 </option>
<option value="text-green-500"> 초롱 </option>
<option value="text-blue-500"> 파랑 </option>
<option value="text-red-500"> 빨강 </option>
</Select>
</div>

<div>
<GrayText>HighLight Text</GrayText>
<Select onSelectChange={handleTextBgColor}>
<option value=""> 기본 </option>
<option value="#FFFF00"> 노랑 </option>
<option value="#00FEFE"> 청록 </option>
<option value="#00FF00"> 녹색 </option>
<option value="#FF00FF"> 분홍 </option>
</Select>
</div>

<div className="flex justify-end gap-2">
<button
className="w-14 h-8 bg-red-500 hover:bg-red-700 text-white rounded-md shadow-md duration-300"
onClick={() => setHover(false)}
>
닫기
</button>
<button
className="w-14 h-8 bg-green-500 hover:bg-green-700 text-white rounded-md shadow-md duration-300"
onClick={onClick}
>
{" "}
적용{" "}
</button>
</div>
</div>
)}
</>
Expand Down
35 changes: 31 additions & 4 deletions src/components/diary/MenuBar.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { RefObject, useRef } from "react";
import { useNavigate } from "react-router-dom";
import { useRecoilState, useSetRecoilState } from "recoil";
import { apply, bgImage } from "../../recoil/diary";
import { apply, bgImage, strokeColor, strokeWidth } from "../../recoil/diary";

/**
* 뒤로가기 버튼, background Image을 넣을 input(type="file"), template에 그린 것을 적용시킬 버튼
* @returns <DayDiary /> page의 상단메뉴
* 뒤로가기 버튼, background Image을 넣을 input(type="file"), canvas 도구, template에 그린 것을 적용시킬 버튼
* @returns DayDiary page의 상단메뉴
*/
const MenuBar = () => {
const history = useNavigate();
const setBgImages = useSetRecoilState<string>(bgImage);
const [isApply, setIsApply] = useRecoilState<boolean>(apply);
const [stroke, setStroke] = useRecoilState<number>(strokeWidth);
const [color, setColor] = useRecoilState<string>(strokeColor);
const imgRef: RefObject<HTMLInputElement> = useRef<HTMLInputElement>(null);
const readURL = () => {
if (!imgRef) return;
Expand All @@ -22,6 +24,7 @@ const MenuBar = () => {
if (typeof reader.result === "string") setBgImages(reader.result);
};
};

return (
<div className="flex w-full h-16 p-2 gap-4 items-center">
<div className="h-fit flex items-center justify-between">
Expand All @@ -44,7 +47,31 @@ const MenuBar = () => {
PNG, JPEG or GIF
</p>
</div>

<div>
<div className="text-gray-500 text-sm dark:text-gray-300">
Line Width : {stroke}
</div>
<input
type="range"
min="1"
max="20"
value={stroke}
onChange={(event) => setStroke(event.currentTarget.valueAsNumber)}
step="0.5"
className="w-36 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
/>
</div>
<div>
<div className="text-gray-500 text-sm dark:text-gray-300">
Line Color
</div>
<input
type="color"
value={color}
onChange={(event) => setColor(event.currentTarget.value)}
className="w-full h-6 cursor-pointer"
/>
</div>
<button
className="w-24 h-12 bg-emerald-500 p-2 rounded-md shadow-md text-white hover:bg-emerald-700 duration-300"
onClick={() => setIsApply((prev) => !prev)}
Expand Down
57 changes: 43 additions & 14 deletions src/components/diary/editor/EditorHead.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useEffect } from "react";
import { useRecoilState, useRecoilValue, useSetRecoilState } from "recoil";
import { useRecoilState, useRecoilValue } from "recoil";
import {
diaryContent,
diaryContentType,
diaryItemList,
diaryItemType,
isDisabled,
resultTemplate,
titleText,
} from "../../../recoil/diary";
import JuiceFont from "../../common/JuiceFont";
Expand All @@ -20,24 +21,52 @@ interface IEditorHead {
*/
const EditorHead = ({ day }: IEditorHead) => {
const [disabled, setDisabled] = useRecoilState<boolean>(isDisabled);
const title = useRecoilValue<string>(titleText);
const titleName = useRecoilValue<string>(titleText);
const items = useRecoilValue<diaryItemType[]>(diaryItemList);
const template = useRecoilValue<string | undefined>(resultTemplate);
const [diary, setDiary] = useRecoilState<diaryContentType[]>(diaryContent);
// 여기 뭔가 이상함ㅋㅋ 왜지?
useEffect(() => {
!disabled &&
setDiary([...diary, { day: day, title: title, content: items }]);
console.log(diary);
}, [disabled]);

const onDisabled = () => {
setDisabled((prev) => !prev);
};
const onSave = () => {
if (disabled) {
const findIndex = diary.findIndex((element) => element.day === day);
if (findIndex === -1) {
setDiary([
...diary,
{ day: day, title: titleName, content: items, template: template },
]);
} else {
let copyDiary = [...diary];
copyDiary[findIndex] = {
day: day,
title: titleName,
content: items,
template: template,
};
setDiary(copyDiary);
}
console.log(diary);
}
};
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 className="flex gap-2">
<button
onClick={onDisabled}
className="font-mono bg-emerald-400 p-1 rounded-md shadow-md text-white hover:bg-emerald-600 duration-300"
>
{disabled ? "활성화" : "비활성화"}
</button>
<button
onClick={onSave}
className="font-mono bg-emerald-400 p-1 rounded-md shadow-md text-white hover:bg-emerald-600 duration-300"
>
저장하기
</button>
</div>
</div>
);
};
Expand Down
1 change: 0 additions & 1 deletion src/components/diary/editor/ItemList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ const ItemList = () => {
}
setItems(tempItemList);
}, [disabled, style]);

return (
<Reorder.Group axis="y" values={items} onReorder={setItems}>
<div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/diary/editor/Title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const Title = () => {

// disabled 가 켜질때만 저장
useEffect(() => {
disabled && setTitle(watch("titleContent"));
!disabled && setTitle(watch("titleContent"));
}, [disabled]);

return (
Expand Down
32 changes: 21 additions & 11 deletions src/components/diary/template/Template.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { RefObject, useEffect, useRef, useState } from "react";
import { useRecoilState, useRecoilValue, useSetRecoilState } from "recoil";
import { apply, bgImage, resultTemplate } from "../../../recoil/diary";
import {
apply,
bgImage,
resultTemplate,
strokeColor,
strokeWidth,
} from "../../../recoil/diary";

interface ITemplate {
width: number;
Expand All @@ -16,25 +22,30 @@ const Template = ({ width, height }: ITemplate) => {
const canvasRef: RefObject<HTMLCanvasElement> =
useRef<HTMLCanvasElement>(null);
const [context, setContext] = useState<CanvasRenderingContext2D>();
const [drawContext, setDrawContext] = useState<CanvasRenderingContext2D>();
const templateImg = useRecoilState<string>(bgImage);
const [isDrawing, SetIsDrawing] = useState<boolean>(false);
const stroke = useRecoilValue<number>(strokeWidth);
const color = useRecoilValue<string>(strokeColor);

const setResultTemplate = useSetRecoilState<string | undefined>(
resultTemplate
);
const isApply = useRecoilValue<boolean>(apply);

// stroke style 지정 (stroke가 변할 때 마다 실행)
useEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas?.getContext("2d");
if (ctx) {
ctx.strokeStyle = "black";
ctx.lineWidth = 2.5;
setDrawContext(ctx);
ctx.strokeStyle = color;
ctx.lineWidth = stroke;
setContext(ctx);
}
}, [stroke, color]);
// background img 지정 (width, height, 배경 바뀔 때 마다 실행)
useEffect(() => {
const img = new Image();
img.src = templateImg[0];

img.onload = () => {
context?.drawImage(img, 0, 0, width, height);
};
Expand All @@ -46,13 +57,12 @@ const Template = ({ width, height }: ITemplate) => {
}, [isApply]);
const drawing = (event: React.MouseEvent<HTMLCanvasElement, MouseEvent>) => {
const { offsetX, offsetY } = event.nativeEvent;

if (!isDrawing) {
drawContext?.beginPath();
drawContext?.moveTo(offsetX, offsetY);
context?.beginPath();
context?.moveTo(offsetX, offsetY);
} else {
drawContext?.lineTo(offsetX, offsetY);
drawContext?.stroke();
context?.lineTo(offsetX, offsetY);
context?.stroke();
}
};

Expand Down
3 changes: 1 addition & 2 deletions src/pages/Diary/DayDiary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,14 @@ const DayDiary = () => {
window.removeEventListener("resize", handleResize);
};
}, []);
console.log(template);
return (
<div className="flex flex-col w-[100vw] h-[100vh] bg-gray-100/[0.7]">
<MenuBar />
<div className="flex divide-x-[1px] w-full h-full">
<div className="w-[50vw]" ref={divRef}>
<Template width={templateWidth} height={templateHeight} />
</div>
<div className="w-[calc(50vw-1px)] h-[calc(100vh-57px)]">
<div className="w-[calc(50vw-1px)] h-[calc(100vh-64px)]">
<img
src={isApply ? template : templateImg}
className={`${
Expand Down

0 comments on commit 1fee217

Please sign in to comment.