Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-07-12 12:39:17 +08:00
parent 82ea9c77c4
commit ea3e82e54c
47 changed files with 1301 additions and 481 deletions
@@ -33,6 +33,10 @@ const Advertisement = sequelize.define("Advertisement", {
},
// ─── Content ──────────────────────────────────────────────────────────────
// "image" = image only, "content" = badge/headline/description/CTAs alongside
// the image — an explicit admin choice made in the creation wizard, decoupled
// from placement/format.
content_mode: { type: DataTypes.ENUM("image", "content"), allowNull: false, defaultValue: "image", label: "Content Mode", order: 3.5 },
badge_label: { type: DataTypes.STRING(100), label: "Badge Label", order: 4 },
headline: { type: DataTypes.STRING(255), label: "Headline", order: 5 },
description: { type: DataTypes.TEXT, label: "Description", order: 6 },
@@ -45,6 +49,15 @@ const Advertisement = sequelize.define("Advertisement", {
// [{ label, link }, ...] — 0-2 entries depending on type
ctas: { type: DataTypes.JSONB, allowNull: false, defaultValue: [], label: "CTAs", order: 7 },
// Where the ad as a whole links to when clicked with no CTA of its own
// (banners/full-image ads have no CTA row) — takes priority over landing_page.
redirect_link: { type: DataTypes.STRING(512), allowNull: true, label: "Redirect Link", order: 7.5 },
// Internally-authored landing page { title, description, body, links: [{label, link}] }
// used as the click-through destination when redirect_link is empty — see
// GET /api/client/advertisements/uuid/:uuid and the /ads/:uuid client route.
landing_page: { type: DataTypes.JSONB, allowNull: true, label: "Landing Page", order: 0, hidden: true },
// ─── Scheduling ───────────────────────────────────────────────────────────
start_date: { type: DataTypes.DATE, label: "Start Date", order: 8 },
end_date: { type: DataTypes.DATE, label: "End Date", order: 9 },