Skip to content
Merged
4 changes: 2 additions & 2 deletions src/app/features/dashboard_Id/components/EditColumnModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ export default function EditColumnModal() {
<button
type="button"
onClick={handleDeleteClick}
className="BG-white Border-btn Text-gray h-54 w-144 rounded-8 px-16 py-10 text-16 font-medium"
className="BG-white Border-btn Text-gray h-54 w-256 rounded-8 px-16 py-10 text-16 font-medium"
>
삭제
</button>
Expand All @@ -167,7 +167,7 @@ export default function EditColumnModal() {
<button
type="submit"
disabled={isUpdateDisabled}
className={`BG-violet h-54 w-144 rounded-8 px-16 py-10 text-16 font-medium text-white transition-opacity ${
className={`BG-violet h-54 w-256 rounded-8 px-16 py-10 text-16 font-medium text-white transition-opacity ${
isUpdateDisabled
? 'cursor-not-allowed opacity-50'
: 'hover:opacity-90'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,34 +52,74 @@ export default function InvitedDashboardRow({
const handleReject = () => handleInvitationResponse(false)

return (
<div className="grid grid-cols-3 items-center gap-20 border-b border-gray-100 py-20 pl-36 pr-32">
{/* 대시보드 이름 */}
<span className="Text-black text-16">
{invitation.dashboard.title || '제목 없음'}
</span>

{/* 초대자 */}
<span className="Text-black text-center text-16">
{invitation.inviter.nickname || invitation.inviter.email}
</span>

{/* 수락/거절 버튼들 */}
<div className="flex items-center justify-center gap-10">
<button
onClick={handleAccept}
disabled={isProcessing}
className="BG-blue flex h-32 w-70 items-center justify-center rounded-8 text-14 font-medium text-white transition-colors hover:bg-blue-600 disabled:cursor-not-allowed disabled:opacity-50"
>
{isProcessing ? '처리 중' : '수락'}
</button>
<button
onClick={handleReject}
disabled={isProcessing}
className="BG-white Border-blue Text-blue flex h-32 w-70 items-center justify-center rounded-8 border text-14 font-medium transition-colors hover:bg-blue-50 disabled:cursor-not-allowed disabled:opacity-50"
>
{isProcessing ? '처리 중' : '거절'}
</button>
<>
{/* 데스크톱/태블릿 테이블 레이아웃 */}
<div className="mobile:hidden grid grid-cols-3 items-center gap-20 border-b border-gray-100 py-20 pl-36 pr-32">
{/* 대시보드 이름 */}
<span className="Text-black text-16">
{invitation.dashboard.title || '제목 없음'}
</span>

{/* 초대자 */}
<span className="Text-black text-center text-16">
{invitation.inviter.nickname || invitation.inviter.email}
</span>

{/* 수락/거절 버튼들 */}
<div className="flex items-center justify-center gap-10">
<button
onClick={handleAccept}
disabled={isProcessing}
className="BG-blue tablet:w-72 tablet:h-30 tablet:text-12 flex h-32 w-70 items-center justify-center rounded-8 text-14 font-medium text-white transition-colors hover:bg-blue-600 disabled:cursor-not-allowed disabled:opacity-50"
>
{isProcessing ? '처리 중' : '수락'}
</button>
<button
onClick={handleReject}
disabled={isProcessing}
className="BG-white Border-blue Text-blue tablet:w-72 tablet:h-30 tablet:text-12 flex h-32 w-70 items-center justify-center rounded-8 border text-14 font-medium transition-colors hover:bg-blue-50 disabled:cursor-not-allowed disabled:opacity-50"
>
{isProcessing ? '처리 중' : '거절'}
</button>
</div>
</div>

{/* 모바일 카드 레이아웃 */}
<div className="mobile:block mb-12 hidden rounded-8 p-16">
{/* 이름 */}
<div className="mb-8 flex items-center gap-8">
<span className="Text-gray-light text-14 font-medium">이름</span>
<span className="Text-black text-14">
{invitation.dashboard.title || '제목 없음'}
</span>
</div>

{/* 초대자 */}
<div className="mb-12 flex items-center gap-8">
<span className="Text-gray-light text-14 font-medium">초대자</span>
<span className="Text-black text-14">
{invitation.inviter.nickname || invitation.inviter.email}
</span>
</div>

{/* 버튼들 */}
<div className="flex gap-8">
<button
onClick={handleAccept}
disabled={isProcessing}
className="BG-blue flex h-32 w-109 items-center justify-center rounded-8 text-12 font-medium text-white transition-colors hover:bg-blue-600 disabled:cursor-not-allowed disabled:opacity-50"
>
{isProcessing ? '처리 중' : '수락'}
</button>
<button
onClick={handleReject}
disabled={isProcessing}
className="BG-white Border-blue Text-blue flex h-32 w-109 items-center justify-center rounded-8 border text-12 font-medium transition-colors hover:bg-blue-50 disabled:cursor-not-allowed disabled:opacity-50"
>
{isProcessing ? '처리 중' : '거절'}
</button>
</div>
</div>
</div>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ export default function InvitedDashboardTable() {
return (
<div className="space-y-24">
{/* 검색창 스켈레톤 */}
<div className="h-40 animate-pulse rounded-8 bg-gray-200" />
<div className="mobile:h-36 h-40 animate-pulse rounded-8 bg-gray-200" />

{/* 테이블 헤더 */}
<div className="grid grid-cols-3 items-center gap-20 pl-36 pr-32">
<div className="mobile:hidden grid grid-cols-3 items-center gap-20 pl-36 pr-32">
<span className="text-16 font-medium text-gray-400">이름</span>
<span className="text-center text-16 font-medium text-gray-400">
초대자
Expand All @@ -67,7 +67,7 @@ export default function InvitedDashboardTable() {
{Array.from({ length: 3 }).map((_, index) => (
<div
key={index}
className="grid grid-cols-3 items-center gap-20 border-b border-gray-100 py-20 pl-36 pr-32"
className="mobile:rounded-8 mobile:bg-gray-50 mobile:p-16 mobile:mb-12 grid grid-cols-3 items-center gap-20 border-b border-gray-100 py-20 pl-36 pr-32"
>
<div className="h-20 animate-pulse rounded-4 bg-gray-200" />
<div className="h-20 animate-pulse rounded-4 bg-gray-200" />
Expand All @@ -82,10 +82,10 @@ export default function InvitedDashboardTable() {
if (isError) {
return (
<div className="flex flex-col items-center justify-center py-60">
<p className="text-16 font-medium text-red-500">
<p className="mobile:text-12 text-16 font-medium text-red-500">
초대받은 대시보드를 불러오는 중 오류가 발생했습니다.
</p>
<p className="mt-8 text-14 text-gray-500">
<p className="mobile:text-10 mt-8 text-14 text-gray-500">
{error?.message || '다시 시도해주세요.'}
</p>
</div>
Expand All @@ -96,15 +96,15 @@ export default function InvitedDashboardTable() {
if (allInvitations.length === 0) {
return (
<div className="flex flex-col items-center justify-center py-60">
<div className="relative mb-24 h-100 w-100">
<div className="mobile:size-60 relative mb-24 h-100 w-100">
<Image
src="/images/unsubscribe.svg"
alt="초대받은 대시보드 없음"
fill
className="object-contain"
/>
</div>
<p className="Text-gray-light text-16 font-medium">
<p className="Text-gray-light mobile:text-12 text-16 font-medium">
아직 초대받은 대시보드가 없어요.
</p>
</div>
Expand All @@ -117,8 +117,8 @@ export default function InvitedDashboardTable() {
{/* 검색창 */}
<SearchInput value={searchQuery} onChange={setSearchQuery} />

{/* 테이블 헤더 */}
<div className="grid grid-cols-3 items-center gap-20 pl-36 pr-32">
{/* 테이블 헤더 - 모바일에서 숨김 */}
<div className="mobile:hidden grid grid-cols-3 items-center gap-20 pl-36 pr-32">
<span className="Text-gray-light text-16 font-normal">이름</span>
<span className="Text-gray-light text-center text-16 font-normal">
초대자
Expand All @@ -129,11 +129,11 @@ export default function InvitedDashboardTable() {
</div>

{/* 테이블 바디 */}
<div className="space-y-0">
<div className="mobile:space-y-0">
{searchQuery.trim() && filteredInvitations.length === 0 ? (
// 검색 결과 없음
<div className="flex flex-col items-center justify-center py-60">
<p className="Text-gray-light text-16 font-medium">
<p className="Text-gray-light mobile:text-12 text-16 font-medium">
`{searchQuery}`에 대한 검색 결과가 없습니다.
</p>
</div>
Expand All @@ -155,7 +155,7 @@ export default function InvitedDashboardTable() {
{/* 더 이상 데이터가 없을 때 */}
{!hasNextPage && allInvitations.length > 0 && (
<div className="py-20 text-center">
<p className="Text-gray-light text-14 font-normal">
<p className="Text-gray-light mobile:text-10 text-14 font-normal">
모든 초대를 확인했습니다.
</p>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ export default function SearchInput({
placeholder = '검색',
}: SearchInputProps) {
return (
<div className="relative h-40 w-960">
<div className="mobile:h-36 relative h-40 w-full">
<input
type="text"
placeholder={placeholder}
value={value}
onChange={(e) => onChange(e.target.value)}
className="Border-btn h-40 w-full rounded-8 border pl-40 pr-12 text-14 placeholder-gray-400 focus:border-blue-500 focus:outline-none"
className="Border-btn mobile:h-36 mobile:text-14 mobile:placeholder:text-14 h-40 w-full rounded-8 border pl-40 pr-12 text-14 placeholder-gray-400 focus:border-blue-500 focus:outline-none"
/>
<div className="absolute left-16 top-1/2 -translate-y-1/2 transform">
<Image
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default function AddDashboardCard() {
return (
<button
onClick={handleClick}
className="BG-white Border-btn hover:BG-gray group flex h-70 w-332 items-center justify-center gap-12 rounded-8 border p-20 transition-all duration-200 hover:border-gray-300"
className="BG-white Border-btn BG-Input-hovered tablet:w-247 tablet:h-68 mobile:w-260 mobile:h-58 group flex h-70 w-332 items-center justify-center gap-12 rounded-8 border p-20 transition-all duration-200 hover:border-gray-300"
>
<span className="Text-black text-16 font-medium">새로운 대시보드</span>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default function MyDashboardCard({ dashboard }: MyDashboardCardProps) {
return (
<div
onClick={handleClick}
className="BG-white Border-btn hover:BG-gray group h-70 w-332 cursor-pointer rounded-8 border p-20 transition-all duration-200 hover:border-gray-300"
className="BG-white Border-btn BG-Input-hovered tablet:w-247 tablet:h-68 mobile:w-260 mobile:h-58 group h-70 w-332 cursor-pointer rounded-8 border p-20 transition-all duration-200 hover:border-gray-300"
>
<div className="flex items-center justify-between">
<div className="flex items-center gap-12">
Expand All @@ -30,7 +30,7 @@ export default function MyDashboardCard({ dashboard }: MyDashboardCardProps) {
/>

{/* 대시보드 제목 */}
<h3 className="Text-black max-w-200 truncate text-16 font-medium">
<h3 className="Text-black tablet:max-w-140 mobile:max-w-160 mobile:text-14 max-w-200 truncate text-16 font-medium">
{dashboard.title}
</h3>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ export default function MyDashboardGrid() {
if (isLoading) {
return (
<section className="mb-40">
<div className="flex max-w-[1020px] flex-wrap gap-12">
<div className="tablet:grid tablet:grid-cols-2 tablet:gap-12 tablet:max-w-[520px] mobile:flex mobile:flex-col mobile:gap-12 mobile:max-w-[260px] flex max-w-[1020px] flex-wrap gap-12">
{/* 새 대시보드 추가 버튼은 항상 표시 */}
<AddDashboardCard />

{/* 로딩 스켈레톤*/}
{Array.from({ length: 5 }).map((_, index) => (
<div
key={index}
className="h-70 w-332 animate-pulse rounded-8 bg-gray-200"
className="tablet:h-68 tablet:w-247 mobile:h-58 mobile:w-260 h-70 w-332 animate-pulse rounded-8 bg-gray-200"
/>
))}
</div>
Expand Down Expand Up @@ -61,7 +61,7 @@ export default function MyDashboardGrid() {

return (
<section className="mb-40">
<div className="flex max-w-[1020px] flex-wrap gap-12">
<div className="tablet:grid tablet:grid-cols-2 tablet:gap-12 tablet:max-w-[520px] mobile:flex mobile:flex-col mobile:gap-12 mobile:max-w-[260px] flex max-w-[1020px] flex-wrap gap-12">
{/* 새 대시보드 추가 카드는 항상 첫 번째 고정 */}
<AddDashboardCard />

Expand All @@ -76,7 +76,7 @@ export default function MyDashboardGrid() {

{/* 페이지네이션 */}
{totalPages > 1 && (
<div className="mt-24 flex max-w-[1020px] items-center justify-end gap-12">
<div className="tablet:max-w-[520px] mobile:max-w-[260px] mt-24 flex max-w-[1020px] items-center justify-end gap-12">
<span className="Text-black text-14 font-normal">
{currentPage} 페이지 중 {totalPages}
</span>
Expand Down
8 changes: 4 additions & 4 deletions src/app/mydashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ export default function MyDashboardPage() {
<Sidebar />

{/* 메인 */}
<div className="BG-gray ml-300 flex-1">
<div className="BG-gray tablet:ml-160 mobile:ml-67 ml-300 flex-1">
{/* 헤더 */}
<Header />

{/* 페이지 콘텐츠 */}
<main className="p-40">
<main className="tablet:p-24 mobile:p-16 p-40">
<MyDashboardGrid />

{/* 초대받은 대시보드 섹션 */}
<section className="BG-white w-1022 rounded-16 p-40 pb-120 pt-24">
<h2 className="Text-black mb-64 text-24 font-bold">
<section className="BG-white tablet:w-504 mobile:w-260 tablet:p-24 mobile:p-16 w-1022 rounded-16 p-40 pb-120 pt-24">
<h2 className="Text-black tablet:text-20 mobile:text-20 mb-64 text-24 font-bold">
초대받은 대시보드
</h2>

Expand Down
22 changes: 21 additions & 1 deletion src/app/shared/components/common/modal/CreateDashboardModal.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
'use client'

import { useModalStore } from '@store/useModalStore'
import { useQueryClient } from '@tanstack/react-query'
import React, { useEffect } from 'react'

import { useDashboardForm } from '@/app/shared/hooks/useDashboardForm'

import DashboardForm from '../../dashboard/DashboardForm'

export default function CreateDashboardModal() {
const queryClient = useQueryClient()
const { modalType, closeModal } = useModalStore()
const isModalOpen = modalType === 'createDashboard'

Expand All @@ -29,6 +31,24 @@ export default function CreateDashboardModal() {

if (!isModalOpen) return null

// 쿼리 무효화 포함한 제출 핸들러
const handleSubmitWithInvalidation = async (
e: React.FormEvent<HTMLFormElement>,
) => {
// 원래 handleSubmit 실행
await handleSubmit(e)

// 사이드바 무한스크롤 쿼리 무효화
queryClient.invalidateQueries({
queryKey: ['dashboards', 'infinite'],
})

// 내 대시보드 페이지 쿼리 무효화
queryClient.invalidateQueries({
queryKey: ['myDashboards'],
})
}

const handleBackdropClick = (e: React.MouseEvent<HTMLDivElement>) => {
if (e.target === e.currentTarget) {
closeModal()
Expand All @@ -47,7 +67,7 @@ export default function CreateDashboardModal() {
onChange={handleChange}
onColorSelect={handleColorSelect}
onSubmit={(e) => {
handleSubmit(e)
handleSubmitWithInvalidation(e)
closeModal()
}}
isSubmitting={isSubmitting}
Expand Down
8 changes: 4 additions & 4 deletions src/app/shared/components/common/sidebar/DashboardItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,22 @@ export default function DashboardItem({
type="button"
aria-current={isActive ? 'page' : undefined}
onClick={handleClick}
className={`Text-black flex w-full items-center gap-12 rounded-6 px-12 py-8 text-left text-18 transition-colors hover:bg-gray-50 ${
className={`Text-black tablet:gap-8 tablet:px-8 tablet:py-6 tablet:text-16 mobile:justify-center mobile:px-4 mobile:py-6 BG-Input-hovered flex w-full items-center gap-12 rounded-6 px-12 py-8 text-left text-18 transition-colors ${
isActive ? 'BG-currentDashboard font-medium' : ''
}`}
>
{/* 컬러 도트 */}
<div
className="size-8 flex-shrink-0 rounded-full"
className="tablet:size-6 mobile:size-12 size-8 flex-shrink-0 rounded-full"
style={{ backgroundColor: dashboard.color }}
/>

{/* 대시보드 제목 */}
<span className="flex-1 truncate">{dashboard.title}</span>
<span className="mobile:hidden flex-1 truncate">{dashboard.title}</span>

{/* 내가 만든 대시보드에 왕관 아이콘 */}
{dashboard.createdByMe && (
<div className="relative h-12 w-14 flex-shrink-0">
<div className="tablet:h-10 tablet:w-12 mobile:hidden relative h-12 w-14 flex-shrink-0">
<Image
src="/images/crown.png"
alt="내가 만든 대시보드"
Expand Down
Loading
Loading