diff --git a/src/pages/404.tsx b/src/pages/404.tsx new file mode 100644 index 0000000..45dc55d --- /dev/null +++ b/src/pages/404.tsx @@ -0,0 +1,7 @@ +export interface NotFoundProps {} + +function NotFound({ ...props }: NotFoundProps) { + return <>404 not found; +} + +export default NotFound; diff --git a/src/pages/post/components/Editor.tsx b/src/pages/post/components/Editor.tsx index 87da07d..8801262 100644 --- a/src/pages/post/components/Editor.tsx +++ b/src/pages/post/components/Editor.tsx @@ -3,6 +3,7 @@ import { Stack, Stroke } from '@base'; import { css } from '@emotion/react'; import { produce } from 'immer'; import { ChangeEvent, useEffect, useRef, useState } from 'react'; +import { Navigate } from 'react-router-dom'; import Image from './Editor/Image'; import Ingredient, { IngredientType } from './Editor/Ingredient'; import TextInput, { TextInputValueItemType } from './Editor/TextInput'; @@ -74,6 +75,11 @@ function Editor({ onChange, ...props }: EditorProps) { onChange(data); }, [data]); + useEffect(() => { + if (data.text.length > 1000) + setData({ ...data, text: data.text.slice(0, 1000) }); + }, [data]); + const handleTitleChange = (e: ChangeEvent) => { setData({ ...data, @@ -268,6 +274,7 @@ function Editor({ onChange, ...props }: EditorProps) { css={styles.input} placeholder="레시피의 이름을 알려주세요." onChange={handleTitleChange} + maxLength={13} /> @@ -334,7 +341,7 @@ function Editor({ onChange, ...props }: EditorProps) { onFocusBlur={(isFocus) => handleFocusBlur(isFocus, index)} /> ) : ( - <>hi + ), )}
(function Timer( }: TimerProps, ref, ) { - const [inputValue, setInputValue] = useState(''); - const timerRef = useRef(null); + const [minuteValue, setMinuteValue] = useState('10'); + const [secondValue, setSecondValue] = useState('00'); + const [isFocused, setIsFocused] = useState(false); + const minuteRef = useRef(null); + const secondRef = useRef(null); - const mergedRef = ref ? mergeRef(ref, timerRef) : timerRef; + const mergedRef = ref ? mergeRef(ref, minuteRef) : minuteRef; - const handleKeyDown = keyDownEventHandler({ - onClickArrowKey, - onDelete, - onSubmit, - setValue: setInputValue, - value: inputValue, - }); + const commonParam = { onClickArrowKey, onDelete, onSubmit }; + + const inputFocusCaretSet = (e: KeyboardEvent) => { + const currentPos = e.currentTarget.selectionStart; + currentPos && e.currentTarget.setSelectionRange(currentPos, currentPos + 1); + if (currentPos === 2) secondRef.current?.focus(); + }; + + const handleKeyPress = (e: KeyboardEvent) => { + if (!/[0-9]/.test(e.key)) { + e.preventDefault(); + } + }; + const handleMinuteInput = (e: KeyboardEvent) => { + inputFocusCaretSet(e); + setMinuteValue(e.currentTarget.value); + }; + const handleSecondInput = (e: KeyboardEvent) => { + inputFocusCaretSet(e); + setSecondValue(e.currentTarget.value); + }; + const handleMinuteKeyDown = (e: KeyboardEvent) => { + if (e.key === 'ArrowRight' && e.currentTarget.selectionEnd === 2) { + secondRef.current?.focus(); + return; + } + keyDownEventHandler({ + setValue: setMinuteValue, + value: minuteValue, + ...commonParam, + })(e); + }; + const handleSecondKeyDown = (e: KeyboardEvent) => { + if (e.key === 'ArrowLeft' && e.currentTarget.selectionStart === 0) { + minuteRef.current?.focus(); + return; + } else if (e.key === 'Backspace' && e.currentTarget.selectionEnd === 0) { + minuteRef.current?.focus(); + e.preventDefault(); + return; + } + keyDownEventHandler({ + setValue: setSecondValue, + value: secondValue, + ...commonParam, + })(e); + }; + const handleFocus = (e: FocusEvent) => { + e.target.setSelectionRange(0, 1); + onFocusBlur?.(true); + setIsFocused(true); + }; + const handelBlur = (e: FocusEvent) => { + let minuteNewVal = minuteValue.padEnd(2, '0'); + let secondNewVal = secondValue.padEnd(2, '0'); + if (parseInt(secondNewVal) > 59) { + minuteNewVal = `${parseInt(minuteNewVal) + 1}`; + secondNewVal = `${parseInt(secondNewVal) - 60}`.padStart(2, '0'); + } + if (parseInt(minuteNewVal) >= 59) { + minuteNewVal = '59'; + secondNewVal = '00'; + } + setMinuteValue(minuteNewVal); + setSecondValue(secondNewVal); + setIsFocused(false); + onFocusBlur?.(false); + }; + const handleKeyUp = (e: KeyboardEvent) => { + let currentPos = e.currentTarget.selectionStart; + currentPos = currentPos === 0 ? 1 : currentPos === 2 ? 1 : currentPos; + if (e.key === 'ArrowRight') + currentPos && + e.currentTarget.setSelectionRange(currentPos, currentPos + 1); + else if (e.key === 'ArrowLeft') + currentPos && + e.currentTarget.setSelectionRange(currentPos - 1, currentPos); + }; useEffect(() => { - onChange?.(inputValue); - }, [inputValue]); + onChange?.(`${minuteValue}:${secondValue}}`); + }, [minuteValue, secondValue]); + + const commonProps = { + maxLength: 2, + size: 2, + css: [styles.input.number, isFocused && styles.input.numberFocus], + onFocus: handleFocus, + onBlur: handelBlur, + autoFocus: true, + onKeyUp: handleKeyUp, + onKeyPress: handleKeyPress, + }; return ( @@ -77,18 +181,24 @@ const Timer = forwardRef(function Timer( - setInputValue(e.currentTarget.value)} - onKeyDown={handleKeyDown} - onFocus={() => onFocusBlur?.(true)} - onBlur={() => onFocusBlur?.(false)} - autoFocus - placeholder="10:00" - size={4} - css={styles.input} - /> + + +
:
+ +