x
This commit is contained in:
1 parent
a128b9c163
commit
7a352d4998
77 files changed
+5481
-21
No files matched your search
@@ -0,0 +1,174 @@
|
||||
import { Elysia, t } from "elysia";
|
||||
import prisma from "../lib/prisma";
|
||||
import { adminOnly } from "../middleware/auth";
|
||||
export const menusRoute = new Elysia({ prefix: "/menus" })
|
||||
.get("/", async () => {
|
||||
return await prisma.menu.findMany({
|
||||
include: {
|
||||
items: {
|
||||
orderBy: { order: "asc" },
|
||||
include: { translations: true }
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.get("/:name", async ({ params: { name }, set }) => {
|
||||
const menu = await prisma.menu.findUnique({
|
||||
where: { name },
|
||||
include: {
|
||||
items: {
|
||||
orderBy: { order: "asc" },
|
||||
include: { translations: true }
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!menu) {
|
||||
return { name, items: [] };
|
||||
}
|
||||
return menu;
|
||||
})
|
||||
.use(adminOnly)
|
||||
.post("/", async ({ body, set }) => {
|
||||
try {
|
||||
const { name, items } = body;
|
||||
const menu = await prisma.menu.create({
|
||||
data: {
|
||||
name,
|
||||
items: items ? {
|
||||
create: items
|
||||
} : undefined
|
||||
},
|
||||
include: { items: true }
|
||||
});
|
||||
return menu;
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
set.status = 500;
|
||||
return { error: "Failed to create menu" };
|
||||
}
|
||||
}, {
|
||||
body: t.Object({
|
||||
name: t.String(),
|
||||
items: t.Optional(t.Array(t.Object({
|
||||
label: t.String(),
|
||||
url: t.String(),
|
||||
order: t.Number()
|
||||
})))
|
||||
})
|
||||
})
|
||||
.put("/:name", async ({ params: { name }, body, set }) => {
|
||||
try {
|
||||
const { items } = body;
|
||||
let menu = await prisma.menu.findUnique({ where: { name } });
|
||||
if (!menu) {
|
||||
menu = await prisma.menu.create({ data: { name } });
|
||||
}
|
||||
await prisma.$transaction(async (tx) => {
|
||||
const existingItems = await tx.menuItem.findMany({ where: { menuId: menu.id } });
|
||||
const existingItemIds = existingItems.map((i) => i.id);
|
||||
const payloadItemIds = items.map(i => i.id).filter(id => id != null);
|
||||
const itemsToDelete = existingItemIds.filter((id) => !payloadItemIds.includes(id));
|
||||
if (itemsToDelete.length > 0) {
|
||||
await tx.menuItem.deleteMany({ where: { id: { in: itemsToDelete } } });
|
||||
}
|
||||
for (const item of items) {
|
||||
if (item.id && existingItemIds.includes(item.id)) {
|
||||
await tx.menuItem.update({
|
||||
where: { id: item.id },
|
||||
data: { label: item.label, url: item.url, order: item.order }
|
||||
});
|
||||
if (item.translations?.length) {
|
||||
for (const t of item.translations) {
|
||||
await tx.menuItemTranslation.upsert({
|
||||
where: { menuItemId_langCode: { menuItemId: item.id, langCode: t.langCode } },
|
||||
update: { label: t.label },
|
||||
create: { menuItemId: item.id, langCode: t.langCode, label: t.label }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
await tx.menuItem.create({
|
||||
data: {
|
||||
menuId: menu.id,
|
||||
label: item.label,
|
||||
url: item.url,
|
||||
order: item.order,
|
||||
translations: item.translations?.length ? {
|
||||
create: item.translations.map(t => ({
|
||||
langCode: t.langCode,
|
||||
label: t.label
|
||||
}))
|
||||
} : undefined
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
return await prisma.menu.findUnique({
|
||||
where: { name },
|
||||
include: { items: { orderBy: { order: "asc" }, include: { translations: true } } }
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
set.status = 500;
|
||||
return { error: "Failed to update menu" };
|
||||
}
|
||||
}, {
|
||||
body: t.Object({
|
||||
items: t.Array(t.Object({
|
||||
id: t.Optional(t.Number()),
|
||||
label: t.String(),
|
||||
url: t.String(),
|
||||
order: t.Number(),
|
||||
translations: t.Optional(t.Array(t.Object({
|
||||
langCode: t.String(),
|
||||
label: t.String()
|
||||
})))
|
||||
}))
|
||||
})
|
||||
})
|
||||
.patch("/items/:id/translations", async ({ params, body, set }) => {
|
||||
const id = Number(params.id);
|
||||
if (isNaN(id)) {
|
||||
set.status = 400;
|
||||
return { error: "Invalid menu item ID" };
|
||||
}
|
||||
const menuItem = await prisma.menuItem.findUnique({ where: { id } });
|
||||
if (!menuItem) {
|
||||
set.status = 404;
|
||||
return { error: "Menu item not found. Please ensure database is seeded or the item exists." };
|
||||
}
|
||||
const payload = body;
|
||||
const results = [];
|
||||
const LANGS = ['th', 'en', 'ja', 'zh', 'vi', 'ko'];
|
||||
for (const lang of LANGS) {
|
||||
const label = typeof payload.label === 'string' ? (lang === 'th' ? payload.label : null) : payload.label?.[lang];
|
||||
if (!label)
|
||||
continue;
|
||||
const existing = await prisma.menuItemTranslation.findUnique({
|
||||
where: { menuItemId_langCode: { menuItemId: id, langCode: lang } }
|
||||
});
|
||||
if (existing) {
|
||||
const updated = await prisma.menuItemTranslation.update({
|
||||
where: { id: existing.id },
|
||||
data: { label }
|
||||
});
|
||||
results.push(updated);
|
||||
}
|
||||
else {
|
||||
const created = await prisma.menuItemTranslation.create({
|
||||
data: { menuItemId: id, langCode: lang, label }
|
||||
});
|
||||
results.push(created);
|
||||
}
|
||||
}
|
||||
const updated = await prisma.menuItem.findUnique({
|
||||
where: { id },
|
||||
include: { translations: true }
|
||||
});
|
||||
return { success: true, translations: results, menuItem: updated };
|
||||
});
|
||||
//# sourceMappingURL=menus.js.map
|
||||
Reference in new issue
Block a user