mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
@@ -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 },
|
||||
|
||||
@@ -12,19 +12,10 @@
|
||||
// in controllers/admin/advertisements.controller.js) — type is never accepted
|
||||
// from the client once a placement is set.
|
||||
|
||||
// TODO(ads-1): Re-categorize placements — Hero -> Dashboard, Banner -> Tier Plans.
|
||||
// Remove the "popup" and "sidebar" formats entirely (dashboard.popup,
|
||||
// course_details.sidebar). Keep in sync with the frontend mirror at
|
||||
// new_starr_app/src/data/placement.data.js. This also feeds the Step 1
|
||||
// "Placement" picker in the Add Advertisement wizard (TODO(ads-6)), which
|
||||
// should only offer Dashboard / Tier Plans / Course Details.
|
||||
const PLACEMENTS = [
|
||||
{ key: "dashboard.hero", format: "hero", page: "dashboard", pageLabel: "Dashboard", slotLabel: "Hero (top of page)" },
|
||||
{ key: "dashboard.popup", format: "popup", page: "dashboard", pageLabel: "Dashboard", slotLabel: "Popup (on load)" },
|
||||
{ key: "course_list.banner", format: "banner", page: "course_list", pageLabel: "Courses", slotLabel: "Banner (above course grid)" },
|
||||
{ key: "tier_plans.banner", format: "banner", page: "tier_plans", pageLabel: "Tier Plans", slotLabel: "Banner (above plan cards)" },
|
||||
{ key: "course_details.banner", format: "banner", page: "course_details", pageLabel: "Course Details", slotLabel: "Banner (below hero)" },
|
||||
{ key: "course_details.sidebar", format: "sidebar", page: "course_details", pageLabel: "Course Details", slotLabel: "Sidebar (beside course content)" },
|
||||
{ key: "plans.banner", format: "banner", page: "plans", pageLabel: "Plans", slotLabel: "Banner (above plan cards)" },
|
||||
];
|
||||
|
||||
const PLACEMENT_MAP = Object.fromEntries(PLACEMENTS.map((p) => [p.key, p]));
|
||||
|
||||
Reference in New Issue
Block a user