Email Client
Three-panel email interface with folder management, compose functionality, and advanced search capabilities.
Advanced communication suite with enterprise-grade email management, real-time chat system, and comprehensive calendar integration. Features responsive layouts, advanced search capabilities, and seamless workflow integration for modern team collaboration.
Full-featured email client with multi-panel layout, advanced search, and comprehensive folder management
Instant messaging with user search, conversation management, and responsive mobile-first design
FullCalendar-powered scheduling with event management, drag-drop functionality, and filtering capabilities
Mobile-first approach with adaptive layouts, touch-friendly interactions, and seamless device transitions
Powerful search capabilities across emails, chats, and calendar events with real-time filtering
Live data synchronization with optimistic updates and seamless state management
Email Client
Three-panel email interface with folder management, compose functionality, and advanced search capabilities.
Instant Messaging
Real-time chat system with user discovery, conversation threads, and mobile-optimized interface.
Calendar Management
Full-featured calendar with event creation, scheduling, and comprehensive filtering options.
Unified Interface
Seamless integration between communication tools with consistent design patterns and shared state.
Professional email management with 975+ lines of Vue code, featuring advanced responsive layout and workflow capabilities.
<script setup lang="ts">import { ref, computed, onMounted, nextTick } from 'vue'import { BaseCard } from '@/components/BaseCard'import { Button } from '@/components/ui/button'import { Icon } from '@iconify/vue'import { Badge } from '@/components/ui/badge'import { ScrollArea } from '@/components/ui/scroll-area'import { useMediaQuery } from '@/hooks/useMediaQuery'import MailSidebar from './components/MailSidebar.vue'import MailList from './components/MailList.vue'import MailDetail from './components/MailDetail.vue'import ComposeEmail from './components/ComposeEmail.vue'import MailSearch from './components/MailSearch.vue'import { useMailData } from './composables/useMailData'
// Mail data managementconst { emails, folders, loading, stats, loadEmails, refreshEmails, markAsRead, markAsUnread, toggleStar, deleteEmails, archiveEmails, markAsSpam, applySearchFilters, clearSearchFilters,} = useMailData()
// Media queries for responsive designconst { isTablet, canShowThreeColumns, TwoXL, shouldUseFullScreen } = useMediaQuery()
// State managementconst selectedFolder = ref<EmailFolder>('inbox')const selectedEmail = ref<Email | null>(null)const isComposing = ref(false)const isSidebarCollapsed = ref(false)const showMobileNav = ref(false)const layoutMode = ref<'list' | 'detail' | 'compose'>('list')
// Computed properties for dynamic layoutconst currentUnreadCount = computed(() => { const currentFolder = folders.value.find((f) => f.id === selectedFolder.value) return currentFolder?.unreadCount || 0})
// Responsive layout logicconst shouldShowSidebar = computed(() => { if (shouldUseFullScreen.value && layoutMode.value !== 'list') { return false } return true})
const shouldShowEmailList = computed(() => { if (shouldUseFullScreen.value) { return layoutMode.value === 'list' } if (TwoXL.value) { return true } return !shouldShowMainContent.value})</script>
<template> <BaseCard class="overflow-hidden"> <div class="h-[calc(100vh-12.5rem)] flex flex-col min-h-[82vh]"> <!-- Mobile Header --> <div v-if="shouldUseFullScreen" class="flex items-center justify-between p-4 border-b"> <div class="flex items-center gap-3"> <Button variant="ghost" size="sm" @click="toggleMobileNav"> <Icon icon="lucide:menu" class="h-5 w-5" /> </Button> <h1 class="text-lg font-semibold">Mail</h1> </div> <Button size="sm" @click="handleComposeNew"> <Icon icon="lucide:pencil" class="h-4 w-4 me-2" /> Compose </Button> </div>
<!-- Main Layout --> <div class="flex-1 flex overflow-hidden"> <!-- Left Sidebar - Mail Folders --> <div v-if="shouldShowSidebar" class="w-72 border-e border-border bg-background"> <MailSidebar :folders="folders" :selected-folder="selectedFolder" :collapsed="isSidebarCollapsed" :loading="loading" @folder-select="handleFolderSelect" /> </div>
<!-- Center Panel - Mail List --> <div v-if="shouldShowEmailList" class="w-96 border-e border-border"> <div class="p-4 border-b border-border space-y-4"> <div class="flex items-center justify-between"> <h3 class="font-medium capitalize">{{ selectedFolder }}</h3> <Badge v-if="currentUnreadCount > 0" variant="secondary"> {{ currentUnreadCount }} new </Badge> </div> <MailSearch @search="handleSearch" @clear="handleClearSearch" /> </div> <MailList :emails="emails" :selected-email-id="selectedEmail?.id" :loading="loading" @email-select="handleEmailSelect" @email-star="handleEmailStar" @bulk-action="handleBulkAction" /> </div>
<!-- Right Panel - Mail Detail/Compose --> <div class="flex-1"> <ComposeEmail v-if="isComposing" :mode="composeMode" @send="handleSendEmail" @save-draft="handleSaveDraft" @close="handleCloseCompose" /> <MailDetail v-else-if="selectedEmail" :email="selectedEmail" @reply="handleReply" @forward="handleForward" @delete="handleEmailAction" /> <div v-else class="h-full flex items-center justify-center"> <div class="text-center"> <Icon icon="lucide:mail" class="h-12 w-12 text-muted-foreground mx-auto mb-4" /> <h2 class="text-xl font-semibold mb-2">Your inbox awaits</h2> <p class="text-muted-foreground mb-6">Select an email to read it</p> <Button @click="handleComposeNew">Compose New Email</Button> </div> </div> </div> </div> </div> </BaseCard></template>
Core Email Features:
Responsive Layout Logic
Panel Management
Bulk Actions
Email Workflow
Advanced Search Features
Filter Categories
Composable Architecture:
const { emails, folders, loading, stats, loadEmails, refreshEmails, markAsRead, markAsUnread, toggleStar, deleteEmails, archiveEmails, markAsSpam, applySearchFilters, clearSearchFilters,} = useMailData()
Responsive Media Queries:
const { isTablet, canShowThreeColumns, TwoXL, shouldUseFullScreen } = useMediaQuery()
Modern chat interface with real-time messaging, user discovery, and conversation management.
<script setup lang="ts">import { ref, onMounted } from 'vue'import { useRouter } from 'vue-router'import { BaseCard } from '@/components/BaseCard'import { Input } from '@/components/ui/input'import { Button } from '@/components/ui/button'import { Badge } from '@/components/ui/badge'import { Icon } from '@iconify/vue'import ChatList from './components/ChatList.vue'import UserSearch from './components/UserSearch.vue'import { useChatData } from './composables/useChatData'
const router = useRouter()const { chats, loading, searchQuery, totalUnreadCount, loadChats, searchUsers, createChat } = useChatData()
const selectedChat = ref<Chat | null>(null)
const handleSelectChat = async (chat: Chat) => { selectedChat.value = chat await router.push({ name: 'chatDetail', params: { id: chat.id } })}
const handleStartChat = async (user: User) => { try { const newChat = await createChat([user]) await router.push({ name: 'chatDetail', params: { id: newChat.id } }) } catch (error) { console.error('Failed to create chat:', error) }}
onMounted(() => { loadChats()})</script>
<template> <div class="space-y-6"> <!-- Page Header --> <div class="flex items-center justify-between"> <div> <h1 class="text-2xl font-semibold">Chat</h1> <p class="mt-1 text-sm text-gray-500"> Manage your conversations <Badge v-if="totalUnreadCount > 0" variant="destructive" class="ms-2"> {{ totalUnreadCount }} unread </Badge> </p> </div> </div>
<div class="grid grid-cols-1 lg:grid-cols-12 gap-6 h-[calc(100vh-15.5rem)] min-h-[72vh]"> <!-- Chat List Sidebar --> <div class="lg:col-span-4 xl:col-span-3"> <BaseCard class="h-full flex flex-col"> <!-- Search bar --> <div class="p-4 border-b"> <div class="relative"> <Icon icon="lucide:search" class="absolute start-3 top-1/2 transform -translate-y-1/2 h-4 w-4" /> <Input v-model="searchQuery" placeholder="Search conversations..." class="ps-10" /> </div> </div>
<!-- Chat list --> <div class="flex-1 overflow-hidden"> <ChatList :chats="chats" :loading="loading" :active-chat="selectedChat" @select-chat="handleSelectChat" /> </div> </BaseCard> </div>
<!-- Welcome Message --> <div class="lg:col-span-8 xl:col-span-9"> <BaseCard class="h-full flex flex-col"> <div class="flex-1 flex flex-col items-center justify-center text-center p-8"> <div class="h-24 w-24 rounded-full bg-gradient-to-r from-primary to-primary/60 flex items-center justify-center mb-4"> <Icon icon="lucide:message-circle" class="h-12 w-12 text-white" /> </div> <h2 class="text-2xl font-bold mb-2">Start a conversation</h2> <p class="text-muted-foreground max-w-md mb-6"> Select a chat from the sidebar or search for users to start a new conversation. </p> <UserSearch @start-chat="handleStartChat" /> </div> </BaseCard> </div> </div> </div></template>
Chat System Features:
Grid Layout System:
State Management:
const { chats, loading, searchQuery, totalUnreadCount, loadChats, searchUsers, createChat} = useChatData()
Live Communication:
Chat Management:
Comprehensive calendar system with event management, scheduling, and advanced filtering capabilities.
<script setup lang="ts">import { ref, onMounted, watch } from 'vue'import { BaseCard } from '@/components/BaseCard'import { Motion } from 'motion-v'import AdminCalendar from './components/AdminCalendar.vue'import CalendarToolbar from './components/CalendarToolbar.vue'import EventModal from './components/EventModal.vue'import { useCalendar } from './composables/useCalendar'import { useEvents } from './composables/useEvents'import { useEventFilters } from './composables/useEventFilters'
const { calendarRef, state, changeView, goToToday, goToPrevious, goToNext, currentViewTitle } = useCalendar()
const { events, loading: eventsLoading, createEvent, updateEvent, deleteEvent, getEvent, duplicateEvent,} = useEvents()
// Event filteringconst { filteredEvents, setSearchTerm, setCategories, setStatuses } = useEventFilters(events.value)
// Sync filtered events with calendar statewatch(filteredEvents, (newFilteredEvents) => { state.events = newFilteredEvents}, { immediate: true })
const selectedEvent = ref<CalendarEvent | null>(null)const newEventDate = ref<Date | null>(null)
// Event handlersconst handleEventClick = (event: CalendarEvent) => { selectedEvent.value = event newEventDate.value = null}
const handleDateClick = (date: Date) => { selectedEvent.value = null newEventDate.value = date}
const handleEventDrop = async (newEvent: CalendarEvent, _oldEvent: CalendarEvent) => { try { await updateEvent(newEvent.id, { start: newEvent.start, end: newEvent.end, }) } catch (error) { console.error('Failed to update event:', error) }}
const handleViewChange = (view: CalendarView) => { changeView(view)}
const handleAddEvent = () => { selectedEvent.value = null newEventDate.value = new Date()}</script>
<template> <Motion :initial="{ opacity: 0, y: 20 }" :animate="{ opacity: 1, y: 0 }" :transition="{ duration: 0.5 }" > <div class="space-y-6"> <!-- Calendar Toolbar --> <CalendarToolbar :current-view="state.currentView" :view-title="currentViewTitle" :loading="state.loading" @view-change="handleViewChange" @go-today="goToToday" @go-previous="goToPrevious" @go-next="goToNext" @add-event="handleAddEvent" @refresh="handleRefresh" @search="setSearchTerm" @filter-categories="setCategories" @filter-statuses="setStatuses" />
<!-- Calendar Component --> <BaseCard> <AdminCalendar ref="adminCalendarRef" :calendar-ref="calendarRef" :events="state.events" :loading="state.loading" :current-view="state.currentView" @event-click="handleEventClick" @date-click="handleDateClick" @event-drop="handleEventDrop" @event-resize="handleEventResize" /> </BaseCard>
<!-- Event Modal --> <EventModal :visible="!!(selectedEvent || newEventDate)" :event="selectedEvent" :default-date="newEventDate" :loading="eventsLoading" @save="handleEventSave" @delete="handleEventDelete" @duplicate="handleEventDuplicate" @close="handleEventModalClose" /> </div> </Motion></template>
Calendar Features:
Core Component Structure:
Event Operations:
const { events, loading, createEvent, updateEvent, deleteEvent, getEvent, duplicateEvent,} = useEvents()
Event Filtering:
const { filteredEvents, setSearchTerm, setCategories, setStatuses} = useEventFilters(events.value)
Event Categories
Event Status
Advanced Scheduling
Calendar Views
External Integration
Workflow Integration
Universal Search Capabilities:
Real-time Notifications:
State Synchronization:
Data Export Options:
Adaptive Layout Strategy:
Mobile Optimizations:
Efficient Rendering:
Security Measures:
User Privacy:
The communication tools provide a comprehensive platform for team collaboration with enterprise-grade features, responsive design, and seamless integration across email, chat, and calendar systems.