Skip to content

Commit

Permalink
basic on click setup logic
Browse files Browse the repository at this point in the history
  • Loading branch information
liyiy committed Oct 11, 2023
1 parent 84c00e4 commit 343a5a4
Show file tree
Hide file tree
Showing 5 changed files with 352 additions and 2 deletions.
4 changes: 2 additions & 2 deletions frontend/src/scenes/surveys/SurveyAppearance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ interface SurveyAppearanceProps {
type: SurveyQuestionType
question: string
appearance: SurveyAppearanceType
surveyQuestionItem: RatingSurveyQuestion | SurveyQuestion | MultipleSurveyQuestion
surveyQuestionItem: SurveyQuestion
description?: string | null
link?: string | null
readOnly?: boolean
Expand Down Expand Up @@ -100,7 +100,7 @@ export function SurveyAppearance({

return (
<>
<h3 className="mb-4 text-center">Preview</h3>
{!readOnly && <h3 className="mb-4 text-center">Preview</h3>}
{!hideSubmittedSurvey && (
<>
{type === SurveyQuestionType.Rating && (
Expand Down
21 changes: 21 additions & 0 deletions frontend/src/scenes/surveys/SurveyTemplates.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@import '../../styles/mixins';

.SurveyTemplateContainer {
display: flex;
align-items: center;
border: 1px solid var(--border);
border-radius: 6px;
min-height: 300px;
margin-top: 2px;

&:hover {
cursor: pointer;
border-color: var(--primary-light);
}

.SurveyTemplate {
-ms-transform: scale(0.6, 0.6); /* IE 9 */
-webkit-transform: scale(0.6, 0.6); /* Safari */
transform: scale(0.6, 0.6);
}
}
51 changes: 51 additions & 0 deletions frontend/src/scenes/surveys/SurveyTemplates.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { SceneExport } from 'scenes/sceneTypes'
import { SurveyAppearance } from './SurveyAppearance'
import { defaultSurveyTemplates } from './constants'
import { SurveyQuestion } from '~/types'
import './SurveyTemplates.scss'
import { useActions } from 'kea'
import { surveyTemplatesLogic } from './surveyTemplatesLogic'

export const scene: SceneExport = {
component: SurveyTemplates,
}

export function SurveyTemplates(): JSX.Element {
const { openSurveyTemplate } = useActions(surveyTemplatesLogic)

return (
<>
<div className="flex flex-row flex-wrap gap-6 ml-8 mt-6">
{defaultSurveyTemplates.map((template, idx) => {
return (
<div
className="flex flex-col items-center max-w-100"
key={idx}
onClick={(template) => openSurveyTemplate(template)}
>
<span className="mb-2">
<b>{template.type}</b>
</span>
<div className="SurveyTemplateContainer">
<div className="SurveyTemplate">
<SurveyAppearance
key={idx}
type={template.questions[0].type}
question={template.questions[0].question}
appearance={{}}
surveyQuestionItem={template.questions[0] as SurveyQuestion}
onAppearanceChange={() => {}}
readOnly
/>
</div>
</div>
<span className="flex flex-wrap text-xs text-muted max-w-80 font-medium mt-3">
{template.description}
</span>
</div>
)
})}
</div>
</>
)
}
262 changes: 262 additions & 0 deletions frontend/src/scenes/surveys/constants.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
import { Link } from '@posthog/lemon-ui'
import { FeatureFlagFilters, Survey, SurveyQuestionType, SurveyType, SurveyUrlMatchType } from '~/types'

export const SURVEY_EVENT_NAME = 'survey sent'
export const SURVEY_RESPONSE_PROPERTY = '$survey_response'

export const SurveyQuestionLabel = {
[SurveyQuestionType.Open]: 'Open text',
[SurveyQuestionType.Rating]: 'Rating',
[SurveyQuestionType.Link]: 'Link',
[SurveyQuestionType.SingleChoice]: 'Single choice select',
[SurveyQuestionType.MultipleChoice]: 'Multiple choice select',
}

export const SurveyUrlMatchTypeLabels = {
[SurveyUrlMatchType.Contains]: '∋ contains',
[SurveyUrlMatchType.Regex]: '∼ matches regex',
[SurveyUrlMatchType.Exact]: '= equals',
}

export const defaultSurveyAppearance = {
backgroundColor: '#eeeded',
submitButtonText: 'Submit',
submitButtonColor: 'black',
ratingButtonColor: 'white',
ratingButtonActiveColor: 'black',
borderColor: '#c9c6c6',
placeholder: '',
whiteLabel: false,
displayThankYouMessage: true,
thankYouMessageHeader: 'Thank you for your feedback!',
position: 'right',
}

export const defaultSurveyFieldValues = {
[SurveyQuestionType.Open]: {
questions: [
{
type: SurveyQuestionType.Open,
question: 'Give us feedback on our product!',
description: '',
},
],
appearance: {
submitButtonText: 'Submit',
thankYouMessageHeader: 'Thank you for your feedback!',
},
},
[SurveyQuestionType.Link]: {
questions: [
{
type: SurveyQuestionType.Link,
question: 'Do you want to join our upcoming webinar?',
description: '',
},
],
appearance: {
submitButtonText: 'Register',
thankYouMessageHeader: 'Redirecting ...',
},
},
[SurveyQuestionType.Rating]: {
questions: [
{
type: SurveyQuestionType.Rating,
question: 'How likely are you to recommend us to a friend?',
description: '',
display: 'number',
scale: 10,
lowerBoundLabel: 'Unlikely',
upperBoundLabel: 'Very likely',
},
],
appearance: {
thankYouMessageHeader: 'Thank you for your feedback!',
},
},
[SurveyQuestionType.SingleChoice]: {
questions: [
{
type: SurveyQuestionType.SingleChoice,
question: 'Have you found this tutorial useful?',
description: '',
choices: ['Yes', 'No'],
},
],
appearance: {
submitButtonText: 'Submit',
thankYouMessageHeader: 'Thank you for your feedback!',
},
},
[SurveyQuestionType.MultipleChoice]: {
questions: [
{
type: SurveyQuestionType.MultipleChoice,
question: 'Which types of content would you like to see more of?',
description: '',
choices: ['Tutorials', 'Customer case studies', 'Product announcements'],
},
],
appearance: {
submitButtonText: 'Submit',
thankYouMessageHeader: 'Thank you for your feedback!',
},
},
}

export interface NewSurvey
extends Pick<
Survey,
| 'name'
| 'description'
| 'type'
| 'conditions'
| 'questions'
| 'start_date'
| 'end_date'
| 'linked_flag'
| 'targeting_flag'
| 'archived'
| 'appearance'
> {
id: 'new'
linked_flag_id: number | undefined
targeting_flag_filters: Pick<FeatureFlagFilters, 'groups'> | undefined
}

export const NEW_SURVEY: NewSurvey = {
id: 'new',
name: '',
description: '',
questions: [
{
type: SurveyQuestionType.Open,
question: defaultSurveyFieldValues[SurveyQuestionType.Open].questions[0].question,
description: defaultSurveyFieldValues[SurveyQuestionType.Open].questions[0].description,
},
],
type: SurveyType.Popover,
linked_flag_id: undefined,
targeting_flag_filters: undefined,
linked_flag: null,
targeting_flag: null,
start_date: null,
end_date: null,
conditions: null,
archived: false,
appearance: defaultSurveyAppearance,
}

export enum SurveyTemplateTypes {
Interview = 'User Interview',
NPS = 'Net Promoter Score (NPS)',
CSAT = 'Customer Satisfaction Score (CSAT)',
CES = 'Customer Effort Score (CES)',
CCR = 'Customer Churn Rate (CCR)',
Superhuman = 'Product Market Fit (Superhuman)',
}

export const defaultSurveyTemplates = [
{
type: SurveyTemplateTypes.Interview,
questions: [
{
type: SurveyQuestionType.Link,
question: 'Would you be interested in participating in a customer interview?',
description: 'We are looking for feedback on our product and would love to hear from you!',
link: 'https://calendly.com/',
},
],
description: (
<>
User interviews provide a more complete picture into your user's experience because you have the
opportunity to ask follow up questions. Find out how to conduct successful user interviews in{' '}
<Link to="https://posthog.com/blog/interview-snapshot-guide" targetBlankIcon target="_blank">
our guide here
</Link>
</>
),
},
{
type: SurveyTemplateTypes.NPS,
questions: [
{
type: SurveyQuestionType.Rating,
question: 'How likely are you to recommend us to a friend?',
description: '',
display: 'number',
scale: 10,
lowerBoundLabel: 'Unlikely',
upperBoundLabel: 'Very likely',
},
],
description:
"NPS is primarily a long-term, relational metric that measures how likely a customer is to recommend your product or brand to others. Think of it as a pulse check on your customer's overall satisfaction with the product as a whole.",
},
{
type: SurveyTemplateTypes.Superhuman,
questions: [
{
type: SurveyQuestionType.SingleChoice,
question: 'How would you feel if you could no longer use PostHog?',
choices: ['Not disappointed', 'Somewhat disappointed', 'Very disappointed'],
},
],
description:
"Ask your users how they would feel if they could no longer use your product. If 40% of your users say they would be 'very disappointed', you've found product market fit.",
},
{
type: SurveyTemplateTypes.CSAT,
questions: [
{
type: SurveyQuestionType.Rating,
question: 'How satisfied are you with PostHog surveys?',
description: '',
display: 'emoji',
scale: 5,
lowerBoundLabel: 'Very dissatisfied',
upperBoundLabel: 'Very satisfied',
},
],
description:
'CSAT surveys are a great way to measure customer satisfaction for a particular interaction or feature with the product. They are short and easy to answer, making them a great way to get feedback from your users for specific product improvements.',
},
{
type: SurveyTemplateTypes.CES,
questions: [
{
type: SurveyQuestionType.Rating,
question: 'How easy was it to use our product?',
description: '',
display: 'emoji',
scale: 5,
lowerBoundLabel: 'Very difficult',
upperBoundLabel: 'Very easy',
},
],
description:
'CES surveys are used to measure how easy a product or service was to use. Customer effort is a good indicator of customer loyalty, and can be used alongside churn surveys to understand if customer effort impacts churn rates.',
},
{
type: SurveyTemplateTypes.CCR,
questions: [
{
type: SurveyQuestionType.MultipleChoice,
question: "We're sorry to see you go. What's your reason for unsubscribing?",
choices: [
'I no longer need the product',
'I found a better product',
'I found the product too difficult to use',
'Other',
],
},
{
type: SurveyQuestionType.Open,
question: "Anything else you'd like to share?",
},
],
description:
"Customer churn can be expensive. Acquiring new customers is often more expensive than retaining existing ones, so it's important to understand why your customers are leaving.",
},
]
16 changes: 16 additions & 0 deletions frontend/src/scenes/surveys/surveyTemplatesLogic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { actions, kea, path } from 'kea'
import { surveyTemplatesLogicType } from './surveyTemplatesLogicType'
import { actionToUrl, router } from 'kea-router'
import { urls } from 'scenes/urls'

export const surveyTemplatesLogic = kea<surveyTemplatesLogicType>([
path(['scenes', 'surveys', 'surveyTemplatesLogic']),
actions({
openSurveyTemplate: (template: any) => ({ template }),
}),
actionToUrl({
openSurveyTemplate: () => {
router.actions.push(urls.survey('new'))
},
}),
])

0 comments on commit 343a5a4

Please sign in to comment.