| Поле | Значення |
|---|
| Статус | 🟢 prod |
| Поверхні | web |
| Доступність | створення/керування — потрібен акаунт; перегляд публічного вступлиста — без логіну |
| Власник | TODO: |
| Останнє підтвердження | 2026-06-14 · код:main + live (публічний /uk/list/<uuid> → 200, /catalogs/<uuid> без токена → 404, /profile/saved → 307). Авторизований UI — code-derived |
Авторизований абітурієнт зберігає конкурсні пропозиції (оффери) з каталогу/пошуку в особисті колекції-каталоги, переглядає їх із персональним конкурсним балом і позицією, кастомізує (емодзі, обкладинка, markdown-опис), ділиться публічним посиланням/QR і клонує чужі публічні каталоги.
- Кнопка-закладка «Зберегти» на картці оферу (
/offers/result/**) → попап вибору каталогу (гостю — пропозиція реєстрації).
- Галерея
/profile/saved (CatalogsAll) — усі каталоги з обкладинкою, емодзі, лічильником, бейджем видимості (Globe=публічний / Lock=приватний / Star=стандартний).
- Каталог
/profile/saved/[catalogId] — hero-обкладинка, markdown «про список», таблиця офферів з персональними concursScore/concursPosition.
- Створення/редагування
/profile/saved/create, /saved/[catalogId]/edit — назва, видимість, опис, контент, емодзі, обкладинка (color/gradient/image).
- Шеринг: діалог QR (
react-qr-code) на abitly.org/<locale>/list/<catalogId>, copy-link, download QR.
- Публічна сторінка
/list/[catalogId] — будь-хто без логіну бачить публічний каталог; гостю — RegisterCTA + кнопка клонувати (SaveCopyButton).
Платіжного/ботового флоу тут немає — фіча суто веб.
| Джерело | Ендпоінт / entity | Призначення |
|---|
| api-v2 | POST/GET/PATCH/DELETE /catalogs | CRUD каталогів |
| api-v2 | GET /catalogs/:id | OptionalJwtAuthGuard: публічний — гостю, приватний → 403 |
| api-v2 | POST/DELETE /catalogs/:id/offers/:offerId | додати/прибрати оффер |
| api-v2 | POST /catalogs/:id/clone | клонувати лише публічний (клон → private, ім’я +« (копія)») |
| api-v2 | entities catalogs (Catalog) + saved_offers (SavedOffer, PK catalogId+offerId) | схема abitly |
- offer-search — джерело офферів (кнопка-закладка); той самий механізм персонального балу (
populateOffersWithUserConcursData).
- account-auth — гейт власницьких сторінок; реєстрація стартує з попапу збереження.
- profile —
/profile/saved як розділ кабінету; лічильник у дашборді.
- profile-bot-link — приватні/публічні вступлісти як джерело specialty-сигналів (ADR-0011, дизайн).
| Репо | Шлях | Примітка |
|---|
abitly-frontend-v2 | src/app/[locale]/(profile)/profile/saved/**, (public)/list/[catalogId] | роути власницькі + публічний |
abitly-frontend-v2 | src/api/catalogs/catalogs.api.ts + catalogs.queries.ts | клієнт (не ретраїть 401/403/404) |
abitly-api-v2 | src/api/catalogs/catalogs.controller.ts · catalog.ts / savedOffer.ts | контролер + entities |
- Власницькі сторінки за логіном — UI не верифіковано браузером (публічний
/list/<uuid> підтверджено live).
- Стандартний (default) каталог (
isDefault): не видаляється (400), не кастомізується; будь-який збережений оффер авто-дзеркалиться в нього; видалення оффера з default прибирає його з усіх каталогів.
- Клонувати можна лише публічний (приватний → 403); клон завжди private.
- Персональні бал/позиція рахуються лише для APPLICANT/APPLICANT_MEMBER із заповненими grades, інакше
null.
- Жорстких лімітів на к-ть каталогів/офферів у коді немає; обмеження довжин:
name≤100, description≤200, content≤5000, emoji≤60, coverValue≤100.
- Публічний URL — повний
/list/<uuid> (не короткий slug); «shortUrl» у QR-діалозі = той самий URL без схеми. SEO: лише public-каталоги індексуються.
| Дата | Подія | Джерело |
|---|
| 2026-06-14 | створено картку (злито saved-offers + vstuplysty); факти з коду main + публічний live | PR Wave 2 |