shadcn-ui / ui

Beautifully designed components that you can copy and paste into your apps. Accessible. Customizable. Open Source.
https://ui.shadcn.com
MIT License
71.35k stars 4.3k forks source link

Form Handle onSubmit not working for me. Nothing happens #2031

Closed jayhubb4 closed 8 months ago

jayhubb4 commented 10 months ago

`"use client";

import { useState, useEffect } from 'react'; import * as z from 'zod'; import { zodResolver } from '@hookform/resolvers/zod' import { UserValidation } from '@/lib/validations/user'; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form"; import { useForm } from 'react-hook-form'; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; import Image from "next/image"; import { ChangeEvent } from 'react'; import { isBase64Image } from '@/lib/utils'; import { useUploadThing } from '@/lib/uploadthing'; import { updateUserProfile } from '@/lib/actions/user.actions'; import { usePathname, useRouter } from 'next/navigation'; import { UserData } from '@/lib/types/user'; import { doc, setDoc, getDoc, collection, serverTimestamp, GeoPoint } from 'firebase/firestore'; import { db } from '@/lib/firebase'; import { currentUser } from '@clerk/nextjs'; import { pmtMethods } from '@/lib/validations/user'; import { revalidatePath } from 'next/cache'; // import { userInfoArr } from '@/lib/actions/user.actions';

// These props are specifically from the form // interface Props { // user: { // id: string; // objectId: string; // username: string; // name: string; // bio: string; // image: string; // zipcode: string; // }; // btnTitle: string; // }

// * The optional fields should probably be in the new local interface for the pilot onboarding. interface UserProfile { user: { id: string; objectId: string; username: string; name: string; bio: string; image: string; zipcode: string; onboarded: boolean; path: string; memberSince: string; media?: string; specialty1?: string; specialty2?: string; specialty3?: string; specialty4?: string; specialty5?: string; pmtMethods?: typeof pmtMethods; prices?: string; facebook?: string; instagram?: string; tiktok?: string; linkedin?: string; isPilot: boolean; }; btnTitle: string; }

// export const onboardArray: { // c_id: string; // name: string; // profile_photo: string; // username: string; // bio: string; // zipCode: string; // isPilot: boolean; // }[] = [ // { // c_id: '', // name: '', // profile_photo: '', // username: '', // bio: '', // zipCode: '', // isPilot: false, // } // ];

const CreateAccount = ({ user, btnTitle }: UserProfile) => { const [files, setFiles] = useState<File[]>([]); const { startUpload } = useUploadThing('media'); const router = useRouter(); const pathname = usePathname(); const [showPilotOnboarding, setShowPilotOnboarding] = useState(false); const [isPilot, setIsPilot] = useState(false); const [onboardArray, setOnboardArray] = useState([ { c_id: '', name: '', profile_photo: '', username: '', bio: '', zipCode: '', isPilot: false, } ]);

const methods = useForm(); const { watch } = methods;

const watchIsPilot = watch('isPilot');

// // * Function to record the state of the checkbox and push its value into the array // const handleCheckboxChange = (checked: boolean) => { // setOnboardArray((prevOnboardArray) => [ // { // ...prevOnboardArray[0], // isPilot: checked, // }, // ]); // };

// Initialize variables to store location data let userLatitude: any = null; let userLongitude: any = null;

// Request the user's location using the Geolocation API if (typeof window !== 'undefined' && navigator.geolocation) { navigator.geolocation.getCurrentPosition((position) => { // Extract and store the latitude and longitude userLatitude = position.coords.latitude; userLongitude = position.coords.longitude;

  // Now you have the user's location, and you can use it as needed
  // For example, you can store it in Firestore or display it on a map
}, (error) => {
  console.error('Error getting user location:', error);
});

} else { console.error('Geolocation is not available in this browser.'); }

const form = useForm({ resolver: zodResolver(UserValidation), defaultValues: { profile_photo: '', name:'', username:'', bio:'', zipCode:'', isPilot: false, media: '', // * This is for uploading media to their profile initially. Editing their profile is still needed specialty1: '', specialty2: '', specialty3: '', specialty4: '', specialty5: '', pmtMethods: ["Zelle", "Cash"], prices: '', // businessHrs: user?.businessHrs || '', facebook: '', instagram: '', tiktok: '', linkedin: '', } });

const { handleSubmit } = useForm({ resolver: zodResolver(UserValidation) });

const handleImage = (e: ChangeEvent, fieldChange: (value: string) => void) => { e.preventDefault();

const fileReader = new FileReader();

if(e.target.files && e.target.files.length > 0) {
  const file = e.target.files[0];

  setFiles(Array.from(e.target.files));

  if(!file.type.includes('image')) return;

  fileReader.onload = async (event) => {
    const imageDataUrl = event.target?.result?.toString() || '';

    fieldChange(imageDataUrl);
  }

  fileReader.readAsDataURL(file);
}

};

const onSubmit = async (values: z.infer) => { const blob = values.profile_photo;

const hasImageChanged = isBase64Image(blob);

if(hasImageChanged) {
  const imgRes = await startUpload(files)

  if(imgRes && imgRes[0].url) {
    values.profile_photo = imgRes[0].url;
  }
}

// * Custom DOC ID for unique pilotID & userID. This follows DB structure

const pilotIdPath = `${values.username}-${'101'}`;
const userIdPath = `${values.username}-${'201'}`;

// Adds user's info to database via onboarding form submission & creates Doc in Firestore database // First (below) is for regular users only

const user = await currentUser(); const addUserRef = doc(db, 'customer-profiles', user?.id || userIdPath); const addPilotRef = doc(db, 'pilot-profiles', user?.id || userIdPath); const location = new GeoPoint(userLatitude, userLongitude);

if (isPilot) {
  await setDoc(addPilotRef,
   {
    id: pilotIdPath,
    c_id: user?.id, // TODO: This was orginally addUserRef.id. If nothing is returned Change it back. Also, this is the ID of the user from Clerk.
    username: values.username.toLowerCase(),
    name: values.name,
    image: values.profile_photo,
    bio: values.bio,
    zipcode: values.zipCode,
    path: pathname,
    profileId: 101, // IDs for users and pilots 101 = user, 201 = pilots
    onboarded: true,
    coordinates: location,
    memberSince: serverTimestamp(),
    specialties: [
      values.specialty1,
      values.specialty2,
      values.specialty3,
      values.specialty4,
      values.specialty5,
    ],
    pmtMethods: values.pmtMethods,
    prices: values.prices,
    socials: [
      values.facebook,
      values.instagram,
      values.tiktok,
      values.linkedin,
    ]
  })
  console.log("Document written with ID: ", addUserRef.id); // TODO: This was orginally addUserRef.id. If nothing is returned Change it back
} else {
  await setDoc(addUserRef,
   {
    id: userIdPath,
    c_id: user?.id, // TODO: This was orginally addUserRef.id. If nothing is returned Change it back. Also, this is the ID of the user from Clerk.
    username: values.username.toLowerCase(),
    name: values.name,
    image: values.profile_photo,
    bio: values.bio,
    zipcode: values.zipCode,
    path: pathname,
    profileId: 201, // IDs for users and pilots 101 = user, 201 = pilots
    onboarded: true,
    coordinates: location,
    memberSince: serverTimestamp()
  })
  console.log("Document written with ID: ", addUserRef.id); // TODO: This was orginally addUserRef.id. If nothing is returned Change it back
}

if (pathname === "/profile/edit") {
  router.back();
} else {
  router.push("/");
}

revalidatePath(pathname);

// // Read items from database
// const getID = await getDoc(addUserRef);
// const data: UserData | undefined = getID.exists() ?
// getID.data() as UserData : undefined;

// // This fucntion pushes data into the UserData object and it is used in the 'find-pilot page'

// if (data) {
//   console.log(data.id);
// } else {
//   console.log('Could not find.');
// }

// onboardArray.push({
//   name: values.name,
//   c_id: user?.id || '', // TODO: This was orginally addUserRef.id. If nothing is returned Change it back. Also, this is the ID of the user from Clerk.
//   username: values.username.toLowerCase(),
//   profile_photo: values.profile_photo,
//   bio: values.bio,
//   zipCode: values.zipCode,
//   isPilot: values.isPilot || false
// })

// console.log(form.formState.errors)

}

return ( <Form {...form}> <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8 flex flex-col justify-start gap-10"

<FormField control={form.control} name="profile_photo" render={({ field }) => (

{field.value ? ( profile photo ) : ( profile photo )} handleImage(e, field.onChange)}
              // onChange={(e) => {
              //   handleImage(e, field.onChange)
              //   setFormData({
              //     ...formData,
              //     profile_photo: e.target.value
              //   });
              // }}
                 />
          </FormControl>
        </FormItem>
      )}
    />

    <FormField
      control={form.control}
      name="name"
      render={({ field }) => (
        <FormItem className='flex gap-3 w-full flex-col'>
          <FormLabel className='text-base-semibold text-light-2 '>
            Name
          </FormLabel>
          <FormControl>
            <Input 
              type='text'
              className='account-form_input no-focus'
              {...field}
              // onChange={(e) => 
              //   setFormData({ 
              //     ...formData, name: e.target.value 
              //   })}
            />
          </FormControl>
          <FormMessage />
        </FormItem>
      )}
    />

    <FormField
      control={form.control}
      name="username"
      render={({ field }) => (
        <FormItem className='flex gap-3 w-full flex-col'>
          <FormLabel className='text-base-semibold text-light-2 '>
            Username
          </FormLabel>
          <FormControl>
            <Input 
              type='text'
              className='account-form_input no-focus'
              {...field}
              // onChange={(e) => 
              //   setFormData({ 
              //     ...formData, username: e.target.value 
              //   })}
            />
          </FormControl>
          <FormMessage />
        </FormItem>
      )}
    />

    <FormField
      control={form.control}
      name="bio"
      render={({ field }) => (
        <FormItem className='flex gap-3 w-full flex-col'>
          <FormLabel className='text-base-semibold text-light-2 '>
            Bio
          </FormLabel>
          <FormControl>
            <Textarea
              rows={10}
              className='account-form_input no-focus'
              {...field}
              // onChange={(e) => 
              //   setFormData({ 
              //     ...formData, bio: e.target.value 
              //   })}
            />
          </FormControl>
        </FormItem>
      )}
    />

    <FormField
      control={form.control}
      name="zipCode"
      render={({ field }) => (
        <FormItem className='flex gap-3 w-full flex-col'>
          <FormLabel className='text-base-semibold text-light-2 '>
            Zip Code
          </FormLabel>
          <FormControl>
            <Input 
              type='text'
              className='account-form_input no-focus'
              {...field}
              // onChange={(e) => 
              //   setFormData({ 
              //     ...formData, username: e.target.value 
              //   })}
            />
          </FormControl>
          <FormMessage />
        </FormItem>
      )}
    />

    <FormField
      control={form.control}
      name='isPilot'
      render={({ field }) => (
        <FormItem>
          <FormControl className='flex flex-row'>
            <Checkbox
              className='border-blue'
              checked={watchIsPilot || field.value}
              onCheckedChange={(checked) => {
                methods.setValue('isPilot', checked);
              }}
              // onCheckedChange={(checked) => { // * This checks if the user is a pilot and records the value
              //   if (typeof checked === 'boolean') {
              //     field.onChange();
              //     handleCheckboxChange(checked);
              //   }
              // }}
            />
          </FormControl>
          <div className="space-y-1 leading-none">
            <FormLabel className='text-base-semibold text-light-2'>
              Check this if you are a pilot
            </FormLabel>
            <FormDescription>
              Need a bit more information if you are, that&apos;s all. If you&apos;re not a pilot, you&apos;re done!
            </FormDescription>
          </div>
        </FormItem>
      )}
    />

    {watchIsPilot ? (
      <>
              <FormField
                control={form.control}
                name="specialty1"
                render={({ field }) => (
                  <FormItem className='flex gap-3 w-full flex-col'>
                    <FormLabel className='text-base-semibold text-light-2 '>
                      Specialties
                    </FormLabel>
                    <FormControl>
                      <Input 
                        type='text'
                        className='account-form_input no-focus'
                        {...field}
                        placeholder='e.g Monitoring & Management'
                        // onChange={(e) => 
                        //   setFormData({ 
                        //     ...formData, username: e.target.value 
                        //   })}
                      />
                    </FormControl>
                  </FormItem>
                )}
              />
              <FormField
                control={form.control}
                name="specialty2"
                render={({ field }) => (
                  <FormItem className='flex gap-3 w-full flex-col'>
                    <FormControl>
                      <Input 
                        type='text'
                        className='account-form_input no-focus'
                        {...field}
                        placeholder='e.g Mapping & Surveying'
                        // onChange={(e) => 
                        //   setFormData({ 
                        //     ...formData, username: e.target.value 
                        //   })}
                      />
                    </FormControl>
                  </FormItem>
                )}
              />
              <FormField
                control={form.control}
                name="specialty3"
                render={({ field }) => (
                  <FormItem className='flex gap-3 w-full flex-col'>
                    <FormControl>
                      <Input 
                        type='text'
                        className='account-form_input no-focus'
                        {...field}
                        placeholder='e.g Construction & Real Estate'
                        // onChange={(e) => 
                        //   setFormData({ 
                        //     ...formData, username: e.target.value 
                        //   })}
                      />
                    </FormControl>
                  </FormItem>
                )}
              />
              <FormField
                control={form.control}
                name="specialty4"
                render={({ field }) => (
                  <FormItem className='flex gap-3 w-full flex-col'>
                    <FormControl>
                      <Input 
                        type='text'
                        className='account-form_input no-focus'
                        {...field}
                        placeholder='e.g Photography & Videography'
                        // onChange={(e) => 
                        //   setFormData({ 
                        //     ...formData, username: e.target.value 
                        //   })}
                      />
                    </FormControl>
                  </FormItem>
                )}
              />
              <FormField
                control={form.control}
                name="specialty5"
                render={({ field }) => (
                  <FormItem className='flex gap-3 w-full flex-col'>
                    <FormControl>
                      <Input 
                        type='text'
                        className='account-form_input no-focus'
                        {...field}
                        placeholder='e.g Photography & Videography'
                        // onChange={(e) => 
                        //   setFormData({ 
                        //     ...formData, username: e.target.value 
                        //   })}
                      />
                    </FormControl>
                  </FormItem>
                )}
              />

      <FormField
        control={form.control}
        name="pmtMethods"
        render={() => (
          <FormItem>
            <div className="mb-4">
              <FormLabel className="text-base text-light-3">Payment Methods</FormLabel>
              <FormDescription>
                Select the payment methods that you accept.
              </FormDescription>
            </div>
            {pmtMethods.map((method) => (
              <FormField
                key={method.id}
                control={form.control}
                name="pmtMethods"
                render={({ field }) => {
                  return (
                    <FormItem
                      key={method.id}
                      className="flex flex-row items-start space-x-3 space-y-0"
                    >
                      <FormControl>
                        <Checkbox
                          className='border-blue'
                          checked={field.value?.includes(method.id)}
                          onCheckedChange={(checked) => {
                            return checked
                              ? field.onChange([...field.value, method.id])
                              : field.onChange(
                                  field.value?.filter(
                                    (value: string) => value !== method.id
                                  )
                                )
                          }}
                        />
                      </FormControl>
                      <FormLabel className="text-sm font-normal text-light-2">
                        {method.label}
                      </FormLabel>
                    </FormItem>
                  )
                }}
              />
            ))}
            <FormMessage />
          </FormItem>
        )}
      />

      <FormField
        control={form.control}
        name="prices"
        render={({ field }) => (
          <FormItem className='flex gap-3 w-full flex-col'>
            <FormLabel className='text-base-semibold text-light-2 '>
              Rates
            </FormLabel>
            <FormControl>
              <Input 
                type='text'
                className='account-form_input no-focus'
                {...field}
                placeholder='List your price range'
                // onChange={(e) => 
                //   setFormData({ 
                //     ...formData, username: e.target.value 
                //   })}
              />
            </FormControl>
            <FormMessage />
          </FormItem>
        )}
      />

      <FormField
        control={form.control}
        name="facebook"
        render={({ field }) => (
          <FormItem className='flex gap-3 w-full flex-col'>
            <FormLabel className='text-base-semibold text-light-2 '>
              Social Media 
            </FormLabel>
              <FormControl>
                <Input 
                  type='text'
                  className='account-form_input no-focus'
                  {...field}
                  placeholder='Add your Facebook profile link'
                  // onChange={(e) => 
                  //   setFormData({ 
                  //     ...formData, name: e.target.value 
                  //   })}
                />
              </FormControl>
            </FormItem>
            )}
          />
      <FormField
        control={form.control}
        name="instagram"
        render={({ field }) => (
          <FormItem className='flex gap-3 w-full flex-col'>
            <FormControl>
              <Input 
                type='text'
                className='account-form_input no-focus'
                {...field}
                placeholder='Add your Instagram profile link'
                // onChange={(e) => 
                //   setFormData({ 
                //     ...formData, name: e.target.value 
                //   })}
              />
            </FormControl>
            <FormMessage />
          </FormItem>
        )}
      />
      <FormField
        control={form.control}
        name="linkedin"
        render={({ field }) => (
          <FormItem className='flex gap-3 w-full flex-col'>
            <FormControl>
              <Input 
                type='text'
                className='account-form_input no-focus'
                {...field}
                placeholder='Add your TikTok profile link'
                // onChange={(e) => 
                //   setFormData({ 
                //     ...formData, name: e.target.value 
                //   })}
              />
            </FormControl>
            <FormMessage />
          </FormItem>
        )}
      />
      <FormField
        control={form.control}
        name="tiktok"
        render={({ field }) => (
          <FormItem className='flex gap-3 w-full flex-col'>
            <FormControl>
              <Input 
                type='text'
                className='account-form_input no-focus'
                {...field}
                placeholder='Add your LinkedIn profile link'
                // onChange={(e) => 
                //   setFormData({ 
                //     ...formData, name: e.target.value 
                //   })}
              />
            </FormControl>
            <FormMessage />
          </FormItem>
        )}
      />

      <p className='mt-3 text-base-regular text-light-2'>Thank you!</p>          
    </>

    ) : (
      <div>
        {/* Content for non-pilots */}
        <p className='mt-3 text-base-regular text-light-2'>Thank you!</p>
      </div>
    )}

    <Button 
      type="submit" 
      className='bg-primary-500'
      onSubmit={onSubmit}>{btnTitle}</Button>
  </form>
</Form>

) }

// {onboardArray[0].isPilot ? ( //

// {/ Content for pilots /} //

Additional content for pilots

//
// ) : ( //
// {/ Content for non-pilots /} //

Thank you!

//
// )}

export default CreateAccount; `

JuanPedroPontVerges commented 10 months ago

Please, provide a reproductable example so we are able to help you

josephdburdick commented 10 months ago

Please remove all commented code and ensure the code blocks are formatted correctly. Code without indentation is impossible to read on mobile.

jayhubb4 commented 10 months ago

Hi Shadcn-Ui/Ui,

I figured it out. It was a validation issue.

On Thu, Dec 7, 2023 at 5:31 PM Joe @.***> wrote:

Please remove all commented code and ensure the code blocks are formatted correctly. Code without indentation is impossible to read on mobile.

— Reply to this email directly, view it on GitHub https://github.com/shadcn-ui/ui/issues/2031#issuecomment-1846210008, or unsubscribe https://github.com/notifications/unsubscribe-auth/AYGIQ3KPKF6F33QIPYYXICLYII7UPAVCNFSM6AAAAABADXGIUOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNBWGIYTAMBQHA . You are receiving this because you authored the thread.Message ID: @.***>

arvind-iyer-2001 commented 10 months ago

image image

You gotta use the form HTML Component Without that No scene of the onSubmit action working.

shadcn commented 8 months ago

This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.