переименования папок

This commit is contained in:
2025-07-21 15:02:10 +03:00
parent d0c79bd334
commit 84f0c9c6aa
72 changed files with 245 additions and 249 deletions

View File

@@ -0,0 +1,177 @@
export interface ExcelParseResult {
fileId: string // ID загруженного файла
data: Record<string, any>
mergedCells: Array<{ from: string; to: string; value: any }>
}
export interface ApiUploadResponse {
file_id: string
cells: {
cells: Record<string, any>
merged: Array<{ from: string; to: string }>
}
}
export interface ApiFileResponse {
file: {
id: string
name: string
path: string
size: number
template_id: string | null
created_at: string
updated_at: string
deleted_at: string | null
cells?: {
cells: Record<string, any>
merged: Array<{ from: string; to: string }>
}
} | null
}
export interface ApiFilesResponse {
files: Array<{
id: string
name: string
path: string
size: number
template_id: string | null
created_at: string
updated_at: string
deleted_at: string | null
}>
}
// API загрузка файла на сервер
export async function parseExcelFile(
file: File,
templateId: string
): Promise<ExcelParseResult> {
const formData = new FormData()
formData.append('file', file)
try {
const response = await fetch(
`/api/files/upload?template_id=${templateId}`,
{
method: 'POST',
body: formData,
}
)
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const result: ApiUploadResponse = await response.json()
// Преобразуем ответ API в формат, ожидаемый приложением
const data = result.cells.cells
const mergedCells = result.cells.merged.map(merge => ({
from: merge.from,
to: merge.to,
value: data[merge.from] || '',
}))
return {
fileId: result.file_id, // Добавляем fileId в возвращаемые данные
data,
mergedCells,
}
} catch (error) {
console.error('Ошибка при загрузке файла:', error)
throw new Error('Ошибка при загрузке файла на сервер')
}
}
// Получение файлов по template_id
export async function getFilesByTemplateId(
templateId: string
): Promise<ApiFilesResponse['files']> {
try {
const response = await fetch('/api/files/', {
method: 'GET',
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const result: ApiFilesResponse = await response.json()
// Фильтруем файлы по template_id
const templateFiles = result.files.filter(
file => file.template_id === templateId && !file.deleted_at
)
return templateFiles
} catch (error) {
console.error('Ошибка при получении файлов:', error)
throw new Error('Ошибка при получении файлов')
}
}
// Получение последнего файла для шаблона
export async function getLatestFileForTemplate(
templateId: string
): Promise<ApiFilesResponse['files'][0] | null> {
try {
const files = await getFilesByTemplateId(templateId)
if (files.length === 0) {
return null
}
// Сортируем по дате обновления и берем последний
const sortedFiles = files.sort(
(a, b) =>
new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()
)
return sortedFiles[0]
} catch (error) {
console.error('Ошибка при получении последнего файла:', error)
return null
}
}
// Получение данных файла по ID
export async function getFileData(fileId: string): Promise<ExcelParseResult> {
try {
const response = await fetch(`/api/files/${fileId}`, {
method: 'GET',
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const result: ApiFileResponse = await response.json()
if (!result.file) {
throw new Error('Файл не найден')
}
// Проверяем, есть ли данные ячеек в ответе
if (!result.file.cells) {
throw new Error('Данные файла не содержат информации о ячейках')
}
// Преобразуем данные в формат, ожидаемый приложением
const data = result.file.cells.cells
const mergedCells = result.file.cells.merged.map(merge => ({
from: merge.from,
to: merge.to,
value: data[merge.from] || '',
}))
return {
fileId: result.file.id,
data,
mergedCells,
}
} catch (error) {
console.error('Ошибка при получении данных файла:', error)
throw new Error('Ошибка при получении данных файла')
}
}

View File

@@ -0,0 +1,204 @@
// API типы для работы с листами
export interface CreateSheetInput {
name: string
cells: Record<string, any>
template_id: string
}
export interface CreateSheetOutput {
id: string
}
export interface GetSheetsOutput {
sheets: ApiSheet[]
}
export interface GetSheetOutput {
sheet: ApiSheet | null
}
export interface PatchSheetInput {
name?: string | null
cells?: Record<string, any> | null
}
export interface PatchSheetOutput {
id: string
}
export interface ApiSheet {
id: string
name: string
cells: Record<string, any>
template_id: string
created_at: string
updated_at: string
deleted_at?: string | null
}
// API создание листа
export async function createSheet(
sheet: CreateSheetInput
): Promise<CreateSheetOutput> {
try {
console.log('📤 Отправляем данные для создания листа:', sheet)
const response = await fetch('/api/sheets/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(sheet),
})
if (!response.ok) {
// Пытаемся получить подробности ошибки от сервера
let errorDetails = `HTTP error! status: ${response.status}`
try {
const errorData = await response.json()
console.error('❌ Детали ошибки сервера:', errorData)
errorDetails += ` - ${JSON.stringify(errorData)}`
} catch (e) {
console.error('❌ Не удалось получить детали ошибки')
}
throw new Error(errorDetails)
}
const result: CreateSheetOutput = await response.json()
console.log('✅ Лист создан успешно:', result)
return result
} catch (error) {
console.error('Ошибка при создании листа:', error)
throw new Error('Ошибка при создании листа на сервере')
}
}
// API получение всех листов
export async function getSheets(): Promise<GetSheetsOutput> {
try {
const response = await fetch('/api/sheets/', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const result: GetSheetsOutput = await response.json()
return result
} catch (error) {
console.error('Ошибка при получении листов:', error)
throw new Error('Ошибка при получении листов с сервера')
}
}
// API получение листов для конкретного шаблона
export async function getSheetsByTemplate(
templateId: string
): Promise<GetSheetsOutput> {
try {
console.log('📋 Запрашиваем листы для templateId:', templateId)
// Получаем все листы и фильтруем на клиенте
const response = await fetch(`/api/sheets/`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
console.log('📋 Ответ сервера на запрос листов:', response.status)
if (!response.ok) {
// Пытаемся получить подробности ошибки от сервера
let errorDetails = `HTTP error! status: ${response.status}`
try {
const errorData = await response.json()
console.error('❌ Детали ошибки при получении листов:', errorData)
errorDetails += ` - ${JSON.stringify(errorData)}`
} catch (e) {
console.error(
'❌ Не удалось получить детали ошибки при получении листов'
)
}
throw new Error(errorDetails)
}
const allSheets: GetSheetsOutput = await response.json()
// Фильтруем листы по template_id на клиенте
const filteredSheets = allSheets.sheets.filter(
sheet => sheet.template_id === templateId
)
console.log('✅ Получены и отфильтрованы листы для шаблона:', {
templateId,
totalSheets: allSheets.sheets.length,
filteredSheetsCount: filteredSheets.length,
sheetNames: filteredSheets.map(s => s.name),
})
return { sheets: filteredSheets }
} catch (error) {
console.error('❌ Ошибка при получении листов шаблона:', error)
// Если ошибка 404 или подобная, возвращаем пустой список вместо выброса ошибки
if (error instanceof Error && error.message.includes('404')) {
console.log('📭 Листы для шаблона не найдены, возвращаем пустой список')
return { sheets: [] }
}
throw new Error('Ошибка при получении листов шаблона с сервера')
}
}
// API получение конкретного листа
export async function getSheet(sheetId: string): Promise<GetSheetOutput> {
try {
const response = await fetch(`/api/sheets/${sheetId}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const result: GetSheetOutput = await response.json()
return result
} catch (error) {
console.error('Ошибка при получении листа:', error)
throw new Error('Ошибка при получении листа с сервера')
}
}
// API обновление листа
export async function patchSheet(
sheetId: string,
sheet: PatchSheetInput
): Promise<PatchSheetOutput> {
try {
const response = await fetch(`/api/sheets/${sheetId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(sheet),
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const result: PatchSheetOutput = await response.json()
return result
} catch (error) {
console.error('Ошибка при обновлении листа:', error)
throw new Error('Ошибка при обновлении листа на сервере')
}
}

View File

@@ -0,0 +1,198 @@
export interface CreateTemplateInput {
name: string
description?: string
elements: Record<string, any>
}
export interface CreateTemplateOutput {
id: string
}
export interface GetTemplatesOutput {
templates: ApiTemplate[]
}
export interface GetTemplateOutput {
template: ApiTemplate | null
}
export interface PatchTemplateInput {
name?: string | null
description?: string | null
elements?: Record<string, any> | null
}
export interface PatchTemplateOutput {
id: string
}
export interface ApiTemplate {
id: string
name: string
description?: string | null
elements: Record<string, any>
created_at: string
updated_at: string
deleted_at?: string | null
}
// Импортируем типы для преобразования
import { getDefaultLayoutSettings, migrateTemplateElement } from '../lib/utils'
import { Template, TemplateElement } from '../type/template'
// Утилитарные функции для преобразования данных
// Преобразование API шаблона в внутренний формат
export function apiTemplateToTemplate(apiTemplate: ApiTemplate): Template {
// Преобразуем elements из Record<string, any> в TemplateElement[]
const elements: TemplateElement[] = Object.values(apiTemplate.elements || {})
.map(el => migrateTemplateElement(el))
.sort((a, b) => (a.order || 0) - (b.order || 0))
return {
id: apiTemplate.id,
name: apiTemplate.name,
description: apiTemplate.description || undefined,
elements,
layoutSettings: getDefaultLayoutSettings(),
createdAt: new Date(apiTemplate.created_at),
updatedAt: new Date(apiTemplate.updated_at),
}
}
// Преобразование внутреннего шаблона в API формат для создания
export function templateToCreateInput(
template: Omit<Template, 'id' | 'createdAt' | 'updatedAt'>
): CreateTemplateInput {
// Преобразуем элементы в Record<string, any>
const elements: Record<string, any> = {}
template.elements.forEach((element, index) => {
elements[element.id] = element
})
return {
name: template.name,
description: template.description,
elements,
}
}
// Преобразование внутреннего шаблона в API формат для обновления
export function templateToPatchInput(template: Template): PatchTemplateInput {
// Преобразуем элементы в Record<string, any>
const elements: Record<string, any> = {}
template.elements.forEach((element, index) => {
elements[element.id] = element
})
return {
name: template.name,
description: template.description,
elements,
}
}
// API создание шаблона
export async function createTemplate(
template: CreateTemplateInput
): Promise<CreateTemplateOutput> {
try {
const response = await fetch('/api/templates/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(template),
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const result: CreateTemplateOutput = await response.json()
return result
} catch (error) {
console.error('Ошибка при создании шаблона:', error)
throw new Error('Ошибка при создании шаблона на сервере')
}
}
// API получение всех шаблонов
export async function getTemplates(): Promise<GetTemplatesOutput> {
try {
const response = await fetch('/api/templates/', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const result: GetTemplatesOutput = await response.json()
return result
} catch (error) {
console.error('Ошибка при получении шаблонов:', error)
throw new Error('Ошибка при получении шаблонов с сервера')
}
}
// API получение конкретного шаблона
export async function getTemplate(
templateId: string
): Promise<GetTemplateOutput> {
try {
const response = await fetch(`/api/templates/${templateId}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const result: GetTemplateOutput = await response.json()
return result
} catch (error) {
console.error('Ошибка при получении шаблона:', error)
throw new Error('Ошибка при получении шаблона с сервера')
}
}
// API обновление шаблона
export async function patchTemplate(
templateId: string,
template: PatchTemplateInput
): Promise<PatchTemplateOutput> {
try {
const response = await fetch(`/api/templates/${templateId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(template),
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const result: PatchTemplateOutput = await response.json()
return result
} catch (error) {
console.error('Ошибка при обновлении шаблона:', error)
throw new Error('Ошибка при обновлении шаблона на сервере')
}
}
// Алиас для удобства использования
export async function updateTemplate(
template: Template
): Promise<PatchTemplateOutput> {
const patchInput = templateToPatchInput(template)
return patchTemplate(template.id, patchInput)
}