# Notification Toast System Documentation

## Overview

The Adopt-a-Street frontend now includes a comprehensive notification toast system that integrates with Socket.IO for real-time updates. The system uses `react-toastify` with custom styling that matches the Bootstrap theme.

## Features

- **Real-time notifications** via Socket.IO integration
- **Four toast types**: success, error, info, warning
- **Auto-dismiss** after 5 seconds (configurable)
- **Dismissible** by clicking or using the close button
- **Mobile responsive** with optimized positioning
- **Duplicate prevention** using toast IDs
- **Custom styling** matching Bootstrap theme
- **Accessibility** compliant with ARIA attributes

## Components

### NotificationProvider

Located at: `frontend/src/context/NotificationProvider.js`

The `NotificationProvider` component automatically listens to Socket.IO events and displays appropriate toast notifications. It must be wrapped within both `AuthProvider` and `SocketProvider`.

### Custom Styles

Located at: `frontend/src/styles/toastStyles.css`

Custom CSS that overrides react-toastify defaults to match the Bootstrap theme, including:
- Bootstrap color scheme (success green, error red, warning yellow, info blue)
- Responsive mobile layout
- Custom animations
- Dark mode support

## Setup

The notification system is already integrated into `App.js`:

```javascript
<AuthProvider>
  <SocketProvider>
    <NotificationProvider>
      <Router>
        {/* Your routes */}
      </Router>
      <ToastContainer
        position="top-right"
        autoClose={5000}
        hideProgressBar={false}
        newestOnTop={true}
        closeOnClick
        pauseOnHover
        draggable
        theme="light"
        limit={5}
      />
    </NotificationProvider>
  </SocketProvider>
</AuthProvider>
```

## Usage

### Method 1: Using the notify utility (Recommended)

```javascript
import { notify } from "../context/NotificationProvider";

// Success notification
notify.success("Operation completed successfully!");

// Error notification
notify.error("Something went wrong!");

// Info notification
notify.info("Here's some information");

// Warning notification
notify.warning("Please be careful!");

// With custom options
notify.success("Data saved!", {
  autoClose: 3000,
  position: "bottom-right",
});

// Dismiss specific toast
notify.dismiss("toast-id");

// Dismiss all toasts
notify.dismissAll();
```

### Method 2: Using toast directly

```javascript
import { toast } from "react-toastify";

// Basic usage
toast.success("Success message");
toast.error("Error message");
toast.info("Info message");
toast.warning("Warning message");

// Prevent duplicates with toast ID
toast.success("Message", {
  toastId: "unique-id",
});

// Custom content
toast.success(
  <div>
    <strong>Title</strong>
    <div>Message</div>
    <small>Details</small>
  </div>
);
```

### Method 3: Promise-based toasts

```javascript
const myPromise = fetch("/api/data");

toast.promise(myPromise, {
  pending: "Loading...",
  success: "Success!",
  error: "Failed!",
});
```

### Method 4: Loading toasts

```javascript
const toastId = toast.loading("Processing...");

// Later, update the toast
toast.update(toastId, {
  render: "Completed!",
  type: "success",
  isLoading: false,
  autoClose: 5000,
});
```

## Socket.IO Events

The `NotificationProvider` automatically handles these Socket.IO events:

### Connection Events
- `connect` - Shows success toast when connected
- `disconnect` - Shows error/warning toast when disconnected
- `reconnect` - Shows success toast when reconnected
- `reconnect_error` - Shows error toast if reconnection fails

### Event Updates (`eventUpdate`)
- `new_event` - New event created
- `participants_updated` - Event participants changed
- `event_updated` - Event details updated
- `event_deleted` - Event cancelled

### Task Updates (`taskUpdate`)
- `new_task` - New task available
- `task_completed` - Task completed by another user
- `task_updated` - Task details updated
- `task_deleted` - Task removed

### Street Updates (`streetUpdate`)
- `street_adopted` - Street adopted by a user
- `street_unadopted` - Street available for adoption

### Achievements
- `achievementUnlocked` - User unlocked an achievement
- `badgeUnlocked` - User earned a badge

### Social Updates
- `newPost` - New post created
- `newComment` - New comment on a post

### Generic Notification
- `notification` - Fallback for any custom notification with `type` and `message`

## Triggering Toasts from Components

### Example: Form Submission

```javascript
import React, { useState } from "react";
import { notify } from "../context/NotificationProvider";
import axios from "axios";

const MyComponent = () => {
  const [loading, setLoading] = useState(false);

  const handleSubmit = async (data) => {
    try {
      setLoading(true);
      await axios.post("/api/endpoint", data);
      notify.success("Data submitted successfully!");
    } catch (error) {
      notify.error(error.response?.data?.msg || "Failed to submit");
    } finally {
      setLoading(false);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* form fields */}
    </form>
  );
};
```

### Example: Real-time Updates

The `NotificationProvider` automatically handles Socket.IO events, but you can also trigger custom notifications:

```javascript
import { useContext } from "react";
import { SocketContext } from "../context/SocketContext";
import { notify } from "../context/NotificationProvider";

const MyComponent = () => {
  const { emit } = useContext(SocketContext);

  const sendNotification = () => {
    // This will be handled by the NotificationProvider
    emit("notification", {
      type: "success",
      message: "Custom notification message",
    });
  };

  return <button onClick={sendNotification}>Send Notification</button>;
};
```

## Configuration Options

### ToastContainer Options

Configured in `App.js`:

```javascript
<ToastContainer
  position="top-right"        // Position: top-left, top-right, top-center, bottom-left, bottom-right, bottom-center
  autoClose={5000}            // Auto close after 5 seconds
  hideProgressBar={false}     // Show progress bar
  newestOnTop={true}          // Stack newest toasts on top
  closeOnClick               // Close on click
  rtl={false}                // Right-to-left support
  pauseOnFocusLoss           // Pause when window loses focus
  draggable                  // Allow dragging to dismiss
  pauseOnHover               // Pause timer on hover
  theme="light"              // Theme: light, dark, colored
  limit={5}                  // Maximum number of toasts
/>
```

### Individual Toast Options

```javascript
toast.success("Message", {
  position: "top-right",
  autoClose: 5000,
  hideProgressBar: false,
  closeOnClick: true,
  pauseOnHover: true,
  draggable: true,
  toastId: "unique-id",      // Prevent duplicates
  onOpen: () => {},          // Callback on open
  onClose: () => {},         // Callback on close
  transition: Bounce,        // Custom transition
  className: "custom-class", // Custom CSS class
  bodyClassName: "body",     // Custom body class
  progressClassName: "bar",  // Custom progress bar class
  closeButton: <button />,   // Custom close button
});
```

## Mobile Responsiveness

The toast system is fully responsive:
- **Desktop**: Positioned in top-right corner (configurable)
- **Mobile (≤480px)**: Full-width toasts at the top of the screen
- **Touch-friendly**: Large touch targets for dismissing
- **Smooth animations**: Optimized for mobile performance

## Accessibility

- ARIA attributes for screen readers
- Keyboard navigation support
- Focus management
- Semantic HTML structure
- Color contrast compliance

## Best Practices

1. **Prevent duplicate toasts**: Always use `toastId` for repeated actions
2. **Keep messages concise**: Aim for 1-2 sentences
3. **Use appropriate types**: 
   - `success` for completed actions
   - `error` for failures
   - `warning` for cautions
   - `info` for neutral information
4. **Don't spam**: Limit notifications to important events
5. **Provide context**: Include relevant details (e.g., "Task 'Clean Street' completed")
6. **Auto-dismiss**: Use appropriate auto-close times (3-7 seconds)
7. **Persistent toasts**: Set `autoClose: false` for critical errors

## Styling Customization

To customize toast styles, edit `frontend/src/styles/toastStyles.css`:

```css
/* Change colors */
:root {
  --toastify-color-success: #28a745;
  --toastify-color-error: #dc3545;
  --toastify-color-warning: #ffc107;
  --toastify-color-info: #17a2b8;
}

/* Custom toast style */
.Toastify__toast--success {
  border-left: 4px solid var(--toastify-color-success);
}

/* Custom animations */
@keyframes customAnimation {
  /* your animation */
}
```

## Backend Integration

To trigger notifications from the backend, emit Socket.IO events:

```javascript
// In backend route
const io = req.app.get("io");

// Notify all connected users
io.emit("notification", {
  type: "info",
  message: "System maintenance in 5 minutes",
});

// Notify specific user
io.to(userSocketId).emit("achievementUnlocked", {
  badge: {
    name: "First Adoption",
    description: "Adopted your first street!",
  },
});

// Notify event participants
io.to(`event_${eventId}`).emit("eventUpdate", {
  type: "participants_updated",
  eventId,
  participants: updatedParticipants,
});
```

## Troubleshooting

### Toasts not appearing
1. Check that `ToastContainer` is in `App.js`
2. Verify `NotificationProvider` is wrapping your app
3. Check browser console for errors
4. Ensure Socket.IO is connected

### Duplicate toasts
1. Add `toastId` to prevent duplicates
2. Check if multiple components are triggering the same event
3. Use `toast.isActive(toastId)` to check before showing

### Styling issues
1. Verify `toastStyles.css` is imported in `App.js`
2. Check for CSS conflicts with Bootstrap
3. Inspect element to verify classes are applied
4. Clear browser cache

## Testing

Example test for components using notifications:

```javascript
import { render, screen, waitFor } from "@testing-library/react";
import { toast } from "react-toastify";
import MyComponent from "./MyComponent";

jest.mock("react-toastify", () => ({
  toast: {
    success: jest.fn(),
    error: jest.fn(),
  },
}));

test("shows success toast on submit", async () => {
  render(<MyComponent />);
  
  // Trigger action
  fireEvent.click(screen.getByText("Submit"));
  
  await waitFor(() => {
    expect(toast.success).toHaveBeenCalledWith("Success message");
  });
});
```

## Resources

- [react-toastify Documentation](https://fkhadra.github.io/react-toastify/)
- [Socket.IO Documentation](https://socket.io/docs/)
- [Bootstrap Colors](https://getbootstrap.com/docs/5.0/utilities/colors/)

## Support

For issues or questions:
1. Check this documentation
2. Review `notificationExamples.js` for usage examples
3. Check browser console for errors
4. Review Socket.IO connection status
