feat(schedule): 검색 결과 없음 UI 추가 및 빈 상태 위치 개선
- PC: 검색 모드에서 결과 0개일 때 아무것도 안 나오던 문제 수정 (돋보기 아이콘 + 검색어 표시), 검색 중 로딩 구분 - 모바일: 검색/날짜별 빈 상태를 아이콘 포함 디자인으로 통일 - 빈 상태/로딩을 일정 영역 기준으로 배치 (PC: 상단 30% 지점, 모바일: 중앙) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
8b8b9a7f53
commit
dd5ef48592
2 changed files with 41 additions and 8 deletions
|
|
@ -695,7 +695,7 @@ function MobileSchedule() {
|
||||||
className="mobile-content"
|
className="mobile-content"
|
||||||
ref={isSearchMode && searchTerm && !showSuggestionsScreen ? scrollContainerRef : contentRef}
|
ref={isSearchMode && searchTerm && !showSuggestionsScreen ? scrollContainerRef : contentRef}
|
||||||
>
|
>
|
||||||
<div className={`px-4 pb-4 ${isSearchMode && showSuggestionsScreen ? 'pt-0' : 'pt-4'}`}>
|
<div className={`px-4 pb-4 min-h-full flex flex-col ${isSearchMode && showSuggestionsScreen ? 'pt-0' : 'pt-4'}`}>
|
||||||
{isSearchMode ? (
|
{isSearchMode ? (
|
||||||
showSuggestionsScreen ? (
|
showSuggestionsScreen ? (
|
||||||
// 추천 검색어 화면
|
// 추천 검색어 화면
|
||||||
|
|
@ -720,11 +720,19 @@ function MobileSchedule() {
|
||||||
) : !searchTerm ? (
|
) : !searchTerm ? (
|
||||||
<div className="text-center py-8 text-gray-400">검색어를 입력하세요</div>
|
<div className="text-center py-8 text-gray-400">검색어를 입력하세요</div>
|
||||||
) : searchLoading ? (
|
) : searchLoading ? (
|
||||||
<div className="flex justify-center py-8">
|
<div className="flex-1 flex items-center justify-center">
|
||||||
<div className="w-8 h-8 border-2 border-primary border-t-transparent rounded-full animate-spin" />
|
<div className="w-8 h-8 border-2 border-primary border-t-transparent rounded-full animate-spin" />
|
||||||
</div>
|
</div>
|
||||||
) : searchResults.length === 0 ? (
|
) : searchResults.length === 0 ? (
|
||||||
<div className="text-center py-8 text-gray-400">검색 결과가 없습니다</div>
|
<div className="flex-1 flex flex-col items-center justify-center">
|
||||||
|
<div className="w-20 h-20 bg-gray-100 rounded-full flex items-center justify-center mb-3">
|
||||||
|
<svg className="w-10 h-10 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M21 21l-4.35-4.35M11 18a7 7 0 110-14 7 7 0 010 14z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-400 text-base font-medium mb-1">검색 결과가 없습니다</p>
|
||||||
|
<p className="text-gray-300 text-sm">'<span className="text-gray-400">{searchTerm}</span>'에 대한 일정을 찾을 수 없습니다</p>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
|
|
@ -771,12 +779,19 @@ function MobileSchedule() {
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
) : loading ? (
|
) : loading ? (
|
||||||
<div className="flex justify-center py-8">
|
<div className="flex-1 flex items-center justify-center">
|
||||||
<div className="w-8 h-8 border-2 border-primary border-t-transparent rounded-full animate-spin" />
|
<div className="w-8 h-8 border-2 border-primary border-t-transparent rounded-full animate-spin" />
|
||||||
</div>
|
</div>
|
||||||
) : selectedDateSchedules.length === 0 ? (
|
) : selectedDateSchedules.length === 0 ? (
|
||||||
<div className="text-center py-8 text-gray-400">
|
<div className="flex-1 flex flex-col items-center justify-center">
|
||||||
{selectedDate.getMonth() + 1}월 {selectedDate.getDate()}일 일정이 없습니다
|
<div className="w-20 h-20 bg-gray-100 rounded-full flex items-center justify-center mb-3">
|
||||||
|
<svg className="w-10 h-10 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-400 text-base font-medium">
|
||||||
|
{selectedDate.getMonth() + 1}월 {selectedDate.getDate()}일 일정이 없습니다
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ function PCSchedule() {
|
||||||
fetchNextPage,
|
fetchNextPage,
|
||||||
hasNextPage,
|
hasNextPage,
|
||||||
isFetchingNextPage,
|
isFetchingNextPage,
|
||||||
|
isLoading: isSearchLoading,
|
||||||
} = useInfiniteQuery({
|
} = useInfiniteQuery({
|
||||||
queryKey: ['scheduleSearch', searchTerm],
|
queryKey: ['scheduleSearch', searchTerm],
|
||||||
queryFn: async ({ pageParam = 0 }) => {
|
queryFn: async ({ pageParam = 0 }) => {
|
||||||
|
|
@ -546,7 +547,7 @@ function PCSchedule() {
|
||||||
{/* 스케줄 목록 */}
|
{/* 스케줄 목록 */}
|
||||||
<div ref={scrollContainerRef} className="flex-1 min-h-0 overflow-y-auto space-y-4 py-2 pr-2">
|
<div ref={scrollContainerRef} className="flex-1 min-h-0 overflow-y-auto space-y-4 py-2 pr-2">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="text-center py-20 text-gray-500">로딩 중...</div>
|
<div className="h-full flex items-center justify-center text-gray-500">로딩 중...</div>
|
||||||
) : filteredSchedules.length > 0 ? (
|
) : filteredSchedules.length > 0 ? (
|
||||||
isSearchMode && searchTerm ? (
|
isSearchMode && searchTerm ? (
|
||||||
<>
|
<>
|
||||||
|
|
@ -609,9 +610,26 @@ function PCSchedule() {
|
||||||
</motion.div>
|
</motion.div>
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
|
) : isSearchMode && searchTerm ? (
|
||||||
|
isSearchLoading ? (
|
||||||
|
<div className="h-full flex items-center justify-center text-gray-500">검색 중...</div>
|
||||||
|
) : (
|
||||||
|
<motion.div initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} className="h-full flex flex-col items-center justify-start pt-[20%]">
|
||||||
|
<div className="w-24 h-24 bg-gray-100 rounded-full flex items-center justify-center mb-4">
|
||||||
|
<svg className="w-12 h-12 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M21 21l-4.35-4.35M11 18a7 7 0 110-14 7 7 0 010 14z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-400 text-lg font-medium mb-1">검색 결과가 없습니다</p>
|
||||||
|
<p className="text-gray-300 text-sm">
|
||||||
|
'<span className="text-gray-400">{searchTerm}</span>'
|
||||||
|
{selectedCategories.length > 0 ? ' 검색 결과가 없습니다' : '에 대한 일정을 찾을 수 없습니다'}
|
||||||
|
</p>
|
||||||
|
</motion.div>
|
||||||
|
)
|
||||||
) : (
|
) : (
|
||||||
!isSearchMode && (
|
!isSearchMode && (
|
||||||
<motion.div initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} className="flex flex-col items-center justify-center py-16">
|
<motion.div initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} className="h-full flex flex-col items-center justify-start pt-[20%]">
|
||||||
<div className="w-24 h-24 bg-gray-100 rounded-full flex items-center justify-center mb-4">
|
<div className="w-24 h-24 bg-gray-100 rounded-full flex items-center justify-center mb-4">
|
||||||
<svg className="w-12 h-12 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg className="w-12 h-12 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue