diff --git a/src/crm/components/CustomerDetailsCard.tsx b/src/crm/components/CustomerDetailsCard.tsx new file mode 100644 index 0000000..43b2b2a --- /dev/null +++ b/src/crm/components/CustomerDetailsCard.tsx @@ -0,0 +1,209 @@ +import * as React from "react"; +import Dialog from "@mui/material/Dialog"; +import DialogTitle from "@mui/material/DialogTitle"; +import DialogContent from "@mui/material/DialogContent"; +import DialogActions from "@mui/material/DialogActions"; +import Button from "@mui/material/Button"; +import Box from "@mui/material/Box"; +import Typography from "@mui/material/Typography"; +import Grid from "@mui/material/Grid"; +import Divider from "@mui/material/Divider"; +import IconButton from "@mui/material/IconButton"; +import EditIcon from "@mui/icons-material/Edit"; +import EmailIcon from "@mui/icons-material/Email"; +import PhoneIcon from "@mui/icons-material/Phone"; +import LocationOnIcon from "@mui/icons-material/LocationOn"; +import PersonIcon from "@mui/icons-material/Person"; +import CakeIcon from "@mui/icons-material/Cake"; +import AccessTimeIcon from "@mui/icons-material/AccessTime"; +import CustomerHeaderInfo from "./CustomerHeaderInfo"; +import type { Customer } from "../types/customer"; + +interface CustomerDetailsCardProps { + open: boolean; + customer: Customer | null; + onClose: () => void; + onEdit: (customer: Customer) => void; +} + +interface DetailItemProps { + icon: React.ReactNode; + label: string; + value: string | React.ReactNode; +} + +function DetailItem({ icon, label, value }: DetailItemProps) { + return ( + + {icon} + + + {label} + + {value} + + + ); +} + +export default function CustomerDetailsCard({ + open, + customer, + onClose, + onEdit, +}: CustomerDetailsCardProps) { + if (!customer) { + return null; + } + + const fullName = `${customer.name.title} ${customer.name.first} ${customer.name.last}`; + const address = `${customer.location.street.number} ${customer.location.street.name}, ${customer.location.city}, ${customer.location.state} ${customer.location.postcode}, ${customer.location.country}`; + const registeredDate = new Date( + customer.registered.date, + ).toLocaleDateString(); + const birthDate = new Date(customer.dob.date).toLocaleDateString(); + + const handleEdit = () => { + onEdit(customer); + }; + + return ( + + + + Customer Details + + + + + + + + + {/* Header with Avatar and Basic Info */} + + + + + + {/* Contact Information */} + + + Contact Information + + + } + label="Email Address" + value={customer.email} + /> + + {customer.phone && ( + } + label="Phone Number" + value={customer.phone} + /> + )} + + {customer.cell && ( + } + label="Cell Phone" + value={customer.cell} + /> + )} + + } + label="Username" + value={customer.login.username} + /> + + + {/* Personal Information */} + + + Personal Information + + + } + label="Date of Birth" + value={`${birthDate} (${customer.dob.age} years old)`} + /> + + } + label="Customer Since" + value={`${registeredDate} (${customer.registered.age} years)`} + /> + + {customer.location.timezone && ( + } + label="Timezone" + value={`${customer.location.timezone.offset} - ${customer.location.timezone.description}`} + /> + )} + + + {/* Address Information */} + + + Address Information + + + } + label="Full Address" + value={address} + /> + + {customer.location.coordinates && ( + } + label="Coordinates" + value={`${customer.location.coordinates.latitude}, ${customer.location.coordinates.longitude}`} + /> + )} + + + + + + + + + + + ); +} diff --git a/src/crm/components/CustomerDialog.tsx b/src/crm/components/CustomerDialog.tsx new file mode 100644 index 0000000..795767a --- /dev/null +++ b/src/crm/components/CustomerDialog.tsx @@ -0,0 +1,463 @@ +import * as React from "react"; +import { useState, useEffect } from "react"; +import Dialog from "@mui/material/Dialog"; +import DialogTitle from "@mui/material/DialogTitle"; +import DialogContent from "@mui/material/DialogContent"; +import DialogActions from "@mui/material/DialogActions"; +import Button from "@mui/material/Button"; +import TextField from "@mui/material/TextField"; +import Grid from "@mui/material/Grid"; +import FormControl from "@mui/material/FormControl"; +import InputLabel from "@mui/material/InputLabel"; +import Select from "@mui/material/Select"; +import MenuItem from "@mui/material/MenuItem"; +import Box from "@mui/material/Box"; +import Alert from "@mui/material/Alert"; +import CircularProgress from "@mui/material/CircularProgress"; +import { customersApi } from "../utils/customersApi"; +import type { + Customer, + CreateCustomerRequest, + UpdateCustomerRequest, +} from "../types/customer"; + +interface CustomerDialogProps { + open: boolean; + customer?: Customer | null; + onClose: () => void; + onSave: () => void; +} + +interface FormData { + firstName: string; + lastName: string; + title: string; + email: string; + username: string; + password: string; + gender: string; + phone: string; + cell: string; + streetNumber: string; + streetName: string; + city: string; + state: string; + country: string; + postcode: string; +} + +const initialFormData: FormData = { + firstName: "", + lastName: "", + title: "Mr", + email: "", + username: "", + password: "", + gender: "male", + phone: "", + cell: "", + streetNumber: "", + streetName: "", + city: "", + state: "", + country: "", + postcode: "", +}; + +export default function CustomerDialog({ + open, + customer, + onClose, + onSave, +}: CustomerDialogProps) { + const [formData, setFormData] = useState(initialFormData); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const isEditing = !!customer; + + useEffect(() => { + if (customer) { + setFormData({ + firstName: customer.name.first, + lastName: customer.name.last, + title: customer.name.title, + email: customer.email, + username: customer.login.username, + password: "", // Don't populate password for editing + gender: customer.gender, + phone: customer.phone || "", + cell: customer.cell || "", + streetNumber: customer.location.street.number.toString(), + streetName: customer.location.street.name, + city: customer.location.city, + state: customer.location.state, + country: customer.location.country, + postcode: customer.location.postcode, + }); + } else { + setFormData(initialFormData); + } + setError(null); + }, [customer, open]); + + const handleInputChange = + (field: keyof FormData) => + (event: React.ChangeEvent) => { + setFormData((prev) => ({ + ...prev, + [field]: event.target.value, + })); + }; + + const handleSelectChange = (field: keyof FormData) => (event: any) => { + setFormData((prev) => ({ + ...prev, + [field]: event.target.value, + })); + }; + + const validateForm = (): boolean => { + if (!formData.firstName.trim()) { + setError("First name is required"); + return false; + } + if (!formData.lastName.trim()) { + setError("Last name is required"); + return false; + } + if (!formData.email.trim()) { + setError("Email is required"); + return false; + } + if (!formData.username.trim()) { + setError("Username is required"); + return false; + } + if (!isEditing && !formData.password.trim()) { + setError("Password is required for new customers"); + return false; + } + return true; + }; + + const handleSave = async () => { + if (!validateForm()) { + return; + } + + setLoading(true); + setError(null); + + try { + if (isEditing && customer) { + const updateData: UpdateCustomerRequest = { + name: { + first: formData.firstName, + last: formData.lastName, + title: formData.title, + }, + location: { + street: { + number: parseInt(formData.streetNumber) || 0, + name: formData.streetName, + }, + city: formData.city, + state: formData.state, + country: formData.country, + postcode: formData.postcode, + }, + email: formData.email, + phone: formData.phone, + cell: formData.cell, + }; + + await customersApi.updateCustomer(customer.login.uuid, updateData); + } else { + const createData: CreateCustomerRequest = { + email: formData.email, + login: { + username: formData.username, + password: formData.password, + }, + name: { + first: formData.firstName, + last: formData.lastName, + title: formData.title, + }, + gender: formData.gender, + location: { + street: { + number: parseInt(formData.streetNumber) || 0, + name: formData.streetName, + }, + city: formData.city, + state: formData.state, + country: formData.country, + postcode: formData.postcode, + }, + phone: formData.phone, + cell: formData.cell, + }; + + await customersApi.createCustomer(createData); + } + + onSave(); + onClose(); + } catch (err) { + setError(err instanceof Error ? err.message : "An error occurred"); + } finally { + setLoading(false); + } + }; + + const handleClose = () => { + if (!loading) { + onClose(); + } + }; + + return ( + + + {isEditing ? "Edit Customer" : "Add New Customer"} + + + + + {error && ( + + {error} + + )} + + + {/* Personal Information */} + + + Personal Information + + + + + + Title + + + + + + + + + + + + + + + + + + + Gender + + + + + {/* Account Information */} + + + Account Information + + + + + + + + {!isEditing && ( + + + + )} + + {/* Contact Information */} + + + Contact Information + + + + + + + + + + + + {/* Address Information */} + + + Address Information + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/src/crm/components/CustomerHeaderInfo.tsx b/src/crm/components/CustomerHeaderInfo.tsx new file mode 100644 index 0000000..e8b6701 --- /dev/null +++ b/src/crm/components/CustomerHeaderInfo.tsx @@ -0,0 +1,54 @@ +import * as React from "react"; +import Avatar from "@mui/material/Avatar"; +import Box from "@mui/material/Box"; +import Typography from "@mui/material/Typography"; +import Chip from "@mui/material/Chip"; +import type { Customer } from "../types/customer"; + +interface CustomerHeaderInfoProps { + customer: Customer; +} + +export default function CustomerHeaderInfo({ + customer, +}: CustomerHeaderInfoProps) { + const fullName = `${customer.name.title} ${customer.name.first} ${customer.name.last}`; + const registeredDate = new Date( + customer.registered.date, + ).toLocaleDateString(); + + return ( + + + {fullName.charAt(0).toUpperCase()} + + + + {fullName} + + + + + + + + Customer since {registeredDate} ({customer.registered.age} years) + + + + ); +} diff --git a/src/crm/components/CustomersDataGrid.tsx b/src/crm/components/CustomersDataGrid.tsx new file mode 100644 index 0000000..c5890f6 --- /dev/null +++ b/src/crm/components/CustomersDataGrid.tsx @@ -0,0 +1,277 @@ +import * as React from "react"; +import { useState, useEffect, useCallback } from "react"; +import { + DataGridPro, + GridColDef, + GridRowParams, + GridCellParams, +} from "@mui/x-data-grid-pro"; +import Avatar from "@mui/material/Avatar"; +import Chip from "@mui/material/Chip"; +import IconButton from "@mui/material/IconButton"; +import Box from "@mui/material/Box"; +import Tooltip from "@mui/material/Tooltip"; +import EditIcon from "@mui/icons-material/Edit"; +import DeleteIcon from "@mui/icons-material/Delete"; +import VisibilityIcon from "@mui/icons-material/Visibility"; +import Typography from "@mui/material/Typography"; +import { customersApi } from "../utils/customersApi"; +import type { Customer } from "../types/customer"; + +interface CustomersDataGridProps { + onEditCustomer: (customer: Customer) => void; + onViewCustomer: (customer: Customer) => void; + onDeleteCustomer: (customer: Customer) => void; + searchQuery?: string; + refreshTrigger?: number; +} + +function renderAvatar(params: GridCellParams) { + const customer = params.row as Customer; + const fullName = `${customer.name.first} ${customer.name.last}`; + + return ( + + {fullName.charAt(0).toUpperCase()} + + ); +} + +function renderName(params: GridCellParams) { + const customer = params.row as Customer; + return `${customer.name.title} ${customer.name.first} ${customer.name.last}`; +} + +function renderLocation(params: GridCellParams) { + const customer = params.row as Customer; + return `${customer.location.city}, ${customer.location.state}, ${customer.location.country}`; +} + +function renderGender(params: GridCellParams) { + const customer = params.row as Customer; + const color = customer.gender === "male" ? "primary" : "secondary"; + return ( + + ); +} + +function renderAge(params: GridCellParams) { + const customer = params.row as Customer; + return customer.dob.age; +} + +export default function CustomersDataGrid({ + onEditCustomer, + onViewCustomer, + onDeleteCustomer, + searchQuery = "", + refreshTrigger = 0, +}: CustomersDataGridProps) { + const [customers, setCustomers] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [paginationModel, setPaginationModel] = useState({ + page: 0, + pageSize: 25, + }); + const [rowCount, setRowCount] = useState(0); + + const loadCustomers = useCallback(async () => { + setLoading(true); + setError(null); + + try { + const response = await customersApi.fetchCustomers({ + page: paginationModel.page + 1, // API is 1-indexed + perPage: paginationModel.pageSize, + search: searchQuery || undefined, + sortBy: "name.first", + }); + + setCustomers(response.data); + setRowCount(response.total); + } catch (err) { + setError(err instanceof Error ? err.message : "An error occurred"); + setCustomers([]); + setRowCount(0); + } finally { + setLoading(false); + } + }, [paginationModel.page, paginationModel.pageSize, searchQuery]); + + useEffect(() => { + loadCustomers(); + }, [loadCustomers, refreshTrigger]); + + const handleActions = (params: GridRowParams) => { + const customer = params.row as Customer; + + return ( + + + { + e.stopPropagation(); + onViewCustomer(customer); + }} + > + + + + + { + e.stopPropagation(); + onEditCustomer(customer); + }} + > + + + + + { + e.stopPropagation(); + onDeleteCustomer(customer); + }} + > + + + + + ); + }; + + const columns: GridColDef[] = [ + { + field: "avatar", + headerName: "", + width: 60, + sortable: false, + filterable: false, + disableColumnMenu: true, + renderCell: renderAvatar, + }, + { + field: "name", + headerName: "Name", + flex: 1, + minWidth: 200, + renderCell: renderName, + sortable: false, // API handles sorting + }, + { + field: "email", + headerName: "Email", + flex: 1, + minWidth: 200, + sortable: false, + }, + { + field: "phone", + headerName: "Phone", + flex: 0.8, + minWidth: 140, + sortable: false, + }, + { + field: "location", + headerName: "Location", + flex: 1, + minWidth: 200, + renderCell: renderLocation, + sortable: false, + }, + { + field: "gender", + headerName: "Gender", + width: 100, + renderCell: renderGender, + sortable: false, + }, + { + field: "age", + headerName: "Age", + width: 80, + renderCell: renderAge, + sortable: false, + }, + { + field: "actions", + headerName: "Actions", + width: 140, + sortable: false, + filterable: false, + disableColumnMenu: true, + renderCell: handleActions, + }, + ]; + + if (error) { + return ( + + Error loading customers: {error} + + ); + } + + return ( + row.login.uuid} + disableRowSelectionOnClick + density="comfortable" + sx={{ + "& .MuiDataGrid-row:hover": { + cursor: "default", + }, + }} + slotProps={{ + filterPanel: { + filterFormProps: { + logicOperatorInputProps: { + variant: "outlined", + size: "small", + }, + columnInputProps: { + variant: "outlined", + size: "small", + sx: { mt: "auto" }, + }, + operatorInputProps: { + variant: "outlined", + size: "small", + sx: { mt: "auto" }, + }, + valueInputProps: { + InputComponentProps: { + variant: "outlined", + size: "small", + }, + }, + }, + }, + }} + /> + ); +} diff --git a/src/crm/pages/Customers.tsx b/src/crm/pages/Customers.tsx index bd63a59..4948b43 100644 --- a/src/crm/pages/Customers.tsx +++ b/src/crm/pages/Customers.tsx @@ -1,17 +1,256 @@ import * as React from "react"; +import { useState, useCallback } from "react"; import Box from "@mui/material/Box"; import Typography from "@mui/material/Typography"; +import Button from "@mui/material/Button"; +import TextField from "@mui/material/TextField"; +import InputAdornment from "@mui/material/InputAdornment"; +import Dialog from "@mui/material/Dialog"; +import DialogTitle from "@mui/material/DialogTitle"; +import DialogContent from "@mui/material/DialogContent"; +import DialogActions from "@mui/material/DialogActions"; +import DialogContentText from "@mui/material/DialogContentText"; +import Snackbar from "@mui/material/Snackbar"; +import Alert from "@mui/material/Alert"; +import Paper from "@mui/material/Paper"; +import Stack from "@mui/material/Stack"; +import SearchIcon from "@mui/icons-material/Search"; +import AddIcon from "@mui/icons-material/Add"; +import RefreshIcon from "@mui/icons-material/Refresh"; +import CustomersDataGrid from "../components/CustomersDataGrid"; +import CustomerDialog from "../components/CustomerDialog"; +import CustomerDetailsCard from "../components/CustomerDetailsCard"; +import { customersApi } from "../utils/customersApi"; +import type { Customer } from "../types/customer"; export default function Customers() { + const [searchQuery, setSearchQuery] = useState(""); + const [customerDialogOpen, setCustomerDialogOpen] = useState(false); + const [customerDetailsOpen, setCustomerDetailsOpen] = useState(false); + const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); + const [selectedCustomer, setSelectedCustomer] = useState( + null, + ); + const [refreshTrigger, setRefreshTrigger] = useState(0); + const [snackbar, setSnackbar] = useState<{ + open: boolean; + message: string; + severity: "success" | "error" | "info"; + }>({ + open: false, + message: "", + severity: "success", + }); + + const showSnackbar = ( + message: string, + severity: "success" | "error" | "info" = "success", + ) => { + setSnackbar({ open: true, message, severity }); + }; + + const handleSnackbarClose = () => { + setSnackbar((prev) => ({ ...prev, open: false })); + }; + + const handleRefresh = () => { + setRefreshTrigger((prev) => prev + 1); + showSnackbar("Customer data refreshed", "info"); + }; + + const handleAddCustomer = () => { + setSelectedCustomer(null); + setCustomerDialogOpen(true); + }; + + const handleEditCustomer = useCallback((customer: Customer) => { + setSelectedCustomer(customer); + setCustomerDialogOpen(true); + }, []); + + const handleViewCustomer = useCallback((customer: Customer) => { + setSelectedCustomer(customer); + setCustomerDetailsOpen(true); + }, []); + + const handleDeleteCustomer = useCallback((customer: Customer) => { + setSelectedCustomer(customer); + setDeleteDialogOpen(true); + }, []); + + const handleCustomerDialogClose = () => { + setCustomerDialogOpen(false); + setSelectedCustomer(null); + }; + + const handleCustomerDetailsClo = () => { + setCustomerDetailsOpen(false); + setSelectedCustomer(null); + }; + + const handleCustomerSave = () => { + setRefreshTrigger((prev) => prev + 1); + showSnackbar( + selectedCustomer + ? "Customer updated successfully" + : "Customer created successfully", + ); + }; + + const handleConfirmDelete = async () => { + if (!selectedCustomer) return; + + try { + await customersApi.deleteCustomer(selectedCustomer.login.uuid); + setDeleteDialogOpen(false); + setSelectedCustomer(null); + setRefreshTrigger((prev) => prev + 1); + showSnackbar("Customer deleted successfully"); + } catch (error) { + showSnackbar( + error instanceof Error ? error.message : "Failed to delete customer", + "error", + ); + } + }; + + const handleCancelDelete = () => { + setDeleteDialogOpen(false); + setSelectedCustomer(null); + }; + + const handleEditFromDetails = (customer: Customer) => { + setCustomerDetailsOpen(false); + setSelectedCustomer(customer); + setCustomerDialogOpen(true); + }; + + const handleSearchChange = (event: React.ChangeEvent) => { + setSearchQuery(event.target.value); + }; + return ( - - Customers Page - - - This is the customers management page where you can view and manage your - customer data. - + {/* Header */} + + + Customer Management + + + Manage your customer database with comprehensive tools for viewing, + editing, and organizing customer information. + + + + {/* Toolbar */} + + + + + + ), + }} + /> + + + + + + + + {/* Data Grid */} + + + + + {/* Customer Dialog (Create/Edit) */} + + + {/* Customer Details Dialog */} + + + {/* Delete Confirmation Dialog */} + + + Confirm Customer Deletion + + + + Are you sure you want to delete the customer{" "} + + {selectedCustomer?.name.first} {selectedCustomer?.name.last} + + ? This action cannot be undone. + + + + + + + + + {/* Snackbar for notifications */} + + + {snackbar.message} + + ); } diff --git a/src/crm/types/customer.ts b/src/crm/types/customer.ts new file mode 100644 index 0000000..96253b5 --- /dev/null +++ b/src/crm/types/customer.ts @@ -0,0 +1,103 @@ +export interface CustomerName { + title: string; + first: string; + last: string; +} + +export interface CustomerLocation { + street: { + number: number; + name: string; + }; + city: string; + state: string; + country: string; + postcode: string; + coordinates?: { + latitude: number; + longitude: number; + }; + timezone?: { + offset: string; + description: string; + }; +} + +export interface CustomerDateOfBirth { + date: string; + age: number; +} + +export interface CustomerRegistered { + date: string; + age: number; +} + +export interface CustomerPicture { + large: string; + medium: string; + thumbnail: string; +} + +export interface CustomerLogin { + uuid: string; + username: string; + password?: string; +} + +export interface Customer { + login: CustomerLogin; + name: CustomerName; + gender: string; + location: CustomerLocation; + email: string; + dob: CustomerDateOfBirth; + registered: CustomerRegistered; + phone: string; + cell: string; + picture: CustomerPicture; + nat: string; +} + +export interface CustomersResponse { + page: number; + perPage: number; + total: number; + span: string; + effectivePage: number; + data: Customer[]; +} + +export interface CreateCustomerRequest { + email: string; + login: { + username: string; + password: string; + }; + name: { + first: string; + last: string; + title: string; + }; + gender: string; + location: { + street: { + number: number; + name: string; + }; + city: string; + state: string; + country: string; + postcode: string; + }; + phone?: string; + cell?: string; +} + +export interface UpdateCustomerRequest { + name?: Partial; + location?: Partial; + email?: string; + phone?: string; + cell?: string; +} diff --git a/src/crm/utils/customersApi.ts b/src/crm/utils/customersApi.ts new file mode 100644 index 0000000..c4d17ce --- /dev/null +++ b/src/crm/utils/customersApi.ts @@ -0,0 +1,131 @@ +import type { + Customer, + CustomersResponse, + CreateCustomerRequest, + UpdateCustomerRequest, +} from "../types/customer"; + +const API_BASE_URL = "https://user-api.builder-io.workers.dev/api"; + +export interface FetchCustomersParams { + page?: number; + perPage?: number; + search?: string; + sortBy?: string; + span?: string; +} + +export const customersApi = { + // Fetch paginated customers with optional search and sorting + async fetchCustomers( + params: FetchCustomersParams = {}, + ): Promise { + const searchParams = new URLSearchParams(); + + if (params.page) searchParams.set("page", params.page.toString()); + if (params.perPage) searchParams.set("perPage", params.perPage.toString()); + if (params.search) searchParams.set("search", params.search); + if (params.sortBy) searchParams.set("sortBy", params.sortBy); + if (params.span) searchParams.set("span", params.span); + + const url = `${API_BASE_URL}/users?${searchParams.toString()}`; + + try { + const response = await fetch(url); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error("Error fetching customers:", error); + throw error; + } + }, + + // Get a specific customer by ID, username, or email + async getCustomer(id: string): Promise { + try { + const response = await fetch(`${API_BASE_URL}/users/${id}`); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error("Error fetching customer:", error); + throw error; + } + }, + + // Create a new customer + async createCustomer( + customerData: CreateCustomerRequest, + ): Promise<{ success: boolean; uuid: string; message: string }> { + try { + const response = await fetch(`${API_BASE_URL}/users`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(customerData), + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error("Error creating customer:", error); + throw error; + } + }, + + // Update an existing customer + async updateCustomer( + id: string, + customerData: UpdateCustomerRequest, + ): Promise<{ success: boolean; message: string }> { + try { + const response = await fetch(`${API_BASE_URL}/users/${id}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(customerData), + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error("Error updating customer:", error); + throw error; + } + }, + + // Delete a customer + async deleteCustomer( + id: string, + ): Promise<{ success: boolean; message: string }> { + try { + const response = await fetch(`${API_BASE_URL}/users/${id}`, { + method: "DELETE", + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error("Error deleting customer:", error); + throw error; + } + }, +};