Темный режим
7.4. Survey - API и интеграция
Интеграция с API
Приложение Survey взаимодействует с API для получения данных опросов и отправки ответов пользователей. Взаимодействие с API реализовано в модуле utils/api.
Структура API модуля
API модуль состоит из нескольких файлов:
src/utils/api/index.ts- основной интерфейс для APIsrc/utils/api/surveyApi.ts- функции для работы с API опросовsrc/utils/api/surveyData.ts- функции для работы с данными опросовsrc/utils/api/cache.ts- функции для кэширования запросов
Кэширование API-запросов
Для оптимизации работы с API и уменьшения количества запросов реализовано кэширование результатов запросов в localStorage.
Пример кода кэширования
// src/utils/api/cache.ts
/**
* Получение данных из кэша
* @param key Ключ кэша
* @returns Данные из кэша или null, если кэш не найден
*/
export const getCache = (key: string) => {
try {
const cacheItem = localStorage.getItem(`cache_${key}`);
if (!cacheItem) {
return null;
}
const { data, timestamp } = JSON.parse(cacheItem);
// Проверяем, не устарел ли кэш (24 часа)
const cacheAge = Date.now() - timestamp;
if (cacheAge > 24 * 60 * 60 * 1000) {
localStorage.removeItem(`cache_${key}`);
return null;
}
return data;
} catch (error) {
console.error('Error getting cache:', error);
return null;
}
};
/**
* Сохранение данных в кэш
* @param key Ключ кэша
* @param data Данные для сохранения
*/
export const setCache = (key: string, data: any) => {
try {
const cacheItem = {
data,
timestamp: Date.now()
};
localStorage.setItem(`cache_${key}`, JSON.stringify(cacheItem));
} catch (error) {
console.error('Error setting cache:', error);
}
};
/**
* Очистка кэша
* @param key Ключ кэша (если не указан, очищается весь кэш)
*/
export const clearCache = (key?: string) => {
try {
if (key) {
localStorage.removeItem(`cache_${key}`);
} else {
// Очистка всего кэша
Object.keys(localStorage).forEach((storageKey) => {
if (storageKey.startsWith('cache_')) {
localStorage.removeItem(storageKey);
}
});
}
} catch (error) {
console.error('Error clearing cache:', error);
}
};
Структура API ответов
Типичная структура ответа API для опроса:
Пример структуры ответа API
{
"questions": [
{
"questionId": "q1",
"question": "Насколько вы удовлетворены своей работой?",
"type": "stars-5pt",
"answer": null,
"hint": "Оцените по шкале от 1 до 5"
},
{
"questionId": "q2",
"question": "Как бы вы оценили атмосферу в команде?",
"type": "scale-11pt",
"answer": null,
"hint": null
},
// ... другие вопросы
],
"question_list": ["q1", "q2", "q3", "q4", "q5"],
"lang": "ru",
"companyname": "Example Company"
}
Обработка ошибок API
В проекте реализована обработка ошибок API с помощью try/catch и отображения ошибок пользователю.
Пример обработки ошибок API
/**
* Общая функция для выполнения API-запросов с обработкой ошибок
* @param url URL запроса
* @param options Опции запроса
* @returns Promise с результатом запроса
*/
export const apiRequest = async (url: string, options?: RequestInit) => {
try {
const response = await fetch(url, options);
if (!response.ok) {
// Проверяем тип ошибки
if (response.status === 401) {
throw new Error('Unauthorized');
} else if (response.status === 404) {
throw new Error('Resource not found');
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
}
return await response.json();
} catch (error) {
console.error('API request failed:', error);
// Для некоторых типов ошибок можно выполнить дополнительные действия
if (error.message === 'Unauthorized') {
// Например, перенаправить на страницу входа
}
throw error;
}
};
Сохранение состояния опроса
Для возможности продолжить опрос позже реализовано сохранение состояния прохождения опроса в localStorage.
Пример сохранения состояния опроса
// src/utils/surveyPersistence.ts
/**
* Сохранение состояния опроса
* @param surveyId ID опроса
* @param userId ID пользователя
* @param answers Ответы пользователя
* @param currentQuestionIndex Индекс текущего вопроса
* @returns true, если сохранение успешно
*/
export const saveSurveyState = (
surveyId: string,
userId: string,
answers: Record<string, any>,
currentQuestionIndex: number
) => {
try {
const stateKey = `surveyState_${surveyId}_${userId}`;
const state = {
answers,
currentQuestionIndex,
timestamp: new Date().toISOString()
};
localStorage.setItem(stateKey, JSON.stringify(state));
return true;
} catch (error) {
console.error('Error saving survey state:', error);
return false;
}
};
/**
* Загрузка состояния опроса
* @param surveyId ID опроса
* @param userId ID пользователя
* @returns Сохраненное состояние опроса или null
*/
export const loadSurveyState = (
surveyId: string,
userId: string
) => {
try {
const stateKey = `surveyState_${surveyId}_${userId}`;
const stateJson = localStorage.getItem(stateKey);
if (!stateJson) {
return null;
}
return JSON.parse(stateJson);
} catch (error) {
console.error('Error loading survey state:', error);
return null;
}
};
/**
* Удаление состояния опроса
* @param surveyId ID опроса
* @param userId ID пользователя
* @returns true, если удаление успешно
*/
export const clearSurveyState = (
surveyId: string,
userId: string
) => {
try {
const stateKey = `surveyState_${surveyId}_${userId}`;
localStorage.removeItem(stateKey);
return true;
} catch (error) {
console.error('Error clearing survey state:', error);
return false;
}
};