# 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`** - Відкрити сторінку MicroDAO (наприклад, `/microdao/daarion`) - Перейти до секції "Branding" 2. **Завантажити банер:** - Натиснути "Upload Banner" - Вибрати зображення (PNG/JPG, рекомендовано 1920x400 або подібне) - Дочекатись завершення завантаження (без помилок) 3. **Перевірити в DevTools → Network:** - Знайти запит на `/api/assets/upload` (або `/api/city/assets/upload`) - Статус: `200 OK` - Відповідь містить `processed_url` або `original_url` з MinIO URL - Знайти запит на `/api/microdao/{slug}/branding` (PATCH) - Статус: `200 OK` - Відповідь містить `banner_url` (не `null`) 4. **Перевірити оновлення в БД:** ```bash curl -s "https://daarion.space/api/city/microdao/daarion" | jq '{logo_url, banner_url}' ``` - `banner_url` має бути заповнений (не `null`) - URL має бути формату: `https://assets.daarion.space/daarion-assets/microdao/banner/...` 5. **Перевірити відображення:** - Оновити сторінку MicroDAO - Банер має відображатись (не placeholder) - В DevTools → Network знайти запит на `/api/city/assets/proxy/microdao/banner/...` - Статус: `200 OK`, `Content-Type: image/png` або `image/jpeg` ### 2. Гарантувати запис `banner_url` у БД **Перевірити:** 1. **Backend endpoint `/api/microdao/{slug}/branding` (PATCH):** - Файл: `apps/web/src/app/api/microdao/[slug]/branding/route.ts` (або подібний) - Переконатись, що `banner_url` зберігається в БД - Перевірити валідацію URL 2. **Backend endpoint `/api/city/microdao/{slug}/branding` (якщо є):** - Файл: `services/city-service/routes_city.py` - Переконатись, що endpoint оновлює `banner_url` в таблиці `microdaos` 3. **Database schema:** - Переконатись, що `microdaos.banner_url` має тип `text` (після міграції `043_asset_urls_to_text.sql`) - Перевірити, що поле може бути `NULL` (для старих записів) ### 3. Додати fallback при `banner_url == null` **Варіанти реалізації:** #### Варіант A: Використати логотип як банер ```typescript // apps/web/src/components/microdao/MicrodaoHeaderCard.tsx const bannerUrl = normalizeAssetUrl(microdao.banner_url) || normalizeAssetUrl(microdao.logo_url); ``` #### Варіант B: Використати дефолтний банер ```typescript // 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 ```typescript // Якщо 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. **Зміст:** - Як завантажити логотип/банер через UI - Рекомендовані розміри: - Logo: 512x512px (квадратне) - Banner: 1920x400px (широке) - Підтримувані формати: PNG, JPG, WebP - Як працює proxy endpoint - Як працює `normalizeAssetUrl` - 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:** - `POST /api/assets/upload` (Next.js route) - Або `POST /api/city/assets/upload` (city-service) - Body: `FormData` з `file` та `type` (наприклад, `microdao_banner`) 2. **Update branding:** - `PATCH /api/microdao/{slug}/branding` - Body: `{ banner_url: "https://assets.daarion.space/..." }` 3. **Get MicroDAO:** - `GET /api/city/microdao/{slug}` - Response: `{ logo_url: "...", banner_url: "..." }` ### Файли для перевірки/зміни 1. **Frontend:** - `apps/web/src/components/microdao/MicrodaoBrandingCard.tsx` — компонент завантаження - `apps/web/src/components/microdao/MicrodaoHeaderCard.tsx` — відображення банера - `apps/web/src/app/microdao/[slug]/page.tsx` — сторінка MicroDAO 2. **Backend:** - `services/city-service/routes_city.py` — endpoint `/assets/upload` та `/microdao/{slug}/branding` - `apps/web/src/app/api/microdao/[slug]/branding/route.ts` — Next.js API route (якщо є) 3. **Database:** - Таблиця `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. Закомітити зміни