diff --git a/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-details.tsx b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-details.tsx new file mode 100644 index 00000000..263e2842 --- /dev/null +++ b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-details.tsx @@ -0,0 +1,47 @@ +"use client" + +import Link from "next/link" +import { useParams } from "next/navigation" +import { ChevronLeft } from "lucide-react" + +import type { LocaleType } from "@/types" +import type { CustomerType } from "../../types" + +import { ensureLocalizedPathname } from "@/lib/i18n" + +import { Button } from "@/components/ui/button" +import { CustomerHeaderCard } from "./customer-header-card" +import { CustomerInfoCard } from "./customer-info-card" +import { CustomerOrdersCard } from "./customer-orders-card" +import { CustomerStatsCard } from "./customer-stats-card" + +interface CustomerDetailsProps { + customer: CustomerType +} + +export function CustomerDetails({ customer }: CustomerDetailsProps) { + const params = useParams() + const locale = params.lang as LocaleType + + return ( +
+ + +
+
+ + +
+
+ + +
+
+
+ ) +} diff --git a/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-header-card.tsx b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-header-card.tsx new file mode 100644 index 00000000..69c2a9c6 --- /dev/null +++ b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-header-card.tsx @@ -0,0 +1,43 @@ +import type { CustomerType } from "../../types" + +import { formatDate, getInitials } from "@/lib/utils" + +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" +import { Badge } from "@/components/ui/badge" +import { Card, CardContent } from "@/components/ui/card" + +interface CustomerHeaderCardProps { + customer: CustomerType +} + +export function CustomerHeaderCard({ customer }: CustomerHeaderCardProps) { + const statusVariant = + customer.status === "VIP" + ? "secondary" + : customer.status === "Inactive" + ? "outline" + : "default" + + return ( + + + + + + {getInitials(customer.name)} + + +
+

{customer.name}

+

{customer.email}

+
+
+ {customer.status} + + Joined {formatDate(customer.joinDate)} + +
+
+
+ ) +} diff --git a/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-info-card.tsx b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-info-card.tsx new file mode 100644 index 00000000..6a2fdf4c --- /dev/null +++ b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-info-card.tsx @@ -0,0 +1,41 @@ +import { Building2, Globe, MapPin, Phone } from "lucide-react" + +import type { CustomerType } from "../../types" + +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" + +interface CustomerInfoCardProps { + customer: CustomerType +} + +export function CustomerInfoCard({ customer }: CustomerInfoCardProps) { + const items = [ + { icon: Phone, label: "Phone", value: customer.phone }, + { + icon: MapPin, + label: "Address", + value: `${customer.address}, ${customer.city}, ${customer.state} ${customer.zipCode}`, + }, + { icon: Globe, label: "Country", value: customer.country }, + { icon: Building2, label: "Organization", value: customer.organization }, + ] + + return ( + + + Information + + + {items.map((item) => ( +
+ +
+

{item.label}

+

{item.value}

+
+
+ ))} +
+
+ ) +} diff --git a/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-not-found.tsx b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-not-found.tsx new file mode 100644 index 00000000..36a544ca --- /dev/null +++ b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-not-found.tsx @@ -0,0 +1,31 @@ +"use client" + +import Link from "next/link" +import { useParams } from "next/navigation" +import { UserX } from "lucide-react" + +import type { LocaleType } from "@/types" + +import { ensureLocalizedPathname } from "@/lib/i18n" + +import { Button } from "@/components/ui/button" + +export function CustomerNotFound() { + const params = useParams() + const locale = params.lang as LocaleType + + return ( +
+ +

Customer Not Found

+

+ The customer you are looking for does not exist or has been removed. +

+ +
+ ) +} diff --git a/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-orders-card.tsx b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-orders-card.tsx new file mode 100644 index 00000000..e8b3f348 --- /dev/null +++ b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-orders-card.tsx @@ -0,0 +1,83 @@ +import type { CustomerType } from "../../types" + +import { formatCurrency, formatDate } from "@/lib/utils" + +import { Badge } from "@/components/ui/badge" +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" +import { ScrollArea } from "@/components/ui/scroll-area" +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table" + +interface CustomerOrdersCardProps { + customer: CustomerType +} + +export function CustomerOrdersCard({ customer }: CustomerOrdersCardProps) { + const { recentOrders } = customer + + const paymentVariant = (status: string) => + status === "Paid" + ? "default" + : status === "Pending" + ? "secondary" + : status === "Failed" + ? "destructive" + : "outline" + + return ( + + + Recent Orders + + + + + + + Order ID + Date + Amount + Status + + + + {recentOrders.length > 0 ? ( + recentOrders.map((order) => ( + + + #{order.orderId} + + {formatDate(order.date)} + + {formatCurrency(order.amount)} + + + + {order.status} + + + + )) + ) : ( + + + No recent orders. + + + )} + +
+
+
+
+ ) +} diff --git a/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-stats-card.tsx b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-stats-card.tsx new file mode 100644 index 00000000..f78768e1 --- /dev/null +++ b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/_components/customer-stats-card.tsx @@ -0,0 +1,54 @@ +import { DollarSign, ShoppingCart, TrendingUp } from "lucide-react" + +import type { CustomerType } from "../../types" + +import { formatCurrency } from "@/lib/utils" + +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" + +interface CustomerStatsCardProps { + customer: CustomerType +} + +export function CustomerStatsCard({ customer }: CustomerStatsCardProps) { + const avgOrderValue = + customer.totalOrders > 0 + ? Math.round(customer.totalSpent / customer.totalOrders) + : 0 + + const stats = [ + { + icon: ShoppingCart, + label: "Total Orders", + value: customer.totalOrders.toString(), + }, + { + icon: DollarSign, + label: "Total Spent", + value: formatCurrency(customer.totalSpent), + }, + { + icon: TrendingUp, + label: "Avg. Order Value", + value: formatCurrency(avgOrderValue), + }, + ] + + return ( +
+ {stats.map((stat) => ( + + + + {stat.label} + + + + +

{stat.value}

+
+
+ ))} +
+ ) +} diff --git a/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/page.tsx b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/page.tsx new file mode 100644 index 00000000..2a1abe88 --- /dev/null +++ b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/[id]/page.tsx @@ -0,0 +1,33 @@ +import type { LocaleType } from "@/types" +import type { Metadata } from "next" + +import { customersData } from "../list/_data/customers" + +import { CustomerDetails } from "./_components/customer-details" +import { CustomerNotFound } from "./_components/customer-not-found" + +export const metadata: Metadata = { + title: "Customer Details", +} + +export default async function CustomerDetailsPage(props: { + params: Promise<{ lang: LocaleType; id: string }> +}) { + const params = await props.params + + const customer = customersData.find((c) => c.id === params.id) + + if (!customer) { + return ( +
+ +
+ ) + } + + return ( +
+ +
+ ) +} diff --git a/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/_components/customers-table-columns.tsx b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/_components/customers-table-columns.tsx new file mode 100644 index 00000000..f79849cf --- /dev/null +++ b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/_components/customers-table-columns.tsx @@ -0,0 +1,143 @@ +"use client" + +import Image from "next/image" +import Link from "next/link" + +import type { LocaleType } from "@/types" +import type { ColumnDef } from "@tanstack/react-table" +import type { CustomerType } from "../../types" + +import { ensureLocalizedPathname } from "@/lib/i18n" +import { formatCurrency, formatDate } from "@/lib/utils" + +import { Badge } from "@/components/ui/badge" +import { Checkbox } from "@/components/ui/checkbox" +import { DataTableColumnHeader } from "@/components/ui/data-table/data-table-column-header" +import { CustomersTableRowActions } from "./customers-table-row-actions" + +export function getCustomersTableColumns( + onDelete: (id: string) => void, + locale: LocaleType +): ColumnDef[] { + return [ + { + id: "select", + header: ({ table }) => ( + table.toggleAllPageRowsSelected(!!value)} + className="ms-4" + aria-label="Select all" + /> + ), + cell: ({ row }) => ( + row.toggleSelected(!!value)} + className="ms-4" + aria-label="Select row" + /> + ), + enableSorting: false, + enableHiding: false, + }, + { + accessorKey: "name", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const customer = row.original + + return ( + + {customer.name} +
+ + {customer.name} + + + {customer.email} + +
+ + ) + }, + }, + { + accessorKey: "phone", + header: ({ column }) => ( + + ), + cell: ({ row }) => ( + {row.getValue("phone")} + ), + }, + { + accessorKey: "status", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const status = row.getValue("status") as string + const variant = + status === "VIP" + ? "secondary" + : status === "Inactive" + ? "outline" + : "default" + + return {status} + }, + filterFn: "equals", + }, + { + accessorKey: "totalOrders", + header: ({ column }) => ( + + ), + }, + { + accessorKey: "totalSpent", + header: ({ column }) => ( + + ), + cell: ({ row }) => ( + {formatCurrency(row.getValue("totalSpent"))} + ), + }, + { + accessorKey: "joinDate", + header: ({ column }) => ( + + ), + cell: ({ row }) => formatDate(row.getValue("joinDate")), + }, + { + id: "actions", + header: () => Actions, + cell: ({ row }) => ( + + ), + }, + ] +} diff --git a/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/_components/customers-table-row-actions.tsx b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/_components/customers-table-row-actions.tsx new file mode 100644 index 00000000..73cfd238 --- /dev/null +++ b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/_components/customers-table-row-actions.tsx @@ -0,0 +1,62 @@ +"use client" + +import Link from "next/link" +import { Eye, MoreHorizontal, Trash2 } from "lucide-react" + +import type { LocaleType } from "@/types" +import type { CustomerType } from "../../types" + +import { ensureLocalizedPathname } from "@/lib/i18n" + +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" + +interface CustomersTableRowActionsProps { + customer: CustomerType + locale: LocaleType + onDelete: (id: string) => void +} + +export function CustomersTableRowActions({ + customer, + locale, + onDelete, +}: CustomersTableRowActionsProps) { + return ( + + + + + + + + + View Details + + + + onDelete(customer.id)} + > + + Delete + + + + ) +} diff --git a/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/_components/customers-table-toolbar.tsx b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/_components/customers-table-toolbar.tsx new file mode 100644 index 00000000..09a7c39e --- /dev/null +++ b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/_components/customers-table-toolbar.tsx @@ -0,0 +1,64 @@ +"use client" + +import { Search } from "lucide-react" + +import type { Table } from "@tanstack/react-table" +import type { CustomerType } from "../../types" + +import { customerStatusesData } from "../_data/customers" + +import { DataTableViewOptions } from "@/components/ui/data-table/data-table-column-toggle" +import { Input } from "@/components/ui/input" +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" + +interface CustomersTableToolbarProps { + table: Table +} + +export function CustomersTableToolbar({ table }: CustomersTableToolbarProps) { + return ( +
+
+ + + table.getColumn("name")?.setFilterValue(event.target.value) + } + className="h-9 w-40 ps-8 md:w-60" + aria-label="Search customers by name" + /> +
+ + +
+ ) +} diff --git a/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/_components/customers-table.tsx b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/_components/customers-table.tsx new file mode 100644 index 00000000..632d12ff --- /dev/null +++ b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/_components/customers-table.tsx @@ -0,0 +1,148 @@ +"use client" + +import { useCallback, useMemo, useState } from "react" +import { useParams } from "next/navigation" +import { + flexRender, + getCoreRowModel, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + useReactTable, +} from "@tanstack/react-table" + +import type { LocaleType } from "@/types" +import type { + ColumnFiltersState, + SortingState, + VisibilityState, +} from "@tanstack/react-table" +import type { CustomerType } from "../../types" + +import { + Card, + CardContent, + CardFooter, + CardHeader, + CardTitle, +} from "@/components/ui/card" +import { DataTablePagination } from "@/components/ui/data-table/data-table-pagination" +import { ScrollArea } from "@/components/ui/scroll-area" +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table" +import { getCustomersTableColumns } from "./customers-table-columns" +import { CustomersTableToolbar } from "./customers-table-toolbar" + +interface CustomersTableProps { + data: CustomerType[] +} + +export function CustomersTable({ data: initialData }: CustomersTableProps) { + const params = useParams() + const locale = params.lang as LocaleType + + const [customers, setCustomers] = useState(initialData) + const [sorting, setSorting] = useState([]) + const [columnFilters, setColumnFilters] = useState([]) + const [columnVisibility, setColumnVisibility] = useState({}) + const [rowSelection, setRowSelection] = useState({}) + + const handleDelete = useCallback((id: string) => { + setCustomers((prev) => prev.filter((c) => c.id !== id)) + }, []) + + const columns = useMemo( + () => getCustomersTableColumns(handleDelete, locale), + [handleDelete, locale] + ) + + const table = useReactTable({ + data: customers, + columns, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + onSortingChange: setSorting, + getSortedRowModel: getSortedRowModel(), + onColumnFiltersChange: setColumnFilters, + getFilteredRowModel: getFilteredRowModel(), + onColumnVisibilityChange: setColumnVisibility, + onRowSelectionChange: setRowSelection, + state: { + sorting, + columnFilters, + columnVisibility, + rowSelection, + }, + }) + + return ( + + + Customers + + + + + + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext() + )} + + ))} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext() + )} + + ))} + + )) + ) : ( + + + No results. + + + )} + +
+
+
+ + + +
+ ) +} diff --git a/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/_data/customers.ts b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/_data/customers.ts new file mode 100644 index 00000000..285c6e35 --- /dev/null +++ b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/_data/customers.ts @@ -0,0 +1,579 @@ +import type { CustomerType } from "../../types" + +export const customerStatusesData = [ + { label: "All", value: "all" }, + { label: "Active", value: "Active" }, + { label: "VIP", value: "VIP" }, + { label: "Inactive", value: "Inactive" }, +] + +const avatars = [ + "/images/avatars/male-01.svg", + "/images/avatars/female-01.svg", + "/images/avatars/male-02.svg", + "/images/avatars/female-02.svg", + "/images/avatars/female-03.svg", +] + +export const customersData: CustomerType[] = [ + { + id: "CUS-1001", + name: "John Doe", + email: "john.doe@email.com", + avatar: avatars[0], + phone: "+1 (555) 123-4567", + address: "123 Main St", + city: "New York", + state: "NY", + country: "United States", + zipCode: "10001", + organization: "Acme Corp", + status: "VIP", + totalOrders: 47, + totalSpent: 42500, + joinDate: "2023-01-15T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1001", + date: "2024-11-01T10:00:00Z", + amount: 270, + status: "Paid", + }, + { + orderId: "ORD-1016", + date: "2024-11-27T09:00:00Z", + amount: 2862, + status: "Paid", + }, + { + orderId: "ORD-1020", + date: "2024-12-05T14:00:00Z", + amount: 486, + status: "Pending", + }, + ], + }, + { + id: "CUS-1002", + name: "Emily Smith", + email: "emily.smith@email.com", + avatar: avatars[1], + phone: "+1 (555) 234-5678", + address: "456 Oak Ave", + city: "Los Angeles", + state: "CA", + country: "United States", + zipCode: "90001", + organization: "TechStart Inc", + status: "Active", + totalOrders: 23, + totalSpent: 18900, + joinDate: "2023-03-22T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1002", + date: "2024-11-03T14:30:00Z", + amount: 8640, + status: "Paid", + }, + { + orderId: "ORD-1008", + date: "2024-11-14T15:00:00Z", + amount: 1188, + status: "Paid", + }, + ], + }, + { + id: "CUS-1003", + name: "Michael Brown", + email: "m.brown@email.com", + avatar: avatars[2], + phone: "+1 (555) 345-6789", + address: "789 Pine Rd", + city: "Chicago", + state: "IL", + country: "United States", + zipCode: "60601", + organization: "Brown & Associates", + status: "Active", + totalOrders: 12, + totalSpent: 9450, + joinDate: "2023-05-10T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1003", + date: "2024-11-05T09:00:00Z", + amount: 3240, + status: "Pending", + }, + { + orderId: "ORD-1013", + date: "2024-11-22T16:00:00Z", + amount: 972, + status: "Paid", + }, + ], + }, + { + id: "CUS-1004", + name: "Sarah Johnson", + email: "sarah.j@email.com", + avatar: avatars[3], + phone: "+1 (555) 456-7890", + address: "321 Elm St", + city: "Houston", + state: "TX", + country: "United States", + zipCode: "77001", + organization: "Johnson Media", + status: "VIP", + totalOrders: 38, + totalSpent: 35200, + joinDate: "2023-02-08T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1004", + date: "2024-11-07T11:00:00Z", + amount: 2160, + status: "Paid", + }, + { + orderId: "ORD-1011", + date: "2024-11-19T14:00:00Z", + amount: 6480, + status: "Paid", + }, + { + orderId: "ORD-1018", + date: "2024-12-01T10:00:00Z", + amount: 4320, + status: "Paid", + }, + ], + }, + { + id: "CUS-1005", + name: "David Wilson", + email: "d.wilson@email.com", + avatar: avatars[4], + phone: "+1 (555) 567-8901", + address: "654 Maple Dr", + city: "Phoenix", + state: "AZ", + country: "United States", + zipCode: "85001", + organization: "Wilson Design", + status: "Inactive", + totalOrders: 3, + totalSpent: 1250, + joinDate: "2024-01-20T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1005", + date: "2024-11-08T16:00:00Z", + amount: 540, + status: "Failed", + }, + ], + }, + { + id: "CUS-1006", + name: "Olivia Martinez", + email: "olivia.m@email.com", + avatar: avatars[1], + phone: "+1 (555) 678-9012", + address: "987 Cedar Ln", + city: "Philadelphia", + state: "PA", + country: "United States", + zipCode: "19101", + organization: "Martinez Solutions", + status: "Active", + totalOrders: 19, + totalSpent: 15700, + joinDate: "2023-06-15T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1006", + date: "2024-11-10T13:00:00Z", + amount: 1944, + status: "Paid", + }, + { + orderId: "ORD-1014", + date: "2024-11-24T10:00:00Z", + amount: 756, + status: "Paid", + }, + ], + }, + { + id: "CUS-1007", + name: "James Anderson", + email: "james.a@email.com", + avatar: avatars[0], + phone: "+1 (555) 789-0123", + address: "147 Birch St", + city: "San Antonio", + state: "TX", + country: "United States", + zipCode: "78201", + organization: "Anderson Tech", + status: "Active", + totalOrders: 8, + totalSpent: 6300, + joinDate: "2023-09-01T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1007", + date: "2024-11-12T10:00:00Z", + amount: 1620, + status: "Refunded", + }, + ], + }, + { + id: "CUS-1008", + name: "Sophia Taylor", + email: "sophia.t@email.com", + avatar: avatars[3], + phone: "+1 (555) 890-1234", + address: "258 Walnut Ave", + city: "San Diego", + state: "CA", + country: "United States", + zipCode: "92101", + organization: "Taylor & Co", + status: "VIP", + totalOrders: 41, + totalSpent: 38900, + joinDate: "2023-01-28T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1008", + date: "2024-11-14T15:00:00Z", + amount: 1188, + status: "Paid", + }, + { + orderId: "ORD-1015", + date: "2024-11-25T13:00:00Z", + amount: 1944, + status: "Refunded", + }, + { + orderId: "ORD-1019", + date: "2024-12-03T12:00:00Z", + amount: 864, + status: "Failed", + }, + ], + }, + { + id: "CUS-1009", + name: "Daniel Thomas", + email: "daniel.t@email.com", + avatar: avatars[2], + phone: "+1 (555) 901-2345", + address: "369 Spruce Ct", + city: "Dallas", + state: "TX", + country: "United States", + zipCode: "75201", + organization: "Thomas Group", + status: "Active", + totalOrders: 15, + totalSpent: 12800, + joinDate: "2023-07-12T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1009", + date: "2024-11-16T12:00:00Z", + amount: 4860, + status: "Paid", + }, + ], + }, + { + id: "CUS-1010", + name: "Isabella Garcia", + email: "isabella.g@email.com", + avatar: avatars[4], + phone: "+1 (555) 012-3456", + address: "480 Ash Blvd", + city: "San Jose", + state: "CA", + country: "United States", + zipCode: "95101", + organization: "Garcia Ventures", + status: "Active", + totalOrders: 7, + totalSpent: 4200, + joinDate: "2024-02-14T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1010", + date: "2024-11-18T09:00:00Z", + amount: 378, + status: "Pending", + }, + ], + }, + { + id: "CUS-1011", + name: "William Lee", + email: "w.lee@email.com", + avatar: avatars[0], + phone: "+1 (555) 111-2222", + address: "591 Willow Way", + city: "Austin", + state: "TX", + country: "United States", + zipCode: "73301", + organization: "Lee Industries", + status: "Active", + totalOrders: 22, + totalSpent: 19600, + joinDate: "2023-04-18T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1011", + date: "2024-11-19T14:00:00Z", + amount: 6480, + status: "Paid", + }, + ], + }, + { + id: "CUS-1012", + name: "Mia Harris", + email: "mia.h@email.com", + avatar: avatars[1], + phone: "+1 (555) 222-3333", + address: "702 Poplar Dr", + city: "Jacksonville", + state: "FL", + country: "United States", + zipCode: "32099", + organization: "Harris Consulting", + status: "Inactive", + totalOrders: 2, + totalSpent: 890, + joinDate: "2024-04-05T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1012", + date: "2024-11-20T11:00:00Z", + amount: 2700, + status: "Failed", + }, + ], + }, + { + id: "CUS-1013", + name: "Ethan Clark", + email: "ethan.c@email.com", + avatar: avatars[2], + phone: "+1 (555) 333-4444", + address: "813 Aspen Rd", + city: "Columbus", + state: "OH", + country: "United States", + zipCode: "43004", + organization: "Clark Engineering", + status: "Active", + totalOrders: 11, + totalSpent: 8750, + joinDate: "2023-08-22T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1013", + date: "2024-11-22T16:00:00Z", + amount: 972, + status: "Paid", + }, + ], + }, + { + id: "CUS-1014", + name: "Charlotte Lewis", + email: "charlotte.l@email.com", + avatar: avatars[3], + phone: "+1 (555) 444-5555", + address: "924 Chestnut Pl", + city: "Fort Worth", + state: "TX", + country: "United States", + zipCode: "76101", + organization: "Lewis Creative", + status: "VIP", + totalOrders: 35, + totalSpent: 29800, + joinDate: "2023-03-01T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1014", + date: "2024-11-24T10:00:00Z", + amount: 756, + status: "Paid", + }, + { + orderId: "ORD-1017", + date: "2024-11-29T15:00:00Z", + amount: 540, + status: "Pending", + }, + ], + }, + { + id: "CUS-1015", + name: "Alexander Walker", + email: "alex.w@email.com", + avatar: avatars[4], + phone: "+1 (555) 555-6666", + address: "135 Magnolia Ln", + city: "Charlotte", + state: "NC", + country: "United States", + zipCode: "28201", + organization: "Walker Digital", + status: "Active", + totalOrders: 9, + totalSpent: 7100, + joinDate: "2023-11-10T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1015", + date: "2024-11-25T13:00:00Z", + amount: 1944, + status: "Refunded", + }, + ], + }, + { + id: "CUS-1016", + name: "Amelia Young", + email: "amelia.y@email.com", + avatar: avatars[1], + phone: "+1 (555) 666-7777", + address: "246 Dogwood St", + city: "Indianapolis", + state: "IN", + country: "United States", + zipCode: "46201", + organization: "Young Studios", + status: "Active", + totalOrders: 16, + totalSpent: 13400, + joinDate: "2023-06-28T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1016", + date: "2024-11-27T09:00:00Z", + amount: 2862, + status: "Paid", + }, + ], + }, + { + id: "CUS-1017", + name: "Benjamin King", + email: "ben.k@email.com", + avatar: avatars[0], + phone: "+1 (555) 777-8888", + address: "357 Juniper Ave", + city: "San Francisco", + state: "CA", + country: "United States", + zipCode: "94101", + organization: "King Software", + status: "VIP", + totalOrders: 44, + totalSpent: 47200, + joinDate: "2023-01-05T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1017", + date: "2024-11-29T15:00:00Z", + amount: 540, + status: "Pending", + }, + ], + }, + { + id: "CUS-1018", + name: "Harper Wright", + email: "harper.w@email.com", + avatar: avatars[3], + phone: "+1 (555) 888-9999", + address: "468 Cypress Rd", + city: "Seattle", + state: "WA", + country: "United States", + zipCode: "98101", + organization: "Wright Photography", + status: "Active", + totalOrders: 14, + totalSpent: 11200, + joinDate: "2023-10-15T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1018", + date: "2024-12-01T10:00:00Z", + amount: 4320, + status: "Paid", + }, + ], + }, + { + id: "CUS-1019", + name: "Lucas Scott", + email: "lucas.s@email.com", + avatar: avatars[2], + phone: "+1 (555) 999-0000", + address: "579 Redwood Blvd", + city: "Denver", + state: "CO", + country: "United States", + zipCode: "80201", + organization: "Scott Labs", + status: "Inactive", + totalOrders: 1, + totalSpent: 350, + joinDate: "2024-06-01T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1019", + date: "2024-12-03T12:00:00Z", + amount: 864, + status: "Failed", + }, + ], + }, + { + id: "CUS-1020", + name: "Ella Adams", + email: "ella.a@email.com", + avatar: avatars[4], + phone: "+1 (555) 000-1111", + address: "690 Sycamore Dr", + city: "Nashville", + state: "TN", + country: "United States", + zipCode: "37201", + organization: "Adams Marketing", + status: "Active", + totalOrders: 6, + totalSpent: 3800, + joinDate: "2024-03-12T00:00:00Z", + recentOrders: [ + { + orderId: "ORD-1020", + date: "2024-12-05T14:00:00Z", + amount: 486, + status: "Pending", + }, + ], + }, +] diff --git a/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/page.tsx b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/page.tsx new file mode 100644 index 00000000..ad1e88b4 --- /dev/null +++ b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/list/page.tsx @@ -0,0 +1,17 @@ +import type { Metadata } from "next" + +import { customersData } from "./_data/customers" + +import { CustomersTable } from "./_components/customers-table" + +export const metadata: Metadata = { + title: "Customers List", +} + +export default function CustomersListPage() { + return ( +
+ +
+ ) +} diff --git a/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/types.ts b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/types.ts new file mode 100644 index 00000000..da92d154 --- /dev/null +++ b/full-kit/src/app/[lang]/(dashboard-layout)/pages/customers/types.ts @@ -0,0 +1,27 @@ +export type CustomerStatusType = "Active" | "Inactive" | "VIP" + +export interface CustomerOrderType { + orderId: string + date: string + amount: number + status: "Paid" | "Pending" | "Failed" | "Refunded" +} + +export interface CustomerType { + id: string + name: string + email: string + avatar: string + phone: string + address: string + city: string + state: string + country: string + zipCode: string + organization: string + status: CustomerStatusType + totalOrders: number + totalSpent: number + joinDate: string + recentOrders: CustomerOrderType[] +} diff --git a/full-kit/src/data/navigations.ts b/full-kit/src/data/navigations.ts index b851209c..3c77511e 100644 --- a/full-kit/src/data/navigations.ts +++ b/full-kit/src/data/navigations.ts @@ -147,13 +147,11 @@ export const navigationsData: NavigationType[] = [ items: [ { title: "List", - href: "/", - label: "Soon", + href: "/pages/customers/list", }, { title: "Details", - href: "/", - label: "Soon", + href: "/pages/customers/CUS-1001", }, ], },