diff --git a/src/components/layout/PageLayout/PageLayout.tsx b/src/components/layout/PageLayout/PageLayout.tsx
index 033ff2d..25bced4 100644
--- a/src/components/layout/PageLayout/PageLayout.tsx
+++ b/src/components/layout/PageLayout/PageLayout.tsx
@@ -1,4 +1,4 @@
-import { useState } from 'react';
+import { useState, useEffect } from 'react';
import { Bell, Settings, User, Plus, Search, Home, FileText, CheckCircle, LogOut, PanelLeft, PanelLeftClose } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
@@ -14,7 +14,7 @@ interface PageLayoutProps {
}
export function PageLayout({ children, currentPage = 'dashboard', onNavigate, onNewRequest }: PageLayoutProps) {
- const [sidebarOpen, setSidebarOpen] = useState(true);
+ const [sidebarOpen, setSidebarOpen] = useState(false);
const menuItems = [
{ id: 'dashboard', label: 'Dashboard', icon: Home },
@@ -27,11 +27,52 @@ export function PageLayout({ children, currentPage = 'dashboard', onNavigate, on
setSidebarOpen(!sidebarOpen);
};
+ // Handle responsive behavior: sidebar open on desktop, closed on mobile
+ useEffect(() => {
+ const handleResize = () => {
+ // 768px is the md breakpoint in Tailwind
+ if (window.innerWidth >= 768) {
+ setSidebarOpen(true); // Always open on desktop
+ } else {
+ setSidebarOpen(false); // Closed by default on mobile
+ }
+ };
+
+ // Set initial state
+ handleResize();
+
+ // Add event listener
+ window.addEventListener('resize', handleResize);
+
+ // Cleanup
+ return () => window.removeEventListener('resize', handleResize);
+ }, []);
+
return (
- {/* Sidebar */}
-
-
+ {/* Mobile Overlay */}
+ {sidebarOpen && (
+
setSidebarOpen(false)}
+ />
+ )}
+
+ {/* Sidebar - Hidden on mobile by default, toggleable on desktop */}
+
{/* Main Content Area */}
diff --git a/src/components/workNote/WorkNoteChat/WorkNoteChat.tsx b/src/components/workNote/WorkNoteChat/WorkNoteChat.tsx
index 62fbd6d..cdc4a07 100644
--- a/src/components/workNote/WorkNoteChat/WorkNoteChat.tsx
+++ b/src/components/workNote/WorkNoteChat/WorkNoteChat.tsx
@@ -305,7 +305,9 @@ export function WorkNoteChat({ requestId, onBack }: WorkNoteChatProps) {
const [showEmojiPicker, setShowEmojiPicker] = useState(false);
const [messages, setMessages] = useState
(INITIAL_MESSAGES);
const [showSidebar, setShowSidebar] = useState(false);
+ const [selectedFiles, setSelectedFiles] = useState([]);
const messagesEndRef = useRef(null);
+ const fileInputRef = useRef(null);
// Get request info
const requestInfo = useMemo(() => {
@@ -334,26 +336,116 @@ export function WorkNoteChat({ requestId, onBack }: WorkNoteChatProps) {
}, [messages]);
const handleSendMessage = () => {
- if (message.trim()) {
+ if (message.trim() || selectedFiles.length > 0) {
+ const attachments = selectedFiles.map(file => ({
+ name: file.name,
+ url: URL.createObjectURL(file),
+ type: file.type.split('/')[1] || 'file'
+ }));
+
const newMessage: Message = {
id: Date.now().toString(),
user: { name: 'You', avatar: 'YO', role: 'Current User' },
content: message,
- timestamp: new Date().toLocaleString(),
+ timestamp: new Date().toLocaleString('en-US', {
+ month: 'short',
+ day: 'numeric',
+ year: 'numeric',
+ hour: 'numeric',
+ minute: 'numeric',
+ hour12: true
+ }),
mentions: extractMentions(message),
- isHighPriority: message.includes('!important') || message.includes('urgent')
+ isHighPriority: message.includes('!important') || message.includes('urgent'),
+ attachments: attachments.length > 0 ? attachments : undefined
};
setMessages(prev => [...prev, newMessage]);
setMessage('');
+ setSelectedFiles([]);
}
};
+ const handleFileSelect = (e: React.ChangeEvent) => {
+ if (e.target.files) {
+ const filesArray = Array.from(e.target.files);
+ setSelectedFiles(prev => [...prev, ...filesArray]);
+ }
+ };
+
+ const handleRemoveFile = (index: number) => {
+ setSelectedFiles(prev => prev.filter((_, i) => i !== index));
+ // Reset file input to allow reselecting the same file
+ if (fileInputRef.current) {
+ fileInputRef.current.value = '';
+ }
+ };
+
+ const handleEmojiSelect = (emoji: string) => {
+ setMessage(prev => prev + emoji);
+ setShowEmojiPicker(false);
+ };
+
+ const handleAttachmentClick = () => {
+ fileInputRef.current?.click();
+ };
+
+ // Emoji picker data - Expanded collection
+ const emojiList = [
+ // Smileys & Emotions
+ '๐', '๐', '๐คฃ', '๐', '๐', '๐', '๐
', '๐', '๐', '๐',
+ '๐', '๐ฅฐ', '๐', '๐', '๐', '๐', '๐', '๐ค', '๐คฉ', '๐ค',
+ '๐คจ', '๐', '๐', '๐ถ', '๐', '๐', '๐', '๐', '๐ฌ', '๐ค',
+ '๐ด', '๐ช', '๐ต', '๐คฏ', '๐คช', '๐', '๐', '๐', '๐คค', '๐',
+ '๐', '๐ค', '๐ง', '๐', '๐', '๐', 'โน๏ธ', '๐ฎ', '๐ฏ', '๐ฒ',
+ '๐ณ', '๐ฅบ', '๐ฆ', '๐ง', '๐จ', '๐ฐ', '๐ฅ', '๐ข', '๐ญ', '๐ฑ',
+ '๐', '๐ฃ', '๐', '๐', '๐ฉ', '๐ซ', '๐ฅฑ', '๐ค', '๐ก', '๐ ',
+ '๐คฌ', '๐', '๐ฟ', '๐', 'โ ๏ธ', '๐ฉ', '๐คก', '๐น', '๐บ', '๐ป',
+
+ // Gestures & Body
+ '๐', '๐ค', '๐๏ธ', 'โ', '๐', '๐', '๐ค', '๐ค', 'โ๏ธ', '๐ค',
+ '๐ค', '๐ค', '๐ค', '๐', '๐', '๐', '๐', '๐', 'โ๏ธ', '๐',
+ '๐', 'โ', '๐', '๐ค', '๐ค', '๐', '๐', '๐', '๐คฒ', '๐ค',
+ '๐', '๐ช', '๐ฆพ', '๐ฆฟ', '๐ฆต', '๐ฆถ', '๐', '๐ฆป', '๐', '๐ง ',
+
+ // Hearts & Love
+ 'โค๏ธ', '๐งก', '๐', '๐', '๐', '๐', '๐ค', '๐ค', '๐ค', '๐',
+ 'โฃ๏ธ', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐', 'โค๏ธโ๐ฅ',
+
+ // Work & Office
+ '๐ผ', '๐', '๐', '๐', '๐ป', 'โจ๏ธ', '๐ฅ๏ธ', '๐จ๏ธ', '๐ฑ๏ธ', '๐พ',
+ '๐ฟ', '๐ฑ', 'โ๏ธ', '๐', '๐', '๐ ', '๐ง', 'โ๏ธ', '๐จ', '๐ฉ',
+ '๐ฎ', '๐ช', '๐ซ', '๐ฌ', '๐ญ', '๐', '๐', '๐', '๐', 'โ๏ธ',
+ 'โ๏ธ', '๐๏ธ', '๐๏ธ', '๐', '๐', '๐', '๐', '๐๏ธ', '๐', '๐',
+
+ // Success & Achievement
+ 'โ
', 'โ๏ธ', 'โ๏ธ', '๐ฏ', '๐๏ธ', '๐', '๐ฅ', '๐ฅ', '๐ฅ', 'โญ',
+ '๐', 'โจ', '๐ซ', '๐ฅ', '๐ฅ', 'โก', '๐ฏ', '๐', '๐', '๐',
+
+ // Alerts & Symbols
+ 'โ ๏ธ', '๐ซ', 'โ', 'โ', '๐ท', '๐ฏ', '๐ฑ', '๐ณ', '๐', '๐ต',
+ 'โ', 'โ', 'โ', 'โ', 'โผ๏ธ', 'โ๏ธ', '๐ข', '๐ฌ', '๐ญ', '๐ฏ๏ธ',
+
+ // Time & Calendar
+ 'โฐ', 'โฑ๏ธ', 'โฒ๏ธ', 'โณ', 'โ', '๐
', '๐', '๐๏ธ', '๐', '๐',
+ '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐', '๐',
+
+ // Actions & Arrows
+ '๐', '๐ฏ', '๐ฒ', '๐ฐ', '๐งฉ', '๐', '๐', '๐', '๐๏ธ', '๐',
+ '๐', '๐', '๐', '๐', '๐', '๐ฃ', '๐ข', '๐ก', '๐ฆ', '๐ฎ',
+ 'โ', 'โ', 'โ๏ธ', 'โ', 'โพ๏ธ', 'โผ๏ธ', 'โ๏ธ', 'โ', 'โ', 'โ',
+ '๐', '๐', '๐', 'โถ๏ธ', 'โธ๏ธ', 'โฏ๏ธ', 'โน๏ธ', 'โบ๏ธ', 'โญ๏ธ', 'โฎ๏ธ',
+ 'โฉ', 'โช', 'โซ', 'โฌ', 'โ๏ธ', '๐ผ', '๐ฝ', 'โก๏ธ', 'โฌ
๏ธ', 'โฌ๏ธ',
+ 'โฌ๏ธ', 'โ๏ธ', 'โ๏ธ', 'โ๏ธ', 'โ๏ธ', 'โ๏ธ', 'โ๏ธ', 'โช๏ธ', 'โฉ๏ธ', 'โคด๏ธ'
+ ];
+
const extractMentions = (text: string): string[] => {
const mentionRegex = /@([\w\s]+)(?=\s|$|[.,!?])/g;
- const mentions = [];
+ const mentions: string[] = [];
let match;
while ((match = mentionRegex.exec(text)) !== null) {
- mentions.push(match[1].trim());
+ if (match[1]) {
+ mentions.push(match[1].trim());
+ }
}
return mentions;
};
@@ -392,8 +484,8 @@ export function WorkNoteChat({ requestId, onBack }: WorkNoteChatProps) {
return (
- {/* Header */}
-
+ {/* Header - Fixed at top */}
+