From e1efba3660af020bf55eee85195ef6aaf5b9983b Mon Sep 17 00:00:00 2001 From: Qwelian D Tanner Date: Wed, 7 Feb 2024 17:08:08 -0500 Subject: [PATCH] Add Deadline to Copy (#207) * update form schema and add deadline input field * add datepicker to form * change to basic input * change type of instance config * change metohd of entry calculate deadlien in sent email * getting dateline * calculating deadline. todo: update copy * adding copy changes * messed up * copy done * rmv logs * rmv date-fns * rmv import * change copy, correct nudge deadline * remove after --------- Co-authored-by: qweliant --- core/app/c/[communitySlug]/stages/page.tsx | 2 +- .../prisma/exampleCommunitySeeds/unjournal.ts | 2 + .../app/actions/evaluate/evaluate.tsx | 5 +- .../evaluations/app/actions/evaluate/page.tsx | 2 + .../app/actions/respond/actions.ts | 10 + .../app/actions/respond/respond.tsx | 51 +++-- .../evaluations/app/configure/configure.tsx | 63 +++++- .../evaluations/lib/components/Process.tsx | 19 +- integrations/evaluations/lib/emails.ts | 54 +++-- integrations/evaluations/lib/types.ts | 10 +- packages/ui/package.json | 2 + packages/ui/src/calandar.tsx | 60 ++++++ packages/ui/src/index.tsx | 1 + packages/ui/src/select.tsx | 160 ++++++++++++++ pnpm-lock.yaml | 201 +++++++++++++++++- 15 files changed, 591 insertions(+), 51 deletions(-) create mode 100644 packages/ui/src/calandar.tsx create mode 100644 packages/ui/src/select.tsx diff --git a/core/app/c/[communitySlug]/stages/page.tsx b/core/app/c/[communitySlug]/stages/page.tsx index d450675fd..61943a5b1 100644 --- a/core/app/c/[communitySlug]/stages/page.tsx +++ b/core/app/c/[communitySlug]/stages/page.tsx @@ -37,7 +37,7 @@ export default async function Page({ params }: Props) { return ( <>
-

Stages

-{" "} +

Stages

{/* Manage Stages */}
- +

{pubType.name}

{pubType.description}

diff --git a/integrations/evaluations/app/actions/evaluate/page.tsx b/integrations/evaluations/app/actions/evaluate/page.tsx index 59bc2a49e..f1682710a 100644 --- a/integrations/evaluations/app/actions/evaluate/page.tsx +++ b/integrations/evaluations/app/actions/evaluate/page.tsx @@ -7,6 +7,7 @@ import { cookie } from "~/lib/request"; import { Declined } from "./declined"; import { Evaluate } from "./evaluate"; import { Submitted } from "./submitted"; +import { EvaluatorWhoAccepted } from "~/lib/types"; type Props = { searchParams: { @@ -38,6 +39,7 @@ export default async function Page(props: Props) { instanceConfig={instanceConfig} pub={pub} pubType={pubType} + evaluator={instanceState[user.id] as EvaluatorWhoAccepted} /> ); // If they have responded "Decline", render the decline page. diff --git a/integrations/evaluations/app/actions/respond/actions.ts b/integrations/evaluations/app/actions/respond/actions.ts index cb304508a..357dc1ba6 100644 --- a/integrations/evaluations/app/actions/respond/actions.ts +++ b/integrations/evaluations/app/actions/respond/actions.ts @@ -9,6 +9,7 @@ import { sendRequestedInfoNotification, unscheduleNoReplyNotificationEmail, unscheduleReminderEmail, + calculateDeadline, } from "~/lib/emails"; import { getInstanceConfig, getInstanceState, setInstanceState } from "~/lib/instance"; import { cookie } from "~/lib/request"; @@ -38,7 +39,16 @@ export const accept = async (instanceId: string, pubId: string) => { ...evaluator, status: "accepted", acceptedAt: new Date().toString(), + deadline: new Date(Date.now()), }; + const deadline = calculateDeadline( + { + deadlineLength: instanceConfig.deadlineLength, + deadlineUnit: instanceConfig.deadlineUnit, + }, + new Date(evaluator.acceptedAt) + ); + evaluator.deadline = deadline; await setInstanceState(instanceId, pubId, instanceState); // Unschedule reminder email. await unscheduleReminderEmail(instanceId, pubId, evaluator); diff --git a/integrations/evaluations/app/actions/respond/respond.tsx b/integrations/evaluations/app/actions/respond/respond.tsx index 988e52cd5..e32a3db29 100644 --- a/integrations/evaluations/app/actions/respond/respond.tsx +++ b/integrations/evaluations/app/actions/respond/respond.tsx @@ -1,11 +1,12 @@ "use client"; import { GetPubResponseBody } from "@pubpub/sdk"; -import { useCallback, useEffect } from "react"; +import { useCallback } from "react"; import { Button, toast } from "ui"; import { accept, contact, decline } from "./actions"; import { InstanceConfig } from "~/lib/types"; import Link from "next/link"; +import { calculateDeadline } from "~/lib/emails"; type Props = { intent: "accept" | "decline" | "info"; @@ -88,9 +89,10 @@ const EvaluationProcess = () => { > value this work - , we offer evaluators a $400 honorarium for completing the assignment by the - specified deadline, and we are also setting aside $150 per evaluation for evaluator - incentives and prizes. + , we offer evaluators a $300 honorarium for completing the assignment by the + deadline. Evaluators may earn an additional $100 “prompt evaluation bonus” for + completing the assignment promptly (see below). As of February 2024: We are also + currently setting aside $150 per evaluation for evaluator incentives and prizes.

Your evaluation will be made public and given a DOI, but you have the option to{" "} @@ -206,7 +208,13 @@ export const Respond = (props: Props) => { const submissionUrl = props.pub.values["unjournal:url"] as string; const submissionTitle = props.pub.values[props.instanceConfig.titleFieldSlug] as string; const submissionAbstract = props.pub.values["unjournal:description"] as string; - + const deadline = calculateDeadline( + { + deadlineLength: props.instanceConfig.deadlineLength, + deadlineUnit: props.instanceConfig.deadlineUnit, + }, + new Date(Date.now()) + ); if (props.intent === "decline") { const params = new URLSearchParams(window.location.search); params.set("intent", "info"); @@ -280,12 +288,18 @@ export const Respond = (props: Props) => { <>

Confirm

- We encourage reviewers to complete reviews in three weeks. Upon accepting - this invitation, your evaluation will be due roughly on{" "} + We strongly encourage evaluators to complete evaluations relatively quickly, + for the benefit of authors, research-users, and the evaluation ecosystem. If + you submit the evaluation within that window (by{" "} - {new Date(Date.now() + 21 * (1000 * 60 * 60 * 24)).toLocaleDateString()} + {new Date( + deadline.getTime() - 21 * (1000 * 60 * 60 * 24) + ).toLocaleDateString()} - . + ), you will receive a $100 “prompt evaluation bonus.” After{" "} + {new Date(deadline.getTime()).toLocaleDateString()}, we + will consider re-assigning the evaluation, and later submissions may not be + eligible for the full baseline compensation.

@@ -306,10 +320,21 @@ export const Respond = (props: Props) => { <>

To respond to our invitation...

- To agree to take on this assignment, please click the 'Accept' button below. - If you have questions at this point, please select Contact Evaluation - Manager. If you will not be able to accept our invitation, please choose - 'Decline' below. + To agree to take on this assignment, please click the ‘Accept’ button below. + If you have questions at this point, please select ‘Contact Evaluation + Manager’. If you cannot accept our invitation, please choose ‘Decline’ + below. We strongly encourage evaluators to complete evaluations relatively + quickly, for the benefit of authors, research-users, and the evaluation + ecosystem. If you submit the evaluation within that window (by{" "} + + {new Date( + deadline.getTime() - 21 * (1000 * 60 * 60 * 24) + ).toLocaleDateString()} + + ), you will receive a $100 “prompt evaluation bonus.” After{" "} + {new Date(deadline.getTime()).toLocaleDateString()}, we + will consider re-assigning the evaluation, and later submissions may not be + eligible for the full baseline compensation.

diff --git a/integrations/evaluations/app/configure/configure.tsx b/integrations/evaluations/app/configure/configure.tsx index e34c9f11b..c9d442ba8 100644 --- a/integrations/evaluations/app/configure/configure.tsx +++ b/integrations/evaluations/app/configure/configure.tsx @@ -19,6 +19,11 @@ import { FormMessage, Icon, Input, + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, Textarea, useToast, } from "ui"; @@ -51,6 +56,9 @@ const schema: z.ZodType = z.object({ subject: z.string(), message: z.string(), }), + // coerce is used here to assert this field is a number, otherwise a vlaidation error will be thrown saying this is a string + deadlineLength: z.coerce.number().min(35), + deadlineUnit: z.enum(["days", "months"]), }); const isActionRedirect = (props: Props): props is RedirectProps => { @@ -62,17 +70,19 @@ const defaultEmailTemplate = { message: "Please reach out if you have any questions.", }; -const defaultInstanceConfig = { +const defaultFormValues: InstanceConfig = { pubTypeId: "", evaluatorFieldSlug: "", titleFieldSlug: "", - template: defaultEmailTemplate, + emailTemplate: defaultEmailTemplate, + deadlineLength: 35, + deadlineUnit: "days", }; export function Configure(props: Props) { const { toast } = useToast(); const defaultValues = useMemo( - () => Object.assign({}, defaultInstanceConfig, props.instanceConfig), + () => Object.assign({}, defaultFormValues, props.instanceConfig), [] ); const form = useForm>({ @@ -166,6 +176,53 @@ export function Configure(props: Props) { )} /> +
+ Deadline +
+ ( + + Deadline length + + + + + This field is used to determine thhe length of the deadline. + + + + )} + /> + ( + + Deadline Format + + + This field allows you to select whether the deadline is in + days or months. + + + + )} + />
Email Template
diff --git a/integrations/evaluations/lib/components/Process.tsx b/integrations/evaluations/lib/components/Process.tsx index f0f51d252..0edad1b68 100644 --- a/integrations/evaluations/lib/components/Process.tsx +++ b/integrations/evaluations/lib/components/Process.tsx @@ -1,6 +1,23 @@ -export const Process = () => { +import { EvaluatorWhoAccepted } from "../types"; + +type Props = { + evaluator: EvaluatorWhoAccepted; +}; + +export const Process = (props: Props) => { + const deadline = new Date(props.evaluator.deadline); + return ( <> +

+ We strongly encourage evaluators to complete evaluations relatively quickly, for the + benefit of authors, research-users, and the evaluation ecosystem. If you submit the + evaluation within that window (by{" "} + {new Date(deadline.getTime() - 21 * (1000 * 60 * 60 * 24)).toLocaleDateString()} ), + you will receive a $100 “prompt evaluation bonus.” After{" "} + {deadline.toLocaleDateString()}, we will consider re-assigning the evaluation, and + later submissions may not be eligible for the full baseline compensation. +

About our evaluation process

As a sign that we{" "} diff --git a/integrations/evaluations/lib/emails.ts b/integrations/evaluations/lib/emails.ts index d5bd7b78d..309835b89 100644 --- a/integrations/evaluations/lib/emails.ts +++ b/integrations/evaluations/lib/emails.ts @@ -8,7 +8,26 @@ import { const DAYS_TO_ACCEPT_INVITE = 10; const DAYS_TO_REMIND_EVALUATOR = 5; -const DAYS_TO_SUBMIT_EVALUATION = 21; + +/** + * Reaturns a new date object with the deadline calculated based on the deadlineLength and deadlineUnit. + * @param deadline + * @param date + * @returns Date + */ +export function calculateDeadline( + deadline: Pick, + date: Date +): Date { + switch (deadline.deadlineUnit) { + case "days": + return new Date(date.setMinutes(date.getMinutes() + deadline.deadlineLength * 24 * 60)); + case "months": + return new Date(date.setMonth(date.getMonth() + deadline.deadlineLength)); + default: + throw new Error('Invalid time unit. Use "days", "weeks", or "months".'); + } +} const notificationFooter = '

This is an automated email sent from Unjournal. Please contact contact@unjournal.org with any questions.

'; @@ -71,11 +90,10 @@ export const scheduleNoSubmitNotificationEmail = async ( instanceId: string, instanceConfig: InstanceConfig, pubId: string, - evaluator: EvaluatorWithInvite + evaluator: EvaluatorWhoAccepted ) => { const jobKey = makeNoSubmitJobKey(instanceId, pubId, evaluator); - const runAt = new Date(evaluator.invitedAt); - runAt.setMinutes(runAt.getMinutes() + DAYS_TO_SUBMIT_EVALUATION * 24 * 60); + const runAt = evaluator.deadline; await client.scheduleEmail( instanceId, @@ -95,7 +113,7 @@ ${notificationFooter}`, }, }, extra: { - due_at: runAt.toLocaleDateString(), + due_at: evaluator.deadline.toLocaleDateString(), manage_link: `Invite Evaluators page`, }, }, @@ -190,22 +208,26 @@ export const sendAcceptedEmail = async ( pubId: string, evaluator: EvaluatorWhoAccepted ) => { - const dueAt = new Date(evaluator.acceptedAt); - dueAt.setMinutes(dueAt.getMinutes() + DAYS_TO_SUBMIT_EVALUATION * 24 * 60); - await client.sendEmail(instanceId, { to: { userId: evaluator.userId, }, subject: `[Unjournal] Thank you for agreeing to evaluate "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}"`, message: `

Hi {{user.firstName}} {{user.lastName}},

-

Thank you for agreeing to evaluate "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}" for The Unjournal. Please submit your evaluation and ratings using {{extra.evaluate_link}}. The form includes general instructions as well as (potentially) specific considerations for this research and particular issues and priorities for this evaluation.

-

Please aim to submit your completed evaluation by {{extra.due_at}}. If you have any questions, do not hesitate to reach out to me at {{users.invitor.email}}.

-

Once your evaluation has been submitted and reviewed, we will follow up with details about payment and next steps.

-

Thank you again for your important contribution to the future of science.

-

Thanks and best wishes,

-

{{users.invitor.firstName}} {{users.invitor.lastName}}

-

Unjournal.org

`, +

Thank you for agreeing to evaluate "{{pubs.submission.values["${ + instanceConfig.titleFieldSlug + }"]}}" for The Unjournal. Please submit your evaluation and ratings using {{extra.evaluate_link}}. The form includes general instructions as well as (potentially) specific considerations for this research and particular issues and priorities for this evaluation.

+

We strongly encourage evaluators to complete evaluations within three weeks; relatively quick turnaround is an important part of The Unjournal model, for the benefit of authors, research-users, and the evaluation ecosystem. If you submit the evaluation within that window (by ${new Date( + evaluator.deadline.getTime() - 21 * (1000 * 60 * 60 * 24) + ).toLocaleDateString()}), you will receive a $100 “prompt evaluation bonus.” After ${new Date( + evaluator.deadline.getTime() + ).toLocaleDateString()}, we will consider re-assigning the evaluation, and later submissions may not be eligible for the full baseline compensation.

+

If you have any questions, do not hesitate to reach out to me at {{users.invitor.email}}.

+

Once your evaluation has been submitted and reviewed, we will follow up with details about payment and next steps.

+

Thank you again for your important contribution to the future of science.

+

Thanks and best wishes,

+

{{users.invitor.firstName}} {{users.invitor.lastName}}

+

Unjournal.org

`, include: { pubs: { submission: pubId, @@ -216,7 +238,7 @@ export const sendAcceptedEmail = async ( }, extra: { evaluate_link: `this evaluation form`, - due_at: dueAt.toLocaleDateString(), + due_at: evaluator.deadline.toLocaleDateString(), }, }); }; diff --git a/integrations/evaluations/lib/types.ts b/integrations/evaluations/lib/types.ts index 7d3ac1bc6..79827e7c1 100644 --- a/integrations/evaluations/lib/types.ts +++ b/integrations/evaluations/lib/types.ts @@ -60,6 +60,7 @@ export type EvaluatorWithInvite = z.infer; export const EvaluatorWhoAccepted = EvaluatorWithInvite.merge( z.object({ acceptedAt: z.string(), + deadline: z.date(), }) ); export type EvaluatorWhoAccepted = z.infer; @@ -95,19 +96,14 @@ export type InstanceConfig = { evaluatorFieldSlug: string; titleFieldSlug: string; emailTemplate: EmailTemplate; + deadlineLength: number; + deadlineUnit: "days" | "months"; }; export type InstanceState = { [evaluatorPubPubUserId: string]: Evaluator; }; -export const defaultInstanceConfig = { - pubTypeId: "", - emailTemplate: { subject: "", message: "" }, - evaluatorFieldSlug: "", - titleFieldSlug: "", -}; - export const isSaved = ( evaluator: Evaluator ): evaluator is Exclude => { diff --git a/packages/ui/package.json b/packages/ui/package.json index b7f70258d..ac4bc0110 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -22,6 +22,7 @@ "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-popover": "^1.0.6", + "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slider": "^1.1.2", "@radix-ui/react-slot": "^1.0.2", @@ -38,6 +39,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", "lucide-react": "^0.274.0", + "react-day-picker": "^8.10.0", "tailwind-merge": "^1.14.0", "tailwindcss-animate": "^1.0.6", "utils": "workspace:*" diff --git a/packages/ui/src/calandar.tsx b/packages/ui/src/calandar.tsx new file mode 100644 index 000000000..07153a6a8 --- /dev/null +++ b/packages/ui/src/calandar.tsx @@ -0,0 +1,60 @@ +"use client"; + +import * as React from "react"; +import { ChevronLeft, ChevronRight } from "lucide-react"; +import { CalendarIcon } from "@radix-ui/react-icons"; +import { DayPicker } from "react-day-picker"; + +import { cn } from "utils"; +import { buttonVariants } from "./button"; + +export type CalendarProps = React.ComponentProps; + +function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) { + return ( + , + IconRight: ({ ...props }) => , + }} + {...props} + /> + ); +} +Calendar.displayName = "Calendar"; + +export { Calendar, CalendarIcon }; diff --git a/packages/ui/src/index.tsx b/packages/ui/src/index.tsx index e314adb01..2c851a98b 100644 --- a/packages/ui/src/index.tsx +++ b/packages/ui/src/index.tsx @@ -17,6 +17,7 @@ export * from "./hover-card"; export * from "./input"; export * from "./label"; export * from "./popover"; +export * from "./select"; export * from "./separator"; export * from "./tabs"; export * from "./textarea"; diff --git a/packages/ui/src/select.tsx b/packages/ui/src/select.tsx new file mode 100644 index 000000000..27ad45b58 --- /dev/null +++ b/packages/ui/src/select.tsx @@ -0,0 +1,160 @@ +"use client" + +import * as React from "react" +import * as SelectPrimitive from "@radix-ui/react-select" +import { Check, ChevronDown, ChevronUp } from "lucide-react" + +import { cn } from "utils" + +const Select = SelectPrimitive.Root + +const SelectGroup = SelectPrimitive.Group + +const SelectValue = SelectPrimitive.Value + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + span]:line-clamp-1", + className + )} + {...props} + > + {children} + + + + +)) +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName + +const SelectScrollUpButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName + +const SelectScrollDownButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +SelectScrollDownButton.displayName = + SelectPrimitive.ScrollDownButton.displayName + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, position = "popper", ...props }, ref) => ( + + + + + {children} + + + + +)) +SelectContent.displayName = SelectPrimitive.Content.displayName + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SelectLabel.displayName = SelectPrimitive.Label.displayName + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + + {children} + +)) +SelectItem.displayName = SelectPrimitive.Item.displayName + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SelectSeparator.displayName = SelectPrimitive.Separator.displayName + +export { + Select, + SelectGroup, + SelectValue, + SelectTrigger, + SelectContent, + SelectLabel, + SelectItem, + SelectSeparator, + SelectScrollUpButton, + SelectScrollDownButton, +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1b2526db4..1f0892860 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -227,7 +227,7 @@ importers: version: 2.0.0 next: specifier: 13.5.2 - version: 13.5.2(@babel/core@7.22.17)(react-dom@18.2.0)(react@18.2.0) + version: 13.5.2(react-dom@18.2.0)(react@18.2.0) parse5-sax-parser: specifier: ^7.0.0 version: 7.0.0 @@ -276,7 +276,7 @@ importers: version: 8.4.27 tailwindcss: specifier: ^3.3.3 - version: 3.3.3(ts-node@10.9.1) + version: 3.3.3 tsconfig: specifier: workspace:* version: link:../../tsconfig @@ -458,6 +458,9 @@ importers: '@radix-ui/react-popover': specifier: ^1.0.6 version: 1.0.6(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-select': + specifier: ^2.0.0 + version: 2.0.0(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-separator': specifier: ^1.0.3 version: 1.0.3(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0) @@ -506,6 +509,9 @@ importers: lucide-react: specifier: ^0.274.0 version: 0.274.0(react@18.2.0) + react-day-picker: + specifier: ^8.10.0 + version: 8.10.0(date-fns@3.3.1)(react@18.2.0) tailwind-merge: specifier: ^1.14.0 version: 1.14.0 @@ -514,7 +520,7 @@ importers: version: 3.3.3(ts-node@10.9.1) tailwindcss-animate: specifier: ^1.0.6 - version: 1.0.6(tailwindcss@3.3.3) + version: 1.0.6 utils: specifier: workspace:* version: link:../utils @@ -3467,6 +3473,28 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-focus-scope@1.0.4(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.22.10 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.12)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.12)(react@18.2.0) + '@types/react': 18.2.12 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-hover-card@1.0.7(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-OcUN2FU0YpmajD/qkph3XzMcK/NmSk9hGWnjV68p6QiZMgILugusgQwnLSDs3oFSJYGKf3Y49zgFedhGh04k9A==} peerDependencies: @@ -3776,6 +3804,46 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-select@2.0.0(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-RH5b7af4oHtkcHS7pG6Sgv5rk5Wxa7XI8W5gvB1N/yiuDGZxko1ynvOiVhFM7Cis2A8zxF9bTOUVbRDzPepe6w==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.22.10 + '@radix-ui/number': 1.0.1 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-collection': 1.0.3(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.12)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.12)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.2.12)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.12)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.4(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.12)(react@18.2.0) + '@radix-ui/react-popper': 1.1.3(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.12)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.12)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.12)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.12)(react@18.2.0) + '@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.12)(react@18.2.0) + '@radix-ui/react-visually-hidden': 1.0.3(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.12 + aria-hidden: 1.2.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.2.12)(react@18.2.0) + dev: false + /@radix-ui/react-separator@1.0.3(@types/react@18.2.12)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-itYmTy/kokS21aiV5+Z56MZB54KrhPgn6eHDKkFeOLR34HMN2s8PaN47qZZAGnvupcjxHaFZnW4pQEh0BvvVuw==} peerDependencies: @@ -4425,7 +4493,7 @@ packages: '@sentry/vercel-edge': 7.72.0 '@sentry/webpack-plugin': 1.20.0 chalk: 3.0.0 - next: 13.5.2(@babel/core@7.22.17)(react-dom@18.2.0)(react@18.2.0) + next: 13.5.2(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 rollup: 2.78.0 stacktrace-parser: 0.1.10 @@ -5492,7 +5560,7 @@ packages: lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 postcss-selector-parser: 6.0.10 - tailwindcss: 3.3.3(ts-node@10.9.1) + tailwindcss: 3.3.3 dev: true /@transloadit/prettier-bytes@0.0.7: @@ -6681,6 +6749,10 @@ packages: resolution: {integrity: sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==} dev: true + /date-fns@3.3.1: + resolution: {integrity: sha512-y8e109LYGgoQDveiEBD3DYXKba1jWf5BA8YU1FL5Tvm0BTdEfy54WLCwnuYWZNnzzvALy/QQ4Hov+Q9RVRv+Zw==} + dev: false + /debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -8842,6 +8914,46 @@ packages: - babel-plugin-macros dev: false + /next@13.5.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-vog4UhUaMYAzeqfiAAmgB/QWLW7p01/sg+2vn6bqc/CxHFYizMzLv6gjxKzl31EVFkfl/F+GbxlKizlkTE9RdA==} + engines: {node: '>=16.14.0'} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + react: ^18.2.0 + react-dom: ^18.2.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + sass: + optional: true + dependencies: + '@next/env': 13.5.2 + '@swc/helpers': 0.5.2 + busboy: 1.6.0 + caniuse-lite: 1.0.30001519 + postcss: 8.4.14 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + styled-jsx: 5.1.1(react@18.2.0) + watchpack: 2.4.0 + zod: 3.21.4 + optionalDependencies: + '@next/swc-darwin-arm64': 13.5.2 + '@next/swc-darwin-x64': 13.5.2 + '@next/swc-linux-arm64-gnu': 13.5.2 + '@next/swc-linux-arm64-musl': 13.5.2 + '@next/swc-linux-x64-gnu': 13.5.2 + '@next/swc-linux-x64-musl': 13.5.2 + '@next/swc-win32-arm64-msvc': 13.5.2 + '@next/swc-win32-ia32-msvc': 13.5.2 + '@next/swc-win32-x64-msvc': 13.5.2 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + dev: false + /node-abort-controller@3.1.1: resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} dev: false @@ -9321,6 +9433,23 @@ packages: camelcase-css: 2.0.1 postcss: 8.4.27 + /postcss-load-config@4.0.1(postcss@8.4.27): + resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + dependencies: + lilconfig: 2.1.0 + postcss: 8.4.27 + yaml: 2.3.1 + dev: true + /postcss-load-config@4.0.1(postcss@8.4.27)(ts-node@10.9.1): resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==} engines: {node: '>= 14'} @@ -9551,6 +9680,16 @@ packages: engines: {node: '>=10'} dev: true + /react-day-picker@8.10.0(date-fns@3.3.1)(react@18.2.0): + resolution: {integrity: sha512-mz+qeyrOM7++1NCb1ARXmkjMkzWVh2GL9YiPbRjKe0zHccvekk4HE+0MPOZOrosn8r8zTHIIeOUXTmXRqmkRmg==} + peerDependencies: + date-fns: ^2.28.0 || ^3.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + date-fns: 3.3.1 + react: 18.2.0 + dev: false + /react-dom@18.2.0(react@18.2.0): resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} peerDependencies: @@ -10368,6 +10507,23 @@ packages: react: 18.2.0 dev: false + /styled-jsx@5.1.1(react@18.2.0): + resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + dependencies: + client-only: 0.0.1 + react: 18.2.0 + dev: false + /stylis@4.3.0: resolution: {integrity: sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==} dev: false @@ -10416,14 +10572,43 @@ packages: resolution: {integrity: sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==} dev: false - /tailwindcss-animate@1.0.6(tailwindcss@3.3.3): + /tailwindcss-animate@1.0.6: resolution: {integrity: sha512-4WigSGMvbl3gCCact62ZvOngA+PRqhAn7si3TQ3/ZuPuQZcIEtVap+ENSXbzWhpojKB8CpvnIsrwBu8/RnHtuw==} peerDependencies: tailwindcss: '>=3.0.0 || insiders' - dependencies: - tailwindcss: 3.3.3(ts-node@10.9.1) dev: false + /tailwindcss@3.3.3: + resolution: {integrity: sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.5.3 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.1 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.19.1 + lilconfig: 2.1.0 + micromatch: 4.0.5 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.0.0 + postcss: 8.4.27 + postcss-import: 15.1.0(postcss@8.4.27) + postcss-js: 4.0.1(postcss@8.4.27) + postcss-load-config: 4.0.1(postcss@8.4.27) + postcss-nested: 6.0.1(postcss@8.4.27) + postcss-selector-parser: 6.0.13 + resolve: 1.22.4 + sucrase: 3.34.0 + transitivePeerDependencies: + - ts-node + dev: true + /tailwindcss@3.3.3(ts-node@10.9.1): resolution: {integrity: sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==} engines: {node: '>=14.0.0'}