# Content Article Module — Flow & Structure

## Controller

**File:** `app/Http/Controllers/Backend/ContentArticleController.php`

### Data yang dipass ke view

| Variable | Source | Description |
|----------|--------|-------------|
| `$categories` | Ref where `cat = 'ARTICLE_CAT'` | Dropdown Category |
| `$subcategories` | Ref where `cat = 'ARTICLE_SUBCAT'` | Dropdown Subcategory |
| `$statuses` | Ref where `cat = 'ARTICLE_STATUS'` | Dropdown Status |
| `$languages` | Ref where `cat = 'LANGUAGE'` | Dropdown language switcher |
| `$article` | ContentArticle::with('translations') | Model (edit page only) |

---

## Form Structure

### 1. Translations Card

```
Language switcher (select) ─────► x-model="selectedLang"
                                        │
            ┌───────────────────────────┴───────────────────────────┐
            ▼                                                       ▼
      Title input (per language)                             Content textarea (per language)
      name="translations[BM][title]"                         name="translations[BM][content]"
      x-show="selectedLang === 'BM'"                         x-show="selectedLang === 'BM'"
```

- Semua languages render sekali dalam DOM, tapi hanya **satu** yang nampak (`x-show`)
- `x-data="{ selectedLang: '{{ $firstLang }}' }"` — default ke language pertama
- Main Translation checkbox guna Alpine toggle (`x-data="{ checkboxToggle: ... }"`)

### 2. Article Information Card

| Field | Name Attribute | Type |
|-------|---------------|------|
| Portal Display | `article_portal_category` | text |
| Menu Set | `menu_set` | string |
| Article Slug | `article_code` | text + regenerate button |
| Category | `article_category` | select |
| Subcategory | `article_subcategory` | select |
| Status | `article_status` | select |
| Article Date | `article_date` | date |
| Start Date | `article_start_date` | date |
| Start Time | `article_start_time` | time |
| End Date | `article_end_date` | date |
| End Time | `article_end_time` | time |
| Sorting | `article_sorting` | text (kosong = null) |
| Image | `article_image` | file (FilePond) |

---

## Controller Flow

### STORE (create)

```
Form submit
    │
    ▼
ContentArticleRequest (validation)
    │
    ├── Upload image ke storage/app/public/article/
    │
    ├── ContentArticle::create([...])  ← insert main table
    │
    └── Loop $request->translations:
            if (!empty($translation['title'])):
                ContentArticleTranslation::create([
                    'article_translation_parent_id' => $article->article_id,
                    'article_translation_title'     => $translation['title'],
                    'article_translation_content'   => $translation['content'] ?? '',
                    'article_translation_main'      => $translation['main'] ?? 0,
                    'article_translation_language'  => $lang,
                ])
```

### UPDATE (edit)

```
Form submit (PUT)
    │
    ▼
ContentArticleRequest (validation)
    │
    ├── Upload/Replace image kalau ada baru
    │
    ├── $article->update([...])  ← update main table
    │
    ├── $article->translations()->delete()  ← delete semua translations lama
    │
    └── Loop $request->translations:  ← insert semula yang baru
            (same logic as store)
```

---

## Database Schema

### `content_article` (main table)

| Column | Type | Notes |
|--------|------|-------|
| article_id | PK | auto increment |
| article_code | string | UUID |
| article_date | date | nullable |
| article_category | string | nullable |
| article_subcategory | string | nullable |
| article_status | string | nullable |
| article_url | string | nullable |
| article_image | string | path to storage |
| article_sorting | integer | nullable |
| article_portal_category | string | nullable |
| article_start_date | date | nullable |
| article_start_time | time | nullable |
| article_end_date | date | nullable |
| article_end_time | time | nullable |
| menu_set | string | nullable |
| created_by | integer | FK to users |
| updated_by | integer | FK to users |

### `content_article_translation` (translations table)

| Column | Type | Notes |
|--------|------|-------|
| article_translation_id | PK | auto increment |
| article_translation_parent_id | FK | -> content_article.article_id |
| article_translation_language | string | 'BM', 'EN', etc |
| article_translation_title | string | |
| article_translation_content | text | nullable |
| article_translation_main | boolean | 0/1 |
| created_by | integer | |
| updated_by | integer | |

---

## TailAdmin Form Element Patterns

| Element | Pattern |
|---------|---------|
| Text input | `dark:bg-dark-900 shadow-theme-xs focus:border-brand-300... h-11 w-full rounded-lg...` |
| Select | Wrapped in `div x-data="{ isOptionSelected: false }"` + chevron SVG |
| Date picker | Wrapped in `div.relative` + calendar icon + `onclick="this.showPicker()"` |
| Time picker | Wrapped in `div.relative` + clock icon + `onclick="this.showPicker()"` |
| Checkbox | Alpine toggle: `sr-only` input + styled `div` + SVG checkmark |
| File input | FilePond (`class="filepond w-full"`) — JS replace DOM |

---

## Validation

**File:** `app/Http/Requests/Backend/ContentArticleRequest.php`

Basic validation rules for required fields and image type/size.
