Skip to content

# TASK_PHASE_BRANDING_BANNERS_MVP — Завершення підтримки логотипів та банерів

## Контекст

Після виправлення proxy endpoint та нормалізації URL: - ✅ Логотипи працюють: завантажуються через `/api/city/assets/proxy/...` - ✅ Proxy endpoint працює: HEAD/GET методи підтримуються - ⚠️ Банери: `banner_url: null` в БД (просто ще не завантажували)

Поточна ситуація: - Технічна інфраструктура працює - Потрібно перевірити повний upload flow для банерів - Можливо додати fallback для відображення банера

## Завдання

### 1. Перевірити upload-флоу для банера

Кроки:

1. Залогінитись на `daarion.space`
2. Відкрити сторінку MicroDAO (наприклад, `/microdao/daarion`)

3. Перейти до секції "Branding"

4. Завантажити банер:

5. Натиснути "Upload Banner"
6. Вибрати зображення (PNG/JPG, рекомендовано 1920x400 або подібне)

7. Дочекатись завершення завантаження (без помилок)

8. Перевірити в DevTools → Network:

9. Знайти запит на `/api/assets/upload` (або `/api/city/assets/upload`)
10. Статус: `200 OK`
11. Відповідь містить `processed_url` або `original_url` з MinIO URL
12. Знайти запит на `/api/microdao/{slug}/branding` (PATCH)
13. Статус: `200 OK`

14. Відповідь містить `banner_url` (не `null`)

15. Перевірити оновлення в БД: `bash curl -s "https://daarion.space/api/city/microdao/daarion" | jq '{logo_url, banner_url}'`

16. `banner_url` має бути заповнений (не `null`)

17. URL має бути формату: `https://assets.daarion.space/daarion-assets/microdao/banner/...`

18. Перевірити відображення:

19. Оновити сторінку MicroDAO
20. Банер має відображатись (не placeholder)
21. В DevTools → Network знайти запит на `/api/city/assets/proxy/microdao/banner/...`
22. Статус: `200 OK`, `Content-Type: image/png` або `image/jpeg`

### 2. Гарантувати запис `banner_url` у БД

Перевірити:

1. Backend endpoint `/api/microdao/{slug}/branding` (PATCH):
2. Файл: `apps/web/src/app/api/microdao/[slug]/branding/route.ts` (або подібний)
3. Переконатись, що `banner_url` зберігається в БД

4. Перевірити валідацію URL

5. Backend endpoint `/api/city/microdao/{slug}/branding` (якщо є):

6. Файл: `services/city-service/routes_city.py`

7. Переконатись, що endpoint оновлює `banner_url` в таблиці `microdaos`

8. Database schema:

9. Переконатись, що `microdaos.banner_url` має тип `text` (після міграції `043_asset_urls_to_text.sql`)
10. Перевірити, що поле може бути `NULL` (для старих записів)

### 3. Додати fallback при `banner_url == null`

Варіанти реалізації:

#### Варіант A: Використати логотип як банер

    // apps/web/src/components/microdao/MicrodaoHeaderCard.tsx
    const bannerUrl = normalizeAssetUrl(microdao.banner_url) || normalizeAssetUrl(microdao.logo_url);

#### Варіант B: Використати дефолтний банер

    // apps/web/src/lib/utils/assetUrl.ts
    export function normalizeAssetUrl(url: string | null | undefined, fallback?: string): string | null {
      if (!url) return fallback || null;
      // ... existing logic
    }

    // Usage:
    const bannerUrl = normalizeAssetUrl(microdao.banner_url, '/assets/default-banner.png');

#### Варіант C: CSS gradient fallback

    // Якщо banner_url == null, використати CSS gradient замість зображення
    style={microdao.banner_url ? {
      backgroundImage: `url(${normalizeAssetUrl(microdao.banner_url)})`,
    } : {
      background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
    }}

Рекомендація: Варіант A (використати логотип) — найпростіший і найлогічніший.

### 4. Задокументувати "як правильно додавати логотип/банер до MicroDAO"

Створити документацію:

1. Файл: `docs/BRANDING_ASSETS_GUIDE.md`

2. Зміст:

3. Як завантажити логотип/банер через UI
4. Рекомендовані розміри:
   - Logo: 512x512px (квадратне)
   - Banner: 1920x400px (широке)
5. Підтримувані формати: PNG, JPG, WebP
6. Як працює proxy endpoint
7. Як працює `normalizeAssetUrl`
8. Troubleshooting (якщо зображення не відображається)

## Acceptance Criteria

- [ ] Upload банера працює без помилок
- [ ] `banner_url` зберігається в БД після завантаження
- [ ] Банер відображається на сторінці MicroDAO після завантаження
- [ ] Proxy endpoint працює для банерів (`/api/city/assets/proxy/microdao/banner/...`)
- [ ] Додано fallback для `banner_url == null` (опціонально)
- [ ] Створено документацію по роботі з branding assets

## Технічні деталі

### Endpoints для перевірки

1. Upload asset:
2. `POST /api/assets/upload` (Next.js route)
3. Або `POST /api/city/assets/upload` (city-service)

4. Body: `FormData` з `file` та `type` (наприклад, `microdao_banner`)

5. Update branding:

6. `PATCH /api/microdao/{slug}/branding`

7. Body: `{ banner_url: "https://assets.daarion.space/..." }`

8. Get MicroDAO:

9. `GET /api/city/microdao/{slug}`
10. Response: `{ logo_url: "...", banner_url: "..." }`

### Файли для перевірки/зміни

1. Frontend:
2. `apps/web/src/components/microdao/MicrodaoBrandingCard.tsx` — компонент завантаження
3. `apps/web/src/components/microdao/MicrodaoHeaderCard.tsx` — відображення банера

4. `apps/web/src/app/microdao/[slug]/page.tsx` — сторінка MicroDAO

5. Backend:

6. `services/city-service/routes_city.py` — endpoint `/assets/upload` та `/microdao/{slug}/branding`

7. `apps/web/src/app/api/microdao/[slug]/branding/route.ts` — Next.js API route (якщо є)

8. Database:

9. Таблиця `microdaos` з полями `logo_url` та `banner_url` (тип `text`)

## Troubleshooting

### Проблема: Банер не зберігається в БД

Перевірити: 1. Чи працює endpoint `/api/microdao/{slug}/branding` (PATCH) 2. Чи правильно передається `banner_url` в запиті 3. Чи є помилки в логах city-service

### Проблема: Банер зберігається, але не відображається

Перевірити: 1. Чи використовується `normalizeAssetUrl` для банера 2. Чи працює proxy endpoint для шляху банера 3. Чи файл існує в MinIO за вказаним шляхом

### Проблема: Upload не працює

Перевірити: 1. Чи працює endpoint `/api/assets/upload` 2. Чи правильно налаштовані ENV змінні для MinIO 3. Чи є помилки в логах city-service

## Наступні кроки

1. Виконати перевірку upload-флоу для банера
2. Виправити виявлені проблеми (якщо є)
3. Додати fallback для `banner_url == null` (опціонально)
4. Створити документацію
5. Закомітити зміни