Skip to content

feat: Lost Cats Finder website with announcements, map view & image upload#8

Open
devin-ai-integration[bot] wants to merge 3 commits into
mainfrom
devin/1776338694-lost-cats-website
Open

feat: Lost Cats Finder website with announcements, map view & image upload#8
devin-ai-integration[bot] wants to merge 3 commits into
mainfrom
devin/1776338694-lost-cats-website

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot commented Apr 16, 2026

Summary

Adds a standalone Lost Cats Finder web application under the lost-cats/ directory. This is a React + TypeScript + Vite frontend for posting and browsing lost/found cat announcements.

Features:

  • Hero section with live lost/found/reunited stats
  • 6 hardcoded sample cat announcements with Unsplash images
  • Real-time search filtering by name, location, color, breed
  • Status filter tabs (All / Lost / Found / Reunited) with counts
  • "Post Announcement" modal form with HTML5 validation
  • Detail modal with full cat info and contact button
  • Responsive grid layout (1→2→3 columns)
  • Tailwind CSS styling with Lucide icons

Stack: React 18, TypeScript, Vite 6, Tailwind CSS 3, Lucide React, Leaflet + react-leaflet v4

Live preview: https://lost-cats-finder.surge.sh

Updates since last revision

  • Added interactive Map View — New Leaflet-based map (via react-leaflet@4) showing all cat announcements as color-coded markers: red = lost, blue = found, green = reunited. Map popups display the cat's photo, status, breed, and a "View Details" button. Includes a legend bar and a Grid/Map toggle in the toolbar. Each sample announcement now has lat/lng coordinates (NYC area).

  • Added drag & drop Image Upload — The "Post Announcement" form now has a drag-and-drop zone with file picker support. Uploaded images are converted to data URLs via FileReader and shown as an inline preview. Users can still paste an image URL as a fallback. The URL input is hidden when a file has been uploaded (clears on form close/submit).

  • Fixed "Invalid Date" bug (previous revision) — formatDate helper appends T00:00:00 to date strings before parsing.

Review & Testing Checklist for Human

  • Review lost-cats/src/App.tsx — all application logic (~790 lines) lives in a single component. In particular:
    • The handleSubmit function now constructs CatAnnouncement objects manually (instead of ...formData spread) because lat/lng need parseFloat conversion from string form state to number. Verify this doesn't silently drop any fields.
    • If no lat/lng is provided, the code falls back to a random offset from 40.7128, -74.006. This means new announcements will cluster near NYC regardless of the typed location text.
  • Verify map marker icon CDN URLs — The colored markers load from raw.githubusercontent.com/pointhi/leaflet-color-markers. If this third-party repo is removed or restructured, the map markers will break with no fallback.
  • Test image upload at the live site — Try dragging a photo onto the upload zone, using the file picker, and pasting a URL. Verify the preview appears and the posted announcement displays the uploaded image. Note: large images stored as data URLs in React state could cause performance issues.
  • Test map view — Toggle to Map view, verify all 6 markers appear with correct colors, click a marker popup, and click "View Details" to open the detail modal. Verify filters apply to map markers too.
  • Confirm react-leaflet@4 compatibility — v4 was chosen because v5 requires React 19. If the project upgrades to React 19 later, this should be revisited.

Notes

  • No backend — all announcements are stored in React state and lost on page refresh. This is a frontend prototype.
  • No unit/integration tests are included.
  • New dependencies added: leaflet, react-leaflet@4, @types/leaflet. The package-lock.json diff is large accordingly.
  • The Leaflet CSS is imported directly in App.tsx via import 'leaflet/dist/leaflet.css'.

Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/5876b90f983f47958188a58c3eea8682


Open with Devin

- Hero section with live stats (lost/found/reunited counts)
- 6 sample cat announcements with Unsplash photos
- Search by name, location, color, or breed
- Filter tabs (All / Lost / Found / Reunited)
- Post Announcement form modal with full validation
- Detail modal with cat info and Contact Now button
- Responsive design with Tailwind CSS
- Built with React + TypeScript + Vite
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

devin-ai-integration[bot]

This comment was marked as resolved.

Add formatDate helper that safely parses date strings with timezone
offset to prevent 'Invalid Date' display. Falls back to raw string
if parsing fails, or 'Date not provided' if empty.
Copy link
Copy Markdown
Contributor Author

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 7 additional findings in Devin Review.

Open in Devin Review

Comment thread lost-cats/src/App.tsx
</div>
</div>
<a
href={`tel:${selectedAnnouncement.contact}`}
Copy link
Copy Markdown
Contributor Author

@devin-ai-integration devin-ai-integration Bot Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 tel: link used for contact field that also accepts email addresses

The contact form field placeholder says "Phone or email" (line 411), indicating users can enter either a phone number or an email address. However, the "Contact Now" button in the detail modal always wraps the contact value in a tel: protocol link (lost-cats/src/App.tsx:500). If a user enters an email address as contact info, clicking "Contact Now" will attempt to initiate a phone call to the email string (e.g. tel:user@example.com), which will either fail or produce unexpected behavior on the user's device.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

- Interactive map view with Leaflet showing cat locations with color-coded markers (red=lost, blue=found, green=reunited)
- Grid/Map view toggle
- Drag & drop image upload with file picker and preview
- URL input fallback for image
- Added lat/lng coordinates to all sample data
@devin-ai-integration devin-ai-integration Bot changed the title feat: Lost Cats Finder website with announcements feat: Lost Cats Finder website with announcements, map view & image upload Apr 16, 2026
Copy link
Copy Markdown
Contributor Author

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 9 additional findings in Devin Review.

Open in Devin Review

Comment thread lost-cats/src/App.tsx

{/* Post Announcement Modal */}
{showForm && (
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center p-4 z-50" onClick={() => { setShowForm(false); setImagePreview(null) }}>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Image preview cleared on modal close but formData.image retained, causing ghost image on resubmit

When the form modal is closed (via backdrop click at line 513 or X button at line 520), setImagePreview(null) is called but formData.image is not cleared. If a user uploads a photo (which sets both imagePreview and formData.image to a data URL), then closes the modal, then reopens it:

  1. The upload zone checks imagePreview (line 645) which is null, so it shows the "Drag & drop a photo" placeholder — suggesting no image is attached.
  2. The URL input checks formData.image.startsWith('data:') (line 675), which is true, so it displays an empty string — hiding the stale data URL.
  3. If the user submits the form, formData.image still contains the old data URL, so the announcement is created with an image the user thought was removed.

This creates a mismatch between what the UI shows (no image) and what gets submitted (the previously uploaded image).

Suggested change
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center p-4 z-50" onClick={() => { setShowForm(false); setImagePreview(null) }}>
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center p-4 z-50" onClick={() => { setShowForm(false); setImagePreview(null); setFormData(prev => ({ ...prev, image: '' })) }}>
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants