diff --git a/app/home/transfer/amount/page.tsx b/app/home/transfer/amount/page.tsx index dec1d8c..bf28bff 100644 --- a/app/home/transfer/amount/page.tsx +++ b/app/home/transfer/amount/page.tsx @@ -19,6 +19,7 @@ import RecipientHeader from "@/components/transfer/RecipientHeader"; import AmountInput from "@/components/transfer/AmountInput"; import CategorySelector from "@/components/transfer/CategorySelector"; import PinEntry from "@/components/transfer/PinEntry"; +import { PinSetupModal } from "@/components/PinSetupModal"; import { Loader2 } from "lucide-react"; import { isTokenExpired, getUserIdFromToken } from "@/utils/jwtUtils"; @@ -54,6 +55,8 @@ const AmountPage = () => { const [loading, setLoading] = useState(false); const [error, setError] = useState(""); + const [showPinSetup, setShowPinSetup] = useState(false); + const [hasPinSet, setHasPinSet] = useState(null); // Load recipient from session storage useEffect(() => { @@ -65,7 +68,25 @@ const AmountPage = () => { } else { router.push('/home/transfer'); } - }, [router]); + + // Check PIN status + const checkPin = async () => { + const token = getToken(); + if (token) { + try { + const response: any = await checkUserPinStatus(); + const pinStatus = response?.hasPinSet || false; + setHasPinSet(pinStatus); + if (!pinStatus) { + setShowPinSetup(true); + } + } catch (error) { + console.error('Error checking PIN status:', error); + } + } + }; + checkPin(); + }, [router, getToken]); // Fetch balance and categories useEffect(() => { @@ -266,6 +287,12 @@ const AmountPage = () => {
+ + setHasPinSet(true)} + /> ); }; diff --git a/components/notifications/NotificationCenter.tsx b/components/notifications/NotificationCenter.tsx index f5e0952..dd96407 100644 --- a/components/notifications/NotificationCenter.tsx +++ b/components/notifications/NotificationCenter.tsx @@ -1,6 +1,7 @@ "use client" import React, { useState } from "react" +import { useRouter } from "next/navigation" import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog" import { Button } from "@/components/ui/button" import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" @@ -8,7 +9,7 @@ import { Badge } from "@/components/ui/badge" import { ScrollArea } from "@/components/ui/scroll-area" import { Separator } from "@/components/ui/separator" import { Textarea } from "@/components/ui/textarea" -import { Bell, Users, UserPlus, Check, X, Clock, AlertCircle, Info, Loader2 } from "lucide-react" +import { Bell, Users, UserPlus, Check, X, Clock, AlertCircle, Info, Loader2, MessageCircle, Image, Video, Music, File, DollarSign, UserMinus, UserCheck, UserX, ShieldCheck, ShieldAlert, Settings, Trash2 } from "lucide-react" import { toast } from "@/hooks/use-toast" import { useNotifications } from "@/context/NotificationContext" import { useAuthToken } from "@/hooks/use-auth-token" @@ -34,11 +35,12 @@ const NotificationCenter: React.FC = ({ isOpen, onClose const { notifications, unreadCount, markAsRead, removeContactRequestNotification } = useNotifications() const { getToken } = useAuthToken() const token = getToken() + const router = useRouter() const [respondToJoinRequest, { isLoading: isResponding }] = useRespondToJoinRequestEnhancedMutation() const [respondToContactRequest, { isLoading: isRespondingToContact }] = useRespondToInvitationEnhancedMutation() const [respondToContactByToken, { isLoading: isRespondingByToken }] = useRespondToInvitationByTokenMutation() - const [selectedTab, setSelectedTab] = useState<'all' | 'invitations' | 'requests' | 'contacts'>('all') + const [selectedTab, setSelectedTab] = useState<'all' | 'invitations' | 'requests' | 'contacts' | 'groups' | 'messages'>('all') const [processingRequestId, setProcessingRequestId] = useState(null) const [rejectionReason, setRejectionReason] = useState("") const [showRejectionInput, setShowRejectionInput] = useState(null) @@ -60,19 +62,111 @@ const NotificationCenter: React.FC = ({ isOpen, onClose const getNotificationIcon = (type: string) => { switch (type) { + // Group notifications + case 'GROUP_INVITATION': case 'group_invitation': return + case 'GROUP_JOIN_REQUEST': case 'group_join_request': return + case 'GROUP_JOIN_APPROVED': case 'group_join_approved': return + case 'GROUP_JOIN_REJECTED': case 'group_join_rejected': return + case 'GROUP_CREATED': case 'group_created': return + case 'GROUP_JOINED': + case 'group_joined': + return + case 'GROUP_MEMBER_LEFT': + case 'group_member_left': + return + case 'MEMBER_REMOVED_FROM_GROUP': + case 'member_removed_from_group': + return + case 'GROUP_DELETED': + case 'group_deleted': + return + case 'GROUP_INVITATION_SENT': + case 'group_invitation_sent': + return + case 'GROUP_INVITATION_ACCEPTED': + case 'group_invitation_accepted': + return + case 'GROUP_INVITATION_REJECTED': + case 'group_invitation_rejected': + return + case 'GROUP_MEMBER_ADDED': + case 'group_member_added': + return + case 'GROUP_MEMBER_REMOVED': + case 'group_member_removed': + return + case 'GROUP_MEMBER_ROLE_CHANGED': + case 'group_member_role_changed': + return + case 'GROUP_UPDATED': + case 'group_updated': + return + + // Contact notifications case 'CONTACT_REQUEST_RECEIVED': case 'contact_request': return + case 'CONTACT_INVITATION_SENT': + case 'contact_invitation_sent': + return + case 'CONTACT_REQUEST_ACCEPTED': + case 'contact_request_accepted': + return + case 'CONTACT_REQUEST_REJECTED': + case 'contact_request_rejected': + return + case 'CONTACT_ADDED': + case 'contact_added': + return + case 'CONTACT_BLOCKED': + case 'contact_blocked': + return + case 'CONTACT_UNBLOCKED': + case 'contact_unblocked': + return + case 'CONTACT_REMOVED': + case 'contact_removed': + return + + // Chat notification icons + case 'CHAT_MESSAGE_TEXT': + case 'CHAT_MESSAGE_RECEIVED': + case 'chat_message_text': + return + case 'CHAT_MESSAGE_IMAGE': + case 'chat_message_image': + return + case 'CHAT_MESSAGE_VIDEO': + case 'chat_message_video': + return