78 lines
3.0 KiB
TypeScript
78 lines
3.0 KiB
TypeScript
|
|
import { useParams } from 'react-router-dom';
|
|||
|
|
import { useData, useDataPage } from '../API/common';
|
|||
|
|
import { Institution, Profession, Specialty } from '../types/survey';
|
|||
|
|
import ReactMarkdown from 'react-markdown';
|
|||
|
|
import { LoadingData } from '../components/LoadingData';
|
|||
|
|
import { useEffect, useMemo, useState } from 'react';
|
|||
|
|
import { LoadingList } from '../components/LoadingList';
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
export function ProfessionPage() {
|
|||
|
|
const { professionId } = useParams<{ professionId: string }>();
|
|||
|
|
const profession = useData<Profession>('surveys', 'professions', professionId || 0);
|
|||
|
|
const specialties = useDataPage<Specialty>('surveys', 'specialties', { profession: professionId || 0 }, !!profession);
|
|||
|
|
|
|||
|
|
const [institutionCache, setInstitutionCache] = useState<Map<number, Institution>>(new Map()); // Кеширование учебных заведений
|
|||
|
|
const institutionsToLoad = useMemo(() => {
|
|||
|
|
if (!specialties.items) return [];
|
|||
|
|
return specialties.items
|
|||
|
|
.map(specialty => specialty.institution)
|
|||
|
|
.filter(id => !institutionCache.has(id));
|
|||
|
|
}, [specialties.items, institutionCache]);
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
if (institutionsToLoad.length > 0) {
|
|||
|
|
Promise.all(
|
|||
|
|
institutionsToLoad.map(id =>
|
|||
|
|
useData<Institution>('surveys', 'institutions', id, true)
|
|||
|
|
)
|
|||
|
|
).then(newInstitutions => {
|
|||
|
|
setInstitutionCache(prev => {
|
|||
|
|
const newCache = new Map(prev);
|
|||
|
|
newInstitutions.forEach(institution => institution && newCache.set(institution.id, institution));
|
|||
|
|
return newCache;
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}, [institutionsToLoad]);
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div>
|
|||
|
|
<LoadingData data={profession}>
|
|||
|
|
<h1>{profession?.name}</h1>
|
|||
|
|
<div className="description">
|
|||
|
|
<ReactMarkdown>{profession?.description || ''}</ReactMarkdown>
|
|||
|
|
</div>
|
|||
|
|
<div className="specialties-block">
|
|||
|
|
<h2>Где можно обучиться</h2>
|
|||
|
|
<LoadingList
|
|||
|
|
data={specialties.items}
|
|||
|
|
listElement={(specialty) => (
|
|||
|
|
<SpecialtyBlock
|
|||
|
|
key={specialty.id}
|
|||
|
|
specialty={specialty as Specialty}
|
|||
|
|
institution={institutionCache.get((specialty as Specialty).institution)}
|
|||
|
|
/>
|
|||
|
|
)}
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
</LoadingData>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function SpecialtyBlock({
|
|||
|
|
specialty,
|
|||
|
|
institution,
|
|||
|
|
}: {
|
|||
|
|
specialty: Specialty;
|
|||
|
|
institution: Institution | undefined;
|
|||
|
|
}) {
|
|||
|
|
return (
|
|||
|
|
<div className="specialty-block">
|
|||
|
|
<h3>{specialty.name}</h3>
|
|||
|
|
<p>Учебное заведение: {institution?.name || 'Загрузка...'}</p>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|