-
Notifications
You must be signed in to change notification settings - Fork 0
feat: 새 글 작성 페이지 구현 #56
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
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
f2d16b9
feat: 새 글 작성 페이지 구현
ljh130334 87c6b99
fix: 새 글 작성 완료 조건 수정
ljh130334 83a2583
feat: 책 검색 필터 UI 개선
ljh130334 1c3d956
style: 글 작성 텍스트 영역 border 제거 및 일부 스타일 수정
ljh130334 2db5106
style: 사진 추가 영역 스타일링 일부 수정
ljh130334 a69473a
refactor: 새 글 작성에서 공개 설정 단순화
ljh130334 785bd2b
feat: 2단계 태그 선택 시스템 구현
ljh130334 f7ce204
refactor: 태그 선택 UI 개선 - 유동적 레이아웃 및 SVG 아이콘 적용
ljh130334 9e711cf
fix: 일부 문법 에러 수정
ljh130334 50e030e
fix: conflict 수정
ljh130334 4776544
fix: 중복 라우트 제거
ljh130334 11a035a
refactor: Book 인터페이스 정의 및 타입 안전성 개선
ljh130334 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or 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 hidden or 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,85 @@ | ||
| import styled from '@emotion/styled'; | ||
| import { typography, semanticColors, colors } from '../../styles/global/global'; | ||
|
|
||
| export const PhotoContainer = styled.div` | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: 12px; | ||
| `; | ||
|
|
||
| export const PhotoGrid = styled.div` | ||
| display: flex; | ||
| gap: 12px; | ||
| align-items: center; | ||
| `; | ||
|
|
||
| export const AddPhotoButton = styled.button` | ||
| width: 80px; | ||
| height: 80px; | ||
| border: 1px solid ${colors.grey[300]}; | ||
| background-color: ${semanticColors.background.cardDark}; | ||
| cursor: pointer; | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| transition: all 0.2s; | ||
|
|
||
| img { | ||
| width: 24px; | ||
| height: 24px; | ||
| } | ||
|
|
||
| &:hover:not(:disabled) { | ||
| border-color: ${semanticColors.text.primary}; | ||
| } | ||
|
|
||
| &:disabled { | ||
| background-color: ${colors.darkgrey.dark}; | ||
| border: 1px solid ${colors.darkgrey.main}; | ||
| cursor: not-allowed; | ||
| } | ||
| `; | ||
|
|
||
| export const PhotoItem = styled.div` | ||
| position: relative; | ||
| width: 80px; | ||
| height: 80px; | ||
| `; | ||
|
|
||
| export const PhotoImage = styled.img` | ||
| width: 100%; | ||
| height: 100%; | ||
| object-fit: cover; | ||
| border: 1px solid ${colors.grey[300]}; | ||
| `; | ||
|
|
||
| export const RemoveButton = styled.button` | ||
| position: absolute; | ||
| top: 0px; | ||
| right: 0px; | ||
| width: 24px; | ||
| height: 24px; | ||
| background-color: rgba(0, 0, 0, 0.6); | ||
| border: none; | ||
| cursor: pointer; | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| border: 1px solid ${colors.grey[300]}; | ||
|
|
||
| img { | ||
| width: 12px; | ||
| height: 12px; | ||
| } | ||
|
|
||
| &:hover { | ||
| background-color: rgba(0, 0, 0, 0.8); | ||
| } | ||
| `; | ||
|
|
||
| export const PhotoCount = styled.div` | ||
| align-self: flex-end; | ||
| color: ${semanticColors.text.point.green}; | ||
| font-size: ${typography.fontSize.xs}; | ||
| font-weight: ${typography.fontWeight.regular}; | ||
| `; |
This file contains hidden or 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,74 @@ | ||
| import { useRef } from 'react'; | ||
| import { Section, SectionTitle } from '../../pages/group/CommonSection.styled'; | ||
| import { | ||
| PhotoContainer, | ||
| PhotoGrid, | ||
| AddPhotoButton, | ||
| PhotoImage, | ||
| RemoveButton, | ||
| PhotoCount, | ||
| } from './PhotoSection.styled'; | ||
| import plusIcon from '../../assets/post/plus.svg'; | ||
| import plusDisabledIcon from '../../assets/post/plus-disabled.svg'; | ||
| import closeIcon from '../../assets/post/close.svg'; | ||
|
|
||
| interface PhotoSectionProps { | ||
| photos: File[]; | ||
| onPhotoAdd: (files: File[]) => void; | ||
| onPhotoRemove: (index: number) => void; | ||
| } | ||
|
|
||
| const PhotoSection = ({ photos, onPhotoAdd, onPhotoRemove }: PhotoSectionProps) => { | ||
| const fileInputRef = useRef<HTMLInputElement>(null); | ||
|
|
||
| const handleFileInputClick = () => { | ||
| fileInputRef.current?.click(); | ||
| }; | ||
|
|
||
| const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
| const files = Array.from(e.target.files || []); | ||
| if (files.length > 0) { | ||
| onPhotoAdd(files); | ||
| } | ||
| // input 값 초기화 (같은 파일을 다시 선택할 수 있도록) | ||
| e.target.value = ''; | ||
| }; | ||
|
|
||
| const createImageUrl = (file: File) => { | ||
| return URL.createObjectURL(file); | ||
| }; | ||
|
|
||
| const isDisabled = photos.length >= 3; | ||
|
|
||
| return ( | ||
| <Section> | ||
| <SectionTitle>사진 추가</SectionTitle> | ||
| <PhotoContainer> | ||
| <PhotoGrid> | ||
| <AddPhotoButton onClick={handleFileInputClick} disabled={isDisabled}> | ||
| <img src={isDisabled ? plusDisabledIcon : plusIcon} alt="사진 추가" /> | ||
| </AddPhotoButton> | ||
| {photos.map((photo, index) => ( | ||
| <div key={index} style={{ position: 'relative', width: '80px', height: '80px' }}> | ||
| <PhotoImage src={createImageUrl(photo)} alt={`선택된 사진 ${index + 1}`} /> | ||
| <RemoveButton onClick={() => onPhotoRemove(index)}> | ||
| <img src={closeIcon} alt="삭제" /> | ||
| </RemoveButton> | ||
| </div> | ||
| ))} | ||
| </PhotoGrid> | ||
| <PhotoCount>{photos.length}/3개</PhotoCount> | ||
| <input | ||
| ref={fileInputRef} | ||
| type="file" | ||
| accept="image/*" | ||
| multiple | ||
| style={{ display: 'none' }} | ||
| onChange={handleFileChange} | ||
| /> | ||
| </PhotoContainer> | ||
| </Section> | ||
| ); | ||
| }; | ||
|
|
||
| export default PhotoSection; | ||
This file contains hidden or 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,33 @@ | ||
| import styled from '@emotion/styled'; | ||
| import { typography, semanticColors } from '../../styles/global/global'; | ||
|
|
||
| export const TextAreaBox = styled.div` | ||
| position: relative; | ||
| display: flex; | ||
| flex-direction: column; | ||
| `; | ||
|
|
||
| export const TextArea = styled.textarea` | ||
| width: 100%; | ||
| min-height: 100px; | ||
| background-color: ${semanticColors.background.primary}; | ||
| color: ${semanticColors.text.secondary}; | ||
| font-size: ${typography.fontSize.sm}; | ||
| font-weight: ${typography.fontWeight.regular}; | ||
| font-family: ${typography.fontFamily.primary}; | ||
| resize: none; | ||
| outline: none; | ||
| border: none; | ||
|
|
||
| &::placeholder { | ||
| color: ${semanticColors.text.ghost}; | ||
| } | ||
| `; | ||
|
|
||
| export const CharacterCount = styled.div` | ||
| align-self: flex-end; | ||
| margin-top: 12px; | ||
| color: ${semanticColors.text.point.green}; | ||
| font-size: ${typography.fontSize.xs}; | ||
| font-weight: ${typography.fontWeight.regular}; | ||
| `; |
This file contains hidden or 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,31 @@ | ||
| import { Section, SectionTitle } from '../../pages/group/CommonSection.styled'; | ||
| import { TextAreaBox, TextArea, CharacterCount } from './PostContentSection.styled'; | ||
|
|
||
| interface PostContentSectionProps { | ||
| content: string; | ||
| onContentChange: (value: string) => void; | ||
| } | ||
|
|
||
| const PostContentSection = ({ content, onContentChange }: PostContentSectionProps) => { | ||
| const maxLength = 2000; | ||
|
|
||
| return ( | ||
| <Section> | ||
| <SectionTitle>글 작성</SectionTitle> | ||
| <TextAreaBox> | ||
| <TextArea | ||
| placeholder="...한 생각이 들었어요. 🤔" | ||
| value={content} | ||
| onChange={e => onContentChange(e.target.value)} | ||
| maxLength={maxLength} | ||
| rows={4} | ||
| /> | ||
| <CharacterCount> | ||
| {content.length} / {maxLength} | ||
| </CharacterCount> | ||
| </TextAreaBox> | ||
| </Section> | ||
| ); | ||
| }; | ||
|
|
||
| export default PostContentSection; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
메모리 누수 방지를 위해 URL 해제가 필요합니다.
URL.createObjectURL로 생성된 blob URL은 수동으로 해제해야 메모리 누수를 방지할 수 있습니다.🤖 Prompt for AI Agents