photos()->ordered()->get(); return response()->json([ 'photos' => $photos, 'featured_photo' => $park->featuredPhoto(), ]); } /** * Store a newly uploaded photo. */ public function store(Request $request, Park $park) { $request->validate([ 'photo' => 'required|image|max:10240', // 10MB max 'title' => 'nullable|string|max:255', 'description' => 'nullable|string', 'alt_text' => 'nullable|string|max:255', 'credit' => 'nullable|string|max:255', 'source_url' => 'nullable|url|max:255', 'is_featured' => 'nullable|boolean', ]); // Handle file upload if ($request->hasFile('photo')) { $file = $request->file('photo'); $originalFilename = $file->getClientOriginalName(); $extension = $file->getClientOriginalExtension(); // Generate a unique filename $filename = time() . '_' . Str::slug(pathinfo($originalFilename, PATHINFO_FILENAME)) . '.' . $extension; // Define the storage path $storagePath = 'photos/parks/' . $park->id; $fullPath = $storagePath . '/' . $filename; // Store the original file $file->storeAs('public/' . $storagePath, $filename); // Create image manager instance $manager = new ImageManager(new Driver()); // Get image dimensions $image = $manager->read($file); $width = $image->width(); $height = $image->height(); // Generate thumbnail $thumbnailFilename = pathinfo($filename, PATHINFO_FILENAME) . '_thumb.' . $extension; $thumbnail = $manager->read($file)->scaleDown(width: 300, height: 300); // Save thumbnail $encodedThumbnail = $thumbnail->encode( new JpegEncoder(80) ); Storage::put( 'public/' . $storagePath . '/' . $thumbnailFilename, $encodedThumbnail->toString() ); // Create photo record $photo = $park->addPhoto([ 'title' => $request->input('title'), 'description' => $request->input('description'), 'file_path' => $fullPath, 'file_name' => $originalFilename, 'file_size' => $file->getSize(), 'mime_type' => $file->getMimeType(), 'width' => $width, 'height' => $height, 'alt_text' => $request->input('alt_text'), 'credit' => $request->input('credit'), 'source_url' => $request->input('source_url'), 'is_featured' => $request->input('is_featured', false), ]); return response()->json([ 'message' => 'Photo uploaded successfully', 'photo' => $photo, ], 201); } return response()->json([ 'message' => 'No photo file provided', ], 400); } /** * Display the specified photo. */ public function show(Photo $photo) { return response()->json($photo); } /** * Update the specified photo. */ public function update(Request $request, Photo $photo) { $request->validate([ 'title' => 'nullable|string|max:255', 'description' => 'nullable|string', 'alt_text' => 'nullable|string|max:255', 'credit' => 'nullable|string|max:255', 'source_url' => 'nullable|url|max:255', 'is_featured' => 'nullable|boolean', ]); $photo->update($request->only([ 'title', 'description', 'alt_text', 'credit', 'source_url' ])); // Handle featured status if ($request->has('is_featured') && $request->input('is_featured')) { $photo->setAsFeatured(); } return response()->json([ 'message' => 'Photo updated successfully', 'photo' => $photo, ]); } /** * Remove the specified photo. */ public function destroy(Photo $photo) { // Get the file paths $filePath = 'public/' . $photo->file_path; $pathInfo = pathinfo($photo->file_path); $thumbnailPath = 'public/' . $pathInfo['dirname'] . '/' . $pathInfo['filename'] . '_thumb.' . $pathInfo['extension']; // Delete the files Storage::delete([$filePath, $thumbnailPath]); // Delete the record $photo->delete(); return response()->json([ 'message' => 'Photo deleted successfully', ]); } /** * Reorder photos for a park. */ public function reorder(Request $request, Park $park) { $request->validate([ 'photo_ids' => 'required|array', 'photo_ids.*' => 'required|integer|exists:photos,id', ]); $success = $park->reorderPhotos($request->input('photo_ids')); if ($success) { return response()->json([ 'message' => 'Photos reordered successfully', ]); } return response()->json([ 'message' => 'Failed to reorder photos', ], 500); } /** * Set a photo as featured. */ public function setFeatured(Request $request, Park $park, Photo $photo) { if ($photo->photoable_id !== $park->id || $photo->photoable_type !== Park::class) { return response()->json([ 'message' => 'Photo does not belong to this park', ], 400); } $success = $park->setFeaturedPhoto($photo); if ($success) { return response()->json([ 'message' => 'Featured photo set successfully', ]); } return response()->json([ 'message' => 'Failed to set featured photo', ], 500); } }