feat(media): add Media Manager UI (grid, upload, delete)
Some checks failed
Architecture Governance / architecture (push) Has been cancelled

MediaLibraryPageComponent replaces the coming-soon placeholder at
/backoffice/media. Built entirely on Sprint 6 Design System primitives
(app-card, app-button, app-input, app-empty-state, app-dialog, app-pagination,
app-skeleton) and Sprint 4 Task 2's MediaRepository/MockMediaRepository.

- Grid view with per-tile filename/size and delete action
- Hidden native file input triggered by an app-button, uploads via
  MediaLibraryFacade -> MediaRepository.upload()
- Delete requires confirmation through app-dialog (destructive action)
- Search + pagination wired to MockMediaRepository's list() params
- Loading state shows app-skeleton tiles; empty state shows app-empty-state
- New mediaLibrary.* translation namespace across en/ru/hy

Verified in browser (via a temporary unguarded route, reverted before
commit - /backoffice/media itself requires Telegram QR admin auth not
available in this session): empty state renders correctly with translated
copy, search input and upload button present, no console errors.
This commit is contained in:
sdarbinyan
2026-07-15 07:14:16 +04:00
parent c663c9099c
commit 5ffb353011
9 changed files with 358 additions and 1 deletions

View File

@@ -846,4 +846,17 @@ export const en: Translations = {
optionalDataMissingDescription: 'Optional configuration data is absent.',
optionalDataMissingResolution: 'Add optional value if UX depends on it.',
},
mediaLibrary: {
title: 'Media Library',
upload: 'Upload',
uploading: 'Uploading...',
searchPlaceholder: 'Search files...',
delete: 'Delete',
deleteConfirmTitle: 'Delete file?',
deleteConfirmBody: 'This cannot be undone.',
cancel: 'Cancel',
confirm: 'Delete',
emptyTitle: 'No files yet',
emptyDescription: 'Upload an image or document to get started.',
},
};

View File

@@ -841,4 +841,17 @@ export const hy: Translations = {
optionalDataMissingDescription: 'Optional config արժեքը բացակայում է։',
optionalDataMissingResolution: 'Ավելացրեք արժեքը, եթե UX-ը կախված է դրանից։',
},
mediaLibrary: {
title: 'Մեդիագրադարան',
upload: 'Վերբեռնել',
uploading: 'Վերբեռնվում է...',
searchPlaceholder: 'Փնտրել ֆայլեր...',
delete: 'Ջնջել',
deleteConfirmTitle: 'Ջնջե՞լ ֆայլը',
deleteConfirmBody: 'Այս գործողությունը հնարավոր չէ հետարկել։',
cancel: 'Չեղարկել',
confirm: 'Ջնջել',
emptyTitle: 'Ֆայլեր դեռ չկան',
emptyDescription: 'Վերբեռնեք պատկեր կամ փաստաթուղթ սկսելու համար։',
},
};

View File

@@ -841,4 +841,17 @@ export const ru: Translations = {
optionalDataMissingDescription: 'Необязательное конфигурационное значение отсутствует.',
optionalDataMissingResolution: 'Добавьте значение, если оно нужно UX.',
},
mediaLibrary: {
title: 'Медиатека',
upload: 'Загрузить',
uploading: 'Загрузка...',
searchPlaceholder: 'Поиск файлов...',
delete: 'Удалить',
deleteConfirmTitle: 'Удалить файл?',
deleteConfirmBody: 'Это действие необратимо.',
cancel: 'Отмена',
confirm: 'Удалить',
emptyTitle: 'Пока нет файлов',
emptyDescription: 'Загрузите изображение или документ, чтобы начать.',
},
};

View File

@@ -844,4 +844,17 @@ export interface Translations {
optionalDataMissingDescription: string;
optionalDataMissingResolution: string;
};
mediaLibrary: {
title: string;
upload: string;
uploading: string;
searchPlaceholder: string;
delete: string;
deleteConfirmTitle: string;
deleteConfirmBody: string;
cancel: string;
confirm: string;
emptyTitle: string;
emptyDescription: string;
};
}