[web] interviews/qns: update topics
This commit is contained in:
parent
fcbbeda777
commit
da4ed17781
|
|
@ -171,23 +171,28 @@ function getQuestionBankSectionData(
|
|||
ts: createQuestionData(language.ts),
|
||||
};
|
||||
|
||||
const topicQuestionsData: Record<
|
||||
QuestionTopic,
|
||||
{
|
||||
count: number;
|
||||
duration: number;
|
||||
questions: ReadonlyArray<QuestionMetadata>;
|
||||
}
|
||||
const topicQuestionsData: Partial<
|
||||
Record<
|
||||
QuestionTopic,
|
||||
{
|
||||
count: number;
|
||||
duration: number;
|
||||
questions: ReadonlyArray<QuestionMetadata>;
|
||||
}
|
||||
>
|
||||
> = {
|
||||
a11y: createQuestionData(topicQuestions.a11y),
|
||||
async: createQuestionData(topicQuestions.async),
|
||||
closure: createQuestionData(topicQuestions.closure),
|
||||
css: createQuestionData(topicQuestions.css),
|
||||
html: createQuestionData(topicQuestions.html),
|
||||
i18n: createQuestionData(topicQuestions.i18n),
|
||||
javascript: createQuestionData(topicQuestions.javascript),
|
||||
network: createQuestionData(topicQuestions.network),
|
||||
networking: createQuestionData(topicQuestions.networking),
|
||||
oop: createQuestionData(topicQuestions.oop),
|
||||
performance: createQuestionData(topicQuestions.performance),
|
||||
security: createQuestionData(topicQuestions.security),
|
||||
testing: createQuestionData(topicQuestions.testing),
|
||||
'web-api': createQuestionData(topicQuestions['web-api']),
|
||||
};
|
||||
|
||||
const formatQuestionsData: Record<
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import {
|
|||
} from '~/components/ui/theme';
|
||||
|
||||
import useQuestionFormatFilter from '../questions/listings/filters/hooks/useQuestionFormatFilter';
|
||||
import useQuestionTopicLabels from '../questions/listings/filters/useQuestionTopicLabels';
|
||||
|
||||
type FilterType = 'format' | 'framework' | 'topics';
|
||||
|
||||
|
|
@ -52,23 +53,43 @@ export type QuestionBankDataType = Readonly<{
|
|||
format: Record<QuestionFormat, QuestionDataType>;
|
||||
framework: Record<QuestionFramework, QuestionDataType>;
|
||||
language: Record<QuestionLanguage, QuestionDataType>;
|
||||
topic: Record<QuestionTopic, QuestionDataType>;
|
||||
topic: Partial<Record<QuestionTopic, QuestionDataType>>;
|
||||
}>;
|
||||
|
||||
type Props = Readonly<{
|
||||
questions: QuestionBankDataType;
|
||||
}>;
|
||||
|
||||
const topicRoute: Record<QuestionTopic, string> = {
|
||||
a11y: '/questions/quiz',
|
||||
const selectedTopics = [
|
||||
'a11y',
|
||||
'async',
|
||||
'css',
|
||||
'closure',
|
||||
'html',
|
||||
'i18n',
|
||||
'javascript',
|
||||
'networking',
|
||||
'oop',
|
||||
'performance',
|
||||
'security',
|
||||
'web-api',
|
||||
] as const;
|
||||
|
||||
type QuestionTopicToDisplay = (typeof selectedTopics)[number];
|
||||
|
||||
const topicHrefs: Record<QuestionTopicToDisplay, string> = {
|
||||
a11y: '/questions/user-interface',
|
||||
async: '/questions/quiz',
|
||||
closure: '/questions/closure',
|
||||
css: '/questions/css',
|
||||
html: '/questions/html',
|
||||
i18n: '/questions/quiz',
|
||||
javascript: '/questions/js',
|
||||
network: '/questions/quiz',
|
||||
javascript: '/questions/javascript',
|
||||
networking: '/questions/quiz',
|
||||
oop: '/questions/quiz',
|
||||
performance: '/questions/quiz',
|
||||
security: '/questions/quiz',
|
||||
testing: '/questions/quiz',
|
||||
'web-api': '/questions/quiz',
|
||||
};
|
||||
|
||||
const MAX_TO_SHOW = 4;
|
||||
|
|
@ -78,12 +99,13 @@ export default function InterviewsMarketingPracticeQuestionBankSection({
|
|||
}: Props) {
|
||||
const intl = useIntl();
|
||||
|
||||
const topics = useQuestionTopicLabels();
|
||||
const [selectedFilter, setSelectedFilter] = useState<FilterType>('topics');
|
||||
const [formatFilters, formatFilterOptions] = useQuestionFormatFilter({
|
||||
initialValue: ['javascript'],
|
||||
});
|
||||
const [topicFilters, topicFilterOptions] = useQuestionTopicFilter({
|
||||
initialValue: ['javascript'],
|
||||
initialValue: ['a11y'],
|
||||
});
|
||||
const [languageFilters, languageFilterOptions] = useQuestionLanguageFilter({
|
||||
initialValue: ['html'],
|
||||
|
|
@ -154,7 +176,10 @@ export default function InterviewsMarketingPracticeQuestionBankSection({
|
|||
value: selectedFramework || selectedLanguage,
|
||||
},
|
||||
topics: {
|
||||
items: topicFilterOptions.options,
|
||||
items: selectedTopics.map((topic) => ({
|
||||
label: topics[topic].label,
|
||||
value: topic,
|
||||
})),
|
||||
onClick: (value: string) =>
|
||||
topicFilterOptions.setValues(new Set([value]) as Set<QuestionTopic>),
|
||||
value: selectedTopic,
|
||||
|
|
@ -171,7 +196,9 @@ export default function InterviewsMarketingPracticeQuestionBankSection({
|
|||
const selectedRoute = (() => {
|
||||
switch (selectedFilter) {
|
||||
case 'topics': {
|
||||
return topicRoute[selectedTopic];
|
||||
return (
|
||||
topicHrefs[selectedTopic as QuestionTopicToDisplay] ?? '/questions'
|
||||
);
|
||||
}
|
||||
case 'framework': {
|
||||
return (
|
||||
|
|
@ -193,7 +220,7 @@ export default function InterviewsMarketingPracticeQuestionBankSection({
|
|||
return framework[selectedFramework] || language[selectedLanguage];
|
||||
}
|
||||
case 'topics': {
|
||||
return topic[selectedTopic];
|
||||
return topic[selectedTopic] ?? { count: 0, duration: 0, questions: [] };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,14 +161,22 @@ export type QuestionMetadataWithCompletedStatus = QuestionMetadata & {
|
|||
|
||||
export type QuestionTopic =
|
||||
| 'a11y'
|
||||
| 'async'
|
||||
| 'browser'
|
||||
| 'closure'
|
||||
| 'css'
|
||||
| 'graph'
|
||||
| 'html'
|
||||
| 'i18n'
|
||||
| 'javascript'
|
||||
| 'network'
|
||||
| 'networking'
|
||||
| 'oop'
|
||||
| 'performance'
|
||||
| 'recursion'
|
||||
| 'security'
|
||||
| 'testing';
|
||||
| 'testing'
|
||||
| 'tree'
|
||||
| 'web-api';
|
||||
|
||||
export type QuestionQuiz = QuestionBase;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,14 +14,22 @@ import type { QuestionFilter } from '../QuestionFilterType';
|
|||
// The lower the earlier it appears.
|
||||
const topicRanks: Record<QuestionTopic, number> = {
|
||||
a11y: 3,
|
||||
async: 0,
|
||||
browser: 0,
|
||||
closure: 0,
|
||||
css: 1,
|
||||
graph: 0,
|
||||
html: 2,
|
||||
i18n: 40,
|
||||
javascript: 0,
|
||||
network: 60,
|
||||
networking: 60,
|
||||
oop: 0,
|
||||
performance: 50,
|
||||
recursion: 0,
|
||||
security: 80,
|
||||
testing: 99,
|
||||
tree: 0,
|
||||
'web-api': 0,
|
||||
};
|
||||
|
||||
type Props = Readonly<{
|
||||
|
|
@ -77,7 +85,6 @@ export default function useQuestionTopicFilter(
|
|||
topicRanks[a as QuestionTopic] - topicRanks[b as QuestionTopic],
|
||||
)
|
||||
.map((topic) => ({
|
||||
icon: topicLabels[topic as QuestionTopic].icon,
|
||||
label: topicLabels[topic as QuestionTopic].label,
|
||||
value: topic as QuestionTopic,
|
||||
})),
|
||||
|
|
|
|||
|
|
@ -1,15 +1,3 @@
|
|||
import { BiUniversalAccess } from 'react-icons/bi';
|
||||
import {
|
||||
RiCss3Fill,
|
||||
RiDashboard2Line,
|
||||
RiHtml5Fill,
|
||||
RiJavascriptFill,
|
||||
RiLock2Line,
|
||||
RiTestTubeLine,
|
||||
RiTranslate2,
|
||||
RiWifiLine,
|
||||
} from 'react-icons/ri';
|
||||
|
||||
import { useIntl } from '~/components/intl';
|
||||
|
||||
import type { QuestionTopic } from '../../common/QuestionsTypes';
|
||||
|
|
@ -20,80 +8,114 @@ export default function useQuestionTopicLabels() {
|
|||
const topicTitles: Record<
|
||||
QuestionTopic,
|
||||
Readonly<{
|
||||
icon: (props: React.ComponentProps<'svg'>) => JSX.Element;
|
||||
label: string;
|
||||
}>
|
||||
> = {
|
||||
a11y: {
|
||||
icon: BiUniversalAccess,
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: 'Accessibility',
|
||||
description: 'Accessibility topic for quiz questions',
|
||||
id: 'q0+3Lk',
|
||||
description: 'Front end development topic',
|
||||
id: 'TbZTWa',
|
||||
}),
|
||||
},
|
||||
async: {
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: 'Async',
|
||||
description: 'Front end development topic',
|
||||
id: 'ezEYel',
|
||||
}),
|
||||
},
|
||||
browser: {
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: 'Browser',
|
||||
description: 'Front end development topic',
|
||||
id: '+4J3PK',
|
||||
}),
|
||||
},
|
||||
closure: {
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: 'Closure',
|
||||
description: 'Front end development topic',
|
||||
id: 'MMLnqG',
|
||||
}),
|
||||
},
|
||||
css: {
|
||||
icon: RiCss3Fill,
|
||||
label: 'CSS',
|
||||
},
|
||||
graph: {
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: 'CSS',
|
||||
description: 'CSS topic for quiz questions',
|
||||
id: 'P4Or/u',
|
||||
defaultMessage: 'Graph',
|
||||
description: 'Front end development topic',
|
||||
id: 'F8ULPJ',
|
||||
}),
|
||||
},
|
||||
html: {
|
||||
icon: RiHtml5Fill,
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: 'HTML',
|
||||
description: 'HTML topic for quiz questions',
|
||||
id: 'Yb2e9Q',
|
||||
}),
|
||||
label: 'HTML',
|
||||
},
|
||||
i18n: {
|
||||
icon: RiTranslate2,
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: 'Internationalization',
|
||||
description: 'Internationalization topic for quiz questions',
|
||||
id: 'tonRki',
|
||||
description: 'Front end development topic',
|
||||
id: 'Oykw81',
|
||||
}),
|
||||
},
|
||||
javascript: {
|
||||
icon: RiJavascriptFill,
|
||||
label: 'JavaScript',
|
||||
},
|
||||
networking: {
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: 'JavaScript',
|
||||
description: 'JavaScript topic for quiz questions',
|
||||
id: 'w22UH7',
|
||||
defaultMessage: 'Networking',
|
||||
description: 'Front end development topic',
|
||||
id: 'ZutazH',
|
||||
}),
|
||||
},
|
||||
network: {
|
||||
icon: RiWifiLine,
|
||||
oop: {
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: 'Network',
|
||||
description: 'Network topic for quiz questions',
|
||||
id: 'pM/ZPq',
|
||||
defaultMessage: 'Object-oriented programming',
|
||||
description: 'Front end development topic',
|
||||
id: 'KLoXYT',
|
||||
}),
|
||||
},
|
||||
performance: {
|
||||
icon: RiDashboard2Line,
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: 'Performance',
|
||||
description: 'Performance topic for quiz questions',
|
||||
id: 'kwblYW',
|
||||
description: 'Front end development topic',
|
||||
id: 'd1LTa+',
|
||||
}),
|
||||
},
|
||||
recursion: {
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: 'Recursion',
|
||||
description: 'Front end development topic',
|
||||
id: 'trRb9Z',
|
||||
}),
|
||||
},
|
||||
security: {
|
||||
icon: RiLock2Line,
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: 'Security',
|
||||
description: 'Security topic for quiz questions',
|
||||
id: 'kvLlxS',
|
||||
description: 'Front end development topic',
|
||||
id: '4MzF6x',
|
||||
}),
|
||||
},
|
||||
testing: {
|
||||
icon: RiTestTubeLine,
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: 'Testing',
|
||||
description: 'Testing topic for quiz questions',
|
||||
id: 'l9OWsu',
|
||||
description: 'Front end development topic',
|
||||
id: 'QwoKre',
|
||||
}),
|
||||
},
|
||||
tree: {
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: 'Tree',
|
||||
description: 'Front end development topic',
|
||||
id: 'Rs1Xi9',
|
||||
}),
|
||||
},
|
||||
'web-api': {
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: 'Web APIs',
|
||||
description: 'Front end development topic',
|
||||
id: 'a1RZkG',
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,16 +8,24 @@ import useQuestionTopicLabels from '../listings/filters/useQuestionTopicLabels';
|
|||
|
||||
const TopicLabelClasses: Record<QuestionTopic, string> = {
|
||||
a11y: 'bg-pink-500 text-white dark:bg-neutral-800 dark:text-pink-500',
|
||||
async: '',
|
||||
browser: '',
|
||||
closure: '',
|
||||
css: 'bg-sky-500 text-white dark:bg-neutral-800 dark:text-sky-500',
|
||||
graph: '',
|
||||
html: 'bg-orange-600 text-white dark:bg-neutral-800 dark:text-orange-600',
|
||||
i18n: 'bg-neutral-700 text-white dark:bg-neutral-800 dark:text-neutral-300',
|
||||
javascript:
|
||||
'bg-yellow-500 text-black dark:bg-neutral-800 dark:text-yellow-500',
|
||||
network: 'bg-teal-400 text-white dark:bg-neutral-800 dark:text-teal-400',
|
||||
networking: 'bg-teal-400 text-white dark:bg-neutral-800 dark:text-teal-400',
|
||||
oop: '',
|
||||
performance:
|
||||
'bg-indigo-500 text-white dark:bg-neutral-800 dark:text-indigo-400',
|
||||
recursion: '',
|
||||
security: 'bg-red text-white dark:bg-neutral-800 dark:text-red',
|
||||
testing: 'bg-green-dark text-white dark:bg-neutral-800 dark:text-green',
|
||||
tree: '',
|
||||
'web-api': '',
|
||||
};
|
||||
|
||||
export default function QuestionTopicLabel({
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ export function useQuestionFormatsData(): QuestionFormatData {
|
|||
'a11y',
|
||||
'i18n',
|
||||
'css',
|
||||
'network',
|
||||
'networking',
|
||||
'security',
|
||||
'testing',
|
||||
],
|
||||
|
|
|
|||
|
|
@ -408,54 +408,37 @@ export function categorizeQuestionsByTopic(
|
|||
quizQuestions: ReadonlyArray<QuestionMetadata>;
|
||||
}>,
|
||||
): Record<QuestionTopic, ReadonlyArray<QuestionMetadata>> {
|
||||
const categorizedQuestions: Record<
|
||||
QuestionTopic,
|
||||
ReadonlyArray<QuestionMetadata>
|
||||
> = {
|
||||
const categorizedQuestions: Record<QuestionTopic, Array<QuestionMetadata>> = {
|
||||
a11y: [],
|
||||
async: [],
|
||||
browser: [],
|
||||
closure: [],
|
||||
css: [],
|
||||
graph: [],
|
||||
html: [],
|
||||
i18n: [],
|
||||
javascript: [],
|
||||
network: [],
|
||||
networking: [],
|
||||
oop: [],
|
||||
performance: [],
|
||||
recursion: [],
|
||||
security: [],
|
||||
testing: [],
|
||||
tree: [],
|
||||
'web-api': [],
|
||||
};
|
||||
const { codingQuestions, quizQuestions } = questions;
|
||||
const LANGUAGE_TO_TOPIC: Record<string, QuestionTopic> = {
|
||||
css: 'css',
|
||||
html: 'html',
|
||||
js: 'javascript',
|
||||
};
|
||||
|
||||
function categorize(question: QuestionMetadata, type: 'coding' | 'quiz') {
|
||||
if (type === 'coding') {
|
||||
question.languages.forEach((language) => {
|
||||
const topic = LANGUAGE_TO_TOPIC[language];
|
||||
|
||||
if (topic) {
|
||||
categorizedQuestions[topic] = [
|
||||
...categorizedQuestions[topic],
|
||||
question,
|
||||
];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
question.topics.forEach((topic) => {
|
||||
if (categorizedQuestions[topic]) {
|
||||
categorizedQuestions[topic] = [
|
||||
...categorizedQuestions[topic],
|
||||
question,
|
||||
];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Process all coding and quiz questions in a single pass
|
||||
codingQuestions.forEach((question) => categorize(question, 'coding'));
|
||||
quizQuestions.forEach((question) => categorize(question, 'quiz'));
|
||||
codingQuestions.forEach((question) => {
|
||||
question.topics.forEach((topic) => {
|
||||
categorizedQuestions[topic].push(question);
|
||||
});
|
||||
});
|
||||
quizQuestions.forEach((question) => {
|
||||
question.topics.forEach((topic) => {
|
||||
categorizedQuestions[topic].push(question);
|
||||
});
|
||||
});
|
||||
|
||||
return categorizedQuestions;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue