feat: Implement agent messaging and settings pages with new components and icons.
3
public/assets/icons/arrow-down-icon.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 5V19M12 19L5 12M12 19L19 12" stroke="#00293d" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 230 B |
3
public/assets/icons/chevron-right-icon.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="8" height="14" viewBox="0 0 8 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 1L7 7L1 13" stroke="#00293D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 208 B |
4
public/assets/icons/compose-icon.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11 4H4C3.46957 4 2.96086 4.21071 2.58579 4.58579C2.21071 4.96086 2 5.46957 2 6V20C2 20.5304 2.21071 21.0391 2.58579 21.4142C2.96086 21.7893 3.46957 22 4 22H18C18.5304 22 19.0391 21.7893 19.4142 21.4142C19.7893 21.0391 20 20.5304 20 20V13" stroke="#00293d" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M18.5 2.50001C18.8978 2.10219 19.4374 1.87869 20 1.87869C20.5626 1.87869 21.1022 2.10219 21.5 2.50001C21.8978 2.89784 22.1213 3.4374 22.1213 4.00001C22.1213 4.56262 21.8978 5.10219 21.5 5.50001L12 15L8 16L9 12L18.5 2.50001Z" stroke="#00293d" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 756 B |
6
public/assets/icons/emoji-icon.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="12" r="10" stroke="#e58625" stroke-width="2"/>
|
||||
<path d="M8 14C8 14 9.5 16 12 16C14.5 16 16 14 16 14" stroke="#e58625" stroke-width="2" stroke-linecap="round"/>
|
||||
<circle cx="9" cy="9" r="1" fill="#e58625"/>
|
||||
<circle cx="15" cy="9" r="1" fill="#e58625"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 382 B |
5
public/assets/icons/gallery-icon.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2" stroke="#e58625" stroke-width="2"/>
|
||||
<circle cx="8.5" cy="8.5" r="1.5" fill="#e58625"/>
|
||||
<path d="M21 15L16 10L5 21" stroke="#e58625" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 355 B |
6
public/assets/icons/gif-icon.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="2" y="5" width="20" height="14" rx="2" stroke="#e58625" stroke-width="2"/>
|
||||
<path d="M7 12H6C5.44772 12 5 11.5523 5 11V10C5 9.44772 5.44772 9 6 9H8V15H6C5.44772 15 5 14.5523 5 14V13C5 12.4477 5.44772 12 6 12H7" stroke="#e58625" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M11 9V15" stroke="#e58625" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M14 9H18M14 9V15M14 12H17" stroke="#e58625" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 592 B |
4
public/assets/icons/search-icon.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11 19C15.4183 19 19 15.4183 19 11C19 6.58172 15.4183 3 11 3C6.58172 3 3 6.58172 3 11C3 15.4183 6.58172 19 11 19Z" stroke="#00293d" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M21 21L16.65 16.65" stroke="#00293d" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 426 B |
3
public/assets/icons/settings-bell-icon.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 20C11.1 20 12 19.1 12 18H8C8 19.1 8.9 20 10 20ZM16 14V9C16 5.93 14.36 3.36 11.5 2.68V2C11.5 1.17 10.83 0.5 10 0.5C9.17 0.5 8.5 1.17 8.5 2V2.68C5.63 3.36 4 5.92 4 9V14L2 16V17H18V16L16 14Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 327 B |
3
public/assets/icons/settings-lock-icon.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="18" height="20" viewBox="0 0 18 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15.75 7H14.625V5C14.625 2.2425 12.3825 0 9.625 0C6.8675 0 4.625 2.2425 4.625 5V7H3.5C2.4 7 1.5 7.9 1.5 9V18C1.5 19.1 2.4 20 3.5 20H15.75C16.85 20 17.75 19.1 17.75 18V9C17.75 7.9 16.85 7 15.75 7ZM9.625 15C8.525 15 7.625 14.1 7.625 13C7.625 11.9 8.525 11 9.625 11C10.725 11 11.625 11.9 11.625 13C11.625 14.1 10.725 15 9.625 15ZM12.675 7H6.575V5C6.575 3.3425 7.9175 2 9.625 2C11.3325 2 12.675 3.3425 12.675 5V7Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 545 B |
3
public/assets/icons/settings-privacy-icon.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 1L3 4.5V9.5C3 14.025 6.15 18.275 10 19.5C13.85 18.275 17 14.025 17 9.5V4.5L10 1ZM10 9.99H15C14.575 13.34 12.61 16.325 10 17.435V10H5V5.65L10 3.2V9.99Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 290 B |
3
public/assets/icons/settings-profile-icon.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 10C12.0711 10 13.75 8.32107 13.75 6.25C13.75 4.17893 12.0711 2.5 10 2.5C7.92893 2.5 6.25 4.17893 6.25 6.25C6.25 8.32107 7.92893 10 10 10ZM10 11.875C7.08125 11.875 1.25 13.3438 1.25 16.25V17.5H18.75V16.25C18.75 13.3438 12.9188 11.875 10 11.875Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 383 B |
@@ -1,4 +1,3 @@
|
||||
<svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.30942 16.8689C12.8162 15.6602 15.3158 12.8503 15.7079 9.27257C15.8166 7.71948 15.8074 6.16038 15.6803 4.60868C15.6636 4.36407 15.5563 4.13448 15.3793 3.96481C15.2023 3.79513 14.9684 3.69756 14.7233 3.69118C13.1369 3.64232 11.2929 3.37785 9.86821 1.97446C9.71943 1.82752 9.51873 1.74512 9.30961 1.74512C9.10049 1.74512 8.89979 1.82752 8.75101 1.97446C7.3259 3.37785 5.48198 3.64232 3.89594 3.69118C3.65084 3.69756 3.41692 3.79513 3.23993 3.96481C3.06294 4.13448 2.9556 4.36407 2.93889 4.60868C2.81168 6.16037 2.80234 7.71947 2.91096 9.27257C3.30302 12.8503 5.80268 15.6602 9.30942 16.8689Z" stroke="#E58625" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M9.04859 12.0218L10.6637 9.30727H7.94922L9.56434 6.59277" stroke="#E58625" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<svg width="17" height="18" viewBox="0 0 17 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 2.59997L8.43919 0V18C2.41085 15.6 0 11 0 8.4V2.59997ZM16.8784 2.59997L8.43919 0V18C14.4675 15.6 16.8784 11 16.8784 8.4V2.59997Z" fill="#E58625"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 938 B After Width: | Height: | Size: 261 B |
3
public/assets/icons/star-outline-icon.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" stroke="#e58625" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 295 B |
5
public/assets/icons/three-dots-icon.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="5" r="2" fill="#00293d"/>
|
||||
<circle cx="12" cy="12" r="2" fill="#00293d"/>
|
||||
<circle cx="12" cy="19" r="2" fill="#00293d"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 249 B |
@@ -86,7 +86,10 @@ export function ProfileCard({
|
||||
|
||||
{/* Action Buttons */}
|
||||
<div className="flex items-center justify-center lg:justify-start gap-3">
|
||||
<button className="flex items-center gap-2 px-4 py-1.5 bg-[#e58625] text-[#00293d] text-sm font-normal rounded-[15px] border border-[#00293d]/10 hover:bg-[#d47720] transition-colors font-serif">
|
||||
<Link
|
||||
href="/agent/message"
|
||||
className="flex items-center gap-2 px-4 py-1.5 bg-[#e58625] text-[#00293d] text-sm font-normal rounded-[15px] border border-[#00293d]/10 hover:bg-[#d47720] transition-colors font-serif cursor-pointer"
|
||||
>
|
||||
<Image
|
||||
src="/assets/icons/message-dark-icon.svg"
|
||||
alt="Message"
|
||||
@@ -94,7 +97,7 @@ export function ProfileCard({
|
||||
height={13}
|
||||
/>
|
||||
Message
|
||||
</button>
|
||||
</Link>
|
||||
<Link
|
||||
href="/agent/network"
|
||||
className="flex items-center gap-2 px-4 py-1.5 bg-[#e58625] text-[#00293d] text-sm font-normal rounded-[15px] border border-[#00293d]/10 hover:bg-[#d47720] transition-colors font-serif cursor-pointer"
|
||||
|
||||
116
src/app/(agent)/agent/message/component/ChatHeader.tsx
Normal file
@@ -0,0 +1,116 @@
|
||||
'use client';
|
||||
|
||||
import Image from 'next/image';
|
||||
|
||||
interface ChatHeaderProps {
|
||||
name: string;
|
||||
role: string;
|
||||
lastSeen: string;
|
||||
avatar: string;
|
||||
isOnline?: boolean;
|
||||
pronouns?: string;
|
||||
expertise?: string[];
|
||||
}
|
||||
|
||||
export function ChatHeader({
|
||||
name,
|
||||
role,
|
||||
lastSeen,
|
||||
avatar,
|
||||
isOnline = false,
|
||||
pronouns,
|
||||
expertise = [],
|
||||
}: ChatHeaderProps) {
|
||||
return (
|
||||
<div className="border-b border-[#00293d]/10 pb-4">
|
||||
{/* Top row - Name, status, actions */}
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<h2 className="font-fractul font-bold text-[14px] leading-[17px] text-[#00293D]">
|
||||
{name}
|
||||
</h2>
|
||||
<span className={`w-2.5 h-2.5 rounded-full ${isOnline ? 'bg-green-500' : 'bg-gray-400'}`} />
|
||||
<span className="font-serif font-normal text-[14px] leading-[19px] text-[#00293D]">
|
||||
{role}
|
||||
</span>
|
||||
<span className="font-serif font-normal text-[14px] leading-[19px] text-[#00293D]">
|
||||
{lastSeen}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<button className="p-2 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer">
|
||||
<Image
|
||||
src="/assets/icons/three-dots-icon.svg"
|
||||
alt="More options"
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
</button>
|
||||
<button className="p-2 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer">
|
||||
<Image
|
||||
src="/assets/icons/star-outline-icon.svg"
|
||||
alt="Star conversation"
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* User profile row */}
|
||||
<div className="flex items-start gap-3">
|
||||
{/* Avatar */}
|
||||
<div className="relative flex-shrink-0">
|
||||
<div className="w-[50px] h-[50px] rounded-full overflow-hidden">
|
||||
<Image
|
||||
src={avatar}
|
||||
alt={name}
|
||||
width={50}
|
||||
height={50}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
{isOnline && (
|
||||
<div className="absolute bottom-0 right-0 w-3 h-3 bg-green-500 rounded-full border-2 border-white" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* User info */}
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<span className="font-fractul font-bold text-[14px] leading-[17px] text-[#00293D]">
|
||||
{name}
|
||||
</span>
|
||||
<Image
|
||||
src="/assets/icons/shield-verified-icon.svg"
|
||||
alt="Verified"
|
||||
width={17}
|
||||
height={18}
|
||||
/>
|
||||
{pronouns && (
|
||||
<span className="font-fractul font-bold text-[14px] leading-[17px] text-[#00293D]">
|
||||
({pronouns})
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Expertise tags */}
|
||||
{expertise.length > 0 && (
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
{expertise.map((tag, index) => (
|
||||
<span key={index} className="flex items-center">
|
||||
<span className="font-serif font-normal text-[14px] leading-[19px] text-[#00293D]">
|
||||
{tag}
|
||||
</span>
|
||||
{index < expertise.length - 1 && (
|
||||
<span className="mx-2 text-[#00293d]/30">|</span>
|
||||
)}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
65
src/app/(agent)/agent/message/component/ConversationItem.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
'use client';
|
||||
|
||||
import Image from 'next/image';
|
||||
|
||||
interface ConversationItemProps {
|
||||
id: string;
|
||||
name: string;
|
||||
avatar: string;
|
||||
lastMessage: string;
|
||||
date: string;
|
||||
isOnline?: boolean;
|
||||
isSelected?: boolean;
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
export function ConversationItem({
|
||||
id,
|
||||
name,
|
||||
avatar,
|
||||
lastMessage,
|
||||
date,
|
||||
isOnline = false,
|
||||
isSelected = false,
|
||||
onClick,
|
||||
}: ConversationItemProps) {
|
||||
return (
|
||||
<div
|
||||
onClick={onClick}
|
||||
className={`flex items-start gap-3 p-4 border border-[#00293d]/10 rounded-[15px] cursor-pointer transition-colors ${
|
||||
isSelected ? 'bg-[#00293d]/5' : 'hover:bg-[#00293d]/5'
|
||||
}`}
|
||||
>
|
||||
{/* Avatar with online indicator */}
|
||||
<div className="relative flex-shrink-0">
|
||||
<div className="w-[70px] h-[70px] rounded-full overflow-hidden">
|
||||
<Image
|
||||
src={avatar}
|
||||
alt={name}
|
||||
width={70}
|
||||
height={70}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
{isOnline && (
|
||||
<div className="absolute bottom-1 right-1 w-3 h-3 bg-green-500 rounded-full border-2 border-white" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="font-fractul font-medium text-[14px] leading-[17px] text-[#00293D] mb-1">
|
||||
{name}
|
||||
</p>
|
||||
<p className="font-serif font-normal text-[14px] leading-[19px] text-[#00293D] line-clamp-2">
|
||||
{lastMessage}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Date */}
|
||||
<p className="font-serif font-normal text-[14px] leading-[19px] text-[#00293D] flex-shrink-0">
|
||||
{date}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
41
src/app/(agent)/agent/message/component/ConversationList.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
'use client';
|
||||
|
||||
import Image from 'next/image';
|
||||
import { ConversationItem } from './ConversationItem';
|
||||
|
||||
interface Conversation {
|
||||
id: string;
|
||||
name: string;
|
||||
avatar: string;
|
||||
lastMessage: string;
|
||||
date: string;
|
||||
isOnline?: boolean;
|
||||
}
|
||||
|
||||
interface ConversationListProps {
|
||||
conversations: Conversation[];
|
||||
selectedId: string | null;
|
||||
onSelect: (id: string) => void;
|
||||
}
|
||||
|
||||
export function ConversationList({
|
||||
conversations,
|
||||
selectedId,
|
||||
onSelect,
|
||||
}: ConversationListProps) {
|
||||
return (
|
||||
<div className="border border-[#00293d]/10 rounded-[15px] bg-white h-full flex flex-col">
|
||||
{/* Scrollable conversation list */}
|
||||
<div className="flex-1 overflow-y-auto p-2 space-y-2">
|
||||
{conversations.map((conversation) => (
|
||||
<ConversationItem
|
||||
key={conversation.id}
|
||||
{...conversation}
|
||||
isSelected={selectedId === conversation.id}
|
||||
onClick={() => onSelect(conversation.id)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
98
src/app/(agent)/agent/message/component/MessageInput.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
'use client';
|
||||
|
||||
import Image from 'next/image';
|
||||
import { useState } from 'react';
|
||||
|
||||
interface MessageInputProps {
|
||||
onSend?: (message: string) => void;
|
||||
}
|
||||
|
||||
export function MessageInput({ onSend }: MessageInputProps) {
|
||||
const [message, setMessage] = useState('');
|
||||
|
||||
const handleSend = () => {
|
||||
if (message.trim() && onSend) {
|
||||
onSend(message.trim());
|
||||
setMessage('');
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter' && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
handleSend();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="border border-[#00293d]/10 rounded-[20px] bg-white p-4">
|
||||
{/* Text input area */}
|
||||
<div className="border border-[#00293d]/10 rounded-[20px] p-4 mb-3">
|
||||
<textarea
|
||||
value={message}
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
placeholder="Write a Message........"
|
||||
className="w-full min-h-[120px] resize-none font-serif font-normal text-[14px] leading-[19px] text-[#00293D] placeholder-[#00293D]/50 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Action bar */}
|
||||
<div className="flex items-center justify-between">
|
||||
{/* Attachment buttons */}
|
||||
<div className="flex items-center gap-3">
|
||||
<button className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer">
|
||||
<Image
|
||||
src="/assets/icons/gallery-icon.svg"
|
||||
alt="Add image"
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
</button>
|
||||
<button className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer">
|
||||
<Image
|
||||
src="/assets/icons/chain-icon.svg"
|
||||
alt="Add link"
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
</button>
|
||||
<button className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer">
|
||||
<Image
|
||||
src="/assets/icons/gif-icon.svg"
|
||||
alt="Add GIF"
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
</button>
|
||||
<button className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer">
|
||||
<Image
|
||||
src="/assets/icons/emoji-icon.svg"
|
||||
alt="Add emoji"
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Send button and more options */}
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
onClick={handleSend}
|
||||
className="px-4 py-1.5 bg-[#e58625] text-[#00293d] font-serif font-normal text-[14px] leading-[19px] rounded-[15px] hover:bg-[#d47720] transition-colors cursor-pointer"
|
||||
>
|
||||
Send
|
||||
</button>
|
||||
<button className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer">
|
||||
<Image
|
||||
src="/assets/icons/three-dots-icon.svg"
|
||||
alt="More options"
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
4
src/app/(agent)/agent/message/component/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export { ConversationItem } from './ConversationItem';
|
||||
export { ConversationList } from './ConversationList';
|
||||
export { ChatHeader } from './ChatHeader';
|
||||
export { MessageInput } from './MessageInput';
|
||||
383
src/app/(agent)/agent/message/page.tsx
Normal file
@@ -0,0 +1,383 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import Image from 'next/image';
|
||||
import { ChatHeader, MessageInput } from './component';
|
||||
|
||||
// Custom scrollbar styles
|
||||
const customScrollbarStyles = `
|
||||
.custom-scrollbar::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
.custom-scrollbar::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
.custom-scrollbar::-webkit-scrollbar-thumb {
|
||||
background: rgba(0, 41, 61, 0.5);
|
||||
border-radius: 10px;
|
||||
}
|
||||
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(0, 41, 61, 0.7);
|
||||
}
|
||||
`;
|
||||
|
||||
// Mock data for conversations
|
||||
const conversations = [
|
||||
{
|
||||
id: '1',
|
||||
name: 'Pradeep Ram',
|
||||
avatar: '/assets/icons/user-placeholder-icon.svg',
|
||||
lastMessage: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
|
||||
date: 'Dec 4',
|
||||
isOnline: true,
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'Pradeep',
|
||||
avatar: '/assets/icons/user-placeholder-icon.svg',
|
||||
lastMessage: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
|
||||
date: 'Dec 4',
|
||||
isOnline: true,
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: 'Gokulraj',
|
||||
avatar: '/assets/icons/user-placeholder-icon.svg',
|
||||
lastMessage: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
|
||||
date: 'Dec 4',
|
||||
isOnline: true,
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
name: 'Suriya s',
|
||||
avatar: '/assets/icons/user-placeholder-icon.svg',
|
||||
lastMessage: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
|
||||
date: 'Dec 4',
|
||||
isOnline: true,
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
name: 'Sanjay',
|
||||
avatar: '/assets/icons/user-placeholder-icon.svg',
|
||||
lastMessage: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
|
||||
date: 'Dec 4',
|
||||
isOnline: true,
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
name: 'Pradeep Ram',
|
||||
avatar: '/assets/icons/user-placeholder-icon.svg',
|
||||
lastMessage: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
|
||||
date: 'Dec 4',
|
||||
isOnline: false,
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
name: 'Rahul Kumar',
|
||||
avatar: '/assets/icons/user-placeholder-icon.svg',
|
||||
lastMessage: 'Thanks for your help with the property listing!',
|
||||
date: 'Dec 3',
|
||||
isOnline: true,
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
name: 'Anita Singh',
|
||||
avatar: '/assets/icons/user-placeholder-icon.svg',
|
||||
lastMessage: 'Can we schedule a viewing for tomorrow?',
|
||||
date: 'Dec 3',
|
||||
isOnline: false,
|
||||
},
|
||||
{
|
||||
id: '9',
|
||||
name: 'Vikram Patel',
|
||||
avatar: '/assets/icons/user-placeholder-icon.svg',
|
||||
lastMessage: 'The documents have been submitted.',
|
||||
date: 'Dec 2',
|
||||
isOnline: true,
|
||||
},
|
||||
{
|
||||
id: '10',
|
||||
name: 'Meera Sharma',
|
||||
avatar: '/assets/icons/user-placeholder-icon.svg',
|
||||
lastMessage: 'Looking forward to our meeting next week.',
|
||||
date: 'Dec 2',
|
||||
isOnline: false,
|
||||
},
|
||||
{
|
||||
id: '11',
|
||||
name: 'Arjun Reddy',
|
||||
avatar: '/assets/icons/user-placeholder-icon.svg',
|
||||
lastMessage: 'Please send me the property details.',
|
||||
date: 'Dec 1',
|
||||
isOnline: true,
|
||||
},
|
||||
{
|
||||
id: '12',
|
||||
name: 'Sneha Nair',
|
||||
avatar: '/assets/icons/user-placeholder-icon.svg',
|
||||
lastMessage: 'I have a few questions about the contract.',
|
||||
date: 'Dec 1',
|
||||
isOnline: false,
|
||||
},
|
||||
];
|
||||
|
||||
// Mock data for selected user
|
||||
const selectedUserData = {
|
||||
name: 'Pradeep Ram',
|
||||
role: 'Advisor',
|
||||
lastSeen: '21h Ago',
|
||||
avatar: '/assets/icons/user-placeholder-icon.svg',
|
||||
isOnline: true,
|
||||
pronouns: 'He/Him',
|
||||
expertise: ['Sales', 'Analytics', 'Inspection', 'Residential', 'Commercial'],
|
||||
};
|
||||
|
||||
// Mock messages data
|
||||
const messages = [
|
||||
{
|
||||
id: '1',
|
||||
senderId: '1',
|
||||
text: 'Hi! I saw your profile and I think you might be a great fit for what I\'m looking for.',
|
||||
timestamp: '10:30 AM',
|
||||
isOwn: false,
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
senderId: 'me',
|
||||
text: 'Hello! Thank you for reaching out. I\'d be happy to help. What kind of property are you looking for?',
|
||||
timestamp: '10:32 AM',
|
||||
isOwn: true,
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
senderId: '1',
|
||||
text: 'I\'m looking for a residential property in the downtown area. Preferably a 3-bedroom apartment with modern amenities.',
|
||||
timestamp: '10:35 AM',
|
||||
isOwn: false,
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
senderId: 'me',
|
||||
text: 'That sounds great! I have several listings that might interest you. Do you have a specific budget range in mind?',
|
||||
timestamp: '10:38 AM',
|
||||
isOwn: true,
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
senderId: '1',
|
||||
text: 'My budget is around $500,000 to $700,000. I\'m also interested in properties with good investment potential.',
|
||||
timestamp: '10:40 AM',
|
||||
isOwn: false,
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
senderId: 'me',
|
||||
text: 'Perfect! I have a few properties in that range. Would you like to schedule a viewing this weekend?',
|
||||
timestamp: '10:42 AM',
|
||||
isOwn: true,
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
senderId: '1',
|
||||
text: 'Yes, that would be great! Saturday afternoon works best for me.',
|
||||
timestamp: '10:45 AM',
|
||||
isOwn: false,
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
senderId: 'me',
|
||||
text: 'Saturday at 2 PM works for me. I\'ll send you the addresses and details of the properties we\'ll be visiting.',
|
||||
timestamp: '10:48 AM',
|
||||
isOwn: true,
|
||||
},
|
||||
{
|
||||
id: '9',
|
||||
senderId: '1',
|
||||
text: 'Sounds perfect! Looking forward to it. Thank you for your quick response.',
|
||||
timestamp: '10:50 AM',
|
||||
isOwn: false,
|
||||
},
|
||||
{
|
||||
id: '10',
|
||||
senderId: 'me',
|
||||
text: 'You\'re welcome! See you on Saturday. Feel free to reach out if you have any questions before then.',
|
||||
timestamp: '10:52 AM',
|
||||
isOwn: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default function MessagePage() {
|
||||
const [selectedConversation, setSelectedConversation] = useState<string | null>('1');
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
|
||||
const handleSendMessage = (message: string) => {
|
||||
console.log('Sending message:', message);
|
||||
// In production, this would send the message to the API
|
||||
};
|
||||
|
||||
const filteredConversations = conversations.filter((conv) =>
|
||||
conv.name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<style>{customScrollbarStyles}</style>
|
||||
<div className="border border-[#00293d]/10 rounded-[20px] bg-white overflow-hidden">
|
||||
{/* Header */}
|
||||
<div className="flex items-center gap-4 p-4 border-b border-[#00293d]/10">
|
||||
<h1 className="font-fractul font-bold text-[18px] leading-[22px] text-[#00293D]">
|
||||
Messaging
|
||||
</h1>
|
||||
|
||||
{/* Search bar */}
|
||||
<div className="flex-1 max-w-[600px]">
|
||||
<div className="flex items-center gap-2 border border-[#00293d]/10 rounded-[15px] px-4 py-2">
|
||||
<Image
|
||||
src="/assets/icons/search-icon.svg"
|
||||
alt="Search"
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
placeholder="Search Message"
|
||||
className="flex-1 font-serif font-normal text-[18px] leading-[24px] text-[#00293D] placeholder-[#00293D]/50 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Header actions */}
|
||||
<div className="flex items-center gap-2">
|
||||
<button className="p-2 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer">
|
||||
<Image
|
||||
src="/assets/icons/three-dots-icon.svg"
|
||||
alt="More options"
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
</button>
|
||||
<button className="p-2 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer">
|
||||
<Image
|
||||
src="/assets/icons/compose-icon.svg"
|
||||
alt="Compose"
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Main content */}
|
||||
<div className="flex h-[700px]">
|
||||
{/* Left sidebar - Conversation list */}
|
||||
<div className="w-[380px] border-r border-[#00293d]/10 flex-shrink-0 overflow-hidden flex flex-col">
|
||||
<div className="flex-1 overflow-y-auto p-2 space-y-2 custom-scrollbar">
|
||||
{filteredConversations.map((conversation) => (
|
||||
<div
|
||||
key={conversation.id}
|
||||
onClick={() => setSelectedConversation(conversation.id)}
|
||||
className={`flex items-start gap-3 p-4 border border-[#00293d]/10 rounded-[15px] cursor-pointer transition-colors ${
|
||||
selectedConversation === conversation.id ? 'bg-[#00293d]/5' : 'hover:bg-[#00293d]/5'
|
||||
}`}
|
||||
>
|
||||
{/* Avatar with online indicator */}
|
||||
<div className="relative flex-shrink-0">
|
||||
<div className="w-[70px] h-[70px] rounded-full overflow-hidden">
|
||||
<Image
|
||||
src={conversation.avatar}
|
||||
alt={conversation.name}
|
||||
width={70}
|
||||
height={70}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
{conversation.isOnline && (
|
||||
<div className="absolute bottom-1 right-1 w-3 h-3 bg-green-500 rounded-full border-2 border-white" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="font-fractul font-medium text-[14px] leading-[17px] text-[#00293D] mb-1">
|
||||
{conversation.name}
|
||||
</p>
|
||||
<p className="font-serif font-normal text-[14px] leading-[19px] text-[#00293D] line-clamp-2">
|
||||
{conversation.lastMessage}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Date */}
|
||||
<p className="font-serif font-normal text-[14px] leading-[19px] text-[#00293D] flex-shrink-0">
|
||||
{conversation.date}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right panel - Chat area */}
|
||||
<div className="flex-1 flex flex-col p-4">
|
||||
{selectedConversation ? (
|
||||
<>
|
||||
{/* Chat header */}
|
||||
<ChatHeader {...selectedUserData} />
|
||||
|
||||
{/* Messages area */}
|
||||
<div className="flex-1 overflow-y-auto py-4 relative custom-scrollbar">
|
||||
<div className="space-y-4 px-2">
|
||||
{messages.map((message) => (
|
||||
<div
|
||||
key={message.id}
|
||||
className={`flex ${message.isOwn ? 'justify-end' : 'justify-start'}`}
|
||||
>
|
||||
<div
|
||||
className={`max-w-[70%] rounded-[15px] px-4 py-3 ${
|
||||
message.isOwn
|
||||
? 'bg-[#e58625] text-[#00293D]'
|
||||
: 'bg-[#00293d]/10 text-[#00293D]'
|
||||
}`}
|
||||
>
|
||||
<p className="font-serif font-normal text-[14px] leading-[19px]">
|
||||
{message.text}
|
||||
</p>
|
||||
<p
|
||||
className={`font-serif font-normal text-[12px] leading-[16px] mt-1 ${
|
||||
message.isOwn ? 'text-[#00293D]/70' : 'text-[#00293D]/50'
|
||||
}`}
|
||||
>
|
||||
{message.timestamp}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Scroll to bottom button */}
|
||||
<div className="absolute bottom-4 right-4">
|
||||
<button className="w-[50px] h-[50px] bg-[#00293d]/10 rounded-full flex items-center justify-center hover:bg-[#00293d]/20 transition-colors cursor-pointer">
|
||||
<Image
|
||||
src="/assets/icons/arrow-down-icon.svg"
|
||||
alt="Scroll to bottom"
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Message input */}
|
||||
<MessageInput onSend={handleSendMessage} />
|
||||
</>
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-full text-[#00293D]/50 font-serif">
|
||||
Select a conversation to start messaging
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
133
src/app/(agent)/agent/settings/component/SettingsSidebar.tsx
Normal file
@@ -0,0 +1,133 @@
|
||||
'use client';
|
||||
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
|
||||
interface NavItem {
|
||||
label: string;
|
||||
href: string;
|
||||
icon: string;
|
||||
}
|
||||
|
||||
const navItems: NavItem[] = [
|
||||
{
|
||||
label: 'Profile Settings',
|
||||
href: '/agent/settings',
|
||||
icon: '/assets/icons/settings-profile-icon.svg',
|
||||
},
|
||||
{
|
||||
label: 'Password Security',
|
||||
href: '/agent/settings/password',
|
||||
icon: '/assets/icons/settings-lock-icon.svg',
|
||||
},
|
||||
{
|
||||
label: 'Notifications',
|
||||
href: '/agent/settings/notifications',
|
||||
icon: '/assets/icons/settings-bell-icon.svg',
|
||||
},
|
||||
{
|
||||
label: 'Privacy',
|
||||
href: '/agent/settings/privacy',
|
||||
icon: '/assets/icons/settings-privacy-icon.svg',
|
||||
},
|
||||
];
|
||||
|
||||
interface SettingsSidebarProps {
|
||||
profileImage?: string;
|
||||
name?: string;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export function SettingsSidebar({
|
||||
profileImage = '/assets/icons/user-placeholder-icon.svg',
|
||||
name = 'Brain Nooland',
|
||||
title = 'Top Real Estate Agent',
|
||||
}: SettingsSidebarProps) {
|
||||
const pathname = usePathname();
|
||||
|
||||
return (
|
||||
<div className="w-full lg:w-[280px] bg-white rounded-[15px] border border-[#00293d]/10 overflow-hidden h-fit">
|
||||
{/* Profile Section */}
|
||||
<div className="p-6 flex flex-col items-center">
|
||||
<div className="w-[80px] h-[80px] rounded-full overflow-hidden mb-3 border-2 border-[#e58625]">
|
||||
<Image
|
||||
src={profileImage}
|
||||
alt={name}
|
||||
width={80}
|
||||
height={80}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<h3 className="font-fractul font-bold text-[16px] leading-[19px] text-[#00293D]">
|
||||
{name}
|
||||
</h3>
|
||||
<p className="font-serif font-normal text-[12px] leading-[16px] text-[#00293D]/70 mt-1">
|
||||
{title}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Divider */}
|
||||
<div className="w-full h-[1px] bg-[#00293d]/10" />
|
||||
|
||||
{/* Categories Section */}
|
||||
<div className="p-4">
|
||||
{/* Categories Header */}
|
||||
<div className="flex items-center justify-between mb-4 px-2">
|
||||
<h4 className="font-fractul font-bold text-[14px] leading-[17px] text-[#00293D]">
|
||||
Categories
|
||||
</h4>
|
||||
<Image
|
||||
src="/assets/icons/chevron-right-icon.svg"
|
||||
alt="Expand"
|
||||
width={8}
|
||||
height={14}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Navigation Items */}
|
||||
<nav className="space-y-1">
|
||||
{navItems.map((item) => {
|
||||
const isActive = pathname === item.href;
|
||||
return (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className={`flex items-center gap-3 py-3 px-3 rounded-[10px] transition-colors cursor-pointer ${
|
||||
isActive
|
||||
? 'bg-[#e58625]/10'
|
||||
: 'hover:bg-[#00293d]/5'
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`w-5 h-5 flex items-center justify-center ${
|
||||
isActive ? 'text-[#e58625]' : 'text-[#00293D]'
|
||||
}`}
|
||||
style={{ color: isActive ? '#e58625' : '#00293D' }}
|
||||
>
|
||||
<Image
|
||||
src={item.icon}
|
||||
alt={item.label}
|
||||
width={20}
|
||||
height={20}
|
||||
className={isActive ? 'brightness-0 saturate-100' : ''}
|
||||
style={isActive ? { filter: 'invert(48%) sepia(94%) saturate(1000%) hue-rotate(360deg) brightness(95%) contrast(85%)' } : {}}
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
className={`font-serif text-[14px] leading-[19px] ${
|
||||
isActive
|
||||
? 'font-medium text-[#e58625]'
|
||||
: 'font-normal text-[#00293D]'
|
||||
}`}
|
||||
>
|
||||
{item.label}
|
||||
</span>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
1
src/app/(agent)/agent/settings/component/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { SettingsSidebar } from './SettingsSidebar';
|
||||
206
src/app/(agent)/agent/settings/notifications/page.tsx
Normal file
@@ -0,0 +1,206 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { SettingsSidebar } from '../component/SettingsSidebar';
|
||||
|
||||
interface NotificationSetting {
|
||||
id: string;
|
||||
label: string;
|
||||
description: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export default function NotificationsPage() {
|
||||
const [emailNotifications, setEmailNotifications] = useState<NotificationSetting[]>([
|
||||
{
|
||||
id: 'new_leads',
|
||||
label: 'New Leads',
|
||||
description: 'Get notified when you receive new leads',
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
id: 'messages',
|
||||
label: 'Messages',
|
||||
description: 'Get notified when you receive new messages',
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
id: 'connection_requests',
|
||||
label: 'Connection Requests',
|
||||
description: 'Get notified about new connection requests',
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
id: 'property_updates',
|
||||
label: 'Property Updates',
|
||||
description: 'Get notified about property status changes',
|
||||
enabled: false,
|
||||
},
|
||||
{
|
||||
id: 'marketing',
|
||||
label: 'Marketing & Promotions',
|
||||
description: 'Receive marketing emails and promotions',
|
||||
enabled: false,
|
||||
},
|
||||
]);
|
||||
|
||||
const [pushNotifications, setPushNotifications] = useState<NotificationSetting[]>([
|
||||
{
|
||||
id: 'push_messages',
|
||||
label: 'Messages',
|
||||
description: 'Push notifications for new messages',
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
id: 'push_leads',
|
||||
label: 'New Leads',
|
||||
description: 'Push notifications for new leads',
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
id: 'push_reminders',
|
||||
label: 'Reminders',
|
||||
description: 'Push notifications for scheduled reminders',
|
||||
enabled: false,
|
||||
},
|
||||
]);
|
||||
|
||||
const toggleEmailNotification = (id: string) => {
|
||||
setEmailNotifications((prev) =>
|
||||
prev.map((item) =>
|
||||
item.id === id ? { ...item, enabled: !item.enabled } : item
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const togglePushNotification = (id: string) => {
|
||||
setPushNotifications((prev) =>
|
||||
prev.map((item) =>
|
||||
item.id === id ? { ...item, enabled: !item.enabled } : item
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
console.log('Saving notification settings:', {
|
||||
emailNotifications,
|
||||
pushNotifications,
|
||||
});
|
||||
};
|
||||
|
||||
const ToggleSwitch = ({
|
||||
enabled,
|
||||
onToggle,
|
||||
}: {
|
||||
enabled: boolean;
|
||||
onToggle: () => void;
|
||||
}) => (
|
||||
<button
|
||||
onClick={onToggle}
|
||||
className={`relative w-[44px] h-[24px] rounded-full transition-colors cursor-pointer ${
|
||||
enabled ? 'bg-[#e58625]' : 'bg-[#00293D]/20'
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`absolute top-[2px] w-[20px] h-[20px] rounded-full bg-white shadow transition-transform ${
|
||||
enabled ? 'translate-x-[22px]' : 'translate-x-[2px]'
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col lg:flex-row gap-6">
|
||||
{/* Left Sidebar */}
|
||||
<SettingsSidebar />
|
||||
|
||||
{/* Main Content */}
|
||||
<div className="flex-1">
|
||||
{/* Header Card */}
|
||||
<div className="border border-[#00293d]/10 rounded-[15px] px-6 py-4 mb-4 bg-white">
|
||||
<h1 className="font-fractul font-bold text-[15px] leading-[18px] text-[#00293D]">
|
||||
Notifications
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
{/* Email Notifications */}
|
||||
<div className="border border-[#00293d]/10 rounded-[15px] bg-white p-6 mb-4">
|
||||
<div className="mb-6">
|
||||
<h2 className="font-fractul font-bold text-[16px] text-[#00293D] mb-2">
|
||||
Email Notifications
|
||||
</h2>
|
||||
<p className="font-serif text-[12px] text-[#00293D]/60">
|
||||
Manage your email notification preferences
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
{emailNotifications.map((item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
className="flex items-center justify-between py-3 border-b border-[#00293d]/10 last:border-0"
|
||||
>
|
||||
<div>
|
||||
<h3 className="font-serif font-medium text-[14px] text-[#00293D]">
|
||||
{item.label}
|
||||
</h3>
|
||||
<p className="font-serif text-[12px] text-[#00293D]/60">
|
||||
{item.description}
|
||||
</p>
|
||||
</div>
|
||||
<ToggleSwitch
|
||||
enabled={item.enabled}
|
||||
onToggle={() => toggleEmailNotification(item.id)}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Push Notifications */}
|
||||
<div className="border border-[#00293d]/10 rounded-[15px] bg-white p-6 mb-4">
|
||||
<div className="mb-6">
|
||||
<h2 className="font-fractul font-bold text-[16px] text-[#00293D] mb-2">
|
||||
Push Notifications
|
||||
</h2>
|
||||
<p className="font-serif text-[12px] text-[#00293D]/60">
|
||||
Manage your push notification preferences
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
{pushNotifications.map((item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
className="flex items-center justify-between py-3 border-b border-[#00293d]/10 last:border-0"
|
||||
>
|
||||
<div>
|
||||
<h3 className="font-serif font-medium text-[14px] text-[#00293D]">
|
||||
{item.label}
|
||||
</h3>
|
||||
<p className="font-serif text-[12px] text-[#00293D]/60">
|
||||
{item.description}
|
||||
</p>
|
||||
</div>
|
||||
<ToggleSwitch
|
||||
enabled={item.enabled}
|
||||
onToggle={() => togglePushNotification(item.id)}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Save Button */}
|
||||
<div className="flex justify-end">
|
||||
<button
|
||||
onClick={handleSave}
|
||||
className="px-8 py-3 bg-[#e58625] text-white rounded-[15px] font-fractul font-medium text-[14px] hover:bg-[#d47920] transition-colors"
|
||||
>
|
||||
Save Changes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
172
src/app/(agent)/agent/settings/page.tsx
Normal file
@@ -0,0 +1,172 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import Image from 'next/image';
|
||||
import { SettingsSidebar } from './component/SettingsSidebar';
|
||||
|
||||
export default function ProfileSettingsPage() {
|
||||
const [formData, setFormData] = useState({
|
||||
firstName: 'Brain',
|
||||
lastName: 'Nooland',
|
||||
email: 'brain.nooland@email.com',
|
||||
phone: '+1 (555) 123-4567',
|
||||
title: 'Top Real Estate Agent',
|
||||
location: 'Los Angeles, CA',
|
||||
});
|
||||
|
||||
const handleChange = (field: string, value: string) => {
|
||||
setFormData((prev) => ({ ...prev, [field]: value }));
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
console.log('Saving profile settings:', formData);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col lg:flex-row gap-6">
|
||||
{/* Left Sidebar */}
|
||||
<SettingsSidebar
|
||||
name={`${formData.firstName} ${formData.lastName}`}
|
||||
title={formData.title}
|
||||
/>
|
||||
|
||||
{/* Main Content */}
|
||||
<div className="flex-1">
|
||||
{/* Header Card */}
|
||||
<div className="border border-[#00293d]/10 rounded-[15px] px-6 py-4 mb-4 bg-white">
|
||||
<h1 className="font-fractul font-bold text-[15px] leading-[18px] text-[#00293D]">
|
||||
Profile Settings
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
{/* Profile Settings Form */}
|
||||
<div className="border border-[#00293d]/10 rounded-[15px] bg-white p-6">
|
||||
{/* Profile Photo Section */}
|
||||
<div className="flex items-center gap-6 mb-8 pb-6 border-b border-[#00293d]/10">
|
||||
<div className="relative">
|
||||
<div className="w-[100px] h-[100px] rounded-full overflow-hidden border-2 border-[#e58625]">
|
||||
<Image
|
||||
src="/assets/icons/user-placeholder-icon.svg"
|
||||
alt="Profile"
|
||||
width={100}
|
||||
height={100}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<button className="absolute bottom-0 right-0 w-8 h-8 bg-[#e58625] rounded-full flex items-center justify-center hover:bg-[#d47920] transition-colors">
|
||||
<Image
|
||||
src="/assets/icons/edit-icon.svg"
|
||||
alt="Edit"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-fractul font-bold text-[16px] text-[#00293D] mb-1">
|
||||
Profile Photo
|
||||
</h3>
|
||||
<p className="font-serif text-[12px] text-[#00293D]/60 mb-3">
|
||||
JPG, GIF or PNG. Max size 2MB
|
||||
</p>
|
||||
<button className="px-4 py-2 border border-[#e58625] text-[#e58625] rounded-[15px] font-serif text-[12px] hover:bg-[#e58625]/10 transition-colors">
|
||||
Upload New Photo
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Form Fields */}
|
||||
<div className="space-y-6">
|
||||
{/* Name Row */}
|
||||
<div className="flex flex-col sm:flex-row gap-4">
|
||||
<div className="flex-1">
|
||||
<label className="block text-[12px] font-medium text-[#00293D]/70 font-serif mb-2">
|
||||
First Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.firstName}
|
||||
onChange={(e) => handleChange('firstName', e.target.value)}
|
||||
className="w-full h-[40px] px-4 border border-[#00293D]/20 rounded-[15px] text-[14px] font-serif text-[#00293D] focus:outline-none focus:border-[#E58625]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<label className="block text-[12px] font-medium text-[#00293D]/70 font-serif mb-2">
|
||||
Last Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.lastName}
|
||||
onChange={(e) => handleChange('lastName', e.target.value)}
|
||||
className="w-full h-[40px] px-4 border border-[#00293D]/20 rounded-[15px] text-[14px] font-serif text-[#00293D] focus:outline-none focus:border-[#E58625]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Email */}
|
||||
<div>
|
||||
<label className="block text-[12px] font-medium text-[#00293D]/70 font-serif mb-2">
|
||||
Email Address
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
value={formData.email}
|
||||
onChange={(e) => handleChange('email', e.target.value)}
|
||||
className="w-full h-[40px] px-4 border border-[#00293D]/20 rounded-[15px] text-[14px] font-serif text-[#00293D] focus:outline-none focus:border-[#E58625]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Phone */}
|
||||
<div>
|
||||
<label className="block text-[12px] font-medium text-[#00293D]/70 font-serif mb-2">
|
||||
Phone Number
|
||||
</label>
|
||||
<input
|
||||
type="tel"
|
||||
value={formData.phone}
|
||||
onChange={(e) => handleChange('phone', e.target.value)}
|
||||
className="w-full h-[40px] px-4 border border-[#00293D]/20 rounded-[15px] text-[14px] font-serif text-[#00293D] focus:outline-none focus:border-[#E58625]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Title */}
|
||||
<div>
|
||||
<label className="block text-[12px] font-medium text-[#00293D]/70 font-serif mb-2">
|
||||
Professional Title
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.title}
|
||||
onChange={(e) => handleChange('title', e.target.value)}
|
||||
className="w-full h-[40px] px-4 border border-[#00293D]/20 rounded-[15px] text-[14px] font-serif text-[#00293D] focus:outline-none focus:border-[#E58625]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Location */}
|
||||
<div>
|
||||
<label className="block text-[12px] font-medium text-[#00293D]/70 font-serif mb-2">
|
||||
Location
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.location}
|
||||
onChange={(e) => handleChange('location', e.target.value)}
|
||||
className="w-full h-[40px] px-4 border border-[#00293D]/20 rounded-[15px] text-[14px] font-serif text-[#00293D] focus:outline-none focus:border-[#E58625]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Save Button */}
|
||||
<div className="mt-8 flex justify-end">
|
||||
<button
|
||||
onClick={handleSave}
|
||||
className="px-8 py-3 bg-[#e58625] text-white rounded-[15px] font-fractul font-medium text-[14px] hover:bg-[#d47920] transition-colors"
|
||||
>
|
||||
Save Changes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
165
src/app/(agent)/agent/settings/password/page.tsx
Normal file
@@ -0,0 +1,165 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { SettingsSidebar } from '../component/SettingsSidebar';
|
||||
|
||||
export default function PasswordSecurityPage() {
|
||||
const [formData, setFormData] = useState({
|
||||
currentPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
});
|
||||
|
||||
const [showPasswords, setShowPasswords] = useState({
|
||||
current: false,
|
||||
new: false,
|
||||
confirm: false,
|
||||
});
|
||||
|
||||
const handleChange = (field: string, value: string) => {
|
||||
setFormData((prev) => ({ ...prev, [field]: value }));
|
||||
};
|
||||
|
||||
const toggleShowPassword = (field: 'current' | 'new' | 'confirm') => {
|
||||
setShowPasswords((prev) => ({ ...prev, [field]: !prev[field] }));
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
if (formData.newPassword !== formData.confirmPassword) {
|
||||
alert('Passwords do not match');
|
||||
return;
|
||||
}
|
||||
console.log('Updating password');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col lg:flex-row gap-6">
|
||||
{/* Left Sidebar */}
|
||||
<SettingsSidebar />
|
||||
|
||||
{/* Main Content */}
|
||||
<div className="flex-1">
|
||||
{/* Header Card */}
|
||||
<div className="border border-[#00293d]/10 rounded-[15px] px-6 py-4 mb-4 bg-white">
|
||||
<h1 className="font-fractul font-bold text-[15px] leading-[18px] text-[#00293D]">
|
||||
Password Security
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
{/* Password Form */}
|
||||
<div className="border border-[#00293d]/10 rounded-[15px] bg-white p-6">
|
||||
<div className="mb-6">
|
||||
<h2 className="font-fractul font-bold text-[16px] text-[#00293D] mb-2">
|
||||
Change Password
|
||||
</h2>
|
||||
<p className="font-serif text-[12px] text-[#00293D]/60">
|
||||
Ensure your account is using a strong password to stay secure
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Form Fields */}
|
||||
<div className="space-y-6 max-w-md">
|
||||
{/* Current Password */}
|
||||
<div>
|
||||
<label className="block text-[12px] font-medium text-[#00293D]/70 font-serif mb-2">
|
||||
Current Password
|
||||
</label>
|
||||
<div className="relative">
|
||||
<input
|
||||
type={showPasswords.current ? 'text' : 'password'}
|
||||
value={formData.currentPassword}
|
||||
onChange={(e) => handleChange('currentPassword', e.target.value)}
|
||||
placeholder="Enter current password"
|
||||
className="w-full h-[40px] px-4 pr-12 border border-[#00293D]/20 rounded-[15px] text-[14px] font-serif text-[#00293D] placeholder:text-[#00293D]/40 focus:outline-none focus:border-[#E58625]"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => toggleShowPassword('current')}
|
||||
className="absolute right-4 top-1/2 -translate-y-1/2 text-[#00293D]/50 hover:text-[#00293D] cursor-pointer"
|
||||
>
|
||||
{showPasswords.current ? '🙈' : '👁️'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* New Password */}
|
||||
<div>
|
||||
<label className="block text-[12px] font-medium text-[#00293D]/70 font-serif mb-2">
|
||||
New Password
|
||||
</label>
|
||||
<div className="relative">
|
||||
<input
|
||||
type={showPasswords.new ? 'text' : 'password'}
|
||||
value={formData.newPassword}
|
||||
onChange={(e) => handleChange('newPassword', e.target.value)}
|
||||
placeholder="Enter new password"
|
||||
className="w-full h-[40px] px-4 pr-12 border border-[#00293D]/20 rounded-[15px] text-[14px] font-serif text-[#00293D] placeholder:text-[#00293D]/40 focus:outline-none focus:border-[#E58625]"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => toggleShowPassword('new')}
|
||||
className="absolute right-4 top-1/2 -translate-y-1/2 text-[#00293D]/50 hover:text-[#00293D] cursor-pointer"
|
||||
>
|
||||
{showPasswords.new ? '🙈' : '👁️'}
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-[11px] text-[#00293D]/50 font-serif mt-1">
|
||||
Minimum 8 characters with at least one uppercase, lowercase, and number
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Confirm Password */}
|
||||
<div>
|
||||
<label className="block text-[12px] font-medium text-[#00293D]/70 font-serif mb-2">
|
||||
Confirm New Password
|
||||
</label>
|
||||
<div className="relative">
|
||||
<input
|
||||
type={showPasswords.confirm ? 'text' : 'password'}
|
||||
value={formData.confirmPassword}
|
||||
onChange={(e) => handleChange('confirmPassword', e.target.value)}
|
||||
placeholder="Confirm new password"
|
||||
className="w-full h-[40px] px-4 pr-12 border border-[#00293D]/20 rounded-[15px] text-[14px] font-serif text-[#00293D] placeholder:text-[#00293D]/40 focus:outline-none focus:border-[#E58625]"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => toggleShowPassword('confirm')}
|
||||
className="absolute right-4 top-1/2 -translate-y-1/2 text-[#00293D]/50 hover:text-[#00293D] cursor-pointer"
|
||||
>
|
||||
{showPasswords.confirm ? '🙈' : '👁️'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Save Button */}
|
||||
<div className="mt-8">
|
||||
<button
|
||||
onClick={handleSave}
|
||||
className="px-8 py-3 bg-[#e58625] text-white rounded-[15px] font-fractul font-medium text-[14px] hover:bg-[#d47920] transition-colors"
|
||||
>
|
||||
Update Password
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Two-Factor Authentication Section */}
|
||||
<div className="border border-[#00293d]/10 rounded-[15px] bg-white p-6 mt-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h2 className="font-fractul font-bold text-[16px] text-[#00293D] mb-2">
|
||||
Two-Factor Authentication
|
||||
</h2>
|
||||
<p className="font-serif text-[12px] text-[#00293D]/60">
|
||||
Add an extra layer of security to your account
|
||||
</p>
|
||||
</div>
|
||||
<button className="px-6 py-2 border border-[#e58625] text-[#e58625] rounded-[15px] font-serif text-[12px] hover:bg-[#e58625]/10 transition-colors">
|
||||
Enable 2FA
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
255
src/app/(agent)/agent/settings/privacy/page.tsx
Normal file
@@ -0,0 +1,255 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { SettingsSidebar } from '../component/SettingsSidebar';
|
||||
|
||||
interface PrivacySetting {
|
||||
id: string;
|
||||
label: string;
|
||||
description: string;
|
||||
value: string;
|
||||
options: { value: string; label: string }[];
|
||||
}
|
||||
|
||||
export default function PrivacyPage() {
|
||||
const [privacySettings, setPrivacySettings] = useState<PrivacySetting[]>([
|
||||
{
|
||||
id: 'profile_visibility',
|
||||
label: 'Profile Visibility',
|
||||
description: 'Control who can see your profile',
|
||||
value: 'public',
|
||||
options: [
|
||||
{ value: 'public', label: 'Public' },
|
||||
{ value: 'connections', label: 'Connections Only' },
|
||||
{ value: 'private', label: 'Private' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'contact_info',
|
||||
label: 'Contact Information',
|
||||
description: 'Control who can see your contact details',
|
||||
value: 'connections',
|
||||
options: [
|
||||
{ value: 'public', label: 'Public' },
|
||||
{ value: 'connections', label: 'Connections Only' },
|
||||
{ value: 'private', label: 'Hidden' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'activity_status',
|
||||
label: 'Activity Status',
|
||||
description: 'Show when you are active on the platform',
|
||||
value: 'public',
|
||||
options: [
|
||||
{ value: 'public', label: 'Everyone' },
|
||||
{ value: 'connections', label: 'Connections Only' },
|
||||
{ value: 'private', label: 'No One' },
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const [dataSettings, setDataSettings] = useState({
|
||||
shareAnalytics: true,
|
||||
personalizedAds: false,
|
||||
thirdPartySharing: false,
|
||||
});
|
||||
|
||||
const handlePrivacyChange = (id: string, value: string) => {
|
||||
setPrivacySettings((prev) =>
|
||||
prev.map((item) => (item.id === id ? { ...item, value } : item))
|
||||
);
|
||||
};
|
||||
|
||||
const handleDataSettingChange = (key: keyof typeof dataSettings) => {
|
||||
setDataSettings((prev) => ({ ...prev, [key]: !prev[key] }));
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
console.log('Saving privacy settings:', { privacySettings, dataSettings });
|
||||
};
|
||||
|
||||
const handleDeleteAccount = () => {
|
||||
if (confirm('Are you sure you want to delete your account? This action cannot be undone.')) {
|
||||
console.log('Deleting account');
|
||||
}
|
||||
};
|
||||
|
||||
const ToggleSwitch = ({
|
||||
enabled,
|
||||
onToggle,
|
||||
}: {
|
||||
enabled: boolean;
|
||||
onToggle: () => void;
|
||||
}) => (
|
||||
<button
|
||||
onClick={onToggle}
|
||||
className={`relative w-[44px] h-[24px] rounded-full transition-colors cursor-pointer ${
|
||||
enabled ? 'bg-[#e58625]' : 'bg-[#00293D]/20'
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`absolute top-[2px] w-[20px] h-[20px] rounded-full bg-white shadow transition-transform ${
|
||||
enabled ? 'translate-x-[22px]' : 'translate-x-[2px]'
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col lg:flex-row gap-6">
|
||||
{/* Left Sidebar */}
|
||||
<SettingsSidebar />
|
||||
|
||||
{/* Main Content */}
|
||||
<div className="flex-1">
|
||||
{/* Header Card */}
|
||||
<div className="border border-[#00293d]/10 rounded-[15px] px-6 py-4 mb-4 bg-white">
|
||||
<h1 className="font-fractul font-bold text-[15px] leading-[18px] text-[#00293D]">
|
||||
Privacy
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
{/* Privacy Settings */}
|
||||
<div className="border border-[#00293d]/10 rounded-[15px] bg-white p-6 mb-4">
|
||||
<div className="mb-6">
|
||||
<h2 className="font-fractul font-bold text-[16px] text-[#00293D] mb-2">
|
||||
Privacy Settings
|
||||
</h2>
|
||||
<p className="font-serif text-[12px] text-[#00293D]/60">
|
||||
Control your privacy and visibility preferences
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
{privacySettings.map((item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
className="pb-4 border-b border-[#00293d]/10 last:border-0"
|
||||
>
|
||||
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-3">
|
||||
<div>
|
||||
<h3 className="font-serif font-medium text-[14px] text-[#00293D]">
|
||||
{item.label}
|
||||
</h3>
|
||||
<p className="font-serif text-[12px] text-[#00293D]/60">
|
||||
{item.description}
|
||||
</p>
|
||||
</div>
|
||||
<select
|
||||
value={item.value}
|
||||
onChange={(e) => handlePrivacyChange(item.id, e.target.value)}
|
||||
className="h-[36px] px-4 border border-[#00293D]/20 rounded-[10px] text-[13px] font-serif text-[#00293D] focus:outline-none focus:border-[#E58625] bg-white cursor-pointer"
|
||||
>
|
||||
{item.options.map((option) => (
|
||||
<option key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Data & Personalization */}
|
||||
<div className="border border-[#00293d]/10 rounded-[15px] bg-white p-6 mb-4">
|
||||
<div className="mb-6">
|
||||
<h2 className="font-fractul font-bold text-[16px] text-[#00293D] mb-2">
|
||||
Data & Personalization
|
||||
</h2>
|
||||
<p className="font-serif text-[12px] text-[#00293D]/60">
|
||||
Manage how your data is used
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between py-3 border-b border-[#00293d]/10">
|
||||
<div>
|
||||
<h3 className="font-serif font-medium text-[14px] text-[#00293D]">
|
||||
Share Analytics
|
||||
</h3>
|
||||
<p className="font-serif text-[12px] text-[#00293D]/60">
|
||||
Help improve our service by sharing usage data
|
||||
</p>
|
||||
</div>
|
||||
<ToggleSwitch
|
||||
enabled={dataSettings.shareAnalytics}
|
||||
onToggle={() => handleDataSettingChange('shareAnalytics')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between py-3 border-b border-[#00293d]/10">
|
||||
<div>
|
||||
<h3 className="font-serif font-medium text-[14px] text-[#00293D]">
|
||||
Personalized Ads
|
||||
</h3>
|
||||
<p className="font-serif text-[12px] text-[#00293D]/60">
|
||||
See ads tailored to your interests
|
||||
</p>
|
||||
</div>
|
||||
<ToggleSwitch
|
||||
enabled={dataSettings.personalizedAds}
|
||||
onToggle={() => handleDataSettingChange('personalizedAds')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between py-3">
|
||||
<div>
|
||||
<h3 className="font-serif font-medium text-[14px] text-[#00293D]">
|
||||
Third-Party Data Sharing
|
||||
</h3>
|
||||
<p className="font-serif text-[12px] text-[#00293D]/60">
|
||||
Allow sharing data with third-party partners
|
||||
</p>
|
||||
</div>
|
||||
<ToggleSwitch
|
||||
enabled={dataSettings.thirdPartySharing}
|
||||
onToggle={() => handleDataSettingChange('thirdPartySharing')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Danger Zone */}
|
||||
<div className="border border-red-200 rounded-[15px] bg-red-50/50 p-6 mb-4">
|
||||
<div className="mb-4">
|
||||
<h2 className="font-fractul font-bold text-[16px] text-red-600 mb-2">
|
||||
Danger Zone
|
||||
</h2>
|
||||
<p className="font-serif text-[12px] text-red-600/70">
|
||||
Irreversible and destructive actions
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
|
||||
<div>
|
||||
<h3 className="font-serif font-medium text-[14px] text-[#00293D]">
|
||||
Delete Account
|
||||
</h3>
|
||||
<p className="font-serif text-[12px] text-[#00293D]/60">
|
||||
Permanently delete your account and all data
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleDeleteAccount}
|
||||
className="px-6 py-2 border border-red-500 text-red-500 rounded-[15px] font-serif text-[12px] hover:bg-red-50 transition-colors"
|
||||
>
|
||||
Delete Account
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Save Button */}
|
||||
<div className="flex justify-end">
|
||||
<button
|
||||
onClick={handleSave}
|
||||
className="px-8 py-3 bg-[#e58625] text-white rounded-[15px] font-fractul font-medium text-[14px] hover:bg-[#d47920] transition-colors"
|
||||
>
|
||||
Save Changes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -47,31 +47,30 @@ export function AgentHeader({ userName, userEmail }: AgentHeaderProps) {
|
||||
</nav>
|
||||
|
||||
{/* Right Side Icons */}
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex items-center gap-4">
|
||||
{/* Notification Bell */}
|
||||
<button className="relative p-1 hover:opacity-80 transition-opacity">
|
||||
<button className="relative w-6 h-6 flex items-center justify-center hover:opacity-80 transition-opacity">
|
||||
<Image
|
||||
src="/assets/notification-icon.svg"
|
||||
alt="Notifications"
|
||||
width={18}
|
||||
height={21}
|
||||
width={20}
|
||||
height={22}
|
||||
/>
|
||||
{/* Notification Dot */}
|
||||
<span className="absolute top-0 right-0 w-1.5 h-1.5 bg-red-500 rounded-full"></span>
|
||||
<span className="absolute -top-0.5 -right-0.5 w-2 h-2 bg-red-500 rounded-full"></span>
|
||||
</button>
|
||||
|
||||
{/* Profile Icon with Dropdown */}
|
||||
<div className="relative">
|
||||
<button
|
||||
onClick={() => setShowProfileMenu(!showProfileMenu)}
|
||||
className="w-6 h-6 rounded-full overflow-hidden hover:opacity-80 transition-opacity"
|
||||
className="w-6 h-6 flex items-center justify-center hover:opacity-80 transition-opacity"
|
||||
>
|
||||
<Image
|
||||
src="/assets/profile-icon.svg"
|
||||
alt="Profile"
|
||||
width={24}
|
||||
height={24}
|
||||
className="w-full h-full"
|
||||
/>
|
||||
</button>
|
||||
|
||||
|
||||