#chris-valentine_code

1 messages ยท Page 1 of 1 (latest)

minor sundialBOT
#

๐Ÿ‘‹ Welcome to your new thread!

โฒ๏ธ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.

โฑ๏ธ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.

๐Ÿ”— This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1338593428539441173

๐Ÿ“ Have more to share? Add more details, code, screenshots, videos, etc. below.

maiden pine
#

Hello! I'm afraid that's not enough information to go on. Can you provide more details? Can you link to the page showing the error?

sonic ferry
#

Its on a development server, the live server isnt public. I can link all kinds of code i just could not in that initial box

import React, { Suspense } from 'react'
import ProfilePage from '@/components/profilepage/profilepage'
// import { UserProvider } from '@/app/context/UserProfileUserContext'

import { Elements } from '@stripe/react-stripe-js';
import { loadStripe } from '@stripe/stripe-js';

const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY as string);

function MyProfile() {

  // console.log(stripePromise)

  return (
    <div className='my-8'>
      <Elements stripe={stripePromise}
      options={{
        appearance: {
          theme: 'flat',
          rules: {
            '.Input': {
              border: '1px solid #292524', // Set border for non-focus state
              backgroundColor: '#0c0a09',
              padding: '10px',
            },
          },
          variables: {
            colorBackground: '#000000',
            colorText: '#FFFFFF',
            colorPrimaryText: '#FFFFFF',
            borderRadius: '5px',
            fontSizeBase: '14px',
            fontSizeLg: '18px',
            focusBoxShadow: '0 0 0 2px #FFFFFF', // Set border for focus state
          },
        },
      }}
      >
          <Suspense fallback={<div>Loading...</div>}>
            <ProfilePage />
          </Suspense>
      </Elements>
    </div>
  )
}

export default MyProfile


<AddressElement


            onChange={(event) => {
              const { value } = event;
              setValue('name', (value.name || ''));
              setValue('address.line1', value.address.line1);
              setValue('address.line2', value.address.line2);
              setValue('address.city', value.address.city);
              setValue('address.state', value.address.state);
              setValue('address.country', value.address.country);
              setValue('address.postal_code', value.address.postal_code);
            }}
            options={{
              mode: 'billing',

              fields: {
                phone: 'never',
              },
              defaultValues: {
                name: currentUser?.full_name || '',
                // firstName: currentUser?.first_name || '',
                // lastName: currentUser?.last_name || '',
                address : {
                  line1: currentUser?.address1 || '',
                  line2: currentUser?.address2 || '',
                  city: currentUser?.city || '',
                  state: currentUser?.state || '',
                  postal_code: currentUser?.zip || '',
                  country: currentUser?.country || '',
                }
              },
            }} // Required options
          />

Error is:

shared-666b312be4be014d22b8a4b6de89355b.js:1 Uncaught (in promise) Error: Unable to select session. Make sure Elements is initialized with clientSecret
      or use the nullableSessionSelector() instead.
maiden pine
#

Have you confirmed you're initializing Elements with a cleint secret?

sonic ferry
#

yes i can log the public key, i see it in log

maiden pine
#

That's your publishable key, which is not a client secret. A client secret comes from an Intent or a Session of some kind.

minor sundialBOT
sonic ferry
#

should my actual secret key be put on a client page? this page used to work then stopped and i dont believe i have ever had the client secret on it.

my understanding is the client secret shoudl be reserved for server functions not thrown out to the client

vast turtle
#

Hello
No, you should never expose your secret API key to your client side app. Client-secret is meant to be used by the client-side application.

sonic ferry
#

i tried that to see and it doesnt like it anyway

#

is client-secret synonymous with publishable key?

#

oh i read the other message now

#

so i need to start an intent/session to check address validation? this is not for a checkout session this is just to make sure their address in t heir profile is saved in a manner in which stripe will like it eventually when they do go to checkout

vast turtle
sonic ferry
#

only address element

#

that linked document does show it using a publishable key (pk_)

vast turtle
#

Right.. I suspect the error might be misleading. Can you comment out the Address Element and see if the error still persists?

sonic ferry
#

it does not

#

i've done that. without the address element no error message occurs

vast turtle
#

What's your component hierarchy? What component renders AddressElement?

#

Is it under MyProfile?

sonic ferry
#

page.tsx > profilepage > accounttab

#

const AccountTab = React.lazy(() => import('./AccountTab'));

could this cause anything? i think this was a recent change

vast turtle
#

Unintended changes in the component hierarchy can cause issues, yes.
If you revert it, does the error go away?

sonic ferry
#

reverted it, did not go away

#

doing a full rebuild just to be sure of that statement

#

ok. confirmed it did not go away, still receive error message

vast turtle
#

Can you share the exact code your app uses? Like from App component to the component that renders Address Element?

My gut says there's something wonky with App hierarchy

sonic ferry
#

i can, one moment

vast turtle
#

uh can you upload it to github or similar code hosting platform? Even a gist would work or you can copy paste the code in the thread.

I won't be able to open the zip file

minor sundialBOT
#

๐Ÿง‘โ€๐Ÿ’ป How to format code on Discord

Inline code: wrap in single backticks (`)

This:

The variable `foo` contains the value `bar`.

Will turn into this:

The variable foo contains the value bar.

Code blocks: wrap in three backticks (```)

Also, you can specify the language after the first three backticks to get syntax highlighting.

This:

```javascript
function foo() {
return 'bar';
}
```

Will turn into this:

function foo() {
  return 'bar';
}```

Notes about **code blocks**:
- Specifying the language is optional (e.g., you can omit `javascript` in the example above)
  - If you don't specify the language you won't get syntax highlighting
- When you're inside a code block (after you type \`\`\`) the `Return`/`Enter` key will add a new line instead of sending your message
  - Once you end the code block `Return`/`Enter` works normally again

You can [read more about message formatting on Discord's website.](https://support.discord.com/hc/en-us/articles/210298617)
sonic ferry
#

//ProfilePage

'use client'
import React, { Suspense, useEffect } from 'react'

import { FaChartLine, FaClipboardCheck, FaMessage, FaReceipt, FaTags, FaUser} from 'react-icons/fa6';
import { MdAccountBox,MdOutlineLibraryBooks,MdOutlineShoppingBag, MdList } from "react-icons/md";


import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { useUser } from '@/app/context/UserProfileUserContext';

import { useRouter, useSearchParams } from "next/navigation";

import { LuPackageOpen } from 'react-icons/lu';
import CurrencyNudge from './CurrencyNudge';
import { Compass } from 'lucide-react';
import { useIsMobile } from '@/hooks/use-mobile';

import  AccountTab  from './AccountTab';

const kebabCase = (str: string) => {
    const matches = str.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
    if (!matches) return str

    const result = matches.join('-').toLowerCase();

    return result
}

// const AccountTab =              React.lazy(() => import('./AccountTab'));
const TabNotifications =        React.lazy(() => import('./NotificationsTab'));
const WishlistTab =             React.lazy(() => import('./WishlistTab'));
const ReviewsTab =              React.lazy(() => import('./ReviewsTab'));
const PurchasedTab =            React.lazy(() => import('./PurchasedTab'));
const OrdersTab =               React.lazy(() => import('./OrdersTab'));
const ProviderTab =             React.lazy(() => import('./ProviderTab'));
const ContentTab =              React.lazy(() => import('./ContentTab'));
const BundlesTab =              React.lazy(() => import('./BundlesTab'));
const PromotionsTab =           React.lazy(() => import('./PromotionsTab'));
const SalesReportsTab =         React.lazy(() => import('./SalesReportsTab'));


/*
Mariah notes:
there are some areas where code is repeated like the tables and row content for them

to-dos and wants
- add ability to edit each contact info item
- add wishlist display
- add ability to sort/search purchase and cc table
- add what settings the user should have access to/what changes they can make themselves ?? not sure exactly
end notes
*/

type Props = {}

const ProfilePage:React.FC = (Props) => {
    const router = useRouter()
    const searchParams = useSearchParams();

    const isMobile = useIsMobile()

    const { state: currentUser, dispatch } = useUser()
    const [activeTab, setActiveTab] = React.useState<string>('account')

    // if the query parameter changes, update the state
    useEffect(() => {
        const tab = searchParams.get('tab');
        if (tab) {
        setActiveTab(tab);
        }
    }, [searchParams]);

    // useEffect(() => {
    //     if (!currentUser) return

    //     dispatch({ type: 'REFRESH_FROM_FVTT' });

    // }, [])
    
    if (!currentUser) return <div>Loading Now...</div>    

    const handleNudgeDismiss = () => {
        console.log('nudge dismissed')
        dispatch({ type: 'UPDATE_USER', payload: { dismissed_currency_nudge: true} });
       }
#
 const tabData = [
        {icon: <MdAccountBox className='size-6 mr-0 md:mr-4'/>, title: 'Account', content: <AccountTab handleNudgeDismiss={handleNudgeDismiss}  />
 },
        // {icon: <FaShield className='size-8 mr-0 md:mr-4'/>, title: 'Security', content: <SecurityTab /> }, 
        {icon: <FaMessage className='size-5 mr-0 md:mr-4'/>, title: 'Notifications', content: <Suspense fallback={<div>Loading...</div>}><TabNotifications /></Suspense> },        
        {icon: <MdList className='size-6 mr-0 md:mr-4'/>, title: 'Wishlist', content: <Suspense fallback={<div>Loading...</div>}><WishlistTab /></Suspense>},
        {icon: <FaClipboardCheck className='size-6 mr-0 md:mr-4'/>, title: 'Reviews', content: <Suspense fallback={<div>Loading...</div>}><ReviewsTab /></Suspense>},
        {icon: <MdOutlineShoppingBag className='size-6 mr-0 md:mr-4 md:size-10 lg:size-6'/>, title: 'Purchased Content', content: <Suspense fallback={<div>Loading...</div>}><PurchasedTab /></Suspense>},
        {icon: <FaReceipt className='size-6 mr-0 md:mr-4'/>, title: 'Order History', content: <Suspense fallback={<div>Loading...</div>}><OrdersTab /></Suspense>},

        // creator only sections before here
        {icon: <Compass className='size-6 mr-0 md:mr-4'/>, title: 'Providers', content: <Suspense fallback={<div>Loading...</div>}><ProviderTab /></Suspense>, creatorsOnly: true},
        {icon: <MdOutlineLibraryBooks className='size-6 mr-0 md:mr-4'/>, title: 'Created Content', content: <Suspense fallback={<div>Loading...</div>}><ContentTab /></Suspense>, creatorsOnly: true},
        // {icon: <LuPackageOpen className='size-6 mr-0 md:mr-4'/>, title: 'Bundles', content: <Suspense fallback={<div>Loading...</div>}><BundlesTab /></Suspense>, creatorsOnly: true},
        {icon: <FaTags className='size-6 mr-0 md:mr-4'/>, title: 'Promotions', content: <Suspense fallback={<div>Loading...</div>}><PromotionsTab /></Suspense>, creatorsOnly: true},
        {icon: <FaChartLine className='size-6 mr-0 md:mr-4'/>, title: 'Content Sales', content: <Suspense fallback={<div>Loading...</div>}><SalesReportsTab /></Suspense>, creatorsOnly: true},
    ]

    // console.log(session.user)   

    const handleTabChange = (value: string) => {
        setActiveTab(value)
        router.push(`?tab=${value}`);
    }

  const contentMaker = currentUser.creator
  const showNudge = !currentUser?.dismissed_currency_nudge
#
return (
        // <> is an abbreviation for <React.Fragment> which is a wrapper that doesn't create a new div in the DOM
        <> 
            <div className='relative flex flex-col min-h-screen max-w-7xl m-auto p-4 rounded-2xl bg-gradient-to-b from-purplebrown-800 to-purplebrown-950 outline outline-[1px] outline-hotMetal-test1/25'>
                     {showNudge  && <CurrencyNudge handleNudgeDismiss={handleNudgeDismiss} />}
                    <div className='flex flex-row justify-start items-center pl-4 gap-1  border-zinc-600 w-full py-4'>
                        {/* fixme */}
                        {currentUser?.image
                            ?<div><img src={currentUser.image.replace("sigil-services.", "metamorphic-digital.")} className='size-16 p-1 border-white'/></div>
                            :  <div><FaUser className='size-16 p-1  border-white'/></div>
                        }                        
                        <div className='grow ml-3 text-white'>
                            <div className=' text-3xl'>{currentUser?.name}</div>
                            <div className='flex gap-1 justify-start items-center'>{currentUser?.email}</div>
                        </div>
                        
                    </div>
                <Tabs 
                
                value={activeTab}
                onValueChange={handleTabChange}
                // defaultValue={tabData[0].title} 
                className="w-full min-h-[1000px] flex flex-row justify-start" orientation="vertical">
                    <TabsList className=' flex flex-col justify-start w-fit md:w-1/5'>
                        {tabData && tabData.map((tab, index) => { 
                            
                            if (tab.creatorsOnly && !contentMaker) return null

                            return (
                            <TabsTrigger key={index} value={kebabCase(tab.title)} 
                                className={`${tab.creatorsOnly ? 'bg-purplebrown-500/40 hidden lg:flex' : 'flex'} justify-start items-center text-base data-[state=active]:bg-purplebrown-800 dark:data-[state=active]:bg-purplebrown-600 text-left`}>
                                {tab.icon}<span className="hidden md:block break-words md:break-normal overflow-hidden whitespace-pre-wrap md:whitespace-nowrap">{tab.title} </span>            
                            </TabsTrigger>
                        )})}
                    </TabsList>
                    <div className='grow rounded-lg'>
                        {tabData && tabData.map((tab, index) => (
                            <TabsContent forceMount key={index} value={kebabCase(tab.title)} className='w-full  md:w-full h-full rounded-lg pb-4 ' >
                                {/* <Suspense fallback={<div>Loading...</div>}> */}
                                    {tab.content}
                                {/* </Suspense> */}
                            </TabsContent>
                        ))}
                    </div>
                </Tabs>


            </div>
        </>
    )
}
  
export default ProfilePage
#

//AccountPage

'use client'

import React, { useState } from 'react'

import { toast } from 'sonner';

import { useUser } from '@/app/context/UserProfileUserContext';
import { TitledBox } from '../profilepage/ProfileUtils'
import { Button } from '../ui/button';
import Link from 'next/link';
import { FaArrowRotateRight } from 'react-icons/fa6';

import { useForm } from "react-hook-form";

import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";

import { AddressElement } from '@stripe/react-stripe-js';

import { useSession } from 'next-auth/react';
import { Input } from '../ui/input';
import {
    Form,
    FormControl,
    FormField,
    FormItem,
    FormLabel,
    FormMessage,
  } from "../ui/form";

// import { Label } from "@/components/ui/label"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
import CurrencyReminder from './CurrencyReminder';
import { useShoppingCart } from '@/app/context/CartProvider';

type Props = {
  handleNudgeDismiss: () => void;
}

  const schema = z.object({
    displayname: z.string().min(1, { message: "Display Name is required." }),
    phone_num: z
      .string()
      // .min(7, { message: "Phone must be at least 7 characters." })
      .optional(),
    currency: z.string().min(1, { message: "Currency is required." }),
    name: z.string().min(1, { message: "Full name is required." }),
    address: z.object({
      line1: z.string().min(1, 'Address line 1 is required'),
      line2: z.string().nullable().optional(),
      city: z.string().min(1, 'City is required'),
      state: z.string().optional(),
      country: z.string().min(1, 'Country is required'),
      postal_code: z.string().min(1, 'Postal code is required'),
    }),
  });
#
function AccountTab({handleNudgeDismiss}: Props) {

    const { state: currentUser, dispatch } = useUser()

    const [accountRecord, setAccountRecord] = useState<any>(null)

    const { data: session, status } = useSession()

    const { cart, updateCartCurrency } = useShoppingCart()

    if (status === 'loading') return <div>Loading...</div>
    if (!session) return <div>Not signed in</div>

    const form = useForm<{
      displayname: string;
      phone_num: string;
      currency: string;
      name: string;
      address: {
        line1: string;
        line2: string | null;
        city: string;
        state: string;
        country: string;
        postal_code: string;
      }
    }>({
        resolver: zodResolver(schema),
        defaultValues: {
          displayname: currentUser?.displayname || '',
          phone_num: currentUser?.phone || '',
          currency: currentUser?.currency || 'USD', // Default to 'USD' if not provided
          name: currentUser?.full_name || '',
          address: {
            line1: currentUser?.address1 || '',
            line2: currentUser?.address2 || null, // Set to null for nullable fields
            city: currentUser?.city || '',
            state: currentUser?.state || '',
            country: currentUser?.country || '',
            postal_code: currentUser?.zip || '',
          },
        },
      });
    
      const onSubmit = (data: any) => {
        // console.log("Form Data:", data);

        // convert the data to the format expected by the API
        const convertedData = {
          currency: data.currency,
          full_name: data.name,
          displayname: data.displayname,
          phone: data.phone_num,
          address1: data.address.line1,
          address2: data.address.line2,
          city: data.address.city,
          state: data.address.state,
          country: data.address.country,
          zip: data.address.postal_code,
        };

        // console.log("Converted Form Data:", convertedData);

        // Save the user data to the AP
        // console.log('updating cart to', data.currency, cart?.currency)
        updateCartCurrency(data.currency, true);

        // Update the user state with the new data
        dispatch({ type: 'UPDATE_USER', payload: convertedData });
        // console.log('toasting...');
        toast.success('Account information saved.');
      }

      const { setValue, formState: { errors } } = form;

    const FoundryButton = () => <div className='flex justify-end gap-2 items-center'>
        <Link title='Refresh Data' href="#" className='bg-stone-400/25 rounded-md p-1 hover:text-black hover:bg-foundry-golden'>
            <FaArrowRotateRight className='size-4' />
        </Link>
        <Link target='_blank' href={`https://foundryvtt.com/community/${currentUser?.username}`} className='bg-stone-400/25 text-white px-2 rounded-md hover:bg-foundry-golden  hover:text-black'>
            Manage Account at FoundryVTT.com
        </Link>
    </div>

    if (!currentUser) return <div>Loading...</div>



    // console.log('currentUser', session)

  const showCurrencyNudge = !currentUser.dismissed_currency_nudge
#
return (
        // profile tab content
        <div className='flex flex-col justify-start gap-8 pl-4 md:px-4'>

        <TitledBox title='Account Info' className='flex justify-start p-4 relative' upperRightComponent={<FoundryButton />}>
        
        <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
        <FormField
          control={form.control}
          name="displayname"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Display Name <span className='text-xs'>(required)</span></FormLabel>
              <FormControl>
                <Input placeholder="Enter a display name" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <div className='bg-purplebrown-700 p-2 md:p-8 rounded-xl border border-foundry-golden/10 flex flex-col gap-5'>
          <h2 className='text-xl font-semibold text-foundry-golden font-firaSans'>Payment and Billing Information</h2>
          <p>These fields are required if you wish to purchase or sell on this site.</p>
          {errors.address && <FormMessage>
            Please fill out all requried fields.
          </FormMessage>}
 
          <hr className='border border-foundry-golden/10' />
#
<AddressElement


            onChange={(event) => {
              const { value } = event;
              setValue('name', (value.name || ''));
              setValue('address.line1', value.address.line1);
              setValue('address.line2', value.address.line2);
              setValue('address.city', value.address.city);
              setValue('address.state', value.address.state);
              setValue('address.country', value.address.country);
              setValue('address.postal_code', value.address.postal_code);
            }}
            options={{
              mode: 'billing',

              fields: {
                phone: 'never',
              },
              defaultValues: {
                name: currentUser?.full_name || '',
                // firstName: currentUser?.first_name || '',
                // lastName: currentUser?.last_name || '',
                address : {
                  line1: currentUser?.address1 || '',
                  line2: currentUser?.address2 || '',
                  city: currentUser?.city || '',
                  state: currentUser?.state || '',
                  postal_code: currentUser?.zip || '',
                  country: currentUser?.country || '',
                }
              },
            }} // Required options
          />
#
<FormField
            control={form.control}
            name="phone_num"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Phone (optional)</FormLabel>
                <FormControl>
                  <Input placeholder="Enter phone number" {...field} />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
          <FormField
            control={form.control}
            name="currency"
            render={({ field }) => (
              <FormItem className="space-y-3">
                <FormLabel>Currency</FormLabel>
                <FormControl>
                  <RadioGroup
                    onValueChange={field.onChange}
                    defaultValue={field.value || 'USD'}
                    className="flex flex-row justify-start items-center self-center gap-4"
                  >
                    <FormItem className="flex items-center space-x-3 space-y-0">
                      <FormControl>
                        <RadioGroupItem value="USD" />
                      </FormControl>
                      <FormLabel className="font-normal">
                        USD
                      </FormLabel>
                    </FormItem>
                    <FormItem className="flex items-center space-x-3 space-y-0">
                      <FormControl>
                        <RadioGroupItem value="EUR" />
                      </FormControl>
                      <FormLabel className="font-normal">
                        EUR
                      </FormLabel>
                    </FormItem>
                  </RadioGroup>
                </FormControl>
                {showCurrencyNudge && <CurrencyReminder handleNudgeDismiss={handleNudgeDismiss} />}
                <FormMessage />
              </FormItem>
            )}
          />
        </div>
        <Button type="submit">Save</Button>
      </form>
    </Form>
  </TitledBox>

  <TitledBox title='Badges' className='flex justify-start p-4 relative'>
  {currentUser && currentUser.badges && currentUser.badges.length > 0 && (
      <div className='flex flex-col gap-2'>
                  {currentUser.badges.map((badge: any, index: number) => (
                      <span key={index} className='flex gap-2'>
                          {badge.url && <img src={badge.url} alt={badge.name} className='w-8 h-8' />}
                          {badge.name}
                      </span>
                  ))}
              </div>       
  )}
  </TitledBox>

  {/* <button type='button' className='bg-white/25 rounded-lg px-1'
      onClick={onTestClick}
  >
      Get Foundry VTT Record
  </button> */}

  {accountRecord && (
  <TitledBox title='Record JSON' className='flex justify-start p-4 relative'>
          <pre>
              {JSON.stringify(accountRecord, null, 2)}
          </pre>
  </TitledBox>
  )}

</div>
  )
}

export default AccountTab
sonic ferry
#

titlebox is just a div wrapper doesnt do anythign special

vast turtle
#

Hmm So I don't see Elements getting initialized in the parent component or the AccountTab component

sonic ferry
vast turtle
#

Right but that's not part of the component tree from which AddressElement is rendered correct?

sonic ferry
#

it is:

page.tsx (that page)
profilepage
accounttab

vast turtle
#

Ah okay.
What happens if you move <Elements /> code to Account Tab instead?
Or move <AddressElement /> to Profile Page?

sonic ferry
#

one moment

sonic ferry
#

moving address element up one component that is

vast turtle
#

Hmm quite weird. It is almost as if the Address Element is unable to find the Elements..

Try moving <Elements /> to Account Tab?

sonic ferry
#

ok one moment

#

same error.

i removed completely from parentage, used elements as main element of accounttab render, did full rebuild (not hot reload). same outcome

minor sundialBOT
sonic ferry
#

starting to feel like when they call more doctors into the surgery room.... never a good sign

hushed flame
#

๐Ÿ‘‹ stepping in here as hanzo needs to step away

#

Okay there is a lot of backscroll and I'm catching up but it seems there is an issue rendering AddressElement?

sonic ferry
#

yes this message

hushed flame
#

Okay let's comment everything out and just do:

 <Elements stripe={stripe} >
       <AddressElement options={{mode: 'shipping'}} />
    </Elements>
#

So as bare-bones as possible

#

Let's make sure the basic example renders

sonic ferry
#

'use client'

import React, { useState } from 'react'


import { AddressElement, Elements } from '@stripe/react-stripe-js';


import { loadStripe } from '@stripe/stripe-js';

const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY as string);

type Props = {
  handleNudgeDismiss: () => void;
}


function AccountTab({handleNudgeDismiss}: Props) {

    // console.log(process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY as string)

  



  return (
    <Elements stripe={stripePromise} >
    <AddressElement options={{mode: 'shipping'}} />
 </Elements>

  )
}

export default AccountTab


#

full page now

hushed flame
#

Okay and same error?

sonic ferry
#

doing a full rebuild to be sure but the hot reload was yes error

hushed flame
#

Great

sonic ferry
#

still error after a full rebuild

#

i can log the key so should be present

hushed flame
#

Are you sure there isn't an Elements component anywhere else in your code?

sonic ferry
#

the one i commented out, and this one

#

this results in no error, so pretty sure its from here

hushed flame
#

K one sec

#

Let me spin up my sample real quick to make sure I'm not going crazy

sonic ferry
#

appreciate it

hushed flame
#

Huh okay interesting..... when I don't render Elements with a clientsecret I see that error, however my AddressElement still renders.... ?

#

Looking more

sonic ferry
#

yes it does render i just get the error and i believe validation does not occur, the input boxes seem to work fine though

hushed flame
#

ah

#

Thanks for clarifying

sonic ferry
#

this does log a key on every render, never a null

#

i confirmed the key i'm using is the key in the stripe test developer dashboard

hushed flame
#

Yeah I don't think the key is the issue

#

I am wondering if this was never built to be displayed as a standalone Element. Or if the work wasn't finished to enable that -- the error talks about a nullableSessionSelector() but that is an internal state and not something that I'm aware of being able to set.

#

Looking more though give me a few mins

sonic ferry
#

ya i could not find documentation on that

#

this did at one time work though, when i first made the page. it just later started to fail, presumably during some npm package update

hushed flame
#

Okay that's good to know. So I think for now what I'd recommend is just putting in some fake options. Like you can do:

  let options = {
    mode: 'payment',
    amount: 1000,
    currency: 'usd',
  }
#

And I'll go flag internally that this isn't currently working

#

By just omitting options here, since it really shouldn't be required

sonic ferry
#

and those options go on the address element?

hushed flame
#

(To be clear, you pass those options to your Elements Provider)

sonic ferry
#

right, got it

hushed flame
#

Yeah those options are how you would do the deferred-intent Payment Element or Express Checkout Element flow.

sonic ferry
#

Type '"payment"' is not assignable to type 'AddressMode'.

#
    <Elements stripe={stripePromise} >
      <AddressElement 
        options={{
          mode: 'payment',
          amount: 1000,
          currency: 'usd',
      }} />
    </Elements>

assuming i did that right

hushed flame
#

<Elements stripe={stripePromise} options={options}>

sonic ferry
#

oh

hushed flame
#

You pass options to Elements

sonic ferry
#

oh, ya , my bad

hushed flame
#

np!

sonic ferry
#

that indeed makes the error cease on the minimal example

hushed flame
#

You said this did work for you in the past when you omitted passing any options to <Elements /> ?

sonic ferry
#

my fallible human memory does insist that is the case. i do not have actual proof, but i believed it to have been working when i made it

hushed flame
#

No worries

#

Regardless it should just work!

sonic ferry
hushed flame
#

Yay!

sonic ferry
#

now to see if it validates an address...

#

Also appears to work, thank you so much

hushed flame
#

Yay!

sonic ferry
#

an additional note, unless its something i'm done. if i select an address it finds thru the drop down it only appears to give me the part i didnt already type not the full line

hushed flame
#

Hmm can you explain more what you mean?

sonic ferry
#

i'll make a little video one sec

sonic ferry
hushed flame
#

Ah that's good to hear

sonic ferry
#

basically if i typed 123 main street, and selected it from the list, only "main street" would go in the box without the numbers

hushed flame
#

Hmm yeah it probably does only autocomplete on a real address?

#

I'm not positive on that but if you see that with an actual address then I could look some more.

sonic ferry
#

will report if so