diff --git a/.env.example b/.env.example index 07a74e21e..57cf22a7a 100644 --- a/.env.example +++ b/.env.example @@ -52,9 +52,6 @@ NEXT_PRIVATE_OPEN_AI_ORG= # Keys used to connect to Claude (only needed for ai development) ANTHROPIC_API_KEY= -# already preset. -NEXT_PUBLIC_ENV=development - # secret used to authenticate cron jobs, not needed for dev CRON_SECRET= diff --git a/src/actions/user/account/create-coupon.ts b/src/actions/user/account/create-coupon.ts index 1277fe08d..cc530c425 100644 --- a/src/actions/user/account/create-coupon.ts +++ b/src/actions/user/account/create-coupon.ts @@ -7,9 +7,6 @@ import { getUser } from '../authed/get-user'; * Upon user signup, we create a 60% off their first 3 three * months of TechBlitz premium. * Eligible for 72 hours after signup. - * - * We are only hitting this action from within other actions, - * so we can pass the userUid as a parameter. */ export const createCouponOnSignup = async () => { const user = await getUser(); diff --git a/src/actions/user/authed/get-user.ts b/src/actions/user/authed/get-user.ts index 85207b727..b5d3b940f 100644 --- a/src/actions/user/authed/get-user.ts +++ b/src/actions/user/authed/get-user.ts @@ -5,7 +5,7 @@ import type { UserRecord } from '@/types'; import { revalidateTag } from 'next/cache'; /** - * Get the user from the server - used in api routes, server componets & server actions + * Get the user from the server - used in api routes, server components & server actions * * @returns User | null */ diff --git a/src/app/(app)/(default_layout)/(roadmaps)/roadmaps/[slug]/page.tsx b/src/app/(app)/(default_layout)/(roadmaps)/roadmaps/[slug]/page.tsx index ca11a588d..639f602e8 100644 --- a/src/app/(app)/(default_layout)/(roadmaps)/roadmaps/[slug]/page.tsx +++ b/src/app/(app)/(default_layout)/(roadmaps)/roadmaps/[slug]/page.tsx @@ -231,7 +231,7 @@ export default async function RoadmapPage({ params }: { params: { slug: string } chip={} />
-
+
}> ); -export default async function ExploreQuestionsPage() { +export default async function ExploreQuestionsPage({ + searchParams, +}: { + searchParams: { [key: string]: string | string[] | undefined }; +}) { + const user = await useUserServer(); + // used to determine if the onboarding tour guide needs to be shown. + const { onboarding } = searchParams; + // create json ld const jsonLd: WebPageJsonLd = { '@context': 'https://schema.org', @@ -109,35 +122,51 @@ export default async function ExploreQuestionsPage() { type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} /> -
- -
-
- {categories.map((category) => ( -
-
-

{category}

- {studyPathsByCategory[category][0].categoryToolTip && ( - - - - - - {studyPathsByCategory[category][0].categoryToolTip} - - - )} -
-
- {studyPathsByCategory[category].map((studyPath) => ( - - ))} -
+ + + +
+ +
+
+ {categories.map((category) => ( +
+
+

{category}

+ {studyPathsByCategory[category][0].categoryToolTip && ( + + + + + + {studyPathsByCategory[category][0].categoryToolTip} + + + )} +
+
+ {studyPathsByCategory[category].map((studyPath) => ( + + ))} +
+
+ ))}
- ))} +
-
-
+ + ); } diff --git a/src/app/(app)/layout.tsx b/src/app/(app)/layout.tsx index 2c56c6888..491d67e8f 100644 --- a/src/app/(app)/layout.tsx +++ b/src/app/(app)/layout.tsx @@ -18,7 +18,7 @@ import { getSuggestions } from '@/utils/data/questions/get-suggestions'; // onboarding import { Onborda, OnbordaProvider } from 'onborda'; import { TourCard } from '@/components/app/shared/question/tour-card'; -import { steps } from '@/lib/onborda'; +import { questionPageSteps } from '@/lib/onborda'; export async function generateMetadata() { return createMetadata({ @@ -39,7 +39,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo
diff --git a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-cheat-sheet/regular-expression-cheat-sheet/page.tsx b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-cheat-sheet/regular-expression-cheat-sheet/page.tsx index 0686610d4..7a509e14d 100644 --- a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-cheat-sheet/regular-expression-cheat-sheet/page.tsx +++ b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-cheat-sheet/regular-expression-cheat-sheet/page.tsx @@ -121,10 +121,6 @@ export default async function JavascriptRegularExpressionCheatSheet({ params }:
diff --git a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-coding-interview-questions-and-answers/javascript-coding-test/page.tsx b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-coding-interview-questions-and-answers/javascript-coding-test/page.tsx index f100d0268..167ff1c8f 100644 --- a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-coding-interview-questions-and-answers/javascript-coding-test/page.tsx +++ b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-coding-interview-questions-and-answers/javascript-coding-test/page.tsx @@ -121,10 +121,6 @@ export default async function JavascriptCodingTest({ params }: BlogPostParams) {
diff --git a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-coding-interview-questions-and-answers/javascript-interview-questions-for-senior-developers/page.tsx b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-coding-interview-questions-and-answers/javascript-interview-questions-for-senior-developers/page.tsx index de8171e1e..7e94146b1 100644 --- a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-coding-interview-questions-and-answers/javascript-interview-questions-for-senior-developers/page.tsx +++ b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-coding-interview-questions-and-answers/javascript-interview-questions-for-senior-developers/page.tsx @@ -127,10 +127,6 @@ export default async function JavascriptInterviewQuestionsForSeniorDevelopers({
diff --git a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/how-does-javascript-work/page.tsx b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/how-does-javascript-work/page.tsx index 8e42bb1bc..bafe23a35 100644 --- a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/how-does-javascript-work/page.tsx +++ b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/how-does-javascript-work/page.tsx @@ -121,10 +121,6 @@ export default async function HowDoesJavascriptWork({ params }: BlogPostParams)
diff --git a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/how-to-write-a-function-in-javascript/page.tsx b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/how-to-write-a-function-in-javascript/page.tsx index ba044ec4c..026947de3 100644 --- a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/how-to-write-a-function-in-javascript/page.tsx +++ b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/how-to-write-a-function-in-javascript/page.tsx @@ -121,10 +121,6 @@ export default async function HowToWriteAFunctionInJavascript({ params }: BlogPo diff --git a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/how-to-write-javascript/page.tsx b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/how-to-write-javascript/page.tsx index 5bca3df1d..b0c646afa 100644 --- a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/how-to-write-javascript/page.tsx +++ b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/how-to-write-javascript/page.tsx @@ -121,10 +121,6 @@ export default async function HowToWriteJavascript({ params }: BlogPostParams) { diff --git a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/html-conditional-statement/page.tsx b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/html-conditional-statement/page.tsx index 868ba7e63..b1f20a5d1 100644 --- a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/html-conditional-statement/page.tsx +++ b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/html-conditional-statement/page.tsx @@ -121,10 +121,6 @@ export default async function HtmlConditionalStatement({ params }: BlogPostParam diff --git a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/javascript-conditionals/page.tsx b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/javascript-conditionals/page.tsx index dc667d8cf..ec3edc1da 100644 --- a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/javascript-conditionals/page.tsx +++ b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/javascript-conditionals/page.tsx @@ -121,10 +121,6 @@ export default async function JavaScriptConditionals({ params }: BlogPostParams) diff --git a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/javascript-format-strings-with-variables/page.tsx b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/javascript-format-strings-with-variables/page.tsx index be04a2343..7dcd73586 100644 --- a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/javascript-format-strings-with-variables/page.tsx +++ b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/javascript-format-strings-with-variables/page.tsx @@ -121,10 +121,6 @@ export default async function JavaScriptFormatStringsWithVariables({ params }: B diff --git a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/javascript-naming-conventions/page.tsx b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/javascript-naming-conventions/page.tsx index 558bb29d7..74b7b020f 100644 --- a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/javascript-naming-conventions/page.tsx +++ b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/javascript-naming-conventions/page.tsx @@ -121,10 +121,6 @@ export default async function JavaScriptNamingConventions({ params }: BlogPostPa diff --git a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/javascript-nested-conditionals/page.tsx b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/javascript-nested-conditionals/page.tsx index 14e72826a..521e9b53c 100644 --- a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/javascript-nested-conditionals/page.tsx +++ b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/javascript-nested-conditionals/page.tsx @@ -121,10 +121,6 @@ export default async function JavaScriptNestedConditionals({ params }: BlogPostP diff --git a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/loose-vs-strict-equality-in-javascript/page.tsx b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/loose-vs-strict-equality-in-javascript/page.tsx index c1645eac0..b0071e61f 100644 --- a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/loose-vs-strict-equality-in-javascript/page.tsx +++ b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/loose-vs-strict-equality-in-javascript/page.tsx @@ -121,10 +121,6 @@ export default async function LooseVsStrictEqualityInJavascript({ params }: Blog diff --git a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/primitive-types-in-javascript/page.tsx b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/primitive-types-in-javascript/page.tsx index 6d5b31902..94725cddf 100644 --- a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/primitive-types-in-javascript/page.tsx +++ b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-fundamentals/primitive-types-in-javascript/page.tsx @@ -121,10 +121,6 @@ export default async function PrimitiveTypesInJavascript({ params }: BlogPostPar diff --git a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-projects-for-beginners/programming-challenges-for-beginners/page.tsx b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-projects-for-beginners/programming-challenges-for-beginners/page.tsx index 2a3ac2560..0ecd8f245 100644 --- a/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-projects-for-beginners/programming-challenges-for-beginners/page.tsx +++ b/src/app/(marketing)/(landing-pages)/(pillar-pages)/javascript-projects-for-beginners/programming-challenges-for-beginners/page.tsx @@ -123,10 +123,6 @@ export default async function JavascriptProgrammingChallengesForBeginners({ diff --git a/src/app/(marketing)/(landing-pages)/coding-roadmap/page.tsx b/src/app/(marketing)/(landing-pages)/coding-roadmap/page.tsx index 6d464414c..81f963182 100644 --- a/src/app/(marketing)/(landing-pages)/coding-roadmap/page.tsx +++ b/src/app/(marketing)/(landing-pages)/coding-roadmap/page.tsx @@ -274,10 +274,6 @@ export default function CodingRoadmapPage() { diff --git a/src/app/(marketing)/(landing-pages)/javascript-coding-questions/page.tsx b/src/app/(marketing)/(landing-pages)/javascript-coding-questions/page.tsx index 2892f6cde..e5ccfc75a 100644 --- a/src/app/(marketing)/(landing-pages)/javascript-coding-questions/page.tsx +++ b/src/app/(marketing)/(landing-pages)/javascript-coding-questions/page.tsx @@ -272,10 +272,6 @@ export default function JavascriptCodingQuestionsPage() { diff --git a/src/app/(marketing)/(landing-pages)/javascript-for-beginners/page.tsx b/src/app/(marketing)/(landing-pages)/javascript-for-beginners/page.tsx index c95fde14b..4da3ca2b5 100644 --- a/src/app/(marketing)/(landing-pages)/javascript-for-beginners/page.tsx +++ b/src/app/(marketing)/(landing-pages)/javascript-for-beginners/page.tsx @@ -255,10 +255,6 @@ export default function JavascriptForBeginnersPage() { diff --git a/src/app/(marketing)/(landing-pages)/javascript-roadmap/page.tsx b/src/app/(marketing)/(landing-pages)/javascript-roadmap/page.tsx index d53a8534a..313f0b01e 100644 --- a/src/app/(marketing)/(landing-pages)/javascript-roadmap/page.tsx +++ b/src/app/(marketing)/(landing-pages)/javascript-roadmap/page.tsx @@ -274,10 +274,6 @@ export default function JavascriptRoadmapPage() { diff --git a/src/app/(marketing)/(landing-pages)/react-roadmap/page.tsx b/src/app/(marketing)/(landing-pages)/react-roadmap/page.tsx index afd4376f7..81936bf48 100644 --- a/src/app/(marketing)/(landing-pages)/react-roadmap/page.tsx +++ b/src/app/(marketing)/(landing-pages)/react-roadmap/page.tsx @@ -285,10 +285,6 @@ export default function ReactRoadmapPage() { diff --git a/src/app/(marketing)/blog/[slug]/page.tsx b/src/app/(marketing)/blog/[slug]/page.tsx index c1c885d17..00cc2eba8 100644 --- a/src/app/(marketing)/blog/[slug]/page.tsx +++ b/src/app/(marketing)/blog/[slug]/page.tsx @@ -143,10 +143,6 @@ export default async function BlogPost({ params }: BlogPostParams) { diff --git a/src/app/(marketing)/features/leaderboard/page.tsx b/src/app/(marketing)/features/leaderboard/page.tsx index 57c716819..6f6c7234b 100644 --- a/src/app/(marketing)/features/leaderboard/page.tsx +++ b/src/app/(marketing)/features/leaderboard/page.tsx @@ -252,10 +252,6 @@ export default function LeaderboardPage() { diff --git a/src/app/(marketing)/features/roadmap/page.tsx b/src/app/(marketing)/features/roadmap/page.tsx index bf038a006..dc76d3fb2 100644 --- a/src/app/(marketing)/features/roadmap/page.tsx +++ b/src/app/(marketing)/features/roadmap/page.tsx @@ -246,10 +246,6 @@ export default function FeatureDailyQuestionPage() { diff --git a/src/app/(marketing)/features/statistics/page.tsx b/src/app/(marketing)/features/statistics/page.tsx index 3af799d5f..573922d83 100644 --- a/src/app/(marketing)/features/statistics/page.tsx +++ b/src/app/(marketing)/features/statistics/page.tsx @@ -139,13 +139,7 @@ export default function StatisticsPage() { title="Tracking coding progress made simple." items={featureShowcaseItems} /> - + ); diff --git a/src/app/(no_nav)/onboarding/page.tsx b/src/app/(no_nav)/onboarding/page.tsx index c27a9644e..ee34ff9a2 100644 --- a/src/app/(no_nav)/onboarding/page.tsx +++ b/src/app/(no_nav)/onboarding/page.tsx @@ -1,9 +1,12 @@ +import Link from 'next/link'; + +import { redirect } from 'next/navigation'; + import Logo from '@/components/ui/logo'; import StarsBackground from '@/components/ui/stars-background'; +import OnboardingForm from '@/components/app/onboarding/onboarding-form'; -import Link from 'next/link'; import { UserOnboardingContextProvider } from '@/contexts/onboarding-context'; -import OnboardingForm from '@/components/app/onboarding/onboarding-form'; import { useUserServer } from '@/hooks/use-user-server'; export const metadata = { @@ -11,7 +14,12 @@ export const metadata = { }; export default async function OnboardingPage() { - const [user] = await Promise.all([useUserServer()]); + const user = await useUserServer(); + + // throw the user back to login + if (!user) { + return redirect('/login'); + } return (
@@ -21,9 +29,7 @@ export default async function OnboardingPage() { -
- -
+
diff --git a/src/app/(questions)/question/[slug]/layout.tsx b/src/app/(questions)/question/[slug]/layout.tsx index a75de462a..148ca035e 100644 --- a/src/app/(questions)/question/[slug]/layout.tsx +++ b/src/app/(questions)/question/[slug]/layout.tsx @@ -7,23 +7,23 @@ import { redirect } from 'next/navigation'; import { QuestionSingleContextProvider } from '@/contexts/question-single-context'; // Actions & Utils -import { createMetadata, getQuestionEducationLevel } from '@/utils/seo'; -import { capitalise, getBaseUrl } from '@/utils'; +import { createMetadata } from '@/utils/seo'; +import { capitalise } from '@/utils'; import { getQuestion } from '@/utils/data/questions/get'; import { getUser } from '@/actions/user/authed/get-user'; import { getRelatedQuestions } from '@/utils/data/questions/get-related'; import { getUserAnswer } from '@/utils/data/answers/get-user-answer'; import { getNextAndPreviousQuestion } from '@/utils/data/questions/question-navigation'; -import type { QuizJsonLd } from '@/types'; import { userHasAnsweredAnyQuestion } from '@/utils/data/questions/user-has-answered-any-question'; // Components import { Onborda, OnbordaProvider } from 'onborda'; -import { steps } from '@/lib/onborda'; import { TourCard } from '@/components/app/shared/question/tour-card'; import { getSuggestions } from '@/utils/data/questions/get-suggestions'; import QuestionPageHeader from '@/components/app/layout/question-single/page-header'; +import { questionPageSteps } from '@/lib/onborda'; + // Lazy Components const PremiumQuestionDeniedAccess = lazy( () => import('@/components/app/questions/premium-question-denied-access') @@ -73,55 +73,6 @@ export default async function QuestionUidLayout({ return redirect('/coding-challenges'); } - const defaultQuestionDescription = `Practice ${capitalise( - question?.title || question?.slug?.replace(/-/g, ' ') || 'Coding Question' - )} and improve your coding skills with interactive challenges on TechBlitz`; - - const description = - question?.questionType === 'SIMPLE_MULTIPLE_CHOICE' - ? question?.afterQuestionInfo || defaultQuestionDescription - : defaultQuestionDescription; - - // create json ld - const jsonLd: QuizJsonLd = { - '@context': 'https://schema.org', - '@type': 'Quiz', - name: capitalise(question?.slug?.replace(/-/g, ' ') || ''), - description, - url: `${getBaseUrl()}/question/${slug}`, - educationLevel: getQuestionEducationLevel(question?.difficulty || 'EASY'), - educationalUse: 'practice', - learningResourceType: ['quiz', 'learning activity'], - creator: { '@type': 'Organization', name: 'TechBlitz', url: getBaseUrl() }, - assesses: ['coding'], - dateCreated: question?.createdAt.toISOString() || '', - dateModified: question?.updatedAt.toISOString() || '', - datePublished: question?.questionDate || question?.createdAt.toISOString() || '', - headline: question?.question || '', - interactivityType: 'mixed', - isAccessibleForFree: true, - isFamilyFriendly: true, - teaches: 'coding', - potentialAction: { - '@type': 'SearchAction', - target: `${getBaseUrl()}/search?q={search_term_string}`, - 'query-input': 'required name=search_term_string', - }, - breadcrumb: { - '@type': 'BreadcrumbList', - itemListElement: [ - { '@type': 'ListItem', position: 1, name: 'Home', item: `${getBaseUrl()}` }, - { '@type': 'ListItem', position: 2, name: 'Questions', item: `${getBaseUrl()}/questions` }, - { - '@type': 'ListItem', - position: 3, - name: question.slug, - item: `${getBaseUrl()}/question/${slug}`, - }, - ], - }, - }; - // not resolving the promises here - passing the promises and // using 'use' to resolve them in their own components const nextAndPreviousQuestion = getNextAndPreviousQuestion(question.uid); // cached @@ -138,13 +89,9 @@ export default async function QuestionUidLayout({ return ( <> -