Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions src/app/(main)/project/workspace/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -296,13 +296,12 @@ export default function ProjectPage() {
router.push("/");
} else {
setCurrentView(view);
setShowMemoPanel(false);
}
};

if (tasksLoading) {
return (
<div className="flex flex-col h-full bg-background pt-16">
<div className="flex flex-col h-full bg-background">
<div className="flex-1 flex gap-3 p-3 overflow-hidden">
{[1, 2, 3].map((i) => (
<div key={i} className="w-80 shrink-0 bg-card rounded-lg border border-border p-4 flex flex-col gap-3">
Expand All @@ -318,7 +317,7 @@ export default function ProjectPage() {
}

return (
<div className="flex flex-col h-full bg-background pt-16">
<div className="flex flex-col h-full bg-background">
<div className="flex-1 flex overflow-hidden min-h-0 gap-2 lg:gap-3 p-2 sm:p-3 w-full">

{/* 메인 콘텐츠 */}
Expand All @@ -330,6 +329,8 @@ export default function ProjectPage() {
onCreateTask={handleCreateTask}
onUpdateTask={handleUpdateTask}
onDeleteTask={handleDeleteTask}
onToggleMemo={()=>{setShowMemoPanel((prev)=>!prev)}}
showMemoPanel={showMemoPanel}
onProjectInfoClick={() => { setShowProjectInfoPanel((prev) => !prev); setShowMemoPanel(false); }}
project={{
project_id: projectId,
Expand All @@ -355,6 +356,8 @@ export default function ProjectPage() {
onDeleteTask={handleDeleteTask}
onSelectTask={() => {}}
onTaskCreated={handleRefresh}
onToggleMemo={()=>{setShowMemoPanel((prev)=>!prev)}}
showMemoPanel={showMemoPanel}
onProjectInfoClick={() => { setShowProjectInfoPanel((prev) => !prev); setShowMemoPanel(false); }}
/>
)}
Expand Down Expand Up @@ -387,7 +390,7 @@ export default function ProjectPage() {
: "w-0 opacity-0"
}`}
>
<MemoView projectId={projectId} />
<MemoView projectId={projectId} onClose={()=>setShowMemoPanel(false)} />
</aside>
</div>

Expand Down
2 changes: 1 addition & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default function RootLayout({
<AuthProviders>
<div className="h-full flex flex-col">
<Header />
<div className="flex-1 min-w-0 overflow-auto scrollbar-gutter-stable">{children}</div>
<div className="flex-1 min-w-0 overflow-auto scrollbar-gutter-stable pt-16">{children}</div>
<Toaster />
</div>
</AuthProviders>
Expand Down
6 changes: 6 additions & 0 deletions src/components/features/calendarView/CalendarView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,25 +45,29 @@ interface CalendarViewProps {
started_at?: string;
ended_at?: string;
} | null;
showMemoPanel?: boolean;
onCreateTask?: (
taskData: Omit<Task, "id" | "created_at" | "updated_at">
) => void;
onUpdateTask?: (taskId: string, updates: Partial<Task>) => void;
onDeleteTask?: (taskId: string) => void;
onSelectTask?: (task: Task) => void;
onTaskCreated?: () => void;
onToggleMemo?: () => void;
onProjectInfoClick?: () => void;
}

export default function CalendarView({
tasks = [],
boardId,
project,
showMemoPanel,
onCreateTask,
onUpdateTask,
onDeleteTask,
onSelectTask,
onTaskCreated,
onToggleMemo,
onProjectInfoClick,
}: CalendarViewProps) {
// 프로젝트 정보 추출
Expand Down Expand Up @@ -296,8 +300,10 @@ export default function CalendarView({
currentDate={currentDate}
eventsCount={filteredTasks.length}
showHelp={showHelp}
showMemo={showMemoPanel}
showFilter={showFilter}
onToggleHelp={() => setShowHelp(!showHelp)}
onToggleMemo={onToggleMemo}
onToggleFilter={() => setShowFilter(!showFilter)}
onProjectInfoClick={onProjectInfoClick}
onAddTask={() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,19 @@ import { showToast } from "@/lib/utils/toast";

interface CalendarHeaderProps {
projectName: string;
projectStartedAt?: string;
projectEndedAt?: string;
currentView: View;
currentDate: Date;
eventsCount: number;
showHelp: boolean;
showMemo?: boolean;
showFilter?: boolean;
projectStartedAt?: string;
projectEndedAt?: string;
onToggleHelp: () => void;
onToggleFilter?: () => void;
onAddTask?: () => void;
onProjectInfoClick?: () => void;
onToggleMemo?: () => void;
}

export default function CalendarHeader({
Expand All @@ -33,8 +35,10 @@ export default function CalendarHeader({
currentView,
currentDate,
eventsCount,
showMemo,
showHelp,
showFilter,
onToggleMemo,
onToggleHelp,
onToggleFilter,
onAddTask,
Expand Down
6 changes: 6 additions & 0 deletions src/components/features/kanban/KanbanBoard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ interface KanbanBoardProps {
started_at?: string;
ended_at?: string;
} | null;
showMemoPanel?: boolean;
onToggleMemo?: () => void;
onCreateTask?: (
taskData: Omit<Task, "id" | "created_at" | "updated_at">
) => void;
Expand All @@ -59,6 +61,8 @@ const KanbanBoard = ({
onSelectTask,
onTaskCreated,
onProjectInfoClick,
showMemoPanel,
onToggleMemo,
}: KanbanBoardProps) => {
const projectId = project?.project_id || "";
const projectName = project?.project_name || "이름 없는 프로젝트";
Expand Down Expand Up @@ -333,13 +337,15 @@ const KanbanBoard = ({
onToggleFilter={() => setShowFilter(!showFilter)}
onToggleHelp={() => setShowHelp(!showHelp)}
showHelp={showHelp}
showMemo={showMemoPanel}
hasActiveFilter={
filter.priority !== "all" ||
filter.assignee !== "all" ||
filter.date !== "all"
}
searchQuery={searchQuery}
onSearchChange={setSearchQuery}
onToggleMemo={onToggleMemo}
tasksCount={tasks.length}
project={project}
onProjectInfoClick={onProjectInfoClick}
Expand Down
13 changes: 12 additions & 1 deletion src/components/features/kanban/MemoView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ type SortType = "newest" | "oldest";

interface MemoFormProps {
projectId: string;
onClose?: () => void;
}

const MemoView = ({ projectId }: MemoFormProps) => {
const MemoView = ({ projectId, onClose }: MemoFormProps) => {
// === 기본 상태 관리 ===
const [memos, setMemos] = useState<ProjectMemo[]>([]); // 서버에서 받은 원본 메모 목록
const [newMemo, setNewMemo] = useState(""); // 새 메모 입력 내용
Expand Down Expand Up @@ -524,6 +525,16 @@ const MemoView = ({ projectId }: MemoFormProps) => {
}`}
/>
</button>
{onClose && (
<button
onClick={onClose}
className="p-1.5 hover:bg-white/20 rounded-md transition-colors"
title="메모 닫기"
aria-label="메모 닫기"
>
<Icon type="x" size={14} className="text-white" />
</button>
)}
</div>
</div>

Expand Down
44 changes: 30 additions & 14 deletions src/components/features/kanban/components/KanbanHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,43 @@ import { useState, useRef, useEffect } from "react";
import { format } from "date-fns";
import { ko } from "date-fns/locale";
import { showToast } from "@/lib/utils/toast";
import { Info, SlidersHorizontal, HelpCircle, Plus, Search, X } from "lucide-react";
import { Info, SlidersHorizontal, HelpCircle, Plus, Search, X, StickyNote } from "lucide-react";

interface KanbanHeaderProps {
projectName: string;
onAddClick: () => void;
onToggleFilter: () => void;
onToggleHelp: () => void;
showHelp: boolean;
hasActiveFilter?: boolean;
searchQuery?: string;
onSearchChange?: (q: string) => void;
tasksCount: number;
project?: {
project_id?: string;
project_name: string;
started_at?: string;
ended_at?: string;
} | null;
showHelp: boolean;
showMemo?: boolean;
tasksCount: number;
searchQuery?: string;
hasActiveFilter?: boolean;
onAddClick: () => void;
onToggleHelp: () => void;
onToggleMemo?: () => void;
onToggleFilter: () => void;
onProjectInfoClick?: () => void;
onSearchChange?: (q: string) => void;
}

export default function KanbanHeader({
project,
projectName,
showHelp,
showMemo,
tasksCount,
searchQuery = "",
hasActiveFilter = false,
onAddClick,
onToggleFilter,
onToggleHelp,
showHelp,
hasActiveFilter = false,
searchQuery = "",
onSearchChange,
tasksCount,
project,
onProjectInfoClick,
onToggleMemo,
}: KanbanHeaderProps) {
const [searchOpen, setSearchOpen] = useState(false);
const searchRef = useRef<HTMLInputElement>(null);
Expand Down Expand Up @@ -178,6 +182,18 @@ export default function KanbanHeader({
)}
</button>

{onToggleMemo && (
<button
onClick={onToggleMemo}
className={`${iconBtn} ${showMemo ? "text-main-500 dark:text-main-400 bg-main-500/10" : ""}`}
title={showMemo ? "메모 닫기" : "메모 열기"}
aria-label={showMemo ? "메모 닫기" : "메모 열기"}
>
<StickyNote className="w-4 h-4" />
</button>
)}


<button onClick={onToggleHelp} className={iconBtn} title={showHelp ? "도움말 닫기" : "도움말 열기"} aria-label={showHelp ? "도움말 닫기" : "도움말 열기"}>
<HelpCircle className={`w-4 h-4 transition-colors ${showHelp ? "text-main-500 dark:text-main-400" : ""}`} />
</button>
Expand Down
20 changes: 1 addition & 19 deletions src/components/layout/BottomNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,7 @@ const BottomNavigation = ({
</svg>
),
},
{
id: "memo" as NavItem,
label: "메모",
icon: (
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
/>
</svg>
),
},

];

return (
Expand Down
2 changes: 1 addition & 1 deletion src/components/shared/Container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default function Container({
}: ContainerProps) {
return (
<section
className={`w-full max-w-[1280px] px-10 mx-auto py-25 ${className || ""}`}
className={`w-full max-w-7xl px-10 mx-auto pb-25 pt-6 ${className || ""}`}
{...props}
>
{children}
Expand Down
Loading
Loading