Skip to content

Commit 2bbc7ca

Browse files
authored
Merge branch 'main' into pg-boss-config
2 parents 7cc9259 + 21ddf3a commit 2bbc7ca

File tree

15 files changed

+452
-371
lines changed

15 files changed

+452
-371
lines changed

src/app/(authenticated)/(dashboard)/[publicId]/equity-plans/form.tsx

Lines changed: 56 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
SelectValue,
3232
} from "@/components/ui/select";
3333

34+
import { LinearCombobox } from "@/components/ui/combobox";
3435
import {
3536
Form,
3637
FormControl,
@@ -106,6 +107,18 @@ const EquityPlanForm = ({
106107
: await updateMutation.mutateAsync(values);
107108
};
108109

110+
const shareClassOpts = shareClasses.map((share) => ({
111+
value: share.id || "",
112+
label: share.name || "",
113+
}));
114+
115+
const defaultCancellatonBehaviorOpts = [
116+
{ value: "RETIRE", label: "Retire" },
117+
{ value: "RETURN_TO_POOL", label: "Return to pool" },
118+
{ value: "HOLD_AS_CAPITAL_STOCK", label: "Hold as capital stock" },
119+
{ value: "DEFINED_PER_PLAN_SECURITY", label: "Defined per plan security" },
120+
];
121+
109122
return (
110123
<Form {...form}>
111124
<form onSubmit={form.handleSubmit(onSubmit)}>
@@ -210,64 +223,12 @@ const EquityPlanForm = ({
210223
render={({ field }) => (
211224
<FormItem>
212225
<FormLabel>Select a share class</FormLabel>
213-
<Select
214-
onValueChange={field.onChange}
215-
defaultValue={field.value}
216-
>
217-
<FormControl>
218-
<SelectTrigger className="w-full">
219-
<SelectValue placeholder="Select a share class" />
220-
</SelectTrigger>
221-
</FormControl>
222-
<SelectContent>
223-
<SelectGroup>
224-
<SelectLabel>
225-
{shareClasses.length > 0 ? (
226-
"Share classes"
227-
) : (
228-
<div className="text-sm text-muted-foreground">
229-
<p className="mb-2">
230-
You don't have any share classes yet.
231-
</p>
232-
<Button
233-
className="mt-3"
234-
size={"sm"}
235-
variant={"outline"}
236-
onClick={() => {
237-
pushModal("ShareClassModal", {
238-
type: "create",
239-
title: "Create a share class",
240-
shareClasses,
241-
subtitle: (
242-
<Tldr
243-
message="A share class on a cap table represents a distinct category of shares with specific rights and characteristics, such as voting preferences or priorities. Eg. Common and Preferred shares, Class A, B, etc, ESOs and RSUs, etc."
244-
cta={{
245-
label: "Learn more",
246-
// TODO - this link should be updated to the correct URL
247-
href: "https://captable.inc/help",
248-
}}
249-
/>
250-
),
251-
});
252-
}}
253-
>
254-
<RiAddFill className="mr-2 h-5 w-5" />
255-
Create a share class
256-
</Button>
257-
</div>
258-
)}
259-
</SelectLabel>
260-
261-
{shareClasses.map((shareClass) => (
262-
<SelectItem
263-
key={shareClass.id}
264-
value={shareClass.id as string}
265-
>
266-
{shareClass.name}
267-
</SelectItem>
268-
))}
269-
270-
<SelectSeparator />
226+
<div>
227+
{shareClasses.length > 0 ? (
228+
<LinearCombobox
229+
options={shareClassOpts}
230+
onValueChange={(option) => field.onChange(option.value)}
231+
>
271232
<button
272233
type="button"
273234
className="cursor-pointer w-full text-left"
@@ -289,17 +250,43 @@ const EquityPlanForm = ({
289250
});
290251
}}
291252
>
292-
<div className={SelectItemStyle}>
293-
<span className="absolute left-2 flex h-4 w-4 items-center justify-center">
253+
<div className="flex justify-between items-center my-1">
254+
<span>
294255
<RiAddFill className="h-4 w-4" aria-hidden />
295256
</span>
296257

297258
<div>Create new share class</div>
298259
</div>
299260
</button>
300-
</SelectGroup>
301-
</SelectContent>
302-
</Select>
261+
</LinearCombobox>
262+
) : (
263+
<Button
264+
className="mt-3"
265+
size={"sm"}
266+
variant={"outline"}
267+
onClick={() => {
268+
pushModal("ShareClassModal", {
269+
type: "create",
270+
title: "Create a share class",
271+
shareClasses,
272+
subtitle: (
273+
<Tldr
274+
message="A share class on a cap table represents a distinct category of shares with specific rights and characteristics, such as voting preferences or priorities. Eg. Common and Preferred shares, Class A, B, etc, ESOs and RSUs, etc."
275+
cta={{
276+
label: "Learn more",
277+
// TODO - this link should be updated to the correct URL
278+
href: "https://captable.inc/help",
279+
}}
280+
/>
281+
),
282+
});
283+
}}
284+
>
285+
<RiAddFill className="mr-2 h-5 w-5" />
286+
Create a share class
287+
</Button>
288+
)}
289+
</div>
303290
<FormMessage className="text-xs font-light" />
304291
</FormItem>
305292
)}
@@ -313,28 +300,12 @@ const EquityPlanForm = ({
313300
render={({ field }) => (
314301
<FormItem>
315302
<FormLabel>Default cancellation behavior</FormLabel>
316-
<Select
317-
onValueChange={field.onChange}
318-
defaultValue={field.value}
319-
>
320-
<FormControl>
321-
<SelectTrigger className="w-full">
322-
<SelectValue placeholder="Select a behavior" />
323-
</SelectTrigger>
324-
</FormControl>
325-
<SelectContent>
326-
<SelectItem value="RETIRE">Retire</SelectItem>
327-
<SelectItem value="RETURN_TO_POOL">
328-
Return to pool
329-
</SelectItem>
330-
<SelectItem value="HOLD_AS_CAPITAL_STOCK">
331-
Hold as capital stock
332-
</SelectItem>
333-
<SelectItem value="DEFINED_PER_PLAN_SECURITY">
334-
Defined per plan security
335-
</SelectItem>
336-
</SelectContent>
337-
</Select>
303+
<div>
304+
<LinearCombobox
305+
options={defaultCancellatonBehaviorOpts}
306+
onValueChange={(option) => field.onChange(option.value)}
307+
/>
308+
</div>
338309
<FormMessage className="text-xs font-light" />
339310
</FormItem>
340311
)}

src/components/modals/share-class-form.tsx

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
FormMessage,
3737
} from "@/components/ui/form";
3838
import { popModal } from ".";
39+
import { type ComboBoxOption, LinearCombobox } from "../ui/combobox";
3940

4041
const formSchema = ShareClassMutationSchema;
4142

@@ -76,7 +77,7 @@ const ShareClassForm = ({
7677
const isSubmitting = form.formState.isSubmitting;
7778
const watchConversionRights = watch("conversionRights") as string;
7879
const [renderShareClassInput, setRenderShareClassInput] = useState(false);
79-
80+
const [defShareTypeOpt, setDefShareTypeOpt] = useState<ComboBoxOption>();
8081
useEffect(() => {
8182
if (watchConversionRights === "CONVERTS_TO_SHARE_CLASS_ID") {
8283
setRenderShareClassInput(true);
@@ -117,6 +118,19 @@ const ShareClassForm = ({
117118
: await updateMutation.mutateAsync(values);
118119
};
119120

121+
useEffect(() => {
122+
setDefShareTypeOpt(
123+
shareClassTypeOpts.find(
124+
(opt) => opt.value === form.getValues().classType,
125+
),
126+
);
127+
}, [form.getValues]);
128+
129+
const shareClassTypeOpts = [
130+
{ value: "COMMON", label: "Common share" },
131+
{ value: "PREFERRED", label: "Preferred share" },
132+
];
133+
120134
return (
121135
<Form {...form}>
122136
<form onSubmit={form.handleSubmit(onSubmit)}>
@@ -144,20 +158,13 @@ const ShareClassForm = ({
144158
render={({ field }) => (
145159
<FormItem>
146160
<FormLabel>Type of share class</FormLabel>
147-
<Select
148-
onValueChange={field.onChange}
149-
defaultValue={field.value}
150-
>
151-
<FormControl>
152-
<SelectTrigger className="w-full">
153-
<SelectValue placeholder="Select type" />
154-
</SelectTrigger>
155-
</FormControl>
156-
<SelectContent>
157-
<SelectItem value="COMMON">Common share</SelectItem>
158-
<SelectItem value="PREFERRED">Preferred share</SelectItem>
159-
</SelectContent>
160-
</Select>
161+
<div>
162+
<LinearCombobox
163+
options={shareClassTypeOpts}
164+
onValueChange={(option) => field.onChange(option.value)}
165+
defaultOption={defShareTypeOpt}
166+
/>
167+
</div>
161168
<FormMessage className="text-xs font-light" />
162169
</FormItem>
163170
)}

src/components/modals/stakeholder/single-stake-holder-form.tsx

Lines changed: 37 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { useForm } from "react-hook-form";
88

99
import { popModal } from "@/components/modals";
1010
import { Button } from "@/components/ui/button";
11+
import { LinearCombobox } from "@/components/ui/combobox";
1112
import {
1213
Form,
1314
FormControl,
@@ -17,13 +18,6 @@ import {
1718
FormMessage,
1819
} from "@/components/ui/form";
1920
import { Input } from "@/components/ui/input";
20-
import {
21-
Select,
22-
SelectContent,
23-
SelectItem,
24-
SelectTrigger,
25-
SelectValue,
26-
} from "@/components/ui/select";
2721
import { api } from "@/trpc/react";
2822
import { useRouter } from "next/navigation";
2923
import { toast } from "sonner";
@@ -52,6 +46,28 @@ export const SingleStakeholderForm = () => {
5246
await mutateAsync([values]);
5347
popModal("SingleStakeholdersModal");
5448
};
49+
50+
const stakeHolderTypeOpts = [
51+
{ value: "INDIVIDUAL", label: "Individual" },
52+
{ value: "INSTITUTION", label: "Institution" },
53+
];
54+
55+
const groupTypeOpts = [
56+
{ value: "ADVISOR", label: "Advisor" },
57+
{ value: "BOARD_MEMBER", label: "Board member" },
58+
{ value: "CONSULTANT", label: "Consultant" },
59+
{ value: "EMPLOYEE", label: "Employee" },
60+
{ value: "EX_ADVISOR", label: "Ex advisor" },
61+
{ value: "EX_CONSULTANT", label: "Ex consultant" },
62+
{ value: "EX_EMPLOYEE", label: "Ex employee" },
63+
{ value: "EXECUTIVE", label: "Executive" },
64+
{ value: "FOUNDER", label: "Founder" },
65+
{ value: "INVESTOR", label: "Investor" },
66+
{ value: "NON_US_EMPLOYEE", label: "Non US employee" },
67+
{ value: "OFFICER", label: "Officer" },
68+
{ value: "OTHER", label: "Other" },
69+
];
70+
5571
return (
5672
<Form {...form}>
5773
<form onSubmit={form.handleSubmit(onSubmit)}>
@@ -107,17 +123,14 @@ export const SingleStakeholderForm = () => {
107123
render={({ field }) => (
108124
<FormItem>
109125
<FormLabel>Type</FormLabel>
110-
<Select onValueChange={field.onChange}>
111-
<FormControl>
112-
<SelectTrigger className="w-full">
113-
<SelectValue placeholder="Select type" />
114-
</SelectTrigger>
115-
</FormControl>
116-
<SelectContent>
117-
<SelectItem value="INDIVIDUAL">Individual</SelectItem>
118-
<SelectItem value="INSTITUTION">Institution</SelectItem>
119-
</SelectContent>
120-
</Select>
126+
<div>
127+
<LinearCombobox
128+
options={stakeHolderTypeOpts}
129+
onValueChange={(option) => {
130+
field.onChange(option.value);
131+
}}
132+
/>
133+
</div>
121134
<FormMessage className="text-xs font-light" />
122135
</FormItem>
123136
)}
@@ -130,32 +143,12 @@ export const SingleStakeholderForm = () => {
130143
render={({ field }) => (
131144
<FormItem>
132145
<FormLabel>Group</FormLabel>
133-
<Select onValueChange={field.onChange}>
134-
<FormControl>
135-
<SelectTrigger className="w-full">
136-
<SelectValue placeholder="Select association" />
137-
</SelectTrigger>
138-
</FormControl>
139-
<SelectContent>
140-
<SelectItem value="ADVISOR">Advisor</SelectItem>
141-
<SelectItem value="BOARD_MEMBER">Board member</SelectItem>
142-
<SelectItem value="CONSULTANT">Consultant</SelectItem>
143-
<SelectItem value="EMPLOYEE">Employee</SelectItem>
144-
<SelectItem value="EX_ADVISOR">Ex advisor</SelectItem>
145-
<SelectItem value="EX_CONSULTANT">
146-
Ex consultant
147-
</SelectItem>
148-
<SelectItem value="EX_EMPLOYEE">Ex employee</SelectItem>
149-
<SelectItem value="EXECUTIVE">Executive</SelectItem>
150-
<SelectItem value="FOUNDER">Founder</SelectItem>
151-
<SelectItem value="INVESTOR">Investor</SelectItem>
152-
<SelectItem value="NON_US_EMPLOYEE">
153-
Non US employee
154-
</SelectItem>
155-
<SelectItem value="OFFICER">Officer</SelectItem>
156-
<SelectItem value="OTHER">Other</SelectItem>
157-
</SelectContent>
158-
</Select>
146+
<div>
147+
<LinearCombobox
148+
options={groupTypeOpts}
149+
onValueChange={(option) => field.onChange(option.value)}
150+
/>
151+
</div>
159152
<FormMessage className="text-xs font-light" />
160153
</FormItem>
161154
)}

0 commit comments

Comments
 (0)