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
2 changes: 1 addition & 1 deletion src/app/(landing)/_components/CTASection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export default function CTASection() {
오늘의 할 일, Slice로 계획해요
</h2>
<motion.button
onClick={() => router.push("/login")}
onClick={() => router.push("/dashboard")}
className="bg-orange-250 cursor-pointer rounded-full px-10 py-3.5 text-base font-semibold text-white shadow-lg transition-all duration-300 hover:bg-[#FF7043] sm:px-16 sm:py-4 sm:text-lg"
whileHover={{
scale: 1.05,
Expand Down
4 changes: 2 additions & 2 deletions src/app/(landing)/_components/HeroSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default function HeroSection() {
}, []);

return (
<section className="relative w-full overflow-hidden bg-linear-to-b from-[#FFF9E5] to-[#D4FFFE]">
<section className="relative w-full bg-linear-to-b from-[#FFF9E5] to-[#D4FFFE]">
<div className="pointer-events-none absolute inset-0">
<svg
className="absolute top-8 right-4 h-20 w-20 sm:top-12 sm:right-12 sm:h-28 sm:w-28 lg:top-16 lg:right-24 lg:h-40 lg:w-40"
Expand Down Expand Up @@ -95,7 +95,7 @@ export default function HeroSection() {
오늘의 할 일, Slice로 계획해요
</h1>
<motion.button
onClick={() => router.push("/login")}
onClick={() => router.push("/dashboard")}
className="bg-orange-250 cursor-pointer rounded-full px-10 py-3.5 text-base font-semibold text-white shadow-lg transition-all duration-300 hover:bg-[#FF7043] sm:px-16 sm:py-4 sm:text-lg"
whileHover={{
scale: 1.05,
Expand Down
55 changes: 32 additions & 23 deletions src/app/(protected)/notes/_components/NoteCreateContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,15 @@ export default function NoteCreateContainer({
const { data: todo } = useTodoQuery(todoId);
const { mutate: createNoteMutation, isPending } = useCreateNoteMutation();

const form = useNoteForm({
todoId,
});
const {
form,
embed,
draft,
loadModal,
changeTitle,
changeContent,
changeLinkUrl,
} = useNoteForm({ todoId });

const handleSubmit = () => {
if (!form.title.trim()) {
Expand All @@ -40,16 +46,19 @@ export default function NoteCreateContainer({
return;
}

const trimmedLinkUrl = form.linkUrl?.trim();

createNoteMutation(
{
todoId,
title: form.title.trim(),
content: JSON.stringify(form.content),
...(form.linkUrl.trim() && { linkUrl: form.linkUrl.trim() }),
...(trimmedLinkUrl && { linkUrl: trimmedLinkUrl }),
},
{
onSuccess: (data) => {
draftNoteStorage.remove(todoId);
toast.success("노트가 작성되었습니다.");
router.replace(`/notes?goalId=${data.goal.id}`);
},
onError: (error) => {
Expand Down Expand Up @@ -79,24 +88,24 @@ export default function NoteCreateContainer({
<NoteMobileActions
submitLabel="등록"
isDisabled={isDisabled}
onDraft={form.handleDraft}
onDraft={draft.save}
onSubmit={handleSubmit}
/>
}
desktopActions={
<NoteDesktopActions
submitLabel="등록하기"
isDisabled={isDisabled}
onDraft={form.handleDraft}
onDraft={draft.save}
onSubmit={handleSubmit}
/>
}
/>
{form.hasDraftNote && (
{draft.hasNote && (
<div className="hidden sm:absolute sm:top-12 sm:right-22 sm:z-500 sm:block sm:w-70 lg:top-12">
<DraftCallout
onLoadDraft={form.handleLoadModalOpen}
onClose={form.handleDraftCalloutClose}
onLoadDraft={loadModal.open}
onClose={draft.closeCallout}
/>
</div>
)}
Expand All @@ -105,24 +114,24 @@ export default function NoteCreateContainer({
content={form.content}
linkUrl={form.linkUrl}
linkMetadata={form.linkMetadata}
isEmbedOpen={form.isEmbedOpen}
onChangeTitle={form.handleTitleChange}
onChangeContent={form.handleContentChange}
onChangeLinkUrl={form.handleLinkUrlChange}
onToggleEmbed={form.handleToggleEmbed}
onDeleteLinkPreview={form.handleDeleteLinkPreview}
isEmbedOpen={embed.isOpen}
onChangeTitle={changeTitle}
onChangeContent={changeContent}
onChangeLinkUrl={changeLinkUrl}
onToggleEmbed={embed.toggle}
onDeleteLinkPreview={embed.deletePreview}
metaInfo={metaInfo}
hasDraftNote={form.hasDraftNote}
onLoadDraft={form.handleLoadModalOpen}
onCloseDraftCallout={form.handleDraftCalloutClose}
hasDraftNote={draft.hasNote}
onLoadDraft={loadModal.open}
onCloseDraftCallout={draft.closeCallout}
/>
</div>
{form.isLoadModalOpen && (
{loadModal.isOpen && (
<ConfirmModal
isOpen={form.isLoadModalOpen}
title={`'${form.getDraftTitle()}'\n제목의 노트를 불러오시겠어요?`}
onClose={form.handleLoadModalClose}
onConfirm={form.handleConfirmLoadDraft}
isOpen={loadModal.isOpen}
title={`'${draft.getTitle()}'\n제목의 노트를 불러오시겠어요?`}
onClose={loadModal.close}
onConfirm={draft.load}
/>
)}
</>
Expand Down
22 changes: 11 additions & 11 deletions src/app/(protected)/notes/_components/NoteDetailSkeleton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ export default function NoteDetailSkeleton() {
return (
<div className="flex flex-col">
<header className="border-b border-gray-100 pb-7">
<div className="bg-gray-150 mb-4 h-8 w-2/3 animate-pulse rounded sm:h-10" />
<div className="bg-gray-80 mb-4 h-8 w-2/3 animate-pulse rounded sm:h-10" />
<div className="space-y-2">
<div className="bg-gray-150 h-4 w-40 animate-pulse rounded" />
<div className="bg-gray-150 h-4 w-48 animate-pulse rounded" />
<div className="bg-gray-150 h-4 w-32 animate-pulse rounded" />
<div className="bg-gray-80 h-4 w-40 animate-pulse rounded" />
<div className="bg-gray-80 h-4 w-48 animate-pulse rounded" />
<div className="bg-gray-80 h-4 w-32 animate-pulse rounded" />
</div>
</header>
<div className="mt-6 space-y-2.5">
<div className="bg-gray-150 h-4 w-full animate-pulse rounded" />
<div className="bg-gray-150 h-4 w-full animate-pulse rounded" />
<div className="bg-gray-150 h-4 w-3/4 animate-pulse rounded" />
<div className="bg-gray-150 h-4 w-full animate-pulse rounded" />
<div className="bg-gray-150 h-4 w-5/6 animate-pulse rounded" />
<div className="bg-gray-150 h-4 w-full animate-pulse rounded" />
<div className="bg-gray-150 h-4 w-2/3 animate-pulse rounded" />
<div className="bg-gray-80 h-4 w-full animate-pulse rounded" />
<div className="bg-gray-80 h-4 w-full animate-pulse rounded" />
<div className="bg-gray-80 h-4 w-3/4 animate-pulse rounded" />
<div className="bg-gray-80 h-4 w-full animate-pulse rounded" />
<div className="bg-gray-80 h-4 w-5/6 animate-pulse rounded" />
<div className="bg-gray-80 h-4 w-full animate-pulse rounded" />
<div className="bg-gray-80 h-4 w-2/3 animate-pulse rounded" />
</div>
</div>
);
Expand Down
53 changes: 32 additions & 21 deletions src/app/(protected)/notes/_components/NoteEditContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,15 @@ export default function NoteEditContainer({ noteId }: NoteEditContainerProps) {

const todoId = note.todo.id;

const form = useNoteForm({
const {
form,
embed,
draft,
loadModal,
changeTitle,
changeContent,
changeLinkUrl,
} = useNoteForm({
todoId,
isEditMode: true,
initialData: {
Expand All @@ -46,18 +54,21 @@ export default function NoteEditContainer({ noteId }: NoteEditContainerProps) {
return;
}

const trimmedLinkUrl = form.linkUrl?.trim();

updateNoteMutation(
{
noteId,
data: {
title: form.title.trim(),
content: JSON.stringify(form.content),
linkUrl: form.linkUrl.trim() || null,
linkUrl: trimmedLinkUrl || null,
},
},
{
onSuccess: (data) => {
draftNoteStorage.remove(todoId);
toast.success("노트가 수정되었습니다.");
router.replace(`/notes?goalId=${data.goal.id}`);
},
onError: (error) => {
Expand Down Expand Up @@ -87,24 +98,24 @@ export default function NoteEditContainer({ noteId }: NoteEditContainerProps) {
<NoteMobileActions
submitLabel="수정"
isDisabled={isDisabled}
onDraft={form.handleDraft}
onDraft={draft.save}
onSubmit={handleSubmit}
/>
}
desktopActions={
<NoteDesktopActions
submitLabel="수정하기"
isDisabled={isDisabled}
onDraft={form.handleDraft}
onDraft={draft.save}
onSubmit={handleSubmit}
/>
}
/>
{form.hasDraftNote && (
{draft.hasNote && (
<div className="hidden sm:absolute sm:top-12 sm:right-22 sm:z-500 sm:block sm:w-70 lg:top-12">
<DraftCallout
onLoadDraft={form.handleLoadModalOpen}
onClose={form.handleDraftCalloutClose}
onLoadDraft={loadModal.open}
onClose={draft.closeCallout}
/>
</div>
)}
Expand All @@ -113,24 +124,24 @@ export default function NoteEditContainer({ noteId }: NoteEditContainerProps) {
content={form.content}
linkUrl={form.linkUrl}
linkMetadata={form.linkMetadata}
isEmbedOpen={form.isEmbedOpen}
onChangeTitle={form.handleTitleChange}
onChangeContent={form.handleContentChange}
onChangeLinkUrl={form.handleLinkUrlChange}
onToggleEmbed={form.handleToggleEmbed}
onDeleteLinkPreview={form.handleDeleteLinkPreview}
isEmbedOpen={embed.isOpen}
onChangeTitle={changeTitle}
onChangeContent={changeContent}
onChangeLinkUrl={changeLinkUrl}
onToggleEmbed={embed.toggle}
onDeleteLinkPreview={embed.deletePreview}
metaInfo={metaInfo}
hasDraftNote={form.hasDraftNote}
onLoadDraft={form.handleLoadModalOpen}
onCloseDraftCallout={form.handleDraftCalloutClose}
hasDraftNote={draft.hasNote}
onLoadDraft={loadModal.open}
onCloseDraftCallout={draft.closeCallout}
/>
</div>
{form.isLoadModalOpen && (
{loadModal.isOpen && (
<ConfirmModal
isOpen={form.isLoadModalOpen}
title={`'${form.getDraftTitle()}'\n제목의 노트를 불러오시겠어요?`}
onClose={form.handleLoadModalClose}
onConfirm={form.handleConfirmLoadDraft}
isOpen={loadModal.isOpen}
title={`'${draft.getTitle()}'\n제목의 노트를 불러오시겠어요?`}
onClose={loadModal.close}
onConfirm={draft.load}
/>
)}
</>
Expand Down
6 changes: 3 additions & 3 deletions src/app/(protected)/notes/_components/NoteEditorForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { NoteLinkPreview } from "./NoteLinkPreview";
interface NoteEditorFormProps {
title: string;
content: JSONContent | null;
linkUrl: string;
linkUrl: string | null;
linkMetadata: LinkMetadata | null;
isEmbedOpen: boolean;
onChangeTitle: (e: React.ChangeEvent<HTMLInputElement>) => void;
Expand Down Expand Up @@ -72,12 +72,12 @@ export default function NoteEditorForm({
const countWithoutSpace = text.replace(/\s+/g, "").length;

const handleOpenLinkModal = () => {
setTempLinkUrl(linkUrl);
setTempLinkUrl(linkUrl ?? "");
setIsLinkModalOpen(true);
};

const handleCloseLinkModal = () => {
setTempLinkUrl(linkUrl);
setTempLinkUrl(linkUrl ?? "");
setIsLinkModalOpen(false);
};

Expand Down
6 changes: 3 additions & 3 deletions src/app/(protected)/notes/_components/NoteItemSkeleton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ export default function NoteItemSkeleton() {
return (
<div className="rounded-2xl bg-white p-4 shadow-sm sm:px-8 sm:py-7">
<div className="mb-2 border-b border-b-gray-100 pb-2 sm:mb-3.5 sm:pb-4 lg:mb-4 lg:pb-5">
<div className="bg-gray-150 h-8 animate-pulse rounded lg:h-10" />
<div className="bg-gray-80 h-8 animate-pulse rounded lg:h-10" />
</div>
<div className="flex items-center gap-2">
<div className="bg-gray-150 h-5 w-13 animate-pulse rounded sm:h-6" />
<div className="bg-gray-150 h-5 flex-1 animate-pulse rounded sm:h-6" />
<div className="bg-gray-80 h-5 w-13 animate-pulse rounded sm:h-6" />
<div className="bg-gray-80 h-5 flex-1 animate-pulse rounded sm:h-6" />
</div>
</div>
);
Expand Down
4 changes: 3 additions & 1 deletion src/app/(protected)/notes/_components/NoteListContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useRouter } from "next/navigation";
import EmptyState from "@/components/common/empty-state/EmptyState";
import { EMPTY_MESSAGES } from "@/constants/messages";
import ConfirmModal from "@/components/common/popup-modal/ConfirmModal";
import { toast } from "@/lib/toast";
import GoalBanner from "./GoalBanner";
import NoteList from "./NoteList";

Expand Down Expand Up @@ -40,11 +41,12 @@ export default function NoteListContainer({ goalId }: NoteListContainerProps) {
onSuccess: () => {
setDeleteNoteId(null);
setIsDeleteModalOpen(false);
toast.success("노트가 삭제되었습니다.");
},

onError: (error) => {
console.error("삭제 실패:", error);
alert("노트 삭제에 실패했습니다.");
toast.error("노트 삭제에 실패했습니다.");
},
},
);
Expand Down
Loading