feat(client): add isResized type, uploadGalleryImages, resizeGalleryImage API
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import type { GalleryImageItem } from '@/entities/gallery/model/types'
|
||||
import { apiClient } from '@/shared/api/client'
|
||||
import { apiBaseURL } from '@/shared/config'
|
||||
import { ADMIN_UPLOAD_IMAGE_MAX_BYTES, formatAdminImageMaxSizeHint } from '@/shared/constants/upload-limits'
|
||||
|
||||
export async function fetchAdminGallery(): Promise<{ items: GalleryImageItem[] }> {
|
||||
const { data } = await apiClient.get<{ items: GalleryImageItem[] }>('admin/gallery')
|
||||
@@ -9,3 +11,42 @@ export async function fetchAdminGallery(): Promise<{ items: GalleryImageItem[] }
|
||||
export async function deleteGalleryImage(id: string): Promise<void> {
|
||||
await apiClient.delete(`admin/gallery/${id}`)
|
||||
}
|
||||
|
||||
export async function uploadGalleryImages(files: File[]): Promise<string[]> {
|
||||
for (const f of files) {
|
||||
if (f.size > ADMIN_UPLOAD_IMAGE_MAX_BYTES) {
|
||||
throw new Error(
|
||||
`Файл «${f.name}» слишком большой (максимум ${formatAdminImageMaxSizeHint()} на одно изображение).`,
|
||||
)
|
||||
}
|
||||
}
|
||||
const fd = new FormData()
|
||||
for (const f of files) {
|
||||
fd.append('files', f, f.name)
|
||||
}
|
||||
const token = localStorage.getItem('craftshop_auth_token')
|
||||
const base = apiBaseURL.replace(/\/$/, '')
|
||||
const res = await fetch(`${base}/admin/gallery/upload`, {
|
||||
method: 'POST',
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
body: fd,
|
||||
})
|
||||
const payload = (await res.json().catch(() => ({}))) as { urls?: string[]; error?: string }
|
||||
if (!res.ok) {
|
||||
if (res.status === 413) {
|
||||
throw new Error(
|
||||
'Сервер отклонил файл как слишком большой (413). На проде часто лимит nginx: добавьте client_max_body_size для /api/ (см. docs/nginx-upload-limit.md). Проверьте также MAX_UPLOAD_BODY_BYTES в .env на сервере.',
|
||||
)
|
||||
}
|
||||
throw new Error(typeof payload.error === 'string' ? payload.error : `Ошибка загрузки (${res.status})`)
|
||||
}
|
||||
if (!Array.isArray(payload.urls)) {
|
||||
throw new Error('Некорректный ответ сервера')
|
||||
}
|
||||
return payload.urls
|
||||
}
|
||||
|
||||
export async function resizeGalleryImage(id: string): Promise<{ url: string }> {
|
||||
const { data } = await apiClient.post<{ url: string }>(`admin/gallery/${id}/resize`)
|
||||
return data
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export { fetchAdminGallery, deleteGalleryImage } from './api/gallery-api'
|
||||
export { fetchAdminGallery, deleteGalleryImage, uploadGalleryImages, resizeGalleryImage } from './api/gallery-api'
|
||||
export type { GalleryImageItem } from './model/types'
|
||||
export { GalleryGrid } from './ui/GalleryGrid'
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export type GalleryImageItem = {
|
||||
id: string
|
||||
url: string
|
||||
isResized: boolean
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
Vendored
+4
@@ -1 +1,5 @@
|
||||
export declare const ADMIN_UPLOAD_IMAGE_MAX_FILE_BYTES_DEFAULT: 20971520
|
||||
|
||||
export declare const ADMIN_UPLOAD_IMAGE_MAX_BYTES: 20971520
|
||||
|
||||
export declare function formatAdminImageMaxSizeHint(): string
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
const MB = 1024 * 1024
|
||||
|
||||
export const ADMIN_UPLOAD_IMAGE_MAX_FILE_BYTES_DEFAULT = 20 * MB
|
||||
|
||||
export const ADMIN_UPLOAD_IMAGE_MAX_BYTES = 20 * MB
|
||||
|
||||
export function formatAdminImageMaxSizeHint() {
|
||||
return '20 МБ'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user