From 45925a26c04624d5ccf609bd5df5a95529b6c414 Mon Sep 17 00:00:00 2001 From: 8t-truck Date: Sat, 6 Sep 2025 16:33:22 +0900 Subject: [PATCH 01/16] =?UTF-8?q?=EA=B8=80=EC=93=B0=EA=B8=B0=20=EC=B0=BD?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icons/check.svg | 3 ++ src/app/write/composer-search.tsx | 60 +++++++++++++++++++++++++++++++ src/app/write/page.tsx | 30 ++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 public/icons/check.svg create mode 100644 src/app/write/composer-search.tsx diff --git a/public/icons/check.svg b/public/icons/check.svg new file mode 100644 index 0000000..f4c8588 --- /dev/null +++ b/public/icons/check.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/app/write/composer-search.tsx b/src/app/write/composer-search.tsx new file mode 100644 index 0000000..bfcc5d8 --- /dev/null +++ b/src/app/write/composer-search.tsx @@ -0,0 +1,60 @@ +'use client'; + +import { useState } from 'react'; +import Image from 'next/image'; + +const composers = [ + { id: 1, name: 'L.V. Beethoven', era: '고전주의' }, + { id: 2, name: 'W.A. Mozart', era: '고전주의' }, + { id: 3, name: 'J.S. Bach', era: '바로크' }, + { id: 4, name: 'F. Chopin', era: '낭만주의' }, + { id: 5, name: 'S. Rachmaninoff', era: '낭만주의' }, +]; + +interface ComposerSearchProps { + onSelectComposer: (composerName: string) => void; +} + +export default function ComposerSearch({ onSelectComposer }: ComposerSearchProps) { + const [searchTerm, setSearchTerm] = useState(''); + + const filteredComposers = composers.filter(composer => + composer.name.toLowerCase().includes(searchTerm.toLowerCase()) + ); + + return ( +
+
+ setSearchTerm(e.target.value)} + className="w-full pl-10 pr-4 py-2.5 bg-gray-100 rounded-lg focus:outline-none placeholder-gray-400 text-sm" + /> +
+ search +
+
+
+ {filteredComposers.map(composer => ( + + ))} +
+
+ ); +} diff --git a/src/app/write/page.tsx b/src/app/write/page.tsx index 9a0a128..144ed8e 100644 --- a/src/app/write/page.tsx +++ b/src/app/write/page.tsx @@ -3,6 +3,7 @@ import { useState } from 'react'; import Image from 'next/image'; import { useRouter } from 'next/navigation'; +import ComposerSearch from './composer-search'; // Reusable component for section headers const SectionHeader = ({ title }: { title: string }) => ( @@ -20,6 +21,13 @@ export default function WritePage() { const [isDropdownOpen, setIsDropdownOpen] = useState(false); const [selectedType, setSelectedType] = useState('라흐마니노프 이야기'); const postTypes = ['큐레이션 글', '라흐마니노프 이야기']; + const [selectedComposer, setSelectedComposer] = useState(null); + const [showComposerSearch, setShowComposerSearch] = useState(true); + + const handleSelectComposer = (composerName: string) => { + setSelectedComposer(composerName); + setShowComposerSearch(false); + }; const isButtonEnabled = title.trim() !== '' && content.trim() !== ''; @@ -90,6 +98,28 @@ export default function WritePage() { )} + {selectedType === '큐레이션 글' && ( + <> + + {showComposerSearch ? ( + + ) : ( +
+

{selectedComposer}

+ +
+ )} + + )} +
Date: Sat, 6 Sep 2025 17:07:14 +0900 Subject: [PATCH 02/16] =?UTF-8?q?=EB=B0=B1=EC=97=94=EB=93=9C=EC=97=90=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=EB=A5=BC=20=EB=B3=B4=EB=82=B4?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/write/components/SectionHeader.tsx | 6 + src/app/write/components/WriteForm.tsx | 165 +++++++++++++++++++++ src/app/write/components/WriteHeader.tsx | 32 ++++ src/app/write/page.tsx | 76 +++++++++- 4 files changed, 273 insertions(+), 6 deletions(-) create mode 100644 src/app/write/components/SectionHeader.tsx create mode 100644 src/app/write/components/WriteForm.tsx create mode 100644 src/app/write/components/WriteHeader.tsx diff --git a/src/app/write/components/SectionHeader.tsx b/src/app/write/components/SectionHeader.tsx new file mode 100644 index 0000000..27ca15f --- /dev/null +++ b/src/app/write/components/SectionHeader.tsx @@ -0,0 +1,6 @@ +// src/app/write/components/SectionHeader.tsx +export const SectionHeader = ({ title }: { title: string }) => ( +
+

{title}

+
+); diff --git a/src/app/write/components/WriteForm.tsx b/src/app/write/components/WriteForm.tsx new file mode 100644 index 0000000..f3c76a1 --- /dev/null +++ b/src/app/write/components/WriteForm.tsx @@ -0,0 +1,165 @@ +// src/app/write/components/WriteForm.tsx +'use client'; + +import { useRef, useState } from 'react'; +import Image from 'next/image'; +import ComposerSearch from '../composer-search'; +import { SectionHeader } from './SectionHeader'; + +interface WriteFormProps { + title: string; + setTitle: (title: string) => void; + content: string; + setContent: (content: string) => void; + hashtags: string; + setHashtags: (hashtags: string) => void; + link: string; + setLink: (link: string) => void; + imageFile: File | null; + setImageFile: (file: File | null) => void; + selectedType: string; + setSelectedType: (type: string) => void; + selectedComposer: string | null; + setSelectedComposer: (composer: string | null) => void; +} + +export default function WriteForm({ + title, setTitle, content, setContent, hashtags, setHashtags, link, setLink, + imageFile, setImageFile, selectedType, setSelectedType, selectedComposer, setSelectedComposer +}: WriteFormProps) { + const fileInputRef = useRef(null); + const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const postTypes = ['큐레이션 글', '라흐마니노프 이야기']; + const [showComposerSearch, setShowComposerSearch] = useState(true); + + const handleSelectComposer = (composerName: string) => { + setSelectedComposer(composerName); + setShowComposerSearch(false); + }; + + const handleImageChange = (event: React.ChangeEvent) => { + if (event.target.files && event.target.files[0]) { + setImageFile(event.target.files[0]); + } + }; + + const handleImageUploadClick = () => { + fileInputRef.current?.click(); + }; + + return ( +
+ +
+ + {isDropdownOpen && ( +
+ {postTypes.map((type) => ( +
{ + setSelectedType(type); + setIsDropdownOpen(false); + }} + className="px-6 py-3 hover:bg-gray-100 cursor-pointer text-sm font-medium" + > + {type} +
+ ))} +
+ )} +
+ + {selectedType === '큐레이션 글' && ( + <> + + {showComposerSearch ? ( + + ) : ( +
+

{selectedComposer}

+ +
+ )} + + )} + + +
+ setTitle(e.target.value)} + className="w-full py-2 text-sm font-medium focus:outline-none placeholder-zinc-300" + /> +
+ + +
+