@@ -195,7 +195,7 @@ const ProfileForm: React.FC<{ onSave: () => void }> = ({ onSave }) => {
195195const MomentForm : React . FC < { onSave : ( ) => void } > = ( { onSave } ) => {
196196 const { user, profile } = useAuth ( ) ;
197197 const [ caption , setCaption ] = useState ( '' ) ;
198- const [ imagePreview , setImagePreview ] = useState < string | null > ( null ) ;
198+ const [ imagePreviews , setImagePreviews ] = useState < string [ ] > ( [ ] ) ;
199199 const [ loading , setLoading ] = useState ( false ) ;
200200
201201 // Helper function to get UUID from profile ID
@@ -257,21 +257,37 @@ const MomentForm: React.FC<{ onSave: () => void }> = ({ onSave }) => {
257257 } ;
258258
259259 const handleFileChange = ( e : React . ChangeEvent < HTMLInputElement > ) => {
260- const file = e . target . files ?. [ 0 ] ;
261- if ( file ) {
262- const reader = new FileReader ( ) ;
263- reader . onloadend = ( ) => setImagePreview ( reader . result as string ) ;
264- reader . readAsDataURL ( file ) ;
265- }
260+ const files = Array . from ( e . target . files || [ ] ) ;
261+ if ( files . length === 0 ) return ;
262+
263+ Promise . all (
264+ files . map ( ( file ) => new Promise < string > ( ( resolve , reject ) => {
265+ const reader = new FileReader ( ) ;
266+ reader . onloadend = ( ) => resolve ( reader . result as string ) ;
267+ reader . onerror = ( ) => reject ( new Error ( 'Failed to read selected image' ) ) ;
268+ reader . readAsDataURL ( file ) ;
269+ } ) )
270+ )
271+ . then ( ( newPreviews ) => setImagePreviews ( ( prev ) => [ ...prev , ...newPreviews ] ) )
272+ . catch ( ( error ) => {
273+ console . error ( 'Error reading images:' , error ) ;
274+ alert ( 'Failed to read one or more selected images.' ) ;
275+ } ) ;
276+
277+ e . target . value = '' ;
266278 } ;
267279
268280 const handleSubmit = async ( e : React . FormEvent ) => {
269281 e . preventDefault ( ) ;
270- if ( ! imagePreview || ! user ) return ;
282+ if ( imagePreviews . length === 0 || ! user ) return ;
271283 setLoading ( true ) ;
272284 try {
273285 const userId = await getUserIdAsUUID ( user . id ) ;
274- await momentService . createMoment ( { user_id : userId , image_url : imagePreview , caption } ) ;
286+ await Promise . all (
287+ imagePreviews . map ( ( imageUrl ) =>
288+ momentService . createMoment ( { user_id : userId , image_url : imageUrl , caption } )
289+ )
290+ ) ;
275291 onSave ( ) ;
276292 } catch ( error : any ) {
277293 console . error ( 'Error creating moment:' , error ) ;
@@ -284,21 +300,31 @@ const MomentForm: React.FC<{ onSave: () => void }> = ({ onSave }) => {
284300 return (
285301 < form onSubmit = { handleSubmit } className = "space-y-6" >
286302 < div className = "flex flex-col items-center gap-4" >
287- { imagePreview ? (
288- < div className = "relative w-full aspect-square rounded-3xl overflow-hidden border-2 border-indigo-500/30" >
289- < img src = { imagePreview } className = "w-full h-full object-cover" alt = "Preview" />
290- < button onClick = { ( ) => setImagePreview ( null ) } className = "absolute top-4 right-4 bg-black/50 p-2 rounded-full" > < X size = { 20 } /> </ button >
303+ { imagePreviews . length > 0 ? (
304+ < div className = "w-full grid grid-cols-2 gap-3" >
305+ { imagePreviews . map ( ( preview , index ) => (
306+ < div key = { `${ preview } -${ index } ` } className = "relative aspect-square rounded-3xl overflow-hidden border-2 border-indigo-500/30" >
307+ < img src = { preview } className = "w-full h-full object-cover" alt = "Preview" />
308+ < button type = "button" onClick = { ( ) => setImagePreviews ( ( prev ) => prev . filter ( ( _ , i ) => i !== index ) ) } className = "absolute top-4 right-4 bg-black/50 p-2 rounded-full" > < X size = { 20 } /> </ button >
309+ </ div >
310+ ) ) }
291311 </ div >
292312 ) : (
293313 < label className = "w-full aspect-square rounded-3xl border-2 border-dashed border-zinc-700 bg-zinc-900/50 flex flex-col items-center justify-center cursor-pointer hover:bg-zinc-800 transition-colors" >
294314 < Camera size = { 48 } className = "text-zinc-500 mb-4" />
295- < span className = "text-[10px] font-black uppercase tracking-widest text-zinc-500" > Capture the Moment</ span >
296- < input type = "file" className = "hidden" accept = "image/*" onChange = { handleFileChange } />
315+ < span className = "text-[10px] font-black uppercase tracking-widest text-zinc-500" > Capture Moment(s)</ span >
316+ < input type = "file" multiple className = "hidden" accept = "image/*" onChange = { handleFileChange } />
317+ </ label >
318+ ) }
319+ { imagePreviews . length > 0 && (
320+ < label className = "w-full py-3 rounded-2xl border border-zinc-700 bg-zinc-900/60 text-center text-xs font-black uppercase tracking-widest text-zinc-300 cursor-pointer hover:border-indigo-500/40 hover:text-indigo-300 transition-colors" >
321+ Add More Images
322+ < input type = "file" multiple className = "hidden" accept = "image/*" onChange = { handleFileChange } />
297323 </ label >
298324 ) }
299325 </ div >
300326 < Textarea label = "CAPTION" value = { caption } onChange = { ( e ) => setCaption ( e . target . value ) } placeholder = "What went down?" />
301- < Button type = "submit" disabled = { loading || ! imagePreview } className = "w-full py-4" > SHARE WITH SQUAD</ Button >
327+ < Button type = "submit" disabled = { loading || imagePreviews . length === 0 } className = "w-full py-4" > SHARE WITH SQUAD</ Button >
302328 </ form >
303329 ) ;
304330} ;
0 commit comments