diff --git a/app/components/AuthProvider.tsx b/app/components/AuthProvider.tsx index 93a67c0..0591ad2 100644 --- a/app/components/AuthProvider.tsx +++ b/app/components/AuthProvider.tsx @@ -22,7 +22,7 @@ interface AuthContextType { hasActiveSubscription: boolean; checkingSubscription: boolean; subscriptionData: SubscriptionData | null; - refreshSubscription: () => Promise; + refreshSubscription: (skipRetries?: boolean) => Promise; initializeDynamic: () => void; isDynamicInitialized: boolean; openAuthModal: () => void; @@ -150,7 +150,7 @@ export function AuthProvider({ children }: { children: ReactNode }) { } }, []); - const refreshSubscription = async () => { + const refreshSubscription = async (skipRetries = false) => { const walletAddress = user?.verifiedCredentials?.[0]?.address; if (walletAddress) { // Clear any cached subscription data first @@ -159,8 +159,8 @@ export function AuthProvider({ children }: { children: ReactNode }) { // Check immediately const isActive = await checkSubscription(walletAddress); - // If still not active, retry up to 3 times with increasing delays - if (!isActive) { + // Only retry if not skipping retries (used for payment success page, not manual refresh) + if (!isActive && !skipRetries) { console.log('[AuthProvider] Subscription not active yet, will retry...'); const retryDelays = [1000, 2000, 3000]; // 1s, 2s, 3s @@ -173,6 +173,8 @@ export function AuthProvider({ children }: { children: ReactNode }) { break; } } + } else if (skipRetries) { + console.log('[AuthProvider] Retries skipped (manual refresh)'); } } }; diff --git a/app/components/MenuDropdowns.tsx b/app/components/MenuDropdowns.tsx index 28f2608..ec9163d 100644 --- a/app/components/MenuDropdowns.tsx +++ b/app/components/MenuDropdowns.tsx @@ -333,6 +333,14 @@ export function HelpDropdown({ 🎯 Start Guided Tour )} + + Email Support + void; +} + +export default function OnboardingFlow({ isOpen, onComplete }: OnboardingFlowProps) { + const [currentStep, setCurrentStep] = useState("welcome"); + const [userPath, setUserPath] = useState(null); + const [mounted, setMounted] = useState(false); + const [showSequencingNote, setShowSequencingNote] = useState(false); + const [dontShowAgain, setDontShowAgain] = useState(false); + + useEffect(() => { + setMounted(true); + if (isOpen) { + trackOnboardingStarted(); + } + }, [isOpen]); + + // Track step changes for analytics + useEffect(() => { + if (isOpen && mounted && currentStep !== "complete") { + trackOnboardingStepViewed(currentStep); + } + }, [currentStep, isOpen, mounted]); + + if (!isOpen || !mounted) return null; + + const handleExplorePath = () => { + setUserPath("explore"); + // Researchers go straight to app + if (dontShowAgain) { + localStorage.setItem("onboarding_completed", "true"); + } + localStorage.setItem("user_path", "explore"); + trackOnboardingCompleted("explore"); + onComplete("explore", false); + }; + + const handleOwnDNAPath = () => { + setUserPath("own_dna"); + // Skip the redundant "DNA test status" question and go straight to data availability + setCurrentStep("data_availability"); + }; + + const handleHasDNATest = () => { + // Legacy function - kept for compatibility with old component + setCurrentStep("data_availability"); + }; + + const handleNoDNATest = () => { + // Show get sequenced screen with test dataset instructions + window.open("https://docs.google.com/forms/d/e/1FAIpQLSdHFDpsyU0t6PlaXEkbHX-pwF_y7icuPJeOHyGHMDpe11XigQ/viewform?usp=header", "_blank"); + setCurrentStep("get_sequenced"); + }; + + const handleHasData = () => { + // Show premium with discount + setCurrentStep("premium_offer"); + }; + + const handleNeedsHelp = () => { + // Show them instructions but keep onboarding open + window.open("https://monadicdna.com/guide", "_blank"); + // User can go back or continue when ready + }; + + const handlePremiumSubscribe = () => { + // Always mark complete after going through full premium flow + localStorage.setItem("onboarding_completed", "true"); + localStorage.setItem("user_path", "own_dna_premium"); + trackOnboardingCompleted("own_dna_premium"); + onComplete("own_dna", true); + }; + + const handlePremiumSkip = () => { + // Always mark complete after going through full flow + localStorage.setItem("onboarding_completed", "true"); + localStorage.setItem("user_path", "own_dna_free"); + trackOnboardingCompleted("own_dna_free"); + onComplete("own_dna", false); + }; + + const handleGetSequenced = () => { + // Advance to get_sequenced step immediately + setCurrentStep("get_sequenced"); + // Open form after minimal delay to ensure UI updates first + setTimeout(() => { + window.open("https://docs.google.com/forms/d/e/1FAIpQLSdHFDpsyU0t6PlaXEkbHX-pwF_y7icuPJeOHyGHMDpe11XigQ/viewform?usp=header", "_blank"); + }, 50); + }; + + const handleCompleteOnboarding = (path: string) => { + // Only set completed if "don't show again" is checked or if completing from sequencing note + if (dontShowAgain || showSequencingNote) { + localStorage.setItem("onboarding_completed", "true"); + } + localStorage.setItem("user_path", path); + trackOnboardingCompleted(path as any); + onComplete(path.includes("explore") ? "explore" : "own_dna", false); + }; + + const welcomeContent = ( +
+
+

🧬 Welcome to Monadic DNA Explorer

+

+ Explore genetic associations from the GWAS Catalog +

+
+ +
+

What brings you here today?

+ +
+ + + + + +
+ + {showSequencingNote && ( +
+

βœ“ Sequencing form opened in new tab!

+

+ While you wait for your kit, feel free to explore genetic traits and studies in the app. +

+ +
+ )} + +
+ +
+
+
+ ); + + const dnaTestStatusContent = ( +
+
+

DNA Test Status

+

+ First, let's check if you have genetic data +

+
+ +
+

+ Have you completed a DNA test with 23andMe, AncestryDNA, or a similar service? +

+ +
+ + + +
+ +
+ + +
+
+
+ ); + + const dataAvailabilityContent = ( +
+
+

Data File Ready?

+

+ Almost there! Let's make sure you have your data file +

+
+ +
+

+ Do you already have a copy of your raw genetic data file? +

+ +
+

πŸ“ Supported formats:

+
    +
  • 23andMe: .txt file
  • +
  • AncestryDNA: .txt file
  • +
  • Monadic DNA: .txt, .csv, .tsv
  • +
+
+ +
+ + + +
+ +
+ + +
+
+
+ ); + + const premiumOfferContent = ( +
+
+

πŸŽ‰ Special Welcome Offer

+

+ Get Premium features with your first week free! +

+
+ +
+
+
WELCOME DISCOUNT
+

🎁 Get Your First Week Free

+ +
+

Your coupon code:

+
+ FREEWEEK + +
+
+ +
+
⚑ Run all 1M+ trait analyses
+
πŸ’¬ LLM chat about your genetics
+
πŸ“‹ Comprehensive AI reports
+
+ +

+ Click "Continue to Explorer" below, then go to the Premium tab and enter this code at checkout. +

+
+ +
+ + + +
+
+
+ ); + + const getSequencedContent = ( +
+
+

🧬 Get Sequenced by Monadic DNA

+

+ We've opened the sequencing form in a new tab +

+
+ +
+
+

βœ“ While you wait for your DNA kit to arrive and results to come back, you can test drive the app with a sample dataset!

+
+ +
+

Try the App Now with Test Data

+
    +
  1. Download this test dataset: GFGFilteredUnphasedGenotypes23andMe.zip
  2. +
  3. Click "Continue to Explorer" below
  4. +
  5. Go to the "Upload DNA" tab
  6. +
  7. Upload the sample file to see how the analysis works
  8. +
+
+ +
+ + + +
+
+
+ ); + + const renderContent = () => { + switch (currentStep) { + case "welcome": + return welcomeContent; + case "dna_test_status": + return dnaTestStatusContent; + case "data_availability": + return dataAvailabilityContent; + case "premium_offer": + return premiumOfferContent; + case "get_sequenced": + return getSequencedContent; + default: + return null; + } + }; + + const modalContent = ( +
+
+ {renderContent()} +
+
+ ); + + return createPortal(modalContent, document.body); +} diff --git a/app/components/PaymentModal.tsx b/app/components/PaymentModal.tsx index 2041132..ba2ff64 100644 --- a/app/components/PaymentModal.tsx +++ b/app/components/PaymentModal.tsx @@ -13,13 +13,14 @@ interface PaymentModalProps { isOpen: boolean; onClose: () => void; onSuccess: () => void; + initialPromoCode?: string; } type Currency = 'USDC' | 'USDT' | 'DAI'; type PaymentType = 'stablecoin' | 'card' | 'promo'; type Step = 'choice' | 'promo' | 'amount' | 'currency' | 'confirm' | 'processing' | 'confirming' | 'card-payment' | 'card-success'; -export default function PaymentModal({ isOpen, onClose, onSuccess }: PaymentModalProps) { +export default function PaymentModal({ isOpen, onClose, onSuccess, initialPromoCode }: PaymentModalProps) { const { primaryWallet } = useDynamicContext(); const [step, setStep] = useState('choice'); const [paymentType, setPaymentType] = useState('stablecoin'); @@ -33,6 +34,15 @@ export default function PaymentModal({ isOpen, onClose, onSuccess }: PaymentModa const [retryCount, setRetryCount] = useState(0); const [successfulChecks, setSuccessfulChecks] = useState(0); + // If initialPromoCode is provided, auto-fill and navigate to promo step + useEffect(() => { + if (initialPromoCode && isOpen) { + setPromoCode(initialPromoCode); + setPaymentType('promo'); + setStep('promo'); + } + }, [initialPromoCode, isOpen]); + const paymentWallet = process.env.NEXT_PUBLIC_EVM_PAYMENT_WALLET_ADDRESS || ''; const testnetEnabled = process.env.NEXT_PUBLIC_ENABLE_TESTNET_CHAINS === 'true'; diff --git a/app/components/PremiumPaywall.tsx b/app/components/PremiumPaywall.tsx index 94c9c13..08e0b80 100644 --- a/app/components/PremiumPaywall.tsx +++ b/app/components/PremiumPaywall.tsx @@ -33,15 +33,24 @@ export function PremiumPaywall({ children }: PremiumPaywallProps) { } }, []); - // Listen for payment modal trigger + // Listen for payment modal trigger (with optional promo code) + const [initialPromoCode, setInitialPromoCode] = useState(undefined); + useEffect(() => { - const handleOpenPaymentModal = () => { + const handleOpenPaymentModal = (event: Event) => { + const customEvent = event as CustomEvent<{ promoCode?: string }>; + const promoCodeFromEvent = customEvent.detail?.promoCode; + + if (promoCodeFromEvent) { + setInitialPromoCode(promoCodeFromEvent); + } + setShowPaymentModal(true); // Track when user views premium section trackPremiumSectionViewed(); }; - window.addEventListener('openPaymentModal', handleOpenPaymentModal); - return () => window.removeEventListener('openPaymentModal', handleOpenPaymentModal); + window.addEventListener('openPaymentModal', handleOpenPaymentModal as EventListener); + return () => window.removeEventListener('openPaymentModal', handleOpenPaymentModal as EventListener); }, []); const handleRemovePromoCode = () => { @@ -68,8 +77,12 @@ export function PremiumPaywall({ children }: PremiumPaywallProps) { <> setShowPaymentModal(false)} + onClose={() => { + setShowPaymentModal(false); + setInitialPromoCode(undefined); // Clear initial promo code on close + }} onSuccess={handleModalSuccess} + initialPromoCode={initialPromoCode} /> {children} diff --git a/app/globals.css b/app/globals.css index 07f6887..7b2588b 100644 --- a/app/globals.css +++ b/app/globals.css @@ -6985,3 +6985,563 @@ details[open] .summary-arrow { display: none; } } + +/* ============================================================================ + ONBOARDING FLOW STYLES + ============================================================================ */ + +.onboarding-overlay { + z-index: 10000; +} + +.onboarding-dialog { + max-width: 700px; + width: 90%; + max-height: 90vh; + overflow-y: auto; +} + +.onboarding-content { + padding: 2rem; +} + +.onboarding-header { + text-align: center; + margin-bottom: 2rem; +} + +.onboarding-header h2 { + font-size: 2rem; + margin-bottom: 0.5rem; + background: linear-gradient(135deg, #3b82f6, #8b5cf6); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.onboarding-subtitle { + font-size: 1.1rem; + color: var(--text-secondary); + margin: 0; +} + +.onboarding-body { + margin-top: 1.5rem; +} + +.onboarding-question { + font-size: 1.2rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 1.5rem; + text-align: center; +} + +.onboarding-options { + display: flex; + flex-direction: column; + gap: 1rem; + margin-top: 1.5rem; +} + +.onboarding-options.centered { + align-items: center; +} + +.onboarding-option-card { + display: flex; + align-items: flex-start; + gap: 1.25rem; + padding: 1.5rem; + background: rgba(255, 255, 255, 0.5); + border: 2px solid rgba(59, 130, 246, 0.2); + border-radius: 12px; + cursor: pointer; + transition: all 0.2s ease; + text-align: left; + width: 100%; +} + +.onboarding-option-card:hover { + background: rgba(255, 255, 255, 0.8); + border-color: rgba(59, 130, 246, 0.4); + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15); +} + +.onboarding-option-card.secondary { + background: rgba(248, 250, 252, 0.5); + border-color: rgba(148, 163, 184, 0.2); +} + +.onboarding-option-card.secondary:hover { + background: rgba(248, 250, 252, 0.8); + border-color: rgba(148, 163, 184, 0.4); +} + +.option-icon { + font-size: 2.5rem; + flex-shrink: 0; + line-height: 1; +} + +.option-content { + flex: 1; +} + +.option-content h3 { + font-size: 1.25rem; + font-weight: 600; + margin: 0 0 0.5rem; + color: var(--text-primary); +} + +.option-content p { + font-size: 0.95rem; + color: var(--text-secondary); + margin: 0; + line-height: 1.5; +} + +.onboarding-info-box { + background: rgba(59, 130, 246, 0.05); + border: 1px solid rgba(59, 130, 246, 0.2); + border-radius: 8px; + padding: 1rem 1.25rem; + margin: 1rem 0 1.5rem; +} + +.onboarding-info-box p { + margin: 0 0 0.5rem; + font-weight: 600; + color: var(--text-primary); +} + +.onboarding-info-box ul { + margin: 0; + padding-left: 1.5rem; + list-style-type: disc; +} + +.onboarding-info-box li { + color: var(--text-secondary); + line-height: 1.6; + margin: 0.25rem 0; +} + +.onboarding-footer-buttons { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 1.5rem; + gap: 1rem; + flex-wrap: wrap; +} + +.onboarding-back-button { + background: transparent; + border: none; + color: var(--text-secondary); + cursor: pointer; + font-size: 0.95rem; + padding: 0.5rem; + transition: color 0.2s ease; +} + +.onboarding-back-button:hover { + color: var(--text-primary); +} + +/* Premium Offer Styles */ +.premium-offer-box { + background: linear-gradient(135deg, rgba(59, 130, 246, 0.1) 0%, rgba(139, 92, 246, 0.1) 100%); + border: 2px solid rgba(59, 130, 246, 0.3); + border-radius: 16px; + padding: 2rem; + text-align: center; + margin-bottom: 1.5rem; +} + +.premium-badge { + display: inline-block; + background: linear-gradient(135deg, #3b82f6, #8b5cf6); + color: white; + font-size: 0.75rem; + font-weight: 700; + letter-spacing: 0.05em; + padding: 0.5rem 1rem; + border-radius: 20px; + margin-bottom: 1rem; +} + +.premium-offer-box h3 { + font-size: 1.75rem; + margin: 0 0 1.5rem; + background: linear-gradient(135deg, #3b82f6, #8b5cf6); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.premium-features { + display: flex; + flex-direction: column; + gap: 1rem; + margin-bottom: 1.5rem; + text-align: left; +} + +.premium-feature { + display: flex; + align-items: flex-start; + gap: 1rem; + padding: 1rem; + background: rgba(255, 255, 255, 0.6); + border-radius: 8px; +} + +.feature-icon { + font-size: 1.5rem; + flex-shrink: 0; +} + +.premium-feature strong { + display: block; + font-size: 1.05rem; + margin-bottom: 0.25rem; + color: var(--text-primary); +} + +.premium-feature p { + font-size: 0.9rem; + color: var(--text-secondary); + margin: 0; +} + +.premium-pricing { + background: rgba(255, 255, 255, 0.8); + border-radius: 12px; + padding: 1.25rem; + margin-top: 1.5rem; +} + +.price-line { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.5rem 0; +} + +.price-line.highlight { + background: linear-gradient(90deg, rgba(59, 130, 246, 0.1), rgba(139, 92, 246, 0.1)); + border-radius: 8px; + padding: 0.75rem 1rem; + margin: 0.5rem 0; +} + +.price-label { + font-weight: 500; + color: var(--text-secondary); +} + +.price-old { + text-decoration: line-through; + color: var(--text-secondary); + font-size: 0.95rem; +} + +.price-new { + font-size: 1.5rem; + font-weight: 700; + color: #10b981; +} + +.price-regular { + font-weight: 600; + color: var(--text-primary); +} + +.onboarding-cta-button { + padding: 1rem 2rem; + font-size: 1.1rem; + font-weight: 600; + border-radius: 12px; + border: none; + cursor: pointer; + transition: all 0.2s ease; + width: 100%; + max-width: 400px; +} + +.onboarding-cta-button.primary { + background: linear-gradient(135deg, #3b82f6, #8b5cf6); + color: white; +} + +.onboarding-cta-button.primary:hover { + transform: translateY(-2px); + box-shadow: 0 8px 16px rgba(59, 130, 246, 0.3); +} + +.onboarding-text-button { + background: transparent; + border: none; + color: var(--text-secondary); + cursor: pointer; + font-size: 0.95rem; + margin-top: 0.75rem; + padding: 0.75rem; + text-decoration: underline; + transition: color 0.2s ease; +} + +.onboarding-text-button:hover { + color: var(--text-primary); +} + +.onboarding-note { + font-size: 0.85rem; + color: var(--text-secondary); + margin-top: 1rem; + text-align: center; +} + +/* Coupon code section */ +.coupon-code-section { + margin: 1.5rem 0; + padding: 1.25rem; + background: rgba(16, 185, 129, 0.1); + border: 2px solid rgba(16, 185, 129, 0.3); + border-radius: 12px; + text-align: center; +} + +.coupon-label { + font-size: 0.9rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 0.75rem; +} + +.coupon-code-box { + display: flex; + align-items: center; + justify-content: center; + gap: 0.75rem; + margin: 0.5rem 0; +} + +.coupon-code { + font-family: 'Courier New', monospace; + font-size: 1.5rem; + font-weight: 700; + color: #10b981; + background: rgba(255, 255, 255, 0.9); + padding: 0.6rem 1.25rem; + border-radius: 8px; + letter-spacing: 0.15em; + border: 2px dashed #10b981; + display: inline-block; +} + +.copy-button { + background: #10b981; + color: white; + border: none; + padding: 0.6rem 1rem; + border-radius: 8px; + font-size: 0.9rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + white-space: nowrap; +} + +.copy-button:hover { + background: #059669; + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3); +} + +.copy-button:active { + transform: translateY(0); +} + +.coupon-instructions { + font-size: 0.85rem; + color: var(--text-secondary); + margin-top: 0.75rem; + line-height: 1.4; +} + +/* Compact premium features */ +.premium-features-compact { + margin: 1.25rem 0; + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.premium-feature-compact { + font-size: 0.95rem; + color: var(--text-primary); + padding: 0.5rem; + text-align: left; +} + +/* Test dataset instructions */ +.test-dataset-instructions { + margin: 1.5rem 0; + padding: 1.25rem; + background: rgba(59, 130, 246, 0.1); + border: 1px solid rgba(59, 130, 246, 0.3); + border-radius: 12px; +} + +.test-dataset-instructions h3 { + font-size: 1.1rem; + margin-bottom: 1rem; + color: var(--text-primary); +} + +.test-dataset-instructions ol { + margin: 0; + padding-left: 1.5rem; + line-height: 1.8; +} + +.test-dataset-instructions li { + margin: 0.5rem 0; + color: var(--text-primary); +} + +.download-link { + color: #3b82f6; + font-weight: 600; + text-decoration: underline; +} + +.download-link:hover { + color: #2563eb; +} + +.onboarding-footer-section { + margin-top: 2rem; + padding-top: 1.5rem; + border-top: 1px solid rgba(59, 130, 246, 0.2); + display: flex; + justify-content: center; +} + +.onboarding-checkbox-label { + display: flex; + align-items: center; + gap: 0.5rem; + cursor: pointer; + font-size: 0.95rem; + color: var(--text-secondary); + user-select: none; +} + +.onboarding-checkbox { + width: 18px; + height: 18px; + cursor: pointer; + accent-color: #3b82f6; +} + +.onboarding-checkbox-label:hover { + color: var(--text-primary); +} + +/* Dark mode support */ +:root[data-theme="dark"] .onboarding-option-card { + background: rgba(31, 41, 55, 0.5); + border-color: rgba(59, 130, 246, 0.3); +} + +:root[data-theme="dark"] .onboarding-option-card:hover { + background: rgba(31, 41, 55, 0.8); + border-color: rgba(59, 130, 246, 0.5); +} + +:root[data-theme="dark"] .onboarding-info-box { + background: rgba(59, 130, 246, 0.1); + border-color: rgba(59, 130, 246, 0.3); +} + +:root[data-theme="dark"] .premium-offer-box { + background: linear-gradient(135deg, rgba(59, 130, 246, 0.15) 0%, rgba(139, 92, 246, 0.15) 100%); +} + +:root[data-theme="dark"] .premium-feature { + background: rgba(31, 41, 55, 0.6); +} + +:root[data-theme="dark"] .premium-pricing { + background: rgba(31, 41, 55, 0.8); +} + +:root[data-theme="dark"] .onboarding-footer-section { + border-top-color: rgba(59, 130, 246, 0.3); +} + +:root[data-theme="dark"] .coupon-code-section { + background: rgba(16, 185, 129, 0.15); + border-color: rgba(16, 185, 129, 0.4); +} + +:root[data-theme="dark"] .coupon-code { + background: rgba(17, 24, 39, 0.9); + color: #34d399; + border-color: #34d399; +} + +:root[data-theme="dark"] .test-dataset-instructions { + background: rgba(59, 130, 246, 0.15); + border-color: rgba(59, 130, 246, 0.4); +} + +/* Mobile responsiveness */ +@media (max-width: 768px) { + .onboarding-dialog { + width: 95%; + max-height: 95vh; + } + + .onboarding-content { + padding: 1.5rem; + } + + .onboarding-header h2 { + font-size: 1.5rem; + } + + .onboarding-subtitle { + font-size: 1rem; + } + + .onboarding-question { + font-size: 1.1rem; + } + + .option-icon { + font-size: 2rem; + } + + .option-content h3 { + font-size: 1.1rem; + } + + .option-content p { + font-size: 0.9rem; + } + + .premium-offer-box { + padding: 1.5rem; + } + + .premium-offer-box h3 { + font-size: 1.4rem; + } +} diff --git a/app/page.tsx b/app/page.tsx index 5f35b89..9ab2f52 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -17,6 +17,7 @@ import OverviewReportModal from "./components/OverviewReportModal"; import { PremiumPaywall } from "./components/PremiumPaywall"; import GuidedTour from "./components/GuidedTour"; import MobileBlocker from "./components/MobileBlocker"; +import OnboardingFlow from "./components/OnboardingFlow"; import { hasMatchingSNPs } from "@/lib/snp-utils"; import { analyzeStudyClientSide } from "@/lib/risk-calculator"; import { isDevModeEnabled } from "@/lib/dev-mode"; @@ -224,6 +225,9 @@ function MainContent() { // Guided tour state (declare early since it's used in useEffect below) const [showGuidedTour, setShowGuidedTour] = useState(false); + // Onboarding flow state + const [showOnboarding, setShowOnboarding] = useState(false); + // Load saved tab from localStorage after mount (dev mode only) useEffect(() => { if (isDevModeEnabled()) { @@ -302,12 +306,19 @@ function MainContent() { }); const [loadTime, setLoadTime] = useState(null); - // Check if user has accepted terms and show tour on mount + // Check if user needs onboarding, then show terms/tour on mount useEffect(() => { + const onboardingCompleted = localStorage.getItem('onboarding_completed'); const termsAccepted = localStorage.getItem('terms_accepted'); const tourDismissed = localStorage.getItem('tour_dismissed'); - // Show tour first if not dismissed + // Show onboarding first if not completed + if (!onboardingCompleted) { + setTimeout(() => setShowOnboarding(true), 500); + return; + } + + // After onboarding, show tour first if not dismissed if (!tourDismissed) { // Show tour after a short delay to allow UI to settle setTimeout(() => setShowGuidedTour(true), 500); @@ -547,6 +558,29 @@ function MainContent() { setShowRunAllDisclaimer(true); }; + const handleOnboardingComplete = (userPath: "explore" | "own_dna" | null, showPremium: boolean) => { + setShowOnboarding(false); + + // If user wants premium, trigger the payment modal with discount code + if (showPremium) { + // Dispatch custom event with promo code for welcome discount + setTimeout(() => { + const event = new CustomEvent('openPaymentModal', { + detail: { promoCode: 'FIRSTMONTH' } + }); + window.dispatchEvent(event); + }, 300); + } + + // Show disclaimer after a short delay + setTimeout(() => { + const tourDismissed = localStorage.getItem('tour_dismissed'); + if (!tourDismissed) { + setShowGuidedTour(true); + } + }, showPremium ? 0 : 500); // No extra delay if showing premium modal + }; + const handleRunAllDisclaimerAccept = async () => { setShowRunAllDisclaimer(false); @@ -1213,7 +1247,7 @@ function MainContent() { onClick={async () => { setShowSubscriptionMenu(false); try { - await refreshSubscription(); + await refreshSubscription(true); // Skip retries for manual refresh alert('βœ“ Subscription status refreshed!'); } catch (error) { console.error('Failed to refresh subscription:', error); @@ -1390,6 +1424,10 @@ function MainContent() { isOpen={showOverviewReportModal} onClose={() => setShowOverviewReportModal(false)} /> + { diff --git a/lib/analytics.ts b/lib/analytics.ts index 21196cf..b9fcfed 100644 --- a/lib/analytics.ts +++ b/lib/analytics.ts @@ -41,6 +41,31 @@ export function trackTermsAccepted() { trackEvent('terms_accepted'); } +/** + * User completed onboarding flow + */ +export function trackOnboardingCompleted(userPath: 'explore' | 'own_dna' | 'own_dna_no_test' | 'own_dna_needs_help' | 'own_dna_premium' | 'own_dna_free') { + trackEvent('onboarding_completed', { + user_path: userPath, + }); +} + +/** + * User started onboarding flow + */ +export function trackOnboardingStarted() { + trackEvent('onboarding_started'); +} + +/** + * User progressed to a specific onboarding step + */ +export function trackOnboardingStepViewed(step: string) { + trackEvent('onboarding_step_viewed', { + step: step, + }); +} + /** * User ran a search query to find studies */ diff --git a/lib/empty-module.js b/lib/empty-module.js new file mode 100644 index 0000000..536910e --- /dev/null +++ b/lib/empty-module.js @@ -0,0 +1,3 @@ +// Empty module for Turbopack polyfills +// Used to replace Node.js built-in modules that aren't available in the browser +export default {}; diff --git a/next-env.d.ts b/next-env.d.ts index 40c3d68..c4b7818 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,5 +1,6 @@ /// /// +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited -// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/next.config.mjs b/next.config.mjs index 9999f37..d45615c 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -7,16 +7,25 @@ const __dirname = path.dirname(__filename); /** @type {import('next').NextConfig} */ const nextConfig = { compress: true, // Enable gzip compression for API responses - eslint: { - ignoreDuringBuilds: false, // Keep linting during builds but don't fail on warnings - }, typescript: { ignoreBuildErrors: false, // Keep type checking }, + // Turbopack disabled - doesn't support complex polyfills needed for Nillion packages + // Issue: Can't properly alias libsodium-wrappers-sumo relative imports + // Will re-enable when Turbopack adds better resolve.fallback support + // Mark server-only packages as external (prevents bundling for browser) + // Nillion packages removed - need webpack bundling to apply libsodium alias + serverExternalPackages: [ + 'onnxruntime-node', + 'sharp', + 'alchemy-sdk', + '@ethersproject/web', + '@ethersproject/providers', + ], experimental: { optimizePackageImports: ["react", "react-dom", "viem", "react-markdown"], - serverComponentsExternalPackages: ['onnxruntime-node', 'sharp', 'alchemy-sdk', '@ethersproject/web', '@ethersproject/providers'] }, + // Transpile Nillion packages - removed because they're in serverExternalPackages async rewrites() { return [ { @@ -38,6 +47,15 @@ const nextConfig = { poll: 1000, // Enable polling for better compatibility on Linux }; + // Handle Nillion dependencies that are not compatible with webpack + if (isServer) { + config.externals = config.externals || []; + config.externals.push({ + "libsodium-wrappers-sumo": "commonjs libsodium-wrappers-sumo", + "@nillion/blindfold": "commonjs @nillion/blindfold", + }); + } + // Ignore React Native dependencies in MetaMask SDK (for both client and server) config.resolve.alias = { ...config.resolve.alias, diff --git a/package-lock.json b/package-lock.json index f620f18..c6ea815 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,22 +15,24 @@ "@nillion/nilai-ts": "^0.3.0", "@nillion/nuc": "^2.0.0", "@nillion/secretvaults": "^2.0.0", - "@stripe/react-stripe-js": "^2.8.0", - "@stripe/stripe-js": "^3.5.0", + "@stripe/react-stripe-js": "^6.0.0", + "@stripe/stripe-js": "^9.0.0", "@types/crypto-js": "^4.2.2", "@types/pako": "^2.0.4", "@types/pg": "^8.15.6", "@xenova/transformers": "^2.17.2", "alchemy-sdk": "^3.6.5", + "crypto-browserify": "^3.12.1", "crypto-js": "^4.2.0", "ethers": "^6.13.4", - "next": "^14.2.33", + "next": "^16.2.1", "openai": "^6.7.0", "pako": "^2.1.0", + "path-browserify": "^1.0.1", "pg": "^8.16.3", "pino-pretty": "^13.1.2", - "react": "^18.3.1", - "react-dom": "^18.3.1", + "react": "^19.2.4", + "react-dom": "^19.2.4", "react-markdown": "^10.1.0", "remark-gfm": "^4.0.1", "sharp": "^0.34.5", @@ -3261,9 +3263,9 @@ } }, "node_modules/@next/env": { - "version": "14.2.35", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz", - "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.1.tgz", + "integrity": "sha512-n8P/HCkIWW+gVal2Z8XqXJ6aB3J0tuM29OcHpCsobWlChH/SITBs1DFBk/HajgrwDkqqBXPbuUuzgDvUekREPg==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { @@ -3277,9 +3279,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.33.tgz", - "integrity": "sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.1.tgz", + "integrity": "sha512-BwZ8w8YTaSEr2HIuXLMLxIdElNMPvY9fLqb20LX9A9OMGtJilhHLbCL3ggyd0TwjmMcTxi0XXt+ur1vWUoxj2Q==", "cpu": [ "arm64" ], @@ -3293,9 +3295,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.33.tgz", - "integrity": "sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.1.tgz", + "integrity": "sha512-/vrcE6iQSJq3uL3VGVHiXeaKbn8Es10DGTGRJnRZlkNQQk3kaNtAJg8Y6xuAlrx/6INKVjkfi5rY0iEXorZ6uA==", "cpu": [ "x64" ], @@ -3309,9 +3311,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.33.tgz", - "integrity": "sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.1.tgz", + "integrity": "sha512-uLn+0BK+C31LTVbQ/QU+UaVrV0rRSJQ8RfniQAHPghDdgE+SlroYqcmFnO5iNjNfVWCyKZHYrs3Nl0mUzWxbBw==", "cpu": [ "arm64" ], @@ -3325,9 +3327,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.33.tgz", - "integrity": "sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.1.tgz", + "integrity": "sha512-ssKq6iMRnHdnycGp9hCuGnXJZ0YPr4/wNwrfE5DbmvEcgl9+yv97/Kq3TPVDfYome1SW5geciLB9aiEqKXQjlQ==", "cpu": [ "arm64" ], @@ -3341,9 +3343,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.33.tgz", - "integrity": "sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.1.tgz", + "integrity": "sha512-HQm7SrHRELJ30T1TSmT706IWovFFSRGxfgUkyWJZF/RKBMdbdRWJuFrcpDdE5vy9UXjFOx6L3mRdqH04Mmx0hg==", "cpu": [ "x64" ], @@ -3357,9 +3359,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.33.tgz", - "integrity": "sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.1.tgz", + "integrity": "sha512-aV2iUaC/5HGEpbBkE+4B8aHIudoOy5DYekAKOMSHoIYQ66y/wIVeaRx8MS2ZMdxe/HIXlMho4ubdZs/J8441Tg==", "cpu": [ "x64" ], @@ -3373,9 +3375,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.33.tgz", - "integrity": "sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.1.tgz", + "integrity": "sha512-IXdNgiDHaSk0ZUJ+xp0OQTdTgnpx1RCfRTalhn3cjOP+IddTMINwA7DXZrwTmGDO8SUr5q2hdP/du4DcrB1GxA==", "cpu": [ "arm64" ], @@ -3388,26 +3390,10 @@ "node": ">= 10" } }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.33.tgz", - "integrity": "sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.33", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.33.tgz", - "integrity": "sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.1.tgz", + "integrity": "sha512-qvU+3a39Hay+ieIztkGSbF7+mccbbg1Tk25hc4JDylf8IHjYmY/Zm64Qq1602yPyQqvie+vf5T/uPwNxDNIoeg==", "cpu": [ "x64" ], @@ -5924,44 +5910,43 @@ "peer": true }, "node_modules/@stripe/react-stripe-js": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-2.9.0.tgz", - "integrity": "sha512-+/j2g6qKAKuWSurhgRMfdlIdKM+nVVJCy/wl0US2Ccodlqx0WqfIIBhUkeONkCG+V/b+bZzcj4QVa3E/rXtT4Q==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-6.0.0.tgz", + "integrity": "sha512-vJW37/uyRAJEkD3YKCh3aISmMIMrQGR3ViVBkUVQDB7CqbRCnOUyhwDe8zKg+d6K8V4d0MUcthcQdHL4meqG7A==", "license": "MIT", "dependencies": { "prop-types": "^15.7.2" }, "peerDependencies": { - "@stripe/stripe-js": "^1.44.1 || ^2.0.0 || ^3.0.0 || ^4.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@stripe/stripe-js": ">=9.0.0 <10.0.0", + "react": ">=16.8.0 <20.0.0", + "react-dom": ">=16.8.0 <20.0.0" } }, "node_modules/@stripe/stripe-js": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-3.5.0.tgz", - "integrity": "sha512-pKS3wZnJoL1iTyGBXAvCwduNNeghJHY6QSRSNNvpYnrrQrLZ6Owsazjyynu0e0ObRgks0i7Rv+pe2M7/MBTZpQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-9.0.0.tgz", + "integrity": "sha512-UtUK7LFglQSNVIOwcRBaxfzq4wkfU8CT2f2uQVEeu65jTP6wicxFshYdYCke9Tfd0PCxhOe/b8rwJjr5EiDCfQ==", "license": "MIT", "engines": { "node": ">=12.16" } }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "license": "Apache-2.0" - }, "node_modules/@swc/helpers": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", - "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", "license": "Apache-2.0", "dependencies": { - "@swc/counter": "^0.1.3", - "tslib": "^2.4.0" + "tslib": "^2.8.0" } }, + "node_modules/@swc/helpers/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/@thumbmarkjs/thumbmarkjs": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/@thumbmarkjs/thumbmarkjs/-/thumbmarkjs-0.16.0.tgz", @@ -9086,6 +9071,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "license": "MIT" + }, "node_modules/ast-types-flow": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", @@ -9299,14 +9301,15 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.9.9", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.9.tgz", - "integrity": "sha512-V8fbOCSeOFvlDj7LLChUcqbZrdKD9RU/VR260piF1790vT0mfLSwGc/Qzxv3IqiTukOpNtItePa0HBpMAj7MDg==", - "dev": true, + "version": "2.10.10", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.10.tgz", + "integrity": "sha512-sUoJ3IMxx4AyRqO4MLeHlnGDkyXRoUG0/AI9fjK+vS72ekpV0yWVY7O0BVjmBcRtkNcsAO2QDZ4tdKKGoI6YaQ==", "license": "Apache-2.0", - "peer": true, "bin": { - "baseline-browser-mapping": "dist/cli.js" + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/bech32": { @@ -9480,6 +9483,119 @@ "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", "license": "MIT" }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "license": "MIT", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "license": "MIT", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", + "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", + "license": "MIT", + "dependencies": { + "bn.js": "^5.2.1", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", + "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==", + "license": "ISC", + "dependencies": { + "bn.js": "^5.2.2", + "browserify-rsa": "^4.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.6.1", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.9", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-sign/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/browserify-sign/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/browserify-sign/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/browserify-sign/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/browserslist": { "version": "4.28.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", @@ -9587,6 +9703,12 @@ "integrity": "sha512-M87YIUBsZ6N924W57vDwT/aOu8hw7ZgdByz6ijksLjmHJELBASmYTTlNHRgjE+pTsT9oJXGaDSgqqwfdHotDUg==", "license": "MIT" }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "license": "MIT" + }, "node_modules/bufferutil": { "version": "4.0.9", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.9.tgz", @@ -9600,17 +9722,6 @@ "node": ">=6.14.2" } }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -9814,6 +9925,20 @@ "node": ">=6.0" } }, + "node_modules/cipher-base": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", + "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -9961,6 +10086,49 @@ "node": ">=0.8" } }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "license": "MIT" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "node_modules/cross-fetch": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", @@ -9994,6 +10162,32 @@ "uncrypto": "^0.1.3" } }, + "node_modules/crypto-browserify": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", + "integrity": "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==", + "license": "MIT", + "dependencies": { + "browserify-cipher": "^1.0.1", + "browserify-sign": "^4.2.3", + "create-ecdh": "^4.0.4", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "diffie-hellman": "^5.0.3", + "hash-base": "~3.0.4", + "inherits": "^2.0.4", + "pbkdf2": "^3.1.2", + "public-encrypt": "^4.0.3", + "randombytes": "^2.1.0", + "randomfill": "^1.0.4" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/crypto-js": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", @@ -10287,6 +10481,16 @@ "valtio": "*" } }, + "node_modules/des.js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, "node_modules/destr": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", @@ -10327,6 +10531,23 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "license": "MIT" + }, "node_modules/dijkstrajs": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", @@ -11584,6 +11805,16 @@ "bare-events": "^2.7.0" } }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "license": "MIT", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -12224,7 +12455,8 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" + "license": "ISC", + "peer": true }, "node_modules/graphemer": { "version": "1.4.0", @@ -12343,6 +12575,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", @@ -13179,7 +13424,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, "license": "MIT" }, "node_modules/isexe": { @@ -13699,6 +13943,17 @@ "node": ">= 0.4" } }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, "node_modules/mdast-util-find-and-replace": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", @@ -14598,6 +14853,25 @@ "node": ">=8.6" } }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "license": "MIT" + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -14745,41 +15019,41 @@ "peer": true }, "node_modules/next": { - "version": "14.2.35", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.35.tgz", - "integrity": "sha512-KhYd2Hjt/O1/1aZVX3dCwGXM1QmOV4eNM2UTacK5gipDdPN/oHHK/4oVGy7X8GMfPMsUTUEmGlsy0EY1YGAkig==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/next/-/next-16.2.1.tgz", + "integrity": "sha512-VaChzNL7o9rbfdt60HUj8tev4m6d7iC1igAy157526+cJlXOQu5LzsBXNT+xaJnTP/k+utSX5vMv7m0G+zKH+Q==", "license": "MIT", "dependencies": { - "@next/env": "14.2.35", - "@swc/helpers": "0.5.5", - "busboy": "1.6.0", + "@next/env": "16.2.1", + "@swc/helpers": "0.5.15", + "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", - "graceful-fs": "^4.2.11", "postcss": "8.4.31", - "styled-jsx": "5.1.1" + "styled-jsx": "5.1.6" }, "bin": { "next": "dist/bin/next" }, "engines": { - "node": ">=18.17.0" + "node": ">=20.9.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.2.33", - "@next/swc-darwin-x64": "14.2.33", - "@next/swc-linux-arm64-gnu": "14.2.33", - "@next/swc-linux-arm64-musl": "14.2.33", - "@next/swc-linux-x64-gnu": "14.2.33", - "@next/swc-linux-x64-musl": "14.2.33", - "@next/swc-win32-arm64-msvc": "14.2.33", - "@next/swc-win32-ia32-msvc": "14.2.33", - "@next/swc-win32-x64-msvc": "14.2.33" + "@next/swc-darwin-arm64": "16.2.1", + "@next/swc-darwin-x64": "16.2.1", + "@next/swc-linux-arm64-gnu": "16.2.1", + "@next/swc-linux-arm64-musl": "16.2.1", + "@next/swc-linux-x64-gnu": "16.2.1", + "@next/swc-linux-x64-musl": "16.2.1", + "@next/swc-win32-arm64-msvc": "16.2.1", + "@next/swc-win32-x64-msvc": "16.2.1", + "sharp": "^0.34.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", - "@playwright/test": "^1.41.2", - "react": "^18.2.0", - "react-dom": "^18.2.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "peerDependenciesMeta": { @@ -14789,6 +15063,9 @@ "@playwright/test": { "optional": true }, + "babel-plugin-react-compiler": { + "optional": true + }, "sass": { "optional": true } @@ -15331,6 +15608,22 @@ "node": ">=6" } }, + "node_modules/parse-asn1": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz", + "integrity": "sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==", + "license": "ISC", + "dependencies": { + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "pbkdf2": "^3.1.5", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/parse-entities": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", @@ -15356,6 +15649,12 @@ "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", "license": "MIT" }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "license": "MIT" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -15392,6 +15691,23 @@ "dev": true, "license": "MIT" }, + "node_modules/pbkdf2": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", + "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==", + "license": "MIT", + "dependencies": { + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ripemd160": "^2.0.3", + "safe-buffer": "^5.2.1", + "sha.js": "^2.4.12", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/pg": { "version": "8.16.3", "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz", @@ -15839,6 +16155,26 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "license": "MIT" + }, "node_modules/pump": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", @@ -15968,6 +16304,16 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "license": "MIT", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -15993,13 +16339,10 @@ } }, "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, "engines": { "node": ">=0.10.0" } @@ -16017,16 +16360,15 @@ } }, "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" + "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^18.3.1" + "react": "^19.2.4" } }, "node_modules/react-fast-compare": { @@ -16379,6 +16721,76 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/ripemd160": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", + "license": "MIT", + "dependencies": { + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ripemd160/node_modules/hash-base": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ripemd160/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/ripemd160/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/ripemd160/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/ripemd160/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/ripemd160/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/rpc-websockets": { "version": "9.3.2", "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-9.3.2.tgz", @@ -16543,13 +16955,10 @@ } }, "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" }, "node_modules/schema-utils": { "version": "4.3.3", @@ -16717,6 +17126,26 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, + "node_modules/sha.js": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" + }, + "bin": { + "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/sha256-uint8array": { "version": "0.10.7", "resolved": "https://registry.npmjs.org/sha256-uint8array/-/sha256-uint8array-0.10.7.tgz", @@ -17168,14 +17597,6 @@ "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", "license": "MIT" }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/streamx": { "version": "2.23.0", "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", @@ -17438,9 +17859,9 @@ } }, "node_modules/styled-jsx": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", - "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", "license": "MIT", "dependencies": { "client-only": "0.0.1" @@ -17449,7 +17870,7 @@ "node": ">= 12.0.0" }, "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" }, "peerDependenciesMeta": { "@babel/core": { @@ -17763,6 +18184,20 @@ "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", "license": "MIT" }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -17913,7 +18348,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", - "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.3", @@ -18272,15 +18706,6 @@ } } }, - "node_modules/use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/utf-8-validate": { "version": "5.0.10", "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", @@ -18364,6 +18789,15 @@ } } }, + "node_modules/valtio/node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", diff --git a/package.json b/package.json index 74b3b0f..dff3aad 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,10 @@ "description": "Match your DNA data against an open ended catalogue of DNA traits", "type": "module", "scripts": { - "dev": "next dev", - "build": "next build", + "dev": "next dev --webpack", + "build": "next build --webpack", "start": "next start", - "lint": "next lint" + "lint": "eslint . --ext .js,.jsx,.ts,.tsx --ignore-path .gitignore" }, "keywords": [], "author": "Monadic DNA / RecherchΓ© Inc", @@ -19,22 +19,24 @@ "@nillion/nilai-ts": "^0.3.0", "@nillion/nuc": "^2.0.0", "@nillion/secretvaults": "^2.0.0", - "@stripe/react-stripe-js": "^2.8.0", - "@stripe/stripe-js": "^3.5.0", + "@stripe/react-stripe-js": "^6.0.0", + "@stripe/stripe-js": "^9.0.0", "@types/crypto-js": "^4.2.2", "@types/pako": "^2.0.4", "@types/pg": "^8.15.6", "@xenova/transformers": "^2.17.2", "alchemy-sdk": "^3.6.5", + "crypto-browserify": "^3.12.1", "crypto-js": "^4.2.0", "ethers": "^6.13.4", - "next": "^14.2.33", + "next": "^16.2.1", "openai": "^6.7.0", "pako": "^2.1.0", + "path-browserify": "^1.0.1", "pg": "^8.16.3", "pino-pretty": "^13.1.2", - "react": "^18.3.1", - "react-dom": "^18.3.1", + "react": "^19.2.4", + "react-dom": "^19.2.4", "react-markdown": "^10.1.0", "remark-gfm": "^4.0.1", "sharp": "^0.34.5", @@ -52,5 +54,6 @@ "ignore-loader": "^0.1.2", "node-loader": "^2.1.0", "typescript": "^5.9.2" - } + }, + "packageManager": "yarn@4.9.1+sha512.f95ce356460e05be48d66401c1ae64ef84d163dd689964962c6888a9810865e39097a5e9de748876c2e0bf89b232d583c33982773e9903ae7a76257270986538" } diff --git a/tsconfig.json b/tsconfig.json index 2ecc618..2078a0f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,7 +16,7 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", + "jsx": "react-jsx", "incremental": true, "paths": { "@/*": [ @@ -33,7 +33,8 @@ "next-env.d.ts", "**/*.ts", "**/*.tsx", - ".next/types/**/*.ts" + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts" ], "exclude": [ "node_modules"