125 lines
3.7 KiB
TypeScript
125 lines
3.7 KiB
TypeScript
"use client"
|
|
|
|
import { useEffect, useState } from "react"
|
|
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 { TrashView } from "./trash-view"
|
|
import { BulkCreateDialog } from "./bulk-create-dialog"
|
|
import { ImportDialog } from "./import-dialog"
|
|
|
|
export type ContactsPageView =
|
|
| "contacts"
|
|
| "frequent"
|
|
| "other"
|
|
| "merge"
|
|
| "import"
|
|
| "trash"
|
|
| "detail"
|
|
| "create"
|
|
| "edit"
|
|
| "label"
|
|
|
|
export function ContactsAppShell() {
|
|
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)
|
|
|
|
useEffect(() => {
|
|
setSearchQuery("")
|
|
}, [currentView, activeLabelId])
|
|
|
|
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 handleNavigate(view: ContactsPageView) {
|
|
if (view === "import") {
|
|
setImportOpen(true)
|
|
return
|
|
}
|
|
setCurrentView(view)
|
|
}
|
|
|
|
return (
|
|
<div className="flex h-dvh max-h-dvh overflow-hidden bg-white">
|
|
<ContactsSidebar
|
|
currentView={currentView}
|
|
activeLabelId={activeLabelId}
|
|
onNavigate={handleNavigate}
|
|
onCreateContact={openCreate}
|
|
onBulkCreate={() => setBulkCreateOpen(true)}
|
|
onSelectLabel={(id) => { setActiveLabelId(id); setCurrentView("label") }}
|
|
/>
|
|
<div className="flex min-w-0 flex-1 flex-col">
|
|
<ContactsHeader
|
|
searchQuery={searchQuery}
|
|
onSearchChange={setSearchQuery}
|
|
/>
|
|
<main className="min-h-0 flex-1 overflow-y-auto">
|
|
{(currentView === "contacts" ||
|
|
currentView === "frequent" ||
|
|
currentView === "other" ||
|
|
currentView === "label") && (
|
|
<ContactsTable
|
|
view={currentView}
|
|
searchQuery={searchQuery}
|
|
activeLabelId={activeLabelId}
|
|
onOpenContact={openContact}
|
|
/>
|
|
)}
|
|
{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)} />
|
|
</div>
|
|
)
|
|
}
|