detail customer

This commit is contained in:
hamid zarghami
2025-11-05 14:05:24 +03:30
parent 7f96669bc7
commit 2b1b2daacf
9 changed files with 576 additions and 2 deletions
+41
View File
@@ -0,0 +1,41 @@
import { EmptyWallet, Star1 } from 'iconsax-react'
import { type FC } from 'react'
interface CustomerStatsProps {
points?: number | string
walletBalance?: string
}
const CustomerStats: FC<CustomerStatsProps> = ({
points = '124',
walletBalance = '۲۴۰.۰۰۰ تومان'
}) => {
return (
<div className='bg-white rounded-4xl p-8'>
<div className='flex gap-4 items-center'>
<div className='flex gap-1.5'>
<Star1 size={16} color='black' />
<div className='text-xs'>امتیاز</div>
</div>
<div className='flex-1 border-b border-dashed border-border'></div>
<div className='text-xs'>{points} امتیاز</div>
</div>
<div className='flex gap-4 mt-5 items-center'>
<div className='flex gap-1.5'>
<EmptyWallet size={16} color='black' />
<div className='text-xs'>موجودی کیف پول</div>
</div>
<div className='flex-1 border-b border-dashed border-border'></div>
<div className='text-xs'>{walletBalance}</div>
</div>
</div>
)
}
export default CustomerStats
+4
View File
@@ -43,3 +43,7 @@ textarea::placeholder {
.dltr {
direction: ltr;
}
tbody tr:nth-child(odd) {
background: rgba(233, 235, 244, 0.2) !important;
}
+94
View File
@@ -0,0 +1,94 @@
import Table from '@/components/Table'
import { type FC } from 'react'
import type { RowDataType, ActionType } from '@/components/types/TableTypes'
interface AddressData extends RowDataType {
id: number
number: number
title: string
province: string
city: string
address: string
}
const AddressesTable: FC = () => {
const handleRowActions = (item: AddressData): ActionType[] => {
return [
{
label: 'ویرایش',
onClick: () => {
console.log('ویرایش آدرس:', item.id)
},
},
{
label: 'حذف',
onClick: () => {
console.log('حذف آدرس:', item.id)
},
},
]
}
const columns = [
{
key: 'number',
title: 'شماره',
},
{
key: 'title',
title: 'عنوان',
},
{
key: 'province',
title: 'استان',
},
{
key: 'city',
title: 'شهر',
},
{
key: 'address',
title: 'آدرس',
},
]
const data: AddressData[] = [
{
id: 1,
number: 1,
title: 'خانه',
province: 'مرکزی',
city: 'اراک',
address: 'خیابان شریعتی - خیابان جنت',
},
{
id: 2,
number: 2,
title: 'خانه',
province: 'مرکزی',
city: 'اراک',
address: 'خیابان شریعتی - خیابان جنت',
},
{
id: 3,
number: 3,
title: 'خانه',
province: 'مرکزی',
city: 'اراک',
address: 'خیابان شریعتی - خیابان جنت',
},
]
return (
<Table
columns={columns}
data={data}
selectable={true}
rowActions={handleRowActions}
className="mt-0"
/>
)
}
export default AddressesTable
+113
View File
@@ -0,0 +1,113 @@
import Button from '@/components/Button'
import CustomerStats from '@/components/CustomerStats'
import AddressesTable from './AddressesTable'
import TransactionsTable from './TransactionsTable'
import PointsLogTable from './PointsLogTable'
import DiscountCodesTable from './DiscountCodesTable'
import { Edit, TaskSquare } from 'iconsax-react'
import { type FC } from 'react'
const CustomerDetails: FC = () => {
return (
<div className='mt-5'>
<div className='flex justify-between items-center'>
<h1 className='text-lg font-light'>مشتری: مهرداد مظفری</h1>
<Button className='w-fit px-6 bg-transparent text-primary border-primary border'>
<div className='flex gap-2 items-center'>
<TaskSquare color='#000' size={20} />
<span>سفارشات</span>
</div>
</Button>
</div>
<div className='flex gap-7 mt-9'>
<div className='flex-1'>
<div className='w-full bg-white rounded-4xl p-8'>
<div className='flex justify-between items-center'>
<div className='text-lg font-light'>
اطلاعات مشتری
</div>
<div className='flex gap-1 text-[#0047FF]'>
<Edit size={18} color='#0047FF' />
<div className='text-xs'>ویرایش</div>
</div>
</div>
<div className='mt-8 flex flex-wrap gap-y-7 gap-20 text-[13px] font-light border-b border-dashed border-border pb-8'>
<div className='flex gap-2'>
<div className='text-description'>
نام و نام خانوادگی :
</div>
<div>مهرداد مظفری</div>
</div>
<div className='flex gap-2'>
<div className='text-description'>
کدملی :
</div>
<div>۰۵۲۱۲۳۴۵۶۷</div>
</div>
<div className='flex gap-2'>
<div className='text-description'>شغل:</div>
<div>برنامه نویس</div>
</div>
<div className='flex gap-2'>
<div className='text-description'>تاریخ تولد :</div>
<div>۱۳۶۹/۰۵/۱۱</div>
</div>
</div>
<div className='mt-8 flex gap-20 text-[13px] font-light'>
<div className='flex gap-2'>
<div className='text-description'>شماره تماس:</div>
<div>۰۸۶۹۱۰۰۹۱۰۰۱</div>
</div>
<div className='flex gap-2'>
<div className='text-description'>ایمیل:</div>
<div>info@example.com</div>
</div>
</div>
</div>
<div className='w-full bg-white rounded-4xl p-8 mt-8'>
<div className='text-lg font-light'>
آدرس ها
</div>
<AddressesTable />
</div>
<div className='w-full bg-white rounded-4xl p-8 mt-8'>
<div className='text-lg font-light'>
تراکنش ها
</div>
<TransactionsTable />
</div>
<div className='w-full bg-white rounded-4xl p-8 mt-8'>
<div className='text-lg font-light'>
لاگ امتیازها
</div>
<PointsLogTable />
</div>
</div>
<div className='w-[330px]'>
<CustomerStats />
<div className='mt-6 bg-white rounded-4xl p-8'>
<div className='font-light'>
کد تخفیف
</div>
<DiscountCodesTable />
</div>
</div>
</div>
</div>
)
}
export default CustomerDetails
@@ -0,0 +1,93 @@
import { type FC } from 'react'
import { TicketDiscount } from 'iconsax-react'
interface DiscountCode {
id: string
code: string
expiryDate: string
status: 'used' | 'unused'
}
const DiscountCodesTable: FC = () => {
const discountCodes: DiscountCode[] = [
{
id: '1',
code: 'A12345',
expiryDate: '1403/12/01',
status: 'unused'
},
{
id: '2',
code: 'A12345',
expiryDate: '1403/12/01',
status: 'used'
},
{
id: '3',
code: 'A12345',
expiryDate: '1403/12/01',
status: 'used'
}
]
const getStatusStyles = (status: 'used' | 'unused') => {
if (status === 'unused') {
return 'text-[#0047FF]'
}
return 'text-[#FF0000]'
}
const getStatusText = (status: 'used' | 'unused') => {
return status === 'unused' ? 'استفاده نشده' : 'استفاده شده'
}
return (
<div className='mt-4'>
<table className='w-full'>
<thead>
<tr className='border-b border-border'>
<th className='text-right pb-2 font-light text-xs text-description'>
کد
</th>
<th className='text-center pb-2 font-light text-xs text-description'>
انقضا
</th>
<th className='text-center pb-2 font-light text-xs text-description'>
وضعیت
</th>
</tr>
</thead>
<tbody>
{discountCodes.map((item) => (
<tr
key={item.id}
className='border-b border-border last:border-0'
>
<td className='py-2.5 text-xs font-light'>
{item.code}
</td>
<td className='py-2.5 text-xs font-light text-description text-center'>
{item.expiryDate}
</td>
<td className='py-2.5 text-center'>
<span
className={`inline-block py-0.5 rounded-md text-xs font-light ${getStatusStyles(item.status)}`}
>
{getStatusText(item.status)}
</span>
</td>
</tr>
))}
</tbody>
</table>
<button className='w-full mt-4 bg-black text-white rounded-xl py-3 flex items-center justify-center gap-2 text-xs font-light hover:bg-gray-800 transition-colors'>
<TicketDiscount size={16} />
<span>اضافه کردن کد تخفیف</span>
</button>
</div>
)
}
export default DiscountCodesTable
+8 -2
View File
@@ -5,6 +5,8 @@ import { Add, Eye } from 'iconsax-react'
import { type FC, useState } from 'react'
import type { RowDataType, ActionType } from '@/components/types/TableTypes'
import type { FilterValues } from '@/components/Filters'
import { Pages } from '@/config/Pages'
import { Link } from 'react-router-dom'
interface CustomerData extends RowDataType {
id: number
@@ -100,8 +102,12 @@ const CustomersList: FC = () => {
{
key: 'details',
title: 'جزییات',
render: () => {
return <Eye size={20} color="#8C90A3" />
render: (item: CustomerData) => {
return (
<Link to={Pages.customers.detail + item.id}>
<Eye size={20} color="#8C90A3" />
</Link>
)
},
},
]
+94
View File
@@ -0,0 +1,94 @@
import Table from '@/components/Table'
import { type FC } from 'react'
import type { RowDataType, ActionType } from '@/components/types/TableTypes'
interface PointsLogData extends RowDataType {
id: number
number: number
title: string
points: number
date: string
description: string
}
const PointsLogTable: FC = () => {
const handleRowActions = (item: PointsLogData): ActionType[] => {
return [
{
label: 'ویرایش',
onClick: () => {
console.log('ویرایش لاگ امتیاز:', item.id)
},
},
{
label: 'حذف',
onClick: () => {
console.log('حذف لاگ امتیاز:', item.id)
},
},
]
}
const columns = [
{
key: 'number',
title: 'شماره',
},
{
key: 'title',
title: 'عنوان',
},
{
key: 'points',
title: 'امتیاز',
},
{
key: 'date',
title: 'تاریخ',
},
{
key: 'description',
title: 'توضیحات',
},
]
const data: PointsLogData[] = [
{
id: 1,
number: 1,
title: 'خرید با امتیاز',
points: 200,
date: '۱۳۶۹/۰۵/۱۱',
description: 'معادل ۲۰۰,۰۰۰ تومان',
},
{
id: 2,
number: 1,
title: 'افزایش امتیاز',
points: 200,
date: '۱۳۶۹/۰۵/۱۱',
description: 'دعوت دوستان',
},
{
id: 3,
number: 1,
title: 'افزایش امتیاز',
points: 200,
date: '۱۳۶۹/۰۵/۱۱',
description: 'خرید اول',
},
]
return (
<Table
columns={columns}
data={data}
selectable={true}
rowActions={handleRowActions}
className="mt-0"
/>
)
}
export default PointsLogTable
+127
View File
@@ -0,0 +1,127 @@
import Table from '@/components/Table'
import { type FC } from 'react'
import type { RowDataType, ActionType } from '@/components/types/TableTypes'
interface TransactionData extends RowDataType {
id: number
number: number
transactionType: string
amount: string
paymentDate: string
status: 'successful' | 'unsuccessful' | 'unknown'
}
const TransactionsTable: FC = () => {
const handleRowActions = (item: TransactionData): ActionType[] => {
return [
{
label: 'ویرایش',
onClick: () => {
console.log('ویرایش تراکنش:', item.id)
},
},
{
label: 'حذف',
onClick: () => {
console.log('حذف تراکنش:', item.id)
},
},
]
}
const getStatusColor = (status: string) => {
switch (status) {
case 'successful':
return 'text-green-600'
case 'unsuccessful':
return 'text-red-600'
case 'unknown':
return 'text-orange-600'
default:
return 'text-gray-600'
}
}
const getStatusText = (status: string) => {
switch (status) {
case 'successful':
return 'موفق'
case 'unsuccessful':
return 'ناموفق'
case 'unknown':
return 'نا مشخص'
default:
return status
}
}
const columns = [
{
key: 'number',
title: 'شماره',
},
{
key: 'transactionType',
title: 'نوع تراکنش',
},
{
key: 'amount',
title: 'مبلغ',
},
{
key: 'paymentDate',
title: 'تاریخ پرداخت',
},
{
key: 'status',
title: 'وضعیت',
render: (item: TransactionData) => {
return (
<span className={getStatusColor(item.status)}>
{getStatusText(item.status)}
</span>
)
},
},
]
const data: TransactionData[] = [
{
id: 1,
number: 1,
transactionType: 'پرداخت اینترنتی',
amount: '۴,۰۰۰,۰۰۰ ریال',
paymentDate: '۱۳۶۹/۰۵/۱۱',
status: 'successful',
},
{
id: 2,
number: 1,
transactionType: 'پرداخت اینترنتی',
amount: '۴,۰۰۰,۰۰۰ ریال',
paymentDate: '۱۳۶۹/۰۵/۱۱',
status: 'unsuccessful',
},
{
id: 3,
number: 1,
transactionType: 'پرداخت اینترنتی',
amount: '۴,۰۰۰,۰۰۰ ریال',
paymentDate: '۱۳۶۹/۰۵/۱۱',
status: 'unknown',
},
]
return (
<Table
columns={columns}
data={data}
selectable={true}
rowActions={handleRowActions}
className="mt-0"
/>
)
}
export default TransactionsTable
+2
View File
@@ -10,6 +10,7 @@ import { Pages } from '@/config/Pages'
import CreateFood from '@/pages/food/Create'
import CategoryFood from '@/pages/food/Category'
import CustomersList from '@/pages/customers/List'
import CustomerDetails from '@/pages/customers/Details'
const MainRouter: FC = () => {
@@ -32,6 +33,7 @@ const MainRouter: FC = () => {
<Route path={Pages.foods.add} element={<CreateFood />} />
<Route path={Pages.foods.category} element={<CategoryFood />} />
<Route path={Pages.customers.list} element={<CustomersList />} />
<Route path={Pages.customers.detail + ':id'} element={<CustomerDetails />} />
</Routes>
</div>
</div>