Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ export const defaultTranslations = {
numeric: "Numeric",
link: "Link",
date: "Date",
dateRange: "Date range",
},
selectQuestion: {
addOption: "Add option",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import type { Meta, StoryObj } from "@storybook/react-vite"

import { useState } from "react"

import { withSkipA11y } from "@/lib/storybook-utils/parameters"

import { DateRangeQuestion } from "."
import { CoCreationFormProvider } from "../Context"
import { CoCreationFormElement } from "../types"

const meta: Meta<typeof DateRangeQuestion> = {
title: "CoCreationForm/DateRangeQuestion",
component: DateRangeQuestion,
tags: ["autodocs", "experimental"],
render: (args) => {
const [elements, setElements] = useState<CoCreationFormElement[]>([
{ type: "question" as const, question: args },
])

const question =
elements[0] && "question" in elements[0] ? elements[0].question : {}

return (
<div className="max-w-[750px]">
<CoCreationFormProvider
elements={elements}
onChange={setElements}
isEditMode
>
<DateRangeQuestion {...args} {...question} />
</CoCreationFormProvider>
</div>
)
},
}

export default meta
type Story = StoryObj<typeof DateRangeQuestion>

export const EditMode: Story = {
parameters: withSkipA11y({}),
args: {
id: "question-1",
title: "What is the project timeline?",
description: "Select the start and end dates",
type: "daterange",
value: null,
},
}

export const AnswerMode: Story = {
parameters: withSkipA11y({}),
render: (args) => {
const [elements, setElements] = useState<CoCreationFormElement[]>([
{ type: "question" as const, question: args },
])

const question =
elements[0] && "question" in elements[0] ? elements[0].question : {}

return (
<div className="max-w-[750px]">
<CoCreationFormProvider
elements={elements}
onChange={setElements}
isEditMode={false}
>
<DateRangeQuestion {...args} {...question} />
</CoCreationFormProvider>
</div>
)
},
args: {
id: "question-2",
title: "What is the project timeline?",
description: "Select the start and end dates",
type: "daterange",
value: null,
},
}

export const WithValue: Story = {
parameters: withSkipA11y({}),
render: (args) => {
const [elements, setElements] = useState<CoCreationFormElement[]>([
{ type: "question" as const, question: args },
])

const question =
elements[0] && "question" in elements[0] ? elements[0].question : {}

return (
<div className="max-w-[750px]">
<CoCreationFormProvider
elements={elements}
onChange={setElements}
isEditMode={false}
>
<DateRangeQuestion {...args} {...question} />
</CoCreationFormProvider>
</div>
)
},
args: {
id: "question-3",
title: "Contract period",
description: "When does the contract start and end?",
type: "daterange",
value: {
from: new Date(2026, 2, 1),
to: new Date(2026, 5, 30),
},
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { useMemo } from "react"

import { DatePickerValue, F0DatePicker } from "@/components/F0DatePicker"
import { useI18n } from "@/lib/providers/i18n"

import { BaseQuestion } from "../BaseQuestion"
import { useCoCreationFormContext } from "../Context"
import { DateRangeQuestionProps, DateRangeValue } from "./types"

export type { DateRangeQuestionProps } from "./types"

export const DateRangeQuestion = ({
value,
...baseQuestionComponentProps
}: DateRangeQuestionProps) => {
const { onQuestionChange, isEditMode } = useCoCreationFormContext()

const { t } = useI18n()

const handleChangeDateRange = (newValue: DatePickerValue | undefined) => {
if (isEditMode) return

const rangeValue: DateRangeValue | null =
newValue?.value?.from && newValue?.value?.to
? { from: newValue.value.from, to: newValue.value.to }
: null

onQuestionChange?.({
...baseQuestionComponentProps,
type: "daterange",
value: rangeValue,
})
}

const datePickerValue = useMemo(
() =>
value
? {
granularity: "range" as const,
value: { from: value.from, to: value.to },
}
: undefined,
[value]
)

return (
<BaseQuestion {...baseQuestionComponentProps}>
<div className="px-0.5">
<F0DatePicker
size="md"
value={datePickerValue}
onChange={handleChangeDateRange}
granularities={["range"]}
disabled={isEditMode}
label={t("coCreationForm.answer.label")}
hideLabel={true}
required={baseQuestionComponentProps.required}
readonly={isEditMode}
clearable={!baseQuestionComponentProps.required}
/>
</div>
</BaseQuestion>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { BaseQuestionPropsForOtherQuestionComponents } from "../BaseQuestion"
import { BaseQuestionOnChangeParams } from "../types"

export type DateRangeValue = {
from: Date
to: Date
}

export type DateRangeQuestionOnChangeParams = BaseQuestionOnChangeParams & {
type: "daterange"
value?: DateRangeValue | null
}

export type DateRangeQuestionProps =
BaseQuestionPropsForOtherQuestionComponents & {
type: "daterange"
value?: DateRangeValue | null
}
5 changes: 5 additions & 0 deletions packages/react/src/sds/CoCreationForm/Question/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { BaseQuestionPropsForOtherQuestionComponents } from "../BaseQuestion"
import { DateQuestion, DateQuestionProps } from "../DateQuestion"
import { DateRangeQuestion } from "../DateRangeQuestion"
import { DateRangeQuestionProps } from "../DateRangeQuestion/types"
import { LinkQuestion, LinkQuestionProps } from "../LinkQuestion"
import { NumericQuestion, NumericQuestionProps } from "../NumericQuestion"
import { RatingQuestion, RatingQuestionProps } from "../RatingQuestion"
Expand All @@ -15,6 +17,7 @@ export type QuestionProps = BaseQuestionPropsForOtherQuestionComponents &
| (NumericQuestionProps & { type: "numeric" })
| (LinkQuestionProps & { type: "link" })
| (DateQuestionProps & { type: "date" })
| DateRangeQuestionProps
)

export const Question = ({ ...props }: QuestionProps) => {
Expand All @@ -33,6 +36,8 @@ export const Question = ({ ...props }: QuestionProps) => {
return <LinkQuestion {...props} />
case "date":
return <DateQuestion {...props} />
case "daterange":
return <DateRangeQuestion {...props} />
default:
throw new Error("Invalid question type provided")
}
Expand Down
15 changes: 14 additions & 1 deletion packages/react/src/sds/CoCreationForm/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { IconType } from "@/components/F0Icon/F0Icon"
import { Check, CheckDouble, List, Numbers, Star, TextSize } from "@/icons/app"
import {
Calendar,
Check,
CheckDouble,
List,
Numbers,
Star,
TextSize,
} from "@/icons/app"
import { useI18n } from "@/lib/providers/i18n"

import { useCoCreationFormContext } from "./Context"
Expand Down Expand Up @@ -45,6 +53,11 @@ export const useQuestionTypes = () => {
icon: Numbers,
questionType: "numeric",
},
{
label: t("coCreationForm.questionTypes.dateRange"),
icon: Calendar,
questionType: "daterange",
},
]

const filteredQuestionTypes = allQuestionTypes.filter((questionType) =>
Expand Down
5 changes: 5 additions & 0 deletions packages/react/src/sds/CoCreationForm/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ export const getDefaultParamsForQuestionType = (questionType: QuestionType) => {
return {
value: new Date(),
}
case "daterange":
return {
value: null,
}
default:
throw new Error(`Unsupported question type: ${questionType}`)
}
Expand All @@ -103,6 +107,7 @@ const DEFAULT_QUESTION_TYPES: QuestionType[] = [
"numeric",
"link",
"date",
"daterange",
]

export const getDefaultQuestionTypeToAdd = (
Expand Down
7 changes: 7 additions & 0 deletions packages/react/src/sds/CoCreationForm/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DateQuestionProps } from "./DateQuestion"
import { DateRangeQuestionProps } from "./DateRangeQuestion/types"
import { LinkQuestionProps } from "./LinkQuestion"
import { NumericQuestionProps } from "./NumericQuestion"
import { RatingQuestionProps } from "./RatingQuestion"
Expand All @@ -15,6 +16,7 @@ export type QuestionType =
| "numeric"
| "link"
| "date"
| "daterange"

export type ElementType = QuestionType | "section"

Expand All @@ -39,6 +41,7 @@ export type QuestionElement =
| Omit<NumericQuestionProps & { type: "numeric" }, QuestionPropsToOmit>
| Omit<LinkQuestionProps & { type: "link" }, QuestionPropsToOmit>
| Omit<DateQuestionProps & { type: "date" }, QuestionPropsToOmit>
| Omit<DateRangeQuestionProps, QuestionPropsToOmit>

export type CoCreationFormElement =
| { type: "section"; section: SectionElement }
Expand Down Expand Up @@ -99,6 +102,10 @@ type OnChangeQuestionParams = BaseQuestionOnChangeParams &
type: "date"
value?: Date | null
}
| {
type: "daterange"
value?: { from: Date; to: Date } | null
}
)

export type QuestionActionParams = {
Expand Down
Loading