/** * This type represents all the patient profile kind */ export type ProfileKind = 'myself' | 'child' | 'other' /** * this type is done as an example on how to add another data kind */ export type OtherKind = 'otherKindOfType' /** * This type represents all the kind a data that can define `ChoiceInputData` (`OtherKind` is here only as an example on how to add a new kind) */ export type AllChoiceInputDataKind = ProfileKind | OtherKind /** * This interface represents a `StateTrigger` on selected profile kind */ export interface ProfileTrigger { kind: 'profileTrigger' value: ProfileKind } /** * This interface is meant as an example of another kind of `StateTrigger` */ export interface OtherTrigger { kind: 'otherTrigger' field1: number field2: string } /** * This type represents all the state triggers that are defined. * * A state trigger is triggered onto app states. In other words, it is for triggers that cannot be defined thanks to pure workflow answers. */ export type StateTrigger = ProfileTrigger | OtherTrigger export interface IndexedData { [key: string]: T } export type SelectedAnswerData = string | string[] export type SelectedAnswersData = IndexedData[] /** * Tracking between the selected answers and the previous ones (if exist) */ export interface PreviousAnswerData { /** * The answer from the previous consultation */ previousAnswer: T /** * The timestamp of when the previous answer was entered */ timestamp?: Date /** * Whether the value from the current answer and the previous answer has changed */ changed: boolean } export type PreviousAnswersData = IndexedData[] export interface ChoiceInputData { text: string className?: string order?: number /** If defined, the choice input contains a kind that can be used into app. For instance, to check if a specific `kind` of answer has been selected */ kind?: AllChoiceInputDataKind } export interface RadioInputIconOptionsData { variant: 'icon' icon: string } export interface RadioInputData extends ChoiceInputData { options?: RadioInputIconOptionsData } export interface RadioCardInputData extends RadioInputData { bodyText: string } export interface LanguagePickerData extends ChoiceInputData { flag: string // iso3166-1 locale: string } export interface TileRadioData extends ChoiceInputData { fullText?: string image?: string description?: string } export enum InputApplyFunctions { //these are generic metadata categories AllUpperCase = 'AllUpperCase', AllLowerCase = 'AllLowerCase', AllAlphabetical = 'AllAlphabetical', AllAlphanumeric = 'AllAlphanumeric', NoSpaces = 'NoSpaces', } export interface EntryData { id?: number label?: string inputApply?: InputApplyFunctions | InputApplyFunctions[] hideLabel?: boolean minorLabel?: string summaryLabel?: string summaryHidden?: boolean className?: string /** * This field represents a list of `selectedAnswers` that must be set for this entry to be displayed using the followng logical combination of rules: * * #### Single string * * ``` * // Required: rule1 * rules: rule1 * ``` * * #### Array of strings (AND is applied between statements): * * ``` * // Required: rule1 AND rule2 * rules: [ rule1, rule2 ] * ``` * * #### Array of arrays of strings (OR is applied between inner arrays. AND is applied between inner arrays statements) * * ``` * // Required: rule1 OR rule2 * rules: [ * [ rule1 ], * [ rule2 ] * ] * * // Required: rule1 OR (rule2 AND rule3) * rules: [ * [ rule1 ], * [ rule2, rule3 ] * ] * * // THIS IS FORBIDDEN * rules: [ * rule1, // <-- THIS IS FORBIDDEN. Instead use [ rule1 ] * [ rule2, rule3 ] * ] * ``` */ triggers?: string[][] | string[] | string /** * This field represents a list of `StateTrigger` that must be fulfilled for this entry to be displayed. */ stateTriggers?: StateTrigger[] // represents the modal that it will be rendered as componentKind?: string message?: string } export interface SlideData { header: string body: string image?: { src: string alt: string } icon?: string } export enum MetadataCategory { //these are generic metadata categories ChildPersonal = 'ChildPersonal', Consultation = 'Consultation', Refill = 'Refill', DataRetrieval = 'DataRetrieval', Followup = 'Followup', Recovery = 'Recovery', Medical = 'Medical', OtherPersonal = 'OtherPersonal', Personal = 'Personal', Preference = 'Preference', Prescription = 'Prescription', Raw = 'Raw', } /** * This interface describes all images-alias question kind options */ export interface ImagesAliasQuestionOptions { /** * Comma separated list of accepted formats. Will be given to the input html element. * Use same format as described [here](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#accept) */ accept?: string /** * Should allow multiple uploads or not */ multiple?: boolean /** * Should display photo guide instructions or not */ photoGuide?: boolean } export interface GenericQuestionData, O = undefined> extends EntryData { kind: T metaCategory: MetadataCategory answers?: A formValidation?: any[] // use yup-ast expressions placeholder?: string defaultValue?: any value?: string /** * Options to forward to the workflow component */ options?: O messages?: string /** * Overrides the read only ability of the question's answer * populated by extended workflow feature */ readOnly?: boolean /** * Overrides the fillable default of the question's answer * populated by extended workflow feature */ defaultEmpty?: boolean } export interface GroupedGenericQuestionData> extends GenericQuestionData { inline?: boolean inlineLabel?: boolean order?: number } export declare type QuestionData = | GenericQuestionData<'title' | 'paragraph' | 'checkbox', void> | GenericQuestionData< | 'text' | 'text-area' | 'date' | 'number' | 'images' | 'body-parts' | 'pharmacy-picker' | 'online-pharmacy-picker' | 'place-address' > | GenericQuestionData<'images-alias', IndexedData, ImagesAliasQuestionOptions> | GenericQuestionData< 'checkbox-group' | 'hair-loss-frontal' | 'select' | 'multiple' | 'text-select-group', IndexedData > | GroupedGenericQuestionData< 'radio' | 'hair-selector-women' | 'hair-selector-men' | 'hair-loss-stage' | 'hair-loss-other', IndexedData > | GroupedGenericQuestionData<'radio-card' | 'profile-selector', IndexedData> | GroupedGenericQuestionData<'language-picker', IndexedData> | GroupedGenericQuestionData<'tile-radio', IndexedData> export interface FieldData { type: 'field' className?: string id: string } export interface FieldGroupData { type: 'field-group' className?: string fieldsAndGroups: (FieldData | FieldGroupData)[] name?: string inline?: boolean fullWidth?: boolean } export interface WorkflowPageData { className?: string groups?: FieldGroupData[] highlightMsg?: string questions: IndexedData title?: string triggers?: string[] /** * This field represents a list of `ids` which will be spliced from the workflow groups and inserted into a designated location */ prioritizeIds?: string[] } export interface WorkflowData { createdAt: string culDeSacs: EntryData[] id: string locale?: string pages: WorkflowPageData[] summaryImageFieldName?: string // this field is used to show the consult summary image summarySymptomsFieldName?: string // this field is used to show the consult summary symptoms selectedAnswers?: SelectedAnswersData // all current answers previousAnswers?: PreviousAnswersData // if exists, it is a 1-1 mapping of the selectedAnswers' previous values serviceImage?: string walkthroughSlides?: SlideData[] /** * (optional) the service name this workflow provides */ serviceName?: string /** * (optional) the description of the service this workflow provides */ serviceDescription?: string /** * (optional) These are the plan uuids that will be defaulted and shown at payment plan selection */ startingPlanIds?: number[] /** * (optional) rules to hide certain payment plans (`startingPlanIds`) depending on the workflow answers */ hidePlanRules?: HidePlanRule[] /** * (optional) extension of another workflow referenced by uuid */ extendingWorkflow?: string /** * (optional) the extending referenced workflows `createdAt` timestamp */ extendingWorkflowTimestamp?: string /** * (optional) rules for the extension of another workflow */ extendingRules?: IndexedData } export interface WorkflowExtendingRules { /** * Whether the field becomes read only in the extended workflow */ readOnly?: boolean, /** * Whether the field becomes deselected/empty by default in the extended workflow */ defaultEmpty?: boolean, /** * Whether the field should be removed altogether in the extended workflow */ remove?: boolean, /** * Overrides the label of the original question */ label?: string } export interface HidePlanRule { /** * the stripe plan id from the practice service */ idPlan: string /** * Questions to apply yup rules on in, if rules are met then hide the plan */ rules: QuestionHidePlanRule[] | QuestionHidePlanRule[][] } export interface QuestionHidePlanRule { /** * the id of the question to check the rule on */ questionId: string /** * a collection of yup validated rules (same exact syntax we used for the workflow formValidation field, please reuse same functions) */ yupRuleValueToHide: any } /** * This interface describes an upload of an image (could be a picture, a pdf, a text file, etc.) */ export interface WorkflowUploadedImage { /** * Depending on the driver used by WorkflowInput: * - 'indexdb': will fetch the image in IndexDB with this id * - 'vault': will fetch the image in the vault with this id */ idbId?: string /** * The name of the image */ name: string /** * the image data (could be a picture, a pdf, a text file, etc.) */ imageData?: string } /** * This interface describes a workflow prepared and ready to be sent to vault */ export interface PopulatedWorkflowField { previousAnswer?: PreviousAnswerData // Answer from previous consultation answer?: SelectedAnswerData | WorkflowUploadedImage[] // Actual answer from the workflow displayedAnswer?: any // This answer is to be used only when it's impossible to get data from workflow kind: string // If we don't store question. We will need that field to at least know the field type } export interface PopulatedWorkflowData { workflowId: string // The workflow id to refer workflowCreatedAt: string // The workflow version locale?: string fields: Record // key corresponds to the QuestionData key in the workflow }