|
2 | 2 |
|
3 | 3 | import SearchBar from "@/components/searchBar";
|
4 | 4 | import BoardPreview from "@/components/BoardPreview/BoardPreview";
|
5 |
| -import BoardSelector from "@/components/BoardPreview/BoardSelector"; |
6 | 5 | import { useState } from "react";
|
7 | 6 | import UserMenu from "@/components/UserMenu/UserMenu";
|
8 | 7 | import OtherServices from "@/components/UserMenu/OtherServices";
|
| 8 | +import Link from "next/link"; |
| 9 | + |
| 10 | +// 옵션 타입 정의 |
| 11 | +interface UIOptions { |
| 12 | + showWriter: boolean; |
| 13 | + showBoard: boolean; |
| 14 | + showProfile: boolean; |
| 15 | + showHit: boolean; |
| 16 | + showStatus: boolean; |
| 17 | + showAttachment: boolean; |
| 18 | + showRank: boolean; |
| 19 | + showAnswerStatus: boolean; |
| 20 | + showTimeAgo: boolean; |
| 21 | +} |
| 22 | + |
| 23 | +// 옵션 컨트롤 컴포넌트 타입 정의 |
| 24 | +interface OptionControlProps { |
| 25 | + options: UIOptions; |
| 26 | + onChange: (option: string, value: boolean) => void; |
| 27 | +} |
| 28 | + |
| 29 | +// 옵션 컨트롤 컴포넌트 |
| 30 | +const OptionControl = ({ options, onChange }: OptionControlProps) => { |
| 31 | + return ( |
| 32 | + <div className="p-4 bg-white rounded-lg shadow-sm mb-4 border border-gray-200"> |
| 33 | + <h3 className="text-lg font-bold mb-3">UI 옵션 설정</h3> |
| 34 | + <div className="grid grid-cols-3 gap-2"> |
| 35 | + {Object.entries(options).map(([key, value]) => ( |
| 36 | + <div key={key} className="flex items-center"> |
| 37 | + <input |
| 38 | + type="checkbox" |
| 39 | + id={key} |
| 40 | + checked={value} |
| 41 | + onChange={() => onChange(key, !value)} |
| 42 | + className="mr-2" |
| 43 | + /> |
| 44 | + <label htmlFor={key} className="text-sm"> |
| 45 | + {key.replace('show', '')} |
| 46 | + </label> |
| 47 | + </div> |
| 48 | + ))} |
| 49 | + </div> |
| 50 | + </div> |
| 51 | + ); |
| 52 | +}; |
9 | 53 |
|
10 | 54 | export default function Home() {
|
11 | 55 | const [inputValue, setInputValue] = useState("");
|
12 |
| - const [board, setBoard] = useState("talk"); |
13 |
| - |
14 |
| - const handleBoardSelect = (newBoard: string) => { |
15 |
| - setBoard(newBoard); // 🔹 하위 컴포넌트에서 받은 데이터를 상태로 저장 |
| 56 | + |
| 57 | + // UI 옵션 상태 관리 |
| 58 | + const [uiOptions, setUiOptions] = useState<UIOptions>({ |
| 59 | + showWriter: true, |
| 60 | + showBoard: true, |
| 61 | + showProfile: false, |
| 62 | + showHit: true, |
| 63 | + showStatus: true, |
| 64 | + showAttachment: true, |
| 65 | + showRank: false, |
| 66 | + showAnswerStatus: false, |
| 67 | + showTimeAgo: true |
| 68 | + }); |
| 69 | + |
| 70 | + // UI 옵션 변경 핸들러 |
| 71 | + const handleOptionChange = (option: string, value: boolean) => { |
| 72 | + setUiOptions(prev => ({ |
| 73 | + ...prev, |
| 74 | + [option]: value |
| 75 | + })); |
16 | 76 | };
|
17 | 77 |
|
18 |
| - const boardData = [ |
19 |
| - { |
20 |
| - type: "top" as const, |
21 |
| - title: "🔥 지금 핫한 글", |
22 |
| - posts: [ |
23 |
| - { id: 1, rank: 1, title: "핫한 소식", image: true, author: "유저1", timeAgo: "9분전", likes: 50, dislikes: 2, comments: 15 }, |
24 |
| - { id: 2, rank: 2, title: "이 글 대박임", image: false, author: "유저2", timeAgo: "9분전", likes: 40, dislikes: 3, comments: 10 }, |
25 |
| - { id: 10, rank: 3, title: "이 글 대박임", image: false, author: "유저2", timeAgo: "9분전", likes: 40, dislikes: 3, comments: 10 } |
26 |
| - ], |
27 |
| - }, |
28 |
| - { |
29 |
| - type: "all" as const, |
30 |
| - title: "🕑 방금 올라온 글", |
31 |
| - posts: [ |
32 |
| - { id: 3, title: "새로운 정보 공유!", image: true, boardName: "자유게시판", author: "유저3", timeAgo: "9분 전", likes: 5, dislikes: 0, comments: 1 }, |
33 |
| - { id: 4, title: "이거 봤어?", image: false, boardName: "공지사항", author: "유저4", timeAgo: "15분 전", likes: 2, dislikes: 1, comments: 0 }, |
34 |
| - { id: 127, title: "이거 봤어?", image: false, boardName: "공지사항", author: "유저4", timeAgo: "15분 전", likes: 2, dislikes: 1, comments: 0 }, |
35 |
| - ], |
36 |
| - }, |
37 |
| - { |
38 |
| - type: "with-school" as const, |
39 |
| - title: "🏫 학교에게 전합니다", |
40 |
| - posts: [ |
41 |
| - { id: 5, title: "시설 문제 개선 요청", image: false, answered: true, author: "유저5", timeAgo: "1시간 전", likes: 20, dislikes: 3, comments: 5 }, |
42 |
| - { id: 6, title: "이 문제 해결해주세요", image: true, answered: false, author: "유저6", timeAgo: "3시간 전", likes: 15, dislikes: 2, comments: 3 }, |
43 |
| - { id: 11, title: "이 문제 해결해주세요", image: true, answered: false, author: "유저6", timeAgo: "3시간 전", likes: 15, dislikes: 2, comments: 3 }, |
44 |
| - |
45 |
| - ], |
46 |
| - }, |
47 |
| - { |
48 |
| - type: "talk" as const, |
49 |
| - title: "자유게시판", |
50 |
| - posts: [ |
51 |
| - { id: 7, title: "오늘 하루 어땠나요?", image: false, author: "유저7", likes: 10, dislikes: 1, comments: 2 }, |
52 |
| - { id: 8, title: "이거 꿀팁임", image: true, author: "유저8", likes: 25, dislikes: 0, comments: 7 }, |
53 |
| - { id: 12, title: "이거 꿀팁임", image: true, author: "유저8", likes: 25, dislikes: 0, comments: 7 }, |
54 |
| - ], |
| 78 | + // 테스트 데이터 |
| 79 | + const testPosts = [ |
| 80 | + { |
| 81 | + id: 1, |
| 82 | + title: "게시판 컴포넌트 테스트 글입니다", |
| 83 | + author: "개발자", |
| 84 | + timeAgo: "9분 전", |
| 85 | + likes: 50, |
| 86 | + dislikes: 2, |
| 87 | + comments: 15, |
| 88 | + boardName: "개발 게시판", |
| 89 | + hasAttachment: true, |
| 90 | + attachmentType: 'image' as const, |
| 91 | + hit: 230, |
| 92 | + answered: true, |
| 93 | + profileImage: "/assets/ServiceAra.svg" |
55 | 94 | },
|
56 |
| - { |
57 |
| - type: "portal-notice" as const, |
58 |
| - title: "포탈 공지", |
59 |
| - posts: [ |
60 |
| - { id: 21, title: "시설 문제 개선 요청", image: false, answered: true, author: "유저5", timeAgo: "1시간 전", likes: 20, dislikes: 3, comments: 5 }, |
61 |
| - { id: 22, title: "이 문제 해결해주세요", image: true, answered: false, author: "유저6", timeAgo: "3시간 전", likes: 15, dislikes: 2, comments: 3 }, |
62 |
| - { id: 13, title: "이 문제 해결해주세요", image: true, answered: false, author: "유저6", timeAgo: "3시간 전", likes: 15, dislikes: 2, comments: 3 }, |
63 |
| - ], |
| 95 | + { |
| 96 | + id: 2, |
| 97 | + title: "UI 옵션을 변경해보세요!", |
| 98 | + author: "디자이너", |
| 99 | + timeAgo: "20분 전", |
| 100 | + likes: 40, |
| 101 | + dislikes: 3, |
| 102 | + comments: 10, |
| 103 | + boardName: "디자인 게시판", |
| 104 | + hasAttachment: false, |
| 105 | + hit: 185, |
| 106 | + answered: false |
64 | 107 | },
|
65 |
| - { |
66 |
| - type: "student-group" as const, |
67 |
| - title: "학생단체 및 동아리", |
68 |
| - posts: [ |
69 |
| - { id: 30, title: "스팍스으으", image: false, answered: true, author: "유저5", timeAgo: "1시간 전", likes: 20, dislikes: 3, comments: 5 }, |
70 |
| - { id: 31, title: "이 문제 해결해주세요", image: true, answered: false, author: "유저6", timeAgo: "3시간 전", likes: 15, dislikes: 2, comments: 3 }, |
71 |
| - { id: 32, title: "이 문제 해결해주세요", image: true, answered: false, author: "유저6", timeAgo: "3시간 전", likes: 15, dislikes: 2, comments: 3 }, |
72 |
| - ], |
73 |
| - }, |
74 |
| - { |
75 |
| - type: "market" as const, |
76 |
| - title: "거래", |
77 |
| - posts: [ |
78 |
| - { id: 33, title: "어은동 원룸", image: false, answered: true, author: "유저5", timeAgo: "1시간 전", likes: 20, dislikes: 3, comments: 5 }, |
79 |
| - { id: 34, title: "냐옹", image: true, answered: false, author: "유저6", timeAgo: "3시간 전", likes: 15, dislikes: 2, comments: 3 }, |
80 |
| - { id: 35, title: "이 문제 해결해주세요", image: true, answered: false, author: "유저6", timeAgo: "3시간 전", likes: 15, dislikes: 2, comments: 3 }, |
81 |
| - ], |
| 108 | + { |
| 109 | + id: 3, |
| 110 | + title: "프로필 이미지와 순위 표시 테스트", |
| 111 | + author: "테스터", |
| 112 | + timeAgo: "1시간 전", |
| 113 | + likes: 35, |
| 114 | + dislikes: 1, |
| 115 | + comments: 8, |
| 116 | + boardName: "테스트 게시판", |
| 117 | + hasAttachment: true, |
| 118 | + attachmentType: 'both' as const, |
| 119 | + hit: 142, |
| 120 | + answered: true, |
| 121 | + profileImage: "/assets/ServiceAra.svg" |
82 | 122 | },
|
| 123 | + { |
| 124 | + id: 4, |
| 125 | + title: "첨부파일 표시 기능 확인", |
| 126 | + author: "사용자", |
| 127 | + timeAgo: "2시간 전", |
| 128 | + likes: 25, |
| 129 | + dislikes: 0, |
| 130 | + comments: 5, |
| 131 | + boardName: "일반 게시판", |
| 132 | + hasAttachment: true, |
| 133 | + attachmentType: 'file' as const, |
| 134 | + hit: 98, |
| 135 | + answered: false |
| 136 | + } |
83 | 137 | ];
|
| 138 | + |
84 | 139 | return (
|
85 |
| - <div> |
| 140 | + <div className="max-w-[1200px] mx-auto"> |
86 | 141 | <div className="absolute top-0 left-0 w-full h-[400px] bg-gradient-to-b from-[#FFEDD2] to-[#FFFFFF] -z-10"></div>
|
| 142 | + |
87 | 143 | <div className="h-[220px] w-full flex justify-center items-center">
|
88 | 144 | <SearchBar
|
89 | 145 | value={inputValue}
|
90 |
| - onChange={(e) => setInputValue(e.target.value)} |
| 146 | + onChange={(e: React.ChangeEvent<HTMLInputElement>) => setInputValue(e.target.value)} |
| 147 | + /> |
| 148 | + </div> |
| 149 | + |
| 150 | + {/* UI 옵션 컨트롤 */} |
| 151 | + <div className="mb-6"> |
| 152 | + <OptionControl |
| 153 | + options={uiOptions} |
| 154 | + onChange={handleOptionChange} |
91 | 155 | />
|
92 | 156 | </div>
|
93 |
| - <div className="flex w-full px-[80px]"> |
94 |
| - <div className="flex items-center justify-center p-6 border-[1px] border-gray-200 rounded-[20px] shadow-sm w-[857px] bg-white"> |
| 157 | + |
| 158 | + {/* 게시판 프리뷰 테스트 영역 */} |
| 159 | + <div className="flex justify-center"> |
| 160 | + <div className="p-6 border border-gray-200 rounded-[20px] shadow-sm bg-white"> |
95 | 161 | <BoardPreview
|
96 |
| - type={boardData[0].type} |
97 |
| - title={boardData[0].title} |
98 |
| - posts={boardData[0].posts} |
| 162 | + boardTitle="🧪 게시판 컴포넌트 테스트" |
| 163 | + posts={testPosts} |
| 164 | + boardLink="/board/test" |
| 165 | + {...uiOptions} |
99 | 166 | />
|
100 |
| - <BoardPreview |
101 |
| - type={boardData[1].type} |
102 |
| - title={boardData[1].title} |
103 |
| - posts={boardData[1].posts} |
104 |
| - /> |
105 | 167 | </div>
|
106 |
| - |
107 |
| - <div className="bg-white border-[1px] border-gray-200 rounded-[20px] shadow-sm min-w-[355px] p-[20px] space-y-4"> |
108 |
| - <UserMenu /> |
109 |
| - <OtherServices /> |
110 |
| - </div> |
111 |
| - </div> |
112 |
| - |
113 |
| - {/*자유게시판 , 포탈공지, 학생 및 단체 동아리, 거래, 소통, 뉴스*/} |
114 |
| - <div className ="items-center justify-center p-6 border-[1px] border-gray-200 rounded-[20px] shadow-sm w-[857px]"> |
115 |
| - <BoardSelector onBoardSelect={handleBoardSelect} /> |
116 |
| - {board === "talk" && ( |
117 |
| - <BoardPreview |
118 |
| - type={boardData[3].type} |
119 |
| - title={boardData[3].title} |
120 |
| - posts={boardData[3].posts} |
121 |
| - />)} |
122 |
| - {board === "portal-notice" && ( |
123 |
| - <BoardPreview |
124 |
| - type={boardData[4].type} |
125 |
| - title={boardData[4].title} |
126 |
| - posts={boardData[4].posts} |
127 |
| - />)} |
128 |
| - {board === "student-group" && ( |
129 |
| - <BoardPreview |
130 |
| - type={boardData[5].type} |
131 |
| - title={boardData[5].title} |
132 |
| - posts={boardData[5].posts} |
133 |
| - />)} |
134 |
| - {board === "market" && ( |
135 |
| - <BoardPreview |
136 |
| - type={boardData[6].type} |
137 |
| - title={boardData[6].title} |
138 |
| - posts={boardData[6].posts} |
139 |
| - />)} |
140 |
| - </div> |
141 |
| - |
142 |
| - <div className ="items-center justify-center p-6 border-[1px] border-gray-200 rounded-[20px] shadow-sm w-[355px]"> |
143 |
| - <BoardPreview |
144 |
| - type={boardData[2].type} |
145 |
| - title={boardData[2].title} |
146 |
| - posts={boardData[2].posts} |
147 |
| - /> |
148 | 168 | </div>
|
149 | 169 | </div>
|
150 | 170 | );
|
|
0 commit comments