diff --git a/package.json b/package.json
index 88e5a8805..7da0bf134 100644
--- a/package.json
+++ b/package.json
@@ -81,6 +81,7 @@
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
"cookie": "^0.6.0",
+ "date-fns": "^3.6.0",
"dayjs": "^1.11.11",
"hono": "^4.4.8",
"html-to-image": "^1.11.11",
@@ -102,6 +103,7 @@
"prisma-json-types-generator": "^3.0.4",
"pushmodal": "^1.0.4",
"react": "18.3.1",
+ "react-day-picker": "^8.10.1",
"react-dom": "18.2.0",
"react-dropzone": "^14.2.3",
"react-hook-form": "^7.51.5",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c0aea01b9..0dc911986 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -161,6 +161,9 @@ importers:
cookie:
specifier: ^0.6.0
version: 0.6.0
+ date-fns:
+ specifier: ^3.6.0
+ version: 3.6.0
dayjs:
specifier: ^1.11.11
version: 1.11.11
@@ -224,6 +227,9 @@ importers:
react:
specifier: 18.3.1
version: 18.3.1
+ react-day-picker:
+ specifier: ^8.10.1
+ version: 8.10.1(date-fns@3.6.0)(react@18.3.1)
react-dom:
specifier: 18.2.0
version: 18.2.0(react@18.3.1)
@@ -8730,10 +8736,10 @@ snapshots:
'@aws-crypto/sha1-browser': 3.0.0
'@aws-crypto/sha256-browser': 3.0.0
'@aws-crypto/sha256-js': 3.0.0
- '@aws-sdk/client-sso-oidc': 3.577.0(@aws-sdk/client-sts@3.577.0)
- '@aws-sdk/client-sts': 3.577.0
+ '@aws-sdk/client-sso-oidc': 3.577.0
+ '@aws-sdk/client-sts': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0)
'@aws-sdk/core': 3.576.0
- '@aws-sdk/credential-provider-node': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0)(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/credential-provider-node': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0)(@aws-sdk/client-sts@3.577.0(@aws-sdk/client-sso-oidc@3.577.0))
'@aws-sdk/middleware-bucket-endpoint': 3.577.0
'@aws-sdk/middleware-expect-continue': 3.577.0
'@aws-sdk/middleware-flexible-checksums': 3.577.0
@@ -8788,13 +8794,13 @@ snapshots:
transitivePeerDependencies:
- aws-crt
- '@aws-sdk/client-sso-oidc@3.577.0(@aws-sdk/client-sts@3.577.0)':
+ '@aws-sdk/client-sso-oidc@3.577.0':
dependencies:
'@aws-crypto/sha256-browser': 3.0.0
'@aws-crypto/sha256-js': 3.0.0
- '@aws-sdk/client-sts': 3.577.0
+ '@aws-sdk/client-sts': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0)
'@aws-sdk/core': 3.576.0
- '@aws-sdk/credential-provider-node': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0)(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/credential-provider-node': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0)(@aws-sdk/client-sts@3.577.0(@aws-sdk/client-sso-oidc@3.577.0))
'@aws-sdk/middleware-host-header': 3.577.0
'@aws-sdk/middleware-logger': 3.577.0
'@aws-sdk/middleware-recursion-detection': 3.577.0
@@ -8831,7 +8837,6 @@ snapshots:
'@smithy/util-utf8': 3.0.0
tslib: 2.6.2
transitivePeerDependencies:
- - '@aws-sdk/client-sts'
- aws-crt
'@aws-sdk/client-sso@3.577.0':
@@ -8877,13 +8882,13 @@ snapshots:
transitivePeerDependencies:
- aws-crt
- '@aws-sdk/client-sts@3.577.0':
+ '@aws-sdk/client-sts@3.577.0(@aws-sdk/client-sso-oidc@3.577.0)':
dependencies:
'@aws-crypto/sha256-browser': 3.0.0
'@aws-crypto/sha256-js': 3.0.0
- '@aws-sdk/client-sso-oidc': 3.577.0(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/client-sso-oidc': 3.577.0
'@aws-sdk/core': 3.576.0
- '@aws-sdk/credential-provider-node': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0)(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/credential-provider-node': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0)(@aws-sdk/client-sts@3.577.0(@aws-sdk/client-sso-oidc@3.577.0))
'@aws-sdk/middleware-host-header': 3.577.0
'@aws-sdk/middleware-logger': 3.577.0
'@aws-sdk/middleware-recursion-detection': 3.577.0
@@ -8920,6 +8925,7 @@ snapshots:
'@smithy/util-utf8': 3.0.0
tslib: 2.6.2
transitivePeerDependencies:
+ - '@aws-sdk/client-sso-oidc'
- aws-crt
'@aws-sdk/core@3.576.0':
@@ -8951,13 +8957,13 @@ snapshots:
'@smithy/util-stream': 3.0.1
tslib: 2.6.2
- '@aws-sdk/credential-provider-ini@3.577.0(@aws-sdk/client-sso-oidc@3.577.0)(@aws-sdk/client-sts@3.577.0)':
+ '@aws-sdk/credential-provider-ini@3.577.0(@aws-sdk/client-sso-oidc@3.577.0)(@aws-sdk/client-sts@3.577.0(@aws-sdk/client-sso-oidc@3.577.0))':
dependencies:
- '@aws-sdk/client-sts': 3.577.0
+ '@aws-sdk/client-sts': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0)
'@aws-sdk/credential-provider-env': 3.577.0
'@aws-sdk/credential-provider-process': 3.577.0
'@aws-sdk/credential-provider-sso': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0)
- '@aws-sdk/credential-provider-web-identity': 3.577.0(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/credential-provider-web-identity': 3.577.0(@aws-sdk/client-sts@3.577.0(@aws-sdk/client-sso-oidc@3.577.0))
'@aws-sdk/types': 3.577.0
'@smithy/credential-provider-imds': 3.0.0
'@smithy/property-provider': 3.0.0
@@ -8968,14 +8974,14 @@ snapshots:
- '@aws-sdk/client-sso-oidc'
- aws-crt
- '@aws-sdk/credential-provider-node@3.577.0(@aws-sdk/client-sso-oidc@3.577.0)(@aws-sdk/client-sts@3.577.0)':
+ '@aws-sdk/credential-provider-node@3.577.0(@aws-sdk/client-sso-oidc@3.577.0)(@aws-sdk/client-sts@3.577.0(@aws-sdk/client-sso-oidc@3.577.0))':
dependencies:
'@aws-sdk/credential-provider-env': 3.577.0
'@aws-sdk/credential-provider-http': 3.577.0
- '@aws-sdk/credential-provider-ini': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0)(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/credential-provider-ini': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0)(@aws-sdk/client-sts@3.577.0(@aws-sdk/client-sso-oidc@3.577.0))
'@aws-sdk/credential-provider-process': 3.577.0
'@aws-sdk/credential-provider-sso': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0)
- '@aws-sdk/credential-provider-web-identity': 3.577.0(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/credential-provider-web-identity': 3.577.0(@aws-sdk/client-sts@3.577.0(@aws-sdk/client-sso-oidc@3.577.0))
'@aws-sdk/types': 3.577.0
'@smithy/credential-provider-imds': 3.0.0
'@smithy/property-provider': 3.0.0
@@ -9008,9 +9014,9 @@ snapshots:
- '@aws-sdk/client-sso-oidc'
- aws-crt
- '@aws-sdk/credential-provider-web-identity@3.577.0(@aws-sdk/client-sts@3.577.0)':
+ '@aws-sdk/credential-provider-web-identity@3.577.0(@aws-sdk/client-sts@3.577.0(@aws-sdk/client-sso-oidc@3.577.0))':
dependencies:
- '@aws-sdk/client-sts': 3.577.0
+ '@aws-sdk/client-sts': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0)
'@aws-sdk/types': 3.577.0
'@smithy/property-provider': 3.0.0
'@smithy/types': 3.0.0
@@ -9137,7 +9143,7 @@ snapshots:
'@aws-sdk/token-providers@3.577.0(@aws-sdk/client-sso-oidc@3.577.0)':
dependencies:
- '@aws-sdk/client-sso-oidc': 3.577.0(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/client-sso-oidc': 3.577.0
'@aws-sdk/types': 3.577.0
'@smithy/property-provider': 3.0.0
'@smithy/shared-ini-file-loader': 3.0.0
diff --git a/src/components/common/date-picker.tsx b/src/components/common/date-picker.tsx
new file mode 100644
index 000000000..196f8cbbe
--- /dev/null
+++ b/src/components/common/date-picker.tsx
@@ -0,0 +1,66 @@
+"use client";
+
+import { RiCalendar2Line as CalendarIcon } from "@remixicon/react";
+import * as React from "react";
+
+import { Button } from "@/components/ui/button";
+import { Calendar } from "@/components/ui/calendar";
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/components/ui/popover";
+import { cn } from "@/lib/utils";
+import { format } from "date-fns";
+import type { SelectSingleEventHandler } from "react-day-picker";
+
+export type DatePickerProps = {
+ className?: string;
+ dateFormat?: string;
+ disabled?: boolean;
+ locale?: string;
+ selected: Date;
+ onSelect: SelectSingleEventHandler;
+ placeholder?: string;
+};
+
+const DatePicker = ({
+ className,
+ dateFormat,
+ disabled,
+ locale,
+ selected,
+ onSelect,
+ placeholder,
+}: DatePickerProps) => {
+ return (
+
+
+
+
+
+ {
+ if (disabled) return true;
+ return date > new Date() || date < new Date("1900-01-01");
+ }}
+ initialFocus
+ />
+
+
+ );
+};
+
+export default DatePicker;
diff --git a/src/components/onboarding/company-form.tsx b/src/components/onboarding/company-form.tsx
index aa4f14796..ceb7344fb 100644
--- a/src/components/onboarding/company-form.tsx
+++ b/src/components/onboarding/company-form.tsx
@@ -32,10 +32,12 @@ import countries from "@/lib/countries";
import { cn, isFileExists, validateFile } from "@/lib/utils";
import { api } from "@/trpc/react";
import type { RouterOutputs } from "@/trpc/shared";
+import { format, isValid, parse } from "date-fns";
import { useSession } from "next-auth/react";
import { useRouter } from "next/navigation";
import { useRef, useState } from "react";
import { toast } from "sonner";
+import DatePicker from "../common/date-picker";
import Loading from "../common/loading";
import { LinearCombobox } from "../ui/combobox";
@@ -73,9 +75,7 @@ export const CompanyForm = ({ type, data }: CompanyFormProps) => {
company: {
city: data?.company.city ?? "",
incorporationCountry: data?.company.incorporationCountry ?? "",
- incorporationDate: data?.company.incorporationDate
- ? dayjsExt(data.company.incorporationDate).format("YYYY-MM-DD")
- : "",
+ incorporationDate: data?.company.incorporationDate,
incorporationState: data?.company.incorporationState ?? "",
incorporationType: data?.company.incorporationType ?? "",
name: data?.company.name ?? "",
@@ -443,9 +443,13 @@ export const CompanyForm = ({ type, data }: CompanyFormProps) => {
render={({ field }) => (
Incorporation date
-
-
-
+
+
+
)}
diff --git a/src/components/securities/options/steps/relevant-dates.tsx b/src/components/securities/options/steps/relevant-dates.tsx
index 369e25959..7efec4178 100644
--- a/src/components/securities/options/steps/relevant-dates.tsx
+++ b/src/components/securities/options/steps/relevant-dates.tsx
@@ -1,5 +1,6 @@
"use client";
+import DatePicker from "@/components/common/date-picker";
import { Button } from "@/components/ui/button";
import {
Form,
@@ -21,11 +22,11 @@ import { useForm } from "react-hook-form";
import { z } from "zod";
const formSchema = z.object({
- boardApprovalDate: z.string().date(),
- rule144Date: z.string().date(),
- issueDate: z.string().date(),
- expirationDate: z.string().date(),
- vestingStartDate: z.string().date(),
+ boardApprovalDate: z.date(),
+ rule144Date: z.date(),
+ issueDate: z.date(),
+ expirationDate: z.date(),
+ vestingStartDate: z.date(),
});
type TFormSchema = z.infer;
@@ -53,7 +54,10 @@ export const RelevantDates = () => {
Issue date
-
+
@@ -67,7 +71,10 @@ export const RelevantDates = () => {
Expiry date
-
+
diff --git a/src/components/securities/shares/steps/relevant-dates.tsx b/src/components/securities/shares/steps/relevant-dates.tsx
index e1553f3d4..caa21820f 100644
--- a/src/components/securities/shares/steps/relevant-dates.tsx
+++ b/src/components/securities/shares/steps/relevant-dates.tsx
@@ -1,5 +1,6 @@
"use client";
+import DatePicker from "@/components/common/date-picker";
import { Button } from "@/components/ui/button";
import {
Form,
@@ -9,7 +10,6 @@ import {
FormLabel,
FormMessage,
} from "@/components/ui/form";
-import { Input } from "@/components/ui/input";
import {
StepperModalFooter,
StepperPrev,
@@ -21,10 +21,10 @@ import { useForm } from "react-hook-form";
import { z } from "zod";
const formSchema = z.object({
- boardApprovalDate: z.string().date(),
- rule144Date: z.string().date(),
- issueDate: z.string().date(),
- vestingStartDate: z.string().date(),
+ boardApprovalDate: z.date(),
+ rule144Date: z.date(),
+ issueDate: z.date(),
+ vestingStartDate: z.date(),
});
type TFormSchema = z.infer;
@@ -54,7 +54,10 @@ export const RelevantDates = () => {
Issue date
-
+
@@ -69,7 +72,10 @@ export const RelevantDates = () => {
Vesting start date
-
+
@@ -87,7 +93,10 @@ export const RelevantDates = () => {
Board approval date
-
+
@@ -102,7 +111,10 @@ export const RelevantDates = () => {
Rule 144 date
-
+
diff --git a/src/components/ui/calendar.tsx b/src/components/ui/calendar.tsx
new file mode 100644
index 000000000..2ea41aa91
--- /dev/null
+++ b/src/components/ui/calendar.tsx
@@ -0,0 +1,69 @@
+"use client";
+
+import {
+ RiArrowLeftWideLine as ChevronLeft,
+ RiArrowRightWideLine as ChevronRight,
+} from "@remixicon/react";
+import type * as React from "react";
+import { DayPicker } from "react-day-picker";
+
+import { buttonVariants } from "@/components/ui/button";
+import { cn } from "@/lib/utils";
+
+export type CalendarProps = React.ComponentProps;
+
+function Calendar({
+ className,
+ classNames,
+ showOutsideDays = true,
+ ...props
+}: CalendarProps) {
+ return (
+ ,
+ IconRight: ({ ...props }) => ,
+ }}
+ {...props}
+ />
+ );
+}
+Calendar.displayName = "Calendar";
+
+export { Calendar };
diff --git a/src/trpc/routers/onboarding-router/schema.ts b/src/trpc/routers/onboarding-router/schema.ts
index e2def1311..daefa5e99 100644
--- a/src/trpc/routers/onboarding-router/schema.ts
+++ b/src/trpc/routers/onboarding-router/schema.ts
@@ -26,8 +26,8 @@ export const ZodCompanyMutationSchema = z.object({
incorporationType: z.string().min(1, {
message: "Incorporation type is required",
}),
- incorporationDate: z.string().min(1, {
- message: "Incorporation date is required",
+ incorporationDate: z.date({
+ required_error: "Incorporation date is required",
}),
incorporationCountry: z.string().min(1, {
message: "Incorporation country is required",
diff --git a/src/trpc/routers/securities-router/schema.ts b/src/trpc/routers/securities-router/schema.ts
index 03a8554af..b56628d95 100644
--- a/src/trpc/routers/securities-router/schema.ts
+++ b/src/trpc/routers/securities-router/schema.ts
@@ -17,11 +17,11 @@ export const ZodAddOptionMutationSchema = z.object({
type: z.nativeEnum(OptionTypeEnum),
status: z.nativeEnum(OptionStatusEnum),
vestingSchedule: z.nativeEnum(VestingScheduleEnum),
- issueDate: z.string().date(),
- expirationDate: z.string().date(),
- vestingStartDate: z.string().date(),
- boardApprovalDate: z.string().date(),
- rule144Date: z.string().date(),
+ issueDate: z.date(),
+ expirationDate: z.date(),
+ vestingStartDate: z.date(),
+ boardApprovalDate: z.date(),
+ rule144Date: z.date(),
documents: z.array(
z.object({
bucketId: z.string(),
@@ -59,10 +59,10 @@ export const ZodAddShareMutationSchema = z.object({
status: z.nativeEnum(SecuritiesStatusEnum),
vestingSchedule: z.nativeEnum(VestingScheduleEnum),
companyLegends: z.nativeEnum(ShareLegendsEnum).array(),
- issueDate: z.string().date(),
- rule144Date: z.string().date(),
- vestingStartDate: z.string().date(),
- boardApprovalDate: z.string().date(),
+ issueDate: z.date(),
+ rule144Date: z.date(),
+ vestingStartDate: z.date(),
+ boardApprovalDate: z.date(),
documents: z.array(
z.object({
bucketId: z.string(),