add result page

This commit is contained in:
MikanD
2025-06-01 00:52:20 +03:00
parent 48ec88df74
commit 4a5b0a9532
8 changed files with 1146 additions and 24 deletions

1107
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -13,6 +13,7 @@
"dependencies": { "dependencies": {
"react": "^19.1.0", "react": "^19.1.0",
"react-dom": "^19.1.0", "react-dom": "^19.1.0",
"react-markdown": "^10.1.0",
"react-router-dom": "^7.6.0" "react-router-dom": "^7.6.0"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -57,7 +57,7 @@ const createQueryString = (params: Record<string, string | number | boolean | un
return filteredParams.join('&'); return filteredParams.join('&');
}; };
export function useDataPage<T>(application:string, endpoint: string, params:{[key:string]:string|number}={}) { export function useDataPage<T>(application:string, endpoint: string, params:{[key:string]:string|number}={}, needLoad:boolean=true):PageControl<T> {
const [data, setData] = useState<T[]|null>(null); const [data, setData] = useState<T[]|null>(null);
// const [previousUrl, setPreviousUrl] = useState<string|undefined>(undefined) // const [previousUrl, setPreviousUrl] = useState<string|undefined>(undefined)
// const [nextUrl, setNextUrl] = useState<string|undefined>(undefined) // const [nextUrl, setNextUrl] = useState<string|undefined>(undefined)
@@ -67,7 +67,7 @@ export function useDataPage<T>(application:string, endpoint: string, params:{[ke
useEffect( useEffect(
()=>{ ()=>{
if (data === null){ if (data === null && needLoad){
getFetch(`/${application}/${endpoint}/?${createQueryString(params)}`).then((r)=>{ getFetch(`/${application}/${endpoint}/?${createQueryString(params)}`).then((r)=>{
if (r.success){ if (r.success){
const pageData = r.body as PageResponse<T>; const pageData = r.body as PageResponse<T>;
@@ -110,8 +110,8 @@ export function useDataPage<T>(application:string, endpoint: string, params:{[ke
return { return {
items: data, items: data,
hasPrevious: undefined,//previousUrl !== undefined, hasPrevious: false,//previousUrl !== undefined,
hasNext: undefined,//nextUrl !== undefined, hasNext: false,//nextUrl !== undefined,
nextPage, nextPage,
previousPage previousPage
} as PageControl<T> } as PageControl<T>
@@ -119,25 +119,25 @@ export function useDataPage<T>(application:string, endpoint: string, params:{[ke
} }
export function useData<T>(application:string, endpoint: string, id: string|number) { export function useData<T>(application:string, endpoint: string, id: string|number, needLoad:boolean=true): T|null|undefined {
const [data, setData] = useState<T | null | undefined>(null); const [data, setData] = useState<T | null | undefined>(null);
useEffect( useEffect(
()=>{ ()=>{
if (data === null){ if (data === null && needLoad){
getFetch(`/${application}/${endpoint}/${id}`).then((r)=>{ getFetch(`/${application}/${endpoint}/${id}`).then((r)=>{
if (r.success){ if (r.success){
const pageData = r.body as T; const pageData = r.body as T;
setData(pageData); setData(pageData);
} }
else { else {
setData(null); setData(undefined);
} }
}) })
} }
}, },
[data, application, endpoint, id] [data, application, endpoint, id, needLoad]
) )
return data; return data;

View File

@@ -1 +0,0 @@

View File

@@ -1,9 +1,9 @@
// App.tsx // App.tsx
import {BrowserRouter as Router, Routes, Route, Navigate, Link} from 'react-router-dom'; import {BrowserRouter as Router, Routes, Route, Navigate, Link} from 'react-router-dom';
import React from "react";
import {MainPage} from "./pages/MainPage.tsx"; import {MainPage} from "./pages/MainPage.tsx";
import {SurveyPage} from "./pages/SurveyPage.tsx"; import {SurveyPage} from "./pages/SurveyPage.tsx";
import {DashboardPage} from "./pages/DashboardPage.tsx"; import {DashboardPage} from "./pages/DashboardPage.tsx";
import { SurveyResultPage } from './pages/SurveyResultPage.tsx';
@@ -16,6 +16,7 @@ export default function App() {
</div> </div>
<Routes> <Routes>
<Route path="/" element={<MainPage/>}/> <Route path="/" element={<MainPage/>}/>
<Route path="/surveys/results/:scoreVariableId/" element={<SurveyResultPage/>}/>
<Route path="/surveys/:surveyId/" element={<SurveyPage/>}/> <Route path="/surveys/:surveyId/" element={<SurveyPage/>}/>
<Route path="/dashboard/" element={<DashboardPage/>}/> <Route path="/dashboard/" element={<DashboardPage/>}/>
<Route path="*" element={<Navigate to="/"/>}/> <Route path="*" element={<Navigate to="/"/>}/>

View File

@@ -132,11 +132,11 @@ function QuestionBlock({
<div className={`question agreement ${answered !== undefined ? "answered" : "unanswered"}`}> <div className={`question agreement ${answered !== undefined ? "answered" : "unanswered"}`}>
{agreementQuestion.question} {agreementQuestion.question}
<button <button
className={answered === 1 ? "selected" : ""} className={`answer ${answered === 1 ? "selected" : "idle"}`}
disabled={answered===1} disabled={answered===1}
onClick={() => onAnswer(`${question.questionType}_${question.id}`, 1)}>Согласен</button> onClick={() => onAnswer(`${question.questionType}_${question.id}`, 1)}>Согласен</button>
<button <button
className={answered === 0 ? "selected" : ""} className={`answer ${answered === 0 ? "selected" : "idle"}`}
disabled={answered === 0} disabled={answered === 0}
onClick={() => onAnswer(`${question.questionType}_${question.id}`, 0)}>Не согласен</button> onClick={() => onAnswer(`${question.questionType}_${question.id}`, 0)}>Не согласен</button>
@@ -149,7 +149,7 @@ function QuestionBlock({
<div className={`question pair ${answered !== undefined ? "answered" : "unanswered"}`}> <div className={`question pair ${answered !== undefined ? "answered" : "unanswered"}`}>
{pairQuestion.statements.map((statement) => ( {pairQuestion.statements.map((statement) => (
<button <button
className={answered === statement.id ? "selected" : ""} className={`answer ${answered === statement.id ? "selected" : "idle"}`}
disabled={answered === statement.id} disabled={answered === statement.id}
key={statement.id} key={statement.id}
onClick={() => onAnswer(`${question.questionType}_${question.id}`, statement.id)} onClick={() => onAnswer(`${question.questionType}_${question.id}`, statement.id)}

View File

@@ -0,0 +1,31 @@
import { useParams } from 'react-router-dom';
import { useData } from '../API/common';
import { ScoreVariable, Survey } from '../types/survey';
import ReactMarkdown from 'react-markdown';
import { LoadingData } from '../components/LoadingData';
export function SurveyResultPage() {
const { scoreVariableId } = useParams<{ scoreVariableId: string }>();
const scoreVariable = useData<ScoreVariable>('surveys', 'score-variables', scoreVariableId || 0);
const survey = useData<Survey>('surveys', 'surveys', scoreVariable?.survey || 0, !!scoreVariable);
return (
<div>
<LoadingData data={survey && scoreVariable?null:scoreVariable}>
<h1>{survey?.title}</h1>
<div className={"result"}>
<h2>Ваш результат</h2>
<p>{scoreVariable?.title}</p>
</div>
<div className={"description"}>
<ReactMarkdown>{scoreVariable?.description}</ReactMarkdown>
</div>
<div>
<h3>Подходящие профессии</h3>
<p>Здесь будет список профессий.</p>
</div>
</LoadingData>
</div>
);
}

View File

@@ -17,8 +17,7 @@ export enum QuestionType{
} }
export interface Question extends UniqueItem{ export interface Question extends UniqueItem{
questionType: QuestionType, questionType: QuestionType
answer?: number;
} }
@@ -39,5 +38,5 @@ export interface ScoreVariable {
name: string; name: string;
title: string; title: string;
description: string; description: string;
survey: string; survey: number;
} }