Добавлены модели товаров и корзины для оптовиков, реализованы соответствующие мутации и запросы в GraphQL. Обновлен API для загрузки файлов с учетом новых типов данных. Улучшена обработка ошибок и добавлены новые функции для работы с категориями товаров.

This commit is contained in:
Bivekich
2025-07-17 16:36:07 +03:00
parent 6a94d51032
commit f377fbab5f
21 changed files with 3958 additions and 34 deletions

View File

@ -42,12 +42,25 @@ export async function POST(request: NextRequest) {
const file = formData.get('file') as File
const userId = formData.get('userId') as string
const messageType = formData.get('messageType') as string // 'IMAGE' или 'FILE'
const type = formData.get('type') as string // Для товаров: 'product'
if (!file || !userId || !messageType) {
return NextResponse.json(
{ error: 'File, userId and messageType are required' },
{ status: 400 }
)
// Проверяем параметры в зависимости от типа загрузки
if (type === 'product') {
// Для товаров нужен только файл
if (!file) {
return NextResponse.json(
{ error: 'File is required' },
{ status: 400 }
)
}
} else {
// Для мессенджера нужны все параметры
if (!file || !userId || !messageType) {
return NextResponse.json(
{ error: 'File, userId and messageType are required' },
{ status: 400 }
)
}
}
// Проверяем, что файл не пустой
@ -66,8 +79,8 @@ export async function POST(request: NextRequest) {
)
}
// Проверяем тип файла в зависимости от типа сообщения
const isImage = messageType === 'IMAGE'
// Проверяем тип файла в зависимости от типа загрузки
const isImage = type === 'product' || messageType === 'IMAGE'
const allowedTypes = isImage ? ALLOWED_IMAGE_TYPES : [...ALLOWED_IMAGE_TYPES, ...ALLOWED_FILE_TYPES]
if (!allowedTypes.includes(file.type)) {
@ -96,16 +109,41 @@ export async function POST(request: NextRequest) {
.replace(/_{2,}/g, '_') // Убираем множественные подчеркивания
.toLowerCase() // Приводим к нижнему регистру
const folder = isImage ? 'images' : 'files'
const key = `${folder}/${userId}/${timestamp}-${safeFileName}`
// Определяем папку и ключ в зависимости от типа загрузки
let folder: string
let key: string
if (type === 'product') {
folder = 'products'
key = `${folder}/${timestamp}-${safeFileName}`
} else {
folder = isImage ? 'images' : 'files'
key = `${folder}/${userId}/${timestamp}-${safeFileName}`
}
// Конвертируем файл в Buffer
const buffer = Buffer.from(await file.arrayBuffer())
// Очищаем метаданные от недопустимых символов
const cleanOriginalName = file.name.replace(/[^\w\s.-]/g, '_')
const cleanUserId = userId.replace(/[^\w-]/g, '')
const cleanMessageType = messageType.replace(/[^\w]/g, '')
// Подготавливаем метаданные в зависимости от типа загрузки
let metadata: Record<string, string>
if (type === 'product') {
metadata = {
originalname: cleanOriginalName,
uploadtype: 'product'
}
} else {
const cleanUserId = userId.replace(/[^\w-]/g, '')
const cleanMessageType = messageType.replace(/[^\w]/g, '')
metadata = {
originalname: cleanOriginalName,
uploadedby: cleanUserId,
messagetype: cleanMessageType
}
}
// Загружаем в S3
const command = new PutObjectCommand({
@ -114,11 +152,7 @@ export async function POST(request: NextRequest) {
Body: buffer,
ContentType: file.type,
ACL: 'public-read',
Metadata: {
originalname: cleanOriginalName,
uploadedby: cleanUserId,
messagetype: cleanMessageType
}
Metadata: metadata
})
await s3Client.send(command)
@ -126,15 +160,22 @@ export async function POST(request: NextRequest) {
// Возвращаем URL файла и метаданные
const url = `https://s3.twcstorage.ru/${BUCKET_NAME}/${key}`
return NextResponse.json({
const response: Record<string, unknown> = {
success: true,
url,
fileUrl: url, // Изменяем на fileUrl для совместимости с формой товаров
url, // Оставляем для совместимости с мессенджером
key,
originalName: file.name,
size: file.size,
type: file.type,
messageType
})
type: file.type
}
// Добавляем messageType только для мессенджера
if (messageType) {
response.messageType = messageType
}
return NextResponse.json(response)
} catch (error) {
console.error('Error uploading file:', error)