0.0.0-development • Published 11 months ago

@omneo/ui-profile-quiz v0.0.0-development

Weekly downloads
-
License
ISC
Repository
github
Last release
11 months ago

Omneo Profile Quiz

A React component library designed to streamline user onboarding and profile completion with interactive quizzes.

Getting started

To get started, follow the instructions below

Installation

Omneo Profile Quiz is will be available as an npm package.

// npm
npm install @omneo/omneo-ui-profile-quiz

// yarn
yarn add @omneo/omneo-ui-profile-quiz

// pnpm
pnpm add @omneo/omneo-ui-profile-quiz

Import

Import components into your React project like this:

import { Answer } from '@omneo/omneo-ui-profile-quiz';

Examples

'use client';
import { useState } from 'react';

import {
    Answer,
    StepIndicator,
    ProgressIndicator,
    Button,
    Title,
    useQuizController,
    Controller,
    type Step,
} from 'ui-profile-quiz';

const sampleSteps: Step[] = [
    {
        title: 'Question 1',
        questions: [
            {
                id: 'q1',
                text: 'What is your favorite color?',
                type: 'single',
                options: [
                    { id: 'o1', primaryText: 'Red', iconSrc: '🔴' },
                    { id: 'o2', primaryText: 'Blue', iconSrc: '🔵' },
                    { id: 'o3', primaryText: 'Green', iconSrc: '🟢' },
                ],
            },
        ],
    },
    {
        title: 'Question 2',
        questions: [
            {
                id: 'q2',
                text: 'Select all that apply:',
                type: 'multiple',
                options: [
                    {
                        id: 'o4',
                        primaryText: 'I like cats',
                        secondaryText: 'Meow!',
                        iconSrc: '🐱',
                    },
                    {
                        id: 'o5',
                        primaryText: 'I like dogs',
                        secondaryText: 'Woof!',
                        iconSrc: '🐶',
                    },
                    {
                        id: 'o6',
                        primaryText: 'I like birds',
                        secondaryText: 'Tweet!',
                        iconSrc: '🐦',
                    },
                ],
            },
        ],
    },
];

const QuizInterface = ({ postSubmitMessage }) => {
    const {
        currentStep,
        totalSteps,
        steps,
        stepData,
        handleNextStep,
        handlePreviousStep,
        handleAnswer,
    } = useQuizController();

    const currentStepData = steps[currentStep];

    if (!currentStepData) return null;

    const progress = ((currentStep + 1) / totalSteps) * 100;

    return (
        <div style={{ maxWidth: '900px', margin: '0 auto' }}>
            {postSubmitMessage ? (
                <div
                    style={{
                        marginBottom: '20px',
                        padding: '10px',
                        backgroundColor: '#e6f7ff',
                        borderRadius: '4px',
                    }}
                >
                    Your discount code: {postSubmitMessage}
                </div>
            ) : (
                <>
                    <ProgressIndicator progress={progress} />
                    <StepIndicator
                        currentStep={currentStep + 1}
                        totalSteps={totalSteps}
                    />
                    <Title>{currentStepData.title}</Title>
                    {currentStepData.questions.map((question) => (
                        <div key={question.id} style={{ marginBottom: '20px' }}>
                            <p>{question.text}</p>
                            <div
                                style={{
                                    display: 'flex',
                                    flexDirection: 'column',
                                    gap: '10px',
                                }}
                            >
                                {question.options?.map((option) => {
                                    const isSelected = stepData[
                                        currentStep
                                    ]?.some(
                                        (answer) =>
                                            answer.questionId === question.id &&
                                            answer.selectedOptionIds.includes(
                                                option.id
                                            )
                                    );
                                    return (
                                        <Answer
                                            key={option.id}
                                            isSelected={isSelected}
                                            onClick={() =>
                                                handleAnswer(
                                                    question.id,
                                                    option.id,
                                                    question.type
                                                )
                                            }
                                        >
                                            {option.iconSrc && (
                                                <Answer.Icon>
                                                    <span
                                                        style={{
                                                            fontSize: '24px',
                                                        }}
                                                    >
                                                        {option.iconSrc}
                                                    </span>
                                                </Answer.Icon>
                                            )}
                                            <Answer.Content>
                                                <Answer.PrimaryText>
                                                    {option.primaryText}
                                                </Answer.PrimaryText>
                                                {option.secondaryText && (
                                                    <Answer.SecondaryText className="text-sm">
                                                        {option.secondaryText}
                                                    </Answer.SecondaryText>
                                                )}
                                            </Answer.Content>
                                        </Answer>
                                    );
                                })}
                            </div>
                        </div>
                    ))}
                    <div style={{ marginTop: '20px' }}>
                        <Button
                            size="sm"
                            onClick={handlePreviousStep}
                            disabled={currentStep === 0}
                        >
                            Previous
                        </Button>
                        <Button
                            onClick={handleNextStep}
                            style={{ marginLeft: '10px' }}
                            size="sm"
                        >
                            {currentStep < totalSteps - 1 ? 'Next' : 'Submit'}
                        </Button>
                    </div>
                </>
            )}
        </div>
    );
};

const Quiz = () => {
    const [discountCode, setDiscountCode] = useState<string | null>(null);

    return (
        <Controller
            steps={sampleSteps}
            onStepComplete={async (stepData, stepIndex) => {
                console.log(`Step ${stepIndex + 1} completed:`, stepData);
            }}
            onSubmit={async (allData) => {
                console.log('Quiz submitted:', allData);
                alert('Quiz submitted! Check console for data.');
            }}
            onPostSubmit={async () => {
                await new Promise((resolve) => setTimeout(resolve, 1000));
                setDiscountCode('QUIZ10OFF');
            }}
        >
            <QuizInterface postSubmitMessage={discountCode} />
        </Controller>
    );
};

export default Quiz;