import React, { useState, useEffect } from 'react' import { adminApi, tripsApi } from '../../api/client' import { useAuthStore } from '../../store/authStore' import { useToast } from '../shared/Toast' import { Bell, Zap, ArrowRight, CheckCircle, Navigation, User, Calendar, Clock, Image, MessageSquare, Tag, UserPlus, Download, MapPin, } from 'lucide-react' interface Trip { id: number title: string } interface AppUser { id: number username: string email: string } export default function DevNotificationsPanel(): React.ReactElement { const toast = useToast() const user = useAuthStore(s => s.user) const [sending, setSending] = useState(null) const [trips, setTrips] = useState([]) const [selectedTripId, setSelectedTripId] = useState(null) const [users, setUsers] = useState([]) const [selectedUserId, setSelectedUserId] = useState(null) useEffect(() => { tripsApi.list().then(data => { const list = (data.trips || data || []) as Trip[] setTrips(list) if (list.length > 0) setSelectedTripId(list[0].id) }).catch(() => {}) adminApi.users().then(data => { const list = (data.users || data || []) as AppUser[] setUsers(list) if (list.length > 0) setSelectedUserId(list[0].id) }).catch(() => {}) }, []) const fire = async (label: string, payload: Record) => { setSending(label) try { await adminApi.sendTestNotification(payload) toast.success(`Sent: ${label}`) } catch (err: any) { toast.error(err.message || 'Failed') } finally { setSending(null) } } const selectedTrip = trips.find(t => t.id === selectedTripId) const selectedUser = users.find(u => u.id === selectedUserId) const username = user?.username || 'Admin' const tripTitle = selectedTrip?.title || 'Test Trip' // ── Helpers ────────────────────────────────────────────────────────────── const Btn = ({ id, label, sub, icon: Icon, color, onClick, }: { id: string; label: string; sub: string; icon: React.ElementType; color: string; onClick: () => void }) => ( ) const SectionTitle = ({ children }: { children: React.ReactNode }) => (

{children}

) const TripSelector = () => ( ) const UserSelector = () => ( ) return (
DEV ONLY
Notification Testing
{/* ── Type Testing ─────────────────────────────────────────────────── */}
Type Testing

Test how each in-app notification type renders, sent to yourself.

fire('simple-me', { event: 'test_simple', scope: 'user', targetId: user?.id, params: {}, })} /> fire('boolean-me', { event: 'test_boolean', scope: 'user', targetId: user?.id, params: {}, inApp: { type: 'boolean', positiveCallback: { action: 'test_approve', payload: {} }, negativeCallback: { action: 'test_deny', payload: {} }, }, })} /> fire('navigate-me', { event: 'test_navigate', scope: 'user', targetId: user?.id, params: {}, })} /> fire('simple-admins', { event: 'test_simple', scope: 'admin', targetId: 0, params: {}, })} />
{/* ── Trip-Scoped Events ───────────────────────────────────────────── */} {trips.length > 0 && (
Trip-Scoped Events

Fires each trip event to all members of the selected trip (excluding yourself).

selectedTripId && fire('booking_change', { event: 'booking_change', scope: 'trip', targetId: selectedTripId, params: { actor: username, trip: tripTitle, booking: 'Test Hotel', type: 'hotel', tripId: String(selectedTripId) }, })} /> selectedTripId && fire('trip_reminder', { event: 'trip_reminder', scope: 'trip', targetId: selectedTripId, params: { trip: tripTitle, tripId: String(selectedTripId) }, })} /> selectedTripId && fire('photos_shared', { event: 'photos_shared', scope: 'trip', targetId: selectedTripId, params: { actor: username, trip: tripTitle, count: '5', tripId: String(selectedTripId) }, })} /> selectedTripId && fire('collab_message', { event: 'collab_message', scope: 'trip', targetId: selectedTripId, params: { actor: username, trip: tripTitle, preview: 'This is a test message preview.', tripId: String(selectedTripId) }, })} /> selectedTripId && fire('packing_tagged', { event: 'packing_tagged', scope: 'trip', targetId: selectedTripId, params: { actor: username, trip: tripTitle, category: 'Clothing', tripId: String(selectedTripId) }, })} />
)} {/* ── User-Scoped Events ───────────────────────────────────────────── */} {users.length > 0 && (
User-Scoped Events

Fires each user event to the selected recipient.

selectedUserId && fire(`trip_invite-${selectedUserId}`, { event: 'trip_invite', scope: 'user', targetId: selectedUserId, params: { actor: username, trip: tripTitle, invitee: selectedUser?.email || '', tripId: String(selectedTripId ?? 0) }, })} /> selectedUserId && fire(`vacay_invite-${selectedUserId}`, { event: 'vacay_invite', scope: 'user', targetId: selectedUserId, params: { actor: username, planId: '1' }, })} />
)} {/* ── Admin-Scoped Events ──────────────────────────────────────────── */}
Admin-Scoped Events

Fires to all admin users.

fire('version_available', { event: 'version_available', scope: 'admin', targetId: 0, params: { version: '9.9.9-test' }, })} />
) }