-
-
Save joelhooks/e6315053ef3259771ad65c4cbbf3d861 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {publicProcedure, router} from '@skillrecordings/skill-lesson' | |
import {isEmpty} from 'lodash' | |
import {getToken} from 'next-auth/jwt' | |
import {getSubscriberFromCookie} from '@skillrecordings/skill-lesson/utils/ck-subscriber-from-cookie' | |
export const offerRouter = router({ | |
getNextOffer: publicProcedure.query(async ({ctx}) => { | |
const token = await getToken({req: ctx.req}) | |
const subscriber = await getSubscriberFromCookie(ctx.req) | |
console.log({subscriber}) | |
if (subscriber && subscriber.fields) { | |
// User hasn't started any tutorials | |
// - If the user hasn't started a tutorial, display an attractive and eye catching "banner" for the TypeScript Beginner's tutorial | |
const HAS_NOT_STARTED_ANY_TUTORIAL = checkStartedKeysNull( | |
subscriber.fields, | |
) | |
console.log({HAS_NOT_STARTED_ANY_TUTORIAL}) | |
// User has started a tutorial | |
// - Show them a "continue" variant of the above | |
const startedTutorials = orderStartedByDate(subscriber.fields) | |
const HAS_STARTED_TUTORIAL = !isEmpty(startedTutorials) | |
console.log({HAS_STARTED_TUTORIAL}) | |
// User has finished the Basics Tutorial | |
// - Show them a CTA for the Zod tutorial, show continue as appropriate | |
const HAS_COMPLETED_BEGINNERS_TYPESCRIPT_TUTORIAL = | |
hasCompletedBeginnersTypeScriptTutorial(subscriber.fields) | |
console.log({HAS_COMPLETED_BEGINNERS_TYPESCRIPT_TUTORIAL}) | |
// User has finished both tutorials and hasn't bought the Core Volume | |
// - Show a CTA for the core volume | |
const completedTutorials = getCompletedTutorials(subscriber.fields) | |
const HAS_COMPLETED_TWO_OR_MORE_TUTORIALS = completedTutorials.length > 1 | |
console.log({HAS_COMPLETED_TWO_OR_MORE_TUTORIALS}) | |
// User has purchased Core Volume, but hasn't started yet | |
// - Show them a get started CTA | |
const HAS_PURCHASED_CORE_VOLUME = hasPurchasedCoreVolume( | |
subscriber.fields, | |
) | |
console.log({HAS_PURCHASED_CORE_VOLUME}) | |
// User has purchased the Core Volume and made progress | |
// - Show them a "continue" CTA for the next step | |
if (HAS_PURCHASED_CORE_VOLUME && token && token.sub) { | |
// TODO: Ideally we would call a "product progress" here | |
} | |
const getOffer = () => { | |
let offer = {} | |
switch (true) { | |
case HAS_NOT_STARTED_ANY_TUTORIAL: | |
offer = { | |
title: "Beginner's TypeScript", | |
path: '/tutorials/beginners-typescript', | |
cta: 'Get started with TypeScript', | |
} | |
break | |
case HAS_STARTED_TUTORIAL: | |
offer = { | |
title: "Beginner's TypeScript", | |
path: '/tutorials/beginners-typescript', | |
cta: 'Continue learning', | |
} | |
break | |
case HAS_COMPLETED_BEGINNERS_TYPESCRIPT_TUTORIAL: | |
offer = { | |
title: | |
'Zod Tutorial — TypeScript-first schema declaration and validation library', | |
path: '/tutorials/zod', | |
cta: 'Learn Zod', | |
} | |
break | |
case HAS_COMPLETED_TWO_OR_MORE_TUTORIALS: | |
offer = { | |
title: 'Professional TypeScript Workshops', | |
path: '/workshops', | |
cta: 'Become a TypeScript Wizard', | |
} | |
break | |
case HAS_PURCHASED_CORE_VOLUME: | |
offer = {} | |
break | |
default: | |
offer = {} | |
} | |
return offer | |
} | |
const offer = getOffer() | |
return { | |
offer, | |
startedTutorials, | |
HAS_STARTED_TUTORIAL, | |
completedBeginnersTypeScriptTutorial: | |
HAS_COMPLETED_BEGINNERS_TYPESCRIPT_TUTORIAL, | |
completedTwoOrMoreTutorials: HAS_COMPLETED_TWO_OR_MORE_TUTORIALS, | |
purchasedCoreVolume: HAS_PURCHASED_CORE_VOLUME, | |
} | |
} | |
}), | |
}) | |
type Fields = {[key: string]: string | null} | |
function checkStartedKeysNull(fields: Fields) { | |
for (const key in fields) { | |
if (key.startsWith('started_') && fields[key] !== null) { | |
return false | |
} | |
} | |
return true | |
} | |
function orderStartedByDate(obj: Fields): Fields { | |
const startedKeys = Object.keys(obj) | |
.filter((key: string) => key.startsWith('started_')) | |
.filter((key: string) => obj[key] !== null) | |
const sortedKeys = startedKeys.sort((a: string, b: string) => { | |
const dateA = obj[a] | |
const dateB = obj[b] | |
if (dateA && dateB && Date.parse(dateA) && Date.parse(dateB)) { | |
return new Date(dateB).getTime() - new Date(dateA).getTime() | |
} | |
return 0 | |
}) | |
const sortedObj: Fields = {} | |
sortedKeys.forEach((key) => (sortedObj[key] = obj[key])) | |
return sortedObj | |
} | |
function hasCompletedBeginnersTypeScriptTutorial(fields: Fields): boolean { | |
for (let key in fields) { | |
if ( | |
key.includes('completed_on') && | |
key.includes('beginners_typescript') && | |
fields[key] !== null | |
) { | |
return true | |
} | |
} | |
return false | |
} | |
function getCompletedTutorials(fields: Fields) { | |
const completedOnItems = [] | |
for (let key in fields) { | |
if (key.includes('completed_on')) { | |
completedOnItems.push(key) | |
} | |
} | |
return completedOnItems | |
} | |
function hasPurchasedCoreVolume(fields: Fields) { | |
for (let key in fields) { | |
if (key.includes('purchased_core_volume_on')) { | |
return true | |
} | |
} | |
return false | |
} | |
// Testing data | |
const fields = { | |
devs_on_team: 'skip', | |
do_not_survey: 'true', | |
is_developer: null, | |
job_title: null, | |
last_name: 'Holik', | |
last_surveyed_on: '2023-01-05 15:41:00 GMT+0', | |
level: 'advanced-beginner', | |
purchased_core_volume_on: null, | |
purchased_workshop_series_01: null, | |
read_dont_use_function_keyword_in_typescript_on: '2022-12-14', | |
read_mental_model_for_typescript_generics_on: null, | |
read_rewriting_typescript_in_rust_on: null, | |
read_structure_of_a_typescript_error_on: null, | |
read_when_should_you_use_zod_on: null, | |
read_writing_string_replace_in_typescript_on: '2022-12-14', | |
started_beginners_type_script_tutorial: '2023-02-15', | |
started_type_transformations_workshop: null, | |
started_zod_tutorial: '2022-10-07', | |
ts_at_work: 'true', | |
welcomed_on: null, | |
years_developer: null, | |
} | |
const completedBeginnersTypeScriptTutorial = { | |
started_beginners_type_script_tutorial: '2023-02-15', | |
} | |
const notCompletedBeginnersTypeScriptTutorial = { | |
started_beginners_type_script_tutorial: null, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment