1- "use client"
2- import * as z from "zod" ;
3- import { Card , CardFooter } from "@/components/ui/card" ;
4- import { Loader } from "@/components/loader" ;
5- import { Heading } from "@/components/Heading"
1+ "use client" ;
62
3+ import * as z from "zod" ;
4+ import axios from "axios" ;
5+ import Image from "next/image" ;
6+ import { useState } from "react" ;
77import { zodResolver } from "@hookform/resolvers/zod" ;
8- import { Form , FormControl , FormField , FormItem } from "@/components/ui/form" ;
9- import { cn } from "@/lib/utils" ;
10- import { Input } from "@/components/ui/input" ;
8+ import { Download , ImageIcon } from "lucide-react" ;
119import { useForm } from "react-hook-form" ;
12- import { useState } from "react" ;
13- import { Button } from "@/components/ui/button" ;
10+ import { toast } from "react-hot-toast" ;
1411import { useRouter } from "next/navigation" ;
15- import { Download , ImageIcon } from "lucide-react" ;
16- import axios from "axios" ;
17- import { ChatCompletionRequestMessage } from "openai" ;
18- import { Empty } from "@/components/empty" ;
19- import { UserAvatar } from "@/components/user-avatar" ;
20- import { BotAvatar } from "@/components/bot-avatar" ;
21- import { Select , SelectContent , SelectItem , SelectTrigger , SelectValue } from "@/components/ui/select" ;
2212
13+ import { Heading } from "@/components/heading" ;
14+ import { Button } from "@/components/ui/button" ;
15+ import { Card , CardFooter } from "@/components/ui/card" ;
16+ import { Input } from "@/components/ui/input" ;
17+ import { Form , FormControl , FormField , FormItem } from "@/components/ui/form" ;
18+ import { Loader } from "@/components/loader" ;
19+ import { Empty } from "@/components/ui/empty" ;
20+ import { Select , SelectContent , SelectItem , SelectTrigger , SelectValue } from "@/components/ui/select" ;
2321import { useProModal } from "@/hooks/use-pro-modal" ;
24- import { amountOptions , formSchema , resolutionOptions } from "./constants" ;
25- import Image from "next/image" ;
26-
27-
2822
29- const ImagePage = ( ) => {
23+ import { amountOptions , formSchema , resolutionOptions } from "./constants" ;
3024
31- const router = useRouter ( ) ;
32- const [ images , setImages ] = useState < string [ ] > ( [ ] ) ;
33- const proModal = useProModal ( ) ;
25+ const PhotoPage = ( ) => {
26+ const proModal = useProModal ( ) ;
27+ const router = useRouter ( ) ;
28+ const [ photos , setPhotos ] = useState < string [ ] > ( [ ] ) ;
3429
35- const form = useForm < z . infer < typeof formSchema > > ( {
36- resolver : zodResolver ( formSchema ) ,
37- defaultValues : {
38- prompt : "" ,
30+ const form = useForm < z . infer < typeof formSchema > > ( {
31+ resolver : zodResolver ( formSchema ) ,
32+ defaultValues : {
33+ prompt : "" ,
3934 amount : "1" ,
4035 resolution : "512x512"
41- }
42- } ) ;
36+ }
37+ } ) ;
38+
39+ const isLoading = form . formState . isSubmitting ;
4340
44- const isLoading = form . formState . isSubmitting ;
41+ const onSubmit = async ( values : z . infer < typeof formSchema > ) => {
42+ try {
43+ setPhotos ( [ ] ) ;
4544
46- const onSubmit = async ( values : z . infer < typeof formSchema > ) => {
47- try {
48-
49- setImages ( [ ] ) ;
45+ const response = await axios . post ( '/api/image' , values ) ;
5046
51- const response = await axios . post ( '/api/image' , values ) ;
52-
53- const urls = response . data . map ( ( image : { url : string } ) => image . url ) ;
54-
55-
56- setImages ( urls )
57- form . reset ( ) ;
58- } catch ( error : any ) {
59- if ( error ?. response ?. status === 403 ) {
60- proModal . onOpen ( ) ;
61- } else {
62-
63- }
64- } finally {
65- router . refresh ( ) ;
47+ const urls = response . data . map ( ( image : { url : string } ) => image . url ) ;
48+
49+ setPhotos ( urls ) ;
50+ } catch ( error : any ) {
51+ if ( error ?. response ?. status === 403 ) {
52+ proModal . onOpen ( ) ;
53+ } else {
54+ toast . error ( "Something went wrong." ) ;
6655 }
56+ } finally {
57+ router . refresh ( ) ;
6758 }
59+ }
6860
69- return (
70-
71- < div >
72- < Heading
61+ return (
62+ < div >
63+ < Heading
7364 title = "Image Generation"
7465 description = "Turn your prompt into an image."
7566 icon = { ImageIcon }
7667 iconColor = "text-pink-700"
7768 bgColor = "bg-pink-700/10"
7869 />
7970 < div className = "px-4 lg:px-8" >
80- < div >
81- < Form { ...form } onSubmit = { form . handleSubmit ( onSubmit ) } >
82- < form
83- onSubmit = { form . handleSubmit ( onSubmit ) }
84- className = "
85- rounded-lg
86- border
87- w-full
88- p-4
89- px-3
90- md:px-6
91- focus-within:shadow-sm
92- grid
93- grid-cols-12
94- gap-2
95- "
96- >
97- < FormField
71+ < Form { ...form } >
72+ < form
73+ onSubmit = { form . handleSubmit ( onSubmit ) }
74+ className = "
75+ rounded-lg
76+ border
77+ w-full
78+ p-4
79+ px-3
80+ md:px-6
81+ focus-within:shadow-sm
82+ grid
83+ grid-cols-12
84+ gap-2
85+ "
86+ >
87+ < FormField
9888 name = "prompt"
9989 render = { ( { field } ) => (
10090 < FormItem className = "col-span-12 lg:col-span-6" >
@@ -109,10 +99,9 @@ const ImagePage = () => {
10999 </ FormItem >
110100 ) }
111101 />
112-
113- < FormField
102+ < FormField
114103 control = { form . control }
115- name = "resolution "
104+ name = "amount "
116105 render = { ( { field } ) => (
117106 < FormItem className = "col-span-12 lg:col-span-2" >
118107 < Select
@@ -127,7 +116,7 @@ const ImagePage = () => {
127116 </ SelectTrigger >
128117 </ FormControl >
129118 < SelectContent >
130- { resolutionOptions . map ( ( option ) => (
119+ { amountOptions . map ( ( option ) => (
131120 < SelectItem
132121 key = { option . value }
133122 value = { option . value }
@@ -140,10 +129,9 @@ const ImagePage = () => {
140129 </ FormItem >
141130 ) }
142131 />
143-
144- < FormField
132+ < FormField
145133 control = { form . control }
146- name = "amount "
134+ name = "resolution "
147135 render = { ( { field } ) => (
148136 < FormItem className = "col-span-12 lg:col-span-2" >
149137 < Select
@@ -158,7 +146,7 @@ const ImagePage = () => {
158146 </ SelectTrigger >
159147 </ FormControl >
160148 < SelectContent >
161- { amountOptions . map ( ( option ) => (
149+ { resolutionOptions . map ( ( option ) => (
162150 < SelectItem
163151 key = { option . value }
164152 value = { option . value }
@@ -171,23 +159,21 @@ const ImagePage = () => {
171159 </ FormItem >
172160 ) }
173161 />
174- < Button className = "col-span-12 lg:col-span-2 w-full" type = "submit" disabled = { isLoading } >
175- Generate
176- </ Button >
177- </ form >
178- </ Form >
179- </ div >
180- < div className = "space-y-4 mt-4" >
181- { isLoading && (
182- < div className = "p-20" >
183- < Loader />
184- </ div >
185- ) }
186- { images . length === 0 && ! isLoading && (
162+ < Button className = "col-span-12 lg:col-span-2 w-full" type = "submit" disabled = { isLoading } size = "icon" >
163+ Generate
164+ </ Button >
165+ </ form >
166+ </ Form >
167+ { isLoading && (
168+ < div className = "p-20" >
169+ < Loader />
170+ </ div >
171+ ) }
172+ { photos . length === 0 && ! isLoading && (
187173 < Empty label = "No images generated." />
188174 ) }
189- < div className = "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 mt-8" >
190- { images . map ( ( src ) => (
175+ < div className = "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 mt-8" >
176+ { photos . map ( ( src ) => (
191177 < Card key = { src } className = "rounded-lg overflow-hidden" >
192178 < div className = "relative aspect-square" >
193179 < Image
@@ -205,13 +191,9 @@ const ImagePage = () => {
205191 </ Card >
206192 ) ) }
207193 </ div >
208- </ div >
209194 </ div >
210- </ div >
211-
212-
213- )
195+ </ div >
196+ ) ;
214197}
215-
216-
217- export default ImagePage
198+
199+ export default PhotoPage ;
0 commit comments