Skip to content

Commit 2fa8bf3

Browse files
added a new sendCarouselMessage Feature
1 parent 4dfae4a commit 2fa8bf3

File tree

19 files changed

+1168
-89
lines changed

19 files changed

+1168
-89
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
-- CreateEnum
2+
CREATE TYPE "ButtonType" AS ENUM ('WEB_URL', 'POSTBACK');
3+
4+
-- AlterEnum
5+
ALTER TYPE "LISTENERS" ADD VALUE 'CAROUSEL';
6+
7+
-- CreateTable
8+
CREATE TABLE "CarouselTemplate" (
9+
"id" UUID NOT NULL DEFAULT gen_random_uuid(),
10+
"automationId" UUID,
11+
"userId" UUID NOT NULL,
12+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
13+
14+
CONSTRAINT "CarouselTemplate_pkey" PRIMARY KEY ("id")
15+
);
16+
17+
-- CreateTable
18+
CREATE TABLE "Element" (
19+
"id" UUID NOT NULL DEFAULT gen_random_uuid(),
20+
"title" VARCHAR(80) NOT NULL,
21+
"subtitle" VARCHAR(80),
22+
"imageUrl" TEXT,
23+
"carouselTemplateId" UUID,
24+
"defaultAction" JSONB,
25+
"order" INTEGER NOT NULL DEFAULT 0,
26+
27+
CONSTRAINT "Element_pkey" PRIMARY KEY ("id")
28+
);
29+
30+
-- CreateTable
31+
CREATE TABLE "Button" (
32+
"id" UUID NOT NULL DEFAULT gen_random_uuid(),
33+
"type" "ButtonType" NOT NULL,
34+
"title" VARCHAR(20) NOT NULL,
35+
"url" TEXT,
36+
"payload" TEXT,
37+
"elementId" UUID,
38+
39+
CONSTRAINT "Button_pkey" PRIMARY KEY ("id")
40+
);
41+
42+
-- AddForeignKey
43+
ALTER TABLE "CarouselTemplate" ADD CONSTRAINT "CarouselTemplate_automationId_fkey" FOREIGN KEY ("automationId") REFERENCES "Automation"("id") ON DELETE CASCADE ON UPDATE CASCADE;
44+
45+
-- AddForeignKey
46+
ALTER TABLE "CarouselTemplate" ADD CONSTRAINT "CarouselTemplate_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
47+
48+
-- AddForeignKey
49+
ALTER TABLE "Element" ADD CONSTRAINT "Element_carouselTemplateId_fkey" FOREIGN KEY ("carouselTemplateId") REFERENCES "CarouselTemplate"("id") ON DELETE CASCADE ON UPDATE CASCADE;
50+
51+
-- AddForeignKey
52+
ALTER TABLE "Button" ADD CONSTRAINT "Button_elementId_fkey" FOREIGN KEY ("elementId") REFERENCES "Element"("id") ON DELETE CASCADE ON UPDATE CASCADE;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
Warnings:
3+
4+
- Made the column `url` on table `Button` required. This step will fail if there are existing NULL values in that column.
5+
- Made the column `payload` on table `Button` required. This step will fail if there are existing NULL values in that column.
6+
7+
*/
8+
-- AlterTable
9+
ALTER TABLE "Button" ALTER COLUMN "url" SET NOT NULL,
10+
ALTER COLUMN "payload" SET NOT NULL;
11+
12+
-- AlterTable
13+
ALTER TABLE "Element" ALTER COLUMN "defaultAction" SET DATA TYPE TEXT;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-- AlterTable
2+
ALTER TABLE "Button" ALTER COLUMN "url" DROP NOT NULL,
3+
ALTER COLUMN "payload" DROP NOT NULL;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-- AlterTable
2+
ALTER TABLE "Listener" ADD COLUMN "carouselTemplateId" UUID;
3+
4+
-- AddForeignKey
5+
ALTER TABLE "Listener" ADD CONSTRAINT "Listener_carouselTemplateId_fkey" FOREIGN KEY ("carouselTemplateId") REFERENCES "CarouselTemplate"("id") ON DELETE SET NULL ON UPDATE CASCADE;

prisma/schema.prisma

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ model User {
2626
notification Notification[]
2727
analytics Analytics[]
2828
openAiKey String? @unique
29+
carouselTemplates CarouselTemplate[]
2930
}
3031

3132
model Subscription {
@@ -61,6 +62,7 @@ model Automation {
6162
User User? @relation(fields: [userId], references: [id], onDelete: Cascade)
6263
userId String? @db.Uuid
6364
keywords Keyword[]
65+
carouselTemplates CarouselTemplate[]
6466
}
6567

6668
model Dms {
@@ -92,6 +94,8 @@ model Listener {
9294
commentReply String?
9395
dmCount Int @default(0)
9496
commentCount Int @default(0)
97+
carouselTemplateId String? @db.Uuid
98+
carouselTemplate CarouselTemplate? @relation(fields: [carouselTemplateId], references: [id])
9599
}
96100

97101
model Trigger {
@@ -154,4 +158,44 @@ enum MEDIATYPE {
154158
enum LISTENERS {
155159
SMARTAI
156160
MESSAGE
161+
CAROUSEL
157162
}
163+
164+
enum ButtonType {
165+
WEB_URL
166+
POSTBACK
167+
}
168+
169+
170+
model CarouselTemplate {
171+
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
172+
automationId String? @db.Uuid
173+
Automation Automation? @relation(fields: [automationId], references: [id], onDelete: Cascade)
174+
userId String @db.Uuid
175+
User User @relation(fields: [userId], references: [id], onDelete: Cascade)
176+
elements Element[]
177+
listeners Listener[] // Add this relation
178+
createdAt DateTime @default(now())
179+
}
180+
181+
model Element {
182+
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
183+
title String @db.VarChar(80)
184+
subtitle String? @db.VarChar(80)
185+
imageUrl String?
186+
carouselTemplateId String? @db.Uuid
187+
CarouselTemplate CarouselTemplate? @relation(fields: [carouselTemplateId], references: [id], onDelete: Cascade)
188+
defaultAction String?
189+
buttons Button[]
190+
order Int @default(0)
191+
}
192+
193+
model Button {
194+
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
195+
type ButtonType
196+
title String @db.VarChar(20)
197+
url String?
198+
payload String?
199+
elementId String? @db.Uuid
200+
Element Element? @relation(fields: [elementId], references: [id], onDelete: Cascade)
201+
}

src/actions/automations/index.ts

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
findAutomation,
1616
getAutomations,
1717
updateAutomation,
18+
addCarouselTemplate,
1819
} from "./queries";
1920

2021
export const createAutomations = async (id?: string) => {
@@ -92,13 +93,14 @@ export const updateAutomationName = async (
9293

9394
export const saveListener = async (
9495
automationId: string,
95-
listener: "SMARTAI" | "MESSAGE",
96+
listener: "SMARTAI" | "MESSAGE" | "CAROUSEL",
9697
prompt: string,
97-
reply?: string
98+
reply?: string,
99+
carouselTemplateId?: string
98100
) => {
99101
await onCurrentUser();
100102
try {
101-
const create = await addListener(automationId, listener, prompt, reply);
103+
const create = await addListener(automationId, listener, prompt, reply, carouselTemplateId);
102104
if (create) return { status: 200, data: "Listener created" };
103105
return { status: 404, data: "Cant save listener" };
104106
} catch (error) {
@@ -225,4 +227,35 @@ export const activateAutomation = async (id: string, state: boolean) => {
225227
} catch (error) {
226228
return { status: 500, data: "Oops! something went wrong" };
227229
}
228-
};
230+
};
231+
232+
233+
export const createCarouselTemplate = async (
234+
automationId: string,
235+
elements: any[]
236+
) => {
237+
const user = await onCurrentUser();
238+
try {
239+
const userDetails = await findUser(user.id);
240+
241+
if (!userDetails) {
242+
return { status: 404, data: "User not found" };
243+
}
244+
245+
const create = await addCarouselTemplate(automationId, userDetails.id, elements);
246+
247+
if (create) {
248+
return {
249+
status: 200,
250+
data: "Carousel template created successfully",
251+
templateId: create.id
252+
};
253+
}
254+
255+
return { status: 404, data: "Failed to create carousel template" };
256+
} catch (error) {
257+
console.error("Carousel template creation error:", error);
258+
return { status: 500, data: "Internal server error" };
259+
}
260+
};
261+

src/actions/automations/queries.ts

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,18 @@ export const findAutomation = async (id: string) => {
5454
trigger: true,
5555
posts: true,
5656
listener: true,
57+
carouselTemplates: { // Changed from carouselTemplate to carouselTemplates
58+
include: {
59+
elements: {
60+
include: {
61+
buttons: true
62+
},
63+
orderBy: {
64+
order: 'asc'
65+
}
66+
}
67+
}
68+
},
5769
User: {
5870
select: {
5971
subscription: true,
@@ -83,10 +95,15 @@ export const updateAutomation = async (
8395

8496
export const addListener = async (
8597
automationId: string,
86-
listener: "SMARTAI" | "MESSAGE",
98+
listener: "SMARTAI" | "MESSAGE" | "CAROUSEL",
8799
prompt: string,
88-
reply?: string
100+
reply?: string,
101+
carouselTemplateId?: string
89102
) => {
103+
if (listener === "CAROUSEL" && !carouselTemplateId) {
104+
throw new Error("carouselTemplateId is required for CAROUSEL listener");
105+
}
106+
90107
return await client.automation.update({
91108
where: {
92109
id: automationId,
@@ -97,9 +114,25 @@ export const addListener = async (
97114
listener,
98115
prompt,
99116
commentReply: reply,
117+
...(listener === "CAROUSEL" && { carouselTemplateId })
100118
},
101119
},
102120
},
121+
include: {
122+
listener: true,
123+
carouselTemplates: {
124+
include: {
125+
elements: {
126+
include: {
127+
buttons: true
128+
},
129+
orderBy: {
130+
order: 'asc'
131+
}
132+
}
133+
}
134+
}
135+
}
103136
});
104137
};
105138

@@ -193,4 +226,61 @@ export const addPost = async (
193226
},
194227
},
195228
});
229+
};
230+
231+
export const addCarouselTemplate = async (automationId: string, userId: string, elements: Array<{
232+
title: string;
233+
subtitle?: string;
234+
imageUrl?: string;
235+
defaultAction?: string;
236+
buttons: Array<{
237+
type: "WEB_URL" | "POSTBACK";
238+
title: string;
239+
url?: string;
240+
payload?: string;
241+
}>;
242+
}>) => {
243+
return await client.automation.update({
244+
where: {
245+
id: automationId,
246+
},
247+
data: {
248+
carouselTemplates: {
249+
create: {
250+
userId,
251+
elements: {
252+
create: elements.map((element, index) => ({
253+
title: element.title,
254+
subtitle: element.subtitle || "",
255+
imageUrl: element.imageUrl || "",
256+
defaultAction: element.defaultAction || "",
257+
order: index,
258+
buttons: {
259+
create: element.buttons.map(button => ({
260+
type: button.type,
261+
title: button.title,
262+
url: button.type === "WEB_URL" ? button.url : "",
263+
payload: button.type === "POSTBACK" ? button.payload : ""
264+
}))
265+
}
266+
}))
267+
}
268+
}
269+
}
270+
},
271+
include: {
272+
carouselTemplates: {
273+
include: {
274+
elements: {
275+
include: {
276+
buttons: true
277+
},
278+
orderBy: {
279+
order: 'asc'
280+
}
281+
}
282+
}
283+
}
284+
}
285+
});
196286
};

0 commit comments

Comments
 (0)