Skip to content

messages for platform winding down, updates to payments buttons to support free content for all content but still track payments#85

Merged
AustinKelsay merged 1 commit intomainfrom
feature/wind-down-for-new-platform
Sep 24, 2025
Merged

messages for platform winding down, updates to payments buttons to support free content for all content but still track payments#85
AustinKelsay merged 1 commit intomainfrom
feature/wind-down-for-new-platform

Conversation

@AustinKelsay
Copy link
Copy Markdown
Owner

@AustinKelsay AustinKelsay commented Sep 24, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a PromoFreeBadge and site-wide promotional “Free” access flow for courses and resources.
    • Added a homepage announcement banner highlighting the limited-time promo.
  • UI/UX

    • Unified “Free” status display with green indicators and gift/check icons; consolidated price badges across templates and detail views.
  • Bug Fixes

    • Improved purchase validation for amount inputs; ensured loading/invoice states reset; added sign-in guard before payment.
  • Documentation

    • Added AGENTS.md with project guidelines.
  • Chores

    • Updated authorized author list.

…pport free content for all content but still track payments
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Sep 24, 2025

Walkthrough

Introduces a promo-pricing system: adds constants and a PromoFreeBadge component, updates multiple UI surfaces to display promo “Free” messaging, adds auth guard and a promo-free short-circuit in payment buttons, validates amountPaid in the purchase API, adds an announcement banner on the home page, updates authorPubkeys, and adds AGENTS.md.

Changes

Cohort / File(s) Summary
Docs
AGENTS.md
New repository guideline document describing structure, commands, coding/testing practices, and security notes.
Promo pricing: constants & badge component
src/constants/promoPricing.js, src/components/pricing/PromoFreeBadge.js
Adds promo constants (free price = 0, message, tooltip position) and a reusable PromoFreeBadge component with tooltip, optional label/price, and responsive behavior.
Payment buttons: promo short-circuit + auth guard
src/components/bitcoinConnect/CoursePaymentButton.js, src/components/bitcoinConnect/ResourcePaymentButton.js
Adds sign-in enforcement, promo-free path that bypasses invoice flow, success toast, sets amountPaid to promo constant, ensures loading cleanup, and clears invoice after dialog. Updates UI to show a Free action with PromoFreeBadge.
API validation
src/pages/api/purchase/resource.js
Strengthens amountPaid validation: explicit undefined/null checks, integer parsing, NaN rejection; uses parsed amount in DB update.
Content templates: unified promo badge
src/components/content/carousels/templates/CombinedTemplate.js, .../CourseTemplate.js, .../DocumentTemplate.js, .../VideoTemplate.js
Replaces conditional price/free displays with a single Message containing PromoFreeBadge and adjusted flex layout.
Content details: promo indicators
src/components/content/combined/CombinedDetails.js, src/components/content/courses/details/CourseDetails.js, .../DesktopCourseDetails.js, .../MobileCourseDetails.js, src/components/content/documents/DocumentDetails.js, src/components/content/videos/VideoDetails.js
Replaces various paid/tooltip buttons and locks with check/gift icon plus PromoFreeBadge and PROMO_PRICING_MESSAGE; standardizes green-themed indicators across scenarios.
Dropdown item
src/components/content/dropdowns/ContentDropdownItem.js
Consolidates price/free indicator into a success Message with PromoFreeBadge; selection logic unchanged.
Home announcement
src/pages/index.js
Adds top-of-page promo announcement Message with a “Limited” Badge and scoped styles.
Config
src/config/appConfig.js
Adds a new author public key to authorPubkeys array.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant UI as UI Button
  participant Auth as Auth Session
  participant Promo as Promo Constants
  participant Pay as Invoice/Payment Dialog
  participant API as POST /api/purchase/resource

  User->>UI: Click Purchase
  UI->>Auth: Check session
  alt Not signed in
    UI->>User: Toast: Sign in required
    UI->>User: Redirect /auth/signin
  else Signed in
    UI->>Promo: Read PROMO_FREE_PRICE_SATS
    alt Promo free (0 sats)
      UI->>UI: handlePaymentSuccess(preimage="promo-free", amount=0)
      UI->>User: Toast: Access granted (promo)
    else Normal pricing
      UI->>Pay: fetchInvoice + open dialog
      User-->>Pay: Complete/Cancel
      alt Success
        Pay->>API: Record purchase (amountPaid)
        API-->>Pay: 200 OK
        Pay->>UI: Payment success/preimage
        UI->>User: Toast: Access granted
      else Failure/Cancel
        Pay->>UI: Close dialog
      end
      UI->>UI: Clear invoice state
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Refactor/subscriptions #75 — Touches the same payment components (CoursePaymentButton, ResourcePaymentButton), indicating related payment-flow adjustments.
  • Refactor/course and lesson pages #64 — Modifies the same content detail components (CombinedDetails, CourseDetails, Desktop/Mobile details, DocumentDetails, VideoDetails), overlapping UI paths updated here.
  • Refactor/layout and sidebar #48 — Overlaps in appConfig.js (authorPubkeys) and ContentDropdownItem.js, suggesting related configuration/UI changes.

Poem

A bunny taps “Buy,” but hears: “It’s free!”
A badge blinks green, as bright as can be.
Tooltips whisper, “Promo time’s here,”
Locks turn to gifts, spreading good cheer.
I thump my paws—code neat as a tree,
For now we nibble—zero-sat fee! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title accurately summarizes the two main changes: adding winding-down/messaging and updating payment buttons to make content free while still tracking payments; this aligns with the added promo messaging/constants, PromoFreeBadge, banner UI, and payment-button logic changes in the diff. It is specific and directly reflects the primary intent of the PR without being generic or off-topic.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/wind-down-for-new-platform

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


Comment @coderabbitai help to get the list of available commands and usage tips.

@vercel
Copy link
Copy Markdown

vercel bot commented Sep 24, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
plebdevs Ready Ready Preview Comment Sep 24, 2025 2:20pm

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the final PR Bugbot will review for you during this billing cycle

Your free Bugbot reviews will reset on October 1

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.


if (PROMO_FREE_PRICE_SATS === 0) {
await handlePaymentSuccess({ paid: true, preimage: 'promo-free-course' });
showToast('success', 'Free Course Access', PROMO_PRICING_MESSAGE);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Promo Pricing Overwrites Discount Codes

The new promo pricing logic (lines 83-87) bypasses existing discount code functionality, leading to a confusing UX where discounts appear applied but are ignored. This also removes the check for 0-satoshi discounted amounts, which could cause issues when fetching invoices if a discount would make the course free.

Fix in Cursor Fix in Web

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/config/appConfig.js (1)

30-38: Server secrets in shared config risk browser exposure

This module is imported widely; in Next.js anything imported by client bundles risks leaking values or causing undefined-at-runtime differences. Keep LND credentials strictly server-only.

Proposed approach:

  • Move customLightningAddresses (or just the sensitive fields: invoiceMacaroon, lndHost, lndPort, lndCert) into a server-only module (e.g., src/server/config/lndConfig.ts) that is imported only from API routes/server code.
  • Keep a client-safe shape in appConfig (names, flags) without env references.

Example diff to remove env usage from client config:

   customLightningAddresses: [
     {
       // todo remove need for lowercase
       // name will appear as name@plebdevs.com (lowercase)
       name: 'austin',
       // If enabled, zaps are enabled
       allowsNostr: true,
       // make you're own lud06 metadata description
       description: "Austin's Lightning Address",
       // millisats
       maxSendable: 10000000000,
       // millisats
       minSendable: 1000,
-      // Your LND invoice macaroon
-      invoiceMacaroon: process.env.LND_MACAROON,
+      // server-only: invoiceMacaroon configured in server code
       // your LND TLS certificate (may be optional depending on your LND configuration)
       lndCert: '',
-      // your LND host (do not include https:// or port)
-      lndHost: process.env.LND_HOST,
-      // your LND REST API port (default is 8080)
-      lndPort: '8080',
+      // server-only: lndHost/lndPort configured in server code
     },
src/components/bitcoinConnect/CoursePaymentButton.js (1)

250-260: Fix payment dialog title to reflect discounted amount

Title shows the full amount even when a discount is applied.

Use a computed value:

// near render
const payableAmount = discountApplied ? calculateDiscount(amount).discountedAmount : amount;
...
<Payment
  invoice={invoice.paymentRequest}
  onPaid={handlePaymentSuccess}
  paymentMethods="all"
  title={`Pay ${payableAmount} sats`}
/>
src/components/content/documents/DocumentDetails.js (1)

143-153: ReferenceError at runtime: Buffer is not imported

Buffer.from(...) is used but Buffer isn’t imported in this file. This will throw in the browser.

Add the import near the other imports:

+import { Buffer } from 'buffer';
🧹 Nitpick comments (19)
AGENTS.md (1)

6-14: Add runtime/tooling versions and workflow tips

Include Node.js/PNPM versions (engines), Next.js/Prisma versions, and a note about pre-commit hooks (lint/prettier) to reduce CI churn.

Apply this diff to add a Versions section:

 ## Build, Test, and Development Commands
 Install dependencies once with `npm install`. Use `npm run dev` for the hot-reloading Next.js server, or `docker compose up --build` when the Postgres service is required. Apply schema updates with `npx prisma migrate dev` and regenerate clients via `npx prisma generate` (also run automatically on `postinstall`). Before shipping, execute `npm run build` followed by `npm run start` to verify the production bundle. Guard code quality with `npm run lint`, and auto-fix common issues using `npm run lint:fix`.
 
+## Versions & Tooling
+- Node.js: specify supported version in `package.json#engines` (e.g., `>=18`)
+- Package manager: npm (or pnpm) — keep lockfile committed
+- Frameworks: Next.js (version), Prisma (version); keep in sync with CI
+- Optional: enable pre-commit hooks for `lint`/`prettier` to reduce CI failures
src/config/appConfig.js (1)

45-46: Minor copy edit in comment

“make you're own” → “make your own”.

-      // make you're own lud06 metadata description
+      // make your own lud06 metadata description
src/components/content/courses/details/CourseDetails.js (2)

20-22: Remove unused import

PROMO_PRICING_MESSAGE is not used here; will fail lint.

-import PromoFreeBadge from '@/components/pricing/PromoFreeBadge';
-import { PROMO_PRICING_MESSAGE } from '@/constants/promoPricing';
+import PromoFreeBadge from '@/components/pricing/PromoFreeBadge';

168-176: Deduplicate the “check + badge” snippet

Extract to a tiny component to avoid repetition and keep styling consistent.

Example:

+const PaidUnlocked = () => (
+  <div className="flex items-center gap-2">
+    <i className="pi pi-check text-sm text-blue-300" />
+    <PromoFreeBadge
+      wrapperClassName="flex items-center gap-1 text-sm"
+      labelClassName="text-blue-300 font-semibold"
+      iconClassName="pi pi-question-circle text-xs text-blue-300"
+    />
+  </div>
+);
...
-      return (
-        <div className="flex items-center gap-2">
-          <i className="pi pi-check text-sm text-blue-300" />
-          <PromoFreeBadge ... />
-        </div>
-      );
+      return <PaidUnlocked />;
src/pages/index.js (4)

109-111: Deduplicate promo copy: use PROMO_PRICING_MESSAGE constant

Avoid drift by sourcing the banner text from the shared constant.

Apply:

@@
-import { Message } from 'primereact/message';
-import { Badge } from 'primereact/badge';
+import { Message } from 'primereact/message';
+import { Badge } from 'primereact/badge';
+import { PROMO_PRICING_MESSAGE } from '@/constants/promoPricing';
@@
-  const bannerMessage =
-    'All content is free for a limited time while we finish building out PlebDevs Platform V2. Keep an eye out, coming soon (tm)!';
+  const bannerMessage = PROMO_PRICING_MESSAGE;

Also applies to: 11-12


190-206: Unused CSS selector: .announcement-wrapper

The media rule targets .announcement-wrapper, but no element uses it. Either add the class to the wrapper div or remove the rule.

Minimal fix (apply the class):

-        <div className="w-full px-4 md:px-12 mt-6">
+        <div className="w-full px-4 md:px-12 mt-6 announcement-wrapper">

Also applies to: 289-297


280-282: Overly broad CSS rule may leak styles

.announcement-badge :global(*) { color: #f8f8ff !important; } will force color on all nested nodes and risks unintended overrides.

Remove the broad rule:

-        .announcement-badge :global(*) {
-          color: #f8f8ff !important;
-        }

197-205: Consider reusing PromoFreeBadge for consistency

Optional: swap the Badge+custom styles for the shared PromoFreeBadge to keep promo messaging consistent across surfaces.

src/constants/promoPricing.js (1)

1-4: Add an explicit promo toggle and env override

Relying only on a numeric constant makes future rollback easy to miss. Provide IS_PROMO_ACTIVE with env override and keep the message centralized.

 export const PROMO_FREE_PRICE_SATS = 0;
 export const PROMO_PRICING_MESSAGE =
   'All content is free for a limited time while we finish building out PlebDevs Platform V2. Keep an eye out, coming soon (tm)!';
 export const PROMO_TOOLTIP_POSITION = 'top';
+export const IS_PROMO_ACTIVE =
+  (process.env.NEXT_PUBLIC_PROMO_ACTIVE ?? 'true').toLowerCase() === 'true';
src/components/bitcoinConnect/CoursePaymentButton.js (3)

219-225: Remove debug log and rely on existing guard

The unauthenticated path already toasts and redirects in fetchInvoice.

-            if (status === 'unauthenticated') {
-              console.log('unauthenticated');
-              router.push('/auth/signin');
-            } else {
-              fetchInvoice();
-            }
+            if (status === 'unauthenticated') {
+              router.push('/auth/signin');
+              return;
+            }
+            fetchInvoice();

106-113: Mark promo purchases explicitly (optional)

Consider including a promo: PROMO_FREE_PRICE_SATS === 0 flag in purchaseData for analytics and future audits.


73-103: Backend: 0-sats accepted — add promo tagging & course API validation

Confirmed: course and resource endpoints accept amountPaid = 0 (course parses with parseInt; resource explicitly validates and allows 0). The Purchase model has no promo metadata, so promotional grants aren’t recorded as such.

  • Files to review: src/pages/api/purchase/course.js (parses amountPaid), src/pages/api/purchase/resource.js (validation example), src/db/models/userModels.js (addCoursePurchaseToUser / addResourcePurchaseToUser), prisma/schema.prisma (Purchase model).
  • Action items: add promo metadata (e.g., isPromo:Boolean and/or promoCode:String) to Purchase schema and include it when creating purchases; add input validation in src/pages/api/purchase/course.js to mirror resource.js (reject missing/NaN amounts).
  • Optional: persist invoice preimage/comment for audit (client sends preimage like "promo-free-course").
src/components/bitcoinConnect/ResourcePaymentButton.js (2)

121-127: Remove debug log and reuse existing guard

Minor cleanup.

-            if (status === 'unauthenticated') {
-              console.log('unauthenticated');
-              router.push('/auth/signin');
-            } else {
-              fetchInvoice();
-            }
+            if (status === 'unauthenticated') {
+              router.push('/auth/signin');
+              return;
+            }
+            fetchInvoice();

53-66: Backend accepts 0 sats but does not mark promo unlocks

  • /api/purchase/resource accepts amountPaid = 0 (only rejects undefined/null; parseInt(0) → 0) and addResourcePurchaseToUser persists amountPaid: 0 (src/pages/api/purchase/resource.js, src/db/models/userModels.js).
  • There is no distinct promo flag or stored preimage on purchases (prisma schema/migration only records amountPaid). Add a boolean (e.g., promo: true) or promoIdentifier/preimage to the purchased record and update the API + DB migration and front-end payload to distinguish promo unlocks.
src/components/content/videos/VideoDetails.js (2)

179-186: DRY up the repeated “check + PromoFreeBadge” block

The same JSX appears in three branches. Extract a tiny component to cut duplication and ease future tweaks.

Example (outside this file):

// components/pricing/AccessPromoBadge.js
export default function AccessPromoBadge({ color = 'text-blue-300' }) {
  return (
    <div className={`flex items-center gap-2 ${color}`}>
      <i className="pi pi-check text-sm" aria-hidden="true" />
      <PromoFreeBadge
        wrapperClassName="flex items-center gap-1 text-sm"
        labelClassName={`${color} font-semibold`}
        iconClassName={`pi pi-question-circle text-xs ${color}`}
      />
    </div>
  );
}

Then replace each block with:

<AccessPromoBadge />

Also applies to: 198-205, 211-218


242-245: Hide decorative icon from screen readers (a11y nit)

Mark the big gift icon as decorative.

Apply:

-            <i className="pi pi-gift text-[100px] text-green-400"></i>
+            <i className="pi pi-gift text-[100px] text-green-400" aria-hidden="true"></i>
src/components/content/documents/DocumentDetails.js (2)

179-186: Deduplicate the “check + PromoFreeBadge” JSX

Same suggestion as in VideoDetails: extract a small AccessPromoBadge to avoid copy/paste.

See the example component provided in the VideoDetails comment and reuse it here for parity.

Also applies to: 198-205, 211-218


234-237: Hide decorative icon from screen readers (a11y nit)

Mark the gift icon as decorative.

Apply:

-              <i className="pi pi-gift text-[60px] text-green-400"></i>
+              <i className="pi pi-gift text-[60px] text-green-400" aria-hidden="true"></i>
src/components/pricing/PromoFreeBadge.js (1)

33-38: Optional: expose tooltip meaning to assistive tech

If you want AT users to get the same hint, add an aria-label. Otherwise, keep it decorative.

Example:

-      <i
+      <i
         id={tooltipId}
         className={`${iconClassName} cursor-help`}
         data-pr-tooltip={PROMO_PRICING_MESSAGE}
         data-pr-position={tooltipPosition}
+        aria-label="Promo pricing details"
       />
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4a2e0ec and f8af424.

📒 Files selected for processing (19)
  • AGENTS.md (1 hunks)
  • src/components/bitcoinConnect/CoursePaymentButton.js (5 hunks)
  • src/components/bitcoinConnect/ResourcePaymentButton.js (4 hunks)
  • src/components/content/carousels/templates/CombinedTemplate.js (2 hunks)
  • src/components/content/carousels/templates/CourseTemplate.js (2 hunks)
  • src/components/content/carousels/templates/DocumentTemplate.js (2 hunks)
  • src/components/content/carousels/templates/VideoTemplate.js (2 hunks)
  • src/components/content/combined/CombinedDetails.js (4 hunks)
  • src/components/content/courses/details/CourseDetails.js (2 hunks)
  • src/components/content/courses/details/DesktopCourseDetails.js (3 hunks)
  • src/components/content/courses/details/MobileCourseDetails.js (3 hunks)
  • src/components/content/documents/DocumentDetails.js (4 hunks)
  • src/components/content/dropdowns/ContentDropdownItem.js (2 hunks)
  • src/components/content/videos/VideoDetails.js (4 hunks)
  • src/components/pricing/PromoFreeBadge.js (1 hunks)
  • src/config/appConfig.js (1 hunks)
  • src/constants/promoPricing.js (1 hunks)
  • src/pages/api/purchase/resource.js (1 hunks)
  • src/pages/index.js (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (15)
src/components/content/carousels/templates/CombinedTemplate.js (1)
src/components/pricing/PromoFreeBadge.js (2)
  • isMobile (25-25)
  • PromoFreeBadge (12-42)
src/components/bitcoinConnect/ResourcePaymentButton.js (5)
src/components/bitcoinConnect/CoursePaymentButton.js (4)
  • session (28-28)
  • router (30-30)
  • handlePaymentSuccess (106-133)
  • fetchInvoice (74-104)
src/hooks/useToast.js (1)
  • showToast (11-13)
src/constants/promoPricing.js (4)
  • PROMO_FREE_PRICE_SATS (1-1)
  • PROMO_FREE_PRICE_SATS (1-1)
  • PROMO_PRICING_MESSAGE (2-3)
  • PROMO_PRICING_MESSAGE (2-3)
src/components/buttons/GenericButton.js (1)
  • GenericButton (4-35)
src/components/pricing/PromoFreeBadge.js (1)
  • PromoFreeBadge (12-42)
src/components/content/carousels/templates/VideoTemplate.js (1)
src/components/pricing/PromoFreeBadge.js (2)
  • isMobile (25-25)
  • PromoFreeBadge (12-42)
src/components/content/courses/details/MobileCourseDetails.js (1)
src/components/pricing/PromoFreeBadge.js (1)
  • PromoFreeBadge (12-42)
src/components/content/courses/details/DesktopCourseDetails.js (1)
src/components/pricing/PromoFreeBadge.js (1)
  • PromoFreeBadge (12-42)
src/components/content/dropdowns/ContentDropdownItem.js (1)
src/components/pricing/PromoFreeBadge.js (1)
  • PromoFreeBadge (12-42)
src/components/content/courses/details/CourseDetails.js (1)
src/components/pricing/PromoFreeBadge.js (1)
  • PromoFreeBadge (12-42)
src/components/content/carousels/templates/CourseTemplate.js (1)
src/components/pricing/PromoFreeBadge.js (2)
  • isMobile (25-25)
  • PromoFreeBadge (12-42)
src/components/bitcoinConnect/CoursePaymentButton.js (5)
src/components/bitcoinConnect/ResourcePaymentButton.js (4)
  • session (24-24)
  • router (26-26)
  • handlePaymentSuccess (85-112)
  • fetchInvoice (53-83)
src/hooks/useToast.js (1)
  • showToast (11-13)
src/constants/promoPricing.js (4)
  • PROMO_FREE_PRICE_SATS (1-1)
  • PROMO_FREE_PRICE_SATS (1-1)
  • PROMO_PRICING_MESSAGE (2-3)
  • PROMO_PRICING_MESSAGE (2-3)
src/components/buttons/GenericButton.js (1)
  • GenericButton (4-35)
src/components/pricing/PromoFreeBadge.js (1)
  • PromoFreeBadge (12-42)
src/components/content/documents/DocumentDetails.js (2)
src/components/pricing/PromoFreeBadge.js (1)
  • PromoFreeBadge (12-42)
src/constants/promoPricing.js (2)
  • PROMO_PRICING_MESSAGE (2-3)
  • PROMO_PRICING_MESSAGE (2-3)
src/components/content/combined/CombinedDetails.js (3)
src/components/pricing/PromoFreeBadge.js (1)
  • PromoFreeBadge (12-42)
src/components/bitcoinConnect/ResourcePaymentButton.js (1)
  • ResourcePaymentButton (20-165)
src/constants/promoPricing.js (2)
  • PROMO_PRICING_MESSAGE (2-3)
  • PROMO_PRICING_MESSAGE (2-3)
src/components/content/carousels/templates/DocumentTemplate.js (1)
src/components/pricing/PromoFreeBadge.js (2)
  • isMobile (25-25)
  • PromoFreeBadge (12-42)
src/pages/api/purchase/resource.js (2)
src/pages/api/purchase/course.js (1)
  • updatedUser (16-19)
src/db/models/userModels.js (2)
  • addResourcePurchaseToUser (97-116)
  • addResourcePurchaseToUser (97-116)
src/components/content/videos/VideoDetails.js (2)
src/components/pricing/PromoFreeBadge.js (1)
  • PromoFreeBadge (12-42)
src/constants/promoPricing.js (2)
  • PROMO_PRICING_MESSAGE (2-3)
  • PROMO_PRICING_MESSAGE (2-3)
src/components/pricing/PromoFreeBadge.js (2)
src/constants/promoPricing.js (6)
  • PROMO_TOOLTIP_POSITION (4-4)
  • PROMO_TOOLTIP_POSITION (4-4)
  • PROMO_FREE_PRICE_SATS (1-1)
  • PROMO_FREE_PRICE_SATS (1-1)
  • PROMO_PRICING_MESSAGE (2-3)
  • PROMO_PRICING_MESSAGE (2-3)
src/hooks/useWindowWidth.js (1)
  • useWindowWidth (3-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (23)
src/config/appConfig.js (1)

14-15: Pubkey addition LGTM

New author pubkey appended correctly.

src/components/content/carousels/templates/VideoTemplate.js (2)

21-21: Consistent badge import LGTM


109-119: Verify PrimeReact Message supports content prop in your version

Some versions expect text/children; content is version-dependent.

If needed, switch to children or text:

-        <Message
+        <Message
           className={`${isMobile ? 'py-1 text-xs' : 'py-2'} whitespace-nowrap flex items-center gap-2`}
           severity="success"
           icon="pi pi-lock-open"
-          content={
-            <PromoFreeBadge
-              iconClassName="pi pi-question-circle text-xs text-green-300"
-              labelClassName="font-semibold text-green-400"
-            />
-          }
+        >
+          <PromoFreeBadge
+            iconClassName="pi pi-question-circle text-xs text-green-300"
+            labelClassName="font-semibold text-green-400"
+          />
+        </Message>
src/components/content/courses/details/MobileCourseDetails.js (2)

8-8: Badge import LGTM


152-156: Uniform Promo badge presentation LGTM

Matches desktop/detail patterns.

src/components/content/carousels/templates/DocumentTemplate.js (2)

20-20: Consistent badge import LGTM


109-119: Verify Message content support in your PrimeReact

Same as VideoTemplate; ensure your version supports it or switch to children.

See suggested diff in VideoTemplate comment; apply similarly here if needed.

src/components/content/courses/details/CourseDetails.js (1)

155-163: Paid/unlocked state UI simplification LGTM

Compact icon + badge reads well.

src/components/content/carousels/templates/CombinedTemplate.js (2)

20-20: Badge import LGTM


110-115: Confirm PrimeReact Message API

Ensure content prop is supported; otherwise use children pattern as in prior suggestion.

src/pages/api/purchase/resource.js (1)

26-29: LGTM — parsed amount persisted; verification complete

  • Course purchase also parses amountPaid (src/pages/api/purchase/course.js) and both addResourcePurchaseToUser / addCoursePurchaseToUser persist amountPaid (src/db/models/userModels.js).
  • PrimeReact ^10.7.0 supports Message's content prop with JSX; multiple components already use content={...} (e.g. src/pages/index.js, src/components/content/carousels/templates/*).
src/components/content/dropdowns/ContentDropdownItem.js (1)

85-91: LGTM: unified promo badge

Consistent Message + PromoFreeBadge usage across surfaces looks good.

Confirm this should always show for all items during promo, regardless of historical price; if not, gate behind a promo flag.

src/components/content/courses/details/DesktopCourseDetails.js (2)

165-170: LGTM: price row uses PromoFreeBadge

Consistent with promo UX elsewhere.


191-196: Verify Start/Continue disabled state under promo

The button disables when paidCourse && (!decryptionPerformed || paidCourse === 'loading'). During promo, ensure users aren’t blocked if decryption isn’t performed.

Would you like a small change to also enable the button when promo is active?

src/components/content/carousels/templates/CourseTemplate.js (1)

130-140: LGTM: single Message with PromoFreeBadge

Clean replacement of split paid/free UI; props match other surfaces.

src/components/bitcoinConnect/CoursePaymentButton.js (2)

77-86: Auth guard + promo short‑circuit: good

Flow matches the promo UX; finally ensures loading reset.


101-103: Good: loading reset in finally

Prevents stuck spinners on early returns/errors.

src/components/content/combined/CombinedDetails.js (2)

174-181: LGTM: purchased/decrypted promo indicators

Consistent PromoFreeBadge and checkmark across states.

Also applies to: 192-199, 204-210


227-234: Promo CTA block looks good; ensure author.lud16 presence

If author?.lud16 is missing, non‑promo purchases would fail. Promo short‑circuit hides it, but verify for post‑promo.

Also applies to: 229-229

src/components/bitcoinConnect/ResourcePaymentButton.js (2)

62-66: Promo short‑circuit: good

Matches CoursePaymentButton behavior and UX.


80-82: Good: loading reset in finally

Prevents spinner from sticking on early returns.

src/components/content/videos/VideoDetails.js (1)

22-24: Centralized promo messaging import — LGTM

Good move pulling in PromoFreeBadge and PROMO_PRICING_MESSAGE for consistency across surfaces.

src/components/content/documents/DocumentDetails.js (1)

21-22: Centralized promo messaging import — LGTM

Consistent promo UI and copy via shared component/constant looks good.

@AustinKelsay AustinKelsay merged commit d8bba02 into main Sep 24, 2025
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant