-
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.
Merge branch 'develop' into feat/login
- Loading branch information
Showing
17 changed files
with
318 additions
and
20 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,11 @@ | ||
import { Outlet } from 'react-router-dom'; | ||
|
||
const AuthLayout = () => { | ||
return ( | ||
<div className="relative mx-auto flex h-screen w-full max-w-[560px] flex-col items-center overflow-hidden"> | ||
<Outlet /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default AuthLayout; |
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
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
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,23 @@ | ||
import Modal from '@/components/common/Modal.tsx'; | ||
import { ModalStateType } from '@/types/type.ts'; | ||
|
||
interface InfoCardModalProps { | ||
state: ModalStateType; | ||
onClose: () => void; | ||
} | ||
|
||
const InfoCardModal = ({ state, onClose }: InfoCardModalProps) => { | ||
return ( | ||
<Modal | ||
state={state} | ||
onBackgroundClick={onClose} | ||
> | ||
<div className="w-96 p-4"> | ||
<h1 className="text-lg font-bold">Info Card</h1> | ||
<p className="mt-2 text-sm">This is an info card.</p> | ||
</div> | ||
</Modal> | ||
); | ||
}; | ||
|
||
export default InfoCardModal; |
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
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
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,58 @@ | ||
import React, { useEffect, useState } from 'react'; | ||
|
||
import { ModalStateType } from '@/types/type.ts'; | ||
|
||
interface ModalProps { | ||
children?: React.ReactNode; | ||
state: ModalStateType; | ||
onBackgroundClick: () => void; | ||
} | ||
|
||
export default function Modal({ | ||
children, | ||
onBackgroundClick, | ||
state, | ||
}: ModalProps) { | ||
const [isVisible, setIsVisible] = useState(state !== 'closed'); | ||
|
||
useEffect(() => { | ||
if (state === 'open') { | ||
setIsVisible(true); | ||
} else if (state === 'closing') { | ||
const timeout = setTimeout(() => { | ||
setIsVisible(false); | ||
}, 200); | ||
return () => clearTimeout(timeout); | ||
} | ||
}, [state]); | ||
|
||
useEffect(() => { | ||
const handleEsc = (event: KeyboardEvent) => { | ||
if (event.key === 'Escape' && state === 'open') { | ||
onBackgroundClick(); | ||
} | ||
}; | ||
window.addEventListener('keydown', handleEsc); | ||
return () => { | ||
window.removeEventListener('keydown', handleEsc); | ||
}; | ||
}, [onBackgroundClick, state]); | ||
|
||
if (!isVisible) return null; | ||
|
||
return ( | ||
<div | ||
className={`fixed inset-0 z-50 flex items-center justify-center transition-opacity duration-200 ${ | ||
state === 'open' ? 'opacity-100' : 'pointer-events-none opacity-0' | ||
}`} | ||
> | ||
<div | ||
className="absolute inset-0 bg-black bg-opacity-50" | ||
onClick={onBackgroundClick} | ||
/> | ||
<div className="relative flex flex-col items-center rounded-md bg-white p-6"> | ||
{children} | ||
</div> | ||
</div> | ||
); | ||
} |
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,54 @@ | ||
import React, { useEffect, useRef } from 'react'; | ||
import { twMerge } from 'tailwind-merge'; | ||
|
||
interface TextFieldProps | ||
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> { | ||
isEditing?: boolean; | ||
} | ||
|
||
const Textarea = ({ | ||
className = '', | ||
isEditing = false, | ||
rows = 4, | ||
...props | ||
}: TextFieldProps) => { | ||
const textAreaRef = useRef<HTMLTextAreaElement>(null); | ||
const prevIsEditing = useRef(isEditing); | ||
|
||
useEffect(() => { | ||
const textarea = textAreaRef.current; | ||
if (!textarea) return; | ||
|
||
if (isEditing) { | ||
// 포커스 전환 시: 텍스트의 맨 끝으로 커서를 이동하고 스크롤을 맞춤 | ||
textarea.focus(); | ||
const len = textarea.value.length; | ||
textarea.setSelectionRange(len, len); | ||
textarea.scrollTop = textarea.scrollHeight; | ||
} else if (prevIsEditing.current && !isEditing) { | ||
// 포커스 해제 시: 텍스트의 맨 처음으로 커서를 이동하고 스크롤을 맞춤 | ||
textarea.focus(); | ||
textarea.setSelectionRange(0, 0); | ||
textarea.scrollTop = 0; | ||
} | ||
prevIsEditing.current = isEditing; | ||
}, [isEditing]); | ||
|
||
return ( | ||
<textarea | ||
{...props} | ||
rows={rows} | ||
readOnly={!isEditing} | ||
ref={textAreaRef} | ||
className={twMerge( | ||
'textarea-scrollbar box-border w-full resize-none rounded-[4px] bg-white px-[10px] py-[10px] text-sm font-normal placeholder-textGray1', | ||
isEditing | ||
? 'border-[1px] border-borderGray text-black focus:border-[1.5px] focus:border-pointColor focus:px-[9.5px] focus:py-[9.5px] focus:outline-none' | ||
: 'cursor-default border-[1px] border-borderGray text-textGray2 focus:outline-none', | ||
className | ||
)} | ||
/> | ||
); | ||
}; | ||
|
||
export default Textarea; |
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,29 @@ | ||
import { useState, useRef } from 'react'; | ||
import { ModalStateHookType, ModalStateType } from '@/types/type.ts'; | ||
|
||
const MODAL_ANIMATION_DURATION = 300; | ||
|
||
function useModalState(): ModalStateHookType { | ||
const [modalState, setModalState] = useState<ModalStateType>('closed'); | ||
const closeTimeoutRef = useRef<number | null>(null); | ||
|
||
const openModal = () => { | ||
if (closeTimeoutRef.current !== null) { | ||
clearTimeout(closeTimeoutRef.current); | ||
closeTimeoutRef.current = null; | ||
} | ||
setModalState('open'); | ||
}; | ||
|
||
const closeModal = () => { | ||
setModalState('closing'); | ||
closeTimeoutRef.current = window.setTimeout(() => { | ||
setModalState('closed'); | ||
closeTimeoutRef.current = null; | ||
}, MODAL_ANIMATION_DURATION); | ||
}; | ||
|
||
return [modalState, openModal, closeModal]; | ||
} | ||
|
||
export default useModalState; |
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,5 @@ | ||
const Home = () => { | ||
return <div>Home입니다.</div>; | ||
}; | ||
|
||
export default Home; |
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
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
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,39 @@ | ||
import { useState } from 'react'; | ||
|
||
import Input from '@/components/common/Input.tsx'; | ||
import Textarea from '@/components/common/Textarea.tsx'; | ||
import GroupTransferInfo from '@/components/InfoCard/GroupTransferInfo.tsx'; | ||
import InfoCardModal from '@/components/InfoCard/InfoCardModal.tsx'; | ||
import useModalState from '@/hooks/useModal.ts'; | ||
|
||
const Test = () => { | ||
const [infoCardModalState, openInfoCardModal, closeInfoCardModal] = | ||
useModalState(); | ||
|
||
const [isEditing, setIsEditing] = useState(false); | ||
|
||
return ( | ||
<div> | ||
<button onClick={openInfoCardModal}>모달 열기</button> | ||
{infoCardModalState !== 'closed' && ( | ||
<InfoCardModal | ||
state={infoCardModalState} | ||
onClose={closeInfoCardModal} | ||
/> | ||
)} | ||
<button onClick={() => setIsEditing((prev) => !prev)}>edit</button> | ||
<Textarea isEditing={isEditing} /> | ||
<Input /> | ||
|
||
<GroupTransferInfo | ||
teamName="AI기술팀" | ||
startDate="2024.07.02" | ||
endDate="2024.12.23" | ||
leaderName="김철수" | ||
responsibilities="밥먹기" | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Test; |
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
Oops, something went wrong.