refactor(lists): align client and project page controls
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
import { useEffect, useState } from "react"
|
||||
import { Plus, Building2, Loader2, Pencil, Trash2 } from "lucide-react"
|
||||
import { useWorkspace } from "../context/WorkspaceContext"
|
||||
import { useTranslation } from "../hooks/useTranslation"
|
||||
import {
|
||||
CLIENTS_CREATE,
|
||||
CLIENTS_DELETE,
|
||||
CLIENTS_EDIT,
|
||||
canWorkspace,
|
||||
} from "../lib/permissions"
|
||||
import { useTranslation } from "../hooks/useTranslation"
|
||||
import {
|
||||
CLIENTS_CREATE,
|
||||
CLIENTS_DELETE,
|
||||
CLIENTS_EDIT,
|
||||
canWorkspace,
|
||||
} from "../lib/permissions"
|
||||
import { type Client } from "../types/client"
|
||||
import { getClients } from "../api/clients"
|
||||
import CreateClientModal from "../components/CreateClientModal"
|
||||
@@ -38,12 +38,12 @@ export default function Clients() {
|
||||
const [editClient, setEditClient] = useState<Client | null>(null)
|
||||
const [deleteClient, setDeleteClient] = useState<Client | null>(null)
|
||||
|
||||
const { t, lang } = useTranslation()
|
||||
const isFa = lang === "fa"
|
||||
const workspaceRole = activeWorkspace?.my_role
|
||||
const canCreateClient = canWorkspace(workspaceRole, CLIENTS_CREATE)
|
||||
const canEditClient = canWorkspace(workspaceRole, CLIENTS_EDIT)
|
||||
const canDeleteClient = canWorkspace(workspaceRole, CLIENTS_DELETE)
|
||||
const { t, lang } = useTranslation()
|
||||
const isFa = lang === "fa"
|
||||
const workspaceRole = activeWorkspace?.my_role
|
||||
const canCreateClient = canWorkspace(workspaceRole, CLIENTS_CREATE)
|
||||
const canEditClient = canWorkspace(workspaceRole, CLIENTS_EDIT)
|
||||
const canDeleteClient = canWorkspace(workspaceRole, CLIENTS_DELETE)
|
||||
|
||||
const orderingOptions = [
|
||||
{ value: "-created_at", label: t.ordering?.createdAtDesc || "Newest First" },
|
||||
@@ -116,24 +116,24 @@ export default function Clients() {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col p-6 min-h-[calc(100vh-73px)] bg-slate-50 dark:bg-slate-900">
|
||||
<div className="flex justify-between items-center mb-8 gap-4">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-slate-900 dark:text-white">{t.clients.title}</h1>
|
||||
<p className="text-slate-500 dark:text-slate-400 text-sm mt-1">
|
||||
{t.clients.description(activeWorkspace.name)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{canCreateClient && (
|
||||
<Button
|
||||
onClick={() => setIsCreateModalOpen(true)}
|
||||
size="icon"
|
||||
className="shadow-sm shrink-0"
|
||||
title={t.clients.addClient}
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
</Button>
|
||||
)}
|
||||
<div className="flex justify-between items-center mb-8 gap-4">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-slate-900 dark:text-white">{t.clients.title}</h1>
|
||||
<p className="text-slate-500 dark:text-slate-400 text-sm mt-1">
|
||||
{t.clients.description(activeWorkspace.name)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{canCreateClient && (
|
||||
<Button
|
||||
onClick={() => setIsCreateModalOpen(true)}
|
||||
size="icon"
|
||||
className="shadow-sm shrink-0"
|
||||
title={t.clients.addClient}
|
||||
>
|
||||
<Plus className="w-5 h-5" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<FilterBar
|
||||
@@ -170,35 +170,32 @@ export default function Clients() {
|
||||
{client.notes}
|
||||
</p>
|
||||
)}
|
||||
<div className="text-[11px] text-slate-400 mt-3 font-medium">
|
||||
{t.clients.addedOn}: {formatDate(client.created_at)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{(canEditClient || canDeleteClient) && (
|
||||
<div className="flex items-center gap-1 shrink-0">
|
||||
{canEditClient && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => setEditClient(client)}
|
||||
className="h-8 w-8 text-slate-400 hover:text-blue-600 hover:bg-blue-50 dark:hover:text-blue-400 dark:hover:bg-blue-900/20"
|
||||
>
|
||||
<Pencil className="w-4 h-4" />
|
||||
</Button>
|
||||
)}
|
||||
{canDeleteClient && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => setDeleteClient(client)}
|
||||
className="h-8 w-8 text-slate-400 hover:text-red-600 hover:bg-red-50 dark:hover:text-red-400 dark:hover:bg-red-900/20"
|
||||
>
|
||||
<Trash2 className="w-4 h-4" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{(canEditClient || canDeleteClient) && (
|
||||
<div className="flex items-center gap-1 shrink-0">
|
||||
{canEditClient && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => setEditClient(client)}
|
||||
className="h-8 w-8 text-slate-400 hover:text-blue-600 hover:bg-blue-50 dark:hover:text-blue-400 dark:hover:bg-blue-900/20"
|
||||
>
|
||||
<Pencil className="w-4 h-4" />
|
||||
</Button>
|
||||
)}
|
||||
{canDeleteClient && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => setDeleteClient(client)}
|
||||
className="h-8 w-8 text-slate-400 hover:text-red-600 hover:bg-red-50 dark:hover:text-red-400 dark:hover:bg-red-900/20"
|
||||
>
|
||||
<Trash2 className="w-4 h-4" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
@@ -216,32 +213,32 @@ export default function Clients() {
|
||||
/>
|
||||
)}
|
||||
|
||||
{canCreateClient && (
|
||||
<CreateClientModal
|
||||
isOpen={isCreateModalOpen}
|
||||
onClose={() => setIsCreateModalOpen(false)}
|
||||
onSuccess={fetchClientsList}
|
||||
workspaceId={activeWorkspace.id}
|
||||
/>
|
||||
)}
|
||||
|
||||
{canEditClient && (
|
||||
<EditClientModal
|
||||
isOpen={!!editClient}
|
||||
onClose={() => setEditClient(null)}
|
||||
onSuccess={fetchClientsList}
|
||||
client={editClient}
|
||||
/>
|
||||
)}
|
||||
|
||||
{canDeleteClient && (
|
||||
<DeleteClientModal
|
||||
isOpen={!!deleteClient}
|
||||
onClose={() => setDeleteClient(null)}
|
||||
onSuccess={fetchClientsList}
|
||||
client={deleteClient}
|
||||
/>
|
||||
)}
|
||||
{canCreateClient && (
|
||||
<CreateClientModal
|
||||
isOpen={isCreateModalOpen}
|
||||
onClose={() => setIsCreateModalOpen(false)}
|
||||
onSuccess={fetchClientsList}
|
||||
workspaceId={activeWorkspace.id}
|
||||
/>
|
||||
)}
|
||||
|
||||
{canEditClient && (
|
||||
<EditClientModal
|
||||
isOpen={!!editClient}
|
||||
onClose={() => setEditClient(null)}
|
||||
onSuccess={fetchClientsList}
|
||||
client={editClient}
|
||||
/>
|
||||
)}
|
||||
|
||||
{canDeleteClient && (
|
||||
<DeleteClientModal
|
||||
isOpen={!!deleteClient}
|
||||
onClose={() => setDeleteClient(null)}
|
||||
onSuccess={fetchClientsList}
|
||||
client={deleteClient}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user