Skip to content

Commit 98838e7

Browse files
committed
changed location combobox
1 parent 10df1ef commit 98838e7

File tree

2 files changed

+63
-33
lines changed

2 files changed

+63
-33
lines changed

apps/web/src/app/_components/combo-box.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ interface ComboBoxProps {
2727
onSelect: (option: string) => void;
2828
triggerClassName?: string;
2929
onChange?: (value: string) => void;
30-
variant?: "default" | "form";
30+
variant?: "default" | "form" | "filtering";
3131
}
3232

3333
/**
@@ -51,15 +51,18 @@ export default function ComboBox({
5151
const styleVariant =
5252
variant === "form"
5353
? "flex h-16 w-full rounded-md border-[3px] border-cooper-blue-600 bg-white px-3 py-2 text-xl font-normal ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
54-
: "";
54+
: variant === "filtering"
55+
? "w-[340px] h-12 rounded-none border-2 border-l-0 border-t-0 border-[#9A9A9A] text-lg placeholder:opacity-50 focus:ring-0 active:ring-0 lg:rounded-md lg:border-2 py-0"
56+
: "h-8 py-0";
5557

5658
return (
5759
<Popover open={isOpen} onOpenChange={setIsOpen}>
5860
<PopoverTrigger
5961
asChild
6062
className={cn(
61-
"w-[400px] overflow-hidden file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
63+
"overflow-hidden file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
6264
triggerClassName,
65+
variant !== "filtering" ? "w-[400px]" : "",
6366
)}
6467
>
6568
<Button
@@ -68,7 +71,8 @@ export default function ComboBox({
6871
aria-expanded={isOpen}
6972
className={cn(
7073
styleVariant,
71-
"w-[400px] justify-between overflow-hidden text-ellipsis text-nowrap",
74+
"justify-between overflow-hidden text-ellipsis text-nowrap h-12 py-0 min-h-0",
75+
variant !== "filtering" ? "w-[400px]" : "",
7276
)}
7377
>
7478
<span className="overflow-hidden text-ellipsis whitespace-nowrap">

apps/web/src/app/_components/search/company-search-bar.tsx

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { useState } from "react";
1+
import { useEffect, useState } from "react";
22
import { useFormContext } from "react-hook-form";
33

44
import { Button } from "@cooper/ui/button";
5-
import { FormControl, FormField, FormItem } from "@cooper/ui/form";
5+
import { FormControl, FormField, FormItem, FormLabel } from "@cooper/ui/form";
66
import { useCallback } from "react";
77
import {
88
Select,
@@ -18,6 +18,7 @@ import type { IndustryType, LocationType } from "@cooper/db/schema";
1818
import { api } from "~/trpc/react";
1919
import { usePathname, useRouter } from "next/navigation";
2020
import { z } from "zod";
21+
import ComboBox from "../combo-box";
2122

2223
interface SearchBarProps {
2324
industry?: IndustryType;
@@ -39,10 +40,37 @@ export function CompanySearchBar({ industry, location }: SearchBarProps) {
3940
const [selectedIndustry, setSelectedIndustry] = useState<string | undefined>(
4041
industry,
4142
);
42-
const [selectedLocation, setSelectedLocation] = useState<string | undefined>(
43-
location?.city,
43+
44+
const [locationLabel, setLocationLabel] = useState<string>(
45+
location ? `${location.city}, ${location.state}` : "Location",
46+
);
47+
const [searchTerm, setSearchTerm] = useState<string>("");
48+
const [prefix, setPrefix] = useState<string>("");
49+
50+
useEffect(() => {
51+
const newPrefix =
52+
searchTerm.length === 3 ? searchTerm.slice(0, 3).toLowerCase() : null;
53+
if (newPrefix && newPrefix !== prefix) {
54+
setPrefix(newPrefix);
55+
}
56+
}, [prefix, searchTerm]);
57+
const locationsToUpdate = api.location.getByPrefix.useQuery(
58+
{ prefix },
59+
{ enabled: searchTerm.length === 3 },
4460
);
45-
const { data: locations = [] } = api.location.list.useQuery();
61+
62+
const locationValuesAndLabels = locationsToUpdate.data
63+
? locationsToUpdate.data.map((location) => {
64+
return {
65+
value: location.id,
66+
label:
67+
location.city +
68+
(location.state ? `, ${location.state}` : "") +
69+
", " +
70+
location.country,
71+
};
72+
})
73+
: [];
4674

4775
const onSubmit = (data: FormSchema) => {
4876
router.push(pathName + "?" + createQueryString(data));
@@ -109,32 +137,30 @@ export function CompanySearchBar({ industry, location }: SearchBarProps) {
109137
render={({ field }) => (
110138
<FormItem className="col-span-5 lg:col-span-2">
111139
<FormControl>
112-
<Select
113-
onValueChange={(value) => {
114-
setSelectedLocation(value);
115-
const finalValue = value === "LOCATION" ? undefined : value;
140+
<ComboBox
141+
{...field}
142+
variant="filtering"
143+
defaultLabel={locationLabel || "Location"}
144+
searchPlaceholder="Type to begin..."
145+
searchEmpty="No location found."
146+
valuesAndLabels={locationValuesAndLabels}
147+
currLabel={locationLabel}
148+
onChange={(value) => {
149+
setSearchTerm(value);
150+
}}
151+
onSelect={(currentValue) => {
152+
setLocationLabel(currentValue);
153+
const selectedLoc = locationsToUpdate.data?.find(
154+
(loc) =>
155+
`${loc.city}${loc.state ? `, ${loc.state}` : ""}${loc.country ? `, ${loc.country}` : ""}` ===
156+
currentValue,
157+
);
158+
const finalValue =
159+
currentValue === "LOCATION" ? undefined : selectedLoc?.id;
116160
setValue(field.name, finalValue);
117161
void handleSubmit(onSubmit)();
118162
}}
119-
value={selectedLocation}
120-
>
121-
<SelectTrigger className="h-12 w-[340px] rounded-none border-2 border-l-0 border-t-0 border-[#9A9A9A] text-lg placeholder:opacity-50 focus:ring-0 active:ring-0 lg:rounded-md lg:border-2">
122-
<SelectValue placeholder="Location" />
123-
</SelectTrigger>
124-
<SelectContent>
125-
<SelectGroup>
126-
<SelectItem className="font-bold" value="LOCATION">
127-
Location
128-
</SelectItem>
129-
<SelectSeparator />
130-
{locations.map((location: LocationType) => (
131-
<SelectItem key={location.id} value={location.id}>
132-
{location.city + ", " + location.state}
133-
</SelectItem>
134-
))}
135-
</SelectGroup>
136-
</SelectContent>
137-
</Select>
163+
/>
138164
</FormControl>
139165
</FormItem>
140166
)}
@@ -143,7 +169,7 @@ export function CompanySearchBar({ industry, location }: SearchBarProps) {
143169
className="bg-white hover:bg-white hover:text-[#9A9A9A] border-white text-black"
144170
onClick={() => {
145171
setSelectedIndustry("INDUSTRY");
146-
setSelectedLocation("LOCATION");
172+
setLocationLabel("");
147173
form.setValue("searchIndustry", undefined);
148174
form.setValue("searchLocation", undefined);
149175
}}

0 commit comments

Comments
 (0)