diff --git a/src/components/CreateClientModal.tsx b/src/components/CreateClientModal.tsx index 3fbc1a4..4d6938e 100644 --- a/src/components/CreateClientModal.tsx +++ b/src/components/CreateClientModal.tsx @@ -1,5 +1,6 @@ -import { useState } from "react"; -import { createClient } from "../api/clients"; +import { useState } from "react"; +import { toast } from "sonner"; +import { createClient } from "../api/clients"; import { useTranslation } from "../hooks/useTranslation"; import { Button } from "./ui/button"; import { Input } from "./ui/input"; @@ -22,18 +23,20 @@ export default function CreateClientModal({ isOpen, onClose, onSuccess, workspac const handleSubmit = async () => { if (!name.trim()) return; setIsLoading(true); - try { - await createClient(workspaceId, { name, notes }); - onSuccess(); - setName(""); - setNotes(""); - onClose(); - } catch (error) { - console.error(t.clients.errors.createFailed, error); - } finally { - setIsLoading(false); - } - }; + try { + await createClient(workspaceId, { name, notes }); + toast.success(t.clients.createSuccess); + onSuccess(); + setName(""); + setNotes(""); + onClose(); + } catch (error) { + console.error(t.clients.errors.createFailed, error); + toast.error(t.clients.errors.createFailed); + } finally { + setIsLoading(false); + } + }; const footer = ( <> @@ -72,4 +75,4 @@ export default function CreateClientModal({ isOpen, onClose, onSuccess, workspac ); -} \ No newline at end of file +} diff --git a/src/components/DeleteClientModal.tsx b/src/components/DeleteClientModal.tsx index e84caf1..594fdff 100644 --- a/src/components/DeleteClientModal.tsx +++ b/src/components/DeleteClientModal.tsx @@ -1,5 +1,6 @@ -import { useState } from "react"; -import { type Client } from "../types/client"; +import { useState } from "react"; +import { toast } from "sonner"; +import { type Client } from "../types/client"; import { deleteClient } from "../api/clients"; import { useTranslation } from "../hooks/useTranslation"; import { Button } from "./ui/button"; @@ -19,16 +20,18 @@ export default function DeleteClientModal({ isOpen, onClose, onSuccess, client } const handleDelete = async () => { if (!client) return; setIsLoading(true); - try { - await deleteClient(client.id); - onSuccess(); - onClose(); - } catch (error) { - console.error(t.clients.errors.deleteFailed, error); - } finally { - setIsLoading(false); - } - }; + try { + await deleteClient(client.id); + toast.success(t.clients.deleteSuccess); + onSuccess(); + onClose(); + } catch (error) { + console.error(t.clients.errors.deleteFailed, error); + toast.error(t.clients.errors.deleteFailed); + } finally { + setIsLoading(false); + } + }; const footer = ( <> diff --git a/src/components/EditClientModal.tsx b/src/components/EditClientModal.tsx index 218969e..287ad3b 100644 --- a/src/components/EditClientModal.tsx +++ b/src/components/EditClientModal.tsx @@ -1,5 +1,6 @@ -import { useState, useEffect } from "react"; -import { type Client } from "../types/client"; +import { useState, useEffect } from "react"; +import { toast } from "sonner"; +import { type Client } from "../types/client"; import { updateClient } from "../api/clients"; import { useTranslation } from "../hooks/useTranslation"; import { Button } from "./ui/button"; @@ -30,16 +31,18 @@ export default function EditClientModal({ isOpen, onClose, onSuccess, client }: const handleSubmit = async () => { if (!client || !name.trim()) return; setIsLoading(true); - try { - await updateClient(client.id, { name, notes }); - onSuccess(); - onClose(); - } catch (error) { - console.error(t.clients.errors.updateFailed, error); - } finally { - setIsLoading(false); - } - }; + try { + await updateClient(client.id, { name, notes }); + toast.success(t.clients.updateSuccess); + onSuccess(); + onClose(); + } catch (error) { + console.error(t.clients.errors.updateFailed, error); + toast.error(t.clients.errors.updateFailed); + } finally { + setIsLoading(false); + } + }; const footer = ( <> @@ -78,4 +81,4 @@ export default function EditClientModal({ isOpen, onClose, onSuccess, client }: ); -} \ No newline at end of file +} diff --git a/src/locales/en.ts b/src/locales/en.ts index 1917c42..985abbf 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -244,10 +244,13 @@ export const en = { editClient: "Edit Client", deleteConfirmTitle: "Delete Client", deleteConfirmMessage: (name: string) => `Are you sure you want to delete ${name}?`, - delete: "Delete", - saveChanges: "Save Changes", - errors: { - createFailed: "Failed to create client", + delete: "Delete", + saveChanges: "Save Changes", + createSuccess: "Client created successfully.", + updateSuccess: "Client updated successfully.", + deleteSuccess: "Client deleted successfully.", + errors: { + createFailed: "Failed to create client", fetchFailed: "Failed to fetch clients", updateFailed: "Failed to update client", deleteFailed: "Failed to delete client", diff --git a/src/locales/fa.ts b/src/locales/fa.ts index ecb4ae1..d982c8b 100644 --- a/src/locales/fa.ts +++ b/src/locales/fa.ts @@ -241,10 +241,13 @@ export const fa = { editClient: "ویرایش مشتری", deleteConfirmTitle: "حذف مشتری", deleteConfirmMessage: (name: string) => `آیا از حذف ${name} اطمینان دارید؟`, - delete: "حذف", - saveChanges: "ذخیره تغییرات", - errors: { - createFailed: "خطا در ایجاد مشتری", + delete: "حذف", + saveChanges: "ذخیره تغییرات", + createSuccess: "مشتری با موفقیت ایجاد شد.", + updateSuccess: "مشتری با موفقیت بهروزرسانی شد.", + deleteSuccess: "مشتری با موفقیت حذف شد.", + errors: { + createFailed: "خطا در ایجاد مشتری", fetchFailed: "خطا در دریافت لیست مشتریها", updateFailed: "خطا در ویرایش مشتری", deleteFailed: "خطا در حذف مشتری", diff --git a/src/pages/Clients.tsx b/src/pages/Clients.tsx index 33d2ac2..b335764 100644 --- a/src/pages/Clients.tsx +++ b/src/pages/Clients.tsx @@ -1,5 +1,6 @@ -import { useEffect, useState } from "react" -import { Plus, Building2, Loader2, Pencil, Trash2 } from "lucide-react" +import { useEffect, useState } from "react" +import { Plus, Building2, Loader2, Pencil, Trash2 } from "lucide-react" +import { toast } from "sonner" import { useWorkspace } from "../context/WorkspaceContext" import { useAppContext } from "../context/AppContext" import { useTranslation } from "../hooks/useTranslation" @@ -13,11 +14,11 @@ import { type Client } from "../types/client" import { getClients } from "../api/clients" import CreateClientModal from "../components/CreateClientModal" import EditClientModal from "../components/EditClientModal" -import DeleteClientModal from "../components/DeleteClientModal" -import FilterBar from "../components/FilterBar" -import { Button } from "../components/ui/button" -import { Card } from "../components/ui/card" -import { Pagination } from "../components/Pagination" +import DeleteClientModal from "../components/DeleteClientModal" +import FilterBar from "../components/FilterBar" +import { Button } from "../components/ui/button" +import { Card, CardContent, CardTitle } from "../components/ui/card" +import { Pagination } from "../components/Pagination" export default function Clients() { const { activeWorkspace } = useWorkspace() @@ -82,11 +83,12 @@ export default function Clients() { setClients(items) setTotalItems(count) - } catch (error) { - console.error(t.clients.errors.fetchFailed, error) - setClients([]) - } finally { - setIsLoading(false) + } catch (error) { + console.error(t.clients.errors.fetchFailed, error) + toast.error(t.clients.errors.fetchFailed) + setClients([]) + } finally { + setIsLoading(false) } } @@ -107,122 +109,146 @@ export default function Clients() { fetchClientsList() }, [activeWorkspace?.id, debouncedSearch, ordering, currentPage, limit]) - if (!activeWorkspace) { - return ( -
- {t.clients.description(activeWorkspace.name)} -
-- {searchQuery ? t.clients.noClientsSearch : t.clients.noClientsAdd} -
-+ {t.clients.description(activeWorkspace.name)} +
++ {searchQuery ? t.clients.noClientsSearch : t.clients.noClientsAdd} +
+- {client.notes} -
- )} -+ {client.notes || t.workspace?.noDescription || "No description"} +
+