-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[F] Inline questions #71
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,13 @@ | ||
import { ComponentType, FunctionComponent } from "react"; | ||
import { ComponentType, FunctionComponent, useContext } from "react"; | ||
import { Option } from "@/components/shapes/option"; | ||
import { | ||
BaseQuestionProps, | ||
InlineQuestionType, | ||
} from "@/components/shapes/questions"; | ||
import { BaseQuestionProps, InlineQuestionType } from "@/types/questions"; | ||
import * as Styled from "./styles"; | ||
import Readonly from "./Readonly"; | ||
import Text from "./Text"; | ||
import Select from "./Select"; | ||
import Multiselect from "./Multiselect"; | ||
import StoredAnswersContext from "@/contexts/StoredAnswersContext"; | ||
import { InlineQuestionData } from "@/types/answers"; | ||
|
||
interface InlineQuestionPart { | ||
id: string; | ||
|
@@ -30,7 +29,6 @@ export interface InlineMultiselectPart extends InlineQuestionPart { | |
} | ||
|
||
export interface InlineQuestionProps extends BaseQuestionProps { | ||
value?: string | string[]; | ||
parts: Array< | ||
| InlineReadonlyPart | ||
| InlineTextPart | ||
|
@@ -40,26 +38,25 @@ export interface InlineQuestionProps extends BaseQuestionProps { | |
} | ||
|
||
const INPUT_MAP: Record<InlineQuestionType, ComponentType<any>> = { | ||
readonly: Readonly, | ||
readonlyText: Readonly, | ||
text: Text, | ||
select: Select, | ||
multiselect: Multiselect, | ||
}; | ||
|
||
const InlineQuestion: FunctionComponent<InlineQuestionProps> = ({ | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
id, | ||
number, | ||
isDisabled, | ||
parts = [], | ||
}) => { | ||
const callback = (value: string | string[], id: string) => { | ||
console.info({ value, id }); | ||
}; | ||
const { answers, onChangeCallback } = useContext(StoredAnswersContext); | ||
const storedAnswer = answers[id] || {}; | ||
const { data = {} } = storedAnswer; | ||
|
||
return ( | ||
<Styled.InlineContainer value={number}> | ||
{parts.map(({ id, type, ...props }) => { | ||
{parts.map(({ id: partId, type, ...props }) => { | ||
const Input = INPUT_MAP[type]; | ||
|
||
if (!Input) { | ||
|
@@ -72,9 +69,18 @@ const InlineQuestion: FunctionComponent<InlineQuestionProps> = ({ | |
|
||
return ( | ||
<Input | ||
key={id} | ||
onChangeCallback={callback} | ||
{...{ ...props, isDisabled, id }} | ||
key={partId} | ||
id={partId} | ||
onChangeCallback={(value: string | string[]) => | ||
onChangeCallback && | ||
onChangeCallback( | ||
{ ...(data as InlineQuestionData), [partId]: value }, | ||
id, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. updates the |
||
storedAnswer?.id | ||
) | ||
} | ||
value={(data as InlineQuestionData)[partId]} | ||
{...{ ...props, isDisabled }} | ||
/> | ||
); | ||
})} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
"use client"; | ||
import styled from "styled-components"; | ||
|
||
export const SimpleContainer = styled.li` | ||
& > * + * { | ||
margin-block-start: var(--PADDING_SMALL, 20px); | ||
} | ||
`; | ||
|
||
export const QuestionLabel = styled.div` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. co-locate these styles with the |
||
display: inline; | ||
|
||
ul, | ||
ol { | ||
list-style: inside; | ||
|
||
::marker { | ||
margin: 0; | ||
} | ||
} | ||
|
||
& > *:first-child { | ||
display: inline; | ||
} | ||
|
||
& > * + * { | ||
margin-block-start: var(--PADDING_SMALL, 20px); | ||
} | ||
`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kylepratuch I wanted your input here on stringifying the
data
property before putting it into the query. We talked about the DB storing all values as a string type, since the typing ofdata
is very loose for the different question types (it can be a string, array of strings, generic object, mildly typed object), I opted to stringify all the data rather than trying to adapt the limited GQL types to fit.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alexgoff I'm not experienced enough with typescript to know at a glance if this is going to do what we discussed, but I trust that you do. :) Generally, I don't see an issue consistently storing the Answer
data
field as strings of JSON since that's really just supposed to consist of the values provided by users. If you start needing to store additional attributes beyond just the given answer values it might be worth adding some additional fields to the Answer element instead.