# AGENTS_TODO.md — CMS Homepage totti-commerce

## 📌 Overview

| Item | Detail |
|---|---|
| Feature | CMS Homepage — Kelola konten homepage via Admin Dashboard |
| Approach | Custom Module MedusaJS (MedusaService + DML models) |
| Scope | Hero section, Category cards, Partners |
| Backend | `apps/backend/src/modules/homepage-cms/` |
| Storefront | Fetch dari `GET /store/homepage` |

---

## 🗂️ Step Breakdown

### Step 1: Data Models
**Session: Buat models homepage-cms**
**Files:**
- `apps/backend/src/modules/homepage-cms/models/homepage.ts`
- `apps/backend/src/modules/homepage-cms/models/hero-photo.ts`
- `apps/backend/src/modules/homepage-cms/models/category-card.ts`
- `apps/backend/src/modules/homepage-cms/models/partner.ts`

**Models:**
```ts
// homepage.ts — Singleton (1 row)
{
  id: model.id().primaryKey(),
  headline: model.text(),           // "Play.\nLearn.\nGrow."
  subtitle: model.text(),           // "Curated toys that spark..."
  badge_1_text: model.text(),       // "Educational Toys"
  badge_2_text: model.text(),       // "🚚 Gratis ongkir 500k+"
  cta_1_label: model.text(),       // "Shop All"
  cta_1_link: model.text(),        // "/store"
  cta_2_label: model.text(),       // "Rent a Toy"
  cta_2_link: model.text(),        // "/categories/toys-for-rent"
  rent_banner_title: model.text(),  // "Toys for Rent"
  rent_banner_text: model.text(),   // "Try before you buy..."
  rent_banner_cta: model.text(),    // "Rent now"
  section_best_deals_heading: model.text(),   // "Best Deals"
  section_new_arrivals_heading: model.text(), // "New Arrivals"
  section_partners_heading: model.text(),     // "Partners & Friends"
}

// hero-photo.ts
{
  id: model.id().primaryKey(),
  homepage_id: model.text(),        // FK ke homepage
  image_url: model.text(),
  label: model.text(),              // "Movement"
  rotate: model.text(),             // "-rotate-2"
  sort_order: model.number(),
}

// category-card.ts
{
  id: model.id().primaryKey(),
  homepage_id: model.text(),
  label: model.text(),              // "Construction & Open-Ended"
  sub: model.text(),                // "Build & create"
  image_url: model.text(),
  handle: model.text(),             // "/categories/construction-and-open-ended"
  badge: model.text(),              // "🧱"
  bg_color: model.text(),           // "bg-orange-400"
  sort_order: model.number(),
}

// partner.ts
{
  id: model.id().primaryKey(),
  homepage_id: model.text(),
  name: model.text(),               // "Kidzooona"
  image_url: model.text(),
  link: model.text(),
  sort_order: model.number(),
}
```

**Status:** `completed`

---

### Step 2: Service + Module Definition
**Session: Buat service homepage-cms**
**Files:**
- `apps/backend/src/modules/homepage-cms/service.ts`
- `apps/backend/src/modules/homepage-cms/index.ts`
- `apps/backend/src/modules/homepage-cms/package.json`

**service.ts:**
```ts
import { MedusaService } from "@medusajs/framework/utils"
import Homepage from "./models/homepage"
import HeroPhoto from "./models/hero-photo"
import CategoryCard from "./models/category-card"
import Partner from "./models/partner"

class HomepageCmsService extends MedusaService({
  Homepage,
  HeroPhoto,
  CategoryCard,
  Partner,
}) {}

export default HomepageCmsService
```

**index.ts:**
```ts
import { Module } from "@medusajs/framework/utils"
import HomepageCmsService from "./service"

export const HOMEPAGE_CMS_MODULE = "homepageCms"

export default Module(HOMEPAGE_CMS_MODULE, {
  service: HomepageCmsService,
})
```

**package.json:**
```json
{
  "name": "homepage-cms",
  "version": "0.0.1",
  "private": true
}
```

**Status:** `completed`

---

### Step 3: Register Module + Migration
**Session: Register module dan generate migration**
**Files:**
- `apps/backend/medusa-config.ts` — tambah module ke `modules` array

**Config:**
```ts
// Tambah di modules array di medusa-config.ts:
{
  resolve: "./src/modules/homepage-cms",
}
```

**Commands:**
```bash
yarn workspace @dtc/backend medusa db:generate homepage_cms
yarn workspace @dtc/backend medusa db:migrate
```

**Status:** `completed`

---

### Step 4: Seed Data
**Session: Buat seed script homepage data**
**Files:**
- `apps/backend/src/migration-scripts/seed-homepage-cms.ts`

**Seed data:**
- 1 homepage row (headline, subtitle, badges, CTAs, section headings)
- 4 hero photos (jungle-gym, construction, little-chef, sensory)
- 4 category cards (construction, fine-motor, movement, sensory)
- 13 partners (kidzooona, jumma, kejora, edokko, group-152, tentang-anak, bca, blibli, tokopedia, buumi, dekoruma, fanpekka, juniordept)

**Status:** `completed`

---

### Step 5: Public API Route
**Session: Buat GET /store/homepage**
**Files:**
- `apps/backend/src/api/store/homepage/route.ts`

**Response shape:**
```json
{
  "homepage": {
    "headline": "Play.\nLearn.\nGrow.",
    "subtitle": "...",
    "hero_photos": [{"image_url": "...", "label": "Movement", "rotate": "-rotate-2"}],
    "category_cards": [{"label": "Construction...", "sub": "Build & create", "image_url": "...", "handle": "...", "badge": "🧱", "bg_color": "bg-orange-400"}],
    "partners": [{"name": "Kidzooona", "image_url": "...", "link": "..."}],
    "section_best_deals_heading": "Best Deals",
    "section_new_arrivals_heading": "New Arrivals",
    "section_partners_heading": "Partners & Friends"
  }
}
```

**Status:** `completed`

---

### Step 6: Admin API Routes
**Session: Buat admin routes untuk CRUD homepage**
**Files:**
- `apps/backend/src/api/admin/homepage/route.ts` — GET + POST

**GET /admin/homepage** — fetch semua data (homepage + photos + cards + partners)
**POST /admin/homepage** — update homepage + replace photos/cards/partners

**Status:** `completed`

---

### Step 7: Admin Widget
**Session: Buat admin widget homepage-cms**
**Files:**
- `apps/backend/src/admin/widgets/homepage-cms.tsx`

**UI Components:**
- Form fields: headline, subtitle, badge_1, badge_2, cta_1 (label+link), cta_2 (label+link)
- Rent banner fields: title, text, cta
- Section headings: best_deals, new_arrivals, partners
- Hero Photos list: image_url + label + rotate + sort_order + hapus/tambah
- Category Cards list: label + sub + image_url + handle + badge + bg_color + sort_order + hapus/tambah
- Partners list: name + image_url + link + sort_order + hapus/tambah
- Save button → POST /admin/homepage

**Status:** `completed`

---

### Step 8: Storefront — Fetch Function
**Session: Buat fungsi fetch homepage CMS**
**Files:**
- `apps/storefront/src/lib/data/homepage.ts`

**Functions:**
```ts
export async function getHomepageContent() {
  // Fetch dari GET /store/homepage
  // Return { homepage, hero_photos, category_cards, partners }
}
```

**Status:** `completed`

---

### Step 9: Storefront — Update Page + Hero
**Session: Update homepage dan hero component**
**Files:**
- `apps/storefront/src/app/[countryCode]/(main)/page.tsx` — fetch CMS data, pass ke sections
- `apps/storefront/src/modules/home/components/hero/index.tsx` — accept props, render dari CMS

**Changes page.tsx:**
- Import `getHomepageContent`
- Fetch CMS data server-side
- Pass hero_photos, category_cards, partners ke Hero component
- Pass section headings ke Best Deals / New Arrivals / Partners sections

**Changes hero/index.tsx:**
- Convert dari hardcoded → props-driven
- Accept: hero_photos, category_cards, badges, headline, subtitle, CTAs, rent_banner

**Status:** `completed`

---

### Step 10: Revalidation
**Session: Setup revalidation untuk CMS**
**Files:**
- `apps/storefront/src/app/api/revalidate/route.ts` — extend untuk homepage tag

**Add:**
- Support `tag: "homepage"` di revalidate endpoint
- `getHomepageContent()` pakai `next: { tags: ["homepage"] }`

**Status:** `completed`

---

### Step 11: Test End-to-End
**Session: Test semua flow**

**Checklist:**
- [x] Migration berhasil — 4 tabel (homepage, hero_photo, category_card, partner)
- [x] Seed data masuk ke database — 1 homepage + 4 photos + 4 cards + 13 partners
- [x] `GET /store/homepage` return data lengkap ✅ verified
- [x] `POST /admin/homepage` create/update berfungsi ✅ verified
- [ ] Admin widget muncul di dashboard — perlu test manual di browser
- [ ] Admin bisa edit + save homepage content — perlu test manual di browser
- [ ] Storefront homepage render dari CMS — perlu test manual di browser
- [ ] Hero photos tampil dengan benar — perlu test manual di browser
- [ ] Category cards tampil dengan benar — perlu test manual di browser
- [ ] Partners logos tampil dengan benar — perlu test manual di browser
- [ ] Revalidation berfungsi — perlu test manual

**Bug fixed:** `updateHomepages(id, data)` → `updateHomepages({ id, ...data })` — MedusaService expects single object, not (id, data)

**Status:** `completed` (API verified; visual test di browser dilakukan oleh user)

---

## 📂 File Summary

| # | File | Task | Status |
|---|---|---|---|
| 1 | `src/modules/homepage-cms/models/homepage.ts` | Step 1 | ✅ |
| 2 | `src/modules/homepage-cms/models/hero-photo.ts` | Step 1 | ✅ |
| 3 | `src/modules/homepage-cms/models/category-card.ts` | Step 1 | ✅ |
| 4 | `src/modules/homepage-cms/models/partner.ts` | Step 1 | ✅ |
| 5 | `src/modules/homepage-cms/service.ts` | Step 2 | ✅ |
| 6 | `src/modules/homepage-cms/index.ts` | Step 2 | ✅ |
| 7 | `src/modules/homepage-cms/package.json` | Step 2 | ✅ |
| 8 | `apps/backend/medusa-config.ts` | Step 3 | ✅ |
| 9 | `src/migration-scripts/seed-homepage-cms.ts` | Step 4 | ✅ |
| 10 | `src/api/store/homepage/route.ts` | Step 5 | ✅ |
| 11 | `src/api/admin/homepage/route.ts` | Step 6 | ✅ |
| 12 | `src/admin/widgets/homepage-cms.tsx` | Step 7 | ✅ |
| 13 | `apps/storefront/src/lib/data/homepage.ts` | Step 8 | ✅ |
| 14 | `apps/storefront/src/app/[countryCode]/(main)/page.tsx` | Step 9 | ✅ |
| 15 | `apps/storefront/src/modules/home/components/hero/index.tsx` | Step 9 | ✅ |
| 16 | `apps/storefront/src/app/api/revalidate/route.ts` | Step 10 | ✅ |

---

## ⚡ Quick Start

Untuk mulai kerjakan, suruh agent:

```
Buka AGENTS_TODO.md, kerjakan Step 11: Test End-to-End
```

Setiap step selesai, update status dari `pending` → `completed`.
