diff --git a/apps/portal/prisma/migrations/20221106002645_country_ranking/migration.sql b/apps/portal/prisma/migrations/20221106002645_country_ranking/migration.sql new file mode 100644 index 00000000..c5a989d9 --- /dev/null +++ b/apps/portal/prisma/migrations/20221106002645_country_ranking/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Country" ADD COLUMN "ranking" INTEGER DEFAULT 0; diff --git a/apps/portal/prisma/schema.prisma b/apps/portal/prisma/schema.prisma index 77a8d44b..b7264b71 100644 --- a/apps/portal/prisma/schema.prisma +++ b/apps/portal/prisma/schema.prisma @@ -110,6 +110,8 @@ model Country { id String @id name String @unique code String @unique + // The higher the value of the ranking, the higher it appears in the search results. + ranking Int? @default(0) states State[] questionsQuestionEncounters QuestionsQuestionEncounter[] ResumesResume ResumesResume[] diff --git a/apps/portal/src/components/resumes/shared/ResumeLocationTypeahead.tsx b/apps/portal/src/components/resumes/shared/ResumeLocationTypeahead.tsx index cbac0a18..a5f8efe4 100644 --- a/apps/portal/src/components/resumes/shared/ResumeLocationTypeahead.tsx +++ b/apps/portal/src/components/resumes/shared/ResumeLocationTypeahead.tsx @@ -22,6 +22,7 @@ type Props = BaseProps & value?: TypeaheadOption | null; }>; +// TODO: Merge with CountriesTypeahead instead. export default function ResumeLocationTypeahead({ onSelect, selectedValues = new Set(), @@ -42,18 +43,24 @@ export default function ResumeLocationTypeahead({ return []; } - return data - .map(({ id, name }) => ({ - id, - label: name, - value: id, - })) - .filter((option) => !selectedValues.has(option.value)); - }, [countries, selectedValues]); + return ( + data + // Client-side sorting by position of query string appearing + // in the country name since we can't do that in Prisma. + .sort((a, b) => a.name.indexOf(query) - b.name.indexOf(query)) + .map(({ id, name }) => ({ + id, + label: name, + value: id, + })) + .filter((option) => !selectedValues.has(option.value)) + ); + }, [countries, query, selectedValues]); return ( ({ + options={(data ?? []) + // Client-side sorting by position of query string appearing + // in the country name since we can't do that in Prisma. + .sort( + (a, b) => + a.name.toLocaleLowerCase().indexOf(query.toLocaleLowerCase()) - + b.name.toLocaleLowerCase().indexOf(query.toLocaleLowerCase()), + ) + .map(({ id, name }) => ({ id, label: name, value: id, - })) ?? [] - } + }))} value={value} onQueryChange={setQuery} onSelect={onSelect} diff --git a/apps/portal/src/server/router/locations-router.ts b/apps/portal/src/server/router/locations-router.ts index 0db4d38f..253d75a6 100644 --- a/apps/portal/src/server/router/locations-router.ts +++ b/apps/portal/src/server/router/locations-router.ts @@ -45,14 +45,24 @@ export const locationsRouter = createRouter() async resolve({ ctx, input }) { return await ctx.prisma.country.findMany({ orderBy: { - name: 'asc', + ranking: 'desc', }, take: 10, where: { - name: { - contains: input.name, - mode: 'insensitive', - }, + OR: [ + { + name: { + contains: input.name, + mode: 'insensitive', + }, + }, + { + code: { + contains: input.name, + mode: 'insensitive', + }, + }, + ], }, }); },