Skip to content

Commit

Permalink
inv-126 : 타이틀, 내용 업데이트 쿼리 (#64)
Browse files Browse the repository at this point in the history
* feat: using update request api

* feat: title update use debounce

* chore: 불필요한 console.log 제거

* refactor: Config 명세 변경 적용

* feat: 삭제 api 연결

* refactor: title update mutation

* refactor: query auth

* fix: editor.data typo

* feat: 저장 토스트 문구 수정

* fix: query typo

---------

Co-authored-by: bepyan <[email protected]>
  • Loading branch information
xilucks and bepyan authored Aug 18, 2024
1 parent 1536abb commit 41b2496
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 68 deletions.
4 changes: 2 additions & 2 deletions src/app/(main)/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default async function Page() {
if (!auth.user) {
return redirect("/sign-in");
}
const invitations = await getInvitationsByUserId(auth.user.id);
const invitations = await getInvitationsByUserId();

return (
<div className="flex h-dvh flex-col overflow-hidden">
Expand Down Expand Up @@ -55,7 +55,7 @@ export default async function Page() {
{invitations.map((invitation) => (
<li key={invitation.id} className="h-full w-full">
<Link
href={`/i/${invitation.id}/edit`}
href={`/i/${invitation.eventUrl}/edit`}
className="flex h-full flex-col bg-muted p-0.5"
>
<div className="flex-1 overflow-hidden rounded-xl border border-border bg-background p-3">
Expand Down
57 changes: 15 additions & 42 deletions src/app/(main)/i/[subdomain]/edit/page.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,22 @@
import Editor from "~/components/editor";
import { getInvitationByEventUrl } from "~/lib/db/schema/invitations.query";

export default async function Page({
params,
}: {
params: { subdomain: string };
}) {
const invitation = await getInvitationByEventUrl(params.subdomain);

export default async function Page() {
return (
<Editor
editorConfig={{ backLink: "/pg" }}
editorData={[
{
id: "__body",
type: "__body",
name: "Body",
styles: {},
content: [
{
id: "container",
name: "Container",
type: "container",
styles: {
display: "flex",
alignItems: "center",
justifyContent: "center",
gap: 10,
paddingTop: 10,
paddingRight: 10,
paddingBottom: 10,
paddingLeft: 10,
width: "100%",
height: "auto",
},
content: [
{
id: "text",
name: "Text",
type: "text",
styles: {
textAlign: "left",
},
content: {
innerText: "Hello World",
},
},
],
},
],
},
]}
editorConfig={{
backLink: "/pg",
invitationId: invitation.id,
invitationTitle: invitation.title,
invitationSubdomain: invitation.eventUrl,
}}
editorData={invitation.customFields}
/>
);
}
24 changes: 24 additions & 0 deletions src/app/(main)/i/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Script from "next/script";
import { env } from "~/lib/env";

export default function KakaoMapScriptLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<>
<Script
strategy="beforeInteractive"
type="text/javascript"
src={`${env.DAUMCDN_POSTOCDE_URL}`}
/>
<Script
strategy="beforeInteractive"
type="text/javascript"
src={`${env.KAKAO_MAP_BASE_URL}?appkey=${env.KAKAO_MAP_API_KEY}&libraries=services&autoload=false`}
/>
{children}
</>
);
}
28 changes: 21 additions & 7 deletions src/components/editor/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
Undo2,
} from "lucide-react";
import Link from "next/link";
import { useParams, useRouter } from "next/navigation";
import { toast } from "sonner";
import { useEditor } from "~/components/editor/provider";
import TitleInput from "~/components/editor/title-input";
Expand All @@ -27,11 +28,18 @@ import {
} from "~/components/ui/dropdown-menu";
import { Tabs, TabsList, TabsTrigger } from "~/components/ui/tabs";
import TooltipSimple from "~/components/ui/tooltip-simple";
import {
deleteInvitation,
updateInvitation,
} from "~/lib/db/schema/invitations.query";
import { cn } from "~/lib/utils";

export default function EditorNavigation() {
const { editor, dispatch } = useEditor();
const router = useRouter();
const { openDialog } = useAlertDialogStore();
const params = useParams();
const subDomain = params.subdomain;

const handlePreviewClick = () => {
dispatch({ type: "TOGGLE_PREVIEW_MODE" });
Expand All @@ -47,14 +55,17 @@ export default function EditorNavigation() {

const handleOnSave = async () => {
try {
const content = JSON.stringify(editor.data);
console.log(":content", content);
// TODO: API insert page
// TODO: API log notification
toast.success("Saved Editor");
await updateInvitation({
id: editor.config.invitationId,
title: editor.config.invitationTitle,
customFields: editor.data,
});
toast.success("저장되었습니다.");
} catch (error) {
console.error(error);
toast.error("Oppse!", { description: "Could not save editor" });
toast.error("일시적인 오류가 발생되었습니다.", {
description: "잠시후 다시 시도해보세요.",
});
}
};

Expand All @@ -64,7 +75,10 @@ export default function EditorNavigation() {
description: "이 작업을 되돌릴 수 없습니다.",
confirmText: "확인",
cancelText: "취소",
onConfirm: () => {},
onConfirm: async () => {
await deleteInvitation(editor.config.invitationId);
router.replace("/dashboard");
},
});
};

Expand Down
20 changes: 13 additions & 7 deletions src/components/editor/title-input.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
"use client";

import { useMutation } from "@tanstack/react-query";
import { debounce, delay, random } from "es-toolkit";
import { debounce, delay } from "es-toolkit";
import { CheckIcon, LoaderIcon, XIcon } from "lucide-react";
import { useRef } from "react";
import { toast } from "sonner";
import { useEditor } from "~/components/editor/provider";
import { updateInvitation } from "~/lib/db/schema/invitations.query";
import { cn } from "~/lib/utils";

export default function TitleInput() {
const { editor } = useEditor();
const { editor, dispatch } = useEditor();

const abortControllerRef = useRef<AbortController | null>(null);

Expand Down Expand Up @@ -40,16 +41,21 @@ export default function TitleInput() {
value: string;
signal: AbortSignal;
}) => {
await delay(1000);

if (signal.aborted) {
return;
}

if (random(0, 1) > 0.5) {
throw new Error("Failed to update title");
}
await updateInvitation({
id: editor.config.invitationId,
title: value,
});

dispatch({
type: "UPDATE_CONFIG",
payload: {
invitationTitle: value,
},
});
delayMutation.mutate();
},
onError: () => {
Expand Down
30 changes: 21 additions & 9 deletions src/lib/db/schema/invitations.query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { count, eq } from "drizzle-orm";
import { nanoid } from "nanoid";
import { getAuth } from "~/lib/auth/utils";
import { db } from "~/lib/db";
import {
invitations,
Expand All @@ -11,14 +12,14 @@ import {

type CreateInvitationParams = Omit<
InvitationInsert,
"id" | "eventUrl" | "createdAt" | "updatedAt"
"id" | "userId" | "eventUrl" | "createdAt" | "updatedAt"
>;

type UpdateInvitationParams = {
id: string;
title?: string;
eventUrl?: string;
customFields?: Record<string, any>;
id: Invitation["id"];
title?: Invitation["title"];
customFields?: Invitation["customFields"];
eventUrl?: Invitation["eventUrl"];
};

export async function getAllInvitations() {
Expand All @@ -41,18 +42,28 @@ export async function getInvitationByEventUrl(eventUrl: string) {
return responses[0];
}

export async function getInvitationsByUserId(
userId: Invitation["userId"],
): Promise<Invitation[]> {
export async function getInvitationsByUserId(): Promise<Invitation[]> {
const auth = await getAuth();

if (!auth.user) {
throw new Error("No Auth");
}

return await db
.select()
.from(invitations)
.where(eq(invitations.userId, userId));
.where(eq(invitations.userId, auth.user.id));
}

export async function createInvitation(
params: CreateInvitationParams,
): Promise<InvitationInsert> {
const auth = await getAuth();

if (!auth.user) {
throw new Error("No Auth");
}

const id = nanoid();
const currentTimestamp = new Date();

Expand All @@ -62,6 +73,7 @@ export async function createInvitation(
.values({
...params,
id,
userId: auth.user.id,
eventUrl: id,
createdAt: currentTimestamp,
updatedAt: currentTimestamp,
Expand Down
3 changes: 2 additions & 1 deletion src/lib/db/schema/invitations.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { json, pgTable, text, timestamp } from "drizzle-orm/pg-core";
import type { EditorData } from "~/components/editor/type";
import { users } from "~/lib/db/schema/users";

export const invitations = pgTable("invitation", {
id: text("id").primaryKey(),
userId: text("user_id")
.references(() => users.id)
.notNull(),
customFields: json("custom_fields").notNull().$type<Record<string, any>>(),
customFields: json("custom_fields").notNull().$type<EditorData>(),
title: text("title").notNull(),
eventUrl: text("event_url").unique().notNull(),
thumbnailUrl: text("thumbnail_url"),
Expand Down

0 comments on commit 41b2496

Please sign in to comment.