mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2025-07-14 09:57:56 +08:00
[questions][fix] fix landing page location params (#482)
This commit is contained in:
@ -1,10 +1,12 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { ArrowSmallRightIcon } from '@heroicons/react/24/outline';
|
import { ArrowSmallRightIcon } from '@heroicons/react/24/outline';
|
||||||
import type { QuestionsQuestionType } from '@prisma/client';
|
import type { QuestionsQuestionType } from '@prisma/client';
|
||||||
|
import type { TypeaheadOption } from '@tih/ui';
|
||||||
import { Button, Select } from '@tih/ui';
|
import { Button, Select } from '@tih/ui';
|
||||||
|
|
||||||
import { companyOptionToSlug } from '~/utils/questions/companySlug';
|
import { companyOptionToSlug } from '~/utils/questions/companySlug';
|
||||||
import { QUESTION_TYPES } from '~/utils/questions/constants';
|
import { QUESTION_TYPES } from '~/utils/questions/constants';
|
||||||
|
import { locationOptionToSlug } from '~/utils/questions/locationSlug';
|
||||||
import useDefaultCompany from '~/utils/questions/useDefaultCompany';
|
import useDefaultCompany from '~/utils/questions/useDefaultCompany';
|
||||||
import useDefaultLocation from '~/utils/questions/useDefaultLocation';
|
import useDefaultLocation from '~/utils/questions/useDefaultLocation';
|
||||||
|
|
||||||
@ -12,6 +14,8 @@ import type { FilterChoice } from './filter/FilterSection';
|
|||||||
import CompanyTypeahead from './typeahead/CompanyTypeahead';
|
import CompanyTypeahead from './typeahead/CompanyTypeahead';
|
||||||
import LocationTypeahead from './typeahead/LocationTypeahead';
|
import LocationTypeahead from './typeahead/LocationTypeahead';
|
||||||
|
|
||||||
|
import type { Location } from '~/types/questions';
|
||||||
|
|
||||||
export type LandingQueryData = {
|
export type LandingQueryData = {
|
||||||
companySlug: string;
|
companySlug: string;
|
||||||
location: string;
|
location: string;
|
||||||
@ -31,9 +35,9 @@ export default function LandingComponent({
|
|||||||
const [company, setCompany] = useState<FilterChoice | undefined>(
|
const [company, setCompany] = useState<FilterChoice | undefined>(
|
||||||
defaultCompany,
|
defaultCompany,
|
||||||
);
|
);
|
||||||
const [location, setLocation] = useState<FilterChoice | undefined>(
|
const [location, setLocation] = useState<
|
||||||
defaultLocation,
|
(Location & TypeaheadOption) | undefined
|
||||||
);
|
>(defaultLocation);
|
||||||
|
|
||||||
const [questionType, setQuestionType] =
|
const [questionType, setQuestionType] =
|
||||||
useState<QuestionsQuestionType>('CODING');
|
useState<QuestionsQuestionType>('CODING');
|
||||||
@ -42,7 +46,7 @@ export default function LandingComponent({
|
|||||||
setCompany(newCompany);
|
setCompany(newCompany);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleChangeLocation = (newLocation: FilterChoice) => {
|
const handleChangeLocation = (newLocation: Location & TypeaheadOption) => {
|
||||||
setLocation(newLocation);
|
setLocation(newLocation);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -126,7 +130,7 @@ export default function LandingComponent({
|
|||||||
if (company !== undefined && location !== undefined) {
|
if (company !== undefined && location !== undefined) {
|
||||||
return handleLandingQuery({
|
return handleLandingQuery({
|
||||||
companySlug: companyOptionToSlug(company),
|
companySlug: companyOptionToSlug(company),
|
||||||
location: location.value,
|
location: locationOptionToSlug(location),
|
||||||
questionType,
|
questionType,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,11 @@ import LocationTypeahead from '~/components/questions/typeahead/LocationTypeahea
|
|||||||
import RoleTypeahead from '~/components/questions/typeahead/RoleTypeahead';
|
import RoleTypeahead from '~/components/questions/typeahead/RoleTypeahead';
|
||||||
import { JobTitleLabels } from '~/components/shared/JobTitles';
|
import { JobTitleLabels } from '~/components/shared/JobTitles';
|
||||||
|
|
||||||
import {
|
|
||||||
companyOptionToSlug,
|
|
||||||
slugToCompanyOption,
|
|
||||||
} from '~/utils/questions/companySlug';
|
|
||||||
import type { QuestionAge } from '~/utils/questions/constants';
|
import type { QuestionAge } from '~/utils/questions/constants';
|
||||||
import { APP_TITLE } from '~/utils/questions/constants';
|
import { APP_TITLE } from '~/utils/questions/constants';
|
||||||
import { QUESTION_AGES, QUESTION_TYPES } from '~/utils/questions/constants';
|
import { QUESTION_AGES, QUESTION_TYPES } from '~/utils/questions/constants';
|
||||||
import createSlug from '~/utils/questions/createSlug';
|
import createSlug from '~/utils/questions/createSlug';
|
||||||
|
import { locationOptionToSlug } from '~/utils/questions/locationSlug';
|
||||||
import relabelQuestionAggregates from '~/utils/questions/relabelQuestionAggregates';
|
import relabelQuestionAggregates from '~/utils/questions/relabelQuestionAggregates';
|
||||||
import {
|
import {
|
||||||
useSearchParam,
|
useSearchParam,
|
||||||
@ -37,17 +34,6 @@ import type { Location } from '~/types/questions.d';
|
|||||||
import { SortType } from '~/types/questions.d';
|
import { SortType } from '~/types/questions.d';
|
||||||
import { SortOrder } from '~/types/questions.d';
|
import { SortOrder } from '~/types/questions.d';
|
||||||
|
|
||||||
function locationToSlug(value: Location & TypeaheadOption): string {
|
|
||||||
return [
|
|
||||||
value.countryId,
|
|
||||||
value.stateId,
|
|
||||||
value.cityId,
|
|
||||||
value.id,
|
|
||||||
value.label,
|
|
||||||
value.value,
|
|
||||||
].join('-');
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function QuestionsBrowsePage() {
|
export default function QuestionsBrowsePage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
@ -90,7 +76,7 @@ export default function QuestionsBrowsePage() {
|
|||||||
useSearchParam('roles');
|
useSearchParam('roles');
|
||||||
const [selectedLocations, setSelectedLocations, areLocationsInitialized] =
|
const [selectedLocations, setSelectedLocations, areLocationsInitialized] =
|
||||||
useSearchParam<Location & TypeaheadOption>('locations', {
|
useSearchParam<Location & TypeaheadOption>('locations', {
|
||||||
paramToString: locationToSlug,
|
paramToString: locationOptionToSlug,
|
||||||
stringToParam: (param) => {
|
stringToParam: (param) => {
|
||||||
const [countryId, stateId, cityId, id, label, value] = param.split('-');
|
const [countryId, stateId, cityId, id, label, value] = param.split('-');
|
||||||
return { cityId, countryId, id, label, stateId, value };
|
return { cityId, countryId, id, label, stateId, value };
|
||||||
@ -267,7 +253,7 @@ export default function QuestionsBrowsePage() {
|
|||||||
pathname,
|
pathname,
|
||||||
query: {
|
query: {
|
||||||
companies: selectedCompanySlugs,
|
companies: selectedCompanySlugs,
|
||||||
locations: selectedLocations.map(locationToSlug),
|
locations: selectedLocations.map(locationOptionToSlug),
|
||||||
questionAge: selectedQuestionAge,
|
questionAge: selectedQuestionAge,
|
||||||
questionTypes: selectedQuestionTypes,
|
questionTypes: selectedQuestionTypes,
|
||||||
roles: selectedRoles,
|
roles: selectedRoles,
|
||||||
@ -292,7 +278,15 @@ export default function QuestionsBrowsePage() {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const selectedCompanyOptions = useMemo(() => {
|
const selectedCompanyOptions = useMemo(() => {
|
||||||
return selectedCompanySlugs.map(slugToCompanyOption);
|
return selectedCompanySlugs.map((company) => {
|
||||||
|
const [id, label] = company.split('_');
|
||||||
|
return {
|
||||||
|
checked: true,
|
||||||
|
id,
|
||||||
|
label,
|
||||||
|
value: id,
|
||||||
|
};
|
||||||
|
});
|
||||||
}, [selectedCompanySlugs]);
|
}, [selectedCompanySlugs]);
|
||||||
|
|
||||||
const selectedRoleOptions = useMemo(() => {
|
const selectedRoleOptions = useMemo(() => {
|
||||||
@ -359,12 +353,12 @@ export default function QuestionsBrowsePage() {
|
|||||||
if (option.checked) {
|
if (option.checked) {
|
||||||
setSelectedCompanySlugs([
|
setSelectedCompanySlugs([
|
||||||
...selectedCompanySlugs,
|
...selectedCompanySlugs,
|
||||||
companyOptionToSlug(option),
|
`${option.id}_${option.label}`,
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
setSelectedCompanySlugs(
|
setSelectedCompanySlugs(
|
||||||
selectedCompanySlugs.filter(
|
selectedCompanySlugs.filter(
|
||||||
(companySlug) => companySlug !== companyOptionToSlug(option),
|
(companySlug) => companySlug !== `${option.id}_${option.label}`,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ export const questionsQuestionRouter = createRouter()
|
|||||||
input: z.object({
|
input: z.object({
|
||||||
cityIds: z.string().array(),
|
cityIds: z.string().array(),
|
||||||
companyIds: z.string().array(),
|
companyIds: z.string().array(),
|
||||||
|
content: z.string().optional(),
|
||||||
countryIds: z.string().array(),
|
countryIds: z.string().array(),
|
||||||
cursor: z.string().nullish(),
|
cursor: z.string().nullish(),
|
||||||
endDate: z.date().default(new Date()),
|
endDate: z.date().default(new Date()),
|
||||||
|
16
apps/portal/src/utils/questions/locationSlug.ts
Normal file
16
apps/portal/src/utils/questions/locationSlug.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import type { TypeaheadOption } from '@tih/ui';
|
||||||
|
|
||||||
|
import type { Location } from '~/types/questions';
|
||||||
|
|
||||||
|
export function locationOptionToSlug(
|
||||||
|
value: Location & TypeaheadOption,
|
||||||
|
): string {
|
||||||
|
return [
|
||||||
|
value.countryId,
|
||||||
|
value.stateId,
|
||||||
|
value.cityId,
|
||||||
|
value.id,
|
||||||
|
value.label,
|
||||||
|
value.value,
|
||||||
|
].join('-');
|
||||||
|
}
|
Reference in New Issue
Block a user