fix registration

This commit is contained in:
Tatiana Nikolaeva 2025-06-02 18:23:14 +05:00
parent 2ec9354fc1
commit 08f827267d
12 changed files with 84 additions and 88 deletions

View file

@ -1,4 +1,4 @@
import {BASE_URL, createRequestConfig, handleResponse} from "./BaseApi.ts"; import {BASE_URL, createRequestConfig, handleResponse, handleUnauthorizedError} from "./BaseApi.ts";
export const getAnswer = async (id: number) => { export const getAnswer = async (id: number) => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -13,6 +13,7 @@ export const getAnswer = async (id: number) => {
return await handleResponse(response) return await handleResponse(response)
} }
catch (error) { catch (error) {
handleUnauthorizedError(error);
console.error(`error when receiving the response: ${error}`); console.error(`error when receiving the response: ${error}`);
throw error; throw error;
} }
@ -28,9 +29,11 @@ export const getCompletionsAnswer = async (id: number) => {
const response = await fetch(`${BASE_URL}/questions/${id}/answers`, { const response = await fetch(`${BASE_URL}/questions/${id}/answers`, {
...createRequestConfig('GET'), ...createRequestConfig('GET'),
}) })
return await handleResponse(response) return await handleResponse(response)
} }
catch (error) { catch (error) {
handleUnauthorizedError(error);
console.error(`error when receiving the selected response: ${error}`); console.error(`error when receiving the selected response: ${error}`);
throw error; throw error;
} }

View file

@ -1,4 +1,4 @@
import {BASE_URL, createRequestConfig, handleResponse} from "./BaseApi.ts"; import {BASE_URL, createRequestConfig, handleResponse, handleUnauthorizedError} from "./BaseApi.ts";
export interface INewAnswer{ export interface INewAnswer{
text: string; text: string;
@ -42,6 +42,7 @@ export const addNewAnswerVariant = async (surveyId: number, questionId: number,
return await handleResponse(response) return await handleResponse(response)
} }
catch(err){ catch(err){
handleUnauthorizedError(err);
console.error(`Error adding a new response option: ${err}`); console.error(`Error adding a new response option: ${err}`);
throw err; throw err;
} }
@ -67,6 +68,7 @@ export const updateAnswerVariant = async (id: number, answer: INewAnswer): Promi
return await handleResponse(response) return await handleResponse(response)
} }
catch(err){ catch(err){
handleUnauthorizedError(err);
console.error(`Error updating the response option: ${err}`); console.error(`Error updating the response option: ${err}`);
throw err; throw err;
} }
@ -88,6 +90,7 @@ export const deleteAnswerVariant = async (id: number) => {
return responseData; return responseData;
} }
catch(err){ catch(err){
handleUnauthorizedError(err);
console.error(`Error deleting a answer: ${err}`); console.error(`Error deleting a answer: ${err}`);
throw err; throw err;
} }

View file

@ -1,4 +1,4 @@
import {BASE_URL, createRequestConfig, handleResponse} from "./BaseApi.ts"; import {BASE_URL, createRequestConfig, handleResponse, handleUnauthorizedError} from "./BaseApi.ts";
interface IAuthData{ interface IAuthData{
email: string; email: string;
@ -26,12 +26,6 @@ export const getCurrentUser = async () => {
} }
}); });
if (response.status === 401) {
localStorage.removeItem("token");
localStorage.removeItem("user");
throw new Error("Сессия истекла. Пожалуйста, войдите снова.");
}
if (!response.ok) { if (!response.ok) {
throw new Error(`Ошибка сервера: ${response.status}`); throw new Error(`Ошибка сервера: ${response.status}`);
} }
@ -40,6 +34,7 @@ export const getCurrentUser = async () => {
localStorage.setItem("user", JSON.stringify(userData)); localStorage.setItem("user", JSON.stringify(userData));
return userData; return userData;
} catch (error) { } catch (error) {
handleUnauthorizedError(error);
console.error("Ошибка при получении данных пользователя:", error); console.error("Ошибка при получении данных пользователя:", error);
throw error; throw error;
} }
@ -48,17 +43,21 @@ export const getCurrentUser = async () => {
export const registerUser = async (data: IRegistrationData) => { export const registerUser = async (data: IRegistrationData) => {
try { try {
const response = await fetch(`${BASE_URL}/auth/register`, { const response = await fetch(`${BASE_URL}/auth/register`, {
...createRequestConfig('POST'), body: JSON.stringify(data), ...createRequestConfig('POST'),
}) body: JSON.stringify(data),
const responseData = await handleResponse(response); });
if (responseData.accessToken) { if (!response.ok) {
localStorage.setItem("token", responseData.accessToken); const errorData = await response.json();
localStorage.setItem("user", JSON.stringify({ throw new Error(errorData.message || `Ошибка: ${response.status}`);
firstName: data.firstName, }
lastName: data.lastName,
email: data.email const responseData = await handleResponse(response);
})); if (responseData.accessToken || responseData.token) {
localStorage.setItem("token", responseData.accessToken || responseData.token);
if (responseData.user) {
localStorage.setItem("user", JSON.stringify(responseData.user));
}
} }
return responseData; return responseData;
@ -66,7 +65,7 @@ export const registerUser = async (data: IRegistrationData) => {
console.error("Registration error:", error); console.error("Registration error:", error);
throw error; throw error;
} }
} };
export const authUser = async (data: IAuthData) => { export const authUser = async (data: IAuthData) => {
try { try {
@ -74,6 +73,7 @@ export const authUser = async (data: IAuthData) => {
...createRequestConfig('POST'), ...createRequestConfig('POST'),
body: JSON.stringify(data), body: JSON.stringify(data),
}); });
const responseData = await handleResponse(response); const responseData = await handleResponse(response);
const token = responseData.accessToken || responseData.token; const token = responseData.accessToken || responseData.token;
@ -89,6 +89,7 @@ export const authUser = async (data: IAuthData) => {
return responseData; return responseData;
} catch (error) { } catch (error) {
handleUnauthorizedError(error);
console.error("Login error:", error); console.error("Login error:", error);
throw error; throw error;
} }

View file

@ -6,6 +6,13 @@ interface RequestConfig {
body?: BodyInit | null; body?: BodyInit | null;
} }
export const handleUnauthorizedError = (error: unknown) => {
if (error instanceof Error && error.message.includes('401')) {
window.location.href = '/login';
console.log('Сессия истекла. Перенаправление на страницу входа.');
}
};
/** /**
* Создаёт конфигурацию для fetch-запроса * Создаёт конфигурацию для fetch-запроса
* @param method HTTP-метод (GET, POST, PUT, DELETE) * @param method HTTP-метод (GET, POST, PUT, DELETE)
@ -37,14 +44,15 @@ const createRequestConfig = (method: string, isFormData: boolean = false): Reque
* @returns Распарсенные данные или ошибку * @returns Распарсенные данные или ошибку
*/ */
const handleResponse = async (response: Response) => { const handleResponse = async (response: Response) => {
if (response.status === 401) {
localStorage.removeItem("token");
localStorage.removeItem("user");
throw new Error("401: Unauthorized");
}
const responseText = await response.text(); const responseText = await response.text();
if (!responseText) { if (!responseText) {
if (response.status === 401) {
window.location.href = '/auth/login';
throw new Error('Требуется авторизация');
}
if (response.ok) { if (response.ok) {
return null; return null;
} }

View file

@ -1,4 +1,4 @@
import {BASE_URL, createRequestConfig, handleResponse} from "./BaseApi.ts"; import {BASE_URL, createRequestConfig, handleResponse, handleUnauthorizedError} from "./BaseApi.ts";
export interface IAnswer{ export interface IAnswer{
questionId: number; questionId: number;
answerText: string; answerText: string;
@ -16,6 +16,7 @@ export const getAllCompletions = async (surveyId: number) => {
return await handleResponse(response); return await handleResponse(response);
} }
catch (error) { catch (error) {
handleUnauthorizedError(error);
console.error(`Error when receiving all selected responses: ${error}`); console.error(`Error when receiving all selected responses: ${error}`);
throw error; throw error;
} }
@ -36,6 +37,7 @@ export const addNewCompletion = async (surveyId: number, answer: IAnswer) => {
return await handleResponse(response) return await handleResponse(response)
} }
catch (error) { catch (error) {
handleUnauthorizedError(error);
console.error(`Error when adding a new survey passage: ${error}`); console.error(`Error when adding a new survey passage: ${error}`);
throw error; throw error;
} }
@ -54,6 +56,7 @@ export const getCompletionById = async (id: number) => {
return await handleResponse(response); return await handleResponse(response);
} }
catch (error) { catch (error) {
handleUnauthorizedError(error);
console.error(`Error when receiving a completed survey by id: ${error}`); console.error(`Error when receiving a completed survey by id: ${error}`);
throw error; throw error;
} }

View file

@ -1,4 +1,4 @@
import {BASE_URL, createRequestConfig, handleResponse} from "./BaseApi.ts"; import {BASE_URL, createRequestConfig, handleResponse, handleUnauthorizedError} from "./BaseApi.ts";
import {IAnswerVariant} from "./AnswerVariantsApi.ts"; import {IAnswerVariant} from "./AnswerVariantsApi.ts";
export interface INewQuestion{ export interface INewQuestion{
@ -25,6 +25,7 @@ export const addNewQuestion = async (surveyId: number, question: INewQuestion) =
}) })
return await handleResponse(response) return await handleResponse(response)
} catch (error){ } catch (error){
handleUnauthorizedError(error);
throw new Error(`Error when adding a new question: ${error}`); throw new Error(`Error when adding a new question: ${error}`);
} }
} }
@ -34,12 +35,10 @@ export const getListQuestions = async (surveyId: number): Promise<IQuestion[]> =
const response = await fetch(`${BASE_URL}/surveys/${surveyId}/questions`, { const response = await fetch(`${BASE_URL}/surveys/${surveyId}/questions`, {
...createRequestConfig('GET'), ...createRequestConfig('GET'),
}) })
if (response.status === 200) {
return await handleResponse(response); return await handleResponse(response);
} }
throw new Error(`Ожидался код 200, получен ${response.status}`);
}
catch(error){ catch(error){
handleUnauthorizedError(error);
console.error(`Error when receiving the list of questions: ${error}`); console.error(`Error when receiving the list of questions: ${error}`);
throw error; throw error;
} }
@ -59,12 +58,10 @@ export const updateQuestion = async (id: number, question: Partial<INewQuestion>
questionType: question.questionType, questionType: question.questionType,
}), }),
}) })
if (response.status === 200) {
return await handleResponse(response) return await handleResponse(response)
} }
throw new Error(`Ожидался код 200, получен ${response.status}`)
}
catch(error){ catch(error){
handleUnauthorizedError(error);
console.error(`Error when updating question: ${error}`); console.error(`Error when updating question: ${error}`);
throw error; throw error;
} }
@ -86,6 +83,7 @@ export const deleteQuestion = async (id: number) => {
} }
return responseData; return responseData;
} catch (error){ } catch (error){
handleUnauthorizedError(error);
console.error(`Error deleting a question: ${error}`); console.error(`Error deleting a question: ${error}`);
throw error; throw error;
} }

View file

@ -1,4 +1,4 @@
import {BASE_URL, createRequestConfig, handleResponse} from "./BaseApi.ts"; import {BASE_URL, createRequestConfig, handleResponse, handleUnauthorizedError} from "./BaseApi.ts";
export interface ISurvey { export interface ISurvey {
id: number; id: number;
@ -28,6 +28,7 @@ export const getMySurveys = async (): Promise<ISurvey[]> => {
}); });
return await handleResponse(response); return await handleResponse(response);
} catch (error) { } catch (error) {
handleUnauthorizedError(error);
console.error("Error receiving surveys:", error); console.error("Error receiving surveys:", error);
throw error; throw error;
} }
@ -43,6 +44,7 @@ export const getAllSurveys = async (): Promise<ISurvey[]> => {
}) })
return await handleResponse(response); return await handleResponse(response);
} catch (error) { } catch (error) {
handleUnauthorizedError(error);
console.error("Error receiving surveys:", error); console.error("Error receiving surveys:", error);
throw error; throw error;
} }
@ -68,12 +70,13 @@ export const postNewSurvey = async (survey: INewSurvey): Promise<ISurvey> => {
throw new Error(`Ошибка: ${response.status}`); throw new Error(`Ошибка: ${response.status}`);
} }
const data = await response.json(); const data = await handleResponse(response);
if (!data.id) { if (!data.id) {
throw new Error("Сервер не вернул ID опроса"); throw new Error("Сервер не вернул ID опроса");
} }
return data; return data;
} catch (error) { } catch (error) {
handleUnauthorizedError(error);
console.error(`Error when adding a new survey: ${error}`); console.error(`Error when adding a new survey: ${error}`);
throw error; throw error;
} }
@ -90,6 +93,7 @@ export const getSurveyById = async (surveyId: number): Promise<ISurvey> => {
}) })
return await handleResponse(response); return await handleResponse(response);
} catch (error){ } catch (error){
handleUnauthorizedError(error);
console.error(`Error finding the survey by id: ${error}`); console.error(`Error finding the survey by id: ${error}`);
throw error; throw error;
} }
@ -115,6 +119,7 @@ export const deleteSurvey = async (surveyId: number) => {
} }
return responseData; return responseData;
} catch (error){ } catch (error){
handleUnauthorizedError(error);
console.error(`Error deleting a survey: ${error}`); console.error(`Error deleting a survey: ${error}`);
throw error; throw error;
} }
@ -138,12 +143,10 @@ export const updateSurvey = async (surveyId: number, survey: Partial<INewSurvey>
description: survey.description, description: survey.description,
}) })
}) })
if (response.status === 200) {
return await handleResponse(response); return await handleResponse(response);
} }
throw new Error(`Ожидался код 200, получен ${response.status}`);
}
catch (error){ catch (error){
handleUnauthorizedError(error);
console.error(`Error updating survey: ${error}`); console.error(`Error updating survey: ${error}`);
throw error; throw error;
} }

View file

@ -5,3 +5,18 @@
min-height: 100vh; min-height: 100vh;
padding: 34px 16%; padding: 34px 16%;
} }
.departur_button{
display: block;
margin: 10px auto;
padding: 25px 50.5px;
border: none;
border-radius: 20px;
background-color: #3788D6;
color: white;
font-weight: 700;
font-size: 24px;
text-align: center;
box-shadow: 0 0 7.4px 0 rgba(154, 202, 247, 1);
box-sizing: border-box;
}

View file

@ -7,34 +7,16 @@ import {getSurveyById, ISurvey} from "../../api/SurveyApi.ts";
import {getListQuestions} from "../../api/QuestionApi.ts"; import {getListQuestions} from "../../api/QuestionApi.ts";
import {getAnswerVariants, IAnswerVariant} from "../../api/AnswerVariantsApi.ts"; import {getAnswerVariants, IAnswerVariant} from "../../api/AnswerVariantsApi.ts";
export const CompletingSurvey = () => { export const CompletingSurvey = () => {
// const [titleSurvey, setTitleSurvey] = useState("Название опроса");
// const [descriptionSurvey, setDescriptionSurvey] = useState("");
// const [questions, setQuestions] = useState<Question[]>([
// { id: 1, text: 'Вопрос 1', questionType: 'SingleAnswerQuestion', answerVariants: [{ id: 1, text: 'Ответ 1' },
// { id: 2, text: 'Ответ 1' }, { id: 3, text: 'Ответ 1' }]},
// { id: 2, text: 'Вопрос 2', questionType: 'MultipleAnswerQuestion', answerVariants: [{ id: 1, text: 'Ответ 1' },
// { id: 2, text: 'Ответ 1' }, { id: 3, text: 'Ответ 1' }]}
// ]);
// const [questions, setQuestions] = useState<Question[]>([]);
// const [loading, setLoading] = useState(true);
// const [error, setError] = useState<string | null>(null);
//
// const [description, setDescription] = useState('');
// const [title, setTitle] = useState('');
//
// const { survey, setSurvey } = useOutletContext<{
// survey: ISurvey;
// setSurvey: (survey: ISurvey) => void;
// }>();
const {surveyId} = useParams<{surveyId: string}>(); const {surveyId} = useParams<{surveyId: string}>();
const [survey, setSurvey] = useState<ISurvey | null>(null); const [survey, setSurvey] = useState<ISurvey | null>(null);
const [questions, setQuestions] = useState<Question[]>([]); const [questions, setQuestions] = useState<Question[]>([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
useEffect(() => { useEffect(() => {
const fetchSurveyData = async () => { const fetchSurveyData = async () => {
try { try {
@ -73,6 +55,7 @@ export const CompletingSurvey = () => {
if (error) return <div>{error}</div>; if (error) return <div>{error}</div>;
if (!survey) return <div>Опрос не найден</div>; if (!survey) return <div>Опрос не найден</div>;
return ( return (
<div className={styles.survey}> <div className={styles.survey}>
<SurveyInfo <SurveyInfo
@ -85,6 +68,7 @@ export const CompletingSurvey = () => {
questions={questions} questions={questions}
setQuestions={setQuestions} setQuestions={setQuestions}
/> />
<button className={styles.departur_button}>Отправить</button>
</div> </div>
) )
} }

View file

@ -1,16 +0,0 @@
/*QuestionsList.module.css*/
.departur_button{
display: block;
margin: 10px auto;
padding: 25px 50.5px;
border: none;
border-radius: 20px;
background-color: #3788D6;
color: white;
font-weight: 700;
font-size: 24px;
text-align: center;
box-shadow: 0 0 7.4px 0 rgba(154, 202, 247, 1);
box-sizing: border-box;
}

View file

@ -3,7 +3,6 @@ import QuestionItem from "../QuestionItem/QuestionItem.tsx";
import AddQuestionButton from "../AddQuestionButton/AddQuestionButton.tsx"; import AddQuestionButton from "../AddQuestionButton/AddQuestionButton.tsx";
import {addNewQuestion, deleteQuestion, getListQuestions} from "../../api/QuestionApi.ts"; import {addNewQuestion, deleteQuestion, getListQuestions} from "../../api/QuestionApi.ts";
import {addNewAnswerVariant} from "../../api/AnswerVariantsApi.ts"; import {addNewAnswerVariant} from "../../api/AnswerVariantsApi.ts";
import styles from './QuestionsList.module.css'
import {useRouteReadOnly} from "../../hooks/useRouteReadOnly.ts"; import {useRouteReadOnly} from "../../hooks/useRouteReadOnly.ts";
interface QuestionsListProps { interface QuestionsListProps {
@ -127,9 +126,7 @@ const QuestionsList: React.FC<QuestionsListProps> = ({questions, setQuestions, s
surveyId={surveyId} surveyId={surveyId}
/> />
))} ))}
{!isReadOnly ? <AddQuestionButton onClick={handleAddQuestion} /> : ( {!isReadOnly ? <AddQuestionButton onClick={handleAddQuestion} /> : ''}
<button className={styles.departur_button}>Отправить</button>
)}
</> </>
); );

View file

@ -38,10 +38,7 @@ const RegisterForm = () => {
const responseData = await registerUser({username, firstName, lastName, email, password}); const responseData = await registerUser({username, firstName, lastName, email, password});
if (responseData && !responseData.error) { if (responseData && !responseData.error) {
console.log('Регистрация успешна'); console.log('Регистрация успешна');
localStorage.setItem("user", JSON.stringify({ localStorage.setItem("user", JSON.stringify(responseData.user));
firstName,
lastName
}));
navigate('/my-surveys'); navigate('/my-surveys');
} }
else if (responseData.status === 409){ else if (responseData.status === 409){