ultisuite-client/components/gmail/contacts-page/contacts-app-shell.tsx
R3D347HR4Y 303b2b1074
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
wow
2026-06-11 01:22:40 +02:00

202 lines
5.9 KiB
TypeScript

"use client"
import { useCallback, useEffect, useState } from "react"
import { cn } from "@/lib/utils"
import { useIsMobile } from "@/hooks/use-mobile"
import { ContactsSidebar } from "./contacts-sidebar"
import { ContactsHeader } from "./contacts-header"
import { ContactsTable } from "./contacts-table"
import { ContactDetailPage } from "./contact-detail-page"
import { ContactCreatePage } from "./contact-create-page"
import { MergeDuplicatesView } from "./merge-duplicates-view"
import { OtherContactsView } from "./other-contacts-view"
import { IgnoredContactsView } from "./ignored-contacts-view"
import { BlockedContactsView } from "./blocked-contacts-view"
import { TrashView } from "./trash-view"
import { BulkCreateDialog } from "./bulk-create-dialog"
import { ImportDialog } from "./import-dialog"
import { CONTACTS_SHELL_CLASS } from "@/lib/contacts-chrome-classes"
import { AiChatPanel } from "@/components/ai/ai-chat-panel"
export type ContactsPageView =
| "contacts"
| "frequent"
| "other"
| "ignored"
| "blocked"
| "merge"
| "import"
| "trash"
| "detail"
| "create"
| "edit"
| "label"
export function ContactsAppShell() {
const isMobile = useIsMobile()
const [currentView, setCurrentView] = useState<ContactsPageView>("contacts")
const [activeContactId, setActiveContactId] = useState<string | null>(null)
const [activeLabelId, setActiveLabelId] = useState<string | null>(null)
const [searchQuery, setSearchQuery] = useState("")
const [importOpen, setImportOpen] = useState(false)
const [bulkCreateOpen, setBulkCreateOpen] = useState(false)
const [sidebarOpen, setSidebarOpen] = useState(false)
useEffect(() => {
setSearchQuery("")
}, [currentView, activeLabelId])
useEffect(() => {
if (isMobile) {
setSidebarOpen(false)
} else {
setSidebarOpen(true)
}
}, [isMobile])
const closeSidebar = useCallback(() => setSidebarOpen(false), [])
const openSidebar = useCallback(() => setSidebarOpen(true), [])
const toggleSidebar = useCallback(() => setSidebarOpen((open) => !open), [])
function openContact(id: string) {
setActiveContactId(id)
setCurrentView("detail")
}
function openCreate() {
setActiveContactId(null)
setCurrentView("create")
}
function openEdit(id: string) {
setActiveContactId(id)
setCurrentView("edit")
}
function goBack() {
setActiveContactId(null)
setCurrentView("contacts")
}
function goToContactsList() {
setActiveContactId(null)
setActiveLabelId(null)
setSearchQuery("")
setCurrentView("contacts")
if (isMobile) closeSidebar()
}
function handleNavigate(view: ContactsPageView) {
if (view === "import") {
setImportOpen(true)
if (isMobile) closeSidebar()
return
}
setCurrentView(view)
if (isMobile) closeSidebar()
}
function handleSelectLabel(id: string) {
setActiveLabelId(id)
setCurrentView("label")
if (isMobile) closeSidebar()
}
function handleCreateContact() {
openCreate()
if (isMobile) closeSidebar()
}
return (
<div
data-contacts-app
data-contacts-panel
className={cn(
"ultimail-app relative flex h-dvh max-h-dvh overflow-hidden",
CONTACTS_SHELL_CLASS,
)}
>
{isMobile && sidebarOpen && (
<button
type="button"
aria-label="Fermer le menu"
className="absolute inset-0 z-40 bg-black/20"
onClick={closeSidebar}
/>
)}
<ContactsSidebar
open={sidebarOpen}
overlay={isMobile}
onToggle={toggleSidebar}
onClose={closeSidebar}
currentView={currentView}
activeLabelId={activeLabelId}
onNavigate={handleNavigate}
onHome={goToContactsList}
onCreateContact={handleCreateContact}
onBulkCreate={() => setBulkCreateOpen(true)}
onSelectLabel={handleSelectLabel}
/>
<div className="flex min-w-0 flex-1 flex-col">
<ContactsHeader
searchQuery={searchQuery}
onSearchChange={setSearchQuery}
sidebarOpen={sidebarOpen}
onOpenSidebar={openSidebar}
/>
<main className="min-h-0 flex-1 overflow-y-auto">
{(currentView === "contacts" ||
currentView === "frequent" ||
currentView === "label") && (
<ContactsTable
view={currentView}
searchQuery={searchQuery}
activeLabelId={activeLabelId}
onOpenContact={openContact}
/>
)}
{currentView === "other" && (
<OtherContactsView searchQuery={searchQuery} />
)}
{currentView === "ignored" && (
<IgnoredContactsView searchQuery={searchQuery} />
)}
{currentView === "blocked" && (
<BlockedContactsView searchQuery={searchQuery} />
)}
{currentView === "detail" && activeContactId && (
<ContactDetailPage
contactId={activeContactId}
onBack={goBack}
onEdit={openEdit}
/>
)}
{currentView === "create" && (
<ContactCreatePage
mode="create"
onBack={goBack}
onSaved={(id) => openContact(id)}
/>
)}
{currentView === "edit" && activeContactId && (
<ContactCreatePage
mode="edit"
contactId={activeContactId}
onBack={() => openContact(activeContactId)}
onSaved={(id) => openContact(id)}
/>
)}
{currentView === "merge" && <MergeDuplicatesView />}
{currentView === "trash" && <TrashView />}
</main>
</div>
<ImportDialog open={importOpen} onOpenChange={setImportOpen} />
<BulkCreateDialog open={bulkCreateOpen} onOpenChange={setBulkCreateOpen} onOpenImport={() => setImportOpen(true)} />
<AiChatPanel />
</div>
)
}